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