mac_vfs.c revision 160425
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: head/sys/security/mac/mac_vfs.c 160425 2006-07-17 09:07:02Z phk $");
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 <sys/mac_policy.h>
70
71#include <fs/devfs/devfs.h>
72
73#include <security/mac/mac_internal.h>
74
75/*
76 * Warn about EA transactions only the first time they happen.
77 * Weak coherency, no locking.
78 */
79static int	ea_warn_once = 0;
80
81static int	mac_enforce_fs = 1;
82SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
83    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
84TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
85
86#ifdef MAC_DEBUG
87static int	mac_debug_label_fallback = 0;
88SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
89    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
90    "when label is corrupted.");
91TUNABLE_INT("security.mac.debug_label_fallback",
92    &mac_debug_label_fallback);
93
94static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents;
95SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
96    &nmacmounts, 0, "number of mounts in use");
97SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
98    &nmacvnodes, 0, "number of vnodes in use");
99SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
100    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
101#endif
102
103static int	mac_setlabel_vnode_extattr(struct ucred *cred,
104		    struct vnode *vp, struct label *intlabel);
105
106static struct label *
107mac_devfsdirent_label_alloc(void)
108{
109	struct label *label;
110
111	label = mac_labelzone_alloc(M_WAITOK);
112	MAC_PERFORM(init_devfsdirent_label, label);
113	MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
114	return (label);
115}
116
117void
118mac_init_devfsdirent(struct devfs_dirent *de)
119{
120
121	de->de_label = mac_devfsdirent_label_alloc();
122}
123
124static struct label *
125mac_mount_label_alloc(void)
126{
127	struct label *label;
128
129	label = mac_labelzone_alloc(M_WAITOK);
130	MAC_PERFORM(init_mount_label, label);
131	MAC_DEBUG_COUNTER_INC(&nmacmounts);
132	return (label);
133}
134
135static struct label *
136mac_mount_fs_label_alloc(void)
137{
138	struct label *label;
139
140	label = mac_labelzone_alloc(M_WAITOK);
141	MAC_PERFORM(init_mount_fs_label, label);
142	MAC_DEBUG_COUNTER_INC(&nmacmounts);
143	return (label);
144}
145
146void
147mac_init_mount(struct mount *mp)
148{
149
150	mp->mnt_mntlabel = mac_mount_label_alloc();
151	mp->mnt_fslabel = mac_mount_fs_label_alloc();
152}
153
154struct label *
155mac_vnode_label_alloc(void)
156{
157	struct label *label;
158
159	label = mac_labelzone_alloc(M_WAITOK);
160	MAC_PERFORM(init_vnode_label, label);
161	MAC_DEBUG_COUNTER_INC(&nmacvnodes);
162	return (label);
163}
164
165void
166mac_init_vnode(struct vnode *vp)
167{
168
169	vp->v_label = mac_vnode_label_alloc();
170}
171
172static void
173mac_devfsdirent_label_free(struct label *label)
174{
175
176	MAC_PERFORM(destroy_devfsdirent_label, label);
177	mac_labelzone_free(label);
178	MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
179}
180
181void
182mac_destroy_devfsdirent(struct devfs_dirent *de)
183{
184
185	mac_devfsdirent_label_free(de->de_label);
186	de->de_label = NULL;
187}
188
189static void
190mac_mount_label_free(struct label *label)
191{
192
193	MAC_PERFORM(destroy_mount_label, label);
194	mac_labelzone_free(label);
195	MAC_DEBUG_COUNTER_DEC(&nmacmounts);
196}
197
198static void
199mac_mount_fs_label_free(struct label *label)
200{
201
202	MAC_PERFORM(destroy_mount_fs_label, label);
203	mac_labelzone_free(label);
204	MAC_DEBUG_COUNTER_DEC(&nmacmounts);
205}
206
207void
208mac_destroy_mount(struct mount *mp)
209{
210
211	mac_mount_fs_label_free(mp->mnt_fslabel);
212	mp->mnt_fslabel = NULL;
213	mac_mount_label_free(mp->mnt_mntlabel);
214	mp->mnt_mntlabel = NULL;
215}
216
217void
218mac_vnode_label_free(struct label *label)
219{
220
221	MAC_PERFORM(destroy_vnode_label, label);
222	mac_labelzone_free(label);
223	MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
224}
225
226void
227mac_destroy_vnode(struct vnode *vp)
228{
229
230	mac_vnode_label_free(vp->v_label);
231	vp->v_label = NULL;
232}
233
234void
235mac_copy_vnode_label(struct label *src, struct label *dest)
236{
237
238	MAC_PERFORM(copy_vnode_label, src, dest);
239}
240
241int
242mac_externalize_vnode_label(struct label *label, char *elements,
243    char *outbuf, size_t outbuflen)
244{
245	int error;
246
247	MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
248
249	return (error);
250}
251
252int
253mac_internalize_vnode_label(struct label *label, char *string)
254{
255	int error;
256
257	MAC_INTERNALIZE(vnode, label, string);
258
259	return (error);
260}
261
262void
263mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
264    struct vnode *vp)
265{
266
267	MAC_PERFORM(update_devfsdirent, mp, de, de->de_label, vp,
268	    vp->v_label);
269}
270
271void
272mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
273    struct vnode *vp)
274{
275
276	MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_fslabel, de,
277	    de->de_label, vp, vp->v_label);
278}
279
280int
281mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
282{
283	int error;
284
285	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
286
287	MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_fslabel, vp,
288	    vp->v_label);
289
290	return (error);
291}
292
293void
294mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
295{
296
297	MAC_PERFORM(associate_vnode_singlelabel, mp, mp->mnt_fslabel, vp,
298	    vp->v_label);
299}
300
301int
302mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
303    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
304{
305	int error;
306
307	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
308	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
309
310	error = VOP_OPENEXTATTR(vp, cred, curthread);
311	if (error == EOPNOTSUPP) {
312		/* XXX: Optionally abort if transactions not supported. */
313		if (ea_warn_once == 0) {
314			printf("Warning: transactions not supported "
315			    "in EA write.\n");
316			ea_warn_once = 1;
317		}
318	} else if (error)
319		return (error);
320
321	MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel,
322	    dvp, dvp->v_label, vp, vp->v_label, cnp);
323
324	if (error) {
325		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
326		return (error);
327	}
328
329	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
330
331	if (error == EOPNOTSUPP)
332		error = 0;				/* XXX */
333
334	return (error);
335}
336
337static int
338mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
339    struct label *intlabel)
340{
341	int error;
342
343	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
344
345	error = VOP_OPENEXTATTR(vp, cred, curthread);
346	if (error == EOPNOTSUPP) {
347		/* XXX: Optionally abort if transactions not supported. */
348		if (ea_warn_once == 0) {
349			printf("Warning: transactions not supported "
350			    "in EA write.\n");
351			ea_warn_once = 1;
352		}
353	} else if (error)
354		return (error);
355
356	MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel);
357
358	if (error) {
359		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
360		return (error);
361	}
362
363	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
364
365	if (error == EOPNOTSUPP)
366		error = 0;				/* XXX */
367
368	return (error);
369}
370
371void
372mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
373    struct label *interpvnodelabel, struct image_params *imgp)
374{
375
376	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
377
378	if (!mac_enforce_process && !mac_enforce_fs)
379		return;
380
381	MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
382	    interpvnodelabel, imgp, imgp->execlabel);
383}
384
385int
386mac_execve_will_transition(struct ucred *old, struct vnode *vp,
387    struct label *interpvnodelabel, struct image_params *imgp)
388{
389	int result;
390
391	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
392
393	if (!mac_enforce_process && !mac_enforce_fs)
394		return (0);
395
396	result = 0;
397	MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
398	    interpvnodelabel, imgp, imgp->execlabel);
399
400	return (result);
401}
402
403int
404mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
405{
406	int error;
407
408	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
409
410	if (!mac_enforce_fs)
411		return (0);
412
413	MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
414	return (error);
415}
416
417int
418mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
419{
420	int error;
421
422	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
423
424	if (!mac_enforce_fs)
425		return (0);
426
427	MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
428	return (error);
429}
430
431int
432mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
433{
434	int error;
435
436	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
437
438	if (!mac_enforce_fs)
439		return (0);
440
441	MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
442	return (error);
443}
444
445int
446mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
447    struct componentname *cnp, struct vattr *vap)
448{
449	int error;
450
451	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
452
453	if (!mac_enforce_fs)
454		return (0);
455
456	MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
457	return (error);
458}
459
460int
461mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
462    struct componentname *cnp)
463{
464	int error;
465
466	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
467	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
468
469	if (!mac_enforce_fs)
470		return (0);
471
472	MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp,
473	    vp->v_label, cnp);
474	return (error);
475}
476
477int
478mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
479    acl_type_t type)
480{
481	int error;
482
483	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
484
485	if (!mac_enforce_fs)
486		return (0);
487
488	MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
489	return (error);
490}
491
492int
493mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
494    int attrnamespace, const char *name)
495{
496	int error;
497
498	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
499
500	if (!mac_enforce_fs)
501		return (0);
502
503	MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
504	    attrnamespace, name);
505	return (error);
506}
507
508int
509mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
510    struct image_params *imgp)
511{
512	int error;
513
514	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
515
516	if (!mac_enforce_process && !mac_enforce_fs)
517		return (0);
518
519	MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
520	    imgp->execlabel);
521
522	return (error);
523}
524
525int
526mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
527{
528	int error;
529
530	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
531
532	if (!mac_enforce_fs)
533		return (0);
534
535	MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
536	return (error);
537}
538
539int
540mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
541    int attrnamespace, const char *name, struct uio *uio)
542{
543	int error;
544
545	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
546
547	if (!mac_enforce_fs)
548		return (0);
549
550	MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
551	    attrnamespace, name, uio);
552	return (error);
553}
554
555int
556mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
557    struct vnode *vp, struct componentname *cnp)
558{
559	int error;
560
561	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
562	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
563
564	if (!mac_enforce_fs)
565		return (0);
566
567	MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
568	    vp->v_label, cnp);
569	return (error);
570}
571
572int
573mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
574    int attrnamespace)
575{
576	int error;
577
578	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
579
580	if (!mac_enforce_fs)
581		return (0);
582
583	MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
584	    attrnamespace);
585	return (error);
586}
587
588int
589mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
590    struct componentname *cnp)
591{
592	int error;
593
594	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
595
596	if (!mac_enforce_fs)
597		return (0);
598
599	MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
600	return (error);
601}
602
603int
604mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
605    int prot, int flags)
606{
607	int error;
608
609	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
610
611	if (!mac_enforce_fs || !mac_enforce_vm)
612		return (0);
613
614	MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags);
615	return (error);
616}
617
618void
619mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
620{
621	int result = *prot;
622
623	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
624
625	if (!mac_enforce_fs || !mac_enforce_vm)
626		return;
627
628	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
629	    &result);
630
631	*prot = result;
632}
633
634int
635mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
636{
637	int error;
638
639	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
640
641	if (!mac_enforce_fs || !mac_enforce_vm)
642		return (0);
643
644	MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
645	return (error);
646}
647
648int
649mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
650{
651	int error;
652
653	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
654
655	if (!mac_enforce_fs)
656		return (0);
657
658	MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
659	return (error);
660}
661
662int
663mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
664    struct vnode *vp)
665{
666	int error;
667
668	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
669
670	if (!mac_enforce_fs)
671		return (0);
672
673	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
674	    vp->v_label);
675
676	return (error);
677}
678
679int
680mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
681    struct vnode *vp)
682{
683	int error;
684
685	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
686
687	if (!mac_enforce_fs)
688		return (0);
689
690	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
691	    vp->v_label);
692
693	return (error);
694}
695
696int
697mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
698{
699	int error;
700
701	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
702
703	if (!mac_enforce_fs)
704		return (0);
705
706	MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
707	return (error);
708}
709
710int
711mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
712{
713	int error;
714
715	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
716
717	if (!mac_enforce_fs)
718		return (0);
719
720	MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
721	return (error);
722}
723
724static int
725mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
726    struct label *newlabel)
727{
728	int error;
729
730	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
731
732	MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
733
734	return (error);
735}
736
737int
738mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
739    struct vnode *vp, struct componentname *cnp)
740{
741	int error;
742
743	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
744	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
745
746	if (!mac_enforce_fs)
747		return (0);
748
749	MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
750	    vp->v_label, cnp);
751	return (error);
752}
753
754int
755mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
756    struct vnode *vp, int samedir, struct componentname *cnp)
757{
758	int error;
759
760	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
761	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
762
763	if (!mac_enforce_fs)
764		return (0);
765
766	MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
767	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
768	return (error);
769}
770
771int
772mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
773{
774	int error;
775
776	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
777
778	if (!mac_enforce_fs)
779		return (0);
780
781	MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
782	return (error);
783}
784
785int
786mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
787    struct acl *acl)
788{
789	int error;
790
791	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
792
793	if (!mac_enforce_fs)
794		return (0);
795
796	MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
797	return (error);
798}
799
800int
801mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
802    int attrnamespace, const char *name, struct uio *uio)
803{
804	int error;
805
806	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
807
808	if (!mac_enforce_fs)
809		return (0);
810
811	MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
812	    attrnamespace, name, uio);
813	return (error);
814}
815
816int
817mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
818{
819	int error;
820
821	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
822
823	if (!mac_enforce_fs)
824		return (0);
825
826	MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
827	return (error);
828}
829
830int
831mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
832{
833	int error;
834
835	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
836
837	if (!mac_enforce_fs)
838		return (0);
839
840	MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
841	return (error);
842}
843
844int
845mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
846    gid_t gid)
847{
848	int error;
849
850	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
851
852	if (!mac_enforce_fs)
853		return (0);
854
855	MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
856	return (error);
857}
858
859int
860mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
861    struct timespec atime, struct timespec mtime)
862{
863	int error;
864
865	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
866
867	if (!mac_enforce_fs)
868		return (0);
869
870	MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
871	    mtime);
872	return (error);
873}
874
875int
876mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
877    struct vnode *vp)
878{
879	int error;
880
881	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
882
883	if (!mac_enforce_fs)
884		return (0);
885
886	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
887	    vp->v_label);
888	return (error);
889}
890
891int
892mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
893    struct vnode *vp)
894{
895	int error;
896
897	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
898
899	if (!mac_enforce_fs)
900		return (0);
901
902	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
903	    vp->v_label);
904
905	return (error);
906}
907
908void
909mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
910{
911
912	MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
913}
914
915void
916mac_create_mount(struct ucred *cred, struct mount *mp)
917{
918
919	MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel,
920	    mp->mnt_fslabel);
921}
922
923int
924mac_check_mount_stat(struct ucred *cred, struct mount *mount)
925{
926	int error;
927
928	if (!mac_enforce_fs)
929		return (0);
930
931	MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel);
932
933	return (error);
934}
935
936void
937mac_create_devfs_device(struct ucred *cred, struct mount *mp,
938    struct cdev *dev, struct devfs_dirent *de)
939{
940
941	MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label);
942}
943
944void
945mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
946    struct devfs_dirent *dd, struct devfs_dirent *de)
947{
948
949	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
950	    de->de_label);
951}
952
953void
954mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
955    struct devfs_dirent *de)
956{
957
958	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
959	    de->de_label);
960}
961
962/*
963 * Implementation of VOP_SETLABEL() that relies on extended attributes
964 * to store label data.  Can be referenced by filesystems supporting
965 * extended attributes.
966 */
967int
968vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
969{
970	struct vnode *vp = ap->a_vp;
971	struct label *intlabel = ap->a_label;
972	int error;
973
974	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
975
976	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
977		return (EOPNOTSUPP);
978
979	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
980	if (error)
981		return (error);
982
983	mac_relabel_vnode(ap->a_cred, vp, intlabel);
984
985	return (0);
986}
987
988int
989vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
990{
991	int error;
992
993	if (vp->v_mount == NULL) {
994		/* printf("vn_setlabel: null v_mount\n"); */
995		if (vp->v_type != VNON)
996			printf("vn_setlabel: null v_mount with non-VNON\n");
997		return (EBADF);
998	}
999
1000	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1001		return (EOPNOTSUPP);
1002
1003	/*
1004	 * Multi-phase commit.  First check the policies to confirm the
1005	 * change is OK.  Then commit via the filesystem.  Finally,
1006	 * update the actual vnode label.  Question: maybe the filesystem
1007	 * should update the vnode at the end as part of VOP_SETLABEL()?
1008	 */
1009	error = mac_check_vnode_relabel(cred, vp, intlabel);
1010	if (error)
1011		return (error);
1012
1013	/*
1014	 * VADMIN provides the opportunity for the filesystem to make
1015	 * decisions about who is and is not able to modify labels
1016	 * and protections on files.  This might not be right.  We can't
1017	 * assume VOP_SETLABEL() will do it, because we might implement
1018	 * that as part of vop_stdsetlabel_ea().
1019	 */
1020	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
1021	if (error)
1022		return (error);
1023
1024	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1025	if (error)
1026		return (error);
1027
1028	return (0);
1029}
1030
1031void
1032mac_associate_nfsd_label(struct ucred *cred)
1033{
1034
1035	MAC_PERFORM(associate_nfsd_label, cred);
1036}
1037