xref: /freebsd/sys/security/mac/mac_vfs.c (revision ebccf1e3a6b11b97cbf5f813dd76636e892a9035)
1 /*-
2  * Copyright (c) 1999-2002 Robert N. M. Watson
3  * Copyright (c) 2001 Ilmar S. Habibulin
4  * Copyright (c) 2001-2005 McAfee, Inc.
5  * All rights reserved.
6  *
7  * This software was developed by Robert Watson and Ilmar Habibulin for the
8  * TrustedBSD Project.
9  *
10  * This software was developed for the FreeBSD Project in part by McAfee
11  * Research, the Security Research Division of McAfee, Inc. under
12  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
13  * 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 
37 #include <sys/cdefs.h>
38 __FBSDID("$FreeBSD$");
39 
40 #include "opt_mac.h"
41 #include "opt_devfs.h"
42 
43 #include <sys/param.h>
44 #include <sys/condvar.h>
45 #include <sys/extattr.h>
46 #include <sys/imgact.h>
47 #include <sys/kernel.h>
48 #include <sys/lock.h>
49 #include <sys/malloc.h>
50 #include <sys/mutex.h>
51 #include <sys/mac.h>
52 #include <sys/proc.h>
53 #include <sys/sbuf.h>
54 #include <sys/systm.h>
55 #include <sys/vnode.h>
56 #include <sys/mount.h>
57 #include <sys/file.h>
58 #include <sys/namei.h>
59 #include <sys/sysctl.h>
60 
61 #include <vm/vm.h>
62 #include <vm/pmap.h>
63 #include <vm/vm_map.h>
64 #include <vm/vm_object.h>
65 
66 #include <sys/mac_policy.h>
67 
68 #include <fs/devfs/devfs.h>
69 
70 #include <security/mac/mac_internal.h>
71 
72 /*
73  * Warn about EA transactions only the first time they happen.
74  * Weak coherency, no locking.
75  */
76 static int	ea_warn_once = 0;
77 
78 static int	mac_enforce_fs = 1;
79 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
80     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
81 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
82 
83 #ifdef MAC_DEBUG
84 static int	mac_debug_label_fallback = 0;
85 SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
86     &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
87     "when label is corrupted.");
88 TUNABLE_INT("security.mac.debug_label_fallback",
89     &mac_debug_label_fallback);
90 
91 static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents;
92 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
93     &nmacmounts, 0, "number of mounts in use");
94 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
95     &nmacvnodes, 0, "number of vnodes in use");
96 SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
97     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
98 #endif
99 
100 static int	mac_setlabel_vnode_extattr(struct ucred *cred,
101 		    struct vnode *vp, struct label *intlabel);
102 
103 static struct label *
104 mac_devfsdirent_label_alloc(void)
105 {
106 	struct label *label;
107 
108 	label = mac_labelzone_alloc(M_WAITOK);
109 	MAC_PERFORM(init_devfsdirent_label, label);
110 	MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
111 	return (label);
112 }
113 
114 void
115 mac_init_devfsdirent(struct devfs_dirent *de)
116 {
117 
118 	de->de_label = mac_devfsdirent_label_alloc();
119 }
120 
121 static struct label *
122 mac_mount_label_alloc(void)
123 {
124 	struct label *label;
125 
126 	label = mac_labelzone_alloc(M_WAITOK);
127 	MAC_PERFORM(init_mount_label, label);
128 	MAC_DEBUG_COUNTER_INC(&nmacmounts);
129 	return (label);
130 }
131 
132 static struct label *
133 mac_mount_fs_label_alloc(void)
134 {
135 	struct label *label;
136 
137 	label = mac_labelzone_alloc(M_WAITOK);
138 	MAC_PERFORM(init_mount_fs_label, label);
139 	MAC_DEBUG_COUNTER_INC(&nmacmounts);
140 	return (label);
141 }
142 
143 void
144 mac_init_mount(struct mount *mp)
145 {
146 
147 	mp->mnt_mntlabel = mac_mount_label_alloc();
148 	mp->mnt_fslabel = mac_mount_fs_label_alloc();
149 }
150 
151 struct label *
152 mac_vnode_label_alloc(void)
153 {
154 	struct label *label;
155 
156 	label = mac_labelzone_alloc(M_WAITOK);
157 	MAC_PERFORM(init_vnode_label, label);
158 	MAC_DEBUG_COUNTER_INC(&nmacvnodes);
159 	return (label);
160 }
161 
162 void
163 mac_init_vnode(struct vnode *vp)
164 {
165 
166 	vp->v_label = mac_vnode_label_alloc();
167 }
168 
169 static void
170 mac_devfsdirent_label_free(struct label *label)
171 {
172 
173 	MAC_PERFORM(destroy_devfsdirent_label, label);
174 	mac_labelzone_free(label);
175 	MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
176 }
177 
178 void
179 mac_destroy_devfsdirent(struct devfs_dirent *de)
180 {
181 
182 	mac_devfsdirent_label_free(de->de_label);
183 	de->de_label = NULL;
184 }
185 
186 static void
187 mac_mount_label_free(struct label *label)
188 {
189 
190 	MAC_PERFORM(destroy_mount_label, label);
191 	mac_labelzone_free(label);
192 	MAC_DEBUG_COUNTER_DEC(&nmacmounts);
193 }
194 
195 static void
196 mac_mount_fs_label_free(struct label *label)
197 {
198 
199 	MAC_PERFORM(destroy_mount_fs_label, label);
200 	mac_labelzone_free(label);
201 	MAC_DEBUG_COUNTER_DEC(&nmacmounts);
202 }
203 
204 void
205 mac_destroy_mount(struct mount *mp)
206 {
207 
208 	mac_mount_fs_label_free(mp->mnt_fslabel);
209 	mp->mnt_fslabel = NULL;
210 	mac_mount_label_free(mp->mnt_mntlabel);
211 	mp->mnt_mntlabel = NULL;
212 }
213 
214 void
215 mac_vnode_label_free(struct label *label)
216 {
217 
218 	MAC_PERFORM(destroy_vnode_label, label);
219 	mac_labelzone_free(label);
220 	MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
221 }
222 
223 void
224 mac_destroy_vnode(struct vnode *vp)
225 {
226 
227 	mac_vnode_label_free(vp->v_label);
228 	vp->v_label = NULL;
229 }
230 
231 void
232 mac_copy_vnode_label(struct label *src, struct label *dest)
233 {
234 
235 	MAC_PERFORM(copy_vnode_label, src, dest);
236 }
237 
238 int
239 mac_externalize_vnode_label(struct label *label, char *elements,
240     char *outbuf, size_t outbuflen)
241 {
242 	int error;
243 
244 	MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
245 
246 	return (error);
247 }
248 
249 int
250 mac_internalize_vnode_label(struct label *label, char *string)
251 {
252 	int error;
253 
254 	MAC_INTERNALIZE(vnode, label, string);
255 
256 	return (error);
257 }
258 
259 void
260 mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
261     struct vnode *vp)
262 {
263 
264 	MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp,
265 	    vp->v_label);
266 }
267 
268 void
269 mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
270     struct vnode *vp)
271 {
272 
273 	MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de,
274 	    de->de_label, vp, vp->v_label);
275 }
276 
277 int
278 mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
279 {
280 	int error;
281 
282 	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
283 
284 	MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp,
285 	    vp->v_label);
286 
287 	return (error);
288 }
289 
290 void
291 mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
292 {
293 
294 	MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp,
295 	    vp->v_label);
296 }
297 
298 int
299 mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
300     struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
301 {
302 	int error;
303 
304 	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
305 	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
306 
307 	error = VOP_OPENEXTATTR(vp, cred, curthread);
308 	if (error == EOPNOTSUPP) {
309 		/* XXX: Optionally abort if transactions not supported. */
310 		if (ea_warn_once == 0) {
311 			printf("Warning: transactions not supported "
312 			    "in EA write.\n");
313 			ea_warn_once = 1;
314 		}
315 	} else if (error)
316 		return (error);
317 
318 	MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel,
319 	    dvp, dvp->v_label, vp, vp->v_label, cnp);
320 
321 	if (error) {
322 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
323 		return (error);
324 	}
325 
326 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
327 
328 	if (error == EOPNOTSUPP)
329 		error = 0;				/* XXX */
330 
331 	return (error);
332 }
333 
334 static int
335 mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
336     struct label *intlabel)
337 {
338 	int error;
339 
340 	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
341 
342 	error = VOP_OPENEXTATTR(vp, cred, curthread);
343 	if (error == EOPNOTSUPP) {
344 		/* XXX: Optionally abort if transactions not supported. */
345 		if (ea_warn_once == 0) {
346 			printf("Warning: transactions not supported "
347 			    "in EA write.\n");
348 			ea_warn_once = 1;
349 		}
350 	} else if (error)
351 		return (error);
352 
353 	MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel);
354 
355 	if (error) {
356 		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
357 		return (error);
358 	}
359 
360 	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
361 
362 	if (error == EOPNOTSUPP)
363 		error = 0;				/* XXX */
364 
365 	return (error);
366 }
367 
368 void
369 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
370     struct label *interpvnodelabel, struct image_params *imgp)
371 {
372 
373 	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
374 
375 	if (!mac_enforce_process && !mac_enforce_fs)
376 		return;
377 
378 	MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
379 	    interpvnodelabel, imgp, imgp->execlabel);
380 }
381 
382 int
383 mac_execve_will_transition(struct ucred *old, struct vnode *vp,
384     struct label *interpvnodelabel, struct image_params *imgp)
385 {
386 	int result;
387 
388 	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
389 
390 	if (!mac_enforce_process && !mac_enforce_fs)
391 		return (0);
392 
393 	result = 0;
394 	MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
395 	    interpvnodelabel, imgp, imgp->execlabel);
396 
397 	return (result);
398 }
399 
400 int
401 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
402 {
403 	int error;
404 
405 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
406 
407 	if (!mac_enforce_fs)
408 		return (0);
409 
410 	MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
411 	return (error);
412 }
413 
414 int
415 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
416 {
417 	int error;
418 
419 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
420 
421 	if (!mac_enforce_fs)
422 		return (0);
423 
424 	MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
425 	return (error);
426 }
427 
428 int
429 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
430 {
431 	int error;
432 
433 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
434 
435 	if (!mac_enforce_fs)
436 		return (0);
437 
438 	MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
439 	return (error);
440 }
441 
442 int
443 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
444     struct componentname *cnp, struct vattr *vap)
445 {
446 	int error;
447 
448 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
449 
450 	if (!mac_enforce_fs)
451 		return (0);
452 
453 	MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
454 	return (error);
455 }
456 
457 int
458 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
459     struct componentname *cnp)
460 {
461 	int error;
462 
463 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
464 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
465 
466 	if (!mac_enforce_fs)
467 		return (0);
468 
469 	MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp,
470 	    vp->v_label, cnp);
471 	return (error);
472 }
473 
474 int
475 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
476     acl_type_t type)
477 {
478 	int error;
479 
480 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
481 
482 	if (!mac_enforce_fs)
483 		return (0);
484 
485 	MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
486 	return (error);
487 }
488 
489 int
490 mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
491     int attrnamespace, const char *name)
492 {
493 	int error;
494 
495 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
496 
497 	if (!mac_enforce_fs)
498 		return (0);
499 
500 	MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
501 	    attrnamespace, name);
502 	return (error);
503 }
504 
505 int
506 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
507     struct image_params *imgp)
508 {
509 	int error;
510 
511 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
512 
513 	if (!mac_enforce_process && !mac_enforce_fs)
514 		return (0);
515 
516 	MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
517 	    imgp->execlabel);
518 
519 	return (error);
520 }
521 
522 int
523 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
524 {
525 	int error;
526 
527 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
528 
529 	if (!mac_enforce_fs)
530 		return (0);
531 
532 	MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
533 	return (error);
534 }
535 
536 int
537 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
538     int attrnamespace, const char *name, struct uio *uio)
539 {
540 	int error;
541 
542 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
543 
544 	if (!mac_enforce_fs)
545 		return (0);
546 
547 	MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
548 	    attrnamespace, name, uio);
549 	return (error);
550 }
551 
552 int
553 mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
554     struct vnode *vp, struct componentname *cnp)
555 {
556 	int error;
557 
558 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
559 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
560 
561 	if (!mac_enforce_fs)
562 		return (0);
563 
564 	MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
565 	    vp->v_label, cnp);
566 	return (error);
567 }
568 
569 int
570 mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
571     int attrnamespace)
572 {
573 	int error;
574 
575 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
576 
577 	if (!mac_enforce_fs)
578 		return (0);
579 
580 	MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
581 	    attrnamespace);
582 	return (error);
583 }
584 
585 int
586 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
587     struct componentname *cnp)
588 {
589 	int error;
590 
591 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
592 
593 	if (!mac_enforce_fs)
594 		return (0);
595 
596 	MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
597 	return (error);
598 }
599 
600 int
601 mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
602     int prot, int flags)
603 {
604 	int error;
605 
606 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
607 
608 	if (!mac_enforce_fs || !mac_enforce_vm)
609 		return (0);
610 
611 	MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags);
612 	return (error);
613 }
614 
615 void
616 mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
617 {
618 	int result = *prot;
619 
620 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
621 
622 	if (!mac_enforce_fs || !mac_enforce_vm)
623 		return;
624 
625 	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
626 	    &result);
627 
628 	*prot = result;
629 }
630 
631 int
632 mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
633 {
634 	int error;
635 
636 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
637 
638 	if (!mac_enforce_fs || !mac_enforce_vm)
639 		return (0);
640 
641 	MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
642 	return (error);
643 }
644 
645 int
646 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
647 {
648 	int error;
649 
650 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
651 
652 	if (!mac_enforce_fs)
653 		return (0);
654 
655 	MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
656 	return (error);
657 }
658 
659 int
660 mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
661     struct vnode *vp)
662 {
663 	int error;
664 
665 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
666 
667 	if (!mac_enforce_fs)
668 		return (0);
669 
670 	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
671 	    vp->v_label);
672 
673 	return (error);
674 }
675 
676 int
677 mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
678     struct vnode *vp)
679 {
680 	int error;
681 
682 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
683 
684 	if (!mac_enforce_fs)
685 		return (0);
686 
687 	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
688 	    vp->v_label);
689 
690 	return (error);
691 }
692 
693 int
694 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
695 {
696 	int error;
697 
698 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
699 
700 	if (!mac_enforce_fs)
701 		return (0);
702 
703 	MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
704 	return (error);
705 }
706 
707 int
708 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
709 {
710 	int error;
711 
712 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
713 
714 	if (!mac_enforce_fs)
715 		return (0);
716 
717 	MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
718 	return (error);
719 }
720 
721 static int
722 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
723     struct label *newlabel)
724 {
725 	int error;
726 
727 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
728 
729 	MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
730 
731 	return (error);
732 }
733 
734 int
735 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
736     struct vnode *vp, struct componentname *cnp)
737 {
738 	int error;
739 
740 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
741 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
742 
743 	if (!mac_enforce_fs)
744 		return (0);
745 
746 	MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
747 	    vp->v_label, cnp);
748 	return (error);
749 }
750 
751 int
752 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
753     struct vnode *vp, int samedir, struct componentname *cnp)
754 {
755 	int error;
756 
757 	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
758 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
759 
760 	if (!mac_enforce_fs)
761 		return (0);
762 
763 	MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
764 	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
765 	return (error);
766 }
767 
768 int
769 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
770 {
771 	int error;
772 
773 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
774 
775 	if (!mac_enforce_fs)
776 		return (0);
777 
778 	MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
779 	return (error);
780 }
781 
782 int
783 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
784     struct acl *acl)
785 {
786 	int error;
787 
788 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
789 
790 	if (!mac_enforce_fs)
791 		return (0);
792 
793 	MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
794 	return (error);
795 }
796 
797 int
798 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
799     int attrnamespace, const char *name, struct uio *uio)
800 {
801 	int error;
802 
803 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
804 
805 	if (!mac_enforce_fs)
806 		return (0);
807 
808 	MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
809 	    attrnamespace, name, uio);
810 	return (error);
811 }
812 
813 int
814 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
815 {
816 	int error;
817 
818 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
819 
820 	if (!mac_enforce_fs)
821 		return (0);
822 
823 	MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
824 	return (error);
825 }
826 
827 int
828 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
829 {
830 	int error;
831 
832 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
833 
834 	if (!mac_enforce_fs)
835 		return (0);
836 
837 	MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
838 	return (error);
839 }
840 
841 int
842 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
843     gid_t gid)
844 {
845 	int error;
846 
847 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
848 
849 	if (!mac_enforce_fs)
850 		return (0);
851 
852 	MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
853 	return (error);
854 }
855 
856 int
857 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
858     struct timespec atime, struct timespec mtime)
859 {
860 	int error;
861 
862 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
863 
864 	if (!mac_enforce_fs)
865 		return (0);
866 
867 	MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
868 	    mtime);
869 	return (error);
870 }
871 
872 int
873 mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
874     struct vnode *vp)
875 {
876 	int error;
877 
878 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
879 
880 	if (!mac_enforce_fs)
881 		return (0);
882 
883 	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
884 	    vp->v_label);
885 	return (error);
886 }
887 
888 int
889 mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
890     struct vnode *vp)
891 {
892 	int error;
893 
894 	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
895 
896 	if (!mac_enforce_fs)
897 		return (0);
898 
899 	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
900 	    vp->v_label);
901 
902 	return (error);
903 }
904 
905 void
906 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
907 {
908 
909 	MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
910 }
911 
912 void
913 mac_create_mount(struct ucred *cred, struct mount *mp)
914 {
915 
916 	MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel,
917 	    mp->mnt_fslabel);
918 }
919 
920 void
921 mac_create_root_mount(struct ucred *cred, struct mount *mp)
922 {
923 
924 	MAC_PERFORM(create_root_mount, cred, mp, mp->mnt_mntlabel,
925 	    mp->mnt_fslabel);
926 }
927 
928 int
929 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
930 {
931 	int error;
932 
933 	if (!mac_enforce_fs)
934 		return (0);
935 
936 	MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel);
937 
938 	return (error);
939 }
940 
941 void
942 mac_create_devfs_device(struct mount *mp, struct cdev *dev, struct devfs_dirent *de)
943 {
944 
945 	MAC_PERFORM(create_devfs_device, mp, dev, de, de->de_label);
946 }
947 
948 void
949 mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
950     struct devfs_dirent *dd, struct devfs_dirent *de)
951 {
952 
953 	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
954 	    de->de_label);
955 }
956 
957 void
958 mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
959     struct devfs_dirent *de)
960 {
961 
962 	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
963 	    de->de_label);
964 }
965 
966 /*
967  * Implementation of VOP_SETLABEL() that relies on extended attributes
968  * to store label data.  Can be referenced by filesystems supporting
969  * extended attributes.
970  */
971 int
972 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
973 {
974 	struct vnode *vp = ap->a_vp;
975 	struct label *intlabel = ap->a_label;
976 	int error;
977 
978 	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
979 
980 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
981 		return (EOPNOTSUPP);
982 
983 	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
984 	if (error)
985 		return (error);
986 
987 	mac_relabel_vnode(ap->a_cred, vp, intlabel);
988 
989 	return (0);
990 }
991 
992 int
993 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
994 {
995 	int error;
996 
997 	if (vp->v_mount == NULL) {
998 		/* printf("vn_setlabel: null v_mount\n"); */
999 		if (vp->v_type != VNON)
1000 			printf("vn_setlabel: null v_mount with non-VNON\n");
1001 		return (EBADF);
1002 	}
1003 
1004 	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1005 		return (EOPNOTSUPP);
1006 
1007 	/*
1008 	 * Multi-phase commit.  First check the policies to confirm the
1009 	 * change is OK.  Then commit via the filesystem.  Finally,
1010 	 * update the actual vnode label.  Question: maybe the filesystem
1011 	 * should update the vnode at the end as part of VOP_SETLABEL()?
1012 	 */
1013 	error = mac_check_vnode_relabel(cred, vp, intlabel);
1014 	if (error)
1015 		return (error);
1016 
1017 	/*
1018 	 * VADMIN provides the opportunity for the filesystem to make
1019 	 * decisions about who is and is not able to modify labels
1020 	 * and protections on files.  This might not be right.  We can't
1021 	 * assume VOP_SETLABEL() will do it, because we might implement
1022 	 * that as part of vop_stdsetlabel_ea().
1023 	 */
1024 	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
1025 	if (error)
1026 		return (error);
1027 
1028 	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1029 	if (error)
1030 		return (error);
1031 
1032 	return (0);
1033 }
1034