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
464int
465mac_cred_label_update_execve(vfs_context_t ctx, kauth_cred_t new, struct vnode *vp,
466	struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execl,
467	void *macextensions)
468{
469	kauth_cred_t cred;
470	int disjoint = 0;
471	posix_cred_t pcred = posix_cred_get(new);
472
473	if (!mac_proc_enforce && !mac_vnode_enforce)
474		return disjoint;
475
476	/* mark the new cred to indicate "matching" includes the label */
477	pcred->cr_flags |= CRF_MAC_ENFORCE;
478
479	cred = vfs_context_ucred(ctx);
480
481	/*
482	 * NB: Cannot use MAC_PERFORM macro because we need a sequence point after
483	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
484	 *     spawnattrlen as an argument to the hook.
485	 */
486	{
487		struct mac_policy_conf *mpc;
488		u_int i;
489
490		for (i = 0; i< mac_policy_list.staticmax; i++) {
491			mpc = mac_policy_list.entries[i].mpc;
492			if (mpc == NULL)
493				continue;
494
495			mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
496			if (hook == NULL)
497				continue;
498
499			size_t spawnattrlen = 0;
500			void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
501
502			hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
503			     scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
504		}
505		if (mac_policy_list_conditional_busy() != 0) {
506			for (; i <= mac_policy_list.maxindex; i++) {
507				mpc = mac_policy_list.entries[i].mpc;
508				if (mpc == NULL)
509					continue;
510
511				mpo_cred_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_label_update_execve;
512				if (hook == NULL)
513					continue;
514
515				size_t spawnattrlen = 0;
516				void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
517
518				hook(cred, new, vfs_context_proc(ctx), vp, scriptvp, vp->v_label,
519				     scriptvnodelabel, execl, spawnattr, spawnattrlen, &disjoint);
520			}
521			mac_policy_list_unbusy();
522		}
523	}
524
525	return (disjoint);
526}
527
528int
529mac_cred_check_label_update_execve(vfs_context_t ctx, struct vnode *vp,
530	struct vnode *scriptvp, struct label *scriptvnodelabel, struct label *execlabel,
531	struct proc *p, void *macextensions)
532{
533	kauth_cred_t cred;
534	int result = 0;
535
536	if (!mac_proc_enforce && !mac_vnode_enforce)
537		return result;
538
539	cred = vfs_context_ucred(ctx);
540
541	/*
542	 * NB: Cannot use MAC_BOOLEAN macro because we need a sequence point after
543	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
544	 *     spawnattrlen as an argument to the hook.
545	 */
546	{
547		struct mac_policy_conf *mpc;
548		u_int i;
549
550		for (i = 0; i< mac_policy_list.staticmax; i++) {
551			mpc = mac_policy_list.entries[i].mpc;
552			if (mpc == NULL)
553				continue;
554
555			mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
556			if (hook == NULL)
557				continue;
558
559			size_t spawnattrlen = 0;
560			void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
561
562			result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
563		}
564		if (mac_policy_list_conditional_busy() != 0) {
565			for (; i <= mac_policy_list.maxindex; i++) {
566				mpc = mac_policy_list.entries[i].mpc;
567				if (mpc == NULL)
568					continue;
569
570				mpo_cred_check_label_update_execve_t *hook = mpc->mpc_ops->mpo_cred_check_label_update_execve;
571				if (hook == NULL)
572					continue;
573
574				size_t spawnattrlen = 0;
575				void *spawnattr = exec_spawnattr_getmacpolicyinfo(macextensions, mpc->mpc_name, &spawnattrlen);
576
577				result = result || hook(cred, vp, scriptvp, vp->v_label, scriptvnodelabel, execlabel, p, spawnattr, spawnattrlen);
578			}
579			mac_policy_list_unbusy();
580		}
581	}
582
583	return (result);
584}
585
586int
587mac_vnode_check_access(vfs_context_t ctx, struct vnode *vp,
588    int acc_mode)
589{
590	kauth_cred_t cred;
591	int error;
592	int mask;
593
594	if (!mac_vnode_enforce ||
595	    !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
596		return 0;
597
598	cred = vfs_context_ucred(ctx);
599	/* Convert {R,W,X}_OK values to V{READ,WRITE,EXEC} for entry points */
600	mask = ACCESS_MODE_TO_VNODE_MASK(acc_mode);
601	MAC_CHECK(vnode_check_access, cred, vp, vp->v_label, mask);
602	return (error);
603 }
604
605int
606mac_vnode_check_chdir(vfs_context_t ctx, struct vnode *dvp)
607{
608	kauth_cred_t cred;
609	int error;
610
611	if (!mac_vnode_enforce ||
612	    !mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
613		return (0);
614
615	cred = vfs_context_ucred(ctx);
616	MAC_CHECK(vnode_check_chdir, cred, dvp, dvp->v_label);
617	return (error);
618}
619
620int
621mac_vnode_check_chroot(vfs_context_t ctx, struct vnode *dvp,
622    struct componentname *cnp)
623{
624	kauth_cred_t cred;
625	int error;
626
627	if (!mac_vnode_enforce ||
628		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
629		return (0);
630
631	cred = vfs_context_ucred(ctx);
632	MAC_CHECK(vnode_check_chroot, cred, dvp, dvp->v_label, cnp);
633	return (error);
634}
635
636int
637mac_vnode_check_create(vfs_context_t ctx, struct vnode *dvp,
638    struct componentname *cnp, struct vnode_attr *vap)
639{
640	kauth_cred_t cred;
641	int error;
642
643	if (!mac_vnode_enforce ||
644		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
645		return (0);
646
647	cred = vfs_context_ucred(ctx);
648	MAC_CHECK(vnode_check_create, cred, dvp, dvp->v_label, cnp, vap);
649	return (error);
650}
651
652int
653mac_vnode_check_unlink(vfs_context_t ctx, struct vnode *dvp, struct vnode *vp,
654    struct componentname *cnp)
655{
656	kauth_cred_t cred;
657	int error;
658
659	if (!mac_vnode_enforce ||
660		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
661		return (0);
662
663	cred = vfs_context_ucred(ctx);
664	MAC_CHECK(vnode_check_unlink, cred, dvp, dvp->v_label, vp,
665	    vp->v_label, cnp);
666	return (error);
667}
668#if 0
669int
670mac_vnode_check_deleteacl(vfs_context_t ctx, struct vnode *vp,
671    acl_type_t type)
672{
673	kauth_cred_t cred;
674	int error;
675
676	if (!mac_vnode_enforce ||
677		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
678		return (0);
679
680	cred = vfs_context_ucred(ctx);
681	MAC_CHECK(vnode_check_deleteacl, cred, vp, vp->v_label, type);
682	return (error);
683}
684#endif
685
686int
687mac_vnode_check_deleteextattr(vfs_context_t ctx, struct vnode *vp,
688    const char *name)
689{
690	kauth_cred_t cred;
691	int error;
692
693	if (!mac_vnode_enforce ||
694		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
695		return (0);
696
697	cred = vfs_context_ucred(ctx);
698	MAC_CHECK(vnode_check_deleteextattr, cred, vp, vp->v_label, name);
699	return (error);
700}
701int
702mac_vnode_check_exchangedata(vfs_context_t ctx,
703    struct vnode *v1, struct vnode *v2)
704{
705	kauth_cred_t cred;
706	int error;
707
708	if (!mac_vnode_enforce ||
709		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
710		return (0);
711
712	cred = vfs_context_ucred(ctx);
713	MAC_CHECK(vnode_check_exchangedata, cred, v1, v1->v_label,
714	    v2, v2->v_label);
715
716	return (error);
717}
718
719#if 0
720int
721mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
722{
723	kauth_cred_t cred;
724	int error;
725
726	if (!mac_vnode_enforce ||
727		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
728		return (0);
729
730	cred = vfs_context_ucred(ctx);
731	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
732	return (error);
733}
734#endif
735
736int
737mac_vnode_check_getattrlist(vfs_context_t ctx, struct vnode *vp,
738    struct attrlist *alist)
739{
740	kauth_cred_t cred;
741	int error;
742
743	if (!mac_vnode_enforce ||
744		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
745		return (0);
746
747	cred = vfs_context_ucred(ctx);
748	MAC_CHECK(vnode_check_getattrlist, cred, vp, vp->v_label, alist);
749
750	/* Falsify results instead of returning error? */
751	return (error);
752}
753
754int
755mac_vnode_check_exec(vfs_context_t ctx, struct vnode *vp,
756    struct image_params *imgp)
757{
758	kauth_cred_t cred;
759	int error = 0;
760
761	if (!mac_vnode_enforce || !mac_proc_enforce)
762		return (0);
763
764	cred = vfs_context_ucred(ctx);
765
766	/*
767	 * NB: Cannot use MAC_CHECK macro because we need a sequence point after
768	 *     calling exec_spawnattr_getmacpolicyinfo() and before passing the
769	 *     spawnattrlen as an argument to the hook.
770	 */
771	{
772		struct mac_policy_conf *mpc;
773		u_int i;
774
775		for (i = 0; i< mac_policy_list.staticmax; i++) {
776			mpc = mac_policy_list.entries[i].mpc;
777			if (mpc == NULL)
778				continue;
779
780			mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
781			if (hook == NULL)
782				continue;
783
784			size_t spawnattrlen = 0;
785			void *spawnattr =  (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
786
787			error = mac_error_select(
788					hook(cred, vp, vp->v_label,
789					     (imgp != NULL) ? imgp->ip_execlabelp : NULL,
790					     (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
791					     (imgp != NULL) ? &imgp->ip_csflags : NULL,
792					     spawnattr, spawnattrlen), error);
793		}
794		if (mac_policy_list_conditional_busy() != 0) {
795			for (; i <= mac_policy_list.maxindex; i++) {
796				mpc = mac_policy_list.entries[i].mpc;
797				if (mpc == NULL)
798					continue;
799
800				mpo_vnode_check_exec_t *hook = mpc->mpc_ops->mpo_vnode_check_exec;
801				if (hook == NULL)
802					continue;
803
804				size_t spawnattrlen = 0;
805				void *spawnattr =  (imgp != NULL) ? exec_spawnattr_getmacpolicyinfo(imgp->ip_px_smpx, mpc->mpc_name, &spawnattrlen) : NULL;
806
807				error = mac_error_select(
808						hook(cred, vp, vp->v_label,
809						     (imgp != NULL) ? imgp->ip_execlabelp : NULL,
810						     (imgp != NULL) ? &imgp->ip_ndp->ni_cnd : NULL,
811						     (imgp != NULL) ? &imgp->ip_csflags : NULL,
812						     spawnattr, spawnattrlen), error);
813			}
814			mac_policy_list_unbusy();
815		}
816	}
817
818	return (error);
819}
820
821int
822mac_vnode_check_fsgetpath(vfs_context_t ctx, struct vnode *vp)
823{
824	kauth_cred_t cred;
825	int error;
826
827	if (!mac_vnode_enforce ||
828		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
829		return (0);
830
831	cred = vfs_context_ucred(ctx);
832	MAC_CHECK(vnode_check_fsgetpath, cred, vp, vp->v_label);
833	return (error);
834}
835
836int
837mac_vnode_check_signature(struct vnode *vp, off_t macho_offset,
838			  unsigned char *sha1,
839			  void * signature, size_t size)
840{
841	int error;
842
843	if (!mac_vnode_enforce || !mac_proc_enforce)
844		return (0);
845
846	MAC_CHECK(vnode_check_signature, vp, vp->v_label, macho_offset, sha1, signature, size);
847	return (error);
848}
849
850#if 0
851int
852mac_vnode_check_getacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type)
853{
854	kauth_cred_t cred;
855	int error;
856
857	if (!mac_vnode_enforce ||
858		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
859		return (0);
860
861	cred = vfs_context_ucred(ctx);
862	MAC_CHECK(vnode_check_getacl, cred, vp, vp->v_label, type);
863	return (error);
864}
865#endif
866
867int
868mac_vnode_check_getextattr(vfs_context_t ctx, struct vnode *vp,
869    const char *name, struct uio *uio)
870{
871	kauth_cred_t cred;
872	int error;
873
874	if (!mac_vnode_enforce ||
875		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
876		return (0);
877
878	cred = vfs_context_ucred(ctx);
879	MAC_CHECK(vnode_check_getextattr, cred, vp, vp->v_label,
880	    name, uio);
881	return (error);
882}
883
884int
885mac_vnode_check_ioctl(vfs_context_t ctx, struct vnode *vp, u_int cmd)
886{
887	kauth_cred_t cred;
888	int error;
889
890	if (!mac_vnode_enforce ||
891		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
892		return (0);
893
894	cred = vfs_context_ucred(ctx);
895	MAC_CHECK(vnode_check_ioctl, cred, vp, vp->v_label, cmd);
896	return (error);
897}
898
899int
900mac_vnode_check_kqfilter(vfs_context_t ctx, kauth_cred_t file_cred,
901    struct knote *kn, struct vnode *vp)
902{
903	kauth_cred_t cred;
904	int error;
905
906	if (!mac_vnode_enforce ||
907		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
908		return (0);
909
910	cred = vfs_context_ucred(ctx);
911	MAC_CHECK(vnode_check_kqfilter, cred, file_cred, kn, vp,
912	    vp->v_label);
913
914	return (error);
915}
916
917int
918mac_vnode_check_link(vfs_context_t ctx, struct vnode *dvp,
919    struct vnode *vp, struct componentname *cnp)
920{
921	kauth_cred_t cred;
922	int error;
923
924	if (!mac_vnode_enforce ||
925		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
926		return (0);
927
928	cred = vfs_context_ucred(ctx);
929	MAC_CHECK(vnode_check_link, cred, dvp, dvp->v_label, vp,
930	    vp->v_label, cnp);
931	return (error);
932}
933
934int
935mac_vnode_check_listextattr(vfs_context_t ctx, struct vnode *vp)
936{
937	kauth_cred_t cred;
938	int error;
939
940	if (!mac_vnode_enforce ||
941		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
942		return (0);
943
944	cred = vfs_context_ucred(ctx);
945	MAC_CHECK(vnode_check_listextattr, cred, vp, vp->v_label);
946	return (error);
947}
948
949int
950mac_vnode_check_lookup(vfs_context_t ctx, struct vnode *dvp,
951    struct componentname *cnp)
952{
953	kauth_cred_t cred;
954	int error;
955
956	if (!mac_vnode_enforce ||
957		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
958		return (0);
959
960	cred = vfs_context_ucred(ctx);
961	MAC_CHECK(vnode_check_lookup, cred, dvp, dvp->v_label, cnp);
962	return (error);
963}
964
965int
966mac_vnode_check_open(vfs_context_t ctx, struct vnode *vp, int acc_mode)
967{
968	kauth_cred_t cred;
969	int error;
970
971	if (!mac_vnode_enforce ||
972		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
973		return (0);
974
975	cred = vfs_context_ucred(ctx);
976	MAC_CHECK(vnode_check_open, cred, vp, vp->v_label, acc_mode);
977	return (error);
978}
979
980int
981mac_vnode_check_read(vfs_context_t ctx, struct ucred *file_cred,
982    struct vnode *vp)
983{
984	kauth_cred_t cred;
985	int error;
986
987	if (!mac_vnode_enforce ||
988		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
989		return (0);
990
991	cred = vfs_context_ucred(ctx);
992	MAC_CHECK(vnode_check_read, cred, file_cred, vp,
993	    vp->v_label);
994
995	return (error);
996}
997
998int
999mac_vnode_check_readdir(vfs_context_t ctx, struct vnode *dvp)
1000{
1001	kauth_cred_t cred;
1002	int error;
1003
1004	if (!mac_vnode_enforce ||
1005		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1006		return (0);
1007
1008	cred = vfs_context_ucred(ctx);
1009	MAC_CHECK(vnode_check_readdir, cred, dvp, dvp->v_label);
1010	return (error);
1011}
1012
1013int
1014mac_vnode_check_readlink(vfs_context_t ctx, struct vnode *vp)
1015{
1016	kauth_cred_t cred;
1017	int error;
1018
1019	if (!mac_vnode_enforce ||
1020		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1021		return (0);
1022
1023	cred = vfs_context_ucred(ctx);
1024	MAC_CHECK(vnode_check_readlink, cred, vp, vp->v_label);
1025	return (error);
1026}
1027
1028int
1029mac_vnode_check_label_update(vfs_context_t ctx, struct vnode *vp,
1030    struct label *newlabel)
1031{
1032	kauth_cred_t cred;
1033	int error;
1034
1035	if (!mac_vnode_enforce ||
1036		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1037		return (0);
1038
1039	cred = vfs_context_ucred(ctx);
1040	MAC_CHECK(vnode_check_label_update, cred, vp, vp->v_label, newlabel);
1041
1042	return (error);
1043}
1044
1045int
1046mac_vnode_check_rename_from(vfs_context_t ctx, struct vnode *dvp,
1047    struct vnode *vp, struct componentname *cnp)
1048{
1049	kauth_cred_t cred;
1050	int error;
1051
1052	if (!mac_vnode_enforce ||
1053		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1054		return (0);
1055
1056	cred = vfs_context_ucred(ctx);
1057	MAC_CHECK(vnode_check_rename_from, cred, dvp, dvp->v_label, vp,
1058	    vp->v_label, cnp);
1059	return (error);
1060}
1061
1062int
1063mac_vnode_check_rename_to(vfs_context_t ctx, struct vnode *dvp,
1064    struct vnode *vp, int samedir, struct componentname *cnp)
1065{
1066	kauth_cred_t cred;
1067	int error;
1068
1069	if (!mac_vnode_enforce ||
1070		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1071		return (0);
1072
1073	cred = vfs_context_ucred(ctx);
1074	MAC_CHECK(vnode_check_rename_to, cred, dvp, dvp->v_label, vp,
1075	    vp != NULL ? vp->v_label : NULL, samedir, cnp);
1076	return (error);
1077}
1078
1079int
1080mac_vnode_check_revoke(vfs_context_t ctx, struct vnode *vp)
1081{
1082	kauth_cred_t cred;
1083	int error;
1084
1085	if (!mac_vnode_enforce ||
1086		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1087		return (0);
1088
1089	cred = vfs_context_ucred(ctx);
1090	MAC_CHECK(vnode_check_revoke, cred, vp, vp->v_label);
1091	return (error);
1092}
1093
1094int
1095mac_vnode_check_searchfs(vfs_context_t ctx, struct vnode *vp, struct attrlist *alist)
1096{
1097	kauth_cred_t cred;
1098	int error;
1099
1100	if (!mac_vnode_enforce ||
1101		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1102		return (0);
1103
1104	cred = vfs_context_ucred(ctx);
1105	MAC_CHECK(vnode_check_searchfs, cred, vp, vp->v_label, alist);
1106	return (error);
1107}
1108
1109int
1110mac_vnode_check_select(vfs_context_t ctx, struct vnode *vp, int which)
1111{
1112	kauth_cred_t cred;
1113	int error;
1114
1115	if (!mac_vnode_enforce ||
1116		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1117		return (0);
1118
1119	cred = vfs_context_ucred(ctx);
1120	MAC_CHECK(vnode_check_select, cred, vp, vp->v_label, which);
1121	return (error);
1122}
1123
1124#if 0
1125int
1126mac_vnode_check_setacl(vfs_context_t ctx, struct vnode *vp, acl_type_t type,
1127    struct acl *acl)
1128{
1129	kauth_cred_t cred;
1130	int error;
1131
1132	if (!mac_vnode_enforce ||
1133		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1134		return (0);
1135
1136	cred = vfs_context_ucred(ctx);
1137	MAC_CHECK(vnode_check_setacl, cred, vp, vp->v_label, type, acl);
1138	return (error);
1139}
1140#endif
1141
1142int
1143mac_vnode_check_setattrlist(vfs_context_t ctx, struct vnode *vp,
1144    struct attrlist *alist)
1145{
1146	kauth_cred_t cred;
1147	int error;
1148
1149	if (!mac_vnode_enforce ||
1150		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1151		return (0);
1152
1153	cred = vfs_context_ucred(ctx);
1154	MAC_CHECK(vnode_check_setattrlist, cred, vp, vp->v_label, alist);
1155	return (error);
1156}
1157
1158int
1159mac_vnode_check_setextattr(vfs_context_t ctx, struct vnode *vp,
1160    const char *name, struct uio *uio)
1161{
1162	kauth_cred_t cred;
1163	int error;
1164
1165	if (!mac_vnode_enforce ||
1166		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1167		return (0);
1168
1169	cred = vfs_context_ucred(ctx);
1170	MAC_CHECK(vnode_check_setextattr, cred, vp, vp->v_label,
1171	    name, uio);
1172	return (error);
1173}
1174
1175int
1176mac_vnode_check_setflags(vfs_context_t ctx, struct vnode *vp, u_long flags)
1177{
1178	kauth_cred_t cred;
1179	int error;
1180
1181	if (!mac_vnode_enforce ||
1182		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1183		return (0);
1184
1185	cred = vfs_context_ucred(ctx);
1186	MAC_CHECK(vnode_check_setflags, cred, vp, vp->v_label, flags);
1187	return (error);
1188}
1189
1190int
1191mac_vnode_check_setmode(vfs_context_t ctx, struct vnode *vp, mode_t mode)
1192{
1193	kauth_cred_t cred;
1194	int error;
1195
1196	if (!mac_vnode_enforce ||
1197		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1198		return (0);
1199
1200	cred = vfs_context_ucred(ctx);
1201	MAC_CHECK(vnode_check_setmode, cred, vp, vp->v_label, mode);
1202	return (error);
1203}
1204
1205int
1206mac_vnode_check_setowner(vfs_context_t ctx, struct vnode *vp, uid_t uid,
1207    gid_t gid)
1208{
1209	kauth_cred_t cred;
1210	int error;
1211
1212	if (!mac_vnode_enforce ||
1213		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1214		return (0);
1215
1216	cred = vfs_context_ucred(ctx);
1217	MAC_CHECK(vnode_check_setowner, cred, vp, vp->v_label, uid, gid);
1218	return (error);
1219}
1220
1221int
1222mac_vnode_check_setutimes(vfs_context_t ctx, struct vnode *vp,
1223    struct timespec atime, struct timespec mtime)
1224{
1225	kauth_cred_t cred;
1226	int error;
1227
1228	if (!mac_vnode_enforce ||
1229		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1230		return (0);
1231
1232	cred = vfs_context_ucred(ctx);
1233	MAC_CHECK(vnode_check_setutimes, cred, vp, vp->v_label, atime,
1234	    mtime);
1235	return (error);
1236}
1237
1238int
1239mac_vnode_check_stat(vfs_context_t ctx, struct ucred *file_cred,
1240    struct vnode *vp)
1241{
1242	kauth_cred_t cred;
1243	int error;
1244
1245	if (!mac_vnode_enforce ||
1246		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1247		return (0);
1248
1249	cred = vfs_context_ucred(ctx);
1250	MAC_CHECK(vnode_check_stat, cred, file_cred, vp,
1251	    vp->v_label);
1252	return (error);
1253}
1254
1255int
1256mac_vnode_check_truncate(vfs_context_t ctx, struct ucred *file_cred,
1257    struct vnode *vp)
1258{
1259	kauth_cred_t cred;
1260	int error;
1261
1262	if (!mac_vnode_enforce ||
1263		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1264		return (0);
1265
1266	cred = vfs_context_ucred(ctx);
1267	MAC_CHECK(vnode_check_truncate, cred, file_cred, vp,
1268	    vp->v_label);
1269
1270	return (error);
1271}
1272
1273int
1274mac_vnode_check_write(vfs_context_t ctx, struct ucred *file_cred,
1275    struct vnode *vp)
1276{
1277	kauth_cred_t cred;
1278	int error;
1279
1280	if (!mac_vnode_enforce ||
1281		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1282		return (0);
1283
1284	cred = vfs_context_ucred(ctx);
1285	MAC_CHECK(vnode_check_write, cred, file_cred, vp, vp->v_label);
1286
1287	return (error);
1288}
1289
1290int
1291mac_vnode_check_uipc_bind(vfs_context_t ctx, struct vnode *dvp,
1292    struct componentname *cnp, struct vnode_attr *vap)
1293{
1294	kauth_cred_t cred;
1295	int error;
1296
1297	if (!mac_vnode_enforce ||
1298		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1299		return (0);
1300
1301	cred = vfs_context_ucred(ctx);
1302	MAC_CHECK(vnode_check_uipc_bind, cred, dvp, dvp->v_label, cnp, vap);
1303	return (error);
1304}
1305
1306int
1307mac_vnode_check_uipc_connect(vfs_context_t ctx, struct vnode *vp)
1308{
1309	kauth_cred_t cred;
1310	int error;
1311
1312	if (!mac_vnode_enforce ||
1313		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1314		return (0);
1315
1316	cred = vfs_context_ucred(ctx);
1317	MAC_CHECK(vnode_check_uipc_connect, cred, vp, vp->v_label);
1318	return (error);
1319}
1320
1321void
1322mac_vnode_label_update(vfs_context_t ctx, struct vnode *vp, struct label *newlabel)
1323{
1324	kauth_cred_t cred = vfs_context_ucred(ctx);
1325	struct label *tmpl = NULL;
1326
1327	if (vp->v_label == NULL)
1328		tmpl = mac_vnode_label_alloc();
1329
1330	vnode_lock(vp);
1331
1332	/* recheck after lock */
1333	if (vp->v_label == NULL) {
1334		vp->v_label = tmpl;
1335		tmpl = NULL;
1336	}
1337
1338	MAC_PERFORM(vnode_label_update, cred, vp, vp->v_label, newlabel);
1339	vnode_unlock(vp);
1340
1341	if (tmpl != NULL)
1342		mac_vnode_label_free(tmpl);
1343}
1344
1345int
1346mac_vnode_find_sigs(struct proc *p, struct vnode *vp, off_t offset)
1347{
1348	int error;
1349
1350	if (!mac_vnode_enforce || !mac_proc_enforce)
1351		return (0);
1352
1353	MAC_CHECK(vnode_find_sigs, p, vp, offset, vp->v_label);
1354
1355	return (error);
1356}
1357
1358void
1359mac_mount_label_associate(vfs_context_t ctx, struct mount *mp)
1360{
1361	kauth_cred_t cred = vfs_context_ucred(ctx);
1362
1363	/* XXX: eventually this logic may be handled by the policy? */
1364
1365	/* We desire MULTILABEL for the root filesystem. */
1366	if ((mp->mnt_flag & MNT_ROOTFS) &&
1367	    (strcmp(mp->mnt_vfsstat.f_fstypename, "hfs") == 0))
1368		mp->mnt_flag |= MNT_MULTILABEL;
1369
1370	/* MULTILABEL on DEVFS. */
1371	if (strcmp(mp->mnt_vfsstat.f_fstypename, "devfs") == 0)
1372		mp->mnt_flag |= MNT_MULTILABEL;
1373
1374	/* MULTILABEL on FDESC pseudo-filesystem. */
1375	if (strcmp(mp->mnt_vfsstat.f_fstypename, "fdesc") == 0)
1376		mp->mnt_flag |= MNT_MULTILABEL;
1377
1378	/* MULTILABEL on all NFS filesystems. */
1379	if (strcmp(mp->mnt_vfsstat.f_fstypename, "nfs") == 0)
1380		mp->mnt_flag |= MNT_MULTILABEL;
1381
1382	/* MULTILABEL on all AFP filesystems. */
1383	if (strcmp(mp->mnt_vfsstat.f_fstypename, "afpfs") == 0)
1384		mp->mnt_flag |= MNT_MULTILABEL;
1385
1386	if (mp->mnt_vtable != NULL) {
1387		/* Any filesystem that supports native XATTRs. */
1388		if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNATIVEXATTR))
1389			mp->mnt_flag |= MNT_MULTILABEL;
1390
1391		/* Filesystem does not support multilabel. */
1392		if ((mp->mnt_vtable->vfc_vfsflags & VFC_VFSNOMACLABEL) &&
1393		    (mp->mnt_flag & MNT_MULTILABEL))
1394			mp->mnt_flag &= ~MNT_MULTILABEL;
1395	}
1396
1397	MAC_PERFORM(mount_label_associate, cred, mp, mp->mnt_mntlabel);
1398#if DEBUG
1399	printf("MAC Framework enabling %s support: %s -> %s (%s)\n",
1400		mp->mnt_flag & MNT_MULTILABEL ? "multilabel" : "singlelabel",
1401		mp->mnt_vfsstat.f_mntfromname,
1402		mp->mnt_vfsstat.f_mntonname,
1403		mp->mnt_vfsstat.f_fstypename);
1404#endif
1405}
1406
1407int
1408mac_mount_check_mount(vfs_context_t ctx, struct vnode *vp,
1409    struct componentname *cnp, const char *vfc_name)
1410{
1411	kauth_cred_t cred;
1412	int error;
1413
1414	if (!mac_vnode_enforce ||
1415		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1416		return (0);
1417
1418	cred = vfs_context_ucred(ctx);
1419	MAC_CHECK(mount_check_mount, cred, vp, vp->v_label, cnp, vfc_name);
1420
1421	return (error);
1422}
1423
1424int
1425mac_mount_check_remount(vfs_context_t ctx, struct mount *mp)
1426{
1427	kauth_cred_t cred;
1428	int error;
1429
1430	if (!mac_vnode_enforce ||
1431		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1432		return (0);
1433
1434	cred = vfs_context_ucred(ctx);
1435	MAC_CHECK(mount_check_remount, cred, mp, mp->mnt_mntlabel);
1436
1437	return (error);
1438}
1439
1440int
1441mac_mount_check_umount(vfs_context_t ctx, struct mount *mp)
1442{
1443	kauth_cred_t cred;
1444	int error;
1445
1446	if (!mac_vnode_enforce ||
1447		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1448		return (0);
1449
1450	cred = vfs_context_ucred(ctx);
1451	MAC_CHECK(mount_check_umount, cred, mp, mp->mnt_mntlabel);
1452
1453	return (error);
1454}
1455
1456int
1457mac_mount_check_getattr(vfs_context_t ctx, struct mount *mp,
1458    struct vfs_attr *vfa)
1459{
1460	kauth_cred_t cred;
1461	int error;
1462
1463	if (!mac_vnode_enforce ||
1464		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1465		return (0);
1466
1467	cred = vfs_context_ucred(ctx);
1468	MAC_CHECK(mount_check_getattr, cred, mp, mp->mnt_mntlabel, vfa);
1469	return (error);
1470}
1471
1472int
1473mac_mount_check_setattr(vfs_context_t ctx, struct mount *mp,
1474    struct vfs_attr *vfa)
1475{
1476	kauth_cred_t cred;
1477	int error;
1478
1479	if (!mac_vnode_enforce ||
1480		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1481		return (0);
1482
1483	cred = vfs_context_ucred(ctx);
1484	MAC_CHECK(mount_check_setattr, cred, mp, mp->mnt_mntlabel, vfa);
1485	return (error);
1486}
1487
1488int
1489mac_mount_check_stat(vfs_context_t ctx, struct mount *mount)
1490{
1491	kauth_cred_t cred;
1492	int error;
1493
1494	if (!mac_vnode_enforce ||
1495		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1496		return (0);
1497
1498	cred = vfs_context_ucred(ctx);
1499	MAC_CHECK(mount_check_stat, cred, mount, mount->mnt_mntlabel);
1500
1501	return (error);
1502}
1503
1504int
1505mac_mount_check_label_update(vfs_context_t ctx, struct mount *mount)
1506{
1507	kauth_cred_t cred;
1508	int error;
1509
1510	if (!mac_vnode_enforce ||
1511		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1512		return (0);
1513
1514	cred = vfs_context_ucred(ctx);
1515	MAC_CHECK(mount_check_label_update, cred, mount, mount->mnt_mntlabel);
1516
1517	return (error);
1518}
1519
1520int
1521mac_mount_check_fsctl(vfs_context_t ctx, struct mount *mp, u_int cmd)
1522{
1523	kauth_cred_t cred;
1524	int error;
1525
1526	if (!mac_vnode_enforce ||
1527		!mac_context_check_enforce(ctx, MAC_VNODE_ENFORCE))
1528		return (0);
1529
1530	cred = vfs_context_ucred(ctx);
1531	MAC_CHECK(mount_check_fsctl, cred, mp, mp->mnt_mntlabel, cmd);
1532
1533	return (error);
1534}
1535
1536void
1537mac_devfs_label_associate_device(dev_t dev, struct devnode *de,
1538    const char *fullpath)
1539{
1540	if (!mac_device_enforce)
1541		return;
1542
1543	MAC_PERFORM(devfs_label_associate_device, dev, de, de->dn_label,
1544	    fullpath);
1545}
1546
1547void
1548mac_devfs_label_associate_directory(const char *dirname, int dirnamelen,
1549    struct devnode *de, const char *fullpath)
1550{
1551	if (!mac_device_enforce)
1552		return;
1553
1554	MAC_PERFORM(devfs_label_associate_directory, dirname, dirnamelen, de,
1555	    de->dn_label, fullpath);
1556}
1557
1558int
1559vn_setlabel(struct vnode *vp, struct label *intlabel, vfs_context_t context)
1560{
1561	int error;
1562
1563	if (!mac_vnode_enforce || !mac_label_vnodes)
1564		return (0);
1565
1566	if (vp->v_mount == NULL) {
1567		printf("vn_setlabel: null v_mount\n");
1568		if (vp->v_type != VNON)
1569			printf("vn_setlabel: null v_mount with non-VNON\n");
1570		return (EBADF);
1571	}
1572
1573	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
1574		return (ENOTSUP);
1575
1576	/*
1577	 * Multi-phase commit.  First check the policies to confirm the
1578	 * change is OK.  Then commit via the filesystem.  Finally,
1579	 * update the actual vnode label.  Question: maybe the filesystem
1580	 * should update the vnode at the end as part of VNOP_SETLABEL()?
1581	 */
1582	error = mac_vnode_check_label_update(context, vp, intlabel);
1583	if (error)
1584		return (error);
1585
1586	error = VNOP_SETLABEL(vp, intlabel, context);
1587	if (error == ENOTSUP) {
1588		error = mac_vnode_label_store(context, vp,
1589						   intlabel);
1590		if (error) {
1591			printf("%s: mac_vnode_label_store failed %d\n",
1592				__func__, error);
1593			return (error);
1594		}
1595		mac_vnode_label_update(context, vp, intlabel);
1596	} else
1597	if (error) {
1598		printf("vn_setlabel: vop setlabel failed %d\n", error);
1599		return (error);
1600	}
1601
1602	return (0);
1603}
1604
1605int
1606mac_vnode_label_associate_fdesc(struct mount *mp, struct fdescnode *fnp,
1607    struct vnode *vp, vfs_context_t ctx)
1608{
1609	struct fileproc *fp;
1610#if CONFIG_MACF_SOCKET_SUBSET
1611	struct socket *so;
1612#endif
1613	struct pipe *cpipe;
1614	struct vnode *fvp;
1615	struct proc *p;
1616	int error;
1617
1618	error = 0;
1619
1620	/*
1621	 * If no backing file, let the policy choose which label to use.
1622	 */
1623	if (fnp->fd_fd == -1) {
1624		MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1625		    mp, mp->mnt_mntlabel, NULL, NULL, vp, vp->v_label);
1626		return (0);
1627	}
1628
1629	p = vfs_context_proc(ctx);
1630	error = fp_lookup(p, fnp->fd_fd, &fp, 0);
1631	if (error)
1632		return (error);
1633
1634	if (fp->f_fglob == NULL) {
1635		error = EBADF;
1636		goto out;
1637	}
1638
1639	switch (FILEGLOB_DTYPE(fp->f_fglob)) {
1640	case DTYPE_VNODE:
1641		fvp = (struct vnode *)fp->f_fglob->fg_data;
1642		if ((error = vnode_getwithref(fvp)))
1643			goto out;
1644		MAC_PERFORM(vnode_label_copy, fvp->v_label, vp->v_label);
1645		(void)vnode_put(fvp);
1646		break;
1647#if CONFIG_MACF_SOCKET_SUBSET
1648	case DTYPE_SOCKET:
1649		so = (struct socket *)fp->f_fglob->fg_data;
1650		socket_lock(so, 1);
1651		MAC_PERFORM(vnode_label_associate_socket,
1652			    vfs_context_ucred(ctx), (socket_t)so, so->so_label,
1653		    vp, vp->v_label);
1654		socket_unlock(so, 1);
1655		break;
1656#endif
1657	case DTYPE_PSXSHM:
1658		pshm_label_associate(fp, vp, ctx);
1659		break;
1660	case DTYPE_PSXSEM:
1661		psem_label_associate(fp, vp, ctx);
1662		break;
1663	case DTYPE_PIPE:
1664		cpipe = (struct pipe *)fp->f_fglob->fg_data;
1665		/* kern/sys_pipe.c:pipe_select() suggests this test. */
1666		if (cpipe == (struct pipe *)-1) {
1667			error = EINVAL;
1668			goto out;
1669		}
1670		PIPE_LOCK(cpipe);
1671		MAC_PERFORM(vnode_label_associate_pipe, vfs_context_ucred(ctx),
1672		    cpipe, cpipe->pipe_label, vp, vp->v_label);
1673		PIPE_UNLOCK(cpipe);
1674		break;
1675	case DTYPE_KQUEUE:
1676	case DTYPE_FSEVENTS:
1677	default:
1678		MAC_PERFORM(vnode_label_associate_file, vfs_context_ucred(ctx),
1679		    mp, mp->mnt_mntlabel, fp->f_fglob, fp->f_fglob->fg_label,
1680		    vp, vp->v_label);
1681		break;
1682	}
1683out:
1684	fp_drop(p, fnp->fd_fd, fp, 0);
1685	return (error);
1686}
1687