xref: /freebsd/sys/kern/vfs_acl.c (revision 63f9a4cb2684a303e3eb2ffed39c03a2e2b28ae0)
1 /*-
2  * Copyright (c) 1999-2003 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
9  * are met:
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  * 2. Redistributions in binary form must reproduce the above copyright
13  *    notice, this list of conditions and the following disclaimer in the
14  *    documentation and/or other materials provided with the distribution.
15  *
16  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26  * SUCH DAMAGE.
27  */
28 /*
29  * Developed by the TrustedBSD Project.
30  * Support for POSIX.1e access control lists.
31  */
32 
33 #include <sys/cdefs.h>
34 __FBSDID("$FreeBSD$");
35 
36 #include "opt_mac.h"
37 
38 #include <sys/param.h>
39 #include <sys/systm.h>
40 #include <sys/sysproto.h>
41 #include <sys/kernel.h>
42 #include <sys/mac.h>
43 #include <sys/malloc.h>
44 #include <sys/vnode.h>
45 #include <sys/lock.h>
46 #include <sys/mutex.h>
47 #include <sys/namei.h>
48 #include <sys/file.h>
49 #include <sys/filedesc.h>
50 #include <sys/proc.h>
51 #include <sys/sysent.h>
52 #include <sys/errno.h>
53 #include <sys/stat.h>
54 #include <sys/acl.h>
55 
56 MALLOC_DEFINE(M_ACL, "acl", "access control list");
57 
58 static int	vacl_set_acl(struct thread *td, struct vnode *vp,
59 		    acl_type_t type, struct acl *aclp);
60 static int	vacl_get_acl(struct thread *td, struct vnode *vp,
61 		    acl_type_t type, struct acl *aclp);
62 static int	vacl_aclcheck(struct thread *td, struct vnode *vp,
63 		    acl_type_t type, struct acl *aclp);
64 
65 /*
66  * Implement a version of vaccess() that understands POSIX.1e ACL semantics.
67  * Return 0 on success, else an errno value.  Should be merged into
68  * vaccess() eventually.
69  */
70 int
71 vaccess_acl_posix1e(enum vtype type, uid_t file_uid, gid_t file_gid,
72     struct acl *acl, mode_t acc_mode, struct ucred *cred, int *privused)
73 {
74 	struct acl_entry *acl_other, *acl_mask;
75 	mode_t dac_granted;
76 	mode_t cap_granted;
77 	mode_t acl_mask_granted;
78 	int group_matched, i;
79 
80 	/*
81 	 * Look for a normal, non-privileged way to access the file/directory
82 	 * as requested.  If it exists, go with that.  Otherwise, attempt
83 	 * to use privileges granted via cap_granted.  In some cases,
84 	 * which privileges to use may be ambiguous due to "best match",
85 	 * in which case fall back on first match for the time being.
86 	 */
87 	if (privused != NULL)
88 		*privused = 0;
89 
90 	/*
91 	 * Determine privileges now, but don't apply until we've found
92 	 * a DAC entry that matches but has failed to allow access.
93 	 */
94 #ifndef CAPABILITIES
95 	if (suser_cred(cred, SUSER_ALLOWJAIL) == 0)
96 		cap_granted = VALLPERM;
97 	else
98 		cap_granted = 0;
99 #else
100 	cap_granted = 0;
101 
102 	if (type == VDIR) {
103 		if ((acc_mode & VEXEC) && !cap_check(cred, NULL,
104 		     CAP_DAC_READ_SEARCH, SUSER_ALLOWJAIL))
105 			cap_granted |= VEXEC;
106 	} else {
107 		if ((acc_mode & VEXEC) && !cap_check(cred, NULL,
108 		    CAP_DAC_EXECUTE, SUSER_ALLOWJAIL))
109 			cap_granted |= VEXEC;
110 	}
111 
112 	if ((acc_mode & VREAD) && !cap_check(cred, NULL, CAP_DAC_READ_SEARCH,
113 	    SUSER_ALLOWJAIL))
114 		cap_granted |= VREAD;
115 
116 	if (((acc_mode & VWRITE) || (acc_mode & VAPPEND)) &&
117 	    !cap_check(cred, NULL, CAP_DAC_WRITE, SUSER_ALLOWJAIL))
118 		cap_granted |= (VWRITE | VAPPEND);
119 
120 	if ((acc_mode & VADMIN) && !cap_check(cred, NULL, CAP_FOWNER,
121 	    SUSER_ALLOWJAIL))
122 		cap_granted |= VADMIN;
123 #endif /* CAPABILITIES */
124 
125 	/*
126 	 * The owner matches if the effective uid associated with the
127 	 * credential matches that of the ACL_USER_OBJ entry.  While we're
128 	 * doing the first scan, also cache the location of the ACL_MASK
129 	 * and ACL_OTHER entries, preventing some future iterations.
130 	 */
131 	acl_mask = acl_other = NULL;
132 	for (i = 0; i < acl->acl_cnt; i++) {
133 		switch (acl->acl_entry[i].ae_tag) {
134 		case ACL_USER_OBJ:
135 			if (file_uid != cred->cr_uid)
136 				break;
137 			dac_granted = 0;
138 			dac_granted |= VADMIN;
139 			if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
140 				dac_granted |= VEXEC;
141 			if (acl->acl_entry[i].ae_perm & ACL_READ)
142 				dac_granted |= VREAD;
143 			if (acl->acl_entry[i].ae_perm & ACL_WRITE)
144 				dac_granted |= (VWRITE | VAPPEND);
145 			if ((acc_mode & dac_granted) == acc_mode)
146 				return (0);
147 			if ((acc_mode & (dac_granted | cap_granted)) ==
148 			    acc_mode) {
149 				if (privused != NULL)
150 					*privused = 1;
151 				return (0);
152 			}
153 			goto error;
154 
155 		case ACL_MASK:
156 			acl_mask = &acl->acl_entry[i];
157 			break;
158 
159 		case ACL_OTHER:
160 			acl_other = &acl->acl_entry[i];
161 			break;
162 
163 		default:
164 			break;
165 		}
166 	}
167 
168 	/*
169 	 * An ACL_OTHER entry should always exist in a valid access
170 	 * ACL.  If it doesn't, then generate a serious failure.  For now,
171 	 * this means a debugging message and EPERM, but in the future
172 	 * should probably be a panic.
173 	 */
174 	if (acl_other == NULL) {
175 		/*
176 		 * XXX This should never happen
177 		 */
178 		printf("vaccess_acl_posix1e: ACL_OTHER missing\n");
179 		return (EPERM);
180 	}
181 
182 	/*
183 	 * Checks against ACL_USER, ACL_GROUP_OBJ, and ACL_GROUP fields
184 	 * are masked by an ACL_MASK entry, if any.  As such, first identify
185 	 * the ACL_MASK field, then iterate through identifying potential
186 	 * user matches, then group matches.  If there is no ACL_MASK,
187 	 * assume that the mask allows all requests to succeed.
188 	 */
189 	if (acl_mask != NULL) {
190 		acl_mask_granted = 0;
191 		if (acl_mask->ae_perm & ACL_EXECUTE)
192 			acl_mask_granted |= VEXEC;
193 		if (acl_mask->ae_perm & ACL_READ)
194 			acl_mask_granted |= VREAD;
195 		if (acl_mask->ae_perm & ACL_WRITE)
196 			acl_mask_granted |= (VWRITE | VAPPEND);
197 	} else
198 		acl_mask_granted = VEXEC | VREAD | VWRITE | VAPPEND;
199 
200 	/*
201 	 * Iterate through user ACL entries.  Do checks twice, first
202 	 * without privilege, and then if a match is found but failed,
203 	 * a second time with privilege.
204 	 */
205 
206 	/*
207 	 * Check ACL_USER ACL entries.
208 	 */
209 	for (i = 0; i < acl->acl_cnt; i++) {
210 		switch (acl->acl_entry[i].ae_tag) {
211 		case ACL_USER:
212 			if (acl->acl_entry[i].ae_id != cred->cr_uid)
213 				break;
214 			dac_granted = 0;
215 			if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
216 				dac_granted |= VEXEC;
217 			if (acl->acl_entry[i].ae_perm & ACL_READ)
218 				dac_granted |= VREAD;
219 			if (acl->acl_entry[i].ae_perm & ACL_WRITE)
220 				dac_granted |= (VWRITE | VAPPEND);
221 			dac_granted &= acl_mask_granted;
222 			if ((acc_mode & dac_granted) == acc_mode)
223 				return (0);
224 			if ((acc_mode & (dac_granted | cap_granted)) !=
225 			    acc_mode)
226 				goto error;
227 
228 			if (privused != NULL)
229 				*privused = 1;
230 			return (0);
231 		}
232 	}
233 
234 	/*
235 	 * Group match is best-match, not first-match, so find a
236 	 * "best" match.  Iterate across, testing each potential group
237 	 * match.  Make sure we keep track of whether we found a match
238 	 * or not, so that we know if we should try again with any
239 	 * available privilege, or if we should move on to ACL_OTHER.
240 	 */
241 	group_matched = 0;
242 	for (i = 0; i < acl->acl_cnt; i++) {
243 		switch (acl->acl_entry[i].ae_tag) {
244 		case ACL_GROUP_OBJ:
245 			if (!groupmember(file_gid, cred))
246 				break;
247 			dac_granted = 0;
248 			if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
249 				dac_granted |= VEXEC;
250 			if (acl->acl_entry[i].ae_perm & ACL_READ)
251 				dac_granted |= VREAD;
252 			if (acl->acl_entry[i].ae_perm & ACL_WRITE)
253 				dac_granted |= (VWRITE | VAPPEND);
254 			dac_granted  &= acl_mask_granted;
255 
256 			if ((acc_mode & dac_granted) == acc_mode)
257 				return (0);
258 
259 			group_matched = 1;
260 			break;
261 
262 		case ACL_GROUP:
263 			if (!groupmember(acl->acl_entry[i].ae_id, cred))
264 				break;
265 			dac_granted = 0;
266 			if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
267 				dac_granted |= VEXEC;
268 			if (acl->acl_entry[i].ae_perm & ACL_READ)
269 				dac_granted |= VREAD;
270 			if (acl->acl_entry[i].ae_perm & ACL_WRITE)
271 				dac_granted |= (VWRITE | VAPPEND);
272 			dac_granted  &= acl_mask_granted;
273 
274 			if ((acc_mode & dac_granted) == acc_mode)
275 				return (0);
276 
277 			group_matched = 1;
278 			break;
279 
280 		default:
281 			break;
282 		}
283 	}
284 
285 	if (group_matched == 1) {
286 		/*
287 		 * There was a match, but it did not grant rights via
288 		 * pure DAC.  Try again, this time with privilege.
289 		 */
290 		for (i = 0; i < acl->acl_cnt; i++) {
291 			switch (acl->acl_entry[i].ae_tag) {
292 			case ACL_GROUP_OBJ:
293 				if (!groupmember(file_gid, cred))
294 					break;
295 				dac_granted = 0;
296 				if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
297 					dac_granted |= VEXEC;
298 				if (acl->acl_entry[i].ae_perm & ACL_READ)
299 					dac_granted |= VREAD;
300 				if (acl->acl_entry[i].ae_perm & ACL_WRITE)
301 					dac_granted |= (VWRITE | VAPPEND);
302 				dac_granted &= acl_mask_granted;
303 
304 				if ((acc_mode & (dac_granted | cap_granted)) !=
305 				    acc_mode)
306 					break;
307 
308 				if (privused != NULL)
309 					*privused = 1;
310 				return (0);
311 
312 			case ACL_GROUP:
313 				if (!groupmember(acl->acl_entry[i].ae_id,
314 				    cred))
315 					break;
316 				dac_granted = 0;
317 				if (acl->acl_entry[i].ae_perm & ACL_EXECUTE)
318 				dac_granted |= VEXEC;
319 				if (acl->acl_entry[i].ae_perm & ACL_READ)
320 					dac_granted |= VREAD;
321 				if (acl->acl_entry[i].ae_perm & ACL_WRITE)
322 					dac_granted |= (VWRITE | VAPPEND);
323 				dac_granted &= acl_mask_granted;
324 
325 				if ((acc_mode & (dac_granted | cap_granted)) !=
326 				    acc_mode)
327 					break;
328 
329 				if (privused != NULL)
330 					*privused = 1;
331 				return (0);
332 
333 			default:
334 				break;
335 			}
336 		}
337 		/*
338 		 * Even with privilege, group membership was not sufficient.
339 		 * Return failure.
340 		 */
341 		goto error;
342 	}
343 
344 	/*
345 	 * Fall back on ACL_OTHER.  ACL_MASK is not applied to ACL_OTHER.
346 	 */
347 	dac_granted = 0;
348 	if (acl_other->ae_perm & ACL_EXECUTE)
349 		dac_granted |= VEXEC;
350 	if (acl_other->ae_perm & ACL_READ)
351 		dac_granted |= VREAD;
352 	if (acl_other->ae_perm & ACL_WRITE)
353 		dac_granted |= (VWRITE | VAPPEND);
354 
355 	if ((acc_mode & dac_granted) == acc_mode)
356 		return (0);
357 	if ((acc_mode & (dac_granted | cap_granted)) == acc_mode) {
358 		if (privused != NULL)
359 			*privused = 1;
360 		return (0);
361 	}
362 
363 error:
364 	return ((acc_mode & VADMIN) ? EPERM : EACCES);
365 }
366 
367 /*
368  * For the purposes of filesystems maintaining the _OBJ entries in an
369  * inode with a mode_t field, this routine converts a mode_t entry
370  * to an acl_perm_t.
371  */
372 acl_perm_t
373 acl_posix1e_mode_to_perm(acl_tag_t tag, mode_t mode)
374 {
375 	acl_perm_t	perm = 0;
376 
377 	switch(tag) {
378 	case ACL_USER_OBJ:
379 		if (mode & S_IXUSR)
380 			perm |= ACL_EXECUTE;
381 		if (mode & S_IRUSR)
382 			perm |= ACL_READ;
383 		if (mode & S_IWUSR)
384 			perm |= ACL_WRITE;
385 		return (perm);
386 
387 	case ACL_GROUP_OBJ:
388 		if (mode & S_IXGRP)
389 			perm |= ACL_EXECUTE;
390 		if (mode & S_IRGRP)
391 			perm |= ACL_READ;
392 		if (mode & S_IWGRP)
393 			perm |= ACL_WRITE;
394 		return (perm);
395 
396 	case ACL_OTHER:
397 		if (mode & S_IXOTH)
398 			perm |= ACL_EXECUTE;
399 		if (mode & S_IROTH)
400 			perm |= ACL_READ;
401 		if (mode & S_IWOTH)
402 			perm |= ACL_WRITE;
403 		return (perm);
404 
405 	default:
406 		printf("acl_posix1e_mode_to_perm: invalid tag (%d)\n", tag);
407 		return (0);
408 	}
409 }
410 
411 /*
412  * Given inode information (uid, gid, mode), return an acl entry of the
413  * appropriate type.
414  */
415 struct acl_entry
416 acl_posix1e_mode_to_entry(acl_tag_t tag, uid_t uid, gid_t gid, mode_t mode)
417 {
418 	struct acl_entry	acl_entry;
419 
420 	acl_entry.ae_tag = tag;
421 	acl_entry.ae_perm = acl_posix1e_mode_to_perm(tag, mode);
422 	switch(tag) {
423 	case ACL_USER_OBJ:
424 		acl_entry.ae_id = uid;
425 		break;
426 
427 	case ACL_GROUP_OBJ:
428 		acl_entry.ae_id = gid;
429 		break;
430 
431 	case ACL_OTHER:
432 		acl_entry.ae_id = ACL_UNDEFINED_ID;
433 		break;
434 
435 	default:
436 		acl_entry.ae_id = ACL_UNDEFINED_ID;
437 		printf("acl_posix1e_mode_to_entry: invalid tag (%d)\n", tag);
438 	}
439 
440 	return (acl_entry);
441 }
442 
443 /*
444  * Utility function to generate a file mode given appropriate ACL entries.
445  */
446 mode_t
447 acl_posix1e_perms_to_mode(struct acl_entry *acl_user_obj_entry,
448     struct acl_entry *acl_group_obj_entry, struct acl_entry *acl_other_entry)
449 {
450 	mode_t	mode;
451 
452 	mode = 0;
453 	if (acl_user_obj_entry->ae_perm & ACL_EXECUTE)
454 		mode |= S_IXUSR;
455 	if (acl_user_obj_entry->ae_perm & ACL_READ)
456 		mode |= S_IRUSR;
457 	if (acl_user_obj_entry->ae_perm & ACL_WRITE)
458 		mode |= S_IWUSR;
459 	if (acl_group_obj_entry->ae_perm & ACL_EXECUTE)
460 		mode |= S_IXGRP;
461 	if (acl_group_obj_entry->ae_perm & ACL_READ)
462 		mode |= S_IRGRP;
463 	if (acl_group_obj_entry->ae_perm & ACL_WRITE)
464 		mode |= S_IWGRP;
465 	if (acl_other_entry->ae_perm & ACL_EXECUTE)
466 		mode |= S_IXOTH;
467 	if (acl_other_entry->ae_perm & ACL_READ)
468 		mode |= S_IROTH;
469 	if (acl_other_entry->ae_perm & ACL_WRITE)
470 		mode |= S_IWOTH;
471 
472 	return (mode);
473 }
474 
475 /*
476  * Utility function to generate a file mode given a complete POSIX.1e
477  * access ACL.  Note that if the ACL is improperly formed, this may
478  * result in a panic.
479  */
480 mode_t
481 acl_posix1e_acl_to_mode(struct acl *acl)
482 {
483 	struct acl_entry *acl_mask, *acl_user_obj, *acl_group_obj, *acl_other;
484 	int i;
485 
486 	/*
487 	 * Find the ACL entries relevant to a POSIX permission mode.
488 	 */
489 	acl_user_obj = acl_group_obj = acl_other = acl_mask = NULL;
490 	for (i = 0; i < acl->acl_cnt; i++) {
491 		switch (acl->acl_entry[i].ae_tag) {
492 		case ACL_USER_OBJ:
493 			acl_user_obj = &acl->acl_entry[i];
494 			break;
495 
496 		case ACL_GROUP_OBJ:
497 			acl_group_obj = &acl->acl_entry[i];
498 			break;
499 
500 		case ACL_OTHER:
501 			acl_other = &acl->acl_entry[i];
502 			break;
503 
504 		case ACL_MASK:
505 			acl_mask = &acl->acl_entry[i];
506 			break;
507 
508 		case ACL_USER:
509 		case ACL_GROUP:
510 			break;
511 
512 		default:
513 			panic("acl_posix1e_acl_to_mode: bad ae_tag");
514 		}
515 	}
516 
517 	if (acl_user_obj == NULL || acl_group_obj == NULL || acl_other == NULL)
518 		panic("acl_posix1e_acl_to_mode: missing base ae_tags");
519 
520 	/*
521 	 * POSIX.1e specifies that if there is an ACL_MASK entry, we replace
522 	 * the mode "group" bits with its permissions.  If there isn't, we
523 	 * use the ACL_GROUP_OBJ permissions.
524 	 */
525 	if (acl_mask != NULL)
526 		return (acl_posix1e_perms_to_mode(acl_user_obj, acl_mask,
527 		    acl_other));
528 	else
529 		return (acl_posix1e_perms_to_mode(acl_user_obj, acl_group_obj,
530 		    acl_other));
531 }
532 
533 /*
534  * Perform a syntactic check of the ACL, sufficient to allow an
535  * implementing filesystem to determine if it should accept this and
536  * rely on the POSIX.1e ACL properties.
537  */
538 int
539 acl_posix1e_check(struct acl *acl)
540 {
541 	int num_acl_user_obj, num_acl_user, num_acl_group_obj, num_acl_group;
542 	int num_acl_mask, num_acl_other, i;
543 
544 	/*
545 	 * Verify that the number of entries does not exceed the maximum
546 	 * defined for acl_t.
547 	 * Verify that the correct number of various sorts of ae_tags are
548 	 * present:
549 	 *   Exactly one ACL_USER_OBJ
550 	 *   Exactly one ACL_GROUP_OBJ
551 	 *   Exactly one ACL_OTHER
552 	 *   If any ACL_USER or ACL_GROUP entries appear, then exactly one
553 	 *   ACL_MASK entry must also appear.
554 	 * Verify that all ae_perm entries are in ACL_PERM_BITS.
555 	 * Verify all ae_tag entries are understood by this implementation.
556 	 * Note: Does not check for uniqueness of qualifier (ae_id) field.
557 	 */
558 	num_acl_user_obj = num_acl_user = num_acl_group_obj = num_acl_group =
559 	    num_acl_mask = num_acl_other = 0;
560 	if (acl->acl_cnt > ACL_MAX_ENTRIES || acl->acl_cnt < 0)
561 		return (EINVAL);
562 	for (i = 0; i < acl->acl_cnt; i++) {
563 		/*
564 		 * Check for a valid tag.
565 		 */
566 		switch(acl->acl_entry[i].ae_tag) {
567 		case ACL_USER_OBJ:
568 			acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
569 			if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
570 				return (EINVAL);
571 			num_acl_user_obj++;
572 			break;
573 		case ACL_GROUP_OBJ:
574 			acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
575 			if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
576 				return (EINVAL);
577 			num_acl_group_obj++;
578 			break;
579 		case ACL_USER:
580 			if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
581 				return (EINVAL);
582 			num_acl_user++;
583 			break;
584 		case ACL_GROUP:
585 			if (acl->acl_entry[i].ae_id == ACL_UNDEFINED_ID)
586 				return (EINVAL);
587 			num_acl_group++;
588 			break;
589 		case ACL_OTHER:
590 			acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
591 			if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
592 				return (EINVAL);
593 			num_acl_other++;
594 			break;
595 		case ACL_MASK:
596 			acl->acl_entry[i].ae_id = ACL_UNDEFINED_ID; /* XXX */
597 			if (acl->acl_entry[i].ae_id != ACL_UNDEFINED_ID)
598 				return (EINVAL);
599 			num_acl_mask++;
600 			break;
601 		default:
602 			return (EINVAL);
603 		}
604 		/*
605 		 * Check for valid perm entries.
606 		 */
607 		if ((acl->acl_entry[i].ae_perm | ACL_PERM_BITS) !=
608 		    ACL_PERM_BITS)
609 			return (EINVAL);
610 	}
611 	if ((num_acl_user_obj != 1) || (num_acl_group_obj != 1) ||
612 	    (num_acl_other != 1) || (num_acl_mask != 0 && num_acl_mask != 1))
613 		return (EINVAL);
614 	if (((num_acl_group != 0) || (num_acl_user != 0)) &&
615 	    (num_acl_mask != 1))
616 		return (EINVAL);
617 	return (0);
618 }
619 
620 /*
621  * Given a requested mode for a new object, and a default ACL, combine
622  * the two to produce a new mode.  Be careful not to clear any bits that
623  * aren't intended to be affected by the POSIX.1e ACL.  Eventually,
624  * this might also take the cmask as an argument, if we push that down
625  * into per-filesystem-code.
626  */
627 mode_t
628 acl_posix1e_newfilemode(mode_t cmode, struct acl *dacl)
629 {
630 	mode_t mode;
631 
632 	mode = cmode;
633 	/*
634 	 * The current composition policy is that a permission bit must
635 	 * be set in *both* the ACL and the requested creation mode for
636 	 * it to appear in the resulting mode/ACL.  First clear any
637 	 * possibly effected bits, then reconstruct.
638 	 */
639 	mode &= ACL_PRESERVE_MASK;
640 	mode |= (ACL_OVERRIDE_MASK & cmode & acl_posix1e_acl_to_mode(dacl));
641 
642 	return (mode);
643 }
644 
645 /*
646  * These calls wrap the real vnode operations, and are called by the
647  * syscall code once the syscall has converted the path or file
648  * descriptor to a vnode (unlocked).  The aclp pointer is assumed
649  * still to point to userland, so this should not be consumed within
650  * the kernel except by syscall code.  Other code should directly
651  * invoke VOP_{SET,GET}ACL.
652  */
653 
654 /*
655  * Given a vnode, set its ACL.
656  */
657 static int
658 vacl_set_acl(struct thread *td, struct vnode *vp, acl_type_t type,
659     struct acl *aclp)
660 {
661 	struct acl inkernacl;
662 	struct mount *mp;
663 	int error;
664 
665 	error = copyin(aclp, &inkernacl, sizeof(struct acl));
666 	if (error)
667 		return(error);
668 	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
669 	if (error != 0)
670 		return (error);
671 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
672 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
673 #ifdef MAC
674 	error = mac_check_vnode_setacl(td->td_ucred, vp, type, &inkernacl);
675 	if (error != 0)
676 		goto out;
677 #endif
678 	error = VOP_SETACL(vp, type, &inkernacl, td->td_ucred, td);
679 #ifdef MAC
680 out:
681 #endif
682 	VOP_UNLOCK(vp, 0, td);
683 	vn_finished_write(mp);
684 	return(error);
685 }
686 
687 /*
688  * Given a vnode, get its ACL.
689  */
690 static int
691 vacl_get_acl(struct thread *td, struct vnode *vp, acl_type_t type,
692     struct acl *aclp)
693 {
694 	struct acl inkernelacl;
695 	int error;
696 
697 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
698 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
699 #ifdef MAC
700 	error = mac_check_vnode_getacl(td->td_ucred, vp, type);
701 	if (error != 0)
702 		goto out;
703 #endif
704 	error = VOP_GETACL(vp, type, &inkernelacl, td->td_ucred, td);
705 #ifdef MAC
706 out:
707 #endif
708 	VOP_UNLOCK(vp, 0, td);
709 	if (error == 0)
710 		error = copyout(&inkernelacl, aclp, sizeof(struct acl));
711 	return (error);
712 }
713 
714 /*
715  * Given a vnode, delete its ACL.
716  */
717 static int
718 vacl_delete(struct thread *td, struct vnode *vp, acl_type_t type)
719 {
720 	struct mount *mp;
721 	int error;
722 
723 	error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
724 	if (error)
725 		return (error);
726 	VOP_LEASE(vp, td, td->td_ucred, LEASE_WRITE);
727 	vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
728 #ifdef MAC
729 	error = mac_check_vnode_deleteacl(td->td_ucred, vp, type);
730 	if (error)
731 		goto out;
732 #endif
733 	error = VOP_SETACL(vp, type, 0, td->td_ucred, td);
734 #ifdef MAC
735 out:
736 #endif
737 	VOP_UNLOCK(vp, 0, td);
738 	vn_finished_write(mp);
739 	return (error);
740 }
741 
742 /*
743  * Given a vnode, check whether an ACL is appropriate for it
744  */
745 static int
746 vacl_aclcheck(struct thread *td, struct vnode *vp, acl_type_t type,
747     struct acl *aclp)
748 {
749 	struct acl inkernelacl;
750 	int error;
751 
752 	error = copyin(aclp, &inkernelacl, sizeof(struct acl));
753 	if (error)
754 		return(error);
755 	error = VOP_ACLCHECK(vp, type, &inkernelacl, td->td_ucred, td);
756 	return (error);
757 }
758 
759 /*
760  * syscalls -- convert the path/fd to a vnode, and call vacl_whatever.
761  * Don't need to lock, as the vacl_ code will get/release any locks
762  * required.
763  */
764 
765 /*
766  * Given a file path, get an ACL for it
767  *
768  * MPSAFE
769  */
770 int
771 __acl_get_file(struct thread *td, struct __acl_get_file_args *uap)
772 {
773 	struct nameidata nd;
774 	int error;
775 
776 	mtx_lock(&Giant);
777 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
778 	error = namei(&nd);
779 	if (error == 0) {
780 		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
781 		NDFREE(&nd, 0);
782 	}
783 	mtx_unlock(&Giant);
784 	return (error);
785 }
786 
787 /*
788  * Given a file path, get an ACL for it; don't follow links.
789  *
790  * MPSAFE
791  */
792 int
793 __acl_get_link(struct thread *td, struct __acl_get_link_args *uap)
794 {
795 	struct nameidata nd;
796 	int error;
797 
798 	mtx_lock(&Giant);
799 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
800 	error = namei(&nd);
801 	if (error == 0) {
802 		error = vacl_get_acl(td, nd.ni_vp, uap->type, uap->aclp);
803 		NDFREE(&nd, 0);
804 	}
805 	mtx_unlock(&Giant);
806 	return (error);
807 }
808 
809 /*
810  * Given a file path, set an ACL for it
811  *
812  * MPSAFE
813  */
814 int
815 __acl_set_file(struct thread *td, struct __acl_set_file_args *uap)
816 {
817 	struct nameidata nd;
818 	int error;
819 
820 	mtx_lock(&Giant);
821 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
822 	error = namei(&nd);
823 	if (error == 0) {
824 		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
825 		NDFREE(&nd, 0);
826 	}
827 	mtx_unlock(&Giant);
828 	return (error);
829 }
830 
831 /*
832  * Given a file path, set an ACL for it; don't follow links.
833  *
834  * MPSAFE
835  */
836 int
837 __acl_set_link(struct thread *td, struct __acl_set_link_args *uap)
838 {
839 	struct nameidata nd;
840 	int error;
841 
842 	mtx_lock(&Giant);
843 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
844 	error = namei(&nd);
845 	if (error == 0) {
846 		error = vacl_set_acl(td, nd.ni_vp, uap->type, uap->aclp);
847 		NDFREE(&nd, 0);
848 	}
849 	mtx_unlock(&Giant);
850 	return (error);
851 }
852 
853 /*
854  * Given a file descriptor, get an ACL for it
855  *
856  * MPSAFE
857  */
858 int
859 __acl_get_fd(struct thread *td, struct __acl_get_fd_args *uap)
860 {
861 	struct file *fp;
862 	int error;
863 
864 	mtx_lock(&Giant);
865 	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
866 	if (error == 0) {
867 		error = vacl_get_acl(td, fp->f_vnode, uap->type, uap->aclp);
868 		fdrop(fp, td);
869 	}
870 	mtx_unlock(&Giant);
871 	return (error);
872 }
873 
874 /*
875  * Given a file descriptor, set an ACL for it
876  *
877  * MPSAFE
878  */
879 int
880 __acl_set_fd(struct thread *td, struct __acl_set_fd_args *uap)
881 {
882 	struct file *fp;
883 	int error;
884 
885 	mtx_lock(&Giant);
886 	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
887 	if (error == 0) {
888 		error = vacl_set_acl(td, fp->f_vnode, uap->type, uap->aclp);
889 		fdrop(fp, td);
890 	}
891 	mtx_unlock(&Giant);
892 	return (error);
893 }
894 
895 /*
896  * Given a file path, delete an ACL from it.
897  *
898  * MPSAFE
899  */
900 int
901 __acl_delete_file(struct thread *td, struct __acl_delete_file_args *uap)
902 {
903 	struct nameidata nd;
904 	int error;
905 
906 	mtx_lock(&Giant);
907 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
908 	error = namei(&nd);
909 	if (error == 0) {
910 		error = vacl_delete(td, nd.ni_vp, uap->type);
911 		NDFREE(&nd, 0);
912 	}
913 	mtx_unlock(&Giant);
914 	return (error);
915 }
916 
917 /*
918  * Given a file path, delete an ACL from it; don't follow links.
919  *
920  * MPSAFE
921  */
922 int
923 __acl_delete_link(struct thread *td, struct __acl_delete_link_args *uap)
924 {
925 	struct nameidata nd;
926 	int error;
927 
928 	mtx_lock(&Giant);
929 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
930 	error = namei(&nd);
931 	if (error == 0) {
932 		error = vacl_delete(td, nd.ni_vp, uap->type);
933 		NDFREE(&nd, 0);
934 	}
935 	mtx_unlock(&Giant);
936 	return (error);
937 }
938 
939 /*
940  * Given a file path, delete an ACL from it.
941  *
942  * MPSAFE
943  */
944 int
945 __acl_delete_fd(struct thread *td, struct __acl_delete_fd_args *uap)
946 {
947 	struct file *fp;
948 	int error;
949 
950 	mtx_lock(&Giant);
951 	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
952 	if (error == 0) {
953 		error = vacl_delete(td, fp->f_vnode, uap->type);
954 		fdrop(fp, td);
955 	}
956 	mtx_unlock(&Giant);
957 	return (error);
958 }
959 
960 /*
961  * Given a file path, check an ACL for it
962  *
963  * MPSAFE
964  */
965 int
966 __acl_aclcheck_file(struct thread *td, struct __acl_aclcheck_file_args *uap)
967 {
968 	struct nameidata	nd;
969 	int	error;
970 
971 	mtx_lock(&Giant);
972 	NDINIT(&nd, LOOKUP, FOLLOW, UIO_USERSPACE, uap->path, td);
973 	error = namei(&nd);
974 	if (error == 0) {
975 		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
976 		NDFREE(&nd, 0);
977 	}
978 	mtx_unlock(&Giant);
979 	return (error);
980 }
981 
982 /*
983  * Given a file path, check an ACL for it; don't follow links.
984  *
985  * MPSAFE
986  */
987 int
988 __acl_aclcheck_link(struct thread *td, struct __acl_aclcheck_link_args *uap)
989 {
990 	struct nameidata	nd;
991 	int	error;
992 
993 	mtx_lock(&Giant);
994 	NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_USERSPACE, uap->path, td);
995 	error = namei(&nd);
996 	if (error == 0) {
997 		error = vacl_aclcheck(td, nd.ni_vp, uap->type, uap->aclp);
998 		NDFREE(&nd, 0);
999 	}
1000 	mtx_unlock(&Giant);
1001 	return (error);
1002 }
1003 
1004 /*
1005  * Given a file descriptor, check an ACL for it
1006  *
1007  * MPSAFE
1008  */
1009 int
1010 __acl_aclcheck_fd(struct thread *td, struct __acl_aclcheck_fd_args *uap)
1011 {
1012 	struct file *fp;
1013 	int error;
1014 
1015 	mtx_lock(&Giant);
1016 	error = getvnode(td->td_proc->p_fd, uap->filedes, &fp);
1017 	if (error == 0) {
1018 		error = vacl_aclcheck(td, fp->f_vnode, uap->type, uap->aclp);
1019 		fdrop(fp, td);
1020 	}
1021 	mtx_unlock(&Giant);
1022 	return (error);
1023 }
1024