mac_vfs.c revision 165601
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 165601 2006-12-28 22:02:59Z 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/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 */
79static int	ea_warn_once = 0;
80
81static int	mac_setlabel_vnode_extattr(struct ucred *cred,
82		    struct vnode *vp, struct label *intlabel);
83
84static struct label *
85mac_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
94void
95mac_init_devfsdirent(struct devfs_dirent *de)
96{
97
98	de->de_label = mac_devfsdirent_label_alloc();
99}
100
101static struct label *
102mac_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
111static struct label *
112mac_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
121void
122mac_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
129struct label *
130mac_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
139void
140mac_init_vnode(struct vnode *vp)
141{
142
143	vp->v_label = mac_vnode_label_alloc();
144}
145
146static void
147mac_devfsdirent_label_free(struct label *label)
148{
149
150	MAC_PERFORM(destroy_devfsdirent_label, label);
151	mac_labelzone_free(label);
152}
153
154void
155mac_destroy_devfsdirent(struct devfs_dirent *de)
156{
157
158	mac_devfsdirent_label_free(de->de_label);
159	de->de_label = NULL;
160}
161
162static void
163mac_mount_label_free(struct label *label)
164{
165
166	MAC_PERFORM(destroy_mount_label, label);
167	mac_labelzone_free(label);
168}
169
170static void
171mac_mount_fs_label_free(struct label *label)
172{
173
174	MAC_PERFORM(destroy_mount_fs_label, label);
175	mac_labelzone_free(label);
176}
177
178void
179mac_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
188void
189mac_vnode_label_free(struct label *label)
190{
191
192	MAC_PERFORM(destroy_vnode_label, label);
193	mac_labelzone_free(label);
194}
195
196void
197mac_destroy_vnode(struct vnode *vp)
198{
199
200	mac_vnode_label_free(vp->v_label);
201	vp->v_label = NULL;
202}
203
204void
205mac_copy_vnode_label(struct label *src, struct label *dest)
206{
207
208	MAC_PERFORM(copy_vnode_label, src, dest);
209}
210
211int
212mac_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
222int
223mac_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
232void
233mac_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
241void
242mac_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
250int
251mac_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
263void
264mac_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 */
280int
281mac_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
314static int
315mac_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
346void
347mac_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
357int
358mac_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
372int
373mac_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
383int
384mac_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
394int
395mac_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
405int
406mac_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
417int
418mac_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
431int
432mac_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
443int
444mac_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
456int
457mac_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
470int
471mac_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
481int
482mac_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
494int
495mac_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
508int
509mac_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
521int
522mac_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
533int
534mac_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
545void
546mac_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
558int
559mac_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
569int
570mac_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
580int
581mac_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
594int
595mac_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
608int
609mac_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
619int
620mac_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
630static int
631mac_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
643int
644mac_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
657int
658mac_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
671int
672mac_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
682int
683mac_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
694int
695mac_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
707int
708mac_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
718int
719mac_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
729int
730mac_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
741int
742mac_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
754int
755mac_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
767int
768mac_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
781void
782mac_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
788void
789mac_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
796int
797mac_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
806void
807mac_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
814void
815mac_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
823void
824mac_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 */
837int
838vop_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
858int
859vn_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 */
912void
913mac_associate_nfsd_label(struct ucred *cred)
914{
915
916	MAC_PERFORM(associate_nfsd_label, cred);
917}
918