ugidfw_vnode.c revision 134132
1249423Sdim/*-
2249423Sdim * 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: head/sys/security/mac_bsdextended/mac_bsdextended.c 134132 2004-08-21 20:19:19Z trhodes $
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
74SYSCTL_DECL(_security_mac);
75
76SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
77    "TrustedBSD extended BSD MAC policy controls");
78
79static int	mac_bsdextended_enabled = 1;
80SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
81    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
82TUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
83
84MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
85
86#define	MAC_BSDEXTENDED_MAXRULES	250
87static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
88static int rule_count = 0;
89static int rule_slots = 0;
90
91SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
92    &rule_count, 0, "Number of defined rules\n");
93SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
94    &rule_slots, 0, "Number of used rule slots\n");
95
96/*
97 * This tunable spits out information about what is going on which
98 * would be more suited for a log file.  Eventually
99 * this will go away as we do not currently use it.
100 */
101static int mac_bsdextended_debugging;
102SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, debugging, CTLFLAG_RW,
103    &mac_bsdextended_debugging, 0, "Enable debugging on failure");
104
105/*
106 * This is just used for logging purposes as eventually we would like
107 * to log much more then failed requests.
108 */
109static int mac_bsdextended_logging;
110SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
111    &mac_bsdextended_logging, 0, "Log failed authorization requests");
112
113/*
114 * This tunable is here for compatibility.  It will allow the user
115 * to switch between the new mode (first rule matches) and the old
116 * functionality (all rules match).
117 */
118static int
119mac_bsdextended_firstmatch_enabled;
120SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
121	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 0,
122	"Disable/enable match first rule functionality");
123
124static int
125mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
126{
127
128	if ((rule->mbr_subject.mbi_flags | MBI_BITS) != MBI_BITS)
129		return (EINVAL);
130
131	if ((rule->mbr_object.mbi_flags | MBI_BITS) != MBI_BITS)
132		return (EINVAL);
133
134	if ((rule->mbr_mode | VALLPERM) != VALLPERM)
135		return (EINVAL);
136
137	return (0);
138}
139
140static int
141sysctl_rule(SYSCTL_HANDLER_ARGS)
142{
143	struct mac_bsdextended_rule temprule, *ruleptr;
144	u_int namelen;
145	int error, index, *name;
146
147	name = (int *)arg1;
148	namelen = arg2;
149
150	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
151
152	if (namelen != 1)
153		return (EINVAL);
154
155	index = name[0];
156	if (index < 0 || index > rule_slots + 1)
157		return (ENOENT);
158	if (rule_slots >= MAC_BSDEXTENDED_MAXRULES)
159		return (ENOENT);
160
161	if (req->oldptr) {
162		if (rules[index] == NULL)
163			return (ENOENT);
164
165		error = SYSCTL_OUT(req, rules[index], sizeof(*rules[index]));
166		if (error)
167			return (error);
168	}
169
170	if (req->newptr) {
171		if (req->newlen == 0) {
172			/* printf("deletion\n"); */
173			ruleptr = rules[index];
174			if (ruleptr == NULL)
175				return (ENOENT);
176			rule_count--;
177			rules[index] = NULL;
178			FREE(ruleptr, M_MACBSDEXTENDED);
179			return(0);
180		}
181		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
182		if (error)
183			return (error);
184
185		error = mac_bsdextended_rule_valid(&temprule);
186		if (error)
187			return (error);
188
189		if (rules[index] == NULL) {
190			/* printf("addition\n"); */
191			MALLOC(ruleptr, struct mac_bsdextended_rule *,
192			    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK |
193			    M_ZERO);
194			*ruleptr = temprule;
195			rules[index] = ruleptr;
196			if (index+1 > rule_slots)
197				rule_slots = index+1;
198			rule_count++;
199		} else {
200			/* printf("replacement\n"); */
201			*rules[index] = temprule;
202		}
203	}
204
205	return (0);
206}
207
208SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
209    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
210
211static void
212mac_bsdextended_init(struct mac_policy_conf *mpc)
213{
214
215	/* Initialize ruleset lock. */
216	/* Register dynamic sysctl's for rules. */
217}
218
219static void
220mac_bsdextended_destroy(struct mac_policy_conf *mpc)
221{
222
223	/* Tear down sysctls. */
224	/* Destroy ruleset lock. */
225}
226
227static int
228mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
229    struct ucred *cred, uid_t object_uid, gid_t object_gid, int acc_mode)
230{
231	int match;
232
233	/*
234	 * Is there a subject match?
235	 */
236	if (rule->mbr_subject.mbi_flags & MBI_UID_DEFINED) {
237		match =  (rule->mbr_subject.mbi_uid == cred->cr_uid ||
238		    rule->mbr_subject.mbi_uid == cred->cr_ruid ||
239		    rule->mbr_subject.mbi_uid == cred->cr_svuid);
240
241		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
242			match = !match;
243
244		if (!match)
245			return (0);
246	}
247
248	if (rule->mbr_subject.mbi_flags & MBI_GID_DEFINED) {
249		match = (groupmember(rule->mbr_subject.mbi_gid, cred) ||
250		    rule->mbr_subject.mbi_gid == cred->cr_rgid ||
251		    rule->mbr_subject.mbi_gid == cred->cr_svgid);
252
253		if (rule->mbr_subject.mbi_flags & MBI_NEGATED)
254			match = !match;
255
256		if (!match)
257			return (0);
258	}
259
260	/*
261	 * Is there an object match?
262	 */
263	if (rule->mbr_object.mbi_flags & MBI_UID_DEFINED) {
264		match = (rule->mbr_object.mbi_uid == object_uid);
265
266		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
267			match = !match;
268
269		if (!match)
270			return (0);
271	}
272
273	if (rule->mbr_object.mbi_flags & MBI_GID_DEFINED) {
274		match = (rule->mbr_object.mbi_gid == object_gid);
275
276		if (rule->mbr_object.mbi_flags & MBI_NEGATED)
277			match = !match;
278
279		if (!match)
280			return (0);
281	}
282
283	/*
284	 * Is the access permitted?
285	 */
286	if ((rule->mbr_mode & acc_mode) != acc_mode) {
287		if (mac_bsdextended_logging)
288			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
289			    " on %d:%d failed. \n", cred->cr_ruid,
290			    cred->cr_rgid, acc_mode, object_uid, object_gid);
291		return (EACCES); /* Matching rule denies access */
292	}
293	/*
294	 * If the rule matched and allowed access and first match is
295	 * enabled, then return success.
296	 */
297	if (mac_bsdextended_firstmatch_enabled)
298		return (EJUSTRETURN);
299	else
300		return(0);
301}
302
303static int
304mac_bsdextended_check(struct ucred *cred, uid_t object_uid, gid_t object_gid,
305    int acc_mode)
306{
307	int error, i;
308
309	if (suser_cred(cred, 0) == 0)
310		return (0);
311
312	for (i = 0; i < rule_slots; i++) {
313		if (rules[i] == NULL)
314			continue;
315
316		/*
317		 * Since we don't separately handle append, map append to
318		 * write.
319		 */
320		if (acc_mode & VAPPEND) {
321			acc_mode &= ~VAPPEND;
322			acc_mode |= VWRITE;
323		}
324
325		error = mac_bsdextended_rulecheck(rules[i], cred, object_uid,
326		    object_gid, acc_mode);
327		if (error == EJUSTRETURN)
328			break;
329		if (error)
330			return (error);
331	}
332
333	return (0);
334}
335
336static int
337mac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
338    struct label *label)
339{
340	struct vattr vap;
341	int error;
342
343	if (!mac_bsdextended_enabled)
344		return (0);
345
346	error = VOP_GETATTR(vp, &vap, cred, curthread);
347	if (error)
348		return (error);
349	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
350}
351
352static int
353mac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
354    struct label *label, int acc_mode)
355{
356	struct vattr vap;
357	int error;
358
359	if (!mac_bsdextended_enabled)
360		return (0);
361
362	error = VOP_GETATTR(vp, &vap, cred, curthread);
363	if (error)
364		return (error);
365	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
366}
367
368static int
369mac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
370    struct label *dlabel)
371{
372	struct vattr vap;
373	int error;
374
375	if (!mac_bsdextended_enabled)
376		return (0);
377
378	error = VOP_GETATTR(dvp, &vap, cred, curthread);
379	if (error)
380		return (error);
381	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
382}
383
384static int
385mac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
386    struct label *dlabel)
387{
388	struct vattr vap;
389	int error;
390
391	if (!mac_bsdextended_enabled)
392		return (0);
393
394	error = VOP_GETATTR(dvp, &vap, cred, curthread);
395	if (error)
396		return (error);
397	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
398}
399
400static int
401mac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
402    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
403{
404	struct vattr dvap;
405	int error;
406
407	if (!mac_bsdextended_enabled)
408		return (0);
409
410	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
411	if (error)
412		return (error);
413	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid, VWRITE));
414}
415
416static int
417mac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
418    struct label *dlabel, struct vnode *vp, struct label *label,
419    struct componentname *cnp)
420{
421	struct vattr vap;
422	int error;
423
424	if (!mac_bsdextended_enabled)
425		return (0);
426
427	error = VOP_GETATTR(dvp, &vap, cred, curthread);
428	if (error)
429		return (error);
430	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
431	if (error)
432		return (error);
433
434	error = VOP_GETATTR(vp, &vap, cred, curthread);
435	if (error)
436		return (error);
437	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
438}
439
440static int
441mac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
442    struct label *label, acl_type_t type)
443{
444	struct vattr vap;
445	int error;
446
447	if (!mac_bsdextended_enabled)
448		return (0);
449
450	error = VOP_GETATTR(vp, &vap, cred, curthread);
451	if (error)
452		return (error);
453	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
454}
455
456static int
457mac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
458    struct label *label, int attrnamespace, const char *name)
459{
460	struct vattr vap;
461	int error;
462
463	if (!mac_bsdextended_enabled)
464		return (0);
465
466	error = VOP_GETATTR(vp, &vap, cred, curthread);
467	if (error)
468		return (error);
469	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
470}
471
472static int
473mac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
474    struct label *label, struct image_params *imgp,
475    struct label *execlabel)
476{
477	struct vattr vap;
478	int error;
479
480	if (!mac_bsdextended_enabled)
481		return (0);
482
483	error = VOP_GETATTR(vp, &vap, cred, curthread);
484	if (error)
485		return (error);
486	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
487	    VREAD|VEXEC));
488}
489
490static int
491mac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
492    struct label *label, acl_type_t type)
493{
494	struct vattr vap;
495	int error;
496
497	if (!mac_bsdextended_enabled)
498		return (0);
499
500	error = VOP_GETATTR(vp, &vap, cred, curthread);
501	if (error)
502		return (error);
503	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VSTAT));
504}
505
506static int
507mac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
508    struct label *label, int attrnamespace, const char *name, struct uio *uio)
509{
510	struct vattr vap;
511	int error;
512
513	if (!mac_bsdextended_enabled)
514		return (0);
515
516	error = VOP_GETATTR(vp, &vap, cred, curthread);
517	if (error)
518		return (error);
519	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
520}
521
522static int
523mac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
524    struct label *dlabel, struct vnode *vp, struct label *label,
525    struct componentname *cnp)
526{
527	struct vattr vap;
528	int error;
529
530	if (!mac_bsdextended_enabled)
531		return (0);
532
533	error = VOP_GETATTR(dvp, &vap, cred, curthread);
534	if (error)
535		return (error);
536	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
537	if (error)
538		return (error);
539
540	error = VOP_GETATTR(vp, &vap, cred, curthread);
541	if (error)
542		return (error);
543	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
544	if (error)
545		return (error);
546	return (0);
547}
548
549static int
550mac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
551    struct label *label, int attrnamespace)
552{
553	struct vattr vap;
554	int error;
555
556	if (!mac_bsdextended_enabled)
557		return (0);
558
559	error = VOP_GETATTR(vp, &vap, cred, curthread);
560	if (error)
561		return (error);
562	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
563}
564
565static int
566mac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
567    struct label *dlabel, struct componentname *cnp)
568{
569	struct vattr vap;
570	int error;
571
572	if (!mac_bsdextended_enabled)
573		return (0);
574
575	error = VOP_GETATTR(dvp, &vap, cred, curthread);
576	if (error)
577		return (error);
578	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VEXEC));
579}
580
581static int
582mac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
583    struct label *filelabel, int acc_mode)
584{
585	struct vattr vap;
586	int error;
587
588	if (!mac_bsdextended_enabled)
589		return (0);
590
591	error = VOP_GETATTR(vp, &vap, cred, curthread);
592	if (error)
593		return (error);
594	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
595}
596
597static int
598mac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
599    struct label *dlabel)
600{
601	struct vattr vap;
602	int error;
603
604	if (!mac_bsdextended_enabled)
605		return (0);
606
607	error = VOP_GETATTR(dvp, &vap, cred, curthread);
608	if (error)
609		return (error);
610	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
611}
612
613static int
614mac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
615    struct label *label)
616{
617	struct vattr vap;
618	int error;
619
620	if (!mac_bsdextended_enabled)
621		return (0);
622
623	error = VOP_GETATTR(vp, &vap, cred, curthread);
624	if (error)
625		return (error);
626	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VREAD));
627}
628
629static int
630mac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
631    struct label *dlabel, struct vnode *vp, struct label *label,
632    struct componentname *cnp)
633{
634	struct vattr vap;
635	int error;
636
637	if (!mac_bsdextended_enabled)
638		return (0);
639
640	error = VOP_GETATTR(dvp, &vap, cred, curthread);
641	if (error)
642		return (error);
643	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
644	if (error)
645		return (error);
646	error = VOP_GETATTR(vp, &vap, cred, curthread);
647	if (error)
648		return (error);
649	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
650
651	return (error);
652}
653
654static int
655mac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
656    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
657    struct componentname *cnp)
658{
659	struct vattr vap;
660	int error;
661
662	if (!mac_bsdextended_enabled)
663		return (0);
664
665	error = VOP_GETATTR(dvp, &vap, cred, curthread);
666	if (error)
667		return (error);
668	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE);
669	if (error)
670		return (error);
671
672	if (vp != NULL) {
673		error = VOP_GETATTR(vp, &vap, cred, curthread);
674		if (error)
675			return (error);
676		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
677		    VWRITE);
678	}
679
680	return (error);
681}
682
683static int
684mac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
685    struct label *label)
686{
687	struct vattr vap;
688	int error;
689
690	if (!mac_bsdextended_enabled)
691		return (0);
692
693	error = VOP_GETATTR(vp, &vap, cred, curthread);
694	if (error)
695		return (error);
696	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
697}
698
699static int
700mac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
701    struct label *label, acl_type_t type, struct acl *acl)
702{
703	struct vattr vap;
704	int error;
705
706	if (!mac_bsdextended_enabled)
707		return (0);
708
709	error = VOP_GETATTR(vp, &vap, cred, curthread);
710	if (error)
711		return (error);
712	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
713}
714
715static int
716mac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
717    struct label *label, int attrnamespace, const char *name, struct uio *uio)
718{
719	struct vattr vap;
720	int error;
721
722	if (!mac_bsdextended_enabled)
723		return (0);
724
725	error = VOP_GETATTR(vp, &vap, cred, curthread);
726	if (error)
727		return (error);
728	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VWRITE));
729}
730
731static int
732mac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
733    struct label *label, u_long flags)
734{
735	struct vattr vap;
736	int error;
737
738	if (!mac_bsdextended_enabled)
739		return (0);
740
741	error = VOP_GETATTR(vp, &vap, cred, curthread);
742	if (error)
743		return (error);
744	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
745}
746
747static int
748mac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
749    struct label *label, mode_t mode)
750{
751	struct vattr vap;
752	int error;
753
754	if (!mac_bsdextended_enabled)
755		return (0);
756
757	error = VOP_GETATTR(vp, &vap, cred, curthread);
758	if (error)
759		return (error);
760	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
761}
762
763static int
764mac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
765    struct label *label, uid_t uid, gid_t gid)
766{
767	struct vattr vap;
768	int error;
769
770	if (!mac_bsdextended_enabled)
771		return (0);
772
773	error = VOP_GETATTR(vp, &vap, cred, curthread);
774	if (error)
775		return (error);
776	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
777}
778
779static int
780mac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
781    struct label *label, struct timespec atime, struct timespec utime)
782{
783	struct vattr vap;
784	int error;
785
786	if (!mac_bsdextended_enabled)
787		return (0);
788
789	error = VOP_GETATTR(vp, &vap, cred, curthread);
790	if (error)
791		return (error);
792	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, VADMIN));
793}
794
795static int
796mac_bsdextended_check_vnode_stat(struct ucred *active_cred,
797    struct ucred *file_cred, struct vnode *vp, struct label *label)
798{
799	struct vattr vap;
800	int error;
801
802	if (!mac_bsdextended_enabled)
803		return (0);
804
805	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
806	if (error)
807		return (error);
808	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
809	    VSTAT));
810}
811
812static struct mac_policy_ops mac_bsdextended_ops =
813{
814	.mpo_destroy = mac_bsdextended_destroy,
815	.mpo_init = mac_bsdextended_init,
816	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
817	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
818	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
819	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
820	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
821	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
822	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
823	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
824	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
825	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
826	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
827	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
828	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
829	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
830	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
831	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
832	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
833	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
834	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
835	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
836	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
837	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
838	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
839	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
840	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
841	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
842	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
843};
844
845MAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
846    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
847