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