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