mac_vfs.c revision 172930
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: head/sys/security/mac/mac_vfs.c 172930 2007-10-24 19:04:04Z rwatson $");
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 */
78static int	ea_warn_once = 0;
79
80static int	mac_vnode_setlabel_extattr(struct ucred *cred,
81		    struct vnode *vp, struct label *intlabel);
82
83static struct label *
84mac_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
93void
94mac_devfs_init(struct devfs_dirent *de)
95{
96
97	de->de_label = mac_devfs_label_alloc();
98}
99
100static struct label *
101mac_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
110void
111mac_mount_init(struct mount *mp)
112{
113
114	mp->mnt_label = mac_mount_label_alloc();
115}
116
117struct label *
118mac_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
127void
128mac_vnode_init(struct vnode *vp)
129{
130
131	vp->v_label = mac_vnode_label_alloc();
132}
133
134static void
135mac_devfs_label_free(struct label *label)
136{
137
138	MAC_PERFORM(devfs_destroy_label, label);
139	mac_labelzone_free(label);
140}
141
142void
143mac_devfs_destroy(struct devfs_dirent *de)
144{
145
146	mac_devfs_label_free(de->de_label);
147	de->de_label = NULL;
148}
149
150static void
151mac_mount_label_free(struct label *label)
152{
153
154	MAC_PERFORM(mount_destroy_label, label);
155	mac_labelzone_free(label);
156}
157
158void
159mac_mount_destroy(struct mount *mp)
160{
161
162	mac_mount_label_free(mp->mnt_label);
163	mp->mnt_label = NULL;
164}
165
166void
167mac_vnode_label_free(struct label *label)
168{
169
170	MAC_PERFORM(vnode_destroy_label, label);
171	mac_labelzone_free(label);
172}
173
174void
175mac_vnode_destroy(struct vnode *vp)
176{
177
178	mac_vnode_label_free(vp->v_label);
179	vp->v_label = NULL;
180}
181
182void
183mac_vnode_copy_label(struct label *src, struct label *dest)
184{
185
186	MAC_PERFORM(vnode_copy_label, src, dest);
187}
188
189int
190mac_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
200int
201mac_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
210void
211mac_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
217void
218mac_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
226int
227mac_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
239void
240mac_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 */
256int
257mac_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
290static int
291mac_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
322void
323mac_vnode_execve_transition(struct ucred *old, struct ucred *new,
324    struct vnode *vp, struct label *interpvnodelabel,
325    struct image_params *imgp)
326{
327
328	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_transition");
329
330	MAC_PERFORM(vnode_execve_transition, old, new, vp, vp->v_label,
331	    interpvnodelabel, imgp, imgp->execlabel);
332}
333
334int
335mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
336    struct label *interpvnodelabel, struct image_params *imgp)
337{
338	int result;
339
340	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition");
341
342	result = 0;
343	MAC_BOOLEAN(vnode_execve_will_transition, ||, old, vp, vp->v_label,
344	    interpvnodelabel, imgp, imgp->execlabel);
345
346	return (result);
347}
348
349int
350mac_vnode_check_access(struct ucred *cred, struct vnode *vp, int acc_mode)
351{
352	int error;
353
354	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_access");
355
356	MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, acc_mode);
357	return (error);
358}
359
360int
361mac_vnode_check_chdir(struct ucred *cred, struct vnode *dvp)
362{
363	int error;
364
365	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chdir");
366
367	MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
368	return (error);
369}
370
371int
372mac_vnode_check_chroot(struct ucred *cred, struct vnode *dvp)
373{
374	int error;
375
376	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chroot");
377
378	MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label);
379	return (error);
380}
381
382int
383mac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
384    struct componentname *cnp, struct vattr *vap)
385{
386	int error;
387
388	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_create");
389
390	MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
391	return (error);
392}
393
394int
395mac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
396    acl_type_t type)
397{
398	int error;
399
400	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteacl");
401
402	MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
403	return (error);
404}
405
406int
407mac_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
408    int attrnamespace, const char *name)
409{
410	int error;
411
412	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteextattr");
413
414	MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label,
415	    attrnamespace, name);
416	return (error);
417}
418
419int
420mac_vnode_check_exec(struct ucred *cred, struct vnode *vp,
421    struct image_params *imgp)
422{
423	int error;
424
425	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_exec");
426
427	MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label, imgp,
428	    imgp->execlabel);
429
430	return (error);
431}
432
433int
434mac_vnode_check_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
435{
436	int error;
437
438	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getacl");
439
440	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
441	return (error);
442}
443
444int
445mac_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
446    int attrnamespace, const char *name, struct uio *uio)
447{
448	int error;
449
450	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getextattr");
451
452	MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
453	    attrnamespace, name, uio);
454	return (error);
455}
456
457int
458mac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
459    struct vnode *vp, struct componentname *cnp)
460{
461	int error;
462
463	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_link");
464	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_link");
465
466	MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
467	    vp->v_label, cnp);
468	return (error);
469}
470
471int
472mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
473    int attrnamespace)
474{
475	int error;
476
477	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_listextattr");
478
479	MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label,
480	    attrnamespace);
481	return (error);
482}
483
484int
485mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
486    struct componentname *cnp)
487{
488	int error;
489
490	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup");
491
492	MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
493	return (error);
494}
495
496int
497mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
498    int prot, int flags)
499{
500	int error;
501
502	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap");
503
504	MAC_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags);
505	return (error);
506}
507
508void
509mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp, 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
521int
522mac_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
532int
533mac_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
543int
544mac_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
557int
558mac_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
571int
572mac_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
582int
583mac_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
593static int
594mac_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
606int
607mac_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
620int
621mac_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
634int
635mac_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
645int
646mac_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
657int
658mac_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
670int
671mac_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
681int
682mac_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
692int
693mac_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
704int
705mac_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
717int
718mac_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
730int
731mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
732    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
744int
745mac_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
758void
759mac_vnode_relabel(struct ucred *cred, struct vnode *vp, struct label *newlabel)
760{
761
762	MAC_PERFORM(vnode_relabel, cred, vp, vp->v_label, newlabel);
763}
764
765void
766mac_mount_create(struct ucred *cred, struct mount *mp)
767{
768
769	MAC_PERFORM(mount_create, cred, mp, mp->mnt_label);
770}
771
772int
773mac_mount_check_stat(struct ucred *cred, struct mount *mount)
774{
775	int error;
776
777	MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_label);
778
779	return (error);
780}
781
782void
783mac_devfs_create_device(struct ucred *cred, struct mount *mp,
784    struct cdev *dev, struct devfs_dirent *de)
785{
786
787	MAC_PERFORM(devfs_create_device, cred, mp, dev, de, de->de_label);
788}
789
790void
791mac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
792    struct devfs_dirent *dd, struct devfs_dirent *de)
793{
794
795	MAC_PERFORM(devfs_create_symlink, cred, mp, dd, dd->de_label, de,
796	    de->de_label);
797}
798
799void
800mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
801    struct devfs_dirent *de)
802{
803
804	MAC_PERFORM(devfs_create_directory, mp, dirname, dirnamelen, de,
805	    de->de_label);
806}
807
808/*
809 * Implementation of VOP_SETLABEL() that relies on extended attributes
810 * to store label data.  Can be referenced by filesystems supporting
811 * extended attributes.
812 */
813int
814vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
815{
816	struct vnode *vp = ap->a_vp;
817	struct label *intlabel = ap->a_label;
818	int error;
819
820	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
821
822	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
823		return (EOPNOTSUPP);
824
825	error = mac_vnode_setlabel_extattr(ap->a_cred, vp, intlabel);
826	if (error)
827		return (error);
828
829	mac_vnode_relabel(ap->a_cred, vp, intlabel);
830
831	return (0);
832}
833
834int
835vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
836{
837	int error;
838
839	if (vp->v_mount == NULL) {
840		/* printf("vn_setlabel: null v_mount\n"); */
841		if (vp->v_type != VNON)
842			printf("vn_setlabel: null v_mount with non-VNON\n");
843		return (EBADF);
844	}
845
846	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
847		return (EOPNOTSUPP);
848
849	/*
850	 * Multi-phase commit.  First check the policies to confirm the
851	 * change is OK.  Then commit via the filesystem.  Finally, update
852	 * the actual vnode label.
853	 *
854	 * Question: maybe the filesystem should update the vnode at the end
855	 * as part of VOP_SETLABEL()?
856	 */
857	error = mac_vnode_check_relabel(cred, vp, intlabel);
858	if (error)
859		return (error);
860
861	/*
862	 * VADMIN provides the opportunity for the filesystem to make
863	 * decisions about who is and is not able to modify labels and
864	 * protections on files.  This might not be right.  We can't assume
865	 * VOP_SETLABEL() will do it, because we might implement that as
866	 * part of vop_stdsetlabel_ea().
867	 */
868	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
869	if (error)
870		return (error);
871
872	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
873	if (error)
874		return (error);
875
876	return (0);
877}
878
879/*
880 * When a thread becomes an NFS server daemon, its credential may need to be
881 * updated to reflect this so that policies can recognize when file system
882 * operations originate from the network.
883 *
884 * At some point, it would be desirable if the credential used for each NFS
885 * RPC could be set based on the RPC context (i.e., source system, etc) to
886 * provide more fine-grained access control.
887 */
888void
889mac_associate_nfsd_label(struct ucred *cred)
890{
891
892	MAC_PERFORM(associate_nfsd_label, cred);
893}
894