mac_vfs.c revision 121367
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
8 * TrustedBSD Project.
9 *
10 * This software was developed for the FreeBSD Project in part by Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA CHATS research program.
14 *
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
17 * are met:
18 * 1. Redistributions of source code must retain the above copyright
19 *    notice, this list of conditions and the following disclaimer.
20 * 2. Redistributions in binary form must reproduce the above copyright
21 *    notice, this list of conditions and the following disclaimer in the
22 *    documentation and/or other materials provided with the distribution.
23 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37#include <sys/cdefs.h>
38__FBSDID("$FreeBSD: head/sys/security/mac/mac_vfs.c 121367 2003-10-22 20:29:41Z rwatson $");
39
40#include "opt_mac.h"
41#include "opt_devfs.h"
42
43#include <sys/param.h>
44#include <sys/condvar.h>
45#include <sys/extattr.h>
46#include <sys/imgact.h>
47#include <sys/kernel.h>
48#include <sys/lock.h>
49#include <sys/malloc.h>
50#include <sys/mutex.h>
51#include <sys/mac.h>
52#include <sys/proc.h>
53#include <sys/sbuf.h>
54#include <sys/systm.h>
55#include <sys/vnode.h>
56#include <sys/mount.h>
57#include <sys/file.h>
58#include <sys/namei.h>
59#include <sys/sysctl.h>
60
61#include <vm/vm.h>
62#include <vm/pmap.h>
63#include <vm/vm_map.h>
64#include <vm/vm_object.h>
65
66#include <sys/mac_policy.h>
67
68#include <fs/devfs/devfs.h>
69
70#include <security/mac/mac_internal.h>
71
72/*
73 * Warn about EA transactions only the first time they happen.
74 * Weak coherency, no locking.
75 */
76static int	ea_warn_once = 0;
77
78static int	mac_enforce_fs = 1;
79SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
80    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
81TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
82
83#ifdef MAC_DEBUG
84static int	mac_debug_label_fallback = 0;
85SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
86    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
87    "when label is corrupted.");
88TUNABLE_INT("security.mac.debug_label_fallback",
89    &mac_debug_label_fallback);
90
91static unsigned int nmacmounts, nmacvnodes, nmacdevfsdirents;
92SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
93    &nmacmounts, 0, "number of mounts in use");
94SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
95    &nmacvnodes, 0, "number of vnodes in use");
96SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
97    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
98#endif
99
100static int	mac_setlabel_vnode_extattr(struct ucred *cred,
101		    struct vnode *vp, struct label *intlabel);
102
103void
104mac_init_devfsdirent(struct devfs_dirent *de)
105{
106
107	mac_init_label(&de->de_label);
108	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
109	MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
110}
111
112void
113mac_init_mount(struct mount *mp)
114{
115
116	mac_init_label(&mp->mnt_mntlabel);
117	mac_init_label(&mp->mnt_fslabel);
118	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
119	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
120	MAC_DEBUG_COUNTER_INC(&nmacmounts);
121}
122
123void
124mac_init_vnode_label(struct label *label)
125{
126
127	mac_init_label(label);
128	MAC_PERFORM(init_vnode_label, label);
129	MAC_DEBUG_COUNTER_INC(&nmacvnodes);
130}
131
132void
133mac_init_vnode(struct vnode *vp)
134{
135
136	mac_init_vnode_label(&vp->v_label);
137}
138
139void
140mac_destroy_devfsdirent(struct devfs_dirent *de)
141{
142
143	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
144	mac_destroy_label(&de->de_label);
145	MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
146}
147
148void
149mac_destroy_mount(struct mount *mp)
150{
151
152	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
153	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
154	mac_destroy_label(&mp->mnt_fslabel);
155	mac_destroy_label(&mp->mnt_mntlabel);
156	MAC_DEBUG_COUNTER_DEC(&nmacmounts);
157}
158
159void
160mac_destroy_vnode_label(struct label *label)
161{
162
163	MAC_PERFORM(destroy_vnode_label, label);
164	mac_destroy_label(label);
165	MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
166}
167
168void
169mac_destroy_vnode(struct vnode *vp)
170{
171
172	mac_destroy_vnode_label(&vp->v_label);
173}
174
175void
176mac_copy_vnode_label(struct label *src, struct label *dest)
177{
178
179	MAC_PERFORM(copy_vnode_label, src, dest);
180}
181
182int
183mac_externalize_vnode_label(struct label *label, char *elements,
184    char *outbuf, size_t outbuflen, int flags)
185{
186	int error;
187
188	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
189
190	return (error);
191}
192
193int
194mac_internalize_vnode_label(struct label *label, char *string)
195{
196	int error;
197
198	MAC_INTERNALIZE(vnode_label, label, string);
199
200	return (error);
201}
202
203void
204mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
205    struct vnode *vp)
206{
207
208	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
209	    &vp->v_label);
210}
211
212void
213mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
214    struct vnode *vp)
215{
216
217	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
218	    &de->de_label, vp, &vp->v_label);
219}
220
221int
222mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
223{
224	int error;
225
226	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
227
228	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
229	    &vp->v_label);
230
231	return (error);
232}
233
234void
235mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
236{
237
238	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
239	    &vp->v_label);
240}
241
242int
243mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
244    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
245{
246	int error;
247
248	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
249	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
250
251	error = VOP_OPENEXTATTR(vp, cred, curthread);
252	if (error == EOPNOTSUPP) {
253		/* XXX: Optionally abort if transactions not supported. */
254		if (ea_warn_once == 0) {
255			printf("Warning: transactions not supported "
256			    "in EA write.\n");
257			ea_warn_once = 1;
258		}
259	} else if (error)
260		return (error);
261
262	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
263	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
264
265	if (error) {
266		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
267		return (error);
268	}
269
270	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
271
272	if (error == EOPNOTSUPP)
273		error = 0;				/* XXX */
274
275	return (error);
276}
277
278static int
279mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
280    struct label *intlabel)
281{
282	int error;
283
284	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
285
286	error = VOP_OPENEXTATTR(vp, cred, curthread);
287	if (error == EOPNOTSUPP) {
288		/* XXX: Optionally abort if transactions not supported. */
289		if (ea_warn_once == 0) {
290			printf("Warning: transactions not supported "
291			    "in EA write.\n");
292			ea_warn_once = 1;
293		}
294	} else if (error)
295		return (error);
296
297	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
298
299	if (error) {
300		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
301		return (error);
302	}
303
304	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
305
306	if (error == EOPNOTSUPP)
307		error = 0;				/* XXX */
308
309	return (error);
310}
311
312void
313mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
314    struct label *interpvnodelabel, struct image_params *imgp)
315{
316
317	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
318
319	if (!mac_enforce_process && !mac_enforce_fs)
320		return;
321
322	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
323	    interpvnodelabel, imgp, imgp->execlabel);
324}
325
326int
327mac_execve_will_transition(struct ucred *old, struct vnode *vp,
328    struct label *interpvnodelabel, struct image_params *imgp)
329{
330	int result;
331
332	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
333
334	if (!mac_enforce_process && !mac_enforce_fs)
335		return (0);
336
337	result = 0;
338	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
339	    interpvnodelabel, imgp, imgp->execlabel);
340
341	return (result);
342}
343
344int
345mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
346{
347	int error;
348
349	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
350
351	if (!mac_enforce_fs)
352		return (0);
353
354	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
355	return (error);
356}
357
358int
359mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
360{
361	int error;
362
363	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
364
365	if (!mac_enforce_fs)
366		return (0);
367
368	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
369	return (error);
370}
371
372int
373mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
374{
375	int error;
376
377	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
378
379	if (!mac_enforce_fs)
380		return (0);
381
382	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
383	return (error);
384}
385
386int
387mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
388    struct componentname *cnp, struct vattr *vap)
389{
390	int error;
391
392	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
393
394	if (!mac_enforce_fs)
395		return (0);
396
397	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
398	return (error);
399}
400
401int
402mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
403    struct componentname *cnp)
404{
405	int error;
406
407	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
408	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
409
410	if (!mac_enforce_fs)
411		return (0);
412
413	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
414	    &vp->v_label, cnp);
415	return (error);
416}
417
418int
419mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
420    acl_type_t type)
421{
422	int error;
423
424	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
425
426	if (!mac_enforce_fs)
427		return (0);
428
429	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
430	return (error);
431}
432
433int
434mac_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
435    int attrnamespace, const char *name)
436{
437	int error;
438
439	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteextattr");
440
441	if (!mac_enforce_fs)
442		return (0);
443
444	MAC_CHECK(check_vnode_deleteextattr, cred, vp, &vp->v_label,
445	    attrnamespace, name);
446	return (error);
447}
448
449int
450mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
451    struct image_params *imgp)
452{
453	int error;
454
455	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
456
457	if (!mac_enforce_process && !mac_enforce_fs)
458		return (0);
459
460	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
461	    imgp->execlabel);
462
463	return (error);
464}
465
466int
467mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
468{
469	int error;
470
471	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
472
473	if (!mac_enforce_fs)
474		return (0);
475
476	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
477	return (error);
478}
479
480int
481mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
482    int attrnamespace, const char *name, struct uio *uio)
483{
484	int error;
485
486	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
487
488	if (!mac_enforce_fs)
489		return (0);
490
491	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
492	    attrnamespace, name, uio);
493	return (error);
494}
495
496int
497mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
498    struct vnode *vp, struct componentname *cnp)
499{
500	int error;
501
502	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
503	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
504
505	if (!mac_enforce_fs)
506		return (0);
507
508	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
509	    &vp->v_label, cnp);
510	return (error);
511}
512
513int
514mac_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
515    int attrnamespace)
516{
517	int error;
518
519	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_listextattr");
520
521	if (!mac_enforce_fs)
522		return (0);
523
524	MAC_CHECK(check_vnode_listextattr, cred, vp, &vp->v_label,
525	    attrnamespace);
526	return (error);
527}
528
529int
530mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
531    struct componentname *cnp)
532{
533	int error;
534
535	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
536
537	if (!mac_enforce_fs)
538		return (0);
539
540	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
541	return (error);
542}
543
544int
545mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
546{
547	int error;
548
549	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
550
551	if (!mac_enforce_fs || !mac_enforce_vm)
552		return (0);
553
554	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
555	return (error);
556}
557
558void
559mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
560{
561	int result = *prot;
562
563	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
564
565	if (!mac_enforce_fs || !mac_enforce_vm)
566		return;
567
568	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
569	    &result);
570
571	*prot = result;
572}
573
574int
575mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
576{
577	int error;
578
579	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
580
581	if (!mac_enforce_fs || !mac_enforce_vm)
582		return (0);
583
584	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
585	return (error);
586}
587
588int
589mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
590{
591	int error;
592
593	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
594
595	if (!mac_enforce_fs)
596		return (0);
597
598	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
599	return (error);
600}
601
602int
603mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
604    struct vnode *vp)
605{
606	int error;
607
608	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
609
610	if (!mac_enforce_fs)
611		return (0);
612
613	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
614	    &vp->v_label);
615
616	return (error);
617}
618
619int
620mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
621    struct vnode *vp)
622{
623	int error;
624
625	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
626
627	if (!mac_enforce_fs)
628		return (0);
629
630	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
631	    &vp->v_label);
632
633	return (error);
634}
635
636int
637mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
638{
639	int error;
640
641	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
642
643	if (!mac_enforce_fs)
644		return (0);
645
646	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
647	return (error);
648}
649
650int
651mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
652{
653	int error;
654
655	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
656
657	if (!mac_enforce_fs)
658		return (0);
659
660	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
661	return (error);
662}
663
664static int
665mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
666    struct label *newlabel)
667{
668	int error;
669
670	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
671
672	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
673
674	return (error);
675}
676
677int
678mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
679    struct vnode *vp, struct componentname *cnp)
680{
681	int error;
682
683	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
684	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
685
686	if (!mac_enforce_fs)
687		return (0);
688
689	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
690	    &vp->v_label, cnp);
691	return (error);
692}
693
694int
695mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
696    struct vnode *vp, int samedir, struct componentname *cnp)
697{
698	int error;
699
700	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
701	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
702
703	if (!mac_enforce_fs)
704		return (0);
705
706	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
707	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
708	return (error);
709}
710
711int
712mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
713{
714	int error;
715
716	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
717
718	if (!mac_enforce_fs)
719		return (0);
720
721	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
722	return (error);
723}
724
725int
726mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
727    struct acl *acl)
728{
729	int error;
730
731	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
732
733	if (!mac_enforce_fs)
734		return (0);
735
736	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
737	return (error);
738}
739
740int
741mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
742    int attrnamespace, const char *name, struct uio *uio)
743{
744	int error;
745
746	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
747
748	if (!mac_enforce_fs)
749		return (0);
750
751	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
752	    attrnamespace, name, uio);
753	return (error);
754}
755
756int
757mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
758{
759	int error;
760
761	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
762
763	if (!mac_enforce_fs)
764		return (0);
765
766	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
767	return (error);
768}
769
770int
771mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
772{
773	int error;
774
775	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
776
777	if (!mac_enforce_fs)
778		return (0);
779
780	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
781	return (error);
782}
783
784int
785mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
786    gid_t gid)
787{
788	int error;
789
790	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
791
792	if (!mac_enforce_fs)
793		return (0);
794
795	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
796	return (error);
797}
798
799int
800mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
801    struct timespec atime, struct timespec mtime)
802{
803	int error;
804
805	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
806
807	if (!mac_enforce_fs)
808		return (0);
809
810	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
811	    mtime);
812	return (error);
813}
814
815int
816mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
817    struct vnode *vp)
818{
819	int error;
820
821	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
822
823	if (!mac_enforce_fs)
824		return (0);
825
826	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
827	    &vp->v_label);
828	return (error);
829}
830
831int
832mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
833    struct vnode *vp)
834{
835	int error;
836
837	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
838
839	if (!mac_enforce_fs)
840		return (0);
841
842	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
843	    &vp->v_label);
844
845	return (error);
846}
847
848void
849mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
850{
851
852	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
853}
854
855void
856mac_create_mount(struct ucred *cred, struct mount *mp)
857{
858
859	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
860	    &mp->mnt_fslabel);
861}
862
863void
864mac_create_root_mount(struct ucred *cred, struct mount *mp)
865{
866
867	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
868	    &mp->mnt_fslabel);
869}
870
871int
872mac_check_mount_stat(struct ucred *cred, struct mount *mount)
873{
874	int error;
875
876	if (!mac_enforce_fs)
877		return (0);
878
879	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
880
881	return (error);
882}
883
884void
885mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
886{
887
888	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
889}
890
891void
892mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
893    struct devfs_dirent *dd, struct devfs_dirent *de)
894{
895
896	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
897	    &de->de_label);
898}
899
900void
901mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
902    struct devfs_dirent *de)
903{
904
905	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
906	    &de->de_label);
907}
908
909/*
910 * Implementation of VOP_SETLABEL() that relies on extended attributes
911 * to store label data.  Can be referenced by filesystems supporting
912 * extended attributes.
913 */
914int
915vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
916{
917	struct vnode *vp = ap->a_vp;
918	struct label *intlabel = ap->a_label;
919	int error;
920
921	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
922
923	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
924		return (EOPNOTSUPP);
925
926	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
927	if (error)
928		return (error);
929
930	mac_relabel_vnode(ap->a_cred, vp, intlabel);
931
932	return (0);
933}
934
935int
936vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
937{
938	int error;
939
940	if (vp->v_mount == NULL) {
941		/* printf("vn_setlabel: null v_mount\n"); */
942		if (vp->v_type != VNON)
943			printf("vn_setlabel: null v_mount with non-VNON\n");
944		return (EBADF);
945	}
946
947	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
948		return (EOPNOTSUPP);
949
950	/*
951	 * Multi-phase commit.  First check the policies to confirm the
952	 * change is OK.  Then commit via the filesystem.  Finally,
953	 * update the actual vnode label.  Question: maybe the filesystem
954	 * should update the vnode at the end as part of VOP_SETLABEL()?
955	 */
956	error = mac_check_vnode_relabel(cred, vp, intlabel);
957	if (error)
958		return (error);
959
960	/*
961	 * VADMIN provides the opportunity for the filesystem to make
962	 * decisions about who is and is not able to modify labels
963	 * and protections on files.  This might not be right.  We can't
964	 * assume VOP_SETLABEL() will do it, because we might implement
965	 * that as part of vop_stdsetlabel_ea().
966	 */
967	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
968	if (error)
969		return (error);
970
971	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
972	if (error)
973		return (error);
974
975	return (0);
976}
977