mac_vfs.c revision 184413
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 * Copyright (c) 2008 Apple Inc.
7 * All rights reserved.
8 *
9 * This software was developed by Robert Watson and Ilmar Habibulin for the
10 * TrustedBSD Project.
11 *
12 * This software was developed for the FreeBSD Project in part by McAfee
13 * Research, the Security Research Division of McAfee, Inc. under
14 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
15 * CHATS research program.
16 *
17 * This software was enhanced by SPARTA ISSO under SPAWAR contract
18 * N66001-04-C-6019 ("SEFOS").
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 184413 2008-10-28 13:44:11Z trasz $");
44
45#include "opt_mac.h"
46
47#include <sys/param.h>
48#include <sys/condvar.h>
49#include <sys/extattr.h>
50#include <sys/imgact.h>
51#include <sys/kernel.h>
52#include <sys/lock.h>
53#include <sys/malloc.h>
54#include <sys/mutex.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_vnode_setlabel_extattr(struct ucred *cred,
82		    struct vnode *vp, struct label *intlabel);
83
84static struct label *
85mac_devfs_label_alloc(void)
86{
87	struct label *label;
88
89	label = mac_labelzone_alloc(M_WAITOK);
90	MAC_PERFORM(devfs_init_label, label);
91	return (label);
92}
93
94void
95mac_devfs_init(struct devfs_dirent *de)
96{
97
98	if (mac_labeled & MPC_OBJECT_DEVFS)
99		de->de_label = mac_devfs_label_alloc();
100	else
101		de->de_label = NULL;
102}
103
104static struct label *
105mac_mount_label_alloc(void)
106{
107	struct label *label;
108
109	label = mac_labelzone_alloc(M_WAITOK);
110	MAC_PERFORM(mount_init_label, label);
111	return (label);
112}
113
114void
115mac_mount_init(struct mount *mp)
116{
117
118	if (mac_labeled & MPC_OBJECT_MOUNT)
119		mp->mnt_label = mac_mount_label_alloc();
120	else
121		mp->mnt_label = NULL;
122}
123
124struct label *
125mac_vnode_label_alloc(void)
126{
127	struct label *label;
128
129	label = mac_labelzone_alloc(M_WAITOK);
130	MAC_PERFORM(vnode_init_label, label);
131	return (label);
132}
133
134void
135mac_vnode_init(struct vnode *vp)
136{
137
138	if (mac_labeled & MPC_OBJECT_VNODE)
139		vp->v_label = mac_vnode_label_alloc();
140	else
141		vp->v_label = NULL;
142}
143
144static void
145mac_devfs_label_free(struct label *label)
146{
147
148	MAC_PERFORM(devfs_destroy_label, label);
149	mac_labelzone_free(label);
150}
151
152void
153mac_devfs_destroy(struct devfs_dirent *de)
154{
155
156	if (de->de_label != NULL) {
157		mac_devfs_label_free(de->de_label);
158		de->de_label = NULL;
159	}
160}
161
162static void
163mac_mount_label_free(struct label *label)
164{
165
166	MAC_PERFORM(mount_destroy_label, label);
167	mac_labelzone_free(label);
168}
169
170void
171mac_mount_destroy(struct mount *mp)
172{
173
174	if (mp->mnt_label != NULL) {
175		mac_mount_label_free(mp->mnt_label);
176		mp->mnt_label = NULL;
177	}
178}
179
180void
181mac_vnode_label_free(struct label *label)
182{
183
184	MAC_PERFORM(vnode_destroy_label, label);
185	mac_labelzone_free(label);
186}
187
188void
189mac_vnode_destroy(struct vnode *vp)
190{
191
192	if (vp->v_label != NULL) {
193		mac_vnode_label_free(vp->v_label);
194		vp->v_label = NULL;
195	}
196}
197
198void
199mac_vnode_copy_label(struct label *src, struct label *dest)
200{
201
202	MAC_PERFORM(vnode_copy_label, src, dest);
203}
204
205int
206mac_vnode_externalize_label(struct label *label, char *elements,
207    char *outbuf, size_t outbuflen)
208{
209	int error;
210
211	MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
212
213	return (error);
214}
215
216int
217mac_vnode_internalize_label(struct label *label, char *string)
218{
219	int error;
220
221	MAC_INTERNALIZE(vnode, label, string);
222
223	return (error);
224}
225
226void
227mac_devfs_update(struct mount *mp, struct devfs_dirent *de, struct vnode *vp)
228{
229
230	MAC_PERFORM(devfs_update, mp, de, de->de_label, vp, vp->v_label);
231}
232
233void
234mac_devfs_vnode_associate(struct mount *mp, struct devfs_dirent *de,
235    struct vnode *vp)
236{
237
238	MAC_PERFORM(devfs_vnode_associate, mp, mp->mnt_label, de,
239	    de->de_label, vp, vp->v_label);
240}
241
242int
243mac_vnode_associate_extattr(struct mount *mp, struct vnode *vp)
244{
245	int error;
246
247	ASSERT_VOP_LOCKED(vp, "mac_vnode_associate_extattr");
248
249	MAC_CHECK(vnode_associate_extattr, mp, mp->mnt_label, vp,
250	    vp->v_label);
251
252	return (error);
253}
254
255void
256mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp)
257{
258
259	MAC_PERFORM(vnode_associate_singlelabel, mp, mp->mnt_label, vp,
260	    vp->v_label);
261}
262
263/*
264 * Functions implementing extended-attribute backed labels for file systems
265 * that support it.
266 *
267 * Where possible, we use EA transactions to make writes to multiple
268 * attributes across difference policies mutually atomic.  We allow work to
269 * continue on file systems not supporting EA transactions, but generate a
270 * printf warning.
271 */
272int
273mac_vnode_create_extattr(struct ucred *cred, struct mount *mp,
274    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
275{
276	int error;
277
278	ASSERT_VOP_LOCKED(dvp, "mac_vnode_create_extattr");
279	ASSERT_VOP_LOCKED(vp, "mac_vnode_create_extattr");
280
281	error = VOP_OPENEXTATTR(vp, cred, curthread);
282	if (error == EOPNOTSUPP) {
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(vnode_create_extattr, cred, mp, mp->mnt_label, dvp,
292	    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	if (error == EOPNOTSUPP)
301		error = 0;
302
303	return (error);
304}
305
306static int
307mac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
308    struct label *intlabel)
309{
310	int error;
311
312	ASSERT_VOP_LOCKED(vp, "mac_vnode_setlabel_extattr");
313
314	error = VOP_OPENEXTATTR(vp, cred, curthread);
315	if (error == EOPNOTSUPP) {
316		if (ea_warn_once == 0) {
317			printf("Warning: transactions not supported "
318			    "in EA write.\n");
319			ea_warn_once = 1;
320		}
321	} else if (error)
322		return (error);
323
324	MAC_CHECK(vnode_setlabel_extattr, cred, vp, vp->v_label, intlabel);
325
326	if (error) {
327		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
328		return (error);
329	}
330
331	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
332	if (error == EOPNOTSUPP)
333		error = 0;
334
335	return (error);
336}
337
338void
339mac_vnode_execve_transition(struct ucred *old, struct ucred *new,
340    struct vnode *vp, struct label *interpvplabel, struct image_params *imgp)
341{
342
343	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_transition");
344
345	MAC_PERFORM(vnode_execve_transition, old, new, vp, vp->v_label,
346	    interpvplabel, imgp, imgp->execlabel);
347}
348
349int
350mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
351    struct label *interpvplabel, struct image_params *imgp)
352{
353	int result;
354
355	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition");
356
357	result = 0;
358	MAC_BOOLEAN(vnode_execve_will_transition, ||, old, vp, vp->v_label,
359	    interpvplabel, imgp, imgp->execlabel);
360
361	return (result);
362}
363
364int
365mac_vnode_check_access(struct ucred *cred, struct vnode *vp, accmode_t accmode)
366{
367	int error;
368
369	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_access");
370
371	MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, accmode);
372	return (error);
373}
374
375int
376mac_vnode_check_chdir(struct ucred *cred, struct vnode *dvp)
377{
378	int error;
379
380	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chdir");
381
382	MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
383	return (error);
384}
385
386int
387mac_vnode_check_chroot(struct ucred *cred, struct vnode *dvp)
388{
389	int error;
390
391	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_chroot");
392
393	MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label);
394	return (error);
395}
396
397int
398mac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
399    struct componentname *cnp, struct vattr *vap)
400{
401	int error;
402
403	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_create");
404
405	MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
406	return (error);
407}
408
409int
410mac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
411    acl_type_t type)
412{
413	int error;
414
415	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteacl");
416
417	MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
418	return (error);
419}
420
421int
422mac_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
423    int attrnamespace, const char *name)
424{
425	int error;
426
427	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteextattr");
428
429	MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label,
430	    attrnamespace, name);
431	return (error);
432}
433
434int
435mac_vnode_check_exec(struct ucred *cred, struct vnode *vp,
436    struct image_params *imgp)
437{
438	int error;
439
440	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_exec");
441
442	MAC_CHECK(vnode_check_exec, cred, vp, vp->v_label, imgp,
443	    imgp->execlabel);
444
445	return (error);
446}
447
448int
449mac_vnode_check_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
450{
451	int error;
452
453	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getacl");
454
455	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
456	return (error);
457}
458
459int
460mac_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
461    int attrnamespace, const char *name, struct uio *uio)
462{
463	int error;
464
465	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getextattr");
466
467	MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
468	    attrnamespace, name, uio);
469	return (error);
470}
471
472int
473mac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
474    struct vnode *vp, struct componentname *cnp)
475{
476	int error;
477
478	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_link");
479	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_link");
480
481	MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
482	    vp->v_label, cnp);
483	return (error);
484}
485
486int
487mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
488    int attrnamespace)
489{
490	int error;
491
492	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_listextattr");
493
494	MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label,
495	    attrnamespace);
496	return (error);
497}
498
499int
500mac_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
501    struct componentname *cnp)
502{
503	int error;
504
505	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup");
506
507	MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
508	return (error);
509}
510
511int
512mac_vnode_check_mmap(struct ucred *cred, struct vnode *vp, int prot,
513    int flags)
514{
515	int error;
516
517	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap");
518
519	MAC_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags);
520	return (error);
521}
522
523void
524mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
525    int *prot)
526{
527	int result = *prot;
528
529	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap_downgrade");
530
531	MAC_PERFORM(vnode_check_mmap_downgrade, cred, vp, vp->v_label,
532	    &result);
533
534	*prot = result;
535}
536
537int
538mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot)
539{
540	int error;
541
542	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mprotect");
543
544	MAC_CHECK(vnode_check_mprotect, cred, vp, vp->v_label, prot);
545	return (error);
546}
547
548int
549mac_vnode_check_open(struct ucred *cred, struct vnode *vp, accmode_t accmode)
550{
551	int error;
552
553	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_open");
554
555	MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, accmode);
556	return (error);
557}
558
559int
560mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
561    struct vnode *vp)
562{
563	int error;
564
565	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_poll");
566
567	MAC_CHECK(vnode_check_poll, active_cred, file_cred, vp,
568	    vp->v_label);
569
570	return (error);
571}
572
573int
574mac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
575    struct vnode *vp)
576{
577	int error;
578
579	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_read");
580
581	MAC_CHECK(vnode_check_read, active_cred, file_cred, vp,
582	    vp->v_label);
583
584	return (error);
585}
586
587int
588mac_vnode_check_readdir(struct ucred *cred, struct vnode *dvp)
589{
590	int error;
591
592	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_readdir");
593
594	MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
595	return (error);
596}
597
598int
599mac_vnode_check_readlink(struct ucred *cred, struct vnode *vp)
600{
601	int error;
602
603	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_readlink");
604
605	MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
606	return (error);
607}
608
609static int
610mac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
611    struct label *newlabel)
612{
613	int error;
614
615	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_relabel");
616
617	MAC_CHECK(vnode_check_relabel, cred, vp, vp->v_label, newlabel);
618
619	return (error);
620}
621
622int
623mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
624    struct vnode *vp, struct componentname *cnp)
625{
626	int error;
627
628	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_from");
629	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_from");
630
631	MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
632	    vp->v_label, cnp);
633	return (error);
634}
635
636int
637mac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
638    struct vnode *vp, int samedir, struct componentname *cnp)
639{
640	int error;
641
642	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_to");
643	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_to");
644
645	MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
646	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
647	return (error);
648}
649
650int
651mac_vnode_check_revoke(struct ucred *cred, struct vnode *vp)
652{
653	int error;
654
655	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_revoke");
656
657	MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
658	return (error);
659}
660
661int
662mac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
663    struct acl *acl)
664{
665	int error;
666
667	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setacl");
668
669	MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
670	return (error);
671}
672
673int
674mac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
675    int attrnamespace, const char *name, struct uio *uio)
676{
677	int error;
678
679	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setextattr");
680
681	MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
682	    attrnamespace, name, uio);
683	return (error);
684}
685
686int
687mac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
688{
689	int error;
690
691	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setflags");
692
693	MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
694	return (error);
695}
696
697int
698mac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
699{
700	int error;
701
702	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setmode");
703
704	MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
705	return (error);
706}
707
708int
709mac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
710    gid_t gid)
711{
712	int error;
713
714	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setowner");
715
716	MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
717	return (error);
718}
719
720int
721mac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
722    struct timespec atime, struct timespec mtime)
723{
724	int error;
725
726	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setutimes");
727
728	MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
729	    mtime);
730	return (error);
731}
732
733int
734mac_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
735    struct vnode *vp)
736{
737	int error;
738
739	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_stat");
740
741	MAC_CHECK(vnode_check_stat, active_cred, file_cred, vp,
742	    vp->v_label);
743	return (error);
744}
745
746int
747mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
748    struct vnode *vp, struct componentname *cnp)
749{
750	int error;
751
752	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_unlink");
753	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_unlink");
754
755	MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
756	    vp->v_label, cnp);
757	return (error);
758}
759
760int
761mac_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
762    struct vnode *vp)
763{
764	int error;
765
766	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_write");
767
768	MAC_CHECK(vnode_check_write, active_cred, file_cred, vp,
769	    vp->v_label);
770
771	return (error);
772}
773
774void
775mac_vnode_relabel(struct ucred *cred, struct vnode *vp,
776    struct label *newlabel)
777{
778
779	MAC_PERFORM(vnode_relabel, cred, vp, vp->v_label, newlabel);
780}
781
782void
783mac_mount_create(struct ucred *cred, struct mount *mp)
784{
785
786	MAC_PERFORM(mount_create, cred, mp, mp->mnt_label);
787}
788
789int
790mac_mount_check_stat(struct ucred *cred, struct mount *mount)
791{
792	int error;
793
794	MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_label);
795
796	return (error);
797}
798
799void
800mac_devfs_create_device(struct ucred *cred, struct mount *mp,
801    struct cdev *dev, struct devfs_dirent *de)
802{
803
804	MAC_PERFORM(devfs_create_device, cred, mp, dev, de, de->de_label);
805}
806
807void
808mac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
809    struct devfs_dirent *dd, struct devfs_dirent *de)
810{
811
812	MAC_PERFORM(devfs_create_symlink, cred, mp, dd, dd->de_label, de,
813	    de->de_label);
814}
815
816void
817mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
818    struct devfs_dirent *de)
819{
820
821	MAC_PERFORM(devfs_create_directory, mp, dirname, dirnamelen, de,
822	    de->de_label);
823}
824
825/*
826 * Implementation of VOP_SETLABEL() that relies on extended attributes to
827 * store label data.  Can be referenced by filesystems supporting extended
828 * attributes.
829 */
830int
831vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
832{
833	struct vnode *vp = ap->a_vp;
834	struct label *intlabel = ap->a_label;
835	int error;
836
837	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
838
839	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
840		return (EOPNOTSUPP);
841
842	error = mac_vnode_setlabel_extattr(ap->a_cred, vp, intlabel);
843	if (error)
844		return (error);
845
846	mac_vnode_relabel(ap->a_cred, vp, intlabel);
847
848	return (0);
849}
850
851int
852vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
853{
854	int error;
855
856	if (vp->v_mount == NULL) {
857		/* printf("vn_setlabel: null v_mount\n"); */
858		if (vp->v_type != VNON)
859			printf("vn_setlabel: null v_mount with non-VNON\n");
860		return (EBADF);
861	}
862
863	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
864		return (EOPNOTSUPP);
865
866	/*
867	 * Multi-phase commit.  First check the policies to confirm the
868	 * change is OK.  Then commit via the filesystem.  Finally, update
869	 * the actual vnode label.
870	 *
871	 * Question: maybe the filesystem should update the vnode at the end
872	 * as part of VOP_SETLABEL()?
873	 */
874	error = mac_vnode_check_relabel(cred, vp, intlabel);
875	if (error)
876		return (error);
877
878	/*
879	 * VADMIN provides the opportunity for the filesystem to make
880	 * decisions about who is and is not able to modify labels and
881	 * protections on files.  This might not be right.  We can't assume
882	 * VOP_SETLABEL() will do it, because we might implement that as part
883	 * of vop_stdsetlabel_ea().
884	 */
885	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
886	if (error)
887		return (error);
888
889	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
890	if (error)
891		return (error);
892
893	return (0);
894}
895