1/*
2 * Copyright (c) 2007 Apple Inc. All rights reserved.
3 *
4 * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5 *
6 * This file contains Original Code and/or Modifications of Original Code
7 * as defined in and that are subject to the Apple Public Source License
8 * Version 2.0 (the 'License'). You may not use this file except in
9 * compliance with the License. The rights granted to you under the License
10 * may not be used to create, or enable the creation or redistribution of,
11 * unlawful or unlicensed copies of an Apple operating system, or to
12 * circumvent, violate, or enable the circumvention or violation of, any
13 * terms of an Apple operating system software license agreement.
14 *
15 * Please obtain a copy of the License at
16 * http://www.opensource.apple.com/apsl/ and read it before using this file.
17 *
18 * The Original Code and all software distributed under the License are
19 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20 * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21 * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22 * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23 * Please see the License for the specific language governing rights and
24 * limitations under the License.
25 *
26 * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27 */
28/*-
29 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
30 * Copyright (c) 2001 Ilmar S. Habibulin
31 * Copyright (c) 2001, 2002, 2003, 2004 Networks Associates Technology, Inc.
32 * Copyright (c) 2005 SPARTA, Inc.
33 *
34 * This software was developed by Robert Watson and Ilmar Habibulin for the
35 * TrustedBSD Project.
36 *
37 * This software was developed for the FreeBSD Project in part by Network
38 * Associates Laboratories, the Security Research Division of Network
39 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
40 * as part of the DARPA CHATS research program.
41 *
42 * Redistribution and use in source and binary forms, with or without
43 * modification, are permitted provided that the following conditions
44 * are met:
45 * 1. Redistributions of source code must retain the above copyright
46 *    notice, this list of conditions and the following disclaimer.
47 * 2. Redistributions in binary form must reproduce the above copyright
48 *    notice, this list of conditions and the following disclaimer in the
49 *    documentation and/or other materials provided with the distribution.
50 *
51 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
52 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
53 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
54 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
55 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
56 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
57 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
58 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
59 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
60 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
61 * SUCH DAMAGE.
62 *
63 */
64
65#include <sys/param.h>
66#include <sys/systm.h>
67#include <sys/kernel.h>
68#include <sys/proc.h>
69#include <sys/kauth.h>
70
71#include <sys/file_internal.h>
72#include <sys/imgact.h>
73#include <sys/namei.h>
74#include <sys/mount_internal.h>
75#include <sys/pipe.h>
76#include <sys/posix_sem.h>
77#include <sys/posix_shm.h>
78#include <sys/uio_internal.h>
79#include <sys/vnode_internal.h>
80
81#include <miscfs/devfs/devfsdefs.h>
82#include <miscfs/devfs/fdesc.h>
83
84#include <security/mac_internal.h>
85
86/* convert {R,W,X}_OK values to V{READ,WRITE,EXEC} */
87#define	ACCESS_MODE_TO_VNODE_MASK(m)	(m << 6)
88
89static struct label *
90mac_devfsdirent_label_alloc(void)
91{
92	struct label *label;
93
94	label = mac_labelzone_alloc(MAC_WAITOK);
95	if (label == NULL)
96		return (NULL);
97	MAC_PERFORM(devfs_label_init, label);
98	return (label);
99}
100
101void
102mac_devfs_label_init(struct devnode *de)
103{
104
105	de->dn_label = mac_devfsdirent_label_alloc();
106}
107
108static struct label *
109mac_mount_label_alloc(void)
110{
111	struct label *label;
112
113	label = mac_labelzone_alloc(MAC_WAITOK);
114	if (label == NULL)
115		return (NULL);
116	MAC_PERFORM(mount_label_init, label);
117	return (label);
118}
119
120void
121mac_mount_label_init(struct mount *mp)
122{
123
124	mp->mnt_mntlabel = mac_mount_label_alloc();
125}
126
127struct label *
128mac_vnode_label_alloc(void)
129{
130	struct label *label;
131
132	label = mac_labelzone_alloc(MAC_WAITOK);
133	if (label == NULL)
134		return (NULL);
135	MAC_PERFORM(vnode_label_init, label);
136	return (label);
137}
138
139void
140mac_vnode_label_init(vnode_t vp)
141{
142	vp->v_label = mac_vnode_label_alloc();
143}
144
145int
146mac_vnode_label_init_needed(vnode_t vp)
147{
148	return (mac_label_vnodes != 0 && vp->v_label == NULL);
149}
150
151/*
152 * vnode labels are allocated at the same time as vnodes, but vnodes are never
153 * freed.  Instead, we want to remove any sensitive information before putting
154 * them on the free list for reuse.
155*/
156void
157mac_vnode_label_recycle(vnode_t vp)
158{
159
160	MAC_PERFORM(vnode_label_recycle, vp->v_label);
161}
162
163static void
164mac_devfs_label_free(struct label *label)
165{
166	MAC_PERFORM(devfs_label_destroy, label);
167	mac_labelzone_free(label);
168}
169
170void
171mac_devfs_label_destroy(struct devnode *de)
172{
173	if (de->dn_label != NULL) {
174		mac_devfs_label_free(de->dn_label);
175		de->dn_label = NULL;
176	}
177}
178
179static void
180mac_mount_label_free(struct label *label)
181{
182
183	MAC_PERFORM(mount_label_destroy, label);
184	mac_labelzone_free(label);
185}
186
187void
188mac_mount_label_destroy(struct mount *mp)
189{
190	if (mp->mnt_mntlabel != NULL) {
191		mac_mount_label_free(mp->mnt_mntlabel);
192		mp->mnt_mntlabel = NULL;
193	}
194}
195
196void
197mac_vnode_label_free(struct label *label)
198{
199	MAC_PERFORM(vnode_label_destroy, label);
200	mac_labelzone_free(label);
201}
202
203#ifndef __APPLE__
204void
205mac_vnode_label_destroy(struct vnode *vp)
206{
207	if (vp->v_label != NULL) {
208		mac_vnode_label_free(vp->v_label);
209		vp->v_label = NULL;
210	}
211}
212#endif
213
214void
215mac_vnode_label_copy(struct label *src, struct label *dest)
216{
217	if (src == NULL) {
218		MAC_PERFORM(vnode_label_init, dest);
219	} else {
220		MAC_PERFORM(vnode_label_copy, src, dest);
221	}
222}
223
224int
225mac_vnode_label_externalize_audit(struct vnode *vp, struct mac *mac)
226{
227	int error;
228
229	/* It is assumed that any necessary vnode locking is done on entry */
230	error = MAC_EXTERNALIZE_AUDIT(vnode, vp->v_label,
231	    mac->m_string, mac->m_buflen);
232
233	return (error);
234}
235
236int
237mac_vnode_label_externalize(struct label *label, char *elements,
238    char *outbuf, size_t outbuflen, int flags __unused)
239{
240	int error;
241
242	error = MAC_EXTERNALIZE(vnode, label, elements, outbuf, outbuflen);
243
244	return (error);
245}
246
247int
248mac_vnode_label_internalize(struct label *label, char *string)
249{
250	int error;
251
252	error = MAC_INTERNALIZE(vnode, label, string);
253
254	return (error);
255}
256
257int
258mac_mount_label_internalize(struct label *label, char *string)
259{
260	int error;
261
262	error = MAC_INTERNALIZE(mount, label, string);
263
264	return (error);
265}
266
267int
268mac_mount_label_externalize(struct label *label, char *elements,
269    char *outbuf, size_t outbuflen)
270{
271	int error;
272
273	error = MAC_EXTERNALIZE(mount, label, elements, outbuf, outbuflen);
274
275	return (error);
276}
277
278void
279mac_devfs_label_copy(struct label *src, struct label *dest)
280{
281	if (!mac_device_enforce)
282		return;
283
284	MAC_PERFORM(devfs_label_copy, src, dest);
285}
286
287void
288mac_devfs_label_update(struct mount *mp, struct devnode *de,
289    struct vnode *vp)
290{
291
292	if (!mac_device_enforce)
293		return;
294
295	MAC_PERFORM(devfs_label_update, mp, de, de->dn_label, vp,
296	    vp->v_label);
297}
298
299int
300mac_vnode_label_associate(struct mount *mp, struct vnode *vp, vfs_context_t ctx)
301{
302	struct devnode *dnp;
303	struct fdescnode *fnp;
304	int error = 0;
305
306	if (!mac_vnode_enforce)
307		return (error);
308
309	/* XXX: should not inspect v_tag in kernel! */
310	switch (vp->v_tag) {
311	case VT_DEVFS:
312		dnp = VTODN(vp);
313		mac_vnode_label_associate_devfs(mp, dnp, vp);
314		break;
315	case VT_FDESC:
316		fnp = VTOFDESC(vp);
317		error = mac_vnode_label_associate_fdesc(mp, fnp, vp, ctx);
318		break;
319	default:
320		error = mac_vnode_label_associate_extattr(mp, vp);
321		break;
322	}
323
324	return (error);
325}
326
327void
328mac_vnode_label_associate_devfs(struct mount *mp, struct devnode *de,
329    struct vnode *vp)
330{
331	if (!mac_device_enforce)
332		return;
333
334	MAC_PERFORM(vnode_label_associate_devfs,
335	    mp, mp ? mp->mnt_mntlabel : NULL,
336	    de, de->dn_label,
337	    vp, vp->v_label);
338}
339
340int
341mac_vnode_label_associate_extattr(struct mount *mp, struct vnode *vp)
342{
343	int error;
344
345	MAC_CHECK(vnode_label_associate_extattr, mp, mp->mnt_mntlabel, vp,
346	    vp->v_label);
347
348	return (error);
349}
350
351void
352mac_vnode_label_associate_singlelabel(struct mount *mp, struct vnode *vp)
353{
354
355	if (!mac_vnode_enforce || !mac_label_vnodes)
356		return;
357
358	MAC_PERFORM(vnode_label_associate_singlelabel, mp,
359	    mp ? mp->mnt_mntlabel : NULL, vp, vp->v_label);
360}
361
362int
363mac_vnode_notify_create(vfs_context_t ctx, struct mount *mp,
364    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
365{
366	kauth_cred_t cred;
367	int error;
368
369	if (!mac_vnode_enforce ||
370		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
371		return (0);
372
373	cred = vfs_context_ucred(ctx);
374	MAC_CHECK(vnode_notify_create, cred, mp, mp->mnt_mntlabel,
375	    dvp, dvp->v_label, vp, vp->v_label, cnp);
376
377	return (error);
378}
379
380void
381mac_vnode_notify_rename(vfs_context_t ctx, struct vnode *vp,
382    struct vnode *dvp, struct componentname *cnp)
383{
384	kauth_cred_t cred;
385
386	if (!mac_vnode_enforce ||
387		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
388		return;
389
390	cred = vfs_context_ucred(ctx);
391	MAC_PERFORM(vnode_notify_rename, cred, vp, vp->v_label,
392	    dvp, dvp->v_label, cnp);
393}
394
395void
396mac_vnode_notify_open(vfs_context_t ctx, struct vnode *vp, int acc_flags)
397{
398	kauth_cred_t cred;
399
400	if (!mac_vnode_enforce ||
401		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
402		return;
403
404	cred = vfs_context_ucred(ctx);
405	MAC_PERFORM(vnode_notify_open, cred, vp, vp->v_label, acc_flags);
406}
407
408void
409mac_vnode_notify_link(vfs_context_t ctx, struct vnode *vp,
410		      struct vnode *dvp, struct componentname *cnp)
411{
412	kauth_cred_t cred;
413
414	if (!mac_vnode_enforce ||
415		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
416		return;
417
418	cred = vfs_context_ucred(ctx);
419	MAC_PERFORM(vnode_notify_link, cred, dvp, dvp->v_label, vp, vp->v_label, cnp);
420}
421
422/*
423 * Extended attribute 'name' was updated via
424 * vn_setxattr() or vn_removexattr().  Allow the
425 * policy to update the vnode label.
426 */
427void
428mac_vnode_label_update_extattr(struct mount *mp, struct vnode *vp,
429    const char *name)
430{
431	int error = 0;
432
433	if (!mac_vnode_enforce || !mac_label_vnodes)
434		return;
435
436	MAC_PERFORM(vnode_label_update_extattr, mp, mp->mnt_mntlabel, vp,
437		    vp->v_label, name);
438	if (error == 0)
439		return;
440
441	vnode_lock(vp);
442	vnode_relabel(vp);
443	vnode_unlock(vp);
444	return;
445}
446
447static int
448mac_vnode_label_store(vfs_context_t ctx, struct vnode *vp,
449    struct label *intlabel)
450{
451	kauth_cred_t cred;
452	int error;
453
454	if (!mac_vnode_enforce || !mac_label_vnodes ||
455	    !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
456		return 0;
457
458	cred = vfs_context_ucred(ctx);
459	MAC_CHECK(vnode_label_store, cred, vp, vp->v_label, intlabel);
460
461	return (error);
462}
463
464void
465mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp, off_t offset,
466	struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl, u_int *csflags,
467	void *macextensions, int *disjoint, int *labelupdateerror)
468{
469	kauth_cred_t cred;
470	*disjoint = 0;
471	int error;
472	posix_cred_t pcred = posix_cred_get(new);
473
474	if (!mac_proc_enforce && !mac_vnode_enforce)
475		return;
476
477	/* mark the new cred to indicate "matching" includes the label */
478	pcred->cr_flags |= CRF_MAC_ENFORCE;
479
480	cred = vfs_context_ucred(ctx);
481
482	/*
483	 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
484	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
485	 *     spawnattrlen as an argument to the hook.
486	 */
487	{
488		struct mac_policy_conf *mpc;
489		u_int i;
490
491		error = 0;
492		for (i = 0; i< mac_policy_list.staticmax; i++) {
493			mpc = mac_policy_list.entries[i].mpc;
494			if (mpc == NULL)
495				continue;
496
497			mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
498			if (hook == NULL)
499				continue;
500
501			size_t spawnattrlen = 0;
502			void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
503
504			error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
505						 vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
506						 error);
507		}
508		if (mac_policy_list_conditional_busy() != 0) {
509			for (; i <= mac_policy_list.maxindex; i++) {
510				mpc = mac_policy_list.entries[i].mpc;
511				if (mpc == NULL)
512					continue;
513
514				mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
515				if (hook == NULL)
516					continue;
517
518				size_t spawnattrlen = 0;
519				void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
520
521				error = mac_error_select(hook(cred, new, vfs_context_proc(ctx), vp, offset, scriptvp,
522						     vp->v_label, scriptvnodelabel, execl, csflags, spawnattr, spawnattrlen, disjoint),
523							 error);
524			}
525			mac_policy_list_unbusy();
526		}
527	}
528	*labelupdateerror = error;
529}
530
531int
532mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp, off_t offset,
533	struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
534	struct proc *p, void *macextensions)
535{
536	kauth_cred_t cred;
537	int result = 0;
538
539	if (!mac_proc_enforce && !mac_vnode_enforce)
540		return result;
541
542	cred = vfs_context_ucred(ctx);
543
544	/*
545	 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
546	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
547	 *     spawnattrlen as an argument to the hook.
548	 */
549	{
550		struct mac_policy_conf *mpc;
551		u_int i;
552
553		for (i = 0; i< mac_policy_list.staticmax; i++) {
554			mpc = mac_policy_list.entries[i].mpc;
555			if (mpc == NULL)
556				continue;
557
558			mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
559			if (hook == NULL)
560				continue;
561
562			size_t spawnattrlen = 0;
563			void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
564
565			result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
566		}
567		if (mac_policy_list_conditional_busy() != 0) {
568			for (; i <= mac_policy_list.maxindex; i++) {
569				mpc = mac_policy_list.entries[i].mpc;
570				if (mpc == NULL)
571					continue;
572
573				mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
574				if (hook == NULL)
575					continue;
576
577				size_t spawnattrlen = 0;
578				void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
579
580				result = result || hook(cred, vp, offset, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
581			}
582			mac_policy_list_unbusy();
583		}
584	}
585
586	return (result);
587}
588
589int
590mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
591    int acc_mode)
592{
593	kauth_cred_t cred;
594	int error;
595	int mask;
596
597	if (!mac_vnode_enforce ||
598	    !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
599		return 0;
600
601	cred = vfs_context_ucred(ctx);
602	/* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
603	mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
604	MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
605	return (error);
606 }
607
608int
609mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
610{
611	kauth_cred_t cred;
612	int error;
613
614	if (!mac_vnode_enforce ||
615	    !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
616		return (0);
617
618	cred = vfs_context_ucred(ctx);
619	MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
620	return (error);
621}
622
623int
624mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
625    struct componentname *cnp)
626{
627	kauth_cred_t cred;
628	int error;
629
630	if (!mac_vnode_enforce ||
631		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
632		return (0);
633
634	cred = vfs_context_ucred(ctx);
635	MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
636	return (error);
637}
638
639int
640mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
641    struct componentname *cnp, struct vnode_attr *vap)
642{
643	kauth_cred_t cred;
644	int error;
645
646	if (!mac_vnode_enforce ||
647		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
648		return (0);
649
650	cred = vfs_context_ucred(ctx);
651	MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
652	return (error);
653}
654
655int
656mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
657    struct componentname *cnp)
658{
659	kauth_cred_t cred;
660	int error;
661
662	if (!mac_vnode_enforce ||
663		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
664		return (0);
665
666	cred = vfs_context_ucred(ctx);
667	MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
668	    vp->v_label, cnp);
669	return (error);
670}
671#if 0
672int
673mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
674    acl_type_t type)
675{
676	kauth_cred_t cred;
677	int error;
678
679	if (!mac_vnode_enforce ||
680		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
681		return (0);
682
683	cred = vfs_context_ucred(ctx);
684	MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
685	return (error);
686}
687#endif
688
689int
690mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
691    const char *name)
692{
693	kauth_cred_t cred;
694	int error;
695
696	if (!mac_vnode_enforce ||
697		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
698		return (0);
699
700	cred = vfs_context_ucred(ctx);
701	MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
702	return (error);
703}
704int
705mac_vnode_check_exchangedata(vfs_context_t ctx,
706    struct vnode *v1, struct vnode *v2)
707{
708	kauth_cred_t cred;
709	int error;
710
711	if (!mac_vnode_enforce ||
712		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
713		return (0);
714
715	cred = vfs_context_ucred(ctx);
716	MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
717	    v2, v2->v_label);
718
719	return (error);
720}
721
722#if 0
723int
724mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
725{
726	kauth_cred_t cred;
727	int error;
728
729	if (!mac_vnode_enforce ||
730		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
731		return (0);
732
733	cred = vfs_context_ucred(ctx);
734	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
735	return (error);
736}
737#endif
738
739int
740mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
741    struct attrlist *alist)
742{
743	kauth_cred_t cred;
744	int error;
745
746	if (!mac_vnode_enforce ||
747		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
748		return (0);
749
750	cred = vfs_context_ucred(ctx);
751	MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
752
753	/* Falsify results instead of returning error? */
754	return (error);
755}
756
757int
758mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
759    struct image_params *imgp)
760{
761	kauth_cred_t cred;
762	int error = 0;
763
764	if (!mac_vnode_enforce || !mac_proc_enforce)
765		return (0);
766
767	cred = vfs_context_ucred(ctx);
768
769	/*
770	 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
771	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
772	 *     spawnattrlen as an argument to the hook.
773	 */
774	{
775		struct mac_policy_conf *mpc;
776		u_int i;
777
778		for (i = 0; i< mac_policy_list.staticmax; i++) {
779			mpc = mac_policy_list.entries[i].mpc;
780			if (mpc == NULL)
781				continue;
782
783			mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
784			if (hook == NULL)
785				continue;
786
787			size_t spawnattrlen = 0;
788			void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
789
790			error = mac_error_select(
791					hook(cred,
792					     vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
793					     imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
794					     spawnattr, spawnattrlen), error);
795		}
796		if (mac_policy_list_conditional_busy() != 0) {
797			for (; i <= mac_policy_list.maxindex; i++) {
798				mpc = mac_policy_list.entries[i].mpc;
799				if (mpc == NULL)
800					continue;
801
802				mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
803				if (hook == NULL)
804					continue;
805
806				size_t spawnattrlen = 0;
807				void *spawnattr = exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen);
808
809				error = mac_error_select(
810						hook(cred,
811						     vp, imgp->ip_scriptvp, vp->v_label, imgp->ip_scriptlabelp,
812						     imgp->ip_execlabelp, &imgp->ip_ndp->ni_cnd, &imgp->ip_csflags,
813						     spawnattr, spawnattrlen), error);
814			}
815			mac_policy_list_unbusy();
816		}
817	}
818
819	return (error);
820}
821
822int
823mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
824{
825	kauth_cred_t cred;
826	int error;
827
828	if (!mac_vnode_enforce ||
829		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
830		return (0);
831
832	cred = vfs_context_ucred(ctx);
833	MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
834	return (error);
835}
836
837int
838mac_vnode_check_signature(struct vnode *vp, off_t macho_offset,
839			  unsigned char *sha1,
840			  const void *signature, size_t size,
841			  int *is_platform_binary)
842{
843	int error;
844
845	if (!mac_vnode_enforce || !mac_proc_enforce)
846		return (0);
847
848	MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1,
849							  signature, size, is_platform_binary);
850	return (error);
851}
852
853#if 0
854int
855mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
856{
857	kauth_cred_t cred;
858	int error;
859
860	if (!mac_vnode_enforce ||
861		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
862		return (0);
863
864	cred = vfs_context_ucred(ctx);
865	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
866	return (error);
867}
868#endif
869
870int
871mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
872    const char *name, struct uio *uio)
873{
874	kauth_cred_t cred;
875	int error;
876
877	if (!mac_vnode_enforce ||
878		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
879		return (0);
880
881	cred = vfs_context_ucred(ctx);
882	MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
883	    name, uio);
884	return (error);
885}
886
887int
888mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
889{
890	kauth_cred_t cred;
891	int error;
892
893	if (!mac_vnode_enforce ||
894		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
895		return (0);
896
897	cred = vfs_context_ucred(ctx);
898	MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
899	return (error);
900}
901
902int
903mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
904    struct knote *kn, struct vnode *vp)
905{
906	kauth_cred_t cred;
907	int error;
908
909	if (!mac_vnode_enforce ||
910		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
911		return (0);
912
913	cred = vfs_context_ucred(ctx);
914	MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
915	    vp->v_label);
916
917	return (error);
918}
919
920int
921mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
922    struct vnode *vp, struct componentname *cnp)
923{
924	kauth_cred_t cred;
925	int error;
926
927	if (!mac_vnode_enforce ||
928		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
929		return (0);
930
931	cred = vfs_context_ucred(ctx);
932	MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
933	    vp->v_label, cnp);
934	return (error);
935}
936
937int
938mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
939{
940	kauth_cred_t cred;
941	int error;
942
943	if (!mac_vnode_enforce ||
944		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
945		return (0);
946
947	cred = vfs_context_ucred(ctx);
948	MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
949	return (error);
950}
951
952int
953mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
954    struct componentname *cnp)
955{
956	kauth_cred_t cred;
957	int error;
958
959	if (!mac_vnode_enforce ||
960		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
961		return (0);
962
963	cred = vfs_context_ucred(ctx);
964	MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
965	return (error);
966}
967
968int
969mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
970{
971	kauth_cred_t cred;
972	int error;
973
974	if (!mac_vnode_enforce ||
975		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
976		return (0);
977
978	cred = vfs_context_ucred(ctx);
979	MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
980	return (error);
981}
982
983int
984mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
985    struct vnode *vp)
986{
987	kauth_cred_t cred;
988	int error;
989
990	if (!mac_vnode_enforce ||
991		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
992		return (0);
993
994	cred = vfs_context_ucred(ctx);
995	MAC_CHECK(vnode_check_read, cred, file_cred, vp,
996	    vp->v_label);
997
998	return (error);
999}
1000
1001int
1002mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
1003{
1004	kauth_cred_t cred;
1005	int error;
1006
1007	if (!mac_vnode_enforce ||
1008		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1009		return (0);
1010
1011	cred = vfs_context_ucred(ctx);
1012	MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
1013	return (error);
1014}
1015
1016int
1017mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1018{
1019	kauth_cred_t cred;
1020	int error;
1021
1022	if (!mac_vnode_enforce ||
1023		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1024		return (0);
1025
1026	cred = vfs_context_ucred(ctx);
1027	MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1028	return (error);
1029}
1030
1031int
1032mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1033    struct label *newlabel)
1034{
1035	kauth_cred_t cred;
1036	int error;
1037
1038	if (!mac_vnode_enforce ||
1039		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1040		return (0);
1041
1042	cred = vfs_context_ucred(ctx);
1043	MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
1044
1045	return (error);
1046}
1047
1048int
1049mac_vnode_check_rename(vfs_context_t ctx, struct vnode *dvp,
1050    struct vnode *vp, struct componentname *cnp, struct vnode *tdvp,
1051    struct vnode *tvp, struct componentname *tcnp)
1052{
1053	kauth_cred_t cred;
1054	int error;
1055
1056	if (!mac_vnode_enforce ||
1057		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1058		return (0);
1059
1060	cred = vfs_context_ucred(ctx);
1061
1062	MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1063	    vp->v_label, cnp);
1064	if (error)
1065		return (error);
1066
1067	MAC_CHECK(vnode_check_rename_to, cred, tdvp, tdvp->v_label, tvp,
1068	    tvp != NULL ? tvp->v_label : NULL, dvp == tdvp, tcnp);
1069	if (error)
1070		return (error);
1071
1072	MAC_CHECK(vnode_check_rename, cred, dvp, dvp->v_label, vp,
1073	    vp->v_label, cnp, tdvp, tdvp->v_label, tvp,
1074	    tvp != NULL ? tvp->v_label : NULL, tcnp);
1075	return (error);
1076}
1077
1078int
1079mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1080{
1081	kauth_cred_t cred;
1082	int error;
1083
1084	if (!mac_vnode_enforce ||
1085		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1086		return (0);
1087
1088	cred = vfs_context_ucred(ctx);
1089	MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1090	return (error);
1091}
1092
1093int
1094mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1095{
1096	kauth_cred_t cred;
1097	int error;
1098
1099	if (!mac_vnode_enforce ||
1100		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1101		return (0);
1102
1103	cred = vfs_context_ucred(ctx);
1104	MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1105	return (error);
1106}
1107
1108int
1109mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1110{
1111	kauth_cred_t cred;
1112	int error;
1113
1114	if (!mac_vnode_enforce ||
1115		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1116		return (0);
1117
1118	cred = vfs_context_ucred(ctx);
1119	MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1120	return (error);
1121}
1122
1123#if 0
1124int
1125mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
1126    struct acl *acl)
1127{
1128	kauth_cred_t cred;
1129	int error;
1130
1131	if (!mac_vnode_enforce ||
1132		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1133		return (0);
1134
1135	cred = vfs_context_ucred(ctx);
1136	MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
1137	return (error);
1138}
1139#endif
1140
1141int
1142mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1143    struct attrlist *alist)
1144{
1145	kauth_cred_t cred;
1146	int error;
1147
1148	if (!mac_vnode_enforce ||
1149		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1150		return (0);
1151
1152	cred = vfs_context_ucred(ctx);
1153	MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
1154	return (error);
1155}
1156
1157int
1158mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1159    const char *name, struct uio *uio)
1160{
1161	kauth_cred_t cred;
1162	int error;
1163
1164	if (!mac_vnode_enforce ||
1165		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1166		return (0);
1167
1168	cred = vfs_context_ucred(ctx);
1169	MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1170	    name, uio);
1171	return (error);
1172}
1173
1174int
1175mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1176{
1177	kauth_cred_t cred;
1178	int error;
1179
1180	if (!mac_vnode_enforce ||
1181		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1182		return (0);
1183
1184	cred = vfs_context_ucred(ctx);
1185	MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1186	return (error);
1187}
1188
1189int
1190mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1191{
1192	kauth_cred_t cred;
1193	int error;
1194
1195	if (!mac_vnode_enforce ||
1196		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1197		return (0);
1198
1199	cred = vfs_context_ucred(ctx);
1200	MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1201	return (error);
1202}
1203
1204int
1205mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1206    gid_t gid)
1207{
1208	kauth_cred_t cred;
1209	int error;
1210
1211	if (!mac_vnode_enforce ||
1212		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1213		return (0);
1214
1215	cred = vfs_context_ucred(ctx);
1216	MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1217	return (error);
1218}
1219
1220int
1221mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1222    struct timespec atime, struct timespec mtime)
1223{
1224	kauth_cred_t cred;
1225	int error;
1226
1227	if (!mac_vnode_enforce ||
1228		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1229		return (0);
1230
1231	cred = vfs_context_ucred(ctx);
1232	MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1233	    mtime);
1234	return (error);
1235}
1236
1237int
1238mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1239    struct vnode *vp)
1240{
1241	kauth_cred_t cred;
1242	int error;
1243
1244	if (!mac_vnode_enforce ||
1245		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1246		return (0);
1247
1248	cred = vfs_context_ucred(ctx);
1249	MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1250	    vp->v_label);
1251	return (error);
1252}
1253
1254int
1255mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1256    struct vnode *vp)
1257{
1258	kauth_cred_t cred;
1259	int error;
1260
1261	if (!mac_vnode_enforce ||
1262		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1263		return (0);
1264
1265	cred = vfs_context_ucred(ctx);
1266	MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1267	    vp->v_label);
1268
1269	return (error);
1270}
1271
1272int
1273mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1274    struct vnode *vp)
1275{
1276	kauth_cred_t cred;
1277	int error;
1278
1279	if (!mac_vnode_enforce ||
1280		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1281		return (0);
1282
1283	cred = vfs_context_ucred(ctx);
1284	MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1285
1286	return (error);
1287}
1288
1289int
1290mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1291    struct componentname *cnp, struct vnode_attr *vap)
1292{
1293	kauth_cred_t cred;
1294	int error;
1295
1296	if (!mac_vnode_enforce ||
1297		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1298		return (0);
1299
1300	cred = vfs_context_ucred(ctx);
1301	MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1302	return (error);
1303}
1304
1305int
1306mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp)
1307{
1308	kauth_cred_t cred;
1309	int error;
1310
1311	if (!mac_vnode_enforce ||
1312		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1313		return (0);
1314
1315	cred = vfs_context_ucred(ctx);
1316	MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label);
1317	return (error);
1318}
1319
1320void
1321mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1322{
1323	kauth_cred_t cred = vfs_context_ucred(ctx);
1324	struct label *tmpl = NULL;
1325
1326	if (vp->v_label == NULL)
1327		tmpl = mac_vnode_label_alloc();
1328
1329	vnode_lock(vp);
1330
1331	/* recheck after lock */
1332	if (vp->v_label == NULL) {
1333		vp->v_label = tmpl;
1334		tmpl = NULL;
1335	}
1336
1337	MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1338	vnode_unlock(vp);
1339
1340	if (tmpl != NULL)
1341		mac_vnode_label_free(tmpl);
1342}
1343
1344int
1345mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1346{
1347	int error;
1348
1349	if (!mac_vnode_enforce || !mac_proc_enforce)
1350		return (0);
1351
1352	MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1353
1354	return (error);
1355}
1356
1357void
1358mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1359{
1360	kauth_cred_t cred = vfs_context_ucred(ctx);
1361
1362	/* XXX: eventually this logic may be handled by the policy? */
1363
1364	/* We desire MULTILABEL for the root filesystem. */
1365	if ((mp->mnt_flag & MNT_ROOTFS) &&
1366	    (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1367		mp->mnt_flag |= MNT_MULTILABEL;
1368
1369	/* MULTILABEL on DEVFS. */
1370	if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1371		mp->mnt_flag |= MNT_MULTILABEL;
1372
1373	/* MULTILABEL on FDESC pseudo-filesystem. */
1374	if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1375		mp->mnt_flag |= MNT_MULTILABEL;
1376
1377	/* MULTILABEL on all NFS filesystems. */
1378	if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1379		mp->mnt_flag |= MNT_MULTILABEL;
1380
1381	/* MULTILABEL on all AFP filesystems. */
1382	if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1383		mp->mnt_flag |= MNT_MULTILABEL;
1384
1385	if (mp->mnt_vtable != NULL) {
1386		/* Any filesystem that supports native XATTRs. */
1387		if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1388			mp->mnt_flag |= MNT_MULTILABEL;
1389
1390		/* Filesystem does not support multilabel. */
1391		if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1392		    (mp->mnt_flag & MNT_MULTILABEL))
1393			mp->mnt_flag &= ~MNT_MULTILABEL;
1394	}
1395
1396	MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1397#if DEBUG
1398	printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1399		mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1400		mp->mnt_vfsstat.f_mntfromname,
1401		mp->mnt_vfsstat.f_mntonname,
1402		mp->mnt_vfsstat.f_fstypename);
1403#endif
1404}
1405
1406int
1407mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1408    struct componentname *cnp, const char *vfc_name)
1409{
1410	kauth_cred_t cred;
1411	int error;
1412
1413	if (!mac_vnode_enforce ||
1414		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1415		return (0);
1416
1417	cred = vfs_context_ucred(ctx);
1418	MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1419
1420	return (error);
1421}
1422
1423int
1424mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1425{
1426	kauth_cred_t cred;
1427	int error;
1428
1429	if (!mac_vnode_enforce ||
1430		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1431		return (0);
1432
1433	cred = vfs_context_ucred(ctx);
1434	MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1435
1436	return (error);
1437}
1438
1439int
1440mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1441{
1442	kauth_cred_t cred;
1443	int error;
1444
1445	if (!mac_vnode_enforce ||
1446		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1447		return (0);
1448
1449	cred = vfs_context_ucred(ctx);
1450	MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1451
1452	return (error);
1453}
1454
1455int
1456mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1457    struct vfs_attr *vfa)
1458{
1459	kauth_cred_t cred;
1460	int error;
1461
1462	if (!mac_vnode_enforce ||
1463		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1464		return (0);
1465
1466	cred = vfs_context_ucred(ctx);
1467	MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1468	return (error);
1469}
1470
1471int
1472mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1473    struct vfs_attr *vfa)
1474{
1475	kauth_cred_t cred;
1476	int error;
1477
1478	if (!mac_vnode_enforce ||
1479		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1480		return (0);
1481
1482	cred = vfs_context_ucred(ctx);
1483	MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1484	return (error);
1485}
1486
1487int
1488mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1489{
1490	kauth_cred_t cred;
1491	int error;
1492
1493	if (!mac_vnode_enforce ||
1494		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1495		return (0);
1496
1497	cred = vfs_context_ucred(ctx);
1498	MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1499
1500	return (error);
1501}
1502
1503int
1504mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1505{
1506	kauth_cred_t cred;
1507	int error;
1508
1509	if (!mac_vnode_enforce ||
1510		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1511		return (0);
1512
1513	cred = vfs_context_ucred(ctx);
1514	MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1515
1516	return (error);
1517}
1518
1519int
1520mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1521{
1522	kauth_cred_t cred;
1523	int error;
1524
1525	if (!mac_vnode_enforce ||
1526		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1527		return (0);
1528
1529	cred = vfs_context_ucred(ctx);
1530	MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1531
1532	return (error);
1533}
1534
1535void
1536mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1537    const char *fullpath)
1538{
1539	if (!mac_device_enforce)
1540		return;
1541
1542	MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1543	    fullpath);
1544}
1545
1546void
1547mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1548    struct devnode *de, const char *fullpath)
1549{
1550	if (!mac_device_enforce)
1551		return;
1552
1553	MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1554	    de->dn_label, fullpath);
1555}
1556
1557int
1558vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1559{
1560	int error;
1561
1562	if (!mac_vnode_enforce || !mac_label_vnodes)
1563		return (0);
1564
1565	if (vp->v_mount == NULL) {
1566		printf("vn_setlabel: null v_mount\n");
1567		if (vp->v_type != VNON)
1568			printf("vn_setlabel: null v_mount with non-VNON\n");
1569		return (EBADF);
1570	}
1571
1572	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1573		return (ENOTSUP);
1574
1575	/*
1576	 * Multi-phase commit.  First check the policies to confirm the
1577	 * change is OK.  Then commit via the filesystem.  Finally,
1578	 * update the actual vnode label.  Question: maybe the filesystem
1579	 * should update the vnode at the end as part of VNOP_SETLABEL()?
1580	 */
1581	error = mac_vnode_check_label_update(context, vp, intlabel);
1582	if (error)
1583		return (error);
1584
1585	error = VNOP_SETLABEL(vp, intlabel, context);
1586	if (error == ENOTSUP) {
1587		error = mac_vnode_label_store(context, vp,
1588						   intlabel);
1589		if (error) {
1590			printf("%s: mac_vnode_label_store failed %d\n",
1591				__func__, error);
1592			return (error);
1593		}
1594		mac_vnode_label_update(context, vp, intlabel);
1595	} else
1596	if (error) {
1597		printf("vn_setlabel: vop setlabel failed %d\n", error);
1598		return (error);
1599	}
1600
1601	return (0);
1602}
1603
1604int
1605mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1606    struct vnode *vp, vfs_context_t ctx)
1607{
1608	struct fileproc *fp;
1609#if CONFIG_MACF_SOCKET_SUBSET
1610	struct socket *so;
1611#endif
1612	struct pipe *cpipe;
1613	struct vnode *fvp;
1614	struct proc *p;
1615	int error;
1616
1617	error = 0;
1618
1619	/*
1620	 * If no backing file, let the policy choose which label to use.
1621	 */
1622	if (fnp->fd_fd == -1) {
1623		MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1624		    mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1625		return (0);
1626	}
1627
1628	p = vfs_context_proc(ctx);
1629	error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1630	if (error)
1631		return (error);
1632
1633	if (fp->f_fglob == NULL) {
1634		error = EBADF;
1635		goto out;
1636	}
1637
1638	switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1639	case DTYPE_VNODE:
1640		fvp = (struct vnode *)fp->f_fglob->fg_data;
1641		if ((error = vnode_getwithref(fvp)))
1642			goto out;
1643		MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1644		(void)vnode_put(fvp);
1645		break;
1646#if CONFIG_MACF_SOCKET_SUBSET
1647	case DTYPE_SOCKET:
1648		so = (struct socket *)fp->f_fglob->fg_data;
1649		socket_lock(so, 1);
1650		MAC_PERFORM(vnode_label_associate_socket,
1651			    vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1652		    vp, vp->v_label);
1653		socket_unlock(so, 1);
1654		break;
1655#endif
1656	case DTYPE_PSXSHM:
1657		pshm_label_associate(fp, vp, ctx);
1658		break;
1659	case DTYPE_PSXSEM:
1660		psem_label_associate(fp, vp, ctx);
1661		break;
1662	case DTYPE_PIPE:
1663		cpipe = (struct pipe *)fp->f_fglob->fg_data;
1664		/* kern/sys_pipe.c:pipe_select() suggests this test. */
1665		if (cpipe == (struct pipe *)-1) {
1666			error = EINVAL;
1667			goto out;
1668		}
1669		PIPE_LOCK(cpipe);
1670		MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1671		    cpipe, cpipe->pipe_label, vp, vp->v_label);
1672		PIPE_UNLOCK(cpipe);
1673		break;
1674	case DTYPE_KQUEUE:
1675	case DTYPE_FSEVENTS:
1676	default:
1677		MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1678		    mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1679		    vp, vp->v_label);
1680		break;
1681	}
1682out:
1683	fp_drop(p, fnp->fd_fd, fp, 0);
1684	return (error);
1685}
1686