xref: /freebsd/sys/security/mac_bsdextended/mac_bsdextended.c (revision cec50dea12481dc578c0805c887ab2097e1c06c5)
1 /*-
2  * Copyright (c) 1999-2002 Robert N. M. Watson
3  * Copyright (c) 2001-2003 Networks Associates Technology, Inc.
4  * All rights reserved.
5  *
6  * This software was developed by Robert Watson for the TrustedBSD Project.
7  *
8  * This software was developed for the FreeBSD Project in part by Network
9  * Associates Laboratories, the Security Research Division of Network
10  * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11  * as part of the DARPA CHATS research program.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $FreeBSD$
35  */
36 /*
37  * Developed by the TrustedBSD Project.
38  * "BSD Extended" MAC policy, allowing the administrator to impose
39  * mandatory rules regarding users and some system objects.
40  *
41  * XXX: Much locking support required here.
42  */
43 
44 #include <sys/types.h>
45 #include <sys/param.h>
46 #include <sys/acl.h>
47 #include <sys/conf.h>
48 #include <sys/kernel.h>
49 #include <sys/mac.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/proc.h>
53 #include <sys/systm.h>
54 #include <sys/sysproto.h>
55 #include <sys/sysent.h>
56 #include <sys/vnode.h>
57 #include <sys/file.h>
58 #include <sys/socket.h>
59 #include <sys/socketvar.h>
60 #include <sys/sysctl.h>
61 #include <sys/syslog.h>
62 
63 #include <net/bpfdesc.h>
64 #include <net/if.h>
65 #include <net/if_types.h>
66 #include <net/if_var.h>
67 
68 #include <vm/vm.h>
69 
70 #include <sys/mac_policy.h>
71 
72 #include <security/mac_bsdextended/mac_bsdextended.h>
73 
74 SYSCTL_DECL(_security_mac);
75 
76 SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
77     "TrustedBSD extended BSD MAC policy controls");
78 
79 static int	mac_bsdextended_enabled = 1;
80 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
81     &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
82 TUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
83 
84 MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
85 
86 #define	MAC_BSDEXTENDED_MAXRULES	250
87 static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
88 static int rule_count = 0;
89 static int rule_slots = 0;
90 
91 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
92     &rule_count, 0, "Number of defined rules\n");
93 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
94     &rule_slots, 0, "Number of used rule slots\n");
95 
96 /*
97  * This is just used for logging purposes as eventually we would like
98  * to log much more then failed requests.
99  */
100 static int mac_bsdextended_logging;
101 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
102     &mac_bsdextended_logging, 0, "Log failed authorization requests");
103 
104 /*
105  * This tunable is here for compatibility.  It will allow the user
106  * to switch between the new mode (first rule matches) and the old
107  * functionality (all rules match).
108  */
109 static int
110 mac_bsdextended_firstmatch_enabled;
111 SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
112 	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
113 	"Disable/enable match first rule functionality");
114 
115 static int
116 mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
117 {
118 
119 	if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
120 		return (EINVAL);
121 
122 	if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
123 		return (EINVAL);
124 
125 	if ((rule->mbr_mode | VALLPERM) != VALLPERM)
126 		return (EINVAL);
127 
128 	return (0);
129 }
130 
131 static int
132 sysctl_rule(SYSCTL_HANDLER_ARGS)
133 {
134 	struct mac_bsdextended_rule temprule, *ruleptr;
135 	u_int namelen;
136 	int error, index, *name;
137 
138 	name = (int *)arg1;
139 	namelen = arg2;
140 
141 	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
142 
143 	if (namelen != 1)
144 		return (EINVAL);
145 
146 	index = name[0];
147 	if (index < 0 || index > rule_slots + 1)
148 		return (ENOENT);
149 	if (rule_slots >= MAC_BSDEXTENDED_MAXRULES)
150 		return (ENOENT);
151 
152 	if (req->oldptr) {
153 		if (rules[index] == NULL)
154 			return (ENOENT);
155 
156 		error = SYSCTL_OUT(req, rules[index], sizeof(*rules[index]));
157 		if (error)
158 			return (error);
159 	}
160 
161 	if (req->newptr) {
162 		if (req->newlen == 0) {
163 			/* printf("deletion\n"); */
164 			ruleptr = rules[index];
165 			if (ruleptr == NULL)
166 				return (ENOENT);
167 			rule_count--;
168 			rules[index] = NULL;
169 			FREE(ruleptr, M_MACBSDEXTENDED);
170 			return(0);
171 		}
172 		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
173 		if (error)
174 			return (error);
175 
176 		error = mac_bsdextended_rule_valid(&temprule);
177 		if (error)
178 			return (error);
179 
180 		if (rules[index] == NULL) {
181 			/* printf("addition\n"); */
182 			MALLOC(ruleptr, struct mac_bsdextended_rule *,
183 			    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK |
184 			    M_ZERO);
185 			*ruleptr = temprule;
186 			rules[index] = ruleptr;
187 			if (index+1 > rule_slots)
188 				rule_slots = index+1;
189 			rule_count++;
190 		} else {
191 			/* printf("replacement\n"); */
192 			*rules[index] = temprule;
193 		}
194 	}
195 
196 	return (0);
197 }
198 
199 SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
200     CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
201 
202 static void
203 mac_bsdextended_init(struct mac_policy_conf *mpc)
204 {
205 
206 	/* Initialize ruleset lock. */
207 	/* Register dynamic sysctl's for rules. */
208 }
209 
210 static void
211 mac_bsdextended_destroy(struct mac_policy_conf *mpc)
212 {
213 
214 	/* Tear down sysctls. */
215 	/* Destroy ruleset lock. */
216 }
217 
218 static int
219 mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
220     struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
221 {
222 	int match;
223 
224 	/*
225 	 * Is there a subject match?
226 	 */
227 	if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
228 		match =  (rule->mbr_subject.mbi_uid == cred->cr_uid ||
229 		    rule->mbr_subject.mbi_uid == cred->cr_ruid ||
230 		    rule->mbr_subject.mbi_uid == cred->cr_svuid);
231 
232 		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
233 			match = !match;
234 
235 		if (!match)
236 			return (0);
237 	}
238 
239 	if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
240 		match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
241 		    rule->mbr_subject.mbi_gid == cred->cr_rgid ||
242 		    rule->mbr_subject.mbi_gid == cred->cr_svgid);
243 
244 		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
245 			match = !match;
246 
247 		if (!match)
248 			return (0);
249 	}
250 
251 	/*
252 	 * Is there an object match?
253 	 */
254 	if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
255 		match = (rule->mbr_object.mbi_uid == object_uid);
256 
257 		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
258 			match = !match;
259 
260 		if (!match)
261 			return (0);
262 	}
263 
264 	if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
265 		match = (rule->mbr_object.mbi_gid == object_gid);
266 
267 		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
268 			match = !match;
269 
270 		if (!match)
271 			return (0);
272 	}
273 
274 	/*
275 	 * Is the access permitted?
276 	 */
277 	if ((rule->mbr_mode & acc_mode) != acc_mode) {
278 		if (mac_bsdextended_logging)
279 			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
280 			    " on %d:%d failed. \n", cred->cr_ruid,
281 			    cred->cr_rgid, acc_mode, object_uid, object_gid);
282 		return (EACCES); /* Matching rule denies access */
283 	}
284 	/*
285 	 * If the rule matched and allowed access and first match is
286 	 * enabled, then return success.
287 	 */
288 	if (mac_bsdextended_firstmatch_enabled)
289 		return (EJUSTRETURN);
290 	else
291 		return(0);
292 }
293 
294 static int
295 mac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
296     int acc_mode)
297 {
298 	int error, i;
299 
300 	if (suser_cred(cred, 0) == 0)
301 		return (0);
302 
303 	for (i = 0; i < rule_slots; i++) {
304 		if (rules[i] == NULL)
305 			continue;
306 
307 		/*
308 		 * Since we don't separately handle append, map append to
309 		 * write.
310 		 */
311 		if (acc_mode & VAPPEND) {
312 			acc_mode &= ~VAPPEND;
313 			acc_mode |= VWRITE;
314 		}
315 
316 		error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
317 		    object_gid, acc_mode);
318 		if (error == EJUSTRETURN)
319 			break;
320 		if (error)
321 			return (error);
322 	}
323 
324 	return (0);
325 }
326 
327 static int
328 mac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
329     struct label *label)
330 {
331 	struct vattr vap;
332 	int error;
333 
334 	if (!mac_bsdextended_enabled)
335 		return (0);
336 
337 	error = VOP_GETATTR(vp, &vap, cred, curthread);
338 	if (error)
339 		return (error);
340 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
341 }
342 
343 static int
344 mac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
345     struct label *label, int acc_mode)
346 {
347 	struct vattr vap;
348 	int error;
349 
350 	if (!mac_bsdextended_enabled)
351 		return (0);
352 
353 	error = VOP_GETATTR(vp, &vap, cred, curthread);
354 	if (error)
355 		return (error);
356 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
357 }
358 
359 static int
360 mac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
361     struct label *dlabel)
362 {
363 	struct vattr vap;
364 	int error;
365 
366 	if (!mac_bsdextended_enabled)
367 		return (0);
368 
369 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
370 	if (error)
371 		return (error);
372 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
373 }
374 
375 static int
376 mac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
377     struct label *dlabel)
378 {
379 	struct vattr vap;
380 	int error;
381 
382 	if (!mac_bsdextended_enabled)
383 		return (0);
384 
385 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
386 	if (error)
387 		return (error);
388 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
389 }
390 
391 static int
392 mac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
393     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
394 {
395 	struct vattr dvap;
396 	int error;
397 
398 	if (!mac_bsdextended_enabled)
399 		return (0);
400 
401 	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
402 	if (error)
403 		return (error);
404 	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid, VWRITE));
405 }
406 
407 static int
408 mac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
409     struct label *dlabel, struct vnode *vp, struct label *label,
410     struct componentname *cnp)
411 {
412 	struct vattr vap;
413 	int error;
414 
415 	if (!mac_bsdextended_enabled)
416 		return (0);
417 
418 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
419 	if (error)
420 		return (error);
421 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
422 	if (error)
423 		return (error);
424 
425 	error = VOP_GETATTR(vp, &vap, cred, curthread);
426 	if (error)
427 		return (error);
428 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
429 }
430 
431 static int
432 mac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
433     struct label *label, acl_type_t type)
434 {
435 	struct vattr vap;
436 	int error;
437 
438 	if (!mac_bsdextended_enabled)
439 		return (0);
440 
441 	error = VOP_GETATTR(vp, &vap, cred, curthread);
442 	if (error)
443 		return (error);
444 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
445 }
446 
447 static int
448 mac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
449     struct label *label, int attrnamespace, const char *name)
450 {
451 	struct vattr vap;
452 	int error;
453 
454 	if (!mac_bsdextended_enabled)
455 		return (0);
456 
457 	error = VOP_GETATTR(vp, &vap, cred, curthread);
458 	if (error)
459 		return (error);
460 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
461 }
462 
463 static int
464 mac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
465     struct label *label, struct image_params *imgp,
466     struct label *execlabel)
467 {
468 	struct vattr vap;
469 	int error;
470 
471 	if (!mac_bsdextended_enabled)
472 		return (0);
473 
474 	error = VOP_GETATTR(vp, &vap, cred, curthread);
475 	if (error)
476 		return (error);
477 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
478 	    VREAD|VEXEC));
479 }
480 
481 static int
482 mac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
483     struct label *label, acl_type_t type)
484 {
485 	struct vattr vap;
486 	int error;
487 
488 	if (!mac_bsdextended_enabled)
489 		return (0);
490 
491 	error = VOP_GETATTR(vp, &vap, cred, curthread);
492 	if (error)
493 		return (error);
494 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VSTAT));
495 }
496 
497 static int
498 mac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
499     struct label *label, int attrnamespace, const char *name, struct uio *uio)
500 {
501 	struct vattr vap;
502 	int error;
503 
504 	if (!mac_bsdextended_enabled)
505 		return (0);
506 
507 	error = VOP_GETATTR(vp, &vap, cred, curthread);
508 	if (error)
509 		return (error);
510 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
511 }
512 
513 static int
514 mac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
515     struct label *dlabel, struct vnode *vp, struct label *label,
516     struct componentname *cnp)
517 {
518 	struct vattr vap;
519 	int error;
520 
521 	if (!mac_bsdextended_enabled)
522 		return (0);
523 
524 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
525 	if (error)
526 		return (error);
527 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
528 	if (error)
529 		return (error);
530 
531 	error = VOP_GETATTR(vp, &vap, cred, curthread);
532 	if (error)
533 		return (error);
534 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
535 	if (error)
536 		return (error);
537 	return (0);
538 }
539 
540 static int
541 mac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
542     struct label *label, int attrnamespace)
543 {
544 	struct vattr vap;
545 	int error;
546 
547 	if (!mac_bsdextended_enabled)
548 		return (0);
549 
550 	error = VOP_GETATTR(vp, &vap, cred, curthread);
551 	if (error)
552 		return (error);
553 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
554 }
555 
556 static int
557 mac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
558     struct label *dlabel, struct componentname *cnp)
559 {
560 	struct vattr vap;
561 	int error;
562 
563 	if (!mac_bsdextended_enabled)
564 		return (0);
565 
566 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
567 	if (error)
568 		return (error);
569 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
570 }
571 
572 static int
573 mac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
574     struct label *filelabel, int acc_mode)
575 {
576 	struct vattr vap;
577 	int error;
578 
579 	if (!mac_bsdextended_enabled)
580 		return (0);
581 
582 	error = VOP_GETATTR(vp, &vap, cred, curthread);
583 	if (error)
584 		return (error);
585 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
586 }
587 
588 static int
589 mac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
590     struct label *dlabel)
591 {
592 	struct vattr vap;
593 	int error;
594 
595 	if (!mac_bsdextended_enabled)
596 		return (0);
597 
598 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
599 	if (error)
600 		return (error);
601 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
602 }
603 
604 static int
605 mac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
606     struct label *label)
607 {
608 	struct vattr vap;
609 	int error;
610 
611 	if (!mac_bsdextended_enabled)
612 		return (0);
613 
614 	error = VOP_GETATTR(vp, &vap, cred, curthread);
615 	if (error)
616 		return (error);
617 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
618 }
619 
620 static int
621 mac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
622     struct label *dlabel, struct vnode *vp, struct label *label,
623     struct componentname *cnp)
624 {
625 	struct vattr vap;
626 	int error;
627 
628 	if (!mac_bsdextended_enabled)
629 		return (0);
630 
631 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
632 	if (error)
633 		return (error);
634 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
635 	if (error)
636 		return (error);
637 	error = VOP_GETATTR(vp, &vap, cred, curthread);
638 	if (error)
639 		return (error);
640 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
641 
642 	return (error);
643 }
644 
645 static int
646 mac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
647     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
648     struct componentname *cnp)
649 {
650 	struct vattr vap;
651 	int error;
652 
653 	if (!mac_bsdextended_enabled)
654 		return (0);
655 
656 	error = VOP_GETATTR(dvp, &vap, cred, curthread);
657 	if (error)
658 		return (error);
659 	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
660 	if (error)
661 		return (error);
662 
663 	if (vp != NULL) {
664 		error = VOP_GETATTR(vp, &vap, cred, curthread);
665 		if (error)
666 			return (error);
667 		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
668 		    VWRITE);
669 	}
670 
671 	return (error);
672 }
673 
674 static int
675 mac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
676     struct label *label)
677 {
678 	struct vattr vap;
679 	int error;
680 
681 	if (!mac_bsdextended_enabled)
682 		return (0);
683 
684 	error = VOP_GETATTR(vp, &vap, cred, curthread);
685 	if (error)
686 		return (error);
687 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
688 }
689 
690 static int
691 mac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
692     struct label *label, acl_type_t type, struct acl *acl)
693 {
694 	struct vattr vap;
695 	int error;
696 
697 	if (!mac_bsdextended_enabled)
698 		return (0);
699 
700 	error = VOP_GETATTR(vp, &vap, cred, curthread);
701 	if (error)
702 		return (error);
703 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
704 }
705 
706 static int
707 mac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
708     struct label *label, int attrnamespace, const char *name, struct uio *uio)
709 {
710 	struct vattr vap;
711 	int error;
712 
713 	if (!mac_bsdextended_enabled)
714 		return (0);
715 
716 	error = VOP_GETATTR(vp, &vap, cred, curthread);
717 	if (error)
718 		return (error);
719 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
720 }
721 
722 static int
723 mac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
724     struct label *label, u_long flags)
725 {
726 	struct vattr vap;
727 	int error;
728 
729 	if (!mac_bsdextended_enabled)
730 		return (0);
731 
732 	error = VOP_GETATTR(vp, &vap, cred, curthread);
733 	if (error)
734 		return (error);
735 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
736 }
737 
738 static int
739 mac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
740     struct label *label, mode_t mode)
741 {
742 	struct vattr vap;
743 	int error;
744 
745 	if (!mac_bsdextended_enabled)
746 		return (0);
747 
748 	error = VOP_GETATTR(vp, &vap, cred, curthread);
749 	if (error)
750 		return (error);
751 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
752 }
753 
754 static int
755 mac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
756     struct label *label, uid_t uid, gid_t gid)
757 {
758 	struct vattr vap;
759 	int error;
760 
761 	if (!mac_bsdextended_enabled)
762 		return (0);
763 
764 	error = VOP_GETATTR(vp, &vap, cred, curthread);
765 	if (error)
766 		return (error);
767 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
768 }
769 
770 static int
771 mac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
772     struct label *label, struct timespec atime, struct timespec utime)
773 {
774 	struct vattr vap;
775 	int error;
776 
777 	if (!mac_bsdextended_enabled)
778 		return (0);
779 
780 	error = VOP_GETATTR(vp, &vap, cred, curthread);
781 	if (error)
782 		return (error);
783 	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
784 }
785 
786 static int
787 mac_bsdextended_check_vnode_stat(struct ucred *active_cred,
788     struct ucred *file_cred, struct vnode *vp, struct label *label)
789 {
790 	struct vattr vap;
791 	int error;
792 
793 	if (!mac_bsdextended_enabled)
794 		return (0);
795 
796 	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
797 	if (error)
798 		return (error);
799 	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
800 	    VSTAT));
801 }
802 
803 static struct mac_policy_ops mac_bsdextended_ops =
804 {
805 	.mpo_destroy = mac_bsdextended_destroy,
806 	.mpo_init = mac_bsdextended_init,
807 	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
808 	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
809 	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
810 	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
811 	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
812 	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
813 	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
814 	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
815 	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
816 	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
817 	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
818 	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
819 	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
820 	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
821 	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
822 	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
823 	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
824 	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
825 	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
826 	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
827 	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
828 	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
829 	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
830 	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
831 	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
832 	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
833 	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
834 };
835 
836 MAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
837     "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
838