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