mac_vfs.c revision 172107
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 172107 2007-09-10 00:00:18Z 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_setlabel_vnode_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(init_devfs_label, label);
90	return (label);
91}
92
93void
94mac_init_devfs(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(init_mount_label, label);
107	return (label);
108}
109
110void
111mac_init_mount(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(init_vnode_label, label);
124	return (label);
125}
126
127void
128mac_init_vnode(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(destroy_devfs_label, label);
139	mac_labelzone_free(label);
140}
141
142void
143mac_destroy_devfs(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(destroy_mount_label, label);
155	mac_labelzone_free(label);
156}
157
158void
159mac_destroy_mount(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(destroy_vnode_label, label);
171	mac_labelzone_free(label);
172}
173
174void
175mac_destroy_vnode(struct vnode *vp)
176{
177
178	mac_vnode_label_free(vp->v_label);
179	vp->v_label = NULL;
180}
181
182void
183mac_copy_vnode_label(struct label *src, struct label *dest)
184{
185
186	MAC_PERFORM(copy_vnode_label, src, dest);
187}
188
189int
190mac_externalize_vnode_label(struct label *label, char *elements,
191    char *outbuf, size_t outbuflen)
192{
193	int error;
194
195	MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
196
197	return (error);
198}
199
200int
201mac_internalize_vnode_label(struct label *label, char *string)
202{
203	int error;
204
205	MAC_INTERNALIZE(vnode, label, string);
206
207	return (error);
208}
209
210void
211mac_update_devfs(struct mount *mp, struct devfs_dirent *de, struct vnode *vp)
212{
213
214	MAC_PERFORM(update_devfs, mp, de, de->de_label, vp, vp->v_label);
215}
216
217void
218mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
219    struct vnode *vp)
220{
221
222	MAC_PERFORM(associate_vnode_devfs, mp, mp->mnt_label, de,
223	    de->de_label, vp, vp->v_label);
224}
225
226int
227mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
228{
229	int error;
230
231	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
232
233	MAC_CHECK(associate_vnode_extattr, mp, mp->mnt_label, vp,
234	    vp->v_label);
235
236	return (error);
237}
238
239void
240mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
241{
242
243	MAC_PERFORM(associate_vnode_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_create_vnode_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_create_vnode_extattr");
263	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_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(create_vnode_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_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
292    struct label *intlabel)
293{
294	int error;
295
296	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_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(setlabel_vnode_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_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
324    struct label *interpvnodelabel, struct image_params *imgp)
325{
326
327	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
328
329	MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
330	    interpvnodelabel, imgp, imgp->execlabel);
331}
332
333int
334mac_execve_will_transition(struct ucred *old, struct vnode *vp,
335    struct label *interpvnodelabel, struct image_params *imgp)
336{
337	int result;
338
339	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
340
341	result = 0;
342	MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
343	    interpvnodelabel, imgp, imgp->execlabel);
344
345	return (result);
346}
347
348int
349mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
350{
351	int error;
352
353	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
354
355	MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
356	return (error);
357}
358
359int
360mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
361{
362	int error;
363
364	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
365
366	MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
367	return (error);
368}
369
370int
371mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
372{
373	int error;
374
375	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
376
377	MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
378	return (error);
379}
380
381int
382mac_check_vnode_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_check_vnode_create");
388
389	MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
390	return (error);
391}
392
393int
394mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
395    acl_type_t type)
396{
397	int error;
398
399	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
400
401	MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
402	return (error);
403}
404
405int
406mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
407    int attrnamespace, const char *name)
408{
409	int error;
410
411	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
412
413	MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
414	    attrnamespace, name);
415	return (error);
416}
417
418int
419mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
420    struct image_params *imgp)
421{
422	int error;
423
424	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
425
426	MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
427	    imgp->execlabel);
428
429	return (error);
430}
431
432int
433mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
434{
435	int error;
436
437	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
438
439	MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
440	return (error);
441}
442
443int
444mac_check_vnode_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_check_vnode_getextattr");
450
451	MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
452	    attrnamespace, name, uio);
453	return (error);
454}
455
456int
457mac_check_vnode_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_check_vnode_link");
463	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
464
465	MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
466	    vp->v_label, cnp);
467	return (error);
468}
469
470int
471mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
472    int attrnamespace)
473{
474	int error;
475
476	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
477
478	MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
479	    attrnamespace);
480	return (error);
481}
482
483int
484mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
485    struct componentname *cnp)
486{
487	int error;
488
489	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
490
491	MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
492	return (error);
493}
494
495int
496mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
497    int prot, int flags)
498{
499	int error;
500
501	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
502
503	MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags);
504	return (error);
505}
506
507void
508mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
509{
510	int result = *prot;
511
512	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
513
514	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
515	    &result);
516
517	*prot = result;
518}
519
520int
521mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
522{
523	int error;
524
525	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
526
527	MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
528	return (error);
529}
530
531int
532mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
533{
534	int error;
535
536	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
537
538	MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
539	return (error);
540}
541
542int
543mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
544    struct vnode *vp)
545{
546	int error;
547
548	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
549
550	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
551	    vp->v_label);
552
553	return (error);
554}
555
556int
557mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
558    struct vnode *vp)
559{
560	int error;
561
562	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
563
564	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
565	    vp->v_label);
566
567	return (error);
568}
569
570int
571mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
572{
573	int error;
574
575	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
576
577	MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
578	return (error);
579}
580
581int
582mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
583{
584	int error;
585
586	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
587
588	MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
589	return (error);
590}
591
592static int
593mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
594    struct label *newlabel)
595{
596	int error;
597
598	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
599
600	MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
601
602	return (error);
603}
604
605int
606mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
607    struct vnode *vp, struct componentname *cnp)
608{
609	int error;
610
611	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
612	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
613
614	MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
615	    vp->v_label, cnp);
616	return (error);
617}
618
619int
620mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
621    struct vnode *vp, int samedir, struct componentname *cnp)
622{
623	int error;
624
625	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
626	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
627
628	MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
629	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
630	return (error);
631}
632
633int
634mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
635{
636	int error;
637
638	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
639
640	MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
641	return (error);
642}
643
644int
645mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
646    struct acl *acl)
647{
648	int error;
649
650	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
651
652	MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
653	return (error);
654}
655
656int
657mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
658    int attrnamespace, const char *name, struct uio *uio)
659{
660	int error;
661
662	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
663
664	MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
665	    attrnamespace, name, uio);
666	return (error);
667}
668
669int
670mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
671{
672	int error;
673
674	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
675
676	MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
677	return (error);
678}
679
680int
681mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
682{
683	int error;
684
685	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
686
687	MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
688	return (error);
689}
690
691int
692mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
693    gid_t gid)
694{
695	int error;
696
697	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
698
699	MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
700	return (error);
701}
702
703int
704mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
705    struct timespec atime, struct timespec mtime)
706{
707	int error;
708
709	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
710
711	MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
712	    mtime);
713	return (error);
714}
715
716int
717mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
718    struct vnode *vp)
719{
720	int error;
721
722	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
723
724	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
725	    vp->v_label);
726	return (error);
727}
728
729int
730mac_check_vnode_unlink(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
731    struct componentname *cnp)
732{
733	int error;
734
735	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_unlink");
736	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_unlink");
737
738	MAC_CHECK(check_vnode_unlink, cred, dvp, dvp->v_label, vp,
739	    vp->v_label, cnp);
740	return (error);
741}
742
743int
744mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
745    struct vnode *vp)
746{
747	int error;
748
749	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
750
751	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
752	    vp->v_label);
753
754	return (error);
755}
756
757void
758mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
759{
760
761	MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
762}
763
764void
765mac_create_mount(struct ucred *cred, struct mount *mp)
766{
767
768	MAC_PERFORM(create_mount, cred, mp, mp->mnt_label);
769}
770
771int
772mac_check_mount_stat(struct ucred *cred, struct mount *mount)
773{
774	int error;
775
776	MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_label);
777
778	return (error);
779}
780
781void
782mac_create_devfs_device(struct ucred *cred, struct mount *mp,
783    struct cdev *dev, struct devfs_dirent *de)
784{
785
786	MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label);
787}
788
789void
790mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
791    struct devfs_dirent *dd, struct devfs_dirent *de)
792{
793
794	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
795	    de->de_label);
796}
797
798void
799mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
800    struct devfs_dirent *de)
801{
802
803	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
804	    de->de_label);
805}
806
807/*
808 * Implementation of VOP_SETLABEL() that relies on extended attributes
809 * to store label data.  Can be referenced by filesystems supporting
810 * extended attributes.
811 */
812int
813vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
814{
815	struct vnode *vp = ap->a_vp;
816	struct label *intlabel = ap->a_label;
817	int error;
818
819	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
820
821	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
822		return (EOPNOTSUPP);
823
824	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
825	if (error)
826		return (error);
827
828	mac_relabel_vnode(ap->a_cred, vp, intlabel);
829
830	return (0);
831}
832
833int
834vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
835{
836	int error;
837
838	if (vp->v_mount == NULL) {
839		/* printf("vn_setlabel: null v_mount\n"); */
840		if (vp->v_type != VNON)
841			printf("vn_setlabel: null v_mount with non-VNON\n");
842		return (EBADF);
843	}
844
845	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
846		return (EOPNOTSUPP);
847
848	/*
849	 * Multi-phase commit.  First check the policies to confirm the
850	 * change is OK.  Then commit via the filesystem.  Finally, update
851	 * the actual vnode label.
852	 *
853	 * Question: maybe the filesystem should update the vnode at the end
854	 * as part of VOP_SETLABEL()?
855	 */
856	error = mac_check_vnode_relabel(cred, vp, intlabel);
857	if (error)
858		return (error);
859
860	/*
861	 * VADMIN provides the opportunity for the filesystem to make
862	 * decisions about who is and is not able to modify labels and
863	 * protections on files.  This might not be right.  We can't assume
864	 * VOP_SETLABEL() will do it, because we might implement that as
865	 * part of vop_stdsetlabel_ea().
866	 */
867	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
868	if (error)
869		return (error);
870
871	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
872	if (error)
873		return (error);
874
875	return (0);
876}
877
878/*
879 * When a thread becomes an NFS server daemon, its credential may need to be
880 * updated to reflect this so that policies can recognize when file system
881 * operations originate from the network.
882 *
883 * At some point, it would be desirable if the credential used for each NFS
884 * RPC could be set based on the RPC context (i.e., source system, etc) to
885 * provide more fine-grained access control.
886 */
887void
888mac_associate_nfsd_label(struct ucred *cred)
889{
890
891	MAC_PERFORM(associate_nfsd_label, cred);
892}
893