xref: /freebsd/sys/security/mac_bsdextended/mac_bsdextended.c (revision fa030de01267cc324a0b57479715e4a53356b665)
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_deleteacl(struct ucred *cred, struct vnode *vp,
508     struct label *vplabel, acl_type_t type)
509 {
510 
511 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
512 }
513 
514 static int
515 mac_bsdextended_check_vnode_deleteextattr(struct ucred *cred,
516     struct vnode *vp, struct label *vplabel, int attrnamespace,
517     const char *name)
518 {
519 
520 	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
521 }
522 
523 static int
524 mac_bsdextended_check_vnode_exec(struct ucred *cred, struct vnode *vp,
525     struct label *vplabel, struct image_params *imgp,
526     struct label *execlabel)
527 {
528 
529 	return (mac_bsdextended_check_vp(cred, vp, MBI_READ|MBI_EXEC));
530 }
531 
532 static int
533 mac_bsdextended_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
534     struct label *vplabel, acl_type_t type)
535 {
536 
537 	return (mac_bsdextended_check_vp(cred, vp, MBI_STAT));
538 }
539 
540 static int
541 mac_bsdextended_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
542     struct label *vplabel, int attrnamespace, const char *name,
543     struct uio *uio)
544 {
545 
546 	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
547 }
548 
549 static int
550 mac_bsdextended_check_vnode_link(struct ucred *cred, struct vnode *dvp,
551     struct label *dvplabel, struct vnode *vp, struct label *label,
552     struct componentname *cnp)
553 {
554 	int error;
555 
556 	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
557 	if (error)
558 		return (error);
559 	error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
560 	if (error)
561 		return (error);
562 	return (0);
563 }
564 
565 static int
566 mac_bsdextended_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
567     struct label *vplabel, int attrnamespace)
568 {
569 
570 	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
571 }
572 
573 static int
574 mac_bsdextended_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
575     struct label *dvplabel, struct componentname *cnp)
576 {
577 
578 	return (mac_bsdextended_check_vp(cred, dvp, MBI_EXEC));
579 }
580 
581 static int
582 mac_bsdextended_check_vnode_open(struct ucred *cred, struct vnode *vp,
583     struct label *vplabel, int acc_mode)
584 {
585 
586 	return (mac_bsdextended_check_vp(cred, vp, acc_mode));
587 }
588 
589 static int
590 mac_bsdextended_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
591     struct label *dvplabel)
592 {
593 
594 	return (mac_bsdextended_check_vp(cred, dvp, MBI_READ));
595 }
596 
597 static int
598 mac_bsdextended_check_vnode_readdlink(struct ucred *cred, struct vnode *vp,
599     struct label *vplabel)
600 {
601 
602 	return (mac_bsdextended_check_vp(cred, vp, MBI_READ));
603 }
604 
605 static int
606 mac_bsdextended_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
607     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
608     struct componentname *cnp)
609 {
610 	int error;
611 
612 	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
613 	if (error)
614 		return (error);
615 	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
616 }
617 
618 static int
619 mac_bsdextended_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
620     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
621     int samedir, 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 	if (vp != NULL)
629 		error = mac_bsdextended_check_vp(cred, vp, MBI_WRITE);
630 	return (error);
631 }
632 
633 static int
634 mac_bsdextended_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
635     struct label *vplabel)
636 {
637 
638 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
639 }
640 
641 static int
642 mac_bsdextended_check_setacl_vnode(struct ucred *cred, struct vnode *vp,
643     struct label *vplabel, acl_type_t type, struct acl *acl)
644 {
645 
646 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
647 }
648 
649 static int
650 mac_bsdextended_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
651     struct label *vplabel, int attrnamespace, const char *name,
652     struct uio *uio)
653 {
654 
655 	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
656 }
657 
658 static int
659 mac_bsdextended_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
660     struct label *vplabel, u_long flags)
661 {
662 
663 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
664 }
665 
666 static int
667 mac_bsdextended_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
668     struct label *vplabel, mode_t mode)
669 {
670 
671 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
672 }
673 
674 static int
675 mac_bsdextended_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
676     struct label *vplabel, uid_t uid, gid_t gid)
677 {
678 
679 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
680 }
681 
682 static int
683 mac_bsdextended_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
684     struct label *vplabel, struct timespec atime, struct timespec utime)
685 {
686 
687 	return (mac_bsdextended_check_vp(cred, vp, MBI_ADMIN));
688 }
689 
690 static int
691 mac_bsdextended_check_vnode_stat(struct ucred *active_cred,
692     struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
693 {
694 
695 	return (mac_bsdextended_check_vp(active_cred, vp, MBI_STAT));
696 }
697 
698 static int
699 mac_bsdextended_check_vnode_unlink(struct ucred *cred, struct vnode *dvp,
700     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
701     struct componentname *cnp)
702 {
703 	int error;
704 
705 	error = mac_bsdextended_check_vp(cred, dvp, MBI_WRITE);
706 	if (error)
707 		return (error);
708 	return (mac_bsdextended_check_vp(cred, vp, MBI_WRITE));
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_deleteacl = mac_bsdextended_check_vnode_deleteacl,
724 	.mpo_check_vnode_deleteextattr = mac_bsdextended_check_vnode_deleteextattr,
725 	.mpo_check_vnode_exec = mac_bsdextended_check_vnode_exec,
726 	.mpo_check_vnode_getacl = mac_bsdextended_check_vnode_getacl,
727 	.mpo_check_vnode_getextattr = mac_bsdextended_check_vnode_getextattr,
728 	.mpo_check_vnode_link = mac_bsdextended_check_vnode_link,
729 	.mpo_check_vnode_listextattr = mac_bsdextended_check_vnode_listextattr,
730 	.mpo_check_vnode_lookup = mac_bsdextended_check_vnode_lookup,
731 	.mpo_check_vnode_open = mac_bsdextended_check_vnode_open,
732 	.mpo_check_vnode_readdir = mac_bsdextended_check_vnode_readdir,
733 	.mpo_check_vnode_readlink = mac_bsdextended_check_vnode_readdlink,
734 	.mpo_check_vnode_rename_from = mac_bsdextended_check_vnode_rename_from,
735 	.mpo_check_vnode_rename_to = mac_bsdextended_check_vnode_rename_to,
736 	.mpo_check_vnode_revoke = mac_bsdextended_check_vnode_revoke,
737 	.mpo_check_vnode_setacl = mac_bsdextended_check_setacl_vnode,
738 	.mpo_check_vnode_setextattr = mac_bsdextended_check_vnode_setextattr,
739 	.mpo_check_vnode_setflags = mac_bsdextended_check_vnode_setflags,
740 	.mpo_check_vnode_setmode = mac_bsdextended_check_vnode_setmode,
741 	.mpo_check_vnode_setowner = mac_bsdextended_check_vnode_setowner,
742 	.mpo_check_vnode_setutimes = mac_bsdextended_check_vnode_setutimes,
743 	.mpo_check_vnode_stat = mac_bsdextended_check_vnode_stat,
744 	.mpo_check_vnode_unlink = mac_bsdextended_check_vnode_unlink,
745 };
746 
747 MAC_POLICY_SET(&mac_bsdextended_ops, mac_bsdextended,
748     "TrustedBSD MAC/BSD Extended", MPC_LOADTIME_FLAG_UNLOADOK, NULL);
749