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