mac_vfs.c revision 165469
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 165469 2006-12-22 23:34:47Z 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
271int
272mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
273    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
274{
275	int error;
276
277	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
278	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
279
280	error = VOP_OPENEXTATTR(vp, cred, curthread);
281	if (error == EOPNOTSUPP) {
282		/* XXX: Optionally abort if transactions not supported. */
283		if (ea_warn_once == 0) {
284			printf("Warning: transactions not supported "
285			    "in EA write.\n");
286			ea_warn_once = 1;
287		}
288	} else if (error)
289		return (error);
290
291	MAC_CHECK(create_vnode_extattr, cred, mp, mp->mnt_fslabel,
292	    dvp, dvp->v_label, vp, vp->v_label, cnp);
293
294	if (error) {
295		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
296		return (error);
297	}
298
299	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
300
301	if (error == EOPNOTSUPP)
302		error = 0;				/* XXX */
303
304	return (error);
305}
306
307static int
308mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
309    struct label *intlabel)
310{
311	int error;
312
313	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
314
315	error = VOP_OPENEXTATTR(vp, cred, curthread);
316	if (error == EOPNOTSUPP) {
317		/* XXX: Optionally abort if transactions not supported. */
318		if (ea_warn_once == 0) {
319			printf("Warning: transactions not supported "
320			    "in EA write.\n");
321			ea_warn_once = 1;
322		}
323	} else if (error)
324		return (error);
325
326	MAC_CHECK(setlabel_vnode_extattr, cred, vp, vp->v_label, intlabel);
327
328	if (error) {
329		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
330		return (error);
331	}
332
333	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
334
335	if (error == EOPNOTSUPP)
336		error = 0;				/* XXX */
337
338	return (error);
339}
340
341void
342mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
343    struct label *interpvnodelabel, struct image_params *imgp)
344{
345
346	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
347
348	MAC_PERFORM(execve_transition, old, new, vp, vp->v_label,
349	    interpvnodelabel, imgp, imgp->execlabel);
350}
351
352int
353mac_execve_will_transition(struct ucred *old, struct vnode *vp,
354    struct label *interpvnodelabel, struct image_params *imgp)
355{
356	int result;
357
358	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
359
360	result = 0;
361	MAC_BOOLEAN(execve_will_transition, ||, old, vp, vp->v_label,
362	    interpvnodelabel, imgp, imgp->execlabel);
363
364	return (result);
365}
366
367int
368mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
369{
370	int error;
371
372	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
373
374	MAC_CHECK(check_vnode_access, cred, vp, vp->v_label, acc_mode);
375	return (error);
376}
377
378int
379mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
380{
381	int error;
382
383	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
384
385	MAC_CHECK(check_vnode_chdir, cred, dvp, dvp->v_label);
386	return (error);
387}
388
389int
390mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
391{
392	int error;
393
394	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
395
396	MAC_CHECK(check_vnode_chroot, cred, dvp, dvp->v_label);
397	return (error);
398}
399
400int
401mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
402    struct componentname *cnp, struct vattr *vap)
403{
404	int error;
405
406	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
407
408	MAC_CHECK(check_vnode_create, cred, dvp, dvp->v_label, cnp, vap);
409	return (error);
410}
411
412int
413mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
414    struct componentname *cnp)
415{
416	int error;
417
418	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
419	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
420
421	MAC_CHECK(check_vnode_delete, cred, dvp, dvp->v_label, vp,
422	    vp->v_label, cnp);
423	return (error);
424}
425
426int
427mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
428    acl_type_t type)
429{
430	int error;
431
432	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
433
434	MAC_CHECK(check_vnode_deleteacl, cred, vp, vp->v_label, type);
435	return (error);
436}
437
438int
439mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
440    int attrnamespace, const char *name)
441{
442	int error;
443
444	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
445
446	MAC_CHECK(check_vnode_deleteextattr, cred, vp, vp->v_label,
447	    attrnamespace, name);
448	return (error);
449}
450
451int
452mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
453    struct image_params *imgp)
454{
455	int error;
456
457	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
458
459	MAC_CHECK(check_vnode_exec, cred, vp, vp->v_label, imgp,
460	    imgp->execlabel);
461
462	return (error);
463}
464
465int
466mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
467{
468	int error;
469
470	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
471
472	MAC_CHECK(check_vnode_getacl, cred, vp, vp->v_label, type);
473	return (error);
474}
475
476int
477mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
478    int attrnamespace, const char *name, struct uio *uio)
479{
480	int error;
481
482	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
483
484	MAC_CHECK(check_vnode_getextattr, cred, vp, vp->v_label,
485	    attrnamespace, name, uio);
486	return (error);
487}
488
489int
490mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
491    struct vnode *vp, struct componentname *cnp)
492{
493	int error;
494
495	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
496	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
497
498	MAC_CHECK(check_vnode_link, cred, dvp, dvp->v_label, vp,
499	    vp->v_label, cnp);
500	return (error);
501}
502
503int
504mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
505    int attrnamespace)
506{
507	int error;
508
509	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
510
511	MAC_CHECK(check_vnode_listextattr, cred, vp, vp->v_label,
512	    attrnamespace);
513	return (error);
514}
515
516int
517mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
518    struct componentname *cnp)
519{
520	int error;
521
522	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
523
524	MAC_CHECK(check_vnode_lookup, cred, dvp, dvp->v_label, cnp);
525	return (error);
526}
527
528int
529mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
530    int prot, int flags)
531{
532	int error;
533
534	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
535
536	MAC_CHECK(check_vnode_mmap, cred, vp, vp->v_label, prot, flags);
537	return (error);
538}
539
540void
541mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
542{
543	int result = *prot;
544
545	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
546
547	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, vp->v_label,
548	    &result);
549
550	*prot = result;
551}
552
553int
554mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
555{
556	int error;
557
558	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
559
560	MAC_CHECK(check_vnode_mprotect, cred, vp, vp->v_label, prot);
561	return (error);
562}
563
564int
565mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
566{
567	int error;
568
569	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
570
571	MAC_CHECK(check_vnode_open, cred, vp, vp->v_label, acc_mode);
572	return (error);
573}
574
575int
576mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
577    struct vnode *vp)
578{
579	int error;
580
581	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
582
583	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
584	    vp->v_label);
585
586	return (error);
587}
588
589int
590mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
591    struct vnode *vp)
592{
593	int error;
594
595	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
596
597	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
598	    vp->v_label);
599
600	return (error);
601}
602
603int
604mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
605{
606	int error;
607
608	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
609
610	MAC_CHECK(check_vnode_readdir, cred, dvp, dvp->v_label);
611	return (error);
612}
613
614int
615mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
616{
617	int error;
618
619	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
620
621	MAC_CHECK(check_vnode_readlink, cred, vp, vp->v_label);
622	return (error);
623}
624
625static int
626mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
627    struct label *newlabel)
628{
629	int error;
630
631	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
632
633	MAC_CHECK(check_vnode_relabel, cred, vp, vp->v_label, newlabel);
634
635	return (error);
636}
637
638int
639mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
640    struct vnode *vp, struct componentname *cnp)
641{
642	int error;
643
644	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
645	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
646
647	MAC_CHECK(check_vnode_rename_from, cred, dvp, dvp->v_label, vp,
648	    vp->v_label, cnp);
649	return (error);
650}
651
652int
653mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
654    struct vnode *vp, int samedir, struct componentname *cnp)
655{
656	int error;
657
658	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
659	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
660
661	MAC_CHECK(check_vnode_rename_to, cred, dvp, dvp->v_label, vp,
662	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
663	return (error);
664}
665
666int
667mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
668{
669	int error;
670
671	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
672
673	MAC_CHECK(check_vnode_revoke, cred, vp, vp->v_label);
674	return (error);
675}
676
677int
678mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
679    struct acl *acl)
680{
681	int error;
682
683	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
684
685	MAC_CHECK(check_vnode_setacl, cred, vp, vp->v_label, type, acl);
686	return (error);
687}
688
689int
690mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
691    int attrnamespace, const char *name, struct uio *uio)
692{
693	int error;
694
695	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
696
697	MAC_CHECK(check_vnode_setextattr, cred, vp, vp->v_label,
698	    attrnamespace, name, uio);
699	return (error);
700}
701
702int
703mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
704{
705	int error;
706
707	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
708
709	MAC_CHECK(check_vnode_setflags, cred, vp, vp->v_label, flags);
710	return (error);
711}
712
713int
714mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
715{
716	int error;
717
718	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
719
720	MAC_CHECK(check_vnode_setmode, cred, vp, vp->v_label, mode);
721	return (error);
722}
723
724int
725mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
726    gid_t gid)
727{
728	int error;
729
730	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
731
732	MAC_CHECK(check_vnode_setowner, cred, vp, vp->v_label, uid, gid);
733	return (error);
734}
735
736int
737mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
738    struct timespec atime, struct timespec mtime)
739{
740	int error;
741
742	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
743
744	MAC_CHECK(check_vnode_setutimes, cred, vp, vp->v_label, atime,
745	    mtime);
746	return (error);
747}
748
749int
750mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
751    struct vnode *vp)
752{
753	int error;
754
755	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
756
757	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
758	    vp->v_label);
759	return (error);
760}
761
762int
763mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
764    struct vnode *vp)
765{
766	int error;
767
768	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
769
770	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
771	    vp->v_label);
772
773	return (error);
774}
775
776void
777mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
778{
779
780	MAC_PERFORM(relabel_vnode, cred, vp, vp->v_label, newlabel);
781}
782
783void
784mac_create_mount(struct ucred *cred, struct mount *mp)
785{
786
787	MAC_PERFORM(create_mount, cred, mp, mp->mnt_mntlabel,
788	    mp->mnt_fslabel);
789}
790
791int
792mac_check_mount_stat(struct ucred *cred, struct mount *mount)
793{
794	int error;
795
796	MAC_CHECK(check_mount_stat, cred, mount, mount->mnt_mntlabel);
797
798	return (error);
799}
800
801void
802mac_create_devfs_device(struct ucred *cred, struct mount *mp,
803    struct cdev *dev, struct devfs_dirent *de)
804{
805
806	MAC_PERFORM(create_devfs_device, cred, mp, dev, de, de->de_label);
807}
808
809void
810mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
811    struct devfs_dirent *dd, struct devfs_dirent *de)
812{
813
814	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, dd->de_label, de,
815	    de->de_label);
816}
817
818void
819mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
820    struct devfs_dirent *de)
821{
822
823	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
824	    de->de_label);
825}
826
827/*
828 * Implementation of VOP_SETLABEL() that relies on extended attributes
829 * to store label data.  Can be referenced by filesystems supporting
830 * extended attributes.
831 */
832int
833vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
834{
835	struct vnode *vp = ap->a_vp;
836	struct label *intlabel = ap->a_label;
837	int error;
838
839	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
840
841	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
842		return (EOPNOTSUPP);
843
844	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
845	if (error)
846		return (error);
847
848	mac_relabel_vnode(ap->a_cred, vp, intlabel);
849
850	return (0);
851}
852
853int
854vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
855{
856	int error;
857
858	if (vp->v_mount == NULL) {
859		/* printf("vn_setlabel: null v_mount\n"); */
860		if (vp->v_type != VNON)
861			printf("vn_setlabel: null v_mount with non-VNON\n");
862		return (EBADF);
863	}
864
865	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
866		return (EOPNOTSUPP);
867
868	/*
869	 * Multi-phase commit.  First check the policies to confirm the
870	 * change is OK.  Then commit via the filesystem.  Finally, update
871	 * the actual vnode label.
872	 *
873	 * Question: maybe the filesystem should update the vnode at the end
874	 * as part of VOP_SETLABEL()?
875	 */
876	error = mac_check_vnode_relabel(cred, vp, intlabel);
877	if (error)
878		return (error);
879
880	/*
881	 * VADMIN provides the opportunity for the filesystem to make
882	 * decisions about who is and is not able to modify labels and
883	 * protections on files.  This might not be right.  We can't assume
884	 * VOP_SETLABEL() will do it, because we might implement that as
885	 * part of vop_stdsetlabel_ea().
886	 */
887	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
888	if (error)
889		return (error);
890
891	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
892	if (error)
893		return (error);
894
895	return (0);
896}
897
898/*
899 * When a thread becomes an NFS server daemon, its credential may need to be
900 * updated to reflect this so that policies can recognize when file system
901 * operations originate from the network.
902 *
903 * At some point, it would be desirable if the credential used for each NFS
904 * RPC could be set based on the RPC context (i.e., source system, etc) to
905 * provide more fine-grained access control.
906 */
907void
908mac_associate_nfsd_label(struct ucred *cred)
909{
910
911	MAC_PERFORM(associate_nfsd_label, cred);
912}
913