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