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_impl(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_impl(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	if ((cnp->cn_flags & NOMACCHECK) != 0)
576		return (0);
577	MAC_POLICY_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
578	MAC_CHECK_PROBE3(vnode_check_lookup, error, cred, dvp, cnp);
579
580	return (error);
581}
582
583MAC_CHECK_PROBE_DEFINE4(vnode_check_mmap, "struct ucred *", "struct vnode *",
584    "int", "int");
585
586int
587mac_vnode_check_mmap_impl(struct ucred *cred, struct vnode *vp, int prot,
588    int flags)
589{
590	int error;
591
592	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap");
593
594	MAC_POLICY_CHECK(vnode_check_mmap, cred, vp, vp->v_label, prot, flags);
595	MAC_CHECK_PROBE4(vnode_check_mmap, error, cred, vp, prot, flags);
596
597	return (error);
598}
599
600void
601mac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
602    int *prot)
603{
604	int result = *prot;
605
606	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mmap_downgrade");
607
608	MAC_POLICY_PERFORM(vnode_check_mmap_downgrade, cred, vp, vp->v_label,
609	    &result);
610
611	*prot = result;
612}
613
614MAC_CHECK_PROBE_DEFINE3(vnode_check_mprotect, "struct ucred *",
615    "struct vnode *", "int");
616
617int
618mac_vnode_check_mprotect(struct ucred *cred, struct vnode *vp, int prot)
619{
620	int error;
621
622	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_mprotect");
623
624	MAC_POLICY_CHECK(vnode_check_mprotect, cred, vp, vp->v_label, prot);
625	MAC_CHECK_PROBE3(vnode_check_mprotect, error, cred, vp, prot);
626
627	return (error);
628}
629
630MAC_CHECK_PROBE_DEFINE3(vnode_check_open, "struct ucred *", "struct vnode *",
631    "accmode_t");
632
633int
634mac_vnode_check_open_impl(struct ucred *cred, struct vnode *vp, accmode_t accmode)
635{
636	int error;
637
638	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_open");
639
640	MAC_POLICY_CHECK(vnode_check_open, cred, vp, vp->v_label, accmode);
641	MAC_CHECK_PROBE3(vnode_check_open, error, cred, vp, accmode);
642
643	return (error);
644}
645
646MAC_CHECK_PROBE_DEFINE3(vnode_check_poll, "struct ucred *", "struct ucred *",
647    "struct vnode *");
648
649int
650mac_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
651    struct vnode *vp)
652{
653	int error;
654
655	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_poll");
656
657	MAC_POLICY_CHECK(vnode_check_poll, active_cred, file_cred, vp,
658	    vp->v_label);
659	MAC_CHECK_PROBE3(vnode_check_poll, error, active_cred, file_cred,
660	    vp);
661
662	return (error);
663}
664
665MAC_CHECK_PROBE_DEFINE3(vnode_check_read, "struct ucred *", "struct ucred *",
666    "struct vnode *");
667
668int
669mac_vnode_check_read_impl(struct ucred *active_cred, struct ucred *file_cred,
670    struct vnode *vp)
671{
672	int error;
673
674	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_read");
675
676	MAC_POLICY_CHECK(vnode_check_read, active_cred, file_cred, vp,
677	    vp->v_label);
678	MAC_CHECK_PROBE3(vnode_check_read, error, active_cred, file_cred,
679	    vp);
680
681	return (error);
682}
683
684MAC_CHECK_PROBE_DEFINE2(vnode_check_readdir, "struct ucred *",
685    "struct vnode *");
686
687int
688mac_vnode_check_readdir(struct ucred *cred, struct vnode *dvp)
689{
690	int error;
691
692	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_readdir");
693
694	MAC_POLICY_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
695	MAC_CHECK_PROBE2(vnode_check_readdir, error, cred, dvp);
696
697	return (error);
698}
699
700MAC_CHECK_PROBE_DEFINE2(vnode_check_readlink, "struct ucred *",
701    "struct vnode *");
702
703int
704mac_vnode_check_readlink_impl(struct ucred *cred, struct vnode *vp)
705{
706	int error;
707
708	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_readlink");
709
710	MAC_POLICY_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
711	MAC_CHECK_PROBE2(vnode_check_readlink, error, cred, vp);
712
713	return (error);
714}
715
716MAC_CHECK_PROBE_DEFINE3(vnode_check_relabel, "struct ucred *",
717    "struct vnode *", "struct label *");
718
719static int
720mac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
721    struct label *newlabel)
722{
723	int error;
724
725	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_relabel");
726
727	MAC_POLICY_CHECK(vnode_check_relabel, cred, vp, vp->v_label, newlabel);
728	MAC_CHECK_PROBE3(vnode_check_relabel, error, cred, vp, newlabel);
729
730	return (error);
731}
732
733MAC_CHECK_PROBE_DEFINE4(vnode_check_rename_from, "struct ucred *",
734    "struct vnode *", "struct vnode *", "struct componentname *");
735
736int
737mac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
738    struct vnode *vp, struct componentname *cnp)
739{
740	int error;
741
742	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_from");
743	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_from");
744
745	MAC_POLICY_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
746	    vp->v_label, cnp);
747	MAC_CHECK_PROBE4(vnode_check_rename_from, error, cred, dvp, vp, cnp);
748
749	return (error);
750}
751
752MAC_CHECK_PROBE_DEFINE4(vnode_check_rename_to, "struct ucred *",
753    "struct vnode *", "struct vnode *", "struct componentname *");
754
755int
756mac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
757    struct vnode *vp, int samedir, struct componentname *cnp)
758{
759	int error;
760
761	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_rename_to");
762	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_rename_to");
763
764	MAC_POLICY_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
765	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
766	MAC_CHECK_PROBE4(vnode_check_rename_to, error, cred, dvp, vp, cnp);
767	return (error);
768}
769
770MAC_CHECK_PROBE_DEFINE2(vnode_check_revoke, "struct ucred *",
771    "struct vnode *");
772
773int
774mac_vnode_check_revoke(struct ucred *cred, struct vnode *vp)
775{
776	int error;
777
778	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_revoke");
779
780	MAC_POLICY_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
781	MAC_CHECK_PROBE2(vnode_check_revoke, error, cred, vp);
782
783	return (error);
784}
785
786MAC_CHECK_PROBE_DEFINE4(vnode_check_setacl, "struct ucred *",
787    "struct vnode *", "acl_type_t", "struct acl *");
788
789int
790mac_vnode_check_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
791    struct acl *acl)
792{
793	int error;
794
795	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setacl");
796
797	MAC_POLICY_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
798	MAC_CHECK_PROBE4(vnode_check_setacl, error, cred, vp, type, acl);
799
800	return (error);
801}
802
803MAC_CHECK_PROBE_DEFINE4(vnode_check_setextattr, "struct ucred *",
804    "struct vnode *", "int", "const char *");
805
806int
807mac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
808    int attrnamespace, const char *name)
809{
810	int error;
811
812	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setextattr");
813
814	MAC_POLICY_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
815	    attrnamespace, name);
816	MAC_CHECK_PROBE4(vnode_check_setextattr, error, cred, vp,
817	    attrnamespace, name);
818
819	return (error);
820}
821
822MAC_CHECK_PROBE_DEFINE3(vnode_check_setflags, "struct ucred *",
823    "struct vnode *", "u_long");
824
825int
826mac_vnode_check_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
827{
828	int error;
829
830	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setflags");
831
832	MAC_POLICY_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
833	MAC_CHECK_PROBE3(vnode_check_setflags, error, cred, vp, flags);
834
835	return (error);
836}
837
838MAC_CHECK_PROBE_DEFINE3(vnode_check_setmode, "struct ucred *",
839    "struct vnode *", "mode_t");
840
841int
842mac_vnode_check_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
843{
844	int error;
845
846	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setmode");
847
848	MAC_POLICY_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
849	MAC_CHECK_PROBE3(vnode_check_setmode, error, cred, vp, mode);
850
851	return (error);
852}
853
854MAC_CHECK_PROBE_DEFINE4(vnode_check_setowner, "struct ucred *",
855    "struct vnode *", "uid_t", "gid_t");
856
857int
858mac_vnode_check_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
859    gid_t gid)
860{
861	int error;
862
863	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setowner");
864
865	MAC_POLICY_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
866	MAC_CHECK_PROBE4(vnode_check_setowner, error, cred, vp, uid, gid);
867
868	return (error);
869}
870
871MAC_CHECK_PROBE_DEFINE4(vnode_check_setutimes, "struct ucred *",
872    "struct vnode *", "struct timespec *", "struct timespec *");
873
874int
875mac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
876    struct timespec atime, struct timespec mtime)
877{
878	int error;
879
880	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_setutimes");
881
882	MAC_POLICY_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
883	    mtime);
884	MAC_CHECK_PROBE4(vnode_check_setutimes, error, cred, vp, &atime,
885	    &mtime);
886
887	return (error);
888}
889
890MAC_CHECK_PROBE_DEFINE3(vnode_check_stat, "struct ucred *", "struct ucred *",
891    "struct vnode *");
892
893int
894mac_vnode_check_stat_impl(struct ucred *active_cred, struct ucred *file_cred,
895    struct vnode *vp)
896{
897	int error;
898
899	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_stat");
900
901	MAC_POLICY_CHECK(vnode_check_stat, active_cred, file_cred, vp,
902	    vp->v_label);
903	MAC_CHECK_PROBE3(vnode_check_stat, error, active_cred, file_cred,
904	    vp);
905
906	return (error);
907}
908
909MAC_CHECK_PROBE_DEFINE4(vnode_check_unlink, "struct ucred *",
910    "struct vnode *", "struct vnode *", "struct componentname *");
911
912int
913mac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
914    struct vnode *vp, struct componentname *cnp)
915{
916	int error;
917
918	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_unlink");
919	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_unlink");
920
921	MAC_POLICY_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
922	    vp->v_label, cnp);
923	MAC_CHECK_PROBE4(vnode_check_unlink, error, cred, dvp, vp, cnp);
924
925	return (error);
926}
927
928MAC_CHECK_PROBE_DEFINE3(vnode_check_write, "struct ucred *",
929    "struct ucred *", "struct vnode *");
930
931int
932mac_vnode_check_write_impl(struct ucred *active_cred, struct ucred *file_cred,
933    struct vnode *vp)
934{
935	int error;
936
937	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_write");
938
939	MAC_POLICY_CHECK(vnode_check_write, active_cred, file_cred, vp,
940	    vp->v_label);
941	MAC_CHECK_PROBE3(vnode_check_write, error, active_cred, file_cred,
942	    vp);
943
944	return (error);
945}
946
947void
948mac_vnode_relabel(struct ucred *cred, struct vnode *vp,
949    struct label *newlabel)
950{
951
952	MAC_POLICY_PERFORM(vnode_relabel, cred, vp, vp->v_label, newlabel);
953}
954
955void
956mac_mount_create(struct ucred *cred, struct mount *mp)
957{
958
959	MAC_POLICY_PERFORM(mount_create, cred, mp, mp->mnt_label);
960}
961
962MAC_CHECK_PROBE_DEFINE2(mount_check_stat, "struct ucred *",
963    "struct mount *");
964
965int
966mac_mount_check_stat(struct ucred *cred, struct mount *mount)
967{
968	int error;
969
970	MAC_POLICY_CHECK_NOSLEEP(mount_check_stat, cred, mount, mount->mnt_label);
971	MAC_CHECK_PROBE2(mount_check_stat, error, cred, mount);
972
973	return (error);
974}
975
976void
977mac_devfs_create_device(struct ucred *cred, struct mount *mp,
978    struct cdev *dev, struct devfs_dirent *de)
979{
980
981	MAC_POLICY_PERFORM_NOSLEEP(devfs_create_device, cred, mp, dev, de,
982	    de->de_label);
983}
984
985void
986mac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
987    struct devfs_dirent *dd, struct devfs_dirent *de)
988{
989
990	MAC_POLICY_PERFORM_NOSLEEP(devfs_create_symlink, cred, mp, dd,
991	    dd->de_label, de, de->de_label);
992}
993
994void
995mac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
996    struct devfs_dirent *de)
997{
998
999	MAC_POLICY_PERFORM_NOSLEEP(devfs_create_directory, mp, dirname,
1000	    dirnamelen, de, de->de_label);
1001}
1002
1003/*
1004 * Implementation of VOP_SETLABEL() that relies on extended attributes to
1005 * store label data.  Can be referenced by filesystems supporting extended
1006 * attributes.
1007 */
1008int
1009vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
1010{
1011	struct vnode *vp = ap->a_vp;
1012	struct label *intlabel = ap->a_label;
1013	int error;
1014
1015	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
1016
1017	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1018		return (EOPNOTSUPP);
1019
1020	error = mac_vnode_setlabel_extattr(ap->a_cred, vp, intlabel);
1021	if (error)
1022		return (error);
1023
1024	mac_vnode_relabel(ap->a_cred, vp, intlabel);
1025
1026	return (0);
1027}
1028
1029int
1030vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
1031{
1032	int error;
1033
1034	if (vp->v_mount == NULL) {
1035		/* printf("vn_setlabel: null v_mount\n"); */
1036		if (vp->v_type != VNON)
1037			printf("vn_setlabel: null v_mount with non-VNON\n");
1038		return (EBADF);
1039	}
1040
1041	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1042		return (EOPNOTSUPP);
1043
1044	/*
1045	 * Multi-phase commit.  First check the policies to confirm the
1046	 * change is OK.  Then commit via the filesystem.  Finally, update
1047	 * the actual vnode label.
1048	 *
1049	 * Question: maybe the filesystem should update the vnode at the end
1050	 * as part of VOP_SETLABEL()?
1051	 */
1052	error = mac_vnode_check_relabel(cred, vp, intlabel);
1053	if (error)
1054		return (error);
1055
1056	/*
1057	 * VADMIN provides the opportunity for the filesystem to make
1058	 * decisions about who is and is not able to modify labels and
1059	 * protections on files.  This might not be right.  We can't assume
1060	 * VOP_SETLABEL() will do it, because we might implement that as part
1061	 * of vop_stdsetlabel_ea().
1062	 */
1063	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
1064	if (error)
1065		return (error);
1066
1067	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1068	if (error)
1069		return (error);
1070
1071	return (0);
1072}
1073
1074#ifdef DEBUG_VFS_LOCKS
1075void
1076mac_vnode_assert_locked(struct vnode *vp, const char *func)
1077{
1078
1079	ASSERT_VOP_LOCKED(vp, func);
1080}
1081#endif
1082