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