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#include "opt_mac.h"
47
48#include <sys/param.h>
49#include <sys/condvar.h>
50#include <sys/extattr.h>
51#include <sys/imgact.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
55#include <sys/mutex.h>
56#include <sys/proc.h>
57#include <sys/sbuf.h>
58#include <sys/systm.h>
59#include <sys/vnode.h>
60#include <sys/mount.h>
61#include <sys/file.h>
62#include <sys/namei.h>
63#include <sys/sdt.h>
64#include <sys/sysctl.h>
65
66#include <vm/vm.h>
67#include <vm/pmap.h>
68#include <vm/vm_map.h>
69#include <vm/vm_object.h>
70
71#include <fs/devfs/devfs.h>
72
73#include <security/mac/mac_framework.h>
74#include <security/mac/mac_internal.h>
75#include <security/mac/mac_policy.h>
76
77/*
78 * Warn about EA transactions only the first time they happen.  No locking on
79 * this variable.
80 */
81static int	ea_warn_once = 0;
82
83static int	mac_vnode_setlabel_extattr(struct ucred *cred,
84		    struct vnode *vp, struct label *intlabel);
85
86static struct label *
87mac_devfs_label_alloc(void)
88{
89	struct label *label;
90
91	label = mac_labelzone_alloc(M_WAITOK);
92	MAC_POLICY_PERFORM(devfs_init_label, label);
93	return (label);
94}
95
96void
97mac_devfs_init(struct devfs_dirent *de)
98{
99
100	if (mac_labeled & MPC_OBJECT_DEVFS)
101		de->de_label = mac_devfs_label_alloc();
102	else
103		de->de_label = NULL;
104}
105
106static struct label *
107mac_mount_label_alloc(void)
108{
109	struct label *label;
110
111	label = mac_labelzone_alloc(M_WAITOK);
112	MAC_POLICY_PERFORM(mount_init_label, label);
113	return (label);
114}
115
116void
117mac_mount_init(struct mount *mp)
118{
119
120	if (mac_labeled & MPC_OBJECT_MOUNT)
121		mp->mnt_label = mac_mount_label_alloc();
122	else
123		mp->mnt_label = NULL;
124}
125
126struct label *
127mac_vnode_label_alloc(void)
128{
129	struct label *label;
130
131	label = mac_labelzone_alloc(M_WAITOK);
132	MAC_POLICY_PERFORM(vnode_init_label, label);
133	return (label);
134}
135
136void
137mac_vnode_init(struct vnode *vp)
138{
139
140	if (mac_labeled & MPC_OBJECT_VNODE)
141		vp->v_label = mac_vnode_label_alloc();
142	else
143		vp->v_label = NULL;
144}
145
146static void
147mac_devfs_label_free(struct label *label)
148{
149
150	MAC_POLICY_PERFORM_NOSLEEP(devfs_destroy_label, label);
151	mac_labelzone_free(label);
152}
153
154void
155mac_devfs_destroy(struct devfs_dirent *de)
156{
157
158	if (de->de_label != NULL) {
159		mac_devfs_label_free(de->de_label);
160		de->de_label = NULL;
161	}
162}
163
164static void
165mac_mount_label_free(struct label *label)
166{
167
168	MAC_POLICY_PERFORM_NOSLEEP(mount_destroy_label, label);
169	mac_labelzone_free(label);
170}
171
172void
173mac_mount_destroy(struct mount *mp)
174{
175
176	if (mp->mnt_label != NULL) {
177		mac_mount_label_free(mp->mnt_label);
178		mp->mnt_label = NULL;
179	}
180}
181
182void
183mac_vnode_label_free(struct label *label)
184{
185
186	MAC_POLICY_PERFORM_NOSLEEP(vnode_destroy_label, label);
187	mac_labelzone_free(label);
188}
189
190void
191mac_vnode_destroy(struct vnode *vp)
192{
193
194	if (vp->v_label != NULL) {
195		mac_vnode_label_free(vp->v_label);
196		vp->v_label = NULL;
197	}
198}
199
200void
201mac_vnode_copy_label(struct label *src, struct label *dest)
202{
203
204	MAC_POLICY_PERFORM_NOSLEEP(vnode_copy_label, src, dest);
205}
206
207int
208mac_vnode_externalize_label(struct label *label, char *elements,
209    char *outbuf, size_t outbuflen)
210{
211	int error;
212
213	MAC_POLICY_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
214
215	return (error);
216}
217
218int
219mac_vnode_internalize_label(struct label *label, char *string)
220{
221	int error;
222
223	MAC_POLICY_INTERNALIZE(vnode, label, string);
224
225	return (error);
226}
227
228void
229mac_devfs_update(struct mount *mp, struct devfs_dirent *de, struct vnode *vp)
230{
231
232	MAC_POLICY_PERFORM_NOSLEEP(devfs_update, mp, de, de->de_label, vp,
233	    vp->v_label);
234}
235
236void
237mac_devfs_vnode_associate(struct mount *mp, struct devfs_dirent *de,
238    struct vnode *vp)
239{
240
241	MAC_POLICY_PERFORM_NOSLEEP(devfs_vnode_associate, mp, mp->mnt_label,
242	    de, de->de_label, vp, vp->v_label);
243}
244
245int
246mac_vnode_associate_extattr(struct mount *mp, struct vnode *vp)
247{
248	int error;
249
250	ASSERT_VOP_LOCKED(vp, "mac_vnode_associate_extattr");
251
252	MAC_POLICY_CHECK(vnode_associate_extattr, mp, mp->mnt_label, vp,
253	    vp->v_label);
254
255	return (error);
256}
257
258void
259mac_vnode_associate_singlelabel(struct mount *mp, struct vnode *vp)
260{
261
262	MAC_POLICY_PERFORM_NOSLEEP(vnode_associate_singlelabel, mp,
263	    mp->mnt_label, vp, vp->v_label);
264}
265
266/*
267 * Functions implementing extended-attribute backed labels for file systems
268 * that support it.
269 *
270 * Where possible, we use EA transactions to make writes to multiple
271 * attributes across difference policies mutually atomic.  We allow work to
272 * continue on file systems not supporting EA transactions, but generate a
273 * printf warning.
274 */
275int
276mac_vnode_create_extattr(struct ucred *cred, struct mount *mp,
277    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
278{
279	int error;
280
281	ASSERT_VOP_LOCKED(dvp, "mac_vnode_create_extattr");
282	ASSERT_VOP_LOCKED(vp, "mac_vnode_create_extattr");
283
284	error = VOP_OPENEXTATTR(vp, cred, curthread);
285	if (error == EOPNOTSUPP) {
286		if (ea_warn_once == 0) {
287			printf("Warning: transactions not supported "
288			    "in EA write.\n");
289			ea_warn_once = 1;
290		}
291	} else if (error)
292		return (error);
293
294	MAC_POLICY_CHECK(vnode_create_extattr, cred, mp, mp->mnt_label, dvp,
295	    dvp->v_label, vp, vp->v_label, cnp);
296
297	if (error) {
298		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
299		return (error);
300	}
301
302	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
303	if (error == EOPNOTSUPP)
304		error = 0;
305
306	return (error);
307}
308
309static int
310mac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
311    struct label *intlabel)
312{
313	int error;
314
315	ASSERT_VOP_LOCKED(vp, "mac_vnode_setlabel_extattr");
316
317	error = VOP_OPENEXTATTR(vp, cred, curthread);
318	if (error == EOPNOTSUPP) {
319		if (ea_warn_once == 0) {
320			printf("Warning: transactions not supported "
321			    "in EA write.\n");
322			ea_warn_once = 1;
323		}
324	} else if (error)
325		return (error);
326
327	MAC_POLICY_CHECK(vnode_setlabel_extattr, cred, vp, vp->v_label,
328	    intlabel);
329
330	if (error) {
331		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
332		return (error);
333	}
334
335	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
336	if (error == EOPNOTSUPP)
337		error = 0;
338
339	return (error);
340}
341
342void
343mac_vnode_execve_transition(struct ucred *old, struct ucred *new,
344    struct vnode *vp, struct label *interpvplabel, struct image_params *imgp)
345{
346
347	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_transition");
348
349	MAC_POLICY_PERFORM(vnode_execve_transition, old, new, vp,
350	    vp->v_label, interpvplabel, imgp, imgp->execlabel);
351}
352
353int
354mac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
355    struct label *interpvplabel, struct image_params *imgp)
356{
357	int result;
358
359	ASSERT_VOP_LOCKED(vp, "mac_vnode_execve_will_transition");
360
361	result = 0;
362	/* No sleeping since the process lock will be held by the caller. */
363	MAC_POLICY_BOOLEAN_NOSLEEP(vnode_execve_will_transition, ||, old, vp,
364	    vp->v_label, 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_impl(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_POLICY_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_POLICY_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_POLICY_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_POLICY_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp,
429	    vap);
430	MAC_CHECK_PROBE4(vnode_check_create, error, cred, dvp, cnp, vap);
431
432	return (error);
433}
434
435MAC_CHECK_PROBE_DEFINE3(vnode_check_deleteacl, "struct ucred *",
436    "struct vnode *", "acl_type_t");
437
438int
439mac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
440    acl_type_t type)
441{
442	int error;
443
444	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteacl");
445
446	MAC_POLICY_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
447	MAC_CHECK_PROBE3(vnode_check_deleteacl, error, cred, vp, type);
448
449	return (error);
450}
451
452MAC_CHECK_PROBE_DEFINE4(vnode_check_deleteextattr, "struct ucred *",
453    "struct vnode *", "int", "const char *");
454
455int
456mac_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
457    int attrnamespace, const char *name)
458{
459	int error;
460
461	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_deleteextattr");
462
463	MAC_POLICY_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label,
464	    attrnamespace, name);
465	MAC_CHECK_PROBE4(vnode_check_deleteextattr, error, cred, vp,
466	    attrnamespace, name);
467
468	return (error);
469}
470
471MAC_CHECK_PROBE_DEFINE3(vnode_check_exec, "struct ucred *", "struct vnode *",
472    "struct image_params *");
473
474int
475mac_vnode_check_exec(struct ucred *cred, struct vnode *vp,
476    struct image_params *imgp)
477{
478	int error;
479
480	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_exec");
481
482	MAC_POLICY_CHECK(vnode_check_exec, cred, vp, vp->v_label, imgp,
483	    imgp->execlabel);
484	MAC_CHECK_PROBE3(vnode_check_exec, error, cred, vp, imgp);
485
486	return (error);
487}
488
489MAC_CHECK_PROBE_DEFINE3(vnode_check_getacl, "struct ucred *",
490    "struct vnode *", "acl_type_t");
491
492int
493mac_vnode_check_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
494{
495	int error;
496
497	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getacl");
498
499	MAC_POLICY_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
500	MAC_CHECK_PROBE3(vnode_check_getacl, error, cred, vp, type);
501
502	return (error);
503}
504
505MAC_CHECK_PROBE_DEFINE4(vnode_check_getextattr, "struct ucred *",
506    "struct vnode *", "int", "const char *");
507
508int
509mac_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
510    int attrnamespace, const char *name)
511{
512	int error;
513
514	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_getextattr");
515
516	MAC_POLICY_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
517	    attrnamespace, name);
518	MAC_CHECK_PROBE4(vnode_check_getextattr, error, cred, vp,
519	    attrnamespace, name);
520
521	return (error);
522}
523
524MAC_CHECK_PROBE_DEFINE4(vnode_check_link, "struct ucred *", "struct vnode *",
525    "struct vnode *", "struct componentname *");
526
527int
528mac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
529    struct vnode *vp, struct componentname *cnp)
530{
531	int error;
532
533	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_link");
534	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_link");
535
536	MAC_POLICY_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
537	    vp->v_label, cnp);
538	MAC_CHECK_PROBE4(vnode_check_link, error, cred, dvp, vp, cnp);
539
540	return (error);
541}
542
543MAC_CHECK_PROBE_DEFINE3(vnode_check_listextattr, "struct ucred *",
544    "struct vnode *", "int");
545
546int
547mac_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
548    int attrnamespace)
549{
550	int error;
551
552	ASSERT_VOP_LOCKED(vp, "mac_vnode_check_listextattr");
553
554	MAC_POLICY_CHECK(vnode_check_listextattr, cred, vp, vp->v_label,
555	    attrnamespace);
556	MAC_CHECK_PROBE3(vnode_check_listextattr, error, cred, vp,
557	    attrnamespace);
558
559	return (error);
560}
561
562MAC_CHECK_PROBE_DEFINE3(vnode_check_lookup, "struct ucred *",
563    "struct vnode *", "struct componentname *");
564
565int
566mac_vnode_check_lookup_impl(struct ucred *cred, struct vnode *dvp,
567    struct componentname *cnp)
568{
569	int error;
570
571	ASSERT_VOP_LOCKED(dvp, "mac_vnode_check_lookup");
572
573	if ((cnp->cn_flags & NOMACCHECK) != 0)
574		return (0);
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_impl(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_impl(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_impl(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_impl(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_impl(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_impl(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	/*
1023	 * XXXRW: See the comment below in vn_setlabel() as to why this might
1024	 * be the wrong place to call mac_vnode_relabel().
1025	 */
1026	mac_vnode_relabel(ap->a_cred, vp, intlabel);
1027
1028	return (0);
1029}
1030
1031int
1032vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
1033{
1034	int error;
1035
1036	if (vp->v_mount == NULL) {
1037		/* printf("vn_setlabel: null v_mount\n"); */
1038		if (vp->v_type != VNON)
1039			printf("vn_setlabel: null v_mount with non-VNON\n");
1040		return (EBADF);
1041	}
1042
1043	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1044		return (EOPNOTSUPP);
1045
1046	/*
1047	 * Multi-phase commit.  First check the policies to confirm the
1048	 * change is OK.  Then commit via the filesystem.  Finally, update
1049	 * the actual vnode label.
1050	 */
1051	error = mac_vnode_check_relabel(cred, vp, intlabel);
1052	if (error)
1053		return (error);
1054
1055	/*
1056	 * VADMIN provides the opportunity for the filesystem to make
1057	 * decisions about who is and is not able to modify labels and
1058	 * protections on files.  This might not be right.  We can't assume
1059	 * VOP_SETLABEL() will do it, because we might implement that as part
1060	 * of vop_stdsetlabel_ea().
1061	 */
1062	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
1063	if (error)
1064		return (error);
1065
1066	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
1067	if (error)
1068		return (error);
1069
1070	/*
1071	 * It would be more symmetric if mac_vnode_relabel() was called here
1072	 * rather than in VOP_SETLABEL(), but we don't for historical reasons.
1073	 * We should think about moving it so that the filesystem is
1074	 * responsible only for persistence in VOP_SETLABEL(), not the vnode
1075	 * label update itself.
1076	 */
1077
1078	return (0);
1079}
1080
1081#ifdef DEBUG_VFS_LOCKS
1082void
1083mac_vnode_assert_locked(struct vnode *vp, const char *func)
1084{
1085
1086	ASSERT_VOP_LOCKED(vp, func);
1087}
1088#endif
1089