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