xref: /freebsd/sys/security/mac/mac_vfs.c (revision 1e413cf93298b5b97441a21d9a50fdcd0ee9945e)
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_vnode_setlabel_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(devfs_init_label, label);
90 	return (label);
91 }
92 
93 void
94 mac_devfs_init(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(mount_init_label, label);
107 	return (label);
108 }
109 
110 void
111 mac_mount_init(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(vnode_init_label, label);
124 	return (label);
125 }
126 
127 void
128 mac_vnode_init(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(devfs_destroy_label, label);
139 	mac_labelzone_free(label);
140 }
141 
142 void
143 mac_devfs_destroy(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(mount_destroy_label, label);
155 	mac_labelzone_free(label);
156 }
157 
158 void
159 mac_mount_destroy(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(vnode_destroy_label, label);
171 	mac_labelzone_free(label);
172 }
173 
174 void
175 mac_vnode_destroy(struct vnode *vp)
176 {
177 
178 	mac_vnode_label_free(vp->v_label);
179 	vp->v_label = NULL;
180 }
181 
182 void
183 mac_vnode_copy_label(struct label *src, struct label *dest)
184 {
185 
186 	MAC_PERFORM(vnode_copy_label, src, dest);
187 }
188 
189 int
190 mac_vnode_externalize_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_vnode_internalize_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_devfs_update(struct mount *mp, struct devfs_dirent *de, struct vnode *vp)
212 {
213 
214 	MAC_PERFORM(devfs_update, mp, de, de->de_label, vp, vp->v_label);
215 }
216 
217 void
218 mac_devfs_vnode_associate(struct mount *mp, struct devfs_dirent *de,
219     struct vnode *vp)
220 {
221 
222 	MAC_PERFORM(devfs_vnode_associate, mp, mp->mnt_label, de,
223 	    de->de_label, vp, vp->v_label);
224 }
225 
226 int
227 mac_vnode_associate_extattr(struct mount *mp, struct vnode *vp)
228 {
229 	int error;
230 
231 	ASSERT_VOP_LOCKED(vp, "mac_vnode_associate_extattr");
232 
233 	MAC_CHECK(vnode_associate_extattr, mp, mp->mnt_label, vp,
234 	    vp->v_label);
235 
236 	return (error);
237 }
238 
239 void
240 mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp)
241 {
242 
243 	MAC_PERFORM(vnode_associate_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_vnode_create_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_vnode_create_extattr");
263 	ASSERT_VOP_LOCKED(vp, "mac_vnode_create_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(vnode_create_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_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
292     struct label *intlabel)
293 {
294 	int error;
295 
296 	ASSERT_VOP_LOCKED(vp, "mac_vnode_setlabel_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(vnode_setlabel_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_vnode_execve_transition(struct ucred *old, struct ucred *new,
324     struct vnode *vp, struct label *interpvplabel, struct image_params *imgp)
325 {
326 
327 	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_transition");
328 
329 	MAC_PERFORM(vnode_execve_transition, old, new, vp, vp->v_label,
330 	    interpvplabel, imgp, imgp->execlabel);
331 }
332 
333 int
334 mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
335     struct label *interpvplabel, struct image_params *imgp)
336 {
337 	int result;
338 
339 	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition");
340 
341 	result = 0;
342 	MAC_BOOLEAN(vnode_execve_will_transition, ||, old, vp, vp->v_label,
343 	    interpvplabel, imgp, imgp->execlabel);
344 
345 	return (result);
346 }
347 
348 int
349 mac_vnode_check_access(struct ucred *cred, struct vnode *vp, int acc_mode)
350 {
351 	int error;
352 
353 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_access");
354 
355 	MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, acc_mode);
356 	return (error);
357 }
358 
359 int
360 mac_vnode_check_chdir(struct ucred *cred, struct vnode *dvp)
361 {
362 	int error;
363 
364 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chdir");
365 
366 	MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
367 	return (error);
368 }
369 
370 int
371 mac_vnode_check_chroot(struct ucred *cred, struct vnode *dvp)
372 {
373 	int error;
374 
375 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chroot");
376 
377 	MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label);
378 	return (error);
379 }
380 
381 int
382 mac_vnode_check_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_vnode_check_create");
388 
389 	MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
390 	return (error);
391 }
392 
393 int
394 mac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
395     acl_type_t type)
396 {
397 	int error;
398 
399 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteacl");
400 
401 	MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
402 	return (error);
403 }
404 
405 int
406 mac_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
407     int attrnamespace, const char *name)
408 {
409 	int error;
410 
411 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteextattr");
412 
413 	MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label,
414 	    attrnamespace, name);
415 	return (error);
416 }
417 
418 int
419 mac_vnode_check_exec(struct ucred *cred, struct vnode *vp,
420     struct image_params *imgp)
421 {
422 	int error;
423 
424 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_exec");
425 
426 	MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label, imgp,
427 	    imgp->execlabel);
428 
429 	return (error);
430 }
431 
432 int
433 mac_vnode_check_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
434 {
435 	int error;
436 
437 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getacl");
438 
439 	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
440 	return (error);
441 }
442 
443 int
444 mac_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
445     int attrnamespace, const char *name, struct uio *uio)
446 {
447 	int error;
448 
449 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getextattr");
450 
451 	MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
452 	    attrnamespace, name, uio);
453 	return (error);
454 }
455 
456 int
457 mac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
458     struct vnode *vp, struct componentname *cnp)
459 {
460 	int error;
461 
462 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_link");
463 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_link");
464 
465 	MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
466 	    vp->v_label, cnp);
467 	return (error);
468 }
469 
470 int
471 mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
472     int attrnamespace)
473 {
474 	int error;
475 
476 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_listextattr");
477 
478 	MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label,
479 	    attrnamespace);
480 	return (error);
481 }
482 
483 int
484 mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
485     struct componentname *cnp)
486 {
487 	int error;
488 
489 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup");
490 
491 	MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
492 	return (error);
493 }
494 
495 int
496 mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot,
497     int flags)
498 {
499 	int error;
500 
501 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap");
502 
503 	MAC_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags);
504 	return (error);
505 }
506 
507 void
508 mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
509     int *prot)
510 {
511 	int result = *prot;
512 
513 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap_downgrade");
514 
515 	MAC_PERFORM(vnode_check_mmap_downgrade, cred, vp, vp->v_label,
516 	    &result);
517 
518 	*prot = result;
519 }
520 
521 int
522 mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot)
523 {
524 	int error;
525 
526 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mprotect");
527 
528 	MAC_CHECK(vnode_check_mprotect, cred, vp, vp->v_label, prot);
529 	return (error);
530 }
531 
532 int
533 mac_vnode_check_open(struct ucred *cred, struct vnode *vp, int acc_mode)
534 {
535 	int error;
536 
537 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_open");
538 
539 	MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
540 	return (error);
541 }
542 
543 int
544 mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
545     struct vnode *vp)
546 {
547 	int error;
548 
549 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_poll");
550 
551 	MAC_CHECK(vnode_check_poll, active_cred, file_cred, vp,
552 	    vp->v_label);
553 
554 	return (error);
555 }
556 
557 int
558 mac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
559     struct vnode *vp)
560 {
561 	int error;
562 
563 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_read");
564 
565 	MAC_CHECK(vnode_check_read, active_cred, file_cred, vp,
566 	    vp->v_label);
567 
568 	return (error);
569 }
570 
571 int
572 mac_vnode_check_readdir(struct ucred *cred, struct vnode *dvp)
573 {
574 	int error;
575 
576 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_readdir");
577 
578 	MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
579 	return (error);
580 }
581 
582 int
583 mac_vnode_check_readlink(struct ucred *cred, struct vnode *vp)
584 {
585 	int error;
586 
587 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_readlink");
588 
589 	MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
590 	return (error);
591 }
592 
593 static int
594 mac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
595     struct label *newlabel)
596 {
597 	int error;
598 
599 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_relabel");
600 
601 	MAC_CHECK(vnode_check_relabel, cred, vp, vp->v_label, newlabel);
602 
603 	return (error);
604 }
605 
606 int
607 mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
608     struct vnode *vp, struct componentname *cnp)
609 {
610 	int error;
611 
612 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_from");
613 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_from");
614 
615 	MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
616 	    vp->v_label, cnp);
617 	return (error);
618 }
619 
620 int
621 mac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
622     struct vnode *vp, int samedir, struct componentname *cnp)
623 {
624 	int error;
625 
626 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_to");
627 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_to");
628 
629 	MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
630 	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
631 	return (error);
632 }
633 
634 int
635 mac_vnode_check_revoke(struct ucred *cred, struct vnode *vp)
636 {
637 	int error;
638 
639 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_revoke");
640 
641 	MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
642 	return (error);
643 }
644 
645 int
646 mac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
647     struct acl *acl)
648 {
649 	int error;
650 
651 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setacl");
652 
653 	MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
654 	return (error);
655 }
656 
657 int
658 mac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
659     int attrnamespace, const char *name, struct uio *uio)
660 {
661 	int error;
662 
663 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setextattr");
664 
665 	MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
666 	    attrnamespace, name, uio);
667 	return (error);
668 }
669 
670 int
671 mac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
672 {
673 	int error;
674 
675 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setflags");
676 
677 	MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
678 	return (error);
679 }
680 
681 int
682 mac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
683 {
684 	int error;
685 
686 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setmode");
687 
688 	MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
689 	return (error);
690 }
691 
692 int
693 mac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
694     gid_t gid)
695 {
696 	int error;
697 
698 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setowner");
699 
700 	MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
701 	return (error);
702 }
703 
704 int
705 mac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
706     struct timespec atime, struct timespec mtime)
707 {
708 	int error;
709 
710 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setutimes");
711 
712 	MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
713 	    mtime);
714 	return (error);
715 }
716 
717 int
718 mac_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
719     struct vnode *vp)
720 {
721 	int error;
722 
723 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_stat");
724 
725 	MAC_CHECK(vnode_check_stat, active_cred, file_cred, vp,
726 	    vp->v_label);
727 	return (error);
728 }
729 
730 int
731 mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
732     struct vnode *vp, struct componentname *cnp)
733 {
734 	int error;
735 
736 	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_unlink");
737 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_unlink");
738 
739 	MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
740 	    vp->v_label, cnp);
741 	return (error);
742 }
743 
744 int
745 mac_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
746     struct vnode *vp)
747 {
748 	int error;
749 
750 	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_write");
751 
752 	MAC_CHECK(vnode_check_write, active_cred, file_cred, vp,
753 	    vp->v_label);
754 
755 	return (error);
756 }
757 
758 void
759 mac_vnode_relabel(struct ucred *cred, struct vnode *vp,
760     struct label *newlabel)
761 {
762 
763 	MAC_PERFORM(vnode_relabel, cred, vp, vp->v_label, newlabel);
764 }
765 
766 void
767 mac_mount_create(struct ucred *cred, struct mount *mp)
768 {
769 
770 	MAC_PERFORM(mount_create, cred, mp, mp->mnt_label);
771 }
772 
773 int
774 mac_mount_check_stat(struct ucred *cred, struct mount *mount)
775 {
776 	int error;
777 
778 	MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_label);
779 
780 	return (error);
781 }
782 
783 void
784 mac_devfs_create_device(struct ucred *cred, struct mount *mp,
785     struct cdev *dev, struct devfs_dirent *de)
786 {
787 
788 	MAC_PERFORM(devfs_create_device, cred, mp, dev, de, de->de_label);
789 }
790 
791 void
792 mac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
793     struct devfs_dirent *dd, struct devfs_dirent *de)
794 {
795 
796 	MAC_PERFORM(devfs_create_symlink, cred, mp, dd, dd->de_label, de,
797 	    de->de_label);
798 }
799 
800 void
801 mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
802     struct devfs_dirent *de)
803 {
804 
805 	MAC_PERFORM(devfs_create_directory, mp, dirname, dirnamelen, de,
806 	    de->de_label);
807 }
808 
809 /*
810  * Implementation of VOP_SETLABEL() that relies on extended attributes to
811  * store label data.  Can be referenced by filesystems supporting extended
812  * 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_vnode_setlabel_extattr(ap->a_cred, vp, intlabel);
827 	if (error)
828 		return (error);
829 
830 	mac_vnode_relabel(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_vnode_check_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 part
867 	 * 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