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