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