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