mac_internal.h revision 111939
1219820Sjeff/*-
2219820Sjeff * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3219820Sjeff * Copyright (c) 2001 Ilmar S. Habibulin
4219820Sjeff * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5219820Sjeff * All rights reserved.
6219820Sjeff *
7219820Sjeff * This software was developed by Robert Watson and Ilmar Habibulin for the
8219820Sjeff * TrustedBSD Project.
9219820Sjeff *
10219820Sjeff * This software was developed for the FreeBSD Project in part by Network
11219820Sjeff * Associates Laboratories, the Security Research Division of Network
12219820Sjeff * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13219820Sjeff * as part of the DARPA CHATS research program.
14219820Sjeff *
15219820Sjeff * Redistribution and use in source and binary forms, with or without
16219820Sjeff * modification, are permitted provided that the following conditions
17219820Sjeff * are met:
18219820Sjeff * 1. Redistributions of source code must retain the above copyright
19219820Sjeff *    notice, this list of conditions and the following disclaimer.
20219820Sjeff * 2. Redistributions in binary form must reproduce the above copyright
21219820Sjeff *    notice, this list of conditions and the following disclaimer in the
22219820Sjeff *    documentation and/or other materials provided with the distribution.
23219820Sjeff *
24219820Sjeff * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25219820Sjeff * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26219820Sjeff * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27219820Sjeff * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28219820Sjeff * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29219820Sjeff * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30219820Sjeff * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31219820Sjeff * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32219820Sjeff * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33219820Sjeff * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34219820Sjeff * SUCH DAMAGE.
35219820Sjeff *
36219820Sjeff * $FreeBSD: head/sys/security/mac/mac_internal.h 111939 2003-03-06 04:47:47Z rwatson $
37272027Shselasky */
38219820Sjeff/*
39219820Sjeff * Developed by the TrustedBSD Project.
40219820Sjeff *
41219820Sjeff * Framework for extensible kernel access control.  Kernel and userland
42219820Sjeff * interface to the framework, policy registration and composition.
43219820Sjeff */
44219820Sjeff
45219820Sjeff#include "opt_mac.h"
46219820Sjeff#include "opt_devfs.h"
47219820Sjeff
48219820Sjeff#include <sys/param.h>
49219820Sjeff#include <sys/condvar.h>
50219820Sjeff#include <sys/extattr.h>
51219820Sjeff#include <sys/imgact.h>
52219820Sjeff#include <sys/kernel.h>
53219820Sjeff#include <sys/lock.h>
54219820Sjeff#include <sys/malloc.h>
55219820Sjeff#include <sys/mutex.h>
56219820Sjeff#include <sys/mac.h>
57219820Sjeff#include <sys/module.h>
58219820Sjeff#include <sys/proc.h>
59219820Sjeff#include <sys/systm.h>
60219820Sjeff#include <sys/sysproto.h>
61219820Sjeff#include <sys/sysent.h>
62219820Sjeff#include <sys/vnode.h>
63255932Salfred#include <sys/mount.h>
64219820Sjeff#include <sys/file.h>
65219820Sjeff#include <sys/namei.h>
66219820Sjeff#include <sys/socket.h>
67219820Sjeff#include <sys/pipe.h>
68219820Sjeff#include <sys/socketvar.h>
69219820Sjeff#include <sys/sysctl.h>
70255932Salfred
71255932Salfred#include <vm/vm.h>
72255932Salfred#include <vm/pmap.h>
73219820Sjeff#include <vm/vm_map.h>
74219820Sjeff#include <vm/vm_object.h>
75219820Sjeff
76219820Sjeff#include <sys/mac_policy.h>
77219820Sjeff
78219820Sjeff#include <fs/devfs/devfs.h>
79219820Sjeff
80219820Sjeff#include <net/bpfdesc.h>
81219820Sjeff#include <net/if.h>
82219820Sjeff#include <net/if_var.h>
83219820Sjeff
84219820Sjeff#include <netinet/in.h>
85219820Sjeff#include <netinet/ip_var.h>
86219820Sjeff
87219820Sjeff#ifdef MAC
88219820Sjeff
89219820Sjeff/*
90219820Sjeff * Declare that the kernel provides MAC support, version 1.  This permits
91219820Sjeff * modules to refuse to be loaded if the necessary support isn't present,
92219820Sjeff * even if it's pre-boot.
93219820Sjeff */
94219820SjeffMODULE_VERSION(kernel_mac_support, 1);
95219820Sjeff
96219820SjeffSYSCTL_DECL(_security);
97219820Sjeff
98219820SjeffSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
99219820Sjeff    "TrustedBSD MAC policy controls");
100219820Sjeff
101219820Sjeff#if MAC_MAX_POLICIES > 32
102219820Sjeff#error "MAC_MAX_POLICIES too large"
103219820Sjeff#endif
104219820Sjeff
105219820Sjeffstatic unsigned int mac_max_policies = MAC_MAX_POLICIES;
106219820Sjeffstatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
107219820SjeffSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
108219820Sjeff    &mac_max_policies, 0, "");
109219820Sjeff
110219820Sjeff/*
111219820Sjeff * Has the kernel started generating labeled objects yet?  All read/write
112219820Sjeff * access to this variable is serialized during the boot process.  Following
113219820Sjeff * the end of serialization, we don't update this flag; no locking.
114219820Sjeff */
115272027Shselaskystatic int	mac_late = 0;
116219820Sjeff
117219820Sjeff/*
118219820Sjeff * Warn about EA transactions only the first time they happen.
119219820Sjeff * Weak coherency, no locking.
120219820Sjeff */
121219820Sjeffstatic int	ea_warn_once = 0;
122219820Sjeff
123219820Sjeffstatic int	mac_enforce_fs = 1;
124219820SjeffSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
125219820Sjeff    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
126219820SjeffTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
127219820Sjeff
128255932Salfredstatic int	mac_enforce_kld = 1;
129255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
130219820Sjeff    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
131255932SalfredTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
132255932Salfred
133255932Salfredstatic int	mac_enforce_network = 1;
134255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
135255932Salfred    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
136255932SalfredTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
137255932Salfred
138255932Salfredstatic int	mac_enforce_pipe = 1;
139255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
140255932Salfred    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
141255932SalfredTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
142255932Salfred
143255932Salfredstatic int	mac_enforce_process = 1;
144255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
145255932Salfred    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
146255932SalfredTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
147255932Salfred
148255932Salfredstatic int	mac_enforce_socket = 1;
149219820SjeffSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
150219820Sjeff    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
151219820SjeffTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
152219820Sjeff
153219820Sjeffstatic int	mac_enforce_system = 1;
154219820SjeffSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
155219820Sjeff    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
156255932SalfredTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
157255932Salfred
158255932Salfredstatic int	mac_enforce_vm = 1;
159255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
160255932Salfred    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
161219820SjeffTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
162219820Sjeff
163219820Sjeffstatic int	mac_mmap_revocation = 1;
164255932SalfredSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
165255932Salfred    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
166255932Salfred    "relabel");
167219820Sjeffstatic int	mac_mmap_revocation_via_cow = 0;
168219820SjeffSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
169219820Sjeff    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
170255932Salfred    "copy-on-write semantics, or by removing all write access");
171255932Salfred
172219820Sjeff#ifdef MAC_DEBUG
173219820SjeffSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
174219820Sjeff    "TrustedBSD MAC debug info");
175219820Sjeff
176272027Shselaskystatic int	mac_debug_label_fallback = 0;
177272027ShselaskySYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
178272027Shselasky    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
179272027Shselasky    "when label is corrupted.");
180272027ShselaskyTUNABLE_INT("security.mac.debug_label_fallback",
181272027Shselasky    &mac_debug_label_fallback);
182272027Shselasky
183272027ShselaskySYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
184219820Sjeff    "TrustedBSD MAC object counters");
185219820Sjeff
186255932Salfredstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
187255932Salfred    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
188255932Salfred    nmacipqs, nmacpipes, nmacprocs;
189255932Salfred
190255932SalfredSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
191219820Sjeff    &nmacmbufs, 0, "number of mbufs in use");
192219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
193219820Sjeff    &nmaccreds, 0, "number of ucreds in use");
194219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
195219820Sjeff    &nmacifnets, 0, "number of ifnets in use");
196219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
197219820Sjeff    &nmacipqs, 0, "number of ipqs in use");
198219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
199219820Sjeff    &nmacbpfdescs, 0, "number of bpfdescs in use");
200255932SalfredSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
201219820Sjeff    &nmacsockets, 0, "number of sockets in use");
202219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
203219820Sjeff    &nmacpipes, 0, "number of pipes in use");
204255932SalfredSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
205255932Salfred    &nmacprocs, 0, "number of procs in use");
206219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
207219820Sjeff    &nmacmounts, 0, "number of mounts in use");
208255932SalfredSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
209219820Sjeff    &nmactemp, 0, "number of temporary labels in use");
210219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
211219820Sjeff    &nmacvnodes, 0, "number of vnodes in use");
212219820SjeffSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
213219820Sjeff    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
214255932Salfred#endif
215219820Sjeff
216219820Sjeffstatic int	error_select(int error1, int error2);
217255932Salfredstatic int	mac_policy_register(struct mac_policy_conf *mpc);
218219820Sjeffstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
219219820Sjeff
220219820Sjeffstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
221219820Sjeff		    struct vnode *vp, int *prot);
222219820Sjeffstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
223219820Sjeff		    struct ucred *cred, struct vm_map *map);
224219820Sjeff
225219820Sjeffstatic void	mac_destroy_socket_label(struct label *label);
226219820Sjeff
227255932Salfredstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
228219820Sjeff		    struct vnode *vp, struct label *intlabel);
229219820Sjeff
230255932SalfredMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
231219820SjeffMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
232219820Sjeff
233219820Sjeff/*
234219820Sjeff * mac_policy_list stores the list of active policies.  A busy count is
235219820Sjeff * maintained for the list, stored in mac_policy_busy.  The busy count
236255932Salfred * is protected by mac_policy_list_lock; the list may be modified only
237255932Salfred * while the busy count is 0, requiring that the lock be held to
238255932Salfred * prevent new references to the list from being acquired.  For almost
239255932Salfred * all operations, incrementing the busy count is sufficient to
240272027Shselasky * guarantee consistency, as the list cannot be modified while the
241272027Shselasky * busy count is elevated.  For a few special operations involving a
242272027Shselasky * change to the list of active policies, the lock itself must be held.
243272027Shselasky * A condition variable, mac_policy_list_not_busy, is used to signal
244272027Shselasky * potential exclusive consumers that they should try to acquire the
245272027Shselasky * lock if a first attempt at exclusive access fails.
246272027Shselasky */
247272027Shselaskystatic struct mtx mac_policy_list_lock;
248255932Salfredstatic struct cv mac_policy_list_not_busy;
249272027Shselaskystatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
250272027Shselaskystatic int mac_policy_list_busy;
251272027Shselasky
252272027Shselasky#define	MAC_POLICY_LIST_LOCKINIT() do {					\
253272027Shselasky	mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL,	\
254272027Shselasky	    MTX_DEF);							\
255255932Salfred	cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy");	\
256255932Salfred} while (0)
257255932Salfred
258219820Sjeff#define	MAC_POLICY_LIST_LOCK() do {					\
259	mtx_lock(&mac_policy_list_lock);				\
260} while (0)
261
262#define	MAC_POLICY_LIST_UNLOCK() do {					\
263	mtx_unlock(&mac_policy_list_lock);				\
264} while (0)
265
266/*
267 * We manually invoke WITNESS_WARN() to allow Witness to generate
268 * warnings even if we don't end up ever triggering the wait at
269 * run-time.  The consumer of the exclusive interface must not hold
270 * any locks (other than potentially Giant) since we may sleep for
271 * long (potentially indefinite) periods of time waiting for the
272 * framework to become quiescent so that a policy list change may
273 * be made.
274 */
275#define	MAC_POLICY_LIST_EXCLUSIVE() do {				\
276	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,			\
277 	    "mac_policy_list_exclusive() at %s:%d", __FILE__, __LINE__);\
278	mtx_lock(&mac_policy_list_lock);				\
279	while (mac_policy_list_busy != 0)				\
280		cv_wait(&mac_policy_list_not_busy,			\
281		    &mac_policy_list_lock);				\
282} while (0)
283
284#define	MAC_POLICY_LIST_BUSY() do {					\
285	MAC_POLICY_LIST_LOCK();						\
286	mac_policy_list_busy++;						\
287	MAC_POLICY_LIST_UNLOCK();					\
288} while (0)
289
290#define	MAC_POLICY_LIST_UNBUSY() do {					\
291	MAC_POLICY_LIST_LOCK();						\
292	mac_policy_list_busy--;						\
293	KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK"));	\
294	if (mac_policy_list_busy == 0)					\
295		cv_signal(&mac_policy_list_not_busy);			\
296	MAC_POLICY_LIST_UNLOCK();					\
297} while (0)
298
299/*
300 * MAC_CHECK performs the designated check by walking the policy
301 * module list and checking with each as to how it feels about the
302 * request.  Note that it returns its value via 'error' in the scope
303 * of the caller.
304 */
305#define	MAC_CHECK(check, args...) do {					\
306	struct mac_policy_conf *mpc;					\
307									\
308	error = 0;							\
309	MAC_POLICY_LIST_BUSY();						\
310	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
311		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
312			error = error_select(				\
313			    mpc->mpc_ops->mpo_ ## check (args),		\
314			    error);					\
315	}								\
316	MAC_POLICY_LIST_UNBUSY();					\
317} while (0)
318
319/*
320 * MAC_BOOLEAN performs the designated boolean composition by walking
321 * the module list, invoking each instance of the operation, and
322 * combining the results using the passed C operator.  Note that it
323 * returns its value via 'result' in the scope of the caller, which
324 * should be initialized by the caller in a meaningful way to get
325 * a meaningful result.
326 */
327#define	MAC_BOOLEAN(operation, composition, args...) do {		\
328	struct mac_policy_conf *mpc;					\
329									\
330	MAC_POLICY_LIST_BUSY();						\
331	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
332		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
333			result = result composition			\
334			    mpc->mpc_ops->mpo_ ## operation (args);	\
335	}								\
336	MAC_POLICY_LIST_UNBUSY();					\
337} while (0)
338
339#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
340    outbuflen) do {							\
341	char *curptr, *curptr_start, *element_name, *element_temp;	\
342	size_t left, left_start, len;					\
343	int claimed, first, first_start, ignorenotfound;		\
344									\
345	error = 0;							\
346	element_temp = elementlist;					\
347	curptr = outbuf;						\
348	curptr[0] = '\0';						\
349	left = outbuflen;						\
350	first = 1;							\
351	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
352		curptr_start = curptr;					\
353		left_start = left;					\
354		first_start = first;					\
355		if (element_name[0] == '?') {				\
356			element_name++;					\
357			ignorenotfound = 1;				\
358		} else							\
359			ignorenotfound = 0;				\
360		claimed = 0;						\
361		if (first) {						\
362			len = snprintf(curptr, left, "%s/",		\
363			    element_name);				\
364			first = 0;					\
365		} else							\
366			len = snprintf(curptr, left, ",%s/",		\
367			    element_name);				\
368		if (len >= left) {					\
369			error = EINVAL;		/* XXXMAC: E2BIG */	\
370			break;						\
371		}							\
372		curptr += len;						\
373		left -= len;						\
374									\
375		MAC_CHECK(externalize_ ## type, label, element_name,	\
376		    curptr, left, &len, &claimed);			\
377		if (error)						\
378			break;						\
379		if (claimed == 1) {					\
380			if (len >= outbuflen) {				\
381				error = EINVAL;	/* XXXMAC: E2BIG */	\
382				break;					\
383			}						\
384			curptr += len;					\
385			left -= len;					\
386		} else if (claimed == 0 && ignorenotfound) {		\
387			/*						\
388			 * Revert addition of the label element		\
389			 * name.					\
390			 */						\
391			curptr = curptr_start;				\
392			*curptr = '\0';					\
393			left = left_start;				\
394			first = first_start;				\
395		} else {						\
396			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
397			break;						\
398		}							\
399	}								\
400} while (0)
401
402#define	MAC_INTERNALIZE(type, label, instring) do {			\
403	char *element, *element_name, *element_data;			\
404	int claimed;							\
405									\
406	error = 0;							\
407	element = instring;						\
408	while ((element_name = strsep(&element, ",")) != NULL) {	\
409		element_data = element_name;				\
410		element_name = strsep(&element_data, "/");		\
411		if (element_data == NULL) {				\
412			error = EINVAL;					\
413			break;						\
414		}							\
415		claimed = 0;						\
416		MAC_CHECK(internalize_ ## type, label, element_name,	\
417		    element_data, &claimed);				\
418		if (error)						\
419			break;						\
420		if (claimed != 1) {					\
421			/* XXXMAC: Another error here? */		\
422			error = EINVAL;					\
423			break;						\
424		}							\
425	}								\
426} while (0)
427
428/*
429 * MAC_PERFORM performs the designated operation by walking the policy
430 * module list and invoking that operation for each policy.
431 */
432#define	MAC_PERFORM(operation, args...) do {				\
433	struct mac_policy_conf *mpc;					\
434									\
435	MAC_POLICY_LIST_BUSY();						\
436	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
437		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
438			mpc->mpc_ops->mpo_ ## operation (args);		\
439	}								\
440	MAC_POLICY_LIST_UNBUSY();					\
441} while (0)
442
443/*
444 * Initialize the MAC subsystem, including appropriate SMP locks.
445 */
446static void
447mac_init(void)
448{
449
450	LIST_INIT(&mac_policy_list);
451	MAC_POLICY_LIST_LOCKINIT();
452}
453
454/*
455 * For the purposes of modules that want to know if they were loaded
456 * "early", set the mac_late flag once we've processed modules either
457 * linked into the kernel, or loaded before the kernel startup.
458 */
459static void
460mac_late_init(void)
461{
462
463	mac_late = 1;
464}
465
466/*
467 * Allow MAC policy modules to register during boot, etc.
468 */
469int
470mac_policy_modevent(module_t mod, int type, void *data)
471{
472	struct mac_policy_conf *mpc;
473	int error;
474
475	error = 0;
476	mpc = (struct mac_policy_conf *) data;
477
478	switch (type) {
479	case MOD_LOAD:
480		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
481		    mac_late) {
482			printf("mac_policy_modevent: can't load %s policy "
483			    "after booting\n", mpc->mpc_name);
484			error = EBUSY;
485			break;
486		}
487		error = mac_policy_register(mpc);
488		break;
489	case MOD_UNLOAD:
490		/* Don't unregister the module if it was never registered. */
491		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
492		    != 0)
493			error = mac_policy_unregister(mpc);
494		else
495			error = 0;
496		break;
497	default:
498		break;
499	}
500
501	return (error);
502}
503
504static int
505mac_policy_register(struct mac_policy_conf *mpc)
506{
507	struct mac_policy_conf *tmpc;
508	int slot;
509
510	MAC_POLICY_LIST_EXCLUSIVE();
511	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
512		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
513			MAC_POLICY_LIST_UNLOCK();
514			return (EEXIST);
515		}
516	}
517	if (mpc->mpc_field_off != NULL) {
518		slot = ffs(mac_policy_offsets_free);
519		if (slot == 0) {
520			MAC_POLICY_LIST_UNLOCK();
521			return (ENOMEM);
522		}
523		slot--;
524		mac_policy_offsets_free &= ~(1 << slot);
525		*mpc->mpc_field_off = slot;
526	}
527	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
528	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
529
530	/* Per-policy initialization. */
531	if (mpc->mpc_ops->mpo_init != NULL)
532		(*(mpc->mpc_ops->mpo_init))(mpc);
533	MAC_POLICY_LIST_UNLOCK();
534
535	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
536	    mpc->mpc_name);
537
538	return (0);
539}
540
541static int
542mac_policy_unregister(struct mac_policy_conf *mpc)
543{
544
545	/*
546	 * If we fail the load, we may get a request to unload.  Check
547	 * to see if we did the run-time registration, and if not,
548	 * silently succeed.
549	 */
550	MAC_POLICY_LIST_EXCLUSIVE();
551	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
552		MAC_POLICY_LIST_UNLOCK();
553		return (0);
554	}
555#if 0
556	/*
557	 * Don't allow unloading modules with private data.
558	 */
559	if (mpc->mpc_field_off != NULL) {
560		MAC_POLICY_LIST_UNLOCK();
561		return (EBUSY);
562	}
563#endif
564	/*
565	 * Only allow the unload to proceed if the module is unloadable
566	 * by its own definition.
567	 */
568	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
569		MAC_POLICY_LIST_UNLOCK();
570		return (EBUSY);
571	}
572	if (mpc->mpc_ops->mpo_destroy != NULL)
573		(*(mpc->mpc_ops->mpo_destroy))(mpc);
574
575	LIST_REMOVE(mpc, mpc_list);
576	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
577
578	MAC_POLICY_LIST_UNLOCK();
579
580	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
581	    mpc->mpc_name);
582
583	return (0);
584}
585
586/*
587 * Define an error value precedence, and given two arguments, selects the
588 * value with the higher precedence.
589 */
590static int
591error_select(int error1, int error2)
592{
593
594	/* Certain decision-making errors take top priority. */
595	if (error1 == EDEADLK || error2 == EDEADLK)
596		return (EDEADLK);
597
598	/* Invalid arguments should be reported where possible. */
599	if (error1 == EINVAL || error2 == EINVAL)
600		return (EINVAL);
601
602	/* Precedence goes to "visibility", with both process and file. */
603	if (error1 == ESRCH || error2 == ESRCH)
604		return (ESRCH);
605
606	if (error1 == ENOENT || error2 == ENOENT)
607		return (ENOENT);
608
609	/* Precedence goes to DAC/MAC protections. */
610	if (error1 == EACCES || error2 == EACCES)
611		return (EACCES);
612
613	/* Precedence goes to privilege. */
614	if (error1 == EPERM || error2 == EPERM)
615		return (EPERM);
616
617	/* Precedence goes to error over success; otherwise, arbitrary. */
618	if (error1 != 0)
619		return (error1);
620	return (error2);
621}
622
623static void
624mac_init_label(struct label *label)
625{
626
627	bzero(label, sizeof(*label));
628	label->l_flags = MAC_FLAG_INITIALIZED;
629}
630
631static void
632mac_destroy_label(struct label *label)
633{
634
635	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
636	    ("destroying uninitialized label"));
637
638	bzero(label, sizeof(*label));
639	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
640}
641
642void
643mac_init_bpfdesc(struct bpf_d *bpf_d)
644{
645
646	mac_init_label(&bpf_d->bd_label);
647	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
648#ifdef MAC_DEBUG
649	atomic_add_int(&nmacbpfdescs, 1);
650#endif
651}
652
653static void
654mac_init_cred_label(struct label *label)
655{
656
657	mac_init_label(label);
658	MAC_PERFORM(init_cred_label, label);
659#ifdef MAC_DEBUG
660	atomic_add_int(&nmaccreds, 1);
661#endif
662}
663
664void
665mac_init_cred(struct ucred *cred)
666{
667
668	mac_init_cred_label(&cred->cr_label);
669}
670
671void
672mac_init_devfsdirent(struct devfs_dirent *de)
673{
674
675	mac_init_label(&de->de_label);
676	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
677#ifdef MAC_DEBUG
678	atomic_add_int(&nmacdevfsdirents, 1);
679#endif
680}
681
682static void
683mac_init_ifnet_label(struct label *label)
684{
685
686	mac_init_label(label);
687	MAC_PERFORM(init_ifnet_label, label);
688#ifdef MAC_DEBUG
689	atomic_add_int(&nmacifnets, 1);
690#endif
691}
692
693void
694mac_init_ifnet(struct ifnet *ifp)
695{
696
697	mac_init_ifnet_label(&ifp->if_label);
698}
699
700void
701mac_init_ipq(struct ipq *ipq)
702{
703
704	mac_init_label(&ipq->ipq_label);
705	MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
706#ifdef MAC_DEBUG
707	atomic_add_int(&nmacipqs, 1);
708#endif
709}
710
711int
712mac_init_mbuf(struct mbuf *m, int flag)
713{
714	int error;
715
716	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
717
718	mac_init_label(&m->m_pkthdr.label);
719
720	MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
721	if (error) {
722		MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
723		mac_destroy_label(&m->m_pkthdr.label);
724	}
725
726#ifdef MAC_DEBUG
727	if (error == 0)
728		atomic_add_int(&nmacmbufs, 1);
729#endif
730	return (error);
731}
732
733void
734mac_init_mount(struct mount *mp)
735{
736
737	mac_init_label(&mp->mnt_mntlabel);
738	mac_init_label(&mp->mnt_fslabel);
739	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
740	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
741#ifdef MAC_DEBUG
742	atomic_add_int(&nmacmounts, 1);
743#endif
744}
745
746static void
747mac_init_pipe_label(struct label *label)
748{
749
750	mac_init_label(label);
751	MAC_PERFORM(init_pipe_label, label);
752#ifdef MAC_DEBUG
753	atomic_add_int(&nmacpipes, 1);
754#endif
755}
756
757void
758mac_init_pipe(struct pipe *pipe)
759{
760	struct label *label;
761
762	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
763	pipe->pipe_label = label;
764	pipe->pipe_peer->pipe_label = label;
765	mac_init_pipe_label(label);
766}
767
768void
769mac_init_proc(struct proc *p)
770{
771
772	mac_init_label(&p->p_label);
773	MAC_PERFORM(init_proc_label, &p->p_label);
774#ifdef MAC_DEBUG
775	atomic_add_int(&nmacprocs, 1);
776#endif
777}
778
779static int
780mac_init_socket_label(struct label *label, int flag)
781{
782	int error;
783
784	mac_init_label(label);
785
786	MAC_CHECK(init_socket_label, label, flag);
787	if (error) {
788		MAC_PERFORM(destroy_socket_label, label);
789		mac_destroy_label(label);
790	}
791
792#ifdef MAC_DEBUG
793	if (error == 0)
794		atomic_add_int(&nmacsockets, 1);
795#endif
796
797	return (error);
798}
799
800static int
801mac_init_socket_peer_label(struct label *label, int flag)
802{
803	int error;
804
805	mac_init_label(label);
806
807	MAC_CHECK(init_socket_peer_label, label, flag);
808	if (error) {
809		MAC_PERFORM(destroy_socket_label, label);
810		mac_destroy_label(label);
811	}
812
813	return (error);
814}
815
816int
817mac_init_socket(struct socket *socket, int flag)
818{
819	int error;
820
821	error = mac_init_socket_label(&socket->so_label, flag);
822	if (error)
823		return (error);
824
825	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
826	if (error)
827		mac_destroy_socket_label(&socket->so_label);
828
829	return (error);
830}
831
832void
833mac_init_vnode_label(struct label *label)
834{
835
836	mac_init_label(label);
837	MAC_PERFORM(init_vnode_label, label);
838#ifdef MAC_DEBUG
839	atomic_add_int(&nmacvnodes, 1);
840#endif
841}
842
843void
844mac_init_vnode(struct vnode *vp)
845{
846
847	mac_init_vnode_label(&vp->v_label);
848}
849
850void
851mac_destroy_bpfdesc(struct bpf_d *bpf_d)
852{
853
854	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
855	mac_destroy_label(&bpf_d->bd_label);
856#ifdef MAC_DEBUG
857	atomic_subtract_int(&nmacbpfdescs, 1);
858#endif
859}
860
861static void
862mac_destroy_cred_label(struct label *label)
863{
864
865	MAC_PERFORM(destroy_cred_label, label);
866	mac_destroy_label(label);
867#ifdef MAC_DEBUG
868	atomic_subtract_int(&nmaccreds, 1);
869#endif
870}
871
872void
873mac_destroy_cred(struct ucred *cred)
874{
875
876	mac_destroy_cred_label(&cred->cr_label);
877}
878
879void
880mac_destroy_devfsdirent(struct devfs_dirent *de)
881{
882
883	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
884	mac_destroy_label(&de->de_label);
885#ifdef MAC_DEBUG
886	atomic_subtract_int(&nmacdevfsdirents, 1);
887#endif
888}
889
890static void
891mac_destroy_ifnet_label(struct label *label)
892{
893
894	MAC_PERFORM(destroy_ifnet_label, label);
895	mac_destroy_label(label);
896#ifdef MAC_DEBUG
897	atomic_subtract_int(&nmacifnets, 1);
898#endif
899}
900
901void
902mac_destroy_ifnet(struct ifnet *ifp)
903{
904
905	mac_destroy_ifnet_label(&ifp->if_label);
906}
907
908void
909mac_destroy_ipq(struct ipq *ipq)
910{
911
912	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
913	mac_destroy_label(&ipq->ipq_label);
914#ifdef MAC_DEBUG
915	atomic_subtract_int(&nmacipqs, 1);
916#endif
917}
918
919void
920mac_destroy_mbuf(struct mbuf *m)
921{
922
923	MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
924	mac_destroy_label(&m->m_pkthdr.label);
925#ifdef MAC_DEBUG
926	atomic_subtract_int(&nmacmbufs, 1);
927#endif
928}
929
930void
931mac_destroy_mount(struct mount *mp)
932{
933
934	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
935	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
936	mac_destroy_label(&mp->mnt_fslabel);
937	mac_destroy_label(&mp->mnt_mntlabel);
938#ifdef MAC_DEBUG
939	atomic_subtract_int(&nmacmounts, 1);
940#endif
941}
942
943static void
944mac_destroy_pipe_label(struct label *label)
945{
946
947	MAC_PERFORM(destroy_pipe_label, label);
948	mac_destroy_label(label);
949#ifdef MAC_DEBUG
950	atomic_subtract_int(&nmacpipes, 1);
951#endif
952}
953
954void
955mac_destroy_pipe(struct pipe *pipe)
956{
957
958	mac_destroy_pipe_label(pipe->pipe_label);
959	free(pipe->pipe_label, M_MACPIPELABEL);
960}
961
962void
963mac_destroy_proc(struct proc *p)
964{
965
966	MAC_PERFORM(destroy_proc_label, &p->p_label);
967	mac_destroy_label(&p->p_label);
968#ifdef MAC_DEBUG
969	atomic_subtract_int(&nmacprocs, 1);
970#endif
971}
972
973static void
974mac_destroy_socket_label(struct label *label)
975{
976
977	MAC_PERFORM(destroy_socket_label, label);
978	mac_destroy_label(label);
979#ifdef MAC_DEBUG
980	atomic_subtract_int(&nmacsockets, 1);
981#endif
982}
983
984static void
985mac_destroy_socket_peer_label(struct label *label)
986{
987
988	MAC_PERFORM(destroy_socket_peer_label, label);
989	mac_destroy_label(label);
990}
991
992void
993mac_destroy_socket(struct socket *socket)
994{
995
996	mac_destroy_socket_label(&socket->so_label);
997	mac_destroy_socket_peer_label(&socket->so_peerlabel);
998}
999
1000void
1001mac_destroy_vnode_label(struct label *label)
1002{
1003
1004	MAC_PERFORM(destroy_vnode_label, label);
1005	mac_destroy_label(label);
1006#ifdef MAC_DEBUG
1007	atomic_subtract_int(&nmacvnodes, 1);
1008#endif
1009}
1010
1011void
1012mac_destroy_vnode(struct vnode *vp)
1013{
1014
1015	mac_destroy_vnode_label(&vp->v_label);
1016}
1017
1018static void
1019mac_copy_pipe_label(struct label *src, struct label *dest)
1020{
1021
1022	MAC_PERFORM(copy_pipe_label, src, dest);
1023}
1024
1025void
1026mac_copy_vnode_label(struct label *src, struct label *dest)
1027{
1028
1029	MAC_PERFORM(copy_vnode_label, src, dest);
1030}
1031
1032static int
1033mac_check_structmac_consistent(struct mac *mac)
1034{
1035
1036	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1037		return (EINVAL);
1038
1039	return (0);
1040}
1041
1042static int
1043mac_externalize_cred_label(struct label *label, char *elements,
1044    char *outbuf, size_t outbuflen, int flags)
1045{
1046	int error;
1047
1048	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1049
1050	return (error);
1051}
1052
1053static int
1054mac_externalize_ifnet_label(struct label *label, char *elements,
1055    char *outbuf, size_t outbuflen, int flags)
1056{
1057	int error;
1058
1059	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1060
1061	return (error);
1062}
1063
1064static int
1065mac_externalize_pipe_label(struct label *label, char *elements,
1066    char *outbuf, size_t outbuflen, int flags)
1067{
1068	int error;
1069
1070	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1071
1072	return (error);
1073}
1074
1075static int
1076mac_externalize_socket_label(struct label *label, char *elements,
1077    char *outbuf, size_t outbuflen, int flags)
1078{
1079	int error;
1080
1081	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1082
1083	return (error);
1084}
1085
1086static int
1087mac_externalize_socket_peer_label(struct label *label, char *elements,
1088    char *outbuf, size_t outbuflen, int flags)
1089{
1090	int error;
1091
1092	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1093
1094	return (error);
1095}
1096
1097static int
1098mac_externalize_vnode_label(struct label *label, char *elements,
1099    char *outbuf, size_t outbuflen, int flags)
1100{
1101	int error;
1102
1103	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1104
1105	return (error);
1106}
1107
1108static int
1109mac_internalize_cred_label(struct label *label, char *string)
1110{
1111	int error;
1112
1113	MAC_INTERNALIZE(cred_label, label, string);
1114
1115	return (error);
1116}
1117
1118static int
1119mac_internalize_ifnet_label(struct label *label, char *string)
1120{
1121	int error;
1122
1123	MAC_INTERNALIZE(ifnet_label, label, string);
1124
1125	return (error);
1126}
1127
1128static int
1129mac_internalize_pipe_label(struct label *label, char *string)
1130{
1131	int error;
1132
1133	MAC_INTERNALIZE(pipe_label, label, string);
1134
1135	return (error);
1136}
1137
1138static int
1139mac_internalize_socket_label(struct label *label, char *string)
1140{
1141	int error;
1142
1143	MAC_INTERNALIZE(socket_label, label, string);
1144
1145	return (error);
1146}
1147
1148static int
1149mac_internalize_vnode_label(struct label *label, char *string)
1150{
1151	int error;
1152
1153	MAC_INTERNALIZE(vnode_label, label, string);
1154
1155	return (error);
1156}
1157
1158/*
1159 * Initialize MAC label for the first kernel process, from which other
1160 * kernel processes and threads are spawned.
1161 */
1162void
1163mac_create_proc0(struct ucred *cred)
1164{
1165
1166	MAC_PERFORM(create_proc0, cred);
1167}
1168
1169/*
1170 * Initialize MAC label for the first userland process, from which other
1171 * userland processes and threads are spawned.
1172 */
1173void
1174mac_create_proc1(struct ucred *cred)
1175{
1176
1177	MAC_PERFORM(create_proc1, cred);
1178}
1179
1180void
1181mac_thread_userret(struct thread *td)
1182{
1183
1184	MAC_PERFORM(thread_userret, td);
1185}
1186
1187/*
1188 * When a new process is created, its label must be initialized.  Generally,
1189 * this involves inheritence from the parent process, modulo possible
1190 * deltas.  This function allows that processing to take place.
1191 */
1192void
1193mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1194{
1195
1196	MAC_PERFORM(create_cred, parent_cred, child_cred);
1197}
1198
1199void
1200mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1201    struct vnode *vp)
1202{
1203
1204	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1205	    &vp->v_label);
1206}
1207
1208void
1209mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1210    struct vnode *vp)
1211{
1212
1213	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1214	    &de->de_label, vp, &vp->v_label);
1215}
1216
1217int
1218mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1219{
1220	int error;
1221
1222	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1223
1224	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1225	    &vp->v_label);
1226
1227	return (error);
1228}
1229
1230void
1231mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1232{
1233
1234	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1235	    &vp->v_label);
1236}
1237
1238int
1239mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1240    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1241{
1242	int error;
1243
1244	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1245	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1246
1247	error = VOP_OPENEXTATTR(vp, cred, curthread);
1248	if (error == EOPNOTSUPP) {
1249		/* XXX: Optionally abort if transactions not supported. */
1250		if (ea_warn_once == 0) {
1251			printf("Warning: transactions not supported "
1252			    "in EA write.\n");
1253			ea_warn_once = 1;
1254		}
1255	} else if (error)
1256		return (error);
1257
1258	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1259	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1260
1261	if (error) {
1262		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1263		return (error);
1264	}
1265
1266	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1267
1268	if (error == EOPNOTSUPP)
1269		error = 0;				/* XXX */
1270
1271	return (error);
1272}
1273
1274static int
1275mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1276    struct label *intlabel)
1277{
1278	int error;
1279
1280	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1281
1282	error = VOP_OPENEXTATTR(vp, cred, curthread);
1283	if (error == EOPNOTSUPP) {
1284		/* XXX: Optionally abort if transactions not supported. */
1285		if (ea_warn_once == 0) {
1286			printf("Warning: transactions not supported "
1287			    "in EA write.\n");
1288			ea_warn_once = 1;
1289		}
1290	} else if (error)
1291		return (error);
1292
1293	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1294
1295	if (error) {
1296		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1297		return (error);
1298	}
1299
1300	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1301
1302	if (error == EOPNOTSUPP)
1303		error = 0;				/* XXX */
1304
1305	return (error);
1306}
1307
1308int
1309mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1310    struct label *execlabelstorage)
1311{
1312	struct mac mac;
1313	char *buffer;
1314	int error;
1315
1316	if (mac_p == NULL)
1317		return (0);
1318
1319	error = copyin(mac_p, &mac, sizeof(mac));
1320	if (error)
1321		return (error);
1322
1323	error = mac_check_structmac_consistent(&mac);
1324	if (error)
1325		return (error);
1326
1327	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1328	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1329	if (error) {
1330		free(buffer, M_MACTEMP);
1331		return (error);
1332	}
1333
1334	mac_init_cred_label(execlabelstorage);
1335	error = mac_internalize_cred_label(execlabelstorage, buffer);
1336	free(buffer, M_MACTEMP);
1337	if (error) {
1338		mac_destroy_cred_label(execlabelstorage);
1339		return (error);
1340	}
1341	imgp->execlabel = execlabelstorage;
1342	return (0);
1343}
1344
1345void
1346mac_execve_exit(struct image_params *imgp)
1347{
1348	if (imgp->execlabel != NULL)
1349		mac_destroy_cred_label(imgp->execlabel);
1350}
1351
1352void
1353mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1354    struct label *interpvnodelabel, struct image_params *imgp)
1355{
1356
1357	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1358
1359	if (!mac_enforce_process && !mac_enforce_fs)
1360		return;
1361
1362	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1363	    interpvnodelabel, imgp, imgp->execlabel);
1364}
1365
1366int
1367mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1368    struct label *interpvnodelabel, struct image_params *imgp)
1369{
1370	int result;
1371
1372	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1373
1374	if (!mac_enforce_process && !mac_enforce_fs)
1375		return (0);
1376
1377	result = 0;
1378	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1379	    interpvnodelabel, imgp, imgp->execlabel);
1380
1381	return (result);
1382}
1383
1384int
1385mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1386{
1387	int error;
1388
1389	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1390
1391	if (!mac_enforce_fs)
1392		return (0);
1393
1394	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1395	return (error);
1396}
1397
1398int
1399mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1400{
1401	int error;
1402
1403	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1404
1405	if (!mac_enforce_fs)
1406		return (0);
1407
1408	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1409	return (error);
1410}
1411
1412int
1413mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1414{
1415	int error;
1416
1417	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1418
1419	if (!mac_enforce_fs)
1420		return (0);
1421
1422	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1423	return (error);
1424}
1425
1426int
1427mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1428    struct componentname *cnp, struct vattr *vap)
1429{
1430	int error;
1431
1432	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1433
1434	if (!mac_enforce_fs)
1435		return (0);
1436
1437	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1438	return (error);
1439}
1440
1441int
1442mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1443    struct componentname *cnp)
1444{
1445	int error;
1446
1447	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1448	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1449
1450	if (!mac_enforce_fs)
1451		return (0);
1452
1453	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1454	    &vp->v_label, cnp);
1455	return (error);
1456}
1457
1458int
1459mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1460    acl_type_t type)
1461{
1462	int error;
1463
1464	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1465
1466	if (!mac_enforce_fs)
1467		return (0);
1468
1469	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1470	return (error);
1471}
1472
1473int
1474mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1475    struct image_params *imgp)
1476{
1477	int error;
1478
1479	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1480
1481	if (!mac_enforce_process && !mac_enforce_fs)
1482		return (0);
1483
1484	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1485	    imgp->execlabel);
1486
1487	return (error);
1488}
1489
1490int
1491mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1492{
1493	int error;
1494
1495	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1496
1497	if (!mac_enforce_fs)
1498		return (0);
1499
1500	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1501	return (error);
1502}
1503
1504int
1505mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1506    int attrnamespace, const char *name, struct uio *uio)
1507{
1508	int error;
1509
1510	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1511
1512	if (!mac_enforce_fs)
1513		return (0);
1514
1515	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1516	    attrnamespace, name, uio);
1517	return (error);
1518}
1519
1520int
1521mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1522    struct vnode *vp, struct componentname *cnp)
1523{
1524	int error;
1525
1526	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1527	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1528
1529	if (!mac_enforce_fs)
1530		return (0);
1531
1532	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1533	    &vp->v_label, cnp);
1534	return (error);
1535}
1536
1537int
1538mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1539    struct componentname *cnp)
1540{
1541	int error;
1542
1543	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1544
1545	if (!mac_enforce_fs)
1546		return (0);
1547
1548	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1549	return (error);
1550}
1551
1552int
1553mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1554{
1555	int error;
1556
1557	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1558
1559	if (!mac_enforce_fs || !mac_enforce_vm)
1560		return (0);
1561
1562	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1563	return (error);
1564}
1565
1566void
1567mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1568{
1569	int result = *prot;
1570
1571	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1572
1573	if (!mac_enforce_fs || !mac_enforce_vm)
1574		return;
1575
1576	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1577	    &result);
1578
1579	*prot = result;
1580}
1581
1582int
1583mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1584{
1585	int error;
1586
1587	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1588
1589	if (!mac_enforce_fs || !mac_enforce_vm)
1590		return (0);
1591
1592	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1593	return (error);
1594}
1595
1596int
1597mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1598{
1599	int error;
1600
1601	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1602
1603	if (!mac_enforce_fs)
1604		return (0);
1605
1606	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1607	return (error);
1608}
1609
1610int
1611mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1612    struct vnode *vp)
1613{
1614	int error;
1615
1616	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1617
1618	if (!mac_enforce_fs)
1619		return (0);
1620
1621	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1622	    &vp->v_label);
1623
1624	return (error);
1625}
1626
1627int
1628mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1629    struct vnode *vp)
1630{
1631	int error;
1632
1633	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1634
1635	if (!mac_enforce_fs)
1636		return (0);
1637
1638	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1639	    &vp->v_label);
1640
1641	return (error);
1642}
1643
1644int
1645mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1646{
1647	int error;
1648
1649	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1650
1651	if (!mac_enforce_fs)
1652		return (0);
1653
1654	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1655	return (error);
1656}
1657
1658int
1659mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1660{
1661	int error;
1662
1663	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1664
1665	if (!mac_enforce_fs)
1666		return (0);
1667
1668	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1669	return (error);
1670}
1671
1672static int
1673mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1674    struct label *newlabel)
1675{
1676	int error;
1677
1678	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1679
1680	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1681
1682	return (error);
1683}
1684
1685int
1686mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1687    struct vnode *vp, struct componentname *cnp)
1688{
1689	int error;
1690
1691	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1692	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1693
1694	if (!mac_enforce_fs)
1695		return (0);
1696
1697	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1698	    &vp->v_label, cnp);
1699	return (error);
1700}
1701
1702int
1703mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1704    struct vnode *vp, int samedir, struct componentname *cnp)
1705{
1706	int error;
1707
1708	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1709	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1710
1711	if (!mac_enforce_fs)
1712		return (0);
1713
1714	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1715	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1716	return (error);
1717}
1718
1719int
1720mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1721{
1722	int error;
1723
1724	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1725
1726	if (!mac_enforce_fs)
1727		return (0);
1728
1729	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1730	return (error);
1731}
1732
1733int
1734mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1735    struct acl *acl)
1736{
1737	int error;
1738
1739	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1740
1741	if (!mac_enforce_fs)
1742		return (0);
1743
1744	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1745	return (error);
1746}
1747
1748int
1749mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1750    int attrnamespace, const char *name, struct uio *uio)
1751{
1752	int error;
1753
1754	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1755
1756	if (!mac_enforce_fs)
1757		return (0);
1758
1759	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1760	    attrnamespace, name, uio);
1761	return (error);
1762}
1763
1764int
1765mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1766{
1767	int error;
1768
1769	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1770
1771	if (!mac_enforce_fs)
1772		return (0);
1773
1774	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1775	return (error);
1776}
1777
1778int
1779mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1780{
1781	int error;
1782
1783	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1784
1785	if (!mac_enforce_fs)
1786		return (0);
1787
1788	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1789	return (error);
1790}
1791
1792int
1793mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1794    gid_t gid)
1795{
1796	int error;
1797
1798	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1799
1800	if (!mac_enforce_fs)
1801		return (0);
1802
1803	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1804	return (error);
1805}
1806
1807int
1808mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1809    struct timespec atime, struct timespec mtime)
1810{
1811	int error;
1812
1813	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1814
1815	if (!mac_enforce_fs)
1816		return (0);
1817
1818	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1819	    mtime);
1820	return (error);
1821}
1822
1823int
1824mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1825    struct vnode *vp)
1826{
1827	int error;
1828
1829	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1830
1831	if (!mac_enforce_fs)
1832		return (0);
1833
1834	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1835	    &vp->v_label);
1836	return (error);
1837}
1838
1839int
1840mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1841    struct vnode *vp)
1842{
1843	int error;
1844
1845	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1846
1847	if (!mac_enforce_fs)
1848		return (0);
1849
1850	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1851	    &vp->v_label);
1852
1853	return (error);
1854}
1855
1856/*
1857 * When relabeling a process, call out to the policies for the maximum
1858 * permission allowed for each object type we know about in its
1859 * memory space, and revoke access (in the least surprising ways we
1860 * know) when necessary.  The process lock is not held here.
1861 */
1862void
1863mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1864{
1865
1866	/* XXX freeze all other threads */
1867	mac_cred_mmapped_drop_perms_recurse(td, cred,
1868	    &td->td_proc->p_vmspace->vm_map);
1869	/* XXX allow other threads to continue */
1870}
1871
1872static __inline const char *
1873prot2str(vm_prot_t prot)
1874{
1875
1876	switch (prot & VM_PROT_ALL) {
1877	case VM_PROT_READ:
1878		return ("r--");
1879	case VM_PROT_READ | VM_PROT_WRITE:
1880		return ("rw-");
1881	case VM_PROT_READ | VM_PROT_EXECUTE:
1882		return ("r-x");
1883	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
1884		return ("rwx");
1885	case VM_PROT_WRITE:
1886		return ("-w-");
1887	case VM_PROT_EXECUTE:
1888		return ("--x");
1889	case VM_PROT_WRITE | VM_PROT_EXECUTE:
1890		return ("-wx");
1891	default:
1892		return ("---");
1893	}
1894}
1895
1896static void
1897mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
1898    struct vm_map *map)
1899{
1900	struct vm_map_entry *vme;
1901	int result;
1902	vm_prot_t revokeperms;
1903	vm_object_t object;
1904	vm_ooffset_t offset;
1905	struct vnode *vp;
1906
1907	if (!mac_mmap_revocation)
1908		return;
1909
1910	vm_map_lock_read(map);
1911	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
1912		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
1913			mac_cred_mmapped_drop_perms_recurse(td, cred,
1914			    vme->object.sub_map);
1915			continue;
1916		}
1917		/*
1918		 * Skip over entries that obviously are not shared.
1919		 */
1920		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
1921		    !vme->max_protection)
1922			continue;
1923		/*
1924		 * Drill down to the deepest backing object.
1925		 */
1926		offset = vme->offset;
1927		object = vme->object.vm_object;
1928		if (object == NULL)
1929			continue;
1930		while (object->backing_object != NULL) {
1931			object = object->backing_object;
1932			offset += object->backing_object_offset;
1933		}
1934		/*
1935		 * At the moment, vm_maps and objects aren't considered
1936		 * by the MAC system, so only things with backing by a
1937		 * normal object (read: vnodes) are checked.
1938		 */
1939		if (object->type != OBJT_VNODE)
1940			continue;
1941		vp = (struct vnode *)object->handle;
1942		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1943		result = vme->max_protection;
1944		mac_check_vnode_mmap_downgrade(cred, vp, &result);
1945		VOP_UNLOCK(vp, 0, td);
1946		/*
1947		 * Find out what maximum protection we may be allowing
1948		 * now but a policy needs to get removed.
1949		 */
1950		revokeperms = vme->max_protection & ~result;
1951		if (!revokeperms)
1952			continue;
1953		printf("pid %ld: revoking %s perms from %#lx:%ld "
1954		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
1955		    prot2str(revokeperms), (u_long)vme->start,
1956		    (long)(vme->end - vme->start),
1957		    prot2str(vme->max_protection), prot2str(vme->protection));
1958		vm_map_lock_upgrade(map);
1959		/*
1960		 * This is the really simple case: if a map has more
1961		 * max_protection than is allowed, but it's not being
1962		 * actually used (that is, the current protection is
1963		 * still allowed), we can just wipe it out and do
1964		 * nothing more.
1965		 */
1966		if ((vme->protection & revokeperms) == 0) {
1967			vme->max_protection -= revokeperms;
1968		} else {
1969			if (revokeperms & VM_PROT_WRITE) {
1970				/*
1971				 * In the more complicated case, flush out all
1972				 * pending changes to the object then turn it
1973				 * copy-on-write.
1974				 */
1975				vm_object_reference(object);
1976				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1977				vm_object_page_clean(object,
1978				    OFF_TO_IDX(offset),
1979				    OFF_TO_IDX(offset + vme->end - vme->start +
1980					PAGE_MASK),
1981				    OBJPC_SYNC);
1982				VOP_UNLOCK(vp, 0, td);
1983				vm_object_deallocate(object);
1984				/*
1985				 * Why bother if there's no read permissions
1986				 * anymore?  For the rest, we need to leave
1987				 * the write permissions on for COW, or
1988				 * remove them entirely if configured to.
1989				 */
1990				if (!mac_mmap_revocation_via_cow) {
1991					vme->max_protection &= ~VM_PROT_WRITE;
1992					vme->protection &= ~VM_PROT_WRITE;
1993				} if ((revokeperms & VM_PROT_READ) == 0)
1994					vme->eflags |= MAP_ENTRY_COW |
1995					    MAP_ENTRY_NEEDS_COPY;
1996			}
1997			if (revokeperms & VM_PROT_EXECUTE) {
1998				vme->max_protection &= ~VM_PROT_EXECUTE;
1999				vme->protection &= ~VM_PROT_EXECUTE;
2000			}
2001			if (revokeperms & VM_PROT_READ) {
2002				vme->max_protection = 0;
2003				vme->protection = 0;
2004			}
2005			pmap_protect(map->pmap, vme->start, vme->end,
2006			    vme->protection & ~revokeperms);
2007			vm_map_simplify_entry(map, vme);
2008		}
2009		vm_map_lock_downgrade(map);
2010	}
2011	vm_map_unlock_read(map);
2012}
2013
2014/*
2015 * When the subject's label changes, it may require revocation of privilege
2016 * to mapped objects.  This can't be done on-the-fly later with a unified
2017 * buffer cache.
2018 */
2019static void
2020mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2021{
2022
2023	MAC_PERFORM(relabel_cred, cred, newlabel);
2024}
2025
2026void
2027mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2028{
2029
2030	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2031}
2032
2033void
2034mac_create_ifnet(struct ifnet *ifnet)
2035{
2036
2037	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2038}
2039
2040void
2041mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2042{
2043
2044	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2045}
2046
2047void
2048mac_create_socket(struct ucred *cred, struct socket *socket)
2049{
2050
2051	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2052}
2053
2054void
2055mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2056{
2057
2058	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2059}
2060
2061void
2062mac_create_socket_from_socket(struct socket *oldsocket,
2063    struct socket *newsocket)
2064{
2065
2066	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2067	    newsocket, &newsocket->so_label);
2068}
2069
2070static void
2071mac_relabel_socket(struct ucred *cred, struct socket *socket,
2072    struct label *newlabel)
2073{
2074
2075	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2076}
2077
2078static void
2079mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2080{
2081
2082	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2083}
2084
2085void
2086mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2087{
2088
2089	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2090	    socket, &socket->so_peerlabel);
2091}
2092
2093void
2094mac_set_socket_peer_from_socket(struct socket *oldsocket,
2095    struct socket *newsocket)
2096{
2097
2098	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2099	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2100}
2101
2102void
2103mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2104{
2105
2106	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2107	    datagram, &datagram->m_pkthdr.label);
2108}
2109
2110void
2111mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2112{
2113
2114	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2115	    fragment, &fragment->m_pkthdr.label);
2116}
2117
2118void
2119mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2120{
2121
2122	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2123	    &ipq->ipq_label);
2124}
2125
2126void
2127mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2128{
2129
2130	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2131	    newmbuf, &newmbuf->m_pkthdr.label);
2132}
2133
2134void
2135mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2136{
2137
2138	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2139	    &mbuf->m_pkthdr.label);
2140}
2141
2142void
2143mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2144{
2145
2146	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2147	    &mbuf->m_pkthdr.label);
2148}
2149
2150void
2151mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2152{
2153
2154	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2155	    &mbuf->m_pkthdr.label);
2156}
2157
2158void
2159mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2160    struct mbuf *newmbuf)
2161{
2162
2163	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2164	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2165	    &newmbuf->m_pkthdr.label);
2166}
2167
2168void
2169mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2170{
2171
2172	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2173	    newmbuf, &newmbuf->m_pkthdr.label);
2174}
2175
2176int
2177mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2178{
2179	int result;
2180
2181	result = 1;
2182	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2183	    ipq, &ipq->ipq_label);
2184
2185	return (result);
2186}
2187
2188void
2189mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2190{
2191
2192	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2193	    &ipq->ipq_label);
2194}
2195
2196void
2197mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2198{
2199
2200	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2201	    &mbuf->m_pkthdr.label);
2202}
2203
2204void
2205mac_create_mount(struct ucred *cred, struct mount *mp)
2206{
2207
2208	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2209	    &mp->mnt_fslabel);
2210}
2211
2212void
2213mac_create_root_mount(struct ucred *cred, struct mount *mp)
2214{
2215
2216	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2217	    &mp->mnt_fslabel);
2218}
2219
2220int
2221mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2222{
2223	int error;
2224
2225	if (!mac_enforce_network)
2226		return (0);
2227
2228	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2229	    &ifnet->if_label);
2230
2231	return (error);
2232}
2233
2234static int
2235mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2236{
2237	int error;
2238
2239	MAC_CHECK(check_cred_relabel, cred, newlabel);
2240
2241	return (error);
2242}
2243
2244int
2245mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2246{
2247	int error;
2248
2249	if (!mac_enforce_process)
2250		return (0);
2251
2252	MAC_CHECK(check_cred_visible, u1, u2);
2253
2254	return (error);
2255}
2256
2257int
2258mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2259{
2260	int error;
2261
2262	if (!mac_enforce_network)
2263		return (0);
2264
2265	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2266	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2267		if_printf(ifnet, "not initialized\n");
2268
2269	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2270	    &mbuf->m_pkthdr.label);
2271
2272	return (error);
2273}
2274
2275int
2276mac_check_kenv_dump(struct ucred *cred)
2277{
2278	int error;
2279
2280	if (!mac_enforce_system)
2281		return (0);
2282
2283	MAC_CHECK(check_kenv_dump, cred);
2284
2285	return (error);
2286}
2287
2288int
2289mac_check_kenv_get(struct ucred *cred, char *name)
2290{
2291	int error;
2292
2293	if (!mac_enforce_system)
2294		return (0);
2295
2296	MAC_CHECK(check_kenv_get, cred, name);
2297
2298	return (error);
2299}
2300
2301int
2302mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2303{
2304	int error;
2305
2306	if (!mac_enforce_system)
2307		return (0);
2308
2309	MAC_CHECK(check_kenv_set, cred, name, value);
2310
2311	return (error);
2312}
2313
2314int
2315mac_check_kenv_unset(struct ucred *cred, char *name)
2316{
2317	int error;
2318
2319	if (!mac_enforce_system)
2320		return (0);
2321
2322	MAC_CHECK(check_kenv_unset, cred, name);
2323
2324	return (error);
2325}
2326
2327int
2328mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2329{
2330	int error;
2331
2332	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2333
2334	if (!mac_enforce_kld)
2335		return (0);
2336
2337	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2338
2339	return (error);
2340}
2341
2342int
2343mac_check_kld_stat(struct ucred *cred)
2344{
2345	int error;
2346
2347	if (!mac_enforce_kld)
2348		return (0);
2349
2350	MAC_CHECK(check_kld_stat, cred);
2351
2352	return (error);
2353}
2354
2355int
2356mac_check_kld_unload(struct ucred *cred)
2357{
2358	int error;
2359
2360	if (!mac_enforce_kld)
2361		return (0);
2362
2363	MAC_CHECK(check_kld_unload, cred);
2364
2365	return (error);
2366}
2367
2368int
2369mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2370{
2371	int error;
2372
2373	if (!mac_enforce_fs)
2374		return (0);
2375
2376	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2377
2378	return (error);
2379}
2380
2381int
2382mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2383    void *data)
2384{
2385	int error;
2386
2387	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2388
2389	if (!mac_enforce_pipe)
2390		return (0);
2391
2392	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2393
2394	return (error);
2395}
2396
2397int
2398mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2399{
2400	int error;
2401
2402	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2403
2404	if (!mac_enforce_pipe)
2405		return (0);
2406
2407	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2408
2409	return (error);
2410}
2411
2412int
2413mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2414{
2415	int error;
2416
2417	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2418
2419	if (!mac_enforce_pipe)
2420		return (0);
2421
2422	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2423
2424	return (error);
2425}
2426
2427static int
2428mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2429    struct label *newlabel)
2430{
2431	int error;
2432
2433	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2434
2435	if (!mac_enforce_pipe)
2436		return (0);
2437
2438	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2439
2440	return (error);
2441}
2442
2443int
2444mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2445{
2446	int error;
2447
2448	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2449
2450	if (!mac_enforce_pipe)
2451		return (0);
2452
2453	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2454
2455	return (error);
2456}
2457
2458int
2459mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2460{
2461	int error;
2462
2463	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2464
2465	if (!mac_enforce_pipe)
2466		return (0);
2467
2468	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2469
2470	return (error);
2471}
2472
2473int
2474mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2475{
2476	int error;
2477
2478	PROC_LOCK_ASSERT(proc, MA_OWNED);
2479
2480	if (!mac_enforce_process)
2481		return (0);
2482
2483	MAC_CHECK(check_proc_debug, cred, proc);
2484
2485	return (error);
2486}
2487
2488int
2489mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2490{
2491	int error;
2492
2493	PROC_LOCK_ASSERT(proc, MA_OWNED);
2494
2495	if (!mac_enforce_process)
2496		return (0);
2497
2498	MAC_CHECK(check_proc_sched, cred, proc);
2499
2500	return (error);
2501}
2502
2503int
2504mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2505{
2506	int error;
2507
2508	PROC_LOCK_ASSERT(proc, MA_OWNED);
2509
2510	if (!mac_enforce_process)
2511		return (0);
2512
2513	MAC_CHECK(check_proc_signal, cred, proc, signum);
2514
2515	return (error);
2516}
2517
2518int
2519mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2520    struct sockaddr *sockaddr)
2521{
2522	int error;
2523
2524	if (!mac_enforce_socket)
2525		return (0);
2526
2527	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2528	    sockaddr);
2529
2530	return (error);
2531}
2532
2533int
2534mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2535    struct sockaddr *sockaddr)
2536{
2537	int error;
2538
2539	if (!mac_enforce_socket)
2540		return (0);
2541
2542	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2543	    sockaddr);
2544
2545	return (error);
2546}
2547
2548int
2549mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2550{
2551	int error;
2552
2553	if (!mac_enforce_socket)
2554		return (0);
2555
2556	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2557	    &mbuf->m_pkthdr.label);
2558
2559	return (error);
2560}
2561
2562int
2563mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2564{
2565	int error;
2566
2567	if (!mac_enforce_socket)
2568		return (0);
2569
2570	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2571	return (error);
2572}
2573
2574int
2575mac_check_socket_receive(struct ucred *cred, struct socket *so)
2576{
2577	int error;
2578
2579	if (!mac_enforce_socket)
2580		return (0);
2581
2582	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2583
2584	return (error);
2585}
2586
2587static int
2588mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2589    struct label *newlabel)
2590{
2591	int error;
2592
2593	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2594	    newlabel);
2595
2596	return (error);
2597}
2598
2599int
2600mac_check_socket_send(struct ucred *cred, struct socket *so)
2601{
2602	int error;
2603
2604	if (!mac_enforce_socket)
2605		return (0);
2606
2607	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2608
2609	return (error);
2610}
2611
2612int
2613mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2614{
2615	int error;
2616
2617	if (!mac_enforce_socket)
2618		return (0);
2619
2620	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2621
2622	return (error);
2623}
2624
2625int
2626mac_check_sysarch_ioperm(struct ucred *cred)
2627{
2628	int error;
2629
2630	if (!mac_enforce_system)
2631		return (0);
2632
2633	MAC_CHECK(check_sysarch_ioperm, cred);
2634	return (error);
2635}
2636
2637int
2638mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2639{
2640	int error;
2641
2642	if (vp != NULL) {
2643		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2644	}
2645
2646	if (!mac_enforce_system)
2647		return (0);
2648
2649	MAC_CHECK(check_system_acct, cred, vp,
2650	    vp != NULL ? &vp->v_label : NULL);
2651
2652	return (error);
2653}
2654
2655int
2656mac_check_system_nfsd(struct ucred *cred)
2657{
2658	int error;
2659
2660	if (!mac_enforce_system)
2661		return (0);
2662
2663	MAC_CHECK(check_system_nfsd, cred);
2664
2665	return (error);
2666}
2667
2668int
2669mac_check_system_reboot(struct ucred *cred, int howto)
2670{
2671	int error;
2672
2673	if (!mac_enforce_system)
2674		return (0);
2675
2676	MAC_CHECK(check_system_reboot, cred, howto);
2677
2678	return (error);
2679}
2680
2681int
2682mac_check_system_settime(struct ucred *cred)
2683{
2684	int error;
2685
2686	if (!mac_enforce_system)
2687		return (0);
2688
2689	MAC_CHECK(check_system_settime, cred);
2690
2691	return (error);
2692}
2693
2694int
2695mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2696{
2697	int error;
2698
2699	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2700
2701	if (!mac_enforce_system)
2702		return (0);
2703
2704	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2705	return (error);
2706}
2707
2708int
2709mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2710{
2711	int error;
2712
2713	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2714
2715	if (!mac_enforce_system)
2716		return (0);
2717
2718	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2719	return (error);
2720}
2721
2722int
2723mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2724    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2725{
2726	int error;
2727
2728	/*
2729	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2730	 * but since it's not exported from kern_sysctl.c, we can't.
2731	 */
2732	if (!mac_enforce_system)
2733		return (0);
2734
2735	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2736	    inkernel, new, newlen);
2737
2738	return (error);
2739}
2740
2741int
2742mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2743    struct ifnet *ifnet)
2744{
2745	char *elements, *buffer;
2746	struct mac mac;
2747	int error;
2748
2749	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2750	if (error)
2751		return (error);
2752
2753	error = mac_check_structmac_consistent(&mac);
2754	if (error)
2755		return (error);
2756
2757	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2758	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2759	if (error) {
2760		free(elements, M_MACTEMP);
2761		return (error);
2762	}
2763
2764	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2765	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2766	    buffer, mac.m_buflen, M_WAITOK);
2767	if (error == 0)
2768		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2769
2770	free(buffer, M_MACTEMP);
2771	free(elements, M_MACTEMP);
2772
2773	return (error);
2774}
2775
2776int
2777mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2778    struct ifnet *ifnet)
2779{
2780	struct label intlabel;
2781	struct mac mac;
2782	char *buffer;
2783	int error;
2784
2785	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2786	if (error)
2787		return (error);
2788
2789	error = mac_check_structmac_consistent(&mac);
2790	if (error)
2791		return (error);
2792
2793	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2794	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2795	if (error) {
2796		free(buffer, M_MACTEMP);
2797		return (error);
2798	}
2799
2800	mac_init_ifnet_label(&intlabel);
2801	error = mac_internalize_ifnet_label(&intlabel, buffer);
2802	free(buffer, M_MACTEMP);
2803	if (error) {
2804		mac_destroy_ifnet_label(&intlabel);
2805		return (error);
2806	}
2807
2808	/*
2809	 * XXX: Note that this is a redundant privilege check, since
2810	 * policies impose this check themselves if required by the
2811	 * policy.  Eventually, this should go away.
2812	 */
2813	error = suser_cred(cred, 0);
2814	if (error) {
2815		mac_destroy_ifnet_label(&intlabel);
2816		return (error);
2817	}
2818
2819	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2820	    &intlabel);
2821	if (error) {
2822		mac_destroy_ifnet_label(&intlabel);
2823		return (error);
2824	}
2825
2826	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2827
2828	mac_destroy_ifnet_label(&intlabel);
2829	return (0);
2830}
2831
2832void
2833mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
2834{
2835
2836	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
2837}
2838
2839void
2840mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
2841    struct devfs_dirent *dd, struct devfs_dirent *de)
2842{
2843
2844	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
2845	    &de->de_label);
2846}
2847
2848void
2849mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
2850    struct devfs_dirent *de)
2851{
2852
2853	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
2854	    &de->de_label);
2855}
2856
2857int
2858mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2859    struct mac *mac)
2860{
2861	struct label intlabel;
2862	char *buffer;
2863	int error;
2864
2865	error = mac_check_structmac_consistent(mac);
2866	if (error)
2867		return (error);
2868
2869	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2870	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2871	if (error) {
2872		free(buffer, M_MACTEMP);
2873		return (error);
2874	}
2875
2876	mac_init_socket_label(&intlabel, M_WAITOK);
2877	error = mac_internalize_socket_label(&intlabel, buffer);
2878	free(buffer, M_MACTEMP);
2879	if (error) {
2880		mac_destroy_socket_label(&intlabel);
2881		return (error);
2882	}
2883
2884	mac_check_socket_relabel(cred, so, &intlabel);
2885	if (error) {
2886		mac_destroy_socket_label(&intlabel);
2887		return (error);
2888	}
2889
2890	mac_relabel_socket(cred, so, &intlabel);
2891
2892	mac_destroy_socket_label(&intlabel);
2893	return (0);
2894}
2895
2896int
2897mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2898{
2899	int error;
2900
2901	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2902
2903	error = mac_check_pipe_relabel(cred, pipe, label);
2904	if (error)
2905		return (error);
2906
2907	mac_relabel_pipe(cred, pipe, label);
2908
2909	return (0);
2910}
2911
2912int
2913mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2914    struct mac *mac)
2915{
2916	char *buffer, *elements;
2917	int error;
2918
2919	error = mac_check_structmac_consistent(mac);
2920	if (error)
2921		return (error);
2922
2923	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2924	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2925	if (error) {
2926		free(elements, M_MACTEMP);
2927		return (error);
2928	}
2929
2930	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2931	error = mac_externalize_socket_label(&so->so_label, elements,
2932	    buffer, mac->m_buflen, M_WAITOK);
2933	if (error == 0)
2934		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2935
2936	free(buffer, M_MACTEMP);
2937	free(elements, M_MACTEMP);
2938
2939	return (error);
2940}
2941
2942int
2943mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2944    struct mac *mac)
2945{
2946	char *elements, *buffer;
2947	int error;
2948
2949	error = mac_check_structmac_consistent(mac);
2950	if (error)
2951		return (error);
2952
2953	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2954	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2955	if (error) {
2956		free(elements, M_MACTEMP);
2957		return (error);
2958	}
2959
2960	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2961	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2962	    elements, buffer, mac->m_buflen, M_WAITOK);
2963	if (error == 0)
2964		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2965
2966	free(buffer, M_MACTEMP);
2967	free(elements, M_MACTEMP);
2968
2969	return (error);
2970}
2971
2972/*
2973 * Implementation of VOP_SETLABEL() that relies on extended attributes
2974 * to store label data.  Can be referenced by filesystems supporting
2975 * extended attributes.
2976 */
2977int
2978vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2979{
2980	struct vnode *vp = ap->a_vp;
2981	struct label *intlabel = ap->a_label;
2982	int error;
2983
2984	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2985
2986	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2987		return (EOPNOTSUPP);
2988
2989	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2990	if (error)
2991		return (error);
2992
2993	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2994
2995	return (0);
2996}
2997
2998static int
2999vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3000{
3001	int error;
3002
3003	if (vp->v_mount == NULL) {
3004		/* printf("vn_setlabel: null v_mount\n"); */
3005		if (vp->v_type != VNON)
3006			printf("vn_setlabel: null v_mount with non-VNON\n");
3007		return (EBADF);
3008	}
3009
3010	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3011		return (EOPNOTSUPP);
3012
3013	/*
3014	 * Multi-phase commit.  First check the policies to confirm the
3015	 * change is OK.  Then commit via the filesystem.  Finally,
3016	 * update the actual vnode label.  Question: maybe the filesystem
3017	 * should update the vnode at the end as part of VOP_SETLABEL()?
3018	 */
3019	error = mac_check_vnode_relabel(cred, vp, intlabel);
3020	if (error)
3021		return (error);
3022
3023	/*
3024	 * VADMIN provides the opportunity for the filesystem to make
3025	 * decisions about who is and is not able to modify labels
3026	 * and protections on files.  This might not be right.  We can't
3027	 * assume VOP_SETLABEL() will do it, because we might implement
3028	 * that as part of vop_stdsetlabel_ea().
3029	 */
3030	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3031	if (error)
3032		return (error);
3033
3034	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3035	if (error)
3036		return (error);
3037
3038	return (0);
3039}
3040
3041int
3042__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3043{
3044	char *elements, *buffer;
3045	struct mac mac;
3046	struct proc *tproc;
3047	struct ucred *tcred;
3048	int error;
3049
3050	error = copyin(uap->mac_p, &mac, sizeof(mac));
3051	if (error)
3052		return (error);
3053
3054	error = mac_check_structmac_consistent(&mac);
3055	if (error)
3056		return (error);
3057
3058	tproc = pfind(uap->pid);
3059	if (tproc == NULL)
3060		return (ESRCH);
3061
3062	tcred = NULL;				/* Satisfy gcc. */
3063	error = p_cansee(td, tproc);
3064	if (error == 0)
3065		tcred = crhold(tproc->p_ucred);
3066	PROC_UNLOCK(tproc);
3067	if (error)
3068		return (error);
3069
3070	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3071	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3072	if (error) {
3073		free(elements, M_MACTEMP);
3074		crfree(tcred);
3075		return (error);
3076	}
3077
3078	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3079	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3080	    buffer, mac.m_buflen, M_WAITOK);
3081	if (error == 0)
3082		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3083
3084	free(buffer, M_MACTEMP);
3085	free(elements, M_MACTEMP);
3086	crfree(tcred);
3087	return (error);
3088}
3089
3090/*
3091 * MPSAFE
3092 */
3093int
3094__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3095{
3096	char *elements, *buffer;
3097	struct mac mac;
3098	int error;
3099
3100	error = copyin(uap->mac_p, &mac, sizeof(mac));
3101	if (error)
3102		return (error);
3103
3104	error = mac_check_structmac_consistent(&mac);
3105	if (error)
3106		return (error);
3107
3108	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3109	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3110	if (error) {
3111		free(elements, M_MACTEMP);
3112		return (error);
3113	}
3114
3115	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3116	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3117	    elements, buffer, mac.m_buflen, M_WAITOK);
3118	if (error == 0)
3119		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3120
3121	free(buffer, M_MACTEMP);
3122	free(elements, M_MACTEMP);
3123	return (error);
3124}
3125
3126/*
3127 * MPSAFE
3128 */
3129int
3130__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3131{
3132	struct ucred *newcred, *oldcred;
3133	struct label intlabel;
3134	struct proc *p;
3135	struct mac mac;
3136	char *buffer;
3137	int error;
3138
3139	error = copyin(uap->mac_p, &mac, sizeof(mac));
3140	if (error)
3141		return (error);
3142
3143	error = mac_check_structmac_consistent(&mac);
3144	if (error)
3145		return (error);
3146
3147	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3148	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3149	if (error) {
3150		free(buffer, M_MACTEMP);
3151		return (error);
3152	}
3153
3154	mac_init_cred_label(&intlabel);
3155	error = mac_internalize_cred_label(&intlabel, buffer);
3156	free(buffer, M_MACTEMP);
3157	if (error) {
3158		mac_destroy_cred_label(&intlabel);
3159		return (error);
3160	}
3161
3162	newcred = crget();
3163
3164	p = td->td_proc;
3165	PROC_LOCK(p);
3166	oldcred = p->p_ucred;
3167
3168	error = mac_check_cred_relabel(oldcred, &intlabel);
3169	if (error) {
3170		PROC_UNLOCK(p);
3171		crfree(newcred);
3172		goto out;
3173	}
3174
3175	setsugid(p);
3176	crcopy(newcred, oldcred);
3177	mac_relabel_cred(newcred, &intlabel);
3178	p->p_ucred = newcred;
3179
3180	/*
3181	 * Grab additional reference for use while revoking mmaps, prior
3182	 * to releasing the proc lock and sharing the cred.
3183	 */
3184	crhold(newcred);
3185	PROC_UNLOCK(p);
3186
3187	if (mac_enforce_vm) {
3188		mtx_lock(&Giant);
3189		mac_cred_mmapped_drop_perms(td, newcred);
3190		mtx_unlock(&Giant);
3191	}
3192
3193	crfree(newcred);	/* Free revocation reference. */
3194	crfree(oldcred);
3195
3196out:
3197	mac_destroy_cred_label(&intlabel);
3198	return (error);
3199}
3200
3201/*
3202 * MPSAFE
3203 */
3204int
3205__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3206{
3207	char *elements, *buffer;
3208	struct label intlabel;
3209	struct file *fp;
3210	struct mac mac;
3211	struct vnode *vp;
3212	struct pipe *pipe;
3213	short label_type;
3214	int error;
3215
3216	error = copyin(uap->mac_p, &mac, sizeof(mac));
3217	if (error)
3218		return (error);
3219
3220	error = mac_check_structmac_consistent(&mac);
3221	if (error)
3222		return (error);
3223
3224	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3225	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3226	if (error) {
3227		free(elements, M_MACTEMP);
3228		return (error);
3229	}
3230
3231	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3232	mtx_lock(&Giant);				/* VFS */
3233	error = fget(td, uap->fd, &fp);
3234	if (error)
3235		goto out;
3236
3237	label_type = fp->f_type;
3238	switch (fp->f_type) {
3239	case DTYPE_FIFO:
3240	case DTYPE_VNODE:
3241		vp = fp->f_data;
3242
3243		mac_init_vnode_label(&intlabel);
3244
3245		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3246		mac_copy_vnode_label(&vp->v_label, &intlabel);
3247		VOP_UNLOCK(vp, 0, td);
3248
3249		break;
3250	case DTYPE_PIPE:
3251		pipe = fp->f_data;
3252
3253		mac_init_pipe_label(&intlabel);
3254
3255		PIPE_LOCK(pipe);
3256		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3257		PIPE_UNLOCK(pipe);
3258		break;
3259	default:
3260		error = EINVAL;
3261		fdrop(fp, td);
3262		goto out;
3263	}
3264	fdrop(fp, td);
3265
3266	switch (label_type) {
3267	case DTYPE_FIFO:
3268	case DTYPE_VNODE:
3269		if (error == 0)
3270			error = mac_externalize_vnode_label(&intlabel,
3271			    elements, buffer, mac.m_buflen, M_WAITOK);
3272		mac_destroy_vnode_label(&intlabel);
3273		break;
3274	case DTYPE_PIPE:
3275		error = mac_externalize_pipe_label(&intlabel, elements,
3276		    buffer, mac.m_buflen, M_WAITOK);
3277		mac_destroy_pipe_label(&intlabel);
3278		break;
3279	default:
3280		panic("__mac_get_fd: corrupted label_type");
3281	}
3282
3283	if (error == 0)
3284		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3285
3286out:
3287	mtx_unlock(&Giant);				/* VFS */
3288	free(buffer, M_MACTEMP);
3289	free(elements, M_MACTEMP);
3290
3291	return (error);
3292}
3293
3294/*
3295 * MPSAFE
3296 */
3297int
3298__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3299{
3300	char *elements, *buffer;
3301	struct nameidata nd;
3302	struct label intlabel;
3303	struct mac mac;
3304	int error;
3305
3306	error = copyin(uap->mac_p, &mac, sizeof(mac));
3307	if (error)
3308		return (error);
3309
3310	error = mac_check_structmac_consistent(&mac);
3311	if (error)
3312		return (error);
3313
3314	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3315	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3316	if (error) {
3317		free(elements, M_MACTEMP);
3318		return (error);
3319	}
3320
3321	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3322	mtx_lock(&Giant);				/* VFS */
3323	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3324	    td);
3325	error = namei(&nd);
3326	if (error)
3327		goto out;
3328
3329	mac_init_vnode_label(&intlabel);
3330	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3331	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3332	    mac.m_buflen, M_WAITOK);
3333
3334	NDFREE(&nd, 0);
3335	mac_destroy_vnode_label(&intlabel);
3336
3337	if (error == 0)
3338		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3339
3340out:
3341	mtx_unlock(&Giant);				/* VFS */
3342
3343	free(buffer, M_MACTEMP);
3344	free(elements, M_MACTEMP);
3345
3346	return (error);
3347}
3348
3349/*
3350 * MPSAFE
3351 */
3352int
3353__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3354{
3355	char *elements, *buffer;
3356	struct nameidata nd;
3357	struct label intlabel;
3358	struct mac mac;
3359	int error;
3360
3361	error = copyin(uap->mac_p, &mac, sizeof(mac));
3362	if (error)
3363		return (error);
3364
3365	error = mac_check_structmac_consistent(&mac);
3366	if (error)
3367		return (error);
3368
3369	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3370	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3371	if (error) {
3372		free(elements, M_MACTEMP);
3373		return (error);
3374	}
3375
3376	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3377	mtx_lock(&Giant);				/* VFS */
3378	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3379	    td);
3380	error = namei(&nd);
3381	if (error)
3382		goto out;
3383
3384	mac_init_vnode_label(&intlabel);
3385	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3386	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3387	    mac.m_buflen, M_WAITOK);
3388	NDFREE(&nd, 0);
3389	mac_destroy_vnode_label(&intlabel);
3390
3391	if (error == 0)
3392		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3393
3394out:
3395	mtx_unlock(&Giant);				/* VFS */
3396
3397	free(buffer, M_MACTEMP);
3398	free(elements, M_MACTEMP);
3399
3400	return (error);
3401}
3402
3403/*
3404 * MPSAFE
3405 */
3406int
3407__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3408{
3409	struct label intlabel;
3410	struct pipe *pipe;
3411	struct file *fp;
3412	struct mount *mp;
3413	struct vnode *vp;
3414	struct mac mac;
3415	char *buffer;
3416	int error;
3417
3418	error = copyin(uap->mac_p, &mac, sizeof(mac));
3419	if (error)
3420		return (error);
3421
3422	error = mac_check_structmac_consistent(&mac);
3423	if (error)
3424		return (error);
3425
3426	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3427	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3428	if (error) {
3429		free(buffer, M_MACTEMP);
3430		return (error);
3431	}
3432
3433	mtx_lock(&Giant);				/* VFS */
3434
3435	error = fget(td, uap->fd, &fp);
3436	if (error)
3437		goto out;
3438
3439	switch (fp->f_type) {
3440	case DTYPE_FIFO:
3441	case DTYPE_VNODE:
3442		mac_init_vnode_label(&intlabel);
3443		error = mac_internalize_vnode_label(&intlabel, buffer);
3444		if (error) {
3445			mac_destroy_vnode_label(&intlabel);
3446			break;
3447		}
3448
3449		vp = fp->f_data;
3450		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3451		if (error != 0) {
3452			mac_destroy_vnode_label(&intlabel);
3453			break;
3454		}
3455
3456		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3457		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3458		VOP_UNLOCK(vp, 0, td);
3459		vn_finished_write(mp);
3460
3461		mac_destroy_vnode_label(&intlabel);
3462		break;
3463
3464	case DTYPE_PIPE:
3465		mac_init_pipe_label(&intlabel);
3466		error = mac_internalize_pipe_label(&intlabel, buffer);
3467		if (error == 0) {
3468			pipe = fp->f_data;
3469			PIPE_LOCK(pipe);
3470			error = mac_pipe_label_set(td->td_ucred, pipe,
3471			    &intlabel);
3472			PIPE_UNLOCK(pipe);
3473		}
3474
3475		mac_destroy_pipe_label(&intlabel);
3476		break;
3477
3478	default:
3479		error = EINVAL;
3480	}
3481
3482	fdrop(fp, td);
3483out:
3484	mtx_unlock(&Giant);				/* VFS */
3485
3486	free(buffer, M_MACTEMP);
3487
3488	return (error);
3489}
3490
3491/*
3492 * MPSAFE
3493 */
3494int
3495__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3496{
3497	struct label intlabel;
3498	struct nameidata nd;
3499	struct mount *mp;
3500	struct mac mac;
3501	char *buffer;
3502	int error;
3503
3504	error = copyin(uap->mac_p, &mac, sizeof(mac));
3505	if (error)
3506		return (error);
3507
3508	error = mac_check_structmac_consistent(&mac);
3509	if (error)
3510		return (error);
3511
3512	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3513	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3514	if (error) {
3515		free(buffer, M_MACTEMP);
3516		return (error);
3517	}
3518
3519	mac_init_vnode_label(&intlabel);
3520	error = mac_internalize_vnode_label(&intlabel, buffer);
3521	free(buffer, M_MACTEMP);
3522	if (error) {
3523		mac_destroy_vnode_label(&intlabel);
3524		return (error);
3525	}
3526
3527	mtx_lock(&Giant);				/* VFS */
3528
3529	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3530	    td);
3531	error = namei(&nd);
3532	if (error == 0) {
3533		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3534		if (error == 0)
3535			error = vn_setlabel(nd.ni_vp, &intlabel,
3536			    td->td_ucred);
3537		vn_finished_write(mp);
3538	}
3539
3540	NDFREE(&nd, 0);
3541	mtx_unlock(&Giant);				/* VFS */
3542	mac_destroy_vnode_label(&intlabel);
3543
3544	return (error);
3545}
3546
3547/*
3548 * MPSAFE
3549 */
3550int
3551__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3552{
3553	struct label intlabel;
3554	struct nameidata nd;
3555	struct mount *mp;
3556	struct mac mac;
3557	char *buffer;
3558	int error;
3559
3560	error = copyin(uap->mac_p, &mac, sizeof(mac));
3561	if (error)
3562		return (error);
3563
3564	error = mac_check_structmac_consistent(&mac);
3565	if (error)
3566		return (error);
3567
3568	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3569	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3570	if (error) {
3571		free(buffer, M_MACTEMP);
3572		return (error);
3573	}
3574
3575	mac_init_vnode_label(&intlabel);
3576	error = mac_internalize_vnode_label(&intlabel, buffer);
3577	free(buffer, M_MACTEMP);
3578	if (error) {
3579		mac_destroy_vnode_label(&intlabel);
3580		return (error);
3581	}
3582
3583	mtx_lock(&Giant);				/* VFS */
3584
3585	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3586	    td);
3587	error = namei(&nd);
3588	if (error == 0) {
3589		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3590		if (error == 0)
3591			error = vn_setlabel(nd.ni_vp, &intlabel,
3592			    td->td_ucred);
3593		vn_finished_write(mp);
3594	}
3595
3596	NDFREE(&nd, 0);
3597	mtx_unlock(&Giant);				/* VFS */
3598	mac_destroy_vnode_label(&intlabel);
3599
3600	return (error);
3601}
3602
3603/*
3604 * MPSAFE
3605 */
3606int
3607mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3608{
3609	struct mac_policy_conf *mpc;
3610	char target[MAC_MAX_POLICY_NAME];
3611	int error;
3612
3613	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3614	if (error)
3615		return (error);
3616
3617	error = ENOSYS;
3618	MAC_POLICY_LIST_BUSY();
3619	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3620		if (strcmp(mpc->mpc_name, target) == 0 &&
3621		    mpc->mpc_ops->mpo_syscall != NULL) {
3622			error = mpc->mpc_ops->mpo_syscall(td,
3623			    uap->call, uap->arg);
3624			goto out;
3625		}
3626	}
3627
3628out:
3629	MAC_POLICY_LIST_UNBUSY();
3630	return (error);
3631}
3632
3633SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3634SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3635
3636#else /* !MAC */
3637
3638int
3639__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3640{
3641
3642	return (ENOSYS);
3643}
3644
3645int
3646__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3647{
3648
3649	return (ENOSYS);
3650}
3651
3652int
3653__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3654{
3655
3656	return (ENOSYS);
3657}
3658
3659int
3660__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3661{
3662
3663	return (ENOSYS);
3664}
3665
3666int
3667__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3668{
3669
3670	return (ENOSYS);
3671}
3672
3673int
3674__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3675{
3676
3677	return (ENOSYS);
3678}
3679
3680int
3681__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3682{
3683
3684	return (ENOSYS);
3685}
3686
3687int
3688__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3689{
3690
3691	return (ENOSYS);
3692}
3693
3694int
3695__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3696{
3697
3698	return (ENOSYS);
3699}
3700
3701int
3702mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3703{
3704
3705	return (ENOSYS);
3706}
3707
3708#endif
3709