ugidfw_system.c revision 136742
1/*-
2 * Copyright (c) 1999-2002 Robert N. M. Watson
3 * Copyright (c) 2001-2004 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 136742 2004-10-21 11:29:56Z rwatson $
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 is just used for logging purposes as eventually we would like
98 * to log much more then failed requests.
99 */
100static int mac_bsdextended_logging;
101SYSCTL_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 */
109static int
110mac_bsdextended_firstmatch_enabled;
111SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
112	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
113	"Disable/enable match first rule functionality");
114
115static int
116mac_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 | MBI_ALLPERM) != MBI_ALLPERM)
126		return (EINVAL);
127
128	return (0);
129}
130
131static int
132sysctl_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
199SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
200    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
201
202static void
203mac_bsdextended_init(struct mac_policy_conf *mpc)
204{
205
206	/* Initialize ruleset lock. */
207	/* Register dynamic sysctl's for rules. */
208}
209
210static void
211mac_bsdextended_destroy(struct mac_policy_conf *mpc)
212{
213
214	/* Tear down sysctls. */
215	/* Destroy ruleset lock. */
216}
217
218static int
219mac_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
294static int
295mac_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 & MBI_APPEND) {
312			acc_mode &= ~MBI_APPEND;
313			acc_mode |= MBI_WRITE;
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
327static int
328mac_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,
341	    MBI_WRITE));
342}
343
344static int
345mac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
346    struct label *label, int acc_mode)
347{
348	struct vattr vap;
349	int error;
350
351	if (!mac_bsdextended_enabled)
352		return (0);
353
354	error = VOP_GETATTR(vp, &vap, cred, curthread);
355	if (error)
356		return (error);
357	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
358}
359
360static int
361mac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
362    struct label *dlabel)
363{
364	struct vattr vap;
365	int error;
366
367	if (!mac_bsdextended_enabled)
368		return (0);
369
370	error = VOP_GETATTR(dvp, &vap, cred, curthread);
371	if (error)
372		return (error);
373	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
374	    MBI_EXEC));
375}
376
377static int
378mac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
379    struct label *dlabel)
380{
381	struct vattr vap;
382	int error;
383
384	if (!mac_bsdextended_enabled)
385		return (0);
386
387	error = VOP_GETATTR(dvp, &vap, cred, curthread);
388	if (error)
389		return (error);
390	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
391	    MBI_EXEC));
392}
393
394static int
395mac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
396    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
397{
398	struct vattr dvap;
399	int error;
400
401	if (!mac_bsdextended_enabled)
402		return (0);
403
404	error = VOP_GETATTR(dvp, &dvap, cred, curthread);
405	if (error)
406		return (error);
407	return (mac_bsdextended_check(cred, dvap.va_uid, dvap.va_gid,
408	    MBI_WRITE));
409}
410
411static int
412mac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
413    struct label *dlabel, struct vnode *vp, struct label *label,
414    struct componentname *cnp)
415{
416	struct vattr vap;
417	int error;
418
419	if (!mac_bsdextended_enabled)
420		return (0);
421
422	error = VOP_GETATTR(dvp, &vap, cred, curthread);
423	if (error)
424		return (error);
425	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
426	    MBI_WRITE);
427	if (error)
428		return (error);
429
430	error = VOP_GETATTR(vp, &vap, cred, curthread);
431	if (error)
432		return (error);
433	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
434	    MBI_WRITE));
435}
436
437static int
438mac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
439    struct label *label, acl_type_t type)
440{
441	struct vattr vap;
442	int error;
443
444	if (!mac_bsdextended_enabled)
445		return (0);
446
447	error = VOP_GETATTR(vp, &vap, cred, curthread);
448	if (error)
449		return (error);
450	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
451	    MBI_ADMIN));
452}
453
454static int
455mac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
456    struct label *label, int attrnamespace, const char *name)
457{
458	struct vattr vap;
459	int error;
460
461	if (!mac_bsdextended_enabled)
462		return (0);
463
464	error = VOP_GETATTR(vp, &vap, cred, curthread);
465	if (error)
466		return (error);
467	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
468	    MBI_WRITE));
469}
470
471static int
472mac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
473    struct label *label, struct image_params *imgp,
474    struct label *execlabel)
475{
476	struct vattr vap;
477	int error;
478
479	if (!mac_bsdextended_enabled)
480		return (0);
481
482	error = VOP_GETATTR(vp, &vap, cred, curthread);
483	if (error)
484		return (error);
485	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
486	    MBI_READ|MBI_EXEC));
487}
488
489static int
490mac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
491    struct label *label, acl_type_t type)
492{
493	struct vattr vap;
494	int error;
495
496	if (!mac_bsdextended_enabled)
497		return (0);
498
499	error = VOP_GETATTR(vp, &vap, cred, curthread);
500	if (error)
501		return (error);
502	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
503	    MBI_STAT));
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,
520	    MBI_READ));
521}
522
523static int
524mac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
525    struct label *dlabel, struct vnode *vp, struct label *label,
526    struct componentname *cnp)
527{
528	struct vattr vap;
529	int error;
530
531	if (!mac_bsdextended_enabled)
532		return (0);
533
534	error = VOP_GETATTR(dvp, &vap, cred, curthread);
535	if (error)
536		return (error);
537	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
538	    MBI_WRITE);
539	if (error)
540		return (error);
541
542	error = VOP_GETATTR(vp, &vap, cred, curthread);
543	if (error)
544		return (error);
545	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
546	    MBI_WRITE);
547	if (error)
548		return (error);
549	return (0);
550}
551
552static int
553mac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
554    struct label *label, int attrnamespace)
555{
556	struct vattr vap;
557	int error;
558
559	if (!mac_bsdextended_enabled)
560		return (0);
561
562	error = VOP_GETATTR(vp, &vap, cred, curthread);
563	if (error)
564		return (error);
565	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
566	    MBI_READ));
567}
568
569static int
570mac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
571    struct label *dlabel, struct componentname *cnp)
572{
573	struct vattr vap;
574	int error;
575
576	if (!mac_bsdextended_enabled)
577		return (0);
578
579	error = VOP_GETATTR(dvp, &vap, cred, curthread);
580	if (error)
581		return (error);
582	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
583	    MBI_EXEC));
584}
585
586static int
587mac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
588    struct label *filelabel, int acc_mode)
589{
590	struct vattr vap;
591	int error;
592
593	if (!mac_bsdextended_enabled)
594		return (0);
595
596	error = VOP_GETATTR(vp, &vap, cred, curthread);
597	if (error)
598		return (error);
599	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid, acc_mode));
600}
601
602static int
603mac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
604    struct label *dlabel)
605{
606	struct vattr vap;
607	int error;
608
609	if (!mac_bsdextended_enabled)
610		return (0);
611
612	error = VOP_GETATTR(dvp, &vap, cred, curthread);
613	if (error)
614		return (error);
615	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
616	    MBI_READ));
617}
618
619static int
620mac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
621    struct label *label)
622{
623	struct vattr vap;
624	int error;
625
626	if (!mac_bsdextended_enabled)
627		return (0);
628
629	error = VOP_GETATTR(vp, &vap, cred, curthread);
630	if (error)
631		return (error);
632	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
633	    MBI_READ));
634}
635
636static int
637mac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
638    struct label *dlabel, struct vnode *vp, struct label *label,
639    struct componentname *cnp)
640{
641	struct vattr vap;
642	int error;
643
644	if (!mac_bsdextended_enabled)
645		return (0);
646
647	error = VOP_GETATTR(dvp, &vap, cred, curthread);
648	if (error)
649		return (error);
650	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
651	    MBI_WRITE);
652	if (error)
653		return (error);
654	error = VOP_GETATTR(vp, &vap, cred, curthread);
655	if (error)
656		return (error);
657	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
658	    MBI_WRITE);
659
660	return (error);
661}
662
663static int
664mac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
665    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
666    struct componentname *cnp)
667{
668	struct vattr vap;
669	int error;
670
671	if (!mac_bsdextended_enabled)
672		return (0);
673
674	error = VOP_GETATTR(dvp, &vap, cred, curthread);
675	if (error)
676		return (error);
677	error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
678	    MBI_WRITE);
679	if (error)
680		return (error);
681
682	if (vp != NULL) {
683		error = VOP_GETATTR(vp, &vap, cred, curthread);
684		if (error)
685			return (error);
686		error = mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
687		    MBI_WRITE);
688	}
689
690	return (error);
691}
692
693static int
694mac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
695    struct label *label)
696{
697	struct vattr vap;
698	int error;
699
700	if (!mac_bsdextended_enabled)
701		return (0);
702
703	error = VOP_GETATTR(vp, &vap, cred, curthread);
704	if (error)
705		return (error);
706	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
707	    MBI_ADMIN));
708}
709
710static int
711mac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
712    struct label *label, acl_type_t type, struct acl *acl)
713{
714	struct vattr vap;
715	int error;
716
717	if (!mac_bsdextended_enabled)
718		return (0);
719
720	error = VOP_GETATTR(vp, &vap, cred, curthread);
721	if (error)
722		return (error);
723	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
724	    MBI_ADMIN));
725}
726
727static int
728mac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
729    struct label *label, int attrnamespace, const char *name, struct uio *uio)
730{
731	struct vattr vap;
732	int error;
733
734	if (!mac_bsdextended_enabled)
735		return (0);
736
737	error = VOP_GETATTR(vp, &vap, cred, curthread);
738	if (error)
739		return (error);
740	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
741	    MBI_WRITE));
742}
743
744static int
745mac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
746    struct label *label, u_long flags)
747{
748	struct vattr vap;
749	int error;
750
751	if (!mac_bsdextended_enabled)
752		return (0);
753
754	error = VOP_GETATTR(vp, &vap, cred, curthread);
755	if (error)
756		return (error);
757	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
758	    MBI_ADMIN));
759}
760
761static int
762mac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
763    struct label *label, mode_t mode)
764{
765	struct vattr vap;
766	int error;
767
768	if (!mac_bsdextended_enabled)
769		return (0);
770
771	error = VOP_GETATTR(vp, &vap, cred, curthread);
772	if (error)
773		return (error);
774	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
775	    MBI_ADMIN));
776}
777
778static int
779mac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
780    struct label *label, uid_t uid, gid_t gid)
781{
782	struct vattr vap;
783	int error;
784
785	if (!mac_bsdextended_enabled)
786		return (0);
787
788	error = VOP_GETATTR(vp, &vap, cred, curthread);
789	if (error)
790		return (error);
791	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
792	   MBI_ADMIN));
793}
794
795static int
796mac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
797    struct label *label, struct timespec atime, struct timespec utime)
798{
799	struct vattr vap;
800	int error;
801
802	if (!mac_bsdextended_enabled)
803		return (0);
804
805	error = VOP_GETATTR(vp, &vap, cred, curthread);
806	if (error)
807		return (error);
808	return (mac_bsdextended_check(cred, vap.va_uid, vap.va_gid,
809	    MBI_ADMIN));
810}
811
812static int
813mac_bsdextended_check_vnode_stat(struct ucred *active_cred,
814    struct ucred *file_cred, struct vnode *vp, struct label *label)
815{
816	struct vattr vap;
817	int error;
818
819	if (!mac_bsdextended_enabled)
820		return (0);
821
822	error = VOP_GETATTR(vp, &vap, active_cred, curthread);
823	if (error)
824		return (error);
825	return (mac_bsdextended_check(active_cred, vap.va_uid, vap.va_gid,
826	    MBI_STAT));
827}
828
829static struct mac_policy_ops mac_bsdextended_ops =
830{
831	.mpo_destroy = mac_bsdextended_destroy,
832	.mpo_init = mac_bsdextended_init,
833	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
834	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
835	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
836	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
837	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
838	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
839	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
840	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
841	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
842	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
843	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
844	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
845	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
846	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
847	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
848	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
849	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
850	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
851	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
852	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
853	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
854	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
855	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
856	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
857	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
858	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
859	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
860};
861
862MAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
863    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
864