Deleted Added
full compact
vfs_acl.c (191266) vfs_acl.c (192586)
1/*-
2 * Copyright (c) 1999-2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by Robert Watson for the TrustedBSD Project.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 19 unchanged lines hidden (view full) ---

28/*
29 * Developed by the TrustedBSD Project.
30 *
31 * ACL system calls and other functions common across different ACL types.
32 * Type-specific routines go into subr_acl_<type>.c.
33 */
34
35#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1999-2006 Robert N. M. Watson
3 * All rights reserved.
4 *
5 * This software was developed by Robert Watson for the TrustedBSD Project.
6 *
7 * Redistribution and use in source and binary forms, with or without
8 * modification, are permitted provided that the following conditions

--- 19 unchanged lines hidden (view full) ---

28/*
29 * Developed by the TrustedBSD Project.
30 *
31 * ACL system calls and other functions common across different ACL types.
32 * Type-specific routines go into subr_acl_<type>.c.
33 */
34
35#include <sys/cdefs.h>
36__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 191266 2009-04-19 09:56:30Z trasz $");
36__FBSDID("$FreeBSD: head/sys/kern/vfs_acl.c 192586 2009-05-22 15:56:43Z trasz $");
37
38#include "opt_mac.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/sysproto.h>
43#include <sys/fcntl.h>
44#include <sys/kernel.h>

--- 6 unchanged lines hidden (view full) ---

51#include <sys/file.h>
52#include <sys/filedesc.h>
53#include <sys/proc.h>
54#include <sys/sysent.h>
55#include <sys/acl.h>
56
57#include <security/mac/mac_framework.h>
58
37
38#include "opt_mac.h"
39
40#include <sys/param.h>
41#include <sys/systm.h>
42#include <sys/sysproto.h>
43#include <sys/fcntl.h>
44#include <sys/kernel.h>

--- 6 unchanged lines hidden (view full) ---

51#include <sys/file.h>
52#include <sys/filedesc.h>
53#include <sys/proc.h>
54#include <sys/sysent.h>
55#include <sys/acl.h>
56
57#include <security/mac/mac_framework.h>
58
59static MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists");
59CTASSERT(ACL_MAX_ENTRIES >= OLDACL_MAX_ENTRIES);
60
60
61MALLOC_DEFINE(M_ACL, "acl", "Access Control Lists");
62
61static int vacl_set_acl(struct thread *td, struct vnode *vp,
62 acl_type_t type, struct acl *aclp);
63static int vacl_get_acl(struct thread *td, struct vnode *vp,
64 acl_type_t type, struct acl *aclp);
65static int vacl_aclcheck(struct thread *td, struct vnode *vp,
66 acl_type_t type, struct acl *aclp);
67
63static int vacl_set_acl(struct thread *td, struct vnode *vp,
64 acl_type_t type, struct acl *aclp);
65static int vacl_get_acl(struct thread *td, struct vnode *vp,
66 acl_type_t type, struct acl *aclp);
67static int vacl_aclcheck(struct thread *td, struct vnode *vp,
68 acl_type_t type, struct acl *aclp);
69
70int
71acl_copy_oldacl_into_acl(const struct oldacl *source, struct acl *dest)
72{
73 int i;
74
75 if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
76 return (EINVAL);
77
78 bzero(dest, sizeof(*dest));
79
80 dest->acl_cnt = source->acl_cnt;
81 dest->acl_maxcnt = ACL_MAX_ENTRIES;
82
83 for (i = 0; i < dest->acl_cnt; i++) {
84 dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
85 dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
86 dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
87 }
88
89 return (0);
90}
91
92int
93acl_copy_acl_into_oldacl(const struct acl *source, struct oldacl *dest)
94{
95 int i;
96
97 if (source->acl_cnt < 0 || source->acl_cnt > OLDACL_MAX_ENTRIES)
98 return (EINVAL);
99
100 bzero(dest, sizeof(*dest));
101
102 dest->acl_cnt = source->acl_cnt;
103
104 for (i = 0; i < dest->acl_cnt; i++) {
105 dest->acl_entry[i].ae_tag = source->acl_entry[i].ae_tag;
106 dest->acl_entry[i].ae_id = source->acl_entry[i].ae_id;
107 dest->acl_entry[i].ae_perm = source->acl_entry[i].ae_perm;
108 }
109
110 return (0);
111}
112
68/*
113/*
114 * At one time, "struct ACL" was extended in order to add support for NFSv4
115 * ACLs. Instead of creating compatibility versions of all the ACL-related
116 * syscalls, they were left intact. It's possible to find out what the code
117 * calling these syscalls (libc) expects basing on "type" argument - if it's
118 * either ACL_TYPE_ACCESS_OLD or ACL_TYPE_DEFAULT_OLD (which previously were
119 * known as ACL_TYPE_ACCESS and ACL_TYPE_DEFAULT), then it's the "struct
120 * oldacl". If it's something else, then it's the new "struct acl". In the
121 * latter case, the routines below just copyin/copyout the contents. In the
122 * former case, they copyin the "struct oldacl" and convert it to the new
123 * format.
124 */
125static int
126acl_copyin(void *user_acl, struct acl *kernel_acl, acl_type_t type)
127{
128 int error;
129 struct oldacl old;
130
131 switch (type) {
132 case ACL_TYPE_ACCESS_OLD:
133 case ACL_TYPE_DEFAULT_OLD:
134 error = copyin(user_acl, &old, sizeof(old));
135 if (error != 0)
136 break;
137 acl_copy_oldacl_into_acl(&old, kernel_acl);
138 break;
139
140 default:
141 error = copyin(user_acl, kernel_acl, sizeof(*kernel_acl));
142 if (kernel_acl->acl_maxcnt != ACL_MAX_ENTRIES)
143 return (EINVAL);
144 }
145
146 return (error);
147}
148
149static int
150acl_copyout(struct acl *kernel_acl, void *user_acl, acl_type_t type)
151{
152 int error;
153 struct oldacl old;
154
155 switch (type) {
156 case ACL_TYPE_ACCESS_OLD:
157 case ACL_TYPE_DEFAULT_OLD:
158 error = acl_copy_acl_into_oldacl(kernel_acl, &old);
159 if (error != 0)
160 break;
161
162 error = copyout(&old, user_acl, sizeof(old));
163 break;
164
165 default:
166 if (fuword((char *)user_acl +
167 offsetof(struct acl, acl_maxcnt)) != ACL_MAX_ENTRIES)
168 return (EINVAL);
169
170 error = copyout(kernel_acl, user_acl, sizeof(*kernel_acl));
171 }
172
173 return (error);
174}
175
176/*
177 * Convert "old" type - ACL_TYPE_{ACCESS,DEFAULT}_OLD - into its "new"
178 * counterpart. It's required for old (pre-NFS4 ACLs) libc to work
179 * with new kernel. Fixing 'type' for old binaries with new libc
180 * is being done in lib/libc/posix1e/acl_support.c:_acl_type_unold().
181 */
182static int
183acl_type_unold(int type)
184{
185 switch (type) {
186 case ACL_TYPE_ACCESS_OLD:
187 return (ACL_TYPE_ACCESS);
188
189 case ACL_TYPE_DEFAULT_OLD:
190 return (ACL_TYPE_DEFAULT);
191
192 default:
193 return (type);
194 }
195}
196
197/*
69 * These calls wrap the real vnode operations, and are called by the syscall
70 * code once the syscall has converted the path or file descriptor to a vnode
71 * (unlocked). The aclp pointer is assumed still to point to userland, so
72 * this should not be consumed within the kernel except by syscall code.
73 * Other code should directly invoke VOP_{SET,GET}ACL.
74 */
75
76/*
77 * Given a vnode, set its ACL.
78 */
79static int
80vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
81 struct acl *aclp)
82{
83 struct acl *inkernelacl;
84 struct mount *mp;
85 int error;
86
87 inkernelacl = acl_alloc(M_WAITOK);
198 * These calls wrap the real vnode operations, and are called by the syscall
199 * code once the syscall has converted the path or file descriptor to a vnode
200 * (unlocked). The aclp pointer is assumed still to point to userland, so
201 * this should not be consumed within the kernel except by syscall code.
202 * Other code should directly invoke VOP_{SET,GET}ACL.
203 */
204
205/*
206 * Given a vnode, set its ACL.
207 */
208static int
209vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
210 struct acl *aclp)
211{
212 struct acl *inkernelacl;
213 struct mount *mp;
214 int error;
215
216 inkernelacl = acl_alloc(M_WAITOK);
88 error = copyin(aclp, inkernelacl, sizeof(struct acl));
217 error = acl_copyin(aclp, inkernelacl, type);
89 if (error)
90 goto out;
91 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
92 if (error != 0)
93 goto out;
94 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
95#ifdef MAC
96 error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl);
97 if (error != 0)
98 goto out_unlock;
99#endif
218 if (error)
219 goto out;
220 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
221 if (error != 0)
222 goto out;
223 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
224#ifdef MAC
225 error = mac_vnode_check_setacl(td->td_ucred, vp, type, inkernelacl);
226 if (error != 0)
227 goto out_unlock;
228#endif
100 error = VOP_SETACL(vp, type, inkernelacl, td->td_ucred, td);
229 error = VOP_SETACL(vp, acl_type_unold(type), inkernelacl,
230 td->td_ucred, td);
101#ifdef MAC
102out_unlock:
103#endif
104 VOP_UNLOCK(vp, 0);
105 vn_finished_write(mp);
106out:
107 acl_free(inkernelacl);
108 return(error);

--- 11 unchanged lines hidden (view full) ---

120
121 inkernelacl = acl_alloc(M_WAITOK);
122 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
123#ifdef MAC
124 error = mac_vnode_check_getacl(td->td_ucred, vp, type);
125 if (error != 0)
126 goto out;
127#endif
231#ifdef MAC
232out_unlock:
233#endif
234 VOP_UNLOCK(vp, 0);
235 vn_finished_write(mp);
236out:
237 acl_free(inkernelacl);
238 return(error);

--- 11 unchanged lines hidden (view full) ---

250
251 inkernelacl = acl_alloc(M_WAITOK);
252 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
253#ifdef MAC
254 error = mac_vnode_check_getacl(td->td_ucred, vp, type);
255 if (error != 0)
256 goto out;
257#endif
128 error = VOP_GETACL(vp, type, inkernelacl, td->td_ucred, td);
258 error = VOP_GETACL(vp, acl_type_unold(type), inkernelacl,
259 td->td_ucred, td);
260
129#ifdef MAC
130out:
131#endif
132 VOP_UNLOCK(vp, 0);
133 if (error == 0)
261#ifdef MAC
262out:
263#endif
264 VOP_UNLOCK(vp, 0);
265 if (error == 0)
134 error = copyout(inkernelacl, aclp, sizeof(struct acl));
266 error = acl_copyout(inkernelacl, aclp, type);
135 acl_free(inkernelacl);
136 return (error);
137}
138
139/*
140 * Given a vnode, delete its ACL.
141 */
142static int

--- 6 unchanged lines hidden (view full) ---

149 if (error)
150 return (error);
151 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
152#ifdef MAC
153 error = mac_vnode_check_deleteacl(td->td_ucred, vp, type);
154 if (error)
155 goto out;
156#endif
267 acl_free(inkernelacl);
268 return (error);
269}
270
271/*
272 * Given a vnode, delete its ACL.
273 */
274static int

--- 6 unchanged lines hidden (view full) ---

281 if (error)
282 return (error);
283 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
284#ifdef MAC
285 error = mac_vnode_check_deleteacl(td->td_ucred, vp, type);
286 if (error)
287 goto out;
288#endif
157 error = VOP_SETACL(vp, type, 0, td->td_ucred, td);
289 error = VOP_SETACL(vp, acl_type_unold(type), 0, td->td_ucred, td);
158#ifdef MAC
159out:
160#endif
161 VOP_UNLOCK(vp, 0);
162 vn_finished_write(mp);
163 return (error);
164}
165
166/*
167 * Given a vnode, check whether an ACL is appropriate for it
168 */
169static int
170vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
171 struct acl *aclp)
172{
173 struct acl *inkernelacl;
174 int error;
175
176 inkernelacl = acl_alloc(M_WAITOK);
290#ifdef MAC
291out:
292#endif
293 VOP_UNLOCK(vp, 0);
294 vn_finished_write(mp);
295 return (error);
296}
297
298/*
299 * Given a vnode, check whether an ACL is appropriate for it
300 */
301static int
302vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
303 struct acl *aclp)
304{
305 struct acl *inkernelacl;
306 int error;
307
308 inkernelacl = acl_alloc(M_WAITOK);
177 error = copyin(aclp, inkernelacl, sizeof(struct acl));
309 error = acl_copyin(aclp, inkernelacl, type);
178 if (error)
179 goto out;
180 error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td);
181out:
182 acl_free(inkernelacl);
183 return (error);
184}
185

--- 239 unchanged lines hidden (view full) ---

425}
426
427struct acl *
428acl_alloc(int flags)
429{
430 struct acl *aclp;
431
432 aclp = malloc(sizeof(*aclp), M_ACL, flags);
310 if (error)
311 goto out;
312 error = VOP_ACLCHECK(vp, type, inkernelacl, td->td_ucred, td);
313out:
314 acl_free(inkernelacl);
315 return (error);
316}
317

--- 239 unchanged lines hidden (view full) ---

557}
558
559struct acl *
560acl_alloc(int flags)
561{
562 struct acl *aclp;
563
564 aclp = malloc(sizeof(*aclp), M_ACL, flags);
565 aclp->acl_maxcnt = ACL_MAX_ENTRIES;
433
434 return (aclp);
435}
436
437void
438acl_free(struct acl *aclp)
439{
440
441 free(aclp, M_ACL);
442}
566
567 return (aclp);
568}
569
570void
571acl_free(struct acl *aclp)
572{
573
574 free(aclp, M_ACL);
575}