ugidfw_system.c revision 168933
1/*-
2 * Copyright (c) 2005 Tom Rhodes
3 * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
4 * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 * It was later enhanced by Tom Rhodes for the TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * 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 168933 2007-04-21 22:08:48Z rwatson $
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/param.h>
46#include <sys/acl.h>
47#include <sys/kernel.h>
48#include <sys/jail.h>
49#include <sys/lock.h>
50#include <sys/malloc.h>
51#include <sys/module.h>
52#include <sys/mount.h>
53#include <sys/mutex.h>
54#include <sys/systm.h>
55#include <sys/vnode.h>
56#include <sys/sysctl.h>
57#include <sys/syslog.h>
58
59#include <security/mac/mac_policy.h>
60#include <security/mac_bsdextended/mac_bsdextended.h>
61
62static struct mtx mac_bsdextended_mtx;
63
64SYSCTL_DECL(_security_mac);
65
66SYSCTL_NODE(_security_mac, OID_AUTO, bsdextended, CTLFLAG_RW, 0,
67    "TrustedBSD extended BSD MAC policy controls");
68
69static int	mac_bsdextended_enabled = 1;
70SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, enabled, CTLFLAG_RW,
71    &mac_bsdextended_enabled, 0, "Enforce extended BSD policy");
72TUNABLE_INT("security.mac.bsdextended.enabled", &mac_bsdextended_enabled);
73
74MALLOC_DEFINE(M_MACBSDEXTENDED, "mac_bsdextended", "BSD Extended MAC rule");
75
76#define	MAC_BSDEXTENDED_MAXRULES	250
77static struct mac_bsdextended_rule *rules[MAC_BSDEXTENDED_MAXRULES];
78static int rule_count = 0;
79static int rule_slots = 0;
80static int rule_version = MB_VERSION;
81
82SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_count, CTLFLAG_RD,
83    &rule_count, 0, "Number of defined rules\n");
84SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_slots, CTLFLAG_RD,
85    &rule_slots, 0, "Number of used rule slots\n");
86SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, rule_version, CTLFLAG_RD,
87    &rule_version, 0, "Version number for API\n");
88
89/*
90 * This is just used for logging purposes, eventually we would like
91 * to log much more then failed requests.
92 */
93static int mac_bsdextended_logging;
94SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, logging, CTLFLAG_RW,
95    &mac_bsdextended_logging, 0, "Log failed authorization requests");
96
97/*
98 * This tunable is here for compatibility.  It will allow the user
99 * to switch between the new mode (first rule matches) and the old
100 * functionality (all rules match).
101 */
102static int
103mac_bsdextended_firstmatch_enabled;
104SYSCTL_INT(_security_mac_bsdextended, OID_AUTO, firstmatch_enabled,
105	CTLFLAG_RW, &mac_bsdextended_firstmatch_enabled, 1,
106	"Disable/enable match first rule functionality");
107
108static int
109mac_bsdextended_rule_valid(struct mac_bsdextended_rule *rule)
110{
111
112	if ((rule->mbr_subject.mbs_flags | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
113		return (EINVAL);
114
115	if ((rule->mbr_subject.mbs_neg | MBS_ALL_FLAGS) != MBS_ALL_FLAGS)
116		return (EINVAL);
117
118	if ((rule->mbr_object.mbo_flags | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
119		return (EINVAL);
120
121	if ((rule->mbr_object.mbo_neg | MBO_ALL_FLAGS) != MBO_ALL_FLAGS)
122		return (EINVAL);
123
124	if ((rule->mbr_object.mbo_neg | MBO_TYPE_DEFINED) &&
125	    (rule->mbr_object.mbo_type | MBO_ALL_TYPE) != MBO_ALL_TYPE)
126		return (EINVAL);
127
128	if ((rule->mbr_mode | MBI_ALLPERM) != MBI_ALLPERM)
129		return (EINVAL);
130
131	return (0);
132}
133
134static int
135sysctl_rule(SYSCTL_HANDLER_ARGS)
136{
137	struct mac_bsdextended_rule temprule, *ruleptr;
138	u_int namelen;
139	int error, index, *name;
140
141	error = 0;
142	name = (int *)arg1;
143	namelen = arg2;
144
145	/* printf("bsdextended sysctl handler (namelen %d)\n", namelen); */
146
147	if (namelen != 1)
148		return (EINVAL);
149
150	index = name[0];
151        if (index >= MAC_BSDEXTENDED_MAXRULES)
152		return (ENOENT);
153
154	ruleptr = NULL;
155	if (req->newptr && req->newlen != 0) {
156		error = SYSCTL_IN(req, &temprule, sizeof(temprule));
157		if (error)
158			return (error);
159		MALLOC(ruleptr, struct mac_bsdextended_rule *,
160		    sizeof(*ruleptr), M_MACBSDEXTENDED, M_WAITOK | M_ZERO);
161	}
162
163	mtx_lock(&mac_bsdextended_mtx);
164
165	if (req->oldptr) {
166		if (index < 0 || index > rule_slots + 1) {
167			error = ENOENT;
168			goto out;
169		}
170		if (rules[index] == NULL) {
171			error = ENOENT;
172			goto out;
173		}
174		temprule = *rules[index];
175	}
176
177	if (req->newptr && req->newlen == 0) {
178		/* printf("deletion\n"); */
179		KASSERT(ruleptr == NULL, ("sysctl_rule: ruleptr != NULL"));
180		ruleptr = rules[index];
181		if (ruleptr == NULL) {
182			error = ENOENT;
183			goto out;
184		}
185		rule_count--;
186		rules[index] = NULL;
187	} else if (req->newptr) {
188		error = mac_bsdextended_rule_valid(&temprule);
189		if (error)
190			goto out;
191
192		if (rules[index] == NULL) {
193			/* printf("addition\n"); */
194			*ruleptr = temprule;
195			rules[index] = ruleptr;
196			ruleptr = NULL;
197			if (index + 1 > rule_slots)
198				rule_slots = index + 1;
199			rule_count++;
200		} else {
201			/* printf("replacement\n"); */
202			*rules[index] = temprule;
203		}
204	}
205
206out:
207	mtx_unlock(&mac_bsdextended_mtx);
208	if (ruleptr != NULL)
209		FREE(ruleptr, M_MACBSDEXTENDED);
210	if (req->oldptr && error == 0)
211		error = SYSCTL_OUT(req, &temprule, sizeof(temprule));
212
213	return (error);
214}
215
216SYSCTL_NODE(_security_mac_bsdextended, OID_AUTO, rules,
217    CTLFLAG_RW, sysctl_rule, "BSD extended MAC rules");
218
219static void
220mac_bsdextended_init(struct mac_policy_conf *mpc)
221{
222
223	/* Initialize ruleset lock. */
224	mtx_init(&mac_bsdextended_mtx, "mac_bsdextended lock", NULL, MTX_DEF);
225
226	/* Register dynamic sysctl's for rules. */
227}
228
229static void
230mac_bsdextended_destroy(struct mac_policy_conf *mpc)
231{
232
233	/* Destroy ruleset lock. */
234	mtx_destroy(&mac_bsdextended_mtx);
235
236	/* Tear down sysctls. */
237}
238
239static int
240mac_bsdextended_rulecheck(struct mac_bsdextended_rule *rule,
241    struct ucred *cred, struct vnode *vp, struct vattr *vap, int acc_mode)
242{
243	int match;
244	int i;
245
246	/*
247	 * Is there a subject match?
248	 */
249	mtx_assert(&mac_bsdextended_mtx, MA_OWNED);
250	if (rule->mbr_subject.mbs_flags & MBS_UID_DEFINED) {
251		match =  ((cred->cr_uid <= rule->mbr_subject.mbs_uid_max &&
252		    cred->cr_uid >= rule->mbr_subject.mbs_uid_min) ||
253		    (cred->cr_ruid <= rule->mbr_subject.mbs_uid_max &&
254		    cred->cr_ruid >= rule->mbr_subject.mbs_uid_min) ||
255		    (cred->cr_svuid <= rule->mbr_subject.mbs_uid_max &&
256		    cred->cr_svuid >= rule->mbr_subject.mbs_uid_min));
257
258		if (rule->mbr_subject.mbs_neg & MBS_UID_DEFINED)
259			match = !match;
260
261		if (!match)
262			return (0);
263	}
264
265	if (rule->mbr_subject.mbs_flags & MBS_GID_DEFINED) {
266		match = ((cred->cr_rgid <= rule->mbr_subject.mbs_gid_max &&
267		    cred->cr_rgid >= rule->mbr_subject.mbs_gid_min) ||
268		    (cred->cr_svgid <= rule->mbr_subject.mbs_gid_max &&
269		    cred->cr_svgid >= rule->mbr_subject.mbs_gid_min));
270
271		if (!match) {
272			for (i = 0; i < cred->cr_ngroups; i++)
273				if (cred->cr_groups[i]
274				    <= rule->mbr_subject.mbs_gid_max &&
275				    cred->cr_groups[i]
276				    >= rule->mbr_subject.mbs_gid_min) {
277					match = 1;
278					break;
279				}
280		}
281
282		if (rule->mbr_subject.mbs_neg & MBS_GID_DEFINED)
283			match = !match;
284
285		if (!match)
286			return (0);
287	}
288
289	if (rule->mbr_subject.mbs_flags & MBS_PRISON_DEFINED) {
290		match = (cred->cr_prison != NULL &&
291		    cred->cr_prison->pr_id == rule->mbr_subject.mbs_prison);
292
293		if (rule->mbr_subject.mbs_neg & MBS_PRISON_DEFINED)
294			match = !match;
295
296		if (!match)
297			return (0);
298	}
299
300	/*
301	 * Is there an object match?
302	 */
303	if (rule->mbr_object.mbo_flags & MBO_UID_DEFINED) {
304		match = (vap->va_uid <= rule->mbr_object.mbo_uid_max &&
305		    vap->va_uid >= rule->mbr_object.mbo_uid_min);
306
307		if (rule->mbr_object.mbo_neg & MBO_UID_DEFINED)
308			match = !match;
309
310		if (!match)
311			return (0);
312	}
313
314	if (rule->mbr_object.mbo_flags & MBO_GID_DEFINED) {
315		match = (vap->va_gid <= rule->mbr_object.mbo_gid_max &&
316		    vap->va_gid >= rule->mbr_object.mbo_gid_min);
317
318		if (rule->mbr_object.mbo_neg & MBO_GID_DEFINED)
319			match = !match;
320
321		if (!match)
322			return (0);
323	}
324
325	if (rule->mbr_object.mbo_flags & MBO_FSID_DEFINED) {
326		match = (bcmp(&(vp->v_mount->mnt_stat.f_fsid),
327		    &(rule->mbr_object.mbo_fsid),
328		    sizeof(rule->mbr_object.mbo_fsid)) == 0);
329
330		if (rule->mbr_object.mbo_neg & MBO_FSID_DEFINED)
331			match = !match;
332
333		if (!match)
334			return 0;
335	}
336
337	if (rule->mbr_object.mbo_flags & MBO_SUID) {
338		match = (vap->va_mode & VSUID);
339
340		if (rule->mbr_object.mbo_neg & MBO_SUID)
341			match = !match;
342
343		if (!match)
344			return 0;
345	}
346
347	if (rule->mbr_object.mbo_flags & MBO_SGID) {
348		match = (vap->va_mode & VSGID);
349
350		if (rule->mbr_object.mbo_neg & MBO_SGID)
351			match = !match;
352
353		if (!match)
354			return 0;
355	}
356
357	if (rule->mbr_object.mbo_flags & MBO_UID_SUBJECT) {
358		match = (vap->va_uid == cred->cr_uid ||
359		    vap->va_uid == cred->cr_ruid ||
360		    vap->va_uid == cred->cr_svuid);
361
362		if (rule->mbr_object.mbo_neg & MBO_UID_SUBJECT)
363			match = !match;
364
365		if (!match)
366			return 0;
367	}
368
369	if (rule->mbr_object.mbo_flags & MBO_GID_SUBJECT) {
370		match = (groupmember(vap->va_gid, cred) ||
371		    vap->va_gid == cred->cr_rgid ||
372		    vap->va_gid == cred->cr_svgid);
373
374		if (rule->mbr_object.mbo_neg & MBO_GID_SUBJECT)
375			match = !match;
376
377		if (!match)
378			return 0;
379	}
380
381	if (rule->mbr_object.mbo_flags & MBO_TYPE_DEFINED) {
382		switch (vap->va_type) {
383		case VREG:
384			match = (rule->mbr_object.mbo_type & MBO_TYPE_REG);
385			break;
386		case VDIR:
387			match = (rule->mbr_object.mbo_type & MBO_TYPE_DIR);
388			break;
389		case VBLK:
390			match = (rule->mbr_object.mbo_type & MBO_TYPE_BLK);
391			break;
392		case VCHR:
393			match = (rule->mbr_object.mbo_type & MBO_TYPE_CHR);
394			break;
395		case VLNK:
396			match = (rule->mbr_object.mbo_type & MBO_TYPE_LNK);
397			break;
398		case VSOCK:
399			match = (rule->mbr_object.mbo_type & MBO_TYPE_SOCK);
400			break;
401		case VFIFO:
402			match = (rule->mbr_object.mbo_type & MBO_TYPE_FIFO);
403			break;
404		default:
405			match = 0;
406		}
407
408		if (rule->mbr_object.mbo_neg & MBO_TYPE_DEFINED)
409			match = !match;
410
411		if (!match)
412			return 0;
413	}
414
415	/*
416	 * Is the access permitted?
417	 */
418	if ((rule->mbr_mode & acc_mode) != acc_mode) {
419		if (mac_bsdextended_logging)
420			log(LOG_AUTHPRIV, "mac_bsdextended: %d:%d request %d"
421			    " on %d:%d failed. \n", cred->cr_ruid,
422			    cred->cr_rgid, acc_mode, vap->va_uid, vap->va_gid);
423		return (EACCES); /* Matching rule denies access */
424	}
425
426	/*
427	 * If the rule matched, permits access, and first match is enabled,
428	 * return success.
429	 */
430	if (mac_bsdextended_firstmatch_enabled)
431		return (EJUSTRETURN);
432	else
433		return(0);
434}
435
436static int
437mac_bsdextended_check(struct ucred *cred, struct vnode *vp, struct vattr *vap,
438    int acc_mode)
439{
440	int error, i;
441
442	/*
443	 * XXXRW: More specific privilege selection needed?
444	 */
445	if (suser_cred(cred, 0) == 0)
446		return (0);
447
448	/*
449	 * Since we do not separately handle append, map append to write.
450	 */
451	if (acc_mode & MBI_APPEND) {
452		acc_mode &= ~MBI_APPEND;
453		acc_mode |= MBI_WRITE;
454	}
455
456	mtx_lock(&mac_bsdextended_mtx);
457	for (i = 0; i < rule_slots; i++) {
458		if (rules[i] == NULL)
459			continue;
460
461		error = mac_bsdextended_rulecheck(rules[i], cred,
462		    vp, vap, acc_mode);
463		if (error == EJUSTRETURN)
464			break;
465		if (error) {
466			mtx_unlock(&mac_bsdextended_mtx);
467			return (error);
468		}
469	}
470	mtx_unlock(&mac_bsdextended_mtx);
471	return (0);
472}
473
474static int
475mac_bsdextended_check_vp(struct ucred *cred, struct vnode *vp, int acc_mode)
476{
477	int error;
478	struct vattr vap;
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
487	return (mac_bsdextended_check(cred, vp, &vap, acc_mode));
488}
489
490static int
491mac_bsdextended_check_system_acct(struct ucred *cred, struct vnode *vp,
492    struct label *label)
493{
494
495	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
496}
497
498static int
499mac_bsdextended_check_system_auditctl(struct ucred *cred, struct vnode *vp,
500    struct label *label)
501{
502
503	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
504}
505
506static int
507mac_bsdextended_check_system_swapoff(struct ucred *cred, struct vnode *vp,
508    struct label *label)
509{
510
511	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
512}
513
514static int
515mac_bsdextended_check_system_swapon(struct ucred *cred, struct vnode *vp,
516    struct label *label)
517{
518
519	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
520}
521
522static int
523mac_bsdextended_check_vnode_access(struct ucred *cred, struct vnode *vp,
524    struct label *label, int acc_mode)
525{
526
527	return (mac_bsdextended_check_vp(cred, vp, acc_mode));
528}
529
530static int
531mac_bsdextended_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
532    struct label *dlabel)
533{
534
535	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
536}
537
538static int
539mac_bsdextended_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
540    struct label *dlabel)
541{
542
543	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
544}
545
546static int
547mac_bsdextended_check_create_vnode(struct ucred *cred, struct vnode *dvp,
548    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
549{
550
551	return (mac_bsdextended_check_vp(cred, dvp, MBI_WRITE));
552}
553
554static int
555mac_bsdextended_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
556    struct label *dlabel, struct vnode *vp, struct label *label,
557    struct componentname *cnp)
558{
559	int error;
560
561	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
562	if (error)
563		return (error);
564
565	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
566}
567
568static int
569mac_bsdextended_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
570    struct label *label, acl_type_t type)
571{
572
573	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
574}
575
576static int
577mac_bsdextended_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
578    struct label *label, int attrnamespace, const char *name)
579{
580
581	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
582}
583
584static int
585mac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
586    struct label *label, struct image_params *imgp,
587    struct label *execlabel)
588{
589
590	return (mac_bsdextended_check_vp(cred, vp, MBI_READ|MBI_EXEC));
591}
592
593static int
594mac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
595    struct label *label, acl_type_t type)
596{
597
598	return (mac_bsdextended_check_vp(cred, vp, MBI_STAT));
599}
600
601static int
602mac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
603    struct label *label, int attrnamespace, const char *name, struct uio *uio)
604{
605
606	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
607}
608
609static int
610mac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
611    struct label *dlabel, struct vnode *vp, struct label *label,
612    struct componentname *cnp)
613{
614	int error;
615
616	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
617	if (error)
618		return (error);
619
620	error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
621	if (error)
622		return (error);
623	return (0);
624}
625
626static int
627mac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
628    struct label *label, int attrnamespace)
629{
630
631	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
632}
633
634static int
635mac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
636    struct label *dlabel, struct componentname *cnp)
637{
638
639	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
640}
641
642static int
643mac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
644    struct label *filelabel, int acc_mode)
645{
646
647	return (mac_bsdextended_check_vp(cred, vp, acc_mode));
648}
649
650static int
651mac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
652    struct label *dlabel)
653{
654
655	return (mac_bsdextended_check_vp(cred, dvp, MBI_READ));
656}
657
658static int
659mac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
660    struct label *label)
661{
662
663	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
664}
665
666static int
667mac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
668    struct label *dlabel, struct vnode *vp, struct label *label,
669    struct componentname *cnp)
670{
671	int error;
672
673	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
674	if (error)
675		return (error);
676	error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
677
678	return (error);
679}
680
681static int
682mac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
683    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
684    struct componentname *cnp)
685{
686	int error;
687
688	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
689	if (error)
690		return (error);
691
692	if (vp != NULL)
693		error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
694
695	return (error);
696}
697
698static int
699mac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
700    struct label *label)
701{
702
703	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
704}
705
706static int
707mac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
708    struct label *label, acl_type_t type, struct acl *acl)
709{
710
711	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
712}
713
714static int
715mac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
716    struct label *label, int attrnamespace, const char *name, struct uio *uio)
717{
718
719	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
720}
721
722static int
723mac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
724    struct label *label, u_long flags)
725{
726
727	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
728}
729
730static int
731mac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
732    struct label *label, mode_t mode)
733{
734
735	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
736}
737
738static int
739mac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
740    struct label *label, uid_t uid, gid_t gid)
741{
742
743	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
744}
745
746static int
747mac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
748    struct label *label, struct timespec atime, struct timespec utime)
749{
750
751	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
752}
753
754static int
755mac_bsdextended_check_vnode_stat(struct ucred *active_cred,
756    struct ucred *file_cred, struct vnode *vp, struct label *label)
757{
758
759	return (mac_bsdextended_check_vp(active_cred, vp, MBI_STAT));
760}
761
762static struct mac_policy_ops mac_bsdextended_ops =
763{
764	.mpo_destroy = mac_bsdextended_destroy,
765	.mpo_init = mac_bsdextended_init,
766	.mpo_check_system_acct = mac_bsdextended_check_system_acct,
767	.mpo_check_system_auditctl = mac_bsdextended_check_system_auditctl,
768	.mpo_check_system_swapoff = mac_bsdextended_check_system_swapoff,
769	.mpo_check_system_swapon = mac_bsdextended_check_system_swapon,
770	.mpo_check_vnode_access = mac_bsdextended_check_vnode_access,
771	.mpo_check_vnode_chdir = mac_bsdextended_check_vnode_chdir,
772	.mpo_check_vnode_chroot = mac_bsdextended_check_vnode_chroot,
773	.mpo_check_vnode_create = mac_bsdextended_check_create_vnode,
774	.mpo_check_vnode_delete = mac_bsdextended_check_vnode_delete,
775	.mpo_check_vnode_deleteacl = mac_bsdextended_check_vnode_deleteacl,
776	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
777	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
778	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
779	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
780	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
781	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
782	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
783	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
784	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
785	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
786	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
787	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
788	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
789	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
790	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
791	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
792	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
793	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
794	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
795	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
796};
797
798MAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
799    "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
800