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