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