mac_process.c revision 107698
1100894Srwatson/*-
2100894Srwatson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin
4100894Srwatson * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
5100894Srwatson * All rights reserved.
6100894Srwatson *
7100894Srwatson * This software was developed by Robert Watson and Ilmar Habibulin for the
8100894Srwatson * TrustedBSD Project.
9100894Srwatson *
10106392Srwatson * This software was developed for the FreeBSD Project in part by Network
11106392Srwatson * Associates Laboratories, the Security Research Division of Network
12106392Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13106392Srwatson * as part of the DARPA CHATS research program.
14100894Srwatson *
15100894Srwatson * Redistribution and use in source and binary forms, with or without
16100894Srwatson * modification, are permitted provided that the following conditions
17100894Srwatson * are met:
18100894Srwatson * 1. Redistributions of source code must retain the above copyright
19100894Srwatson *    notice, this list of conditions and the following disclaimer.
20100894Srwatson * 2. Redistributions in binary form must reproduce the above copyright
21100894Srwatson *    notice, this list of conditions and the following disclaimer in the
22100894Srwatson *    documentation and/or other materials provided with the distribution.
23100894Srwatson *
24100894Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25100894Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26100894Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27100894Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28100894Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29100894Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30100894Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31100894Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32100894Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33100894Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34100894Srwatson * SUCH DAMAGE.
35100894Srwatson *
36100894Srwatson * $FreeBSD: head/sys/security/mac/mac_process.c 107698 2002-12-09 03:44:28Z rwatson $
37100894Srwatson */
38100894Srwatson/*
39100894Srwatson * Developed by the TrustedBSD Project.
40100894Srwatson *
41100894Srwatson * Framework for extensible kernel access control.  Kernel and userland
42100894Srwatson * interface to the framework, policy registration and composition.
43100894Srwatson */
44100894Srwatson
45100894Srwatson#include "opt_mac.h"
46104300Sphk#include "opt_devfs.h"
47101173Srwatson
48100894Srwatson#include <sys/param.h>
49106856Srwatson#include <sys/condvar.h>
50100979Srwatson#include <sys/extattr.h>
51106468Srwatson#include <sys/imgact.h>
52100979Srwatson#include <sys/kernel.h>
53100979Srwatson#include <sys/lock.h>
54102949Sbde#include <sys/malloc.h>
55100979Srwatson#include <sys/mutex.h>
56100979Srwatson#include <sys/mac.h>
57101712Srwatson#include <sys/module.h>
58100979Srwatson#include <sys/proc.h>
59100979Srwatson#include <sys/systm.h>
60100894Srwatson#include <sys/sysproto.h>
61100894Srwatson#include <sys/sysent.h>
62100979Srwatson#include <sys/vnode.h>
63100979Srwatson#include <sys/mount.h>
64100979Srwatson#include <sys/file.h>
65100979Srwatson#include <sys/namei.h>
66100979Srwatson#include <sys/socket.h>
67100979Srwatson#include <sys/pipe.h>
68100979Srwatson#include <sys/socketvar.h>
69100979Srwatson#include <sys/sysctl.h>
70100894Srwatson
71100979Srwatson#include <vm/vm.h>
72100979Srwatson#include <vm/pmap.h>
73100979Srwatson#include <vm/vm_map.h>
74100979Srwatson#include <vm/vm_object.h>
75100979Srwatson
76100979Srwatson#include <sys/mac_policy.h>
77100979Srwatson
78100979Srwatson#include <fs/devfs/devfs.h>
79100979Srwatson
80100979Srwatson#include <net/bpfdesc.h>
81100979Srwatson#include <net/if.h>
82100979Srwatson#include <net/if_var.h>
83100979Srwatson
84100979Srwatson#include <netinet/in.h>
85100979Srwatson#include <netinet/ip_var.h>
86100979Srwatson
87100979Srwatson#ifdef MAC
88100979Srwatson
89101712Srwatson/*
90101712Srwatson * Declare that the kernel provides MAC support, version 1.  This permits
91101712Srwatson * modules to refuse to be loaded if the necessary support isn't present,
92101712Srwatson * even if it's pre-boot.
93101712Srwatson */
94101712SrwatsonMODULE_VERSION(kernel_mac_support, 1);
95101712Srwatson
96100979SrwatsonSYSCTL_DECL(_security);
97100979Srwatson
98100979SrwatsonSYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
99100979Srwatson    "TrustedBSD MAC policy controls");
100104517Srwatson
101100979Srwatson#if MAC_MAX_POLICIES > 32
102100979Srwatson#error "MAC_MAX_POLICIES too large"
103100979Srwatson#endif
104105497Srwatson
105100979Srwatsonstatic unsigned int mac_max_policies = MAC_MAX_POLICIES;
106100979Srwatsonstatic unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
107100979SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
108100979Srwatson    &mac_max_policies, 0, "");
109100979Srwatson
110105959Srwatson/*
111105959Srwatson * Has the kernel started generating labeled objects yet?  All read/write
112105959Srwatson * access to this variable is serialized during the boot process.  Following
113105959Srwatson * the end of serialization, we don't update this flag; no locking.
114105959Srwatson */
115100979Srwatsonstatic int	mac_late = 0;
116100979Srwatson
117105988Srwatson/*
118105988Srwatson * Warn about EA transactions only the first time they happen.
119105988Srwatson * Weak coherency, no locking.
120105988Srwatson */
121105988Srwatsonstatic int	ea_warn_once = 0;
122105988Srwatson
123100979Srwatsonstatic int	mac_enforce_fs = 1;
124100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
125100979Srwatson    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
126100979SrwatsonTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
127100979Srwatson
128107089Srwatsonstatic int	mac_enforce_kld = 1;
129107089SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
130107089Srwatson    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
131107089SrwatsonTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
132107089Srwatson
133100979Srwatsonstatic int	mac_enforce_network = 1;
134100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
135100979Srwatson    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
136100979SrwatsonTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
137100979Srwatson
138103513Srwatsonstatic int	mac_enforce_pipe = 1;
139103513SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
140103513Srwatson    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
141104236SrwatsonTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
142103513Srwatson
143100979Srwatsonstatic int	mac_enforce_process = 1;
144100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
145100979Srwatson    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
146100979SrwatsonTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
147100979Srwatson
148100979Srwatsonstatic int	mac_enforce_socket = 1;
149100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
150100979Srwatson    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
151100979SrwatsonTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
152100979Srwatson
153106045Srwatsonstatic int	mac_enforce_system = 1;
154106045SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
155106045Srwatson    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
156106045SrwatsonTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
157106025Srwatson
158106045Srwatsonstatic int	mac_enforce_vm = 1;
159103514SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
160103514Srwatson    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
161104236SrwatsonTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
162103514Srwatson
163103136Srwatsonstatic int	mac_mmap_revocation = 1;
164103136SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
165103136Srwatson    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
166103136Srwatson    "relabel");
167101892Srwatsonstatic int	mac_mmap_revocation_via_cow = 0;
168100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
169100979Srwatson    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
170100979Srwatson    "copy-on-write semantics, or by removing all write access");
171100979Srwatson
172101988Srwatson#ifdef MAC_DEBUG
173104268SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
174104268Srwatson    "TrustedBSD MAC debug info");
175104268Srwatson
176104268Srwatsonstatic int	mac_debug_label_fallback = 0;
177104268SrwatsonSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
178104268Srwatson    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
179104268Srwatson    "when label is corrupted.");
180104268SrwatsonTUNABLE_INT("security.mac.debug_label_fallback",
181104268Srwatson    &mac_debug_label_fallback);
182104268Srwatson
183104517SrwatsonSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
184104517Srwatson    "TrustedBSD MAC object counters");
185104517Srwatson
186100979Srwatsonstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
187100979Srwatson    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
188107105Srwatson    nmacipqs, nmacpipes, nmacprocs;
189104517Srwatson
190104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
191100979Srwatson    &nmacmbufs, 0, "number of mbufs in use");
192104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
193100979Srwatson    &nmaccreds, 0, "number of ucreds in use");
194104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
195100979Srwatson    &nmacifnets, 0, "number of ifnets in use");
196104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
197100979Srwatson    &nmacipqs, 0, "number of ipqs in use");
198104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
199100979Srwatson    &nmacbpfdescs, 0, "number of bpfdescs in use");
200104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
201100979Srwatson    &nmacsockets, 0, "number of sockets in use");
202104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
203100979Srwatson    &nmacpipes, 0, "number of pipes in use");
204107105SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
205107105Srwatson    &nmacprocs, 0, "number of procs in use");
206104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
207100979Srwatson    &nmacmounts, 0, "number of mounts in use");
208104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
209100979Srwatson    &nmactemp, 0, "number of temporary labels in use");
210104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
211100979Srwatson    &nmacvnodes, 0, "number of vnodes in use");
212104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
213100979Srwatson    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
214101988Srwatson#endif
215100979Srwatson
216100979Srwatsonstatic int	error_select(int error1, int error2);
217100979Srwatsonstatic int	mac_policy_register(struct mac_policy_conf *mpc);
218100979Srwatsonstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
219100979Srwatson
220104546Srwatsonstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
221104546Srwatson		    struct vnode *vp, int *prot);
222100979Srwatsonstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
223100979Srwatson		    struct ucred *cred, struct vm_map *map);
224100979Srwatson
225104541Srwatsonstatic void	mac_destroy_socket_label(struct label *label);
226104541Srwatson
227105988Srwatsonstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
228105988Srwatson		    struct vnode *vp, struct label *intlabel);
229105988Srwatson
230100979SrwatsonMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
231105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
232100979Srwatson
233100979Srwatson/*
234106856Srwatson * mac_policy_list stores the list of active policies.  A busy count is
235106856Srwatson * maintained for the list, stored in mac_policy_busy.  The busy count
236106856Srwatson * is protected by mac_policy_list_lock; the list may be modified only
237106856Srwatson * while the busy count is 0, requiring that the lock be held to
238106856Srwatson * prevent new references to the list from being acquired.  For almost
239106856Srwatson * all operations, incrementing the busy count is sufficient to
240106856Srwatson * guarantee consistency, as the list cannot be modified while the
241106856Srwatson * busy count is elevated.  For a few special operations involving a
242106856Srwatson * change to the list of active policies, the lock itself must be held.
243106856Srwatson * A condition variable, mac_policy_list_not_busy, is used to signal
244106856Srwatson * potential exclusive consumers that they should try to acquire the
245106856Srwatson * lock if a first attempt at exclusive access fails.
246100979Srwatson */
247100979Srwatsonstatic struct mtx mac_policy_list_lock;
248106856Srwatsonstatic struct cv mac_policy_list_not_busy;
249100979Srwatsonstatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
250100979Srwatsonstatic int mac_policy_list_busy;
251100979Srwatson
252106856Srwatson#define	MAC_POLICY_LIST_LOCKINIT() do {					\
253106856Srwatson	mtx_init(&mac_policy_list_lock, "mac_policy_list_lock", NULL,	\
254106856Srwatson	    MTX_DEF);							\
255106856Srwatson	cv_init(&mac_policy_list_not_busy, "mac_policy_list_not_busy");	\
256106856Srwatson} while (0)
257106856Srwatson
258106856Srwatson#define	MAC_POLICY_LIST_LOCK() do {					\
259106856Srwatson	mtx_lock(&mac_policy_list_lock);				\
260106856Srwatson} while (0)
261106856Srwatson
262106856Srwatson#define	MAC_POLICY_LIST_UNLOCK() do {					\
263106856Srwatson	mtx_unlock(&mac_policy_list_lock);				\
264106856Srwatson} while (0)
265106856Srwatson
266106856Srwatson/*
267106856Srwatson * We manually invoke WITNESS_SLEEP() to allow Witness to generate
268106856Srwatson * warnings even if we don't end up ever triggering the wait at
269106856Srwatson * run-time.  The consumer of the exclusive interface must not hold
270106856Srwatson * any locks (other than potentially Giant) since we may sleep for
271106856Srwatson * long (potentially indefinite) periods of time waiting for the
272106856Srwatson * framework to become quiescent so that a policy list change may
273106856Srwatson * be made.
274106856Srwatson */
275106856Srwatson#define	MAC_POLICY_LIST_EXCLUSIVE() do {				\
276106856Srwatson	WITNESS_SLEEP(1, NULL);						\
277106856Srwatson	mtx_lock(&mac_policy_list_lock);				\
278106856Srwatson	while (mac_policy_list_busy != 0)				\
279106856Srwatson		cv_wait(&mac_policy_list_not_busy,			\
280106856Srwatson		    &mac_policy_list_lock);				\
281106856Srwatson} while (0)
282106856Srwatson
283100979Srwatson#define	MAC_POLICY_LIST_BUSY() do {					\
284100979Srwatson	MAC_POLICY_LIST_LOCK();						\
285100979Srwatson	mac_policy_list_busy++;						\
286100979Srwatson	MAC_POLICY_LIST_UNLOCK();					\
287100979Srwatson} while (0)
288100979Srwatson
289100979Srwatson#define	MAC_POLICY_LIST_UNBUSY() do {					\
290100979Srwatson	MAC_POLICY_LIST_LOCK();						\
291100979Srwatson	mac_policy_list_busy--;						\
292106856Srwatson	KASSERT(mac_policy_list_busy >= 0, ("MAC_POLICY_LIST_LOCK"));	\
293106856Srwatson	if (mac_policy_list_busy == 0)					\
294106856Srwatson		cv_signal(&mac_policy_list_not_busy);			\
295100979Srwatson	MAC_POLICY_LIST_UNLOCK();					\
296100979Srwatson} while (0)
297100979Srwatson
298100979Srwatson/*
299100979Srwatson * MAC_CHECK performs the designated check by walking the policy
300100979Srwatson * module list and checking with each as to how it feels about the
301100979Srwatson * request.  Note that it returns its value via 'error' in the scope
302100979Srwatson * of the caller.
303100979Srwatson */
304100979Srwatson#define	MAC_CHECK(check, args...) do {					\
305100979Srwatson	struct mac_policy_conf *mpc;					\
306100979Srwatson									\
307100979Srwatson	error = 0;							\
308100979Srwatson	MAC_POLICY_LIST_BUSY();						\
309100979Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
310100979Srwatson		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
311100979Srwatson			error = error_select(				\
312100979Srwatson			    mpc->mpc_ops->mpo_ ## check (args),		\
313100979Srwatson			    error);					\
314100979Srwatson	}								\
315100979Srwatson	MAC_POLICY_LIST_UNBUSY();					\
316100979Srwatson} while (0)
317100979Srwatson
318100979Srwatson/*
319100979Srwatson * MAC_BOOLEAN performs the designated boolean composition by walking
320100979Srwatson * the module list, invoking each instance of the operation, and
321100979Srwatson * combining the results using the passed C operator.  Note that it
322100979Srwatson * returns its value via 'result' in the scope of the caller, which
323100979Srwatson * should be initialized by the caller in a meaningful way to get
324100979Srwatson * a meaningful result.
325100979Srwatson */
326100979Srwatson#define	MAC_BOOLEAN(operation, composition, args...) do {		\
327100979Srwatson	struct mac_policy_conf *mpc;					\
328100979Srwatson									\
329100979Srwatson	MAC_POLICY_LIST_BUSY();						\
330100979Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
331100979Srwatson		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
332100979Srwatson			result = result composition			\
333100979Srwatson			    mpc->mpc_ops->mpo_ ## operation (args);	\
334100979Srwatson	}								\
335100979Srwatson	MAC_POLICY_LIST_UNBUSY();					\
336100979Srwatson} while (0)
337100979Srwatson
338105694Srwatson#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
339105694Srwatson    outbuflen) do {							\
340105694Srwatson	char *curptr, *curptr_start, *element_name, *element_temp;	\
341105694Srwatson	size_t left, left_start, len;					\
342105694Srwatson	int claimed, first, first_start, ignorenotfound;		\
343105694Srwatson									\
344105694Srwatson	error = 0;							\
345105694Srwatson	element_temp = elementlist;					\
346105694Srwatson	curptr = outbuf;						\
347105694Srwatson	curptr[0] = '\0';						\
348105694Srwatson	left = outbuflen;						\
349105694Srwatson	first = 1;							\
350105694Srwatson	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
351105694Srwatson		curptr_start = curptr;					\
352105694Srwatson		left_start = left;					\
353105694Srwatson		first_start = first;					\
354105694Srwatson		if (element_name[0] == '?') {				\
355105694Srwatson			element_name++;					\
356105694Srwatson			ignorenotfound = 1;				\
357105694Srwatson		} else							\
358105694Srwatson			ignorenotfound = 0;				\
359105694Srwatson		claimed = 0;						\
360105694Srwatson		if (first) {						\
361105694Srwatson			len = snprintf(curptr, left, "%s/",		\
362105694Srwatson			    element_name);				\
363105694Srwatson			first = 0;					\
364105694Srwatson		} else							\
365105694Srwatson			len = snprintf(curptr, left, ",%s/",		\
366105694Srwatson			    element_name);				\
367105694Srwatson		if (len >= left) {					\
368105694Srwatson			error = EINVAL;		/* XXXMAC: E2BIG */	\
369105694Srwatson			break;						\
370105694Srwatson		}							\
371105694Srwatson		curptr += len;						\
372105694Srwatson		left -= len;						\
373105694Srwatson									\
374105694Srwatson		MAC_CHECK(externalize_ ## type, label, element_name,	\
375105694Srwatson		    curptr, left, &len, &claimed);			\
376105694Srwatson		if (error)						\
377105694Srwatson			break;						\
378105694Srwatson		if (claimed == 1) {					\
379105694Srwatson			if (len >= outbuflen) {				\
380105694Srwatson				error = EINVAL;	/* XXXMAC: E2BIG */	\
381105694Srwatson				break;					\
382105694Srwatson			}						\
383105694Srwatson			curptr += len;					\
384105694Srwatson			left -= len;					\
385105694Srwatson		} else if (claimed == 0 && ignorenotfound) {		\
386105694Srwatson			/*						\
387105694Srwatson			 * Revert addition of the label element		\
388105694Srwatson			 * name.					\
389105694Srwatson			 */						\
390105694Srwatson			curptr = curptr_start;				\
391105694Srwatson			*curptr = '\0';					\
392105694Srwatson			left = left_start;				\
393105694Srwatson			first = first_start;				\
394105694Srwatson		} else {						\
395105694Srwatson			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
396105694Srwatson			break;						\
397105694Srwatson		}							\
398105694Srwatson	}								\
399105694Srwatson} while (0)
400105694Srwatson
401105694Srwatson#define	MAC_INTERNALIZE(type, label, instring) do {			\
402105694Srwatson	char *element, *element_name, *element_data;			\
403105694Srwatson	int claimed;							\
404105694Srwatson									\
405105694Srwatson	error = 0;							\
406105694Srwatson	element = instring;						\
407105694Srwatson	while ((element_name = strsep(&element, ",")) != NULL) {	\
408105694Srwatson		element_data = element_name;				\
409105694Srwatson		element_name = strsep(&element_data, "/");		\
410105694Srwatson		if (element_data == NULL) {				\
411105694Srwatson			error = EINVAL;					\
412105694Srwatson			break;						\
413105694Srwatson		}							\
414105694Srwatson		claimed = 0;						\
415105694Srwatson		MAC_CHECK(internalize_ ## type, label, element_name,	\
416105694Srwatson		    element_data, &claimed);				\
417105694Srwatson		if (error)						\
418105694Srwatson			break;						\
419105694Srwatson		if (claimed != 1) {					\
420105694Srwatson			/* XXXMAC: Another error here? */		\
421105694Srwatson			error = EINVAL;					\
422105694Srwatson			break;						\
423105694Srwatson		}							\
424105694Srwatson	}								\
425105694Srwatson} while (0)
426105694Srwatson
427100979Srwatson/*
428100979Srwatson * MAC_PERFORM performs the designated operation by walking the policy
429100979Srwatson * module list and invoking that operation for each policy.
430100979Srwatson */
431100979Srwatson#define	MAC_PERFORM(operation, args...) do {				\
432100979Srwatson	struct mac_policy_conf *mpc;					\
433100979Srwatson									\
434100979Srwatson	MAC_POLICY_LIST_BUSY();						\
435100979Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {			\
436100979Srwatson		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
437100979Srwatson			mpc->mpc_ops->mpo_ ## operation (args);		\
438100979Srwatson	}								\
439100979Srwatson	MAC_POLICY_LIST_UNBUSY();					\
440100979Srwatson} while (0)
441100979Srwatson
442100979Srwatson/*
443100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks.
444100979Srwatson */
445100979Srwatsonstatic void
446100979Srwatsonmac_init(void)
447100979Srwatson{
448100979Srwatson
449100979Srwatson	LIST_INIT(&mac_policy_list);
450100979Srwatson	MAC_POLICY_LIST_LOCKINIT();
451100979Srwatson}
452100979Srwatson
453100979Srwatson/*
454100979Srwatson * For the purposes of modules that want to know if they were loaded
455100979Srwatson * "early", set the mac_late flag once we've processed modules either
456100979Srwatson * linked into the kernel, or loaded before the kernel startup.
457100979Srwatson */
458100979Srwatsonstatic void
459100979Srwatsonmac_late_init(void)
460100979Srwatson{
461100979Srwatson
462100979Srwatson	mac_late = 1;
463100979Srwatson}
464100979Srwatson
465100979Srwatson/*
466100979Srwatson * Allow MAC policy modules to register during boot, etc.
467100979Srwatson */
468100894Srwatsonint
469100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data)
470100979Srwatson{
471100979Srwatson	struct mac_policy_conf *mpc;
472100979Srwatson	int error;
473100979Srwatson
474100979Srwatson	error = 0;
475100979Srwatson	mpc = (struct mac_policy_conf *) data;
476100979Srwatson
477100979Srwatson	switch (type) {
478100979Srwatson	case MOD_LOAD:
479100979Srwatson		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
480100979Srwatson		    mac_late) {
481100979Srwatson			printf("mac_policy_modevent: can't load %s policy "
482100979Srwatson			    "after booting\n", mpc->mpc_name);
483100979Srwatson			error = EBUSY;
484100979Srwatson			break;
485100979Srwatson		}
486100979Srwatson		error = mac_policy_register(mpc);
487100979Srwatson		break;
488100979Srwatson	case MOD_UNLOAD:
489100979Srwatson		/* Don't unregister the module if it was never registered. */
490100979Srwatson		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
491100979Srwatson		    != 0)
492100979Srwatson			error = mac_policy_unregister(mpc);
493100979Srwatson		else
494100979Srwatson			error = 0;
495100979Srwatson		break;
496100979Srwatson	default:
497100979Srwatson		break;
498100979Srwatson	}
499100979Srwatson
500100979Srwatson	return (error);
501100979Srwatson}
502100979Srwatson
503100979Srwatsonstatic int
504100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc)
505100979Srwatson{
506100979Srwatson	struct mac_policy_conf *tmpc;
507100979Srwatson	int slot;
508100979Srwatson
509106856Srwatson	MAC_POLICY_LIST_EXCLUSIVE();
510100979Srwatson	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
511100979Srwatson		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
512100979Srwatson			MAC_POLICY_LIST_UNLOCK();
513100979Srwatson			return (EEXIST);
514100979Srwatson		}
515100979Srwatson	}
516100979Srwatson	if (mpc->mpc_field_off != NULL) {
517100979Srwatson		slot = ffs(mac_policy_offsets_free);
518100979Srwatson		if (slot == 0) {
519100979Srwatson			MAC_POLICY_LIST_UNLOCK();
520100979Srwatson			return (ENOMEM);
521100979Srwatson		}
522100979Srwatson		slot--;
523100979Srwatson		mac_policy_offsets_free &= ~(1 << slot);
524100979Srwatson		*mpc->mpc_field_off = slot;
525100979Srwatson	}
526100979Srwatson	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
527100979Srwatson	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
528100979Srwatson
529100979Srwatson	/* Per-policy initialization. */
530100979Srwatson	if (mpc->mpc_ops->mpo_init != NULL)
531100979Srwatson		(*(mpc->mpc_ops->mpo_init))(mpc);
532100979Srwatson	MAC_POLICY_LIST_UNLOCK();
533100979Srwatson
534100979Srwatson	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
535100979Srwatson	    mpc->mpc_name);
536100979Srwatson
537100979Srwatson	return (0);
538100979Srwatson}
539100979Srwatson
540100979Srwatsonstatic int
541100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc)
542100979Srwatson{
543100979Srwatson
544104520Srwatson	/*
545104520Srwatson	 * If we fail the load, we may get a request to unload.  Check
546104520Srwatson	 * to see if we did the run-time registration, and if not,
547104520Srwatson	 * silently succeed.
548104520Srwatson	 */
549106856Srwatson	MAC_POLICY_LIST_EXCLUSIVE();
550104520Srwatson	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
551104520Srwatson		MAC_POLICY_LIST_UNLOCK();
552104520Srwatson		return (0);
553104520Srwatson	}
554100979Srwatson#if 0
555100979Srwatson	/*
556100979Srwatson	 * Don't allow unloading modules with private data.
557100979Srwatson	 */
558104520Srwatson	if (mpc->mpc_field_off != NULL) {
559104520Srwatson		MAC_POLICY_LIST_UNLOCK();
560100979Srwatson		return (EBUSY);
561104520Srwatson	}
562100979Srwatson#endif
563104520Srwatson	/*
564104520Srwatson	 * Only allow the unload to proceed if the module is unloadable
565104520Srwatson	 * by its own definition.
566104520Srwatson	 */
567104520Srwatson	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
568104520Srwatson		MAC_POLICY_LIST_UNLOCK();
569100979Srwatson		return (EBUSY);
570104520Srwatson	}
571100979Srwatson	if (mpc->mpc_ops->mpo_destroy != NULL)
572100979Srwatson		(*(mpc->mpc_ops->mpo_destroy))(mpc);
573100979Srwatson
574100979Srwatson	LIST_REMOVE(mpc, mpc_list);
575106856Srwatson	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
576106856Srwatson
577100979Srwatson	MAC_POLICY_LIST_UNLOCK();
578100979Srwatson
579100979Srwatson	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
580100979Srwatson	    mpc->mpc_name);
581100979Srwatson
582100979Srwatson	return (0);
583100979Srwatson}
584100979Srwatson
585100979Srwatson/*
586100979Srwatson * Define an error value precedence, and given two arguments, selects the
587100979Srwatson * value with the higher precedence.
588100979Srwatson */
589100979Srwatsonstatic int
590100979Srwatsonerror_select(int error1, int error2)
591100979Srwatson{
592100979Srwatson
593100979Srwatson	/* Certain decision-making errors take top priority. */
594100979Srwatson	if (error1 == EDEADLK || error2 == EDEADLK)
595100979Srwatson		return (EDEADLK);
596100979Srwatson
597100979Srwatson	/* Invalid arguments should be reported where possible. */
598100979Srwatson	if (error1 == EINVAL || error2 == EINVAL)
599100979Srwatson		return (EINVAL);
600100979Srwatson
601100979Srwatson	/* Precedence goes to "visibility", with both process and file. */
602100979Srwatson	if (error1 == ESRCH || error2 == ESRCH)
603100979Srwatson		return (ESRCH);
604100979Srwatson
605100979Srwatson	if (error1 == ENOENT || error2 == ENOENT)
606100979Srwatson		return (ENOENT);
607100979Srwatson
608100979Srwatson	/* Precedence goes to DAC/MAC protections. */
609100979Srwatson	if (error1 == EACCES || error2 == EACCES)
610100979Srwatson		return (EACCES);
611100979Srwatson
612100979Srwatson	/* Precedence goes to privilege. */
613100979Srwatson	if (error1 == EPERM || error2 == EPERM)
614100979Srwatson		return (EPERM);
615100979Srwatson
616100979Srwatson	/* Precedence goes to error over success; otherwise, arbitrary. */
617100979Srwatson	if (error1 != 0)
618100979Srwatson		return (error1);
619100979Srwatson	return (error2);
620100979Srwatson}
621100979Srwatson
622104521Srwatsonstatic void
623104521Srwatsonmac_init_label(struct label *label)
624104521Srwatson{
625104521Srwatson
626104521Srwatson	bzero(label, sizeof(*label));
627104521Srwatson	label->l_flags = MAC_FLAG_INITIALIZED;
628104521Srwatson}
629104521Srwatson
630104521Srwatsonstatic void
631104521Srwatsonmac_destroy_label(struct label *label)
632104521Srwatson{
633104521Srwatson
634104521Srwatson	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
635104521Srwatson	    ("destroying uninitialized label"));
636104521Srwatson
637104521Srwatson	bzero(label, sizeof(*label));
638104521Srwatson	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
639104521Srwatson}
640104521Srwatson
641100979Srwatsonvoid
642104527Srwatsonmac_init_bpfdesc(struct bpf_d *bpf_d)
643104521Srwatson{
644104521Srwatson
645104527Srwatson	mac_init_label(&bpf_d->bd_label);
646104527Srwatson	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
647104521Srwatson#ifdef MAC_DEBUG
648104527Srwatson	atomic_add_int(&nmacbpfdescs, 1);
649104521Srwatson#endif
650104521Srwatson}
651104521Srwatson
652105694Srwatsonstatic void
653105694Srwatsonmac_init_cred_label(struct label *label)
654104521Srwatson{
655104521Srwatson
656105694Srwatson	mac_init_label(label);
657105694Srwatson	MAC_PERFORM(init_cred_label, label);
658104521Srwatson#ifdef MAC_DEBUG
659104521Srwatson	atomic_add_int(&nmaccreds, 1);
660104521Srwatson#endif
661104521Srwatson}
662104521Srwatson
663104521Srwatsonvoid
664105694Srwatsonmac_init_cred(struct ucred *cred)
665105694Srwatson{
666105694Srwatson
667105694Srwatson	mac_init_cred_label(&cred->cr_label);
668105694Srwatson}
669105694Srwatson
670105694Srwatsonvoid
671104527Srwatsonmac_init_devfsdirent(struct devfs_dirent *de)
672104521Srwatson{
673104521Srwatson
674104527Srwatson	mac_init_label(&de->de_label);
675104527Srwatson	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
676104521Srwatson#ifdef MAC_DEBUG
677104527Srwatson	atomic_add_int(&nmacdevfsdirents, 1);
678104521Srwatson#endif
679104521Srwatson}
680104521Srwatson
681105694Srwatsonstatic void
682105694Srwatsonmac_init_ifnet_label(struct label *label)
683104521Srwatson{
684104521Srwatson
685105694Srwatson	mac_init_label(label);
686105694Srwatson	MAC_PERFORM(init_ifnet_label, label);
687104521Srwatson#ifdef MAC_DEBUG
688104521Srwatson	atomic_add_int(&nmacifnets, 1);
689104521Srwatson#endif
690104521Srwatson}
691104521Srwatson
692104521Srwatsonvoid
693105694Srwatsonmac_init_ifnet(struct ifnet *ifp)
694105694Srwatson{
695105694Srwatson
696105694Srwatson	mac_init_ifnet_label(&ifp->if_label);
697105694Srwatson}
698105694Srwatson
699105694Srwatsonvoid
700104527Srwatsonmac_init_ipq(struct ipq *ipq)
701104521Srwatson{
702104521Srwatson
703104527Srwatson	mac_init_label(&ipq->ipq_label);
704104527Srwatson	MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
705104521Srwatson#ifdef MAC_DEBUG
706104527Srwatson	atomic_add_int(&nmacipqs, 1);
707104521Srwatson#endif
708104521Srwatson}
709104521Srwatson
710104527Srwatsonint
711104527Srwatsonmac_init_mbuf(struct mbuf *m, int flag)
712104527Srwatson{
713104528Srwatson	int error;
714104528Srwatson
715104527Srwatson	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
716104527Srwatson
717104527Srwatson	mac_init_label(&m->m_pkthdr.label);
718104527Srwatson
719104528Srwatson	MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
720104528Srwatson	if (error) {
721104528Srwatson		MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
722104528Srwatson		mac_destroy_label(&m->m_pkthdr.label);
723104528Srwatson	}
724104528Srwatson
725104527Srwatson#ifdef MAC_DEBUG
726104528Srwatson	if (error == 0)
727104528Srwatson		atomic_add_int(&nmacmbufs, 1);
728104527Srwatson#endif
729104528Srwatson	return (error);
730104527Srwatson}
731104527Srwatson
732104521Srwatsonvoid
733104527Srwatsonmac_init_mount(struct mount *mp)
734104521Srwatson{
735104521Srwatson
736104527Srwatson	mac_init_label(&mp->mnt_mntlabel);
737104527Srwatson	mac_init_label(&mp->mnt_fslabel);
738104527Srwatson	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
739104527Srwatson	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
740104521Srwatson#ifdef MAC_DEBUG
741104527Srwatson	atomic_add_int(&nmacmounts, 1);
742104521Srwatson#endif
743104521Srwatson}
744104521Srwatson
745105694Srwatsonstatic void
746105694Srwatsonmac_init_pipe_label(struct label *label)
747105694Srwatson{
748105694Srwatson
749105694Srwatson	mac_init_label(label);
750105694Srwatson	MAC_PERFORM(init_pipe_label, label);
751105694Srwatson#ifdef MAC_DEBUG
752105694Srwatson	atomic_add_int(&nmacpipes, 1);
753105694Srwatson#endif
754105694Srwatson}
755105694Srwatson
756104521Srwatsonvoid
757104527Srwatsonmac_init_pipe(struct pipe *pipe)
758104521Srwatson{
759104527Srwatson	struct label *label;
760104521Srwatson
761104527Srwatson	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
762104527Srwatson	pipe->pipe_label = label;
763104527Srwatson	pipe->pipe_peer->pipe_label = label;
764105694Srwatson	mac_init_pipe_label(label);
765104521Srwatson}
766104521Srwatson
767107105Srwatsonvoid
768107105Srwatsonmac_init_proc(struct proc *p)
769107105Srwatson{
770107105Srwatson
771107105Srwatson	mac_init_label(&p->p_label);
772107105Srwatson	MAC_PERFORM(init_proc_label, &p->p_label);
773107105Srwatson#ifdef MAC_DEBUG
774107105Srwatson	atomic_add_int(&nmacprocs, 1);
775107105Srwatson#endif
776107105Srwatson}
777107105Srwatson
778104541Srwatsonstatic int
779104541Srwatsonmac_init_socket_label(struct label *label, int flag)
780104521Srwatson{
781104541Srwatson	int error;
782104521Srwatson
783104541Srwatson	mac_init_label(label);
784104541Srwatson
785104541Srwatson	MAC_CHECK(init_socket_label, label, flag);
786104541Srwatson	if (error) {
787104541Srwatson		MAC_PERFORM(destroy_socket_label, label);
788104541Srwatson		mac_destroy_label(label);
789104541Srwatson	}
790104541Srwatson
791104521Srwatson#ifdef MAC_DEBUG
792104541Srwatson	if (error == 0)
793104541Srwatson		atomic_add_int(&nmacsockets, 1);
794104521Srwatson#endif
795104541Srwatson
796104541Srwatson	return (error);
797104521Srwatson}
798104521Srwatson
799104541Srwatsonstatic int
800104541Srwatsonmac_init_socket_peer_label(struct label *label, int flag)
801104541Srwatson{
802104541Srwatson	int error;
803104541Srwatson
804104541Srwatson	mac_init_label(label);
805104541Srwatson
806104541Srwatson	MAC_CHECK(init_socket_peer_label, label, flag);
807104541Srwatson	if (error) {
808104541Srwatson		MAC_PERFORM(destroy_socket_label, label);
809104541Srwatson		mac_destroy_label(label);
810104541Srwatson	}
811104541Srwatson
812104541Srwatson	return (error);
813104541Srwatson}
814104541Srwatson
815104541Srwatsonint
816104541Srwatsonmac_init_socket(struct socket *socket, int flag)
817104541Srwatson{
818104541Srwatson	int error;
819104541Srwatson
820104541Srwatson	error = mac_init_socket_label(&socket->so_label, flag);
821104541Srwatson	if (error)
822104541Srwatson		return (error);
823104541Srwatson
824104541Srwatson	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
825104541Srwatson	if (error)
826104541Srwatson		mac_destroy_socket_label(&socket->so_label);
827104541Srwatson
828104541Srwatson	return (error);
829104541Srwatson}
830104541Srwatson
831105988Srwatsonvoid
832105694Srwatsonmac_init_vnode_label(struct label *label)
833104521Srwatson{
834104521Srwatson
835104527Srwatson	mac_init_label(label);
836105694Srwatson	MAC_PERFORM(init_vnode_label, label);
837104521Srwatson#ifdef MAC_DEBUG
838105694Srwatson	atomic_add_int(&nmacvnodes, 1);
839104521Srwatson#endif
840104521Srwatson}
841104521Srwatson
842104521Srwatsonvoid
843104527Srwatsonmac_init_vnode(struct vnode *vp)
844104521Srwatson{
845104521Srwatson
846105694Srwatson	mac_init_vnode_label(&vp->v_label);
847104521Srwatson}
848104521Srwatson
849104521Srwatsonvoid
850104527Srwatsonmac_destroy_bpfdesc(struct bpf_d *bpf_d)
851104521Srwatson{
852104521Srwatson
853104527Srwatson	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
854104527Srwatson	mac_destroy_label(&bpf_d->bd_label);
855104521Srwatson#ifdef MAC_DEBUG
856104527Srwatson	atomic_subtract_int(&nmacbpfdescs, 1);
857104521Srwatson#endif
858104521Srwatson}
859104521Srwatson
860105694Srwatsonstatic void
861105694Srwatsonmac_destroy_cred_label(struct label *label)
862104521Srwatson{
863104521Srwatson
864105694Srwatson	MAC_PERFORM(destroy_cred_label, label);
865105694Srwatson	mac_destroy_label(label);
866104521Srwatson#ifdef MAC_DEBUG
867104527Srwatson	atomic_subtract_int(&nmaccreds, 1);
868104521Srwatson#endif
869104521Srwatson}
870104521Srwatson
871104521Srwatsonvoid
872105694Srwatsonmac_destroy_cred(struct ucred *cred)
873105694Srwatson{
874105694Srwatson
875105694Srwatson	mac_destroy_cred_label(&cred->cr_label);
876105694Srwatson}
877105694Srwatson
878105694Srwatsonvoid
879104527Srwatsonmac_destroy_devfsdirent(struct devfs_dirent *de)
880104521Srwatson{
881104521Srwatson
882104527Srwatson	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
883104527Srwatson	mac_destroy_label(&de->de_label);
884104521Srwatson#ifdef MAC_DEBUG
885104527Srwatson	atomic_subtract_int(&nmacdevfsdirents, 1);
886104521Srwatson#endif
887104521Srwatson}
888104521Srwatson
889105694Srwatsonstatic void
890105694Srwatsonmac_destroy_ifnet_label(struct label *label)
891104521Srwatson{
892104521Srwatson
893105694Srwatson	MAC_PERFORM(destroy_ifnet_label, label);
894105694Srwatson	mac_destroy_label(label);
895104521Srwatson#ifdef MAC_DEBUG
896104527Srwatson	atomic_subtract_int(&nmacifnets, 1);
897104521Srwatson#endif
898104521Srwatson}
899104521Srwatson
900104521Srwatsonvoid
901105694Srwatsonmac_destroy_ifnet(struct ifnet *ifp)
902105694Srwatson{
903105694Srwatson
904105694Srwatson	mac_destroy_ifnet_label(&ifp->if_label);
905105694Srwatson}
906105694Srwatson
907105694Srwatsonvoid
908104527Srwatsonmac_destroy_ipq(struct ipq *ipq)
909104521Srwatson{
910104521Srwatson
911104527Srwatson	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
912104527Srwatson	mac_destroy_label(&ipq->ipq_label);
913104521Srwatson#ifdef MAC_DEBUG
914104527Srwatson	atomic_subtract_int(&nmacipqs, 1);
915104521Srwatson#endif
916104521Srwatson}
917104521Srwatson
918104527Srwatsonvoid
919104527Srwatsonmac_destroy_mbuf(struct mbuf *m)
920104521Srwatson{
921104521Srwatson
922104527Srwatson	MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
923104527Srwatson	mac_destroy_label(&m->m_pkthdr.label);
924104521Srwatson#ifdef MAC_DEBUG
925104527Srwatson	atomic_subtract_int(&nmacmbufs, 1);
926104521Srwatson#endif
927104521Srwatson}
928104521Srwatson
929104527Srwatsonvoid
930104527Srwatsonmac_destroy_mount(struct mount *mp)
931104521Srwatson{
932104521Srwatson
933104527Srwatson	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
934104527Srwatson	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
935104527Srwatson	mac_destroy_label(&mp->mnt_fslabel);
936104527Srwatson	mac_destroy_label(&mp->mnt_mntlabel);
937104521Srwatson#ifdef MAC_DEBUG
938104527Srwatson	atomic_subtract_int(&nmacmounts, 1);
939104521Srwatson#endif
940104521Srwatson}
941104521Srwatson
942105694Srwatsonstatic void
943105694Srwatsonmac_destroy_pipe_label(struct label *label)
944104521Srwatson{
945104521Srwatson
946105694Srwatson	MAC_PERFORM(destroy_pipe_label, label);
947105694Srwatson	mac_destroy_label(label);
948104521Srwatson#ifdef MAC_DEBUG
949104527Srwatson	atomic_subtract_int(&nmacpipes, 1);
950104521Srwatson#endif
951104521Srwatson}
952104521Srwatson
953105694Srwatsonvoid
954105694Srwatsonmac_destroy_pipe(struct pipe *pipe)
955105694Srwatson{
956105694Srwatson
957105694Srwatson	mac_destroy_pipe_label(pipe->pipe_label);
958105694Srwatson	free(pipe->pipe_label, M_MACPIPELABEL);
959105694Srwatson}
960105694Srwatson
961107105Srwatsonvoid
962107105Srwatsonmac_destroy_proc(struct proc *p)
963107105Srwatson{
964107105Srwatson
965107105Srwatson	MAC_PERFORM(destroy_proc_label, &p->p_label);
966107105Srwatson	mac_destroy_label(&p->p_label);
967107105Srwatson#ifdef MAC_DEBUG
968107105Srwatson	atomic_subtract_int(&nmacprocs, 1);
969107105Srwatson#endif
970107105Srwatson}
971107105Srwatson
972104541Srwatsonstatic void
973104541Srwatsonmac_destroy_socket_label(struct label *label)
974104521Srwatson{
975104521Srwatson
976104541Srwatson	MAC_PERFORM(destroy_socket_label, label);
977104541Srwatson	mac_destroy_label(label);
978104521Srwatson#ifdef MAC_DEBUG
979104527Srwatson	atomic_subtract_int(&nmacsockets, 1);
980104521Srwatson#endif
981104521Srwatson}
982104521Srwatson
983104527Srwatsonstatic void
984104541Srwatsonmac_destroy_socket_peer_label(struct label *label)
985104541Srwatson{
986104541Srwatson
987104541Srwatson	MAC_PERFORM(destroy_socket_peer_label, label);
988104541Srwatson	mac_destroy_label(label);
989104541Srwatson}
990104541Srwatson
991104541Srwatsonvoid
992104541Srwatsonmac_destroy_socket(struct socket *socket)
993104541Srwatson{
994104541Srwatson
995104541Srwatson	mac_destroy_socket_label(&socket->so_label);
996104541Srwatson	mac_destroy_socket_peer_label(&socket->so_peerlabel);
997104541Srwatson}
998104541Srwatson
999105988Srwatsonvoid
1000105694Srwatsonmac_destroy_vnode_label(struct label *label)
1001104521Srwatson{
1002104521Srwatson
1003105694Srwatson	MAC_PERFORM(destroy_vnode_label, label);
1004104527Srwatson	mac_destroy_label(label);
1005104521Srwatson#ifdef MAC_DEBUG
1006105694Srwatson	atomic_subtract_int(&nmacvnodes, 1);
1007104521Srwatson#endif
1008104521Srwatson}
1009104521Srwatson
1010104521Srwatsonvoid
1011104527Srwatsonmac_destroy_vnode(struct vnode *vp)
1012104521Srwatson{
1013104521Srwatson
1014105694Srwatson	mac_destroy_vnode_label(&vp->v_label);
1015104521Srwatson}
1016104521Srwatson
1017105694Srwatsonstatic void
1018105694Srwatsonmac_copy_pipe_label(struct label *src, struct label *dest)
1019105694Srwatson{
1020105694Srwatson
1021105694Srwatson	MAC_PERFORM(copy_pipe_label, src, dest);
1022105694Srwatson}
1023105694Srwatson
1024105988Srwatsonvoid
1025105694Srwatsonmac_copy_vnode_label(struct label *src, struct label *dest)
1026105694Srwatson{
1027105694Srwatson
1028105694Srwatson	MAC_PERFORM(copy_vnode_label, src, dest);
1029105694Srwatson}
1030105694Srwatson
1031104522Srwatsonstatic int
1032105694Srwatsonmac_check_structmac_consistent(struct mac *mac)
1033104522Srwatson{
1034105694Srwatson
1035105694Srwatson	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1036105694Srwatson		return (EINVAL);
1037105694Srwatson
1038105694Srwatson	return (0);
1039105694Srwatson}
1040105694Srwatson
1041105694Srwatsonstatic int
1042105694Srwatsonmac_externalize_cred_label(struct label *label, char *elements,
1043105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1044105694Srwatson{
1045104522Srwatson	int error;
1046104522Srwatson
1047105694Srwatson	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1048104522Srwatson
1049104522Srwatson	return (error);
1050104522Srwatson}
1051104522Srwatson
1052104522Srwatsonstatic int
1053105694Srwatsonmac_externalize_ifnet_label(struct label *label, char *elements,
1054105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1055104522Srwatson{
1056104522Srwatson	int error;
1057104522Srwatson
1058105694Srwatson	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1059104522Srwatson
1060104522Srwatson	return (error);
1061104522Srwatson}
1062104522Srwatson
1063105694Srwatsonstatic int
1064105694Srwatsonmac_externalize_pipe_label(struct label *label, char *elements,
1065105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1066105694Srwatson{
1067105694Srwatson	int error;
1068105694Srwatson
1069105694Srwatson	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1070105694Srwatson
1071105694Srwatson	return (error);
1072105694Srwatson}
1073105694Srwatson
1074105694Srwatsonstatic int
1075105694Srwatsonmac_externalize_socket_label(struct label *label, char *elements,
1076105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1077105694Srwatson{
1078105694Srwatson	int error;
1079105694Srwatson
1080105694Srwatson	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1081105694Srwatson
1082105694Srwatson	return (error);
1083105694Srwatson}
1084105694Srwatson
1085105694Srwatsonstatic int
1086105694Srwatsonmac_externalize_socket_peer_label(struct label *label, char *elements,
1087105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1088105694Srwatson{
1089105694Srwatson	int error;
1090105694Srwatson
1091105694Srwatson	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1092105694Srwatson
1093105694Srwatson	return (error);
1094105694Srwatson}
1095105694Srwatson
1096105694Srwatsonstatic int
1097105694Srwatsonmac_externalize_vnode_label(struct label *label, char *elements,
1098105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1099105694Srwatson{
1100105694Srwatson	int error;
1101105694Srwatson
1102105694Srwatson	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1103105694Srwatson
1104105694Srwatson	return (error);
1105105694Srwatson}
1106105694Srwatson
1107105694Srwatsonstatic int
1108105694Srwatsonmac_internalize_cred_label(struct label *label, char *string)
1109105694Srwatson{
1110105694Srwatson	int error;
1111105694Srwatson
1112105694Srwatson	MAC_INTERNALIZE(cred_label, label, string);
1113105694Srwatson
1114105694Srwatson	return (error);
1115105694Srwatson}
1116105694Srwatson
1117105694Srwatsonstatic int
1118105694Srwatsonmac_internalize_ifnet_label(struct label *label, char *string)
1119105694Srwatson{
1120105694Srwatson	int error;
1121105694Srwatson
1122105694Srwatson	MAC_INTERNALIZE(ifnet_label, label, string);
1123105694Srwatson
1124105694Srwatson	return (error);
1125105694Srwatson}
1126105694Srwatson
1127105694Srwatsonstatic int
1128105694Srwatsonmac_internalize_pipe_label(struct label *label, char *string)
1129105694Srwatson{
1130105694Srwatson	int error;
1131105694Srwatson
1132105694Srwatson	MAC_INTERNALIZE(pipe_label, label, string);
1133105694Srwatson
1134105694Srwatson	return (error);
1135105694Srwatson}
1136105694Srwatson
1137105694Srwatsonstatic int
1138105694Srwatsonmac_internalize_socket_label(struct label *label, char *string)
1139105694Srwatson{
1140105694Srwatson	int error;
1141105694Srwatson
1142105694Srwatson	MAC_INTERNALIZE(socket_label, label, string);
1143105694Srwatson
1144105694Srwatson	return (error);
1145105694Srwatson}
1146105694Srwatson
1147105694Srwatsonstatic int
1148105694Srwatsonmac_internalize_vnode_label(struct label *label, char *string)
1149105694Srwatson{
1150105694Srwatson	int error;
1151105694Srwatson
1152105694Srwatson	MAC_INTERNALIZE(vnode_label, label, string);
1153105694Srwatson
1154105694Srwatson	return (error);
1155105694Srwatson}
1156105694Srwatson
1157104522Srwatson/*
1158104522Srwatson * Initialize MAC label for the first kernel process, from which other
1159104522Srwatson * kernel processes and threads are spawned.
1160104522Srwatson */
1161104521Srwatsonvoid
1162104522Srwatsonmac_create_proc0(struct ucred *cred)
1163104522Srwatson{
1164104522Srwatson
1165104522Srwatson	MAC_PERFORM(create_proc0, cred);
1166104522Srwatson}
1167104522Srwatson
1168104522Srwatson/*
1169104522Srwatson * Initialize MAC label for the first userland process, from which other
1170104522Srwatson * userland processes and threads are spawned.
1171104522Srwatson */
1172104522Srwatsonvoid
1173104522Srwatsonmac_create_proc1(struct ucred *cred)
1174104522Srwatson{
1175104522Srwatson
1176104522Srwatson	MAC_PERFORM(create_proc1, cred);
1177104522Srwatson}
1178104522Srwatson
1179104522Srwatsonvoid
1180104522Srwatsonmac_thread_userret(struct thread *td)
1181104522Srwatson{
1182104522Srwatson
1183104522Srwatson	MAC_PERFORM(thread_userret, td);
1184104522Srwatson}
1185104522Srwatson
1186104522Srwatson/*
1187104522Srwatson * When a new process is created, its label must be initialized.  Generally,
1188104522Srwatson * this involves inheritence from the parent process, modulo possible
1189104522Srwatson * deltas.  This function allows that processing to take place.
1190104522Srwatson */
1191104522Srwatsonvoid
1192104522Srwatsonmac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1193104522Srwatson{
1194104522Srwatson
1195104522Srwatson	MAC_PERFORM(create_cred, parent_cred, child_cred);
1196104522Srwatson}
1197104522Srwatson
1198104522Srwatsonvoid
1199107698Srwatsonmac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1200107698Srwatson    struct vnode *vp)
1201100979Srwatson{
1202100979Srwatson
1203107698Srwatson	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1204107698Srwatson	    &vp->v_label);
1205100979Srwatson}
1206100979Srwatson
1207100979Srwatsonvoid
1208105988Srwatsonmac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1209105988Srwatson    struct vnode *vp)
1210100979Srwatson{
1211100979Srwatson
1212105988Srwatson	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1213105988Srwatson	    &de->de_label, vp, &vp->v_label);
1214100979Srwatson}
1215100979Srwatson
1216105988Srwatsonint
1217105988Srwatsonmac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1218100979Srwatson{
1219100979Srwatson	int error;
1220100979Srwatson
1221105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1222100979Srwatson
1223105988Srwatson	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1224105988Srwatson	    &vp->v_label);
1225100979Srwatson
1226100979Srwatson	return (error);
1227100979Srwatson}
1228100979Srwatson
1229100979Srwatsonvoid
1230105988Srwatsonmac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1231100979Srwatson{
1232100979Srwatson
1233105988Srwatson	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1234105988Srwatson	    &vp->v_label);
1235100979Srwatson}
1236100979Srwatson
1237100979Srwatsonint
1238105988Srwatsonmac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1239105988Srwatson    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1240100979Srwatson{
1241105988Srwatson	int error;
1242100979Srwatson
1243105988Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1244105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1245100979Srwatson
1246105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1247105988Srwatson	if (error == EOPNOTSUPP) {
1248105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1249105988Srwatson		if (ea_warn_once == 0) {
1250105988Srwatson			printf("Warning: transactions not supported "
1251105988Srwatson			    "in EA write.\n");
1252105988Srwatson			ea_warn_once = 1;
1253105988Srwatson		}
1254105988Srwatson	} else if (error)
1255100979Srwatson		return (error);
1256100979Srwatson
1257105988Srwatson	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1258105988Srwatson	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1259100979Srwatson
1260105988Srwatson	if (error) {
1261105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1262100979Srwatson		return (error);
1263100979Srwatson	}
1264100979Srwatson
1265105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1266100979Srwatson
1267105988Srwatson	if (error == EOPNOTSUPP)
1268105988Srwatson		error = 0;				/* XXX */
1269100979Srwatson
1270100979Srwatson	return (error);
1271100979Srwatson}
1272100979Srwatson
1273100979Srwatsonstatic int
1274105988Srwatsonmac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1275105988Srwatson    struct label *intlabel)
1276100979Srwatson{
1277100979Srwatson	int error;
1278100979Srwatson
1279105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1280100979Srwatson
1281105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1282105988Srwatson	if (error == EOPNOTSUPP) {
1283105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1284105988Srwatson		if (ea_warn_once == 0) {
1285105988Srwatson			printf("Warning: transactions not supported "
1286105988Srwatson			    "in EA write.\n");
1287105988Srwatson			ea_warn_once = 1;
1288105988Srwatson		}
1289105988Srwatson	} else if (error)
1290105988Srwatson		return (error);
1291100979Srwatson
1292105988Srwatson	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1293100979Srwatson
1294105988Srwatson	if (error) {
1295105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1296100979Srwatson		return (error);
1297100979Srwatson	}
1298100979Srwatson
1299105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1300100979Srwatson
1301105988Srwatson	if (error == EOPNOTSUPP)
1302105988Srwatson		error = 0;				/* XXX */
1303100979Srwatson
1304105988Srwatson	return (error);
1305100979Srwatson}
1306100979Srwatson
1307106468Srwatsonint
1308106468Srwatsonmac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1309106468Srwatson    struct label *execlabelstorage)
1310106468Srwatson{
1311106468Srwatson	struct mac mac;
1312106468Srwatson	char *buffer;
1313106468Srwatson	int error;
1314106468Srwatson
1315106468Srwatson	if (mac_p == NULL)
1316106468Srwatson		return (0);
1317106468Srwatson
1318106468Srwatson	error = copyin(mac_p, &mac, sizeof(mac));
1319106468Srwatson	if (error)
1320106468Srwatson		return (error);
1321106468Srwatson
1322106468Srwatson	error = mac_check_structmac_consistent(&mac);
1323106468Srwatson	if (error)
1324106468Srwatson		return (error);
1325106468Srwatson
1326106468Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1327106468Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1328106468Srwatson	if (error) {
1329106468Srwatson		free(buffer, M_MACTEMP);
1330106468Srwatson		return (error);
1331106468Srwatson	}
1332106468Srwatson
1333106468Srwatson	mac_init_cred_label(execlabelstorage);
1334106468Srwatson	error = mac_internalize_cred_label(execlabelstorage, buffer);
1335106468Srwatson	free(buffer, M_MACTEMP);
1336106468Srwatson	if (error) {
1337106468Srwatson		mac_destroy_cred_label(execlabelstorage);
1338106468Srwatson		return (error);
1339106468Srwatson	}
1340106468Srwatson	imgp->execlabel = execlabelstorage;
1341106468Srwatson	return (0);
1342106468Srwatson}
1343106468Srwatson
1344100979Srwatsonvoid
1345106468Srwatsonmac_execve_exit(struct image_params *imgp)
1346100979Srwatson{
1347106468Srwatson	if (imgp->execlabel != NULL)
1348106468Srwatson		mac_destroy_cred_label(imgp->execlabel);
1349106468Srwatson}
1350100979Srwatson
1351106468Srwatsonvoid
1352106468Srwatsonmac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1353106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1354106468Srwatson{
1355106468Srwatson
1356100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1357100979Srwatson
1358106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1359106460Srwatson		return;
1360106460Srwatson
1361106468Srwatson	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1362106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1363100979Srwatson}
1364100979Srwatson
1365100979Srwatsonint
1366106468Srwatsonmac_execve_will_transition(struct ucred *old, struct vnode *vp,
1367106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1368100979Srwatson{
1369105988Srwatson	int result;
1370100979Srwatson
1371106460Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1372106460Srwatson
1373106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1374106460Srwatson		return (0);
1375106460Srwatson
1376100979Srwatson	result = 0;
1377106468Srwatson	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1378106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1379100979Srwatson
1380100979Srwatson	return (result);
1381100979Srwatson}
1382100979Srwatson
1383100979Srwatsonint
1384106212Srwatsonmac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1385100979Srwatson{
1386100979Srwatson	int error;
1387100979Srwatson
1388100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1389100979Srwatson
1390100979Srwatson	if (!mac_enforce_fs)
1391100979Srwatson		return (0);
1392100979Srwatson
1393106212Srwatson	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1394100979Srwatson	return (error);
1395100979Srwatson}
1396100979Srwatson
1397100979Srwatsonint
1398100979Srwatsonmac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1399100979Srwatson{
1400100979Srwatson	int error;
1401100979Srwatson
1402100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1403100979Srwatson
1404100979Srwatson	if (!mac_enforce_fs)
1405100979Srwatson		return (0);
1406100979Srwatson
1407100979Srwatson	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1408100979Srwatson	return (error);
1409100979Srwatson}
1410100979Srwatson
1411100979Srwatsonint
1412100979Srwatsonmac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1413100979Srwatson{
1414100979Srwatson	int error;
1415100979Srwatson
1416100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1417100979Srwatson
1418100979Srwatson	if (!mac_enforce_fs)
1419100979Srwatson		return (0);
1420100979Srwatson
1421100979Srwatson	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1422100979Srwatson	return (error);
1423100979Srwatson}
1424100979Srwatson
1425100979Srwatsonint
1426100979Srwatsonmac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1427100979Srwatson    struct componentname *cnp, struct vattr *vap)
1428100979Srwatson{
1429100979Srwatson	int error;
1430100979Srwatson
1431100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1432100979Srwatson
1433100979Srwatson	if (!mac_enforce_fs)
1434100979Srwatson		return (0);
1435100979Srwatson
1436100979Srwatson	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1437100979Srwatson	return (error);
1438100979Srwatson}
1439100979Srwatson
1440100979Srwatsonint
1441100979Srwatsonmac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1442100979Srwatson    struct componentname *cnp)
1443100979Srwatson{
1444100979Srwatson	int error;
1445100979Srwatson
1446100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1447100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1448100979Srwatson
1449100979Srwatson	if (!mac_enforce_fs)
1450100979Srwatson		return (0);
1451100979Srwatson
1452100979Srwatson	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1453100979Srwatson	    &vp->v_label, cnp);
1454100979Srwatson	return (error);
1455100979Srwatson}
1456100979Srwatson
1457100979Srwatsonint
1458100979Srwatsonmac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1459100979Srwatson    acl_type_t type)
1460100979Srwatson{
1461100979Srwatson	int error;
1462100979Srwatson
1463100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1464100979Srwatson
1465100979Srwatson	if (!mac_enforce_fs)
1466100979Srwatson		return (0);
1467100979Srwatson
1468100979Srwatson	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1469100979Srwatson	return (error);
1470100979Srwatson}
1471100979Srwatson
1472100979Srwatsonint
1473106468Srwatsonmac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1474106468Srwatson    struct image_params *imgp)
1475100979Srwatson{
1476100979Srwatson	int error;
1477100979Srwatson
1478102102Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1479102102Srwatson
1480100979Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1481100979Srwatson		return (0);
1482100979Srwatson
1483106647Srwatson	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1484106647Srwatson	    imgp->execlabel);
1485100979Srwatson
1486100979Srwatson	return (error);
1487100979Srwatson}
1488100979Srwatson
1489100979Srwatsonint
1490100979Srwatsonmac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1491100979Srwatson{
1492100979Srwatson	int error;
1493100979Srwatson
1494100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1495100979Srwatson
1496100979Srwatson	if (!mac_enforce_fs)
1497100979Srwatson		return (0);
1498100979Srwatson
1499100979Srwatson	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1500100979Srwatson	return (error);
1501100979Srwatson}
1502100979Srwatson
1503100979Srwatsonint
1504100979Srwatsonmac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1505100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1506100979Srwatson{
1507100979Srwatson	int error;
1508100979Srwatson
1509100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1510100979Srwatson
1511100979Srwatson	if (!mac_enforce_fs)
1512100979Srwatson		return (0);
1513100979Srwatson
1514100979Srwatson	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1515100979Srwatson	    attrnamespace, name, uio);
1516100979Srwatson	return (error);
1517100979Srwatson}
1518100979Srwatson
1519100979Srwatsonint
1520104529Srwatsonmac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1521104529Srwatson    struct vnode *vp, struct componentname *cnp)
1522104529Srwatson{
1523104529Srwatson	int error;
1524104529Srwatson
1525104529Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1526104529Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1527104529Srwatson
1528104529Srwatson	if (!mac_enforce_fs)
1529104529Srwatson		return (0);
1530104529Srwatson
1531104529Srwatson	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1532104529Srwatson	    &vp->v_label, cnp);
1533104529Srwatson	return (error);
1534104529Srwatson}
1535104529Srwatson
1536104529Srwatsonint
1537100979Srwatsonmac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1538100979Srwatson    struct componentname *cnp)
1539100979Srwatson{
1540100979Srwatson	int error;
1541100979Srwatson
1542100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1543100979Srwatson
1544100979Srwatson	if (!mac_enforce_fs)
1545100979Srwatson		return (0);
1546100979Srwatson
1547100979Srwatson	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1548100979Srwatson	return (error);
1549100979Srwatson}
1550100979Srwatson
1551104546Srwatsonint
1552104546Srwatsonmac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1553100979Srwatson{
1554104546Srwatson	int error;
1555100979Srwatson
1556104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1557103514Srwatson
1558104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1559104546Srwatson		return (0);
1560104546Srwatson
1561104546Srwatson	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1562104546Srwatson	return (error);
1563100979Srwatson}
1564100979Srwatson
1565104546Srwatsonvoid
1566104546Srwatsonmac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1567104546Srwatson{
1568104546Srwatson	int result = *prot;
1569104546Srwatson
1570104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1571104546Srwatson
1572104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1573104546Srwatson		return;
1574104546Srwatson
1575104546Srwatson	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1576104546Srwatson	    &result);
1577104546Srwatson
1578104546Srwatson	*prot = result;
1579104546Srwatson}
1580104546Srwatson
1581100979Srwatsonint
1582104546Srwatsonmac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1583104546Srwatson{
1584104546Srwatson	int error;
1585104546Srwatson
1586104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1587104546Srwatson
1588104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1589104546Srwatson		return (0);
1590104546Srwatson
1591104546Srwatson	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1592104546Srwatson	return (error);
1593104546Srwatson}
1594104546Srwatson
1595104546Srwatsonint
1596106212Srwatsonmac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1597100979Srwatson{
1598100979Srwatson	int error;
1599100979Srwatson
1600102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1601102112Srwatson
1602100979Srwatson	if (!mac_enforce_fs)
1603100979Srwatson		return (0);
1604100979Srwatson
1605102112Srwatson	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1606102112Srwatson	return (error);
1607102112Srwatson}
1608102112Srwatson
1609102112Srwatsonint
1610102129Srwatsonmac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1611102129Srwatson    struct vnode *vp)
1612102112Srwatson{
1613102112Srwatson	int error;
1614102112Srwatson
1615102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1616102112Srwatson
1617102112Srwatson	if (!mac_enforce_fs)
1618102112Srwatson		return (0);
1619102112Srwatson
1620102129Srwatson	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1621102129Srwatson	    &vp->v_label);
1622100979Srwatson
1623100979Srwatson	return (error);
1624100979Srwatson}
1625100979Srwatson
1626100979Srwatsonint
1627102129Srwatsonmac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1628102129Srwatson    struct vnode *vp)
1629100979Srwatson{
1630100979Srwatson	int error;
1631100979Srwatson
1632102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1633100979Srwatson
1634100979Srwatson	if (!mac_enforce_fs)
1635100979Srwatson		return (0);
1636100979Srwatson
1637102129Srwatson	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1638102129Srwatson	    &vp->v_label);
1639102112Srwatson
1640100979Srwatson	return (error);
1641100979Srwatson}
1642100979Srwatson
1643100979Srwatsonint
1644100979Srwatsonmac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1645100979Srwatson{
1646100979Srwatson	int error;
1647100979Srwatson
1648100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1649100979Srwatson
1650100979Srwatson	if (!mac_enforce_fs)
1651100979Srwatson		return (0);
1652100979Srwatson
1653100979Srwatson	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1654100979Srwatson	return (error);
1655100979Srwatson}
1656100979Srwatson
1657100979Srwatsonint
1658100979Srwatsonmac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1659100979Srwatson{
1660100979Srwatson	int error;
1661100979Srwatson
1662100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1663100979Srwatson
1664100979Srwatson	if (!mac_enforce_fs)
1665100979Srwatson		return (0);
1666100979Srwatson
1667100979Srwatson	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1668100979Srwatson	return (error);
1669100979Srwatson}
1670100979Srwatson
1671100979Srwatsonstatic int
1672100979Srwatsonmac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1673100979Srwatson    struct label *newlabel)
1674100979Srwatson{
1675100979Srwatson	int error;
1676100979Srwatson
1677100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1678100979Srwatson
1679100979Srwatson	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1680100979Srwatson
1681100979Srwatson	return (error);
1682100979Srwatson}
1683100979Srwatson
1684100979Srwatsonint
1685100979Srwatsonmac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1686100979Srwatson    struct vnode *vp, struct componentname *cnp)
1687100979Srwatson{
1688100979Srwatson	int error;
1689100979Srwatson
1690100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1691100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1692100979Srwatson
1693100979Srwatson	if (!mac_enforce_fs)
1694100979Srwatson		return (0);
1695100979Srwatson
1696100979Srwatson	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1697100979Srwatson	    &vp->v_label, cnp);
1698100979Srwatson	return (error);
1699100979Srwatson}
1700100979Srwatson
1701100979Srwatsonint
1702100979Srwatsonmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1703100979Srwatson    struct vnode *vp, int samedir, struct componentname *cnp)
1704100979Srwatson{
1705100979Srwatson	int error;
1706100979Srwatson
1707100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1708100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1709100979Srwatson
1710100979Srwatson	if (!mac_enforce_fs)
1711100979Srwatson		return (0);
1712100979Srwatson
1713100979Srwatson	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1714100979Srwatson	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1715100979Srwatson	return (error);
1716100979Srwatson}
1717100979Srwatson
1718100979Srwatsonint
1719100979Srwatsonmac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1720100979Srwatson{
1721100979Srwatson	int error;
1722100979Srwatson
1723100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1724100979Srwatson
1725100979Srwatson	if (!mac_enforce_fs)
1726100979Srwatson		return (0);
1727100979Srwatson
1728100979Srwatson	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1729100979Srwatson	return (error);
1730100979Srwatson}
1731100979Srwatson
1732100979Srwatsonint
1733100979Srwatsonmac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1734100979Srwatson    struct acl *acl)
1735100979Srwatson{
1736100979Srwatson	int error;
1737100979Srwatson
1738100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1739100979Srwatson
1740100979Srwatson	if (!mac_enforce_fs)
1741100979Srwatson		return (0);
1742100979Srwatson
1743100979Srwatson	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1744100979Srwatson	return (error);
1745100979Srwatson}
1746100979Srwatson
1747100979Srwatsonint
1748100979Srwatsonmac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1749100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1750100979Srwatson{
1751100979Srwatson	int error;
1752100979Srwatson
1753100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1754100979Srwatson
1755100979Srwatson	if (!mac_enforce_fs)
1756100979Srwatson		return (0);
1757100979Srwatson
1758100979Srwatson	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1759100979Srwatson	    attrnamespace, name, uio);
1760100979Srwatson	return (error);
1761100979Srwatson}
1762100979Srwatson
1763100979Srwatsonint
1764100979Srwatsonmac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1765100979Srwatson{
1766100979Srwatson	int error;
1767100979Srwatson
1768100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1769100979Srwatson
1770100979Srwatson	if (!mac_enforce_fs)
1771100979Srwatson		return (0);
1772100979Srwatson
1773100979Srwatson	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1774100979Srwatson	return (error);
1775100979Srwatson}
1776100979Srwatson
1777100979Srwatsonint
1778100979Srwatsonmac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1779100979Srwatson{
1780100979Srwatson	int error;
1781100979Srwatson
1782100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1783100979Srwatson
1784100979Srwatson	if (!mac_enforce_fs)
1785100979Srwatson		return (0);
1786100979Srwatson
1787100979Srwatson	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1788100979Srwatson	return (error);
1789100979Srwatson}
1790100979Srwatson
1791100979Srwatsonint
1792100979Srwatsonmac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1793100979Srwatson    gid_t gid)
1794100979Srwatson{
1795100979Srwatson	int error;
1796100979Srwatson
1797100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1798100979Srwatson
1799100979Srwatson	if (!mac_enforce_fs)
1800100979Srwatson		return (0);
1801100979Srwatson
1802100979Srwatson	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1803100979Srwatson	return (error);
1804100979Srwatson}
1805100979Srwatson
1806100979Srwatsonint
1807100979Srwatsonmac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1808100979Srwatson    struct timespec atime, struct timespec mtime)
1809100979Srwatson{
1810100979Srwatson	int error;
1811100979Srwatson
1812100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1813100979Srwatson
1814100979Srwatson	if (!mac_enforce_fs)
1815100979Srwatson		return (0);
1816100979Srwatson
1817100979Srwatson	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1818100979Srwatson	    mtime);
1819100979Srwatson	return (error);
1820100979Srwatson}
1821100979Srwatson
1822100979Srwatsonint
1823102129Srwatsonmac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1824102129Srwatson    struct vnode *vp)
1825100979Srwatson{
1826100979Srwatson	int error;
1827100979Srwatson
1828100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1829100979Srwatson
1830100979Srwatson	if (!mac_enforce_fs)
1831100979Srwatson		return (0);
1832100979Srwatson
1833102129Srwatson	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1834102129Srwatson	    &vp->v_label);
1835100979Srwatson	return (error);
1836100979Srwatson}
1837100979Srwatson
1838102112Srwatsonint
1839102129Srwatsonmac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1840102129Srwatson    struct vnode *vp)
1841102112Srwatson{
1842102112Srwatson	int error;
1843102112Srwatson
1844102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1845102112Srwatson
1846102112Srwatson	if (!mac_enforce_fs)
1847102112Srwatson		return (0);
1848102112Srwatson
1849102129Srwatson	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1850102129Srwatson	    &vp->v_label);
1851102112Srwatson
1852102112Srwatson	return (error);
1853102112Srwatson}
1854102112Srwatson
1855100979Srwatson/*
1856100979Srwatson * When relabeling a process, call out to the policies for the maximum
1857100979Srwatson * permission allowed for each object type we know about in its
1858100979Srwatson * memory space, and revoke access (in the least surprising ways we
1859100979Srwatson * know) when necessary.  The process lock is not held here.
1860100979Srwatson */
1861107271Srwatsonvoid
1862100979Srwatsonmac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1863100979Srwatson{
1864100979Srwatson
1865100979Srwatson	/* XXX freeze all other threads */
1866100979Srwatson	mac_cred_mmapped_drop_perms_recurse(td, cred,
1867100979Srwatson	    &td->td_proc->p_vmspace->vm_map);
1868100979Srwatson	/* XXX allow other threads to continue */
1869100979Srwatson}
1870100979Srwatson
1871100979Srwatsonstatic __inline const char *
1872100979Srwatsonprot2str(vm_prot_t prot)
1873100979Srwatson{
1874100979Srwatson
1875100979Srwatson	switch (prot & VM_PROT_ALL) {
1876100979Srwatson	case VM_PROT_READ:
1877100979Srwatson		return ("r--");
1878100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE:
1879100979Srwatson		return ("rw-");
1880100979Srwatson	case VM_PROT_READ | VM_PROT_EXECUTE:
1881100979Srwatson		return ("r-x");
1882100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
1883100979Srwatson		return ("rwx");
1884100979Srwatson	case VM_PROT_WRITE:
1885100979Srwatson		return ("-w-");
1886100979Srwatson	case VM_PROT_EXECUTE:
1887100979Srwatson		return ("--x");
1888100979Srwatson	case VM_PROT_WRITE | VM_PROT_EXECUTE:
1889100979Srwatson		return ("-wx");
1890100979Srwatson	default:
1891100979Srwatson		return ("---");
1892100979Srwatson	}
1893100979Srwatson}
1894100979Srwatson
1895100979Srwatsonstatic void
1896100979Srwatsonmac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
1897100979Srwatson    struct vm_map *map)
1898100979Srwatson{
1899100979Srwatson	struct vm_map_entry *vme;
1900104546Srwatson	int result;
1901104546Srwatson	vm_prot_t revokeperms;
1902100979Srwatson	vm_object_t object;
1903100979Srwatson	vm_ooffset_t offset;
1904100979Srwatson	struct vnode *vp;
1905100979Srwatson
1906103136Srwatson	if (!mac_mmap_revocation)
1907103136Srwatson		return;
1908103136Srwatson
1909100979Srwatson	vm_map_lock_read(map);
1910100979Srwatson	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
1911100979Srwatson		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
1912100979Srwatson			mac_cred_mmapped_drop_perms_recurse(td, cred,
1913100979Srwatson			    vme->object.sub_map);
1914100979Srwatson			continue;
1915100979Srwatson		}
1916100979Srwatson		/*
1917100979Srwatson		 * Skip over entries that obviously are not shared.
1918100979Srwatson		 */
1919100979Srwatson		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
1920100979Srwatson		    !vme->max_protection)
1921100979Srwatson			continue;
1922100979Srwatson		/*
1923100979Srwatson		 * Drill down to the deepest backing object.
1924100979Srwatson		 */
1925100979Srwatson		offset = vme->offset;
1926100979Srwatson		object = vme->object.vm_object;
1927100979Srwatson		if (object == NULL)
1928100979Srwatson			continue;
1929100979Srwatson		while (object->backing_object != NULL) {
1930100979Srwatson			object = object->backing_object;
1931100979Srwatson			offset += object->backing_object_offset;
1932100979Srwatson		}
1933100979Srwatson		/*
1934100979Srwatson		 * At the moment, vm_maps and objects aren't considered
1935100979Srwatson		 * by the MAC system, so only things with backing by a
1936100979Srwatson		 * normal object (read: vnodes) are checked.
1937100979Srwatson		 */
1938100979Srwatson		if (object->type != OBJT_VNODE)
1939100979Srwatson			continue;
1940100979Srwatson		vp = (struct vnode *)object->handle;
1941100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1942104546Srwatson		result = vme->max_protection;
1943104546Srwatson		mac_check_vnode_mmap_downgrade(cred, vp, &result);
1944100979Srwatson		VOP_UNLOCK(vp, 0, td);
1945100979Srwatson		/*
1946100979Srwatson		 * Find out what maximum protection we may be allowing
1947100979Srwatson		 * now but a policy needs to get removed.
1948100979Srwatson		 */
1949100979Srwatson		revokeperms = vme->max_protection & ~result;
1950100979Srwatson		if (!revokeperms)
1951100979Srwatson			continue;
1952102949Sbde		printf("pid %ld: revoking %s perms from %#lx:%ld "
1953102949Sbde		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
1954102949Sbde		    prot2str(revokeperms), (u_long)vme->start,
1955102949Sbde		    (long)(vme->end - vme->start),
1956100979Srwatson		    prot2str(vme->max_protection), prot2str(vme->protection));
1957100979Srwatson		vm_map_lock_upgrade(map);
1958100979Srwatson		/*
1959100979Srwatson		 * This is the really simple case: if a map has more
1960100979Srwatson		 * max_protection than is allowed, but it's not being
1961100979Srwatson		 * actually used (that is, the current protection is
1962100979Srwatson		 * still allowed), we can just wipe it out and do
1963100979Srwatson		 * nothing more.
1964100979Srwatson		 */
1965100979Srwatson		if ((vme->protection & revokeperms) == 0) {
1966100979Srwatson			vme->max_protection -= revokeperms;
1967100979Srwatson		} else {
1968100979Srwatson			if (revokeperms & VM_PROT_WRITE) {
1969100979Srwatson				/*
1970100979Srwatson				 * In the more complicated case, flush out all
1971100979Srwatson				 * pending changes to the object then turn it
1972100979Srwatson				 * copy-on-write.
1973100979Srwatson				 */
1974100979Srwatson				vm_object_reference(object);
1975100979Srwatson				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1976100979Srwatson				vm_object_page_clean(object,
1977100979Srwatson				    OFF_TO_IDX(offset),
1978100979Srwatson				    OFF_TO_IDX(offset + vme->end - vme->start +
1979100979Srwatson					PAGE_MASK),
1980100979Srwatson				    OBJPC_SYNC);
1981100979Srwatson				VOP_UNLOCK(vp, 0, td);
1982100979Srwatson				vm_object_deallocate(object);
1983100979Srwatson				/*
1984100979Srwatson				 * Why bother if there's no read permissions
1985100979Srwatson				 * anymore?  For the rest, we need to leave
1986100979Srwatson				 * the write permissions on for COW, or
1987100979Srwatson				 * remove them entirely if configured to.
1988100979Srwatson				 */
1989100979Srwatson				if (!mac_mmap_revocation_via_cow) {
1990100979Srwatson					vme->max_protection &= ~VM_PROT_WRITE;
1991100979Srwatson					vme->protection &= ~VM_PROT_WRITE;
1992100979Srwatson				} if ((revokeperms & VM_PROT_READ) == 0)
1993100979Srwatson					vme->eflags |= MAP_ENTRY_COW |
1994100979Srwatson					    MAP_ENTRY_NEEDS_COPY;
1995100979Srwatson			}
1996100979Srwatson			if (revokeperms & VM_PROT_EXECUTE) {
1997100979Srwatson				vme->max_protection &= ~VM_PROT_EXECUTE;
1998100979Srwatson				vme->protection &= ~VM_PROT_EXECUTE;
1999100979Srwatson			}
2000100979Srwatson			if (revokeperms & VM_PROT_READ) {
2001100979Srwatson				vme->max_protection = 0;
2002100979Srwatson				vme->protection = 0;
2003100979Srwatson			}
2004100979Srwatson			pmap_protect(map->pmap, vme->start, vme->end,
2005100979Srwatson			    vme->protection & ~revokeperms);
2006100979Srwatson			vm_map_simplify_entry(map, vme);
2007100979Srwatson		}
2008100979Srwatson		vm_map_lock_downgrade(map);
2009100979Srwatson	}
2010100979Srwatson	vm_map_unlock_read(map);
2011100979Srwatson}
2012100979Srwatson
2013100979Srwatson/*
2014100979Srwatson * When the subject's label changes, it may require revocation of privilege
2015100979Srwatson * to mapped objects.  This can't be done on-the-fly later with a unified
2016100979Srwatson * buffer cache.
2017100979Srwatson */
2018100979Srwatsonstatic void
2019100979Srwatsonmac_relabel_cred(struct ucred *cred, struct label *newlabel)
2020100979Srwatson{
2021100979Srwatson
2022100979Srwatson	MAC_PERFORM(relabel_cred, cred, newlabel);
2023100979Srwatson}
2024100979Srwatson
2025100979Srwatsonvoid
2026100979Srwatsonmac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2027100979Srwatson{
2028100979Srwatson
2029100979Srwatson	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2030100979Srwatson}
2031100979Srwatson
2032100979Srwatsonvoid
2033100979Srwatsonmac_create_ifnet(struct ifnet *ifnet)
2034100979Srwatson{
2035100979Srwatson
2036100979Srwatson	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2037100979Srwatson}
2038100979Srwatson
2039100979Srwatsonvoid
2040100979Srwatsonmac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2041100979Srwatson{
2042100979Srwatson
2043100979Srwatson	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2044100979Srwatson}
2045100979Srwatson
2046100979Srwatsonvoid
2047100979Srwatsonmac_create_socket(struct ucred *cred, struct socket *socket)
2048100979Srwatson{
2049100979Srwatson
2050100979Srwatson	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2051100979Srwatson}
2052100979Srwatson
2053100979Srwatsonvoid
2054100979Srwatsonmac_create_pipe(struct ucred *cred, struct pipe *pipe)
2055100979Srwatson{
2056100979Srwatson
2057100979Srwatson	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2058100979Srwatson}
2059100979Srwatson
2060100979Srwatsonvoid
2061100979Srwatsonmac_create_socket_from_socket(struct socket *oldsocket,
2062100979Srwatson    struct socket *newsocket)
2063100979Srwatson{
2064100979Srwatson
2065100979Srwatson	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2066100979Srwatson	    newsocket, &newsocket->so_label);
2067100979Srwatson}
2068100979Srwatson
2069100979Srwatsonstatic void
2070100979Srwatsonmac_relabel_socket(struct ucred *cred, struct socket *socket,
2071100979Srwatson    struct label *newlabel)
2072100979Srwatson{
2073100979Srwatson
2074100979Srwatson	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2075100979Srwatson}
2076100979Srwatson
2077100979Srwatsonstatic void
2078100979Srwatsonmac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2079100979Srwatson{
2080100979Srwatson
2081100979Srwatson	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2082100979Srwatson}
2083100979Srwatson
2084100979Srwatsonvoid
2085100979Srwatsonmac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2086100979Srwatson{
2087100979Srwatson
2088100979Srwatson	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2089100979Srwatson	    socket, &socket->so_peerlabel);
2090100979Srwatson}
2091100979Srwatson
2092100979Srwatsonvoid
2093100979Srwatsonmac_set_socket_peer_from_socket(struct socket *oldsocket,
2094100979Srwatson    struct socket *newsocket)
2095100979Srwatson{
2096100979Srwatson
2097100979Srwatson	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2098100979Srwatson	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2099100979Srwatson}
2100100979Srwatson
2101100979Srwatsonvoid
2102100979Srwatsonmac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2103100979Srwatson{
2104100979Srwatson
2105100979Srwatson	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2106100979Srwatson	    datagram, &datagram->m_pkthdr.label);
2107100979Srwatson}
2108100979Srwatson
2109100979Srwatsonvoid
2110100979Srwatsonmac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2111100979Srwatson{
2112100979Srwatson
2113100979Srwatson	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2114100979Srwatson	    fragment, &fragment->m_pkthdr.label);
2115100979Srwatson}
2116100979Srwatson
2117100979Srwatsonvoid
2118100979Srwatsonmac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2119100979Srwatson{
2120100979Srwatson
2121100979Srwatson	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2122100979Srwatson	    &ipq->ipq_label);
2123100979Srwatson}
2124100979Srwatson
2125100979Srwatsonvoid
2126100979Srwatsonmac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2127100979Srwatson{
2128100979Srwatson
2129100979Srwatson	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2130100979Srwatson	    newmbuf, &newmbuf->m_pkthdr.label);
2131100979Srwatson}
2132100979Srwatson
2133100979Srwatsonvoid
2134100979Srwatsonmac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2135100979Srwatson{
2136100979Srwatson
2137100979Srwatson	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2138100979Srwatson	    &mbuf->m_pkthdr.label);
2139100979Srwatson}
2140100979Srwatson
2141100979Srwatsonvoid
2142100979Srwatsonmac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2143100979Srwatson{
2144100979Srwatson
2145100979Srwatson	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2146100979Srwatson	    &mbuf->m_pkthdr.label);
2147100979Srwatson}
2148100979Srwatson
2149100979Srwatsonvoid
2150100979Srwatsonmac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2151100979Srwatson{
2152100979Srwatson
2153100979Srwatson	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2154100979Srwatson	    &mbuf->m_pkthdr.label);
2155100979Srwatson}
2156100979Srwatson
2157100979Srwatsonvoid
2158100979Srwatsonmac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2159100979Srwatson    struct mbuf *newmbuf)
2160100979Srwatson{
2161100979Srwatson
2162100979Srwatson	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2163100979Srwatson	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2164100979Srwatson	    &newmbuf->m_pkthdr.label);
2165100979Srwatson}
2166100979Srwatson
2167100979Srwatsonvoid
2168100979Srwatsonmac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2169100979Srwatson{
2170100979Srwatson
2171100979Srwatson	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2172100979Srwatson	    newmbuf, &newmbuf->m_pkthdr.label);
2173100979Srwatson}
2174100979Srwatson
2175100979Srwatsonint
2176100979Srwatsonmac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2177100979Srwatson{
2178100979Srwatson	int result;
2179100979Srwatson
2180100979Srwatson	result = 1;
2181100979Srwatson	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2182100979Srwatson	    ipq, &ipq->ipq_label);
2183100979Srwatson
2184100979Srwatson	return (result);
2185100979Srwatson}
2186100979Srwatson
2187100979Srwatsonvoid
2188100979Srwatsonmac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2189100979Srwatson{
2190100979Srwatson
2191100979Srwatson	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2192100979Srwatson	    &ipq->ipq_label);
2193100979Srwatson}
2194100979Srwatson
2195100979Srwatsonvoid
2196100979Srwatsonmac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2197100979Srwatson{
2198100979Srwatson
2199100979Srwatson	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2200100979Srwatson	    &mbuf->m_pkthdr.label);
2201100979Srwatson}
2202100979Srwatson
2203100979Srwatsonvoid
2204100979Srwatsonmac_create_mount(struct ucred *cred, struct mount *mp)
2205100979Srwatson{
2206100979Srwatson
2207100979Srwatson	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2208100979Srwatson	    &mp->mnt_fslabel);
2209100979Srwatson}
2210100979Srwatson
2211100979Srwatsonvoid
2212100979Srwatsonmac_create_root_mount(struct ucred *cred, struct mount *mp)
2213100979Srwatson{
2214100979Srwatson
2215100979Srwatson	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2216100979Srwatson	    &mp->mnt_fslabel);
2217100979Srwatson}
2218100979Srwatson
2219100979Srwatsonint
2220100979Srwatsonmac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2221100979Srwatson{
2222100979Srwatson	int error;
2223100979Srwatson
2224100979Srwatson	if (!mac_enforce_network)
2225100979Srwatson		return (0);
2226100979Srwatson
2227100979Srwatson	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2228100979Srwatson	    &ifnet->if_label);
2229100979Srwatson
2230100979Srwatson	return (error);
2231100979Srwatson}
2232100979Srwatson
2233100979Srwatsonstatic int
2234100979Srwatsonmac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2235100979Srwatson{
2236100979Srwatson	int error;
2237100979Srwatson
2238100979Srwatson	MAC_CHECK(check_cred_relabel, cred, newlabel);
2239100979Srwatson
2240100979Srwatson	return (error);
2241100979Srwatson}
2242100979Srwatson
2243100979Srwatsonint
2244100979Srwatsonmac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2245100979Srwatson{
2246100979Srwatson	int error;
2247100979Srwatson
2248100979Srwatson	if (!mac_enforce_process)
2249100979Srwatson		return (0);
2250100979Srwatson
2251100979Srwatson	MAC_CHECK(check_cred_visible, u1, u2);
2252100979Srwatson
2253100979Srwatson	return (error);
2254100979Srwatson}
2255100979Srwatson
2256100979Srwatsonint
2257100979Srwatsonmac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2258100979Srwatson{
2259100979Srwatson	int error;
2260100979Srwatson
2261100979Srwatson	if (!mac_enforce_network)
2262100979Srwatson		return (0);
2263100979Srwatson
2264100979Srwatson	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2265100979Srwatson	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2266105598Sbrooks		if_printf(ifnet, "not initialized\n");
2267100979Srwatson
2268100979Srwatson	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2269100979Srwatson	    &mbuf->m_pkthdr.label);
2270100979Srwatson
2271100979Srwatson	return (error);
2272100979Srwatson}
2273100979Srwatson
2274100979Srwatsonint
2275106308Srwatsonmac_check_kenv_dump(struct ucred *cred)
2276106308Srwatson{
2277106308Srwatson	int error;
2278106308Srwatson
2279106308Srwatson	if (!mac_enforce_system)
2280106308Srwatson		return (0);
2281106308Srwatson
2282106308Srwatson	MAC_CHECK(check_kenv_dump, cred);
2283106308Srwatson
2284106308Srwatson	return (error);
2285106308Srwatson}
2286106308Srwatson
2287106308Srwatsonint
2288106308Srwatsonmac_check_kenv_get(struct ucred *cred, char *name)
2289106308Srwatson{
2290106308Srwatson	int error;
2291106308Srwatson
2292106308Srwatson	if (!mac_enforce_system)
2293106308Srwatson		return (0);
2294106308Srwatson
2295106308Srwatson	MAC_CHECK(check_kenv_get, cred, name);
2296106308Srwatson
2297106308Srwatson	return (error);
2298106308Srwatson}
2299106308Srwatson
2300106308Srwatsonint
2301106308Srwatsonmac_check_kenv_set(struct ucred *cred, char *name, char *value)
2302106308Srwatson{
2303106308Srwatson	int error;
2304106308Srwatson
2305106308Srwatson	if (!mac_enforce_system)
2306106308Srwatson		return (0);
2307106308Srwatson
2308106308Srwatson	MAC_CHECK(check_kenv_set, cred, name, value);
2309106308Srwatson
2310106308Srwatson	return (error);
2311106308Srwatson}
2312106308Srwatson
2313106308Srwatsonint
2314106308Srwatsonmac_check_kenv_unset(struct ucred *cred, char *name)
2315106308Srwatson{
2316106308Srwatson	int error;
2317106308Srwatson
2318106308Srwatson	if (!mac_enforce_system)
2319106308Srwatson		return (0);
2320106308Srwatson
2321106308Srwatson	MAC_CHECK(check_kenv_unset, cred, name);
2322106308Srwatson
2323106308Srwatson	return (error);
2324106308Srwatson}
2325106308Srwatson
2326106308Srwatsonint
2327107089Srwatsonmac_check_kld_load(struct ucred *cred, struct vnode *vp)
2328107089Srwatson{
2329107089Srwatson	int error;
2330107089Srwatson
2331107089Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2332107089Srwatson
2333107089Srwatson	if (!mac_enforce_kld)
2334107089Srwatson		return (0);
2335107089Srwatson
2336107089Srwatson	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2337107089Srwatson
2338107089Srwatson	return (error);
2339107089Srwatson}
2340107089Srwatson
2341107089Srwatsonint
2342107089Srwatsonmac_check_kld_stat(struct ucred *cred)
2343107089Srwatson{
2344107089Srwatson	int error;
2345107089Srwatson
2346107089Srwatson	if (!mac_enforce_kld)
2347107089Srwatson		return (0);
2348107089Srwatson
2349107089Srwatson	MAC_CHECK(check_kld_stat, cred);
2350107089Srwatson
2351107089Srwatson	return (error);
2352107089Srwatson}
2353107089Srwatson
2354107089Srwatsonint
2355107089Srwatsonmac_check_kld_unload(struct ucred *cred)
2356107089Srwatson{
2357107089Srwatson	int error;
2358107089Srwatson
2359107089Srwatson	if (!mac_enforce_kld)
2360107089Srwatson		return (0);
2361107089Srwatson
2362107089Srwatson	MAC_CHECK(check_kld_unload, cred);
2363107089Srwatson
2364107089Srwatson	return (error);
2365107089Srwatson}
2366107089Srwatson
2367107089Srwatsonint
2368100979Srwatsonmac_check_mount_stat(struct ucred *cred, struct mount *mount)
2369100979Srwatson{
2370100979Srwatson	int error;
2371100979Srwatson
2372100979Srwatson	if (!mac_enforce_fs)
2373100979Srwatson		return (0);
2374100979Srwatson
2375100979Srwatson	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2376100979Srwatson
2377100979Srwatson	return (error);
2378100979Srwatson}
2379100979Srwatson
2380100979Srwatsonint
2381100979Srwatsonmac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2382100979Srwatson    void *data)
2383100979Srwatson{
2384100979Srwatson	int error;
2385100979Srwatson
2386104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2387104269Srwatson
2388104269Srwatson	if (!mac_enforce_pipe)
2389104269Srwatson		return (0);
2390104269Srwatson
2391100979Srwatson	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2392100979Srwatson
2393100979Srwatson	return (error);
2394100979Srwatson}
2395100979Srwatson
2396100979Srwatsonint
2397102115Srwatsonmac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2398100979Srwatson{
2399100979Srwatson	int error;
2400100979Srwatson
2401104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2402104269Srwatson
2403104269Srwatson	if (!mac_enforce_pipe)
2404104269Srwatson		return (0);
2405104269Srwatson
2406102115Srwatson	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2407100979Srwatson
2408100979Srwatson	return (error);
2409100979Srwatson}
2410100979Srwatson
2411102115Srwatsonint
2412102115Srwatsonmac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2413102115Srwatson{
2414102115Srwatson	int error;
2415102115Srwatson
2416104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2417104269Srwatson
2418104269Srwatson	if (!mac_enforce_pipe)
2419104269Srwatson		return (0);
2420104269Srwatson
2421102115Srwatson	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2422102115Srwatson
2423102115Srwatson	return (error);
2424102115Srwatson}
2425102115Srwatson
2426100979Srwatsonstatic int
2427100979Srwatsonmac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2428100979Srwatson    struct label *newlabel)
2429100979Srwatson{
2430100979Srwatson	int error;
2431100979Srwatson
2432104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2433104269Srwatson
2434104269Srwatson	if (!mac_enforce_pipe)
2435104269Srwatson		return (0);
2436104269Srwatson
2437100979Srwatson	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2438100979Srwatson
2439100979Srwatson	return (error);
2440100979Srwatson}
2441100979Srwatson
2442100979Srwatsonint
2443102115Srwatsonmac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2444102115Srwatson{
2445102115Srwatson	int error;
2446102115Srwatson
2447104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2448104269Srwatson
2449104269Srwatson	if (!mac_enforce_pipe)
2450104269Srwatson		return (0);
2451104269Srwatson
2452102115Srwatson	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2453102115Srwatson
2454102115Srwatson	return (error);
2455102115Srwatson}
2456102115Srwatson
2457102115Srwatsonint
2458102115Srwatsonmac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2459102115Srwatson{
2460102115Srwatson	int error;
2461102115Srwatson
2462104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2463104269Srwatson
2464104269Srwatson	if (!mac_enforce_pipe)
2465104269Srwatson		return (0);
2466104269Srwatson
2467102115Srwatson	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2468102115Srwatson
2469102115Srwatson	return (error);
2470102115Srwatson}
2471102115Srwatson
2472102115Srwatsonint
2473100979Srwatsonmac_check_proc_debug(struct ucred *cred, struct proc *proc)
2474100979Srwatson{
2475100979Srwatson	int error;
2476100979Srwatson
2477102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2478102103Srwatson
2479100979Srwatson	if (!mac_enforce_process)
2480100979Srwatson		return (0);
2481100979Srwatson
2482100979Srwatson	MAC_CHECK(check_proc_debug, cred, proc);
2483100979Srwatson
2484100979Srwatson	return (error);
2485100979Srwatson}
2486100979Srwatson
2487100979Srwatsonint
2488100979Srwatsonmac_check_proc_sched(struct ucred *cred, struct proc *proc)
2489100979Srwatson{
2490100979Srwatson	int error;
2491100979Srwatson
2492102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2493102103Srwatson
2494100979Srwatson	if (!mac_enforce_process)
2495100979Srwatson		return (0);
2496100979Srwatson
2497100979Srwatson	MAC_CHECK(check_proc_sched, cred, proc);
2498100979Srwatson
2499100979Srwatson	return (error);
2500100979Srwatson}
2501100979Srwatson
2502100979Srwatsonint
2503100979Srwatsonmac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2504100979Srwatson{
2505100979Srwatson	int error;
2506100979Srwatson
2507102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2508102103Srwatson
2509100979Srwatson	if (!mac_enforce_process)
2510100979Srwatson		return (0);
2511100979Srwatson
2512100979Srwatson	MAC_CHECK(check_proc_signal, cred, proc, signum);
2513100979Srwatson
2514100979Srwatson	return (error);
2515100979Srwatson}
2516100979Srwatson
2517100979Srwatsonint
2518100979Srwatsonmac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2519100979Srwatson    struct sockaddr *sockaddr)
2520100979Srwatson{
2521100979Srwatson	int error;
2522100979Srwatson
2523100979Srwatson	if (!mac_enforce_socket)
2524100979Srwatson		return (0);
2525100979Srwatson
2526100979Srwatson	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2527100979Srwatson	    sockaddr);
2528100979Srwatson
2529100979Srwatson	return (error);
2530100979Srwatson}
2531100979Srwatson
2532100979Srwatsonint
2533100979Srwatsonmac_check_socket_connect(struct ucred *cred, struct socket *socket,
2534100979Srwatson    struct sockaddr *sockaddr)
2535100979Srwatson{
2536100979Srwatson	int error;
2537100979Srwatson
2538100979Srwatson	if (!mac_enforce_socket)
2539100979Srwatson		return (0);
2540100979Srwatson
2541100979Srwatson	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2542100979Srwatson	    sockaddr);
2543100979Srwatson
2544100979Srwatson	return (error);
2545100979Srwatson}
2546100979Srwatson
2547100979Srwatsonint
2548101933Srwatsonmac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2549100979Srwatson{
2550100979Srwatson	int error;
2551100979Srwatson
2552100979Srwatson	if (!mac_enforce_socket)
2553100979Srwatson		return (0);
2554100979Srwatson
2555101933Srwatson	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2556101933Srwatson	    &mbuf->m_pkthdr.label);
2557101933Srwatson
2558100979Srwatson	return (error);
2559100979Srwatson}
2560100979Srwatson
2561100979Srwatsonint
2562101933Srwatsonmac_check_socket_listen(struct ucred *cred, struct socket *socket)
2563100979Srwatson{
2564100979Srwatson	int error;
2565100979Srwatson
2566100979Srwatson	if (!mac_enforce_socket)
2567100979Srwatson		return (0);
2568100979Srwatson
2569101933Srwatson	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2570100979Srwatson	return (error);
2571100979Srwatson}
2572100979Srwatson
2573104571Srwatsonint
2574104571Srwatsonmac_check_socket_receive(struct ucred *cred, struct socket *so)
2575104571Srwatson{
2576104571Srwatson	int error;
2577104571Srwatson
2578104571Srwatson	if (!mac_enforce_socket)
2579104571Srwatson		return (0);
2580104571Srwatson
2581104571Srwatson	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2582104571Srwatson
2583104571Srwatson	return (error);
2584104571Srwatson}
2585104571Srwatson
2586100979Srwatsonstatic int
2587100979Srwatsonmac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2588100979Srwatson    struct label *newlabel)
2589100979Srwatson{
2590100979Srwatson	int error;
2591100979Srwatson
2592100979Srwatson	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2593100979Srwatson	    newlabel);
2594100979Srwatson
2595100979Srwatson	return (error);
2596100979Srwatson}
2597100979Srwatson
2598100979Srwatsonint
2599104571Srwatsonmac_check_socket_send(struct ucred *cred, struct socket *so)
2600104571Srwatson{
2601104571Srwatson	int error;
2602104571Srwatson
2603104571Srwatson	if (!mac_enforce_socket)
2604104571Srwatson		return (0);
2605104571Srwatson
2606104571Srwatson	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2607104571Srwatson
2608104571Srwatson	return (error);
2609104571Srwatson}
2610104571Srwatson
2611104571Srwatsonint
2612100979Srwatsonmac_check_socket_visible(struct ucred *cred, struct socket *socket)
2613100979Srwatson{
2614100979Srwatson	int error;
2615100979Srwatson
2616100979Srwatson	if (!mac_enforce_socket)
2617100979Srwatson		return (0);
2618105694Srwatson
2619100979Srwatson	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2620105694Srwatson
2621100979Srwatson	return (error);
2622100979Srwatson}
2623100979Srwatson
2624100979Srwatsonint
2625106412Srwatsonmac_check_system_acct(struct ucred *cred, struct vnode *vp)
2626106412Srwatson{
2627106412Srwatson	int error;
2628106412Srwatson
2629106412Srwatson	if (vp != NULL) {
2630106412Srwatson		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2631106412Srwatson	}
2632106412Srwatson
2633106412Srwatson	if (!mac_enforce_system)
2634106412Srwatson		return (0);
2635106412Srwatson
2636106412Srwatson	MAC_CHECK(check_system_acct, cred, vp,
2637106412Srwatson	    vp != NULL ? &vp->v_label : NULL);
2638106412Srwatson
2639106412Srwatson	return (error);
2640106412Srwatson}
2641106412Srwatson
2642106412Srwatsonint
2643106412Srwatsonmac_check_system_nfsd(struct ucred *cred)
2644106412Srwatson{
2645106412Srwatson	int error;
2646106412Srwatson
2647106412Srwatson	if (!mac_enforce_system)
2648106412Srwatson		return (0);
2649106412Srwatson
2650106412Srwatson	MAC_CHECK(check_system_nfsd, cred);
2651106412Srwatson
2652106412Srwatson	return (error);
2653106412Srwatson}
2654106412Srwatson
2655106412Srwatsonint
2656106024Srwatsonmac_check_system_reboot(struct ucred *cred, int howto)
2657106024Srwatson{
2658106024Srwatson	int error;
2659106024Srwatson
2660106045Srwatson	if (!mac_enforce_system)
2661106024Srwatson		return (0);
2662106024Srwatson
2663106024Srwatson	MAC_CHECK(check_system_reboot, cred, howto);
2664106045Srwatson
2665106024Srwatson	return (error);
2666106024Srwatson}
2667106024Srwatson
2668106024Srwatsonint
2669106369Srwatsonmac_check_system_settime(struct ucred *cred)
2670106369Srwatson{
2671106369Srwatson	int error;
2672106369Srwatson
2673106369Srwatson	if (!mac_enforce_system)
2674106369Srwatson		return (0);
2675106369Srwatson
2676106369Srwatson	MAC_CHECK(check_system_settime, cred);
2677106369Srwatson
2678106369Srwatson	return (error);
2679106369Srwatson}
2680106369Srwatson
2681106369Srwatsonint
2682106023Srwatsonmac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2683106023Srwatson{
2684106023Srwatson	int error;
2685106023Srwatson
2686106023Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2687106023Srwatson
2688106045Srwatson	if (!mac_enforce_system)
2689106023Srwatson		return (0);
2690106023Srwatson
2691106023Srwatson	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2692106023Srwatson	return (error);
2693106023Srwatson}
2694106023Srwatson
2695106023Srwatsonint
2696106025Srwatsonmac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2697106025Srwatson    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2698106025Srwatson{
2699106025Srwatson	int error;
2700106025Srwatson
2701106025Srwatson	/*
2702106025Srwatson	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2703106025Srwatson	 * but since it's not exported from kern_sysctl.c, we can't.
2704106025Srwatson	 */
2705106045Srwatson	if (!mac_enforce_system)
2706106025Srwatson		return (0);
2707106025Srwatson
2708106025Srwatson	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2709106025Srwatson	    inkernel, new, newlen);
2710106025Srwatson
2711106025Srwatson	return (error);
2712106025Srwatson}
2713106025Srwatson
2714106025Srwatsonint
2715100979Srwatsonmac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2716100979Srwatson    struct ifnet *ifnet)
2717100979Srwatson{
2718105694Srwatson	char *elements, *buffer;
2719105694Srwatson	struct mac mac;
2720100979Srwatson	int error;
2721100979Srwatson
2722105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2723100979Srwatson	if (error)
2724100979Srwatson		return (error);
2725100979Srwatson
2726105694Srwatson	error = mac_check_structmac_consistent(&mac);
2727105694Srwatson	if (error)
2728105694Srwatson		return (error);
2729105694Srwatson
2730105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2731105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2732105694Srwatson	if (error) {
2733105694Srwatson		free(elements, M_MACTEMP);
2734105694Srwatson		return (error);
2735105694Srwatson	}
2736105694Srwatson
2737105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2738105694Srwatson	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2739105694Srwatson	    buffer, mac.m_buflen, M_WAITOK);
2740105694Srwatson	if (error == 0)
2741105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2742105694Srwatson
2743105694Srwatson	free(buffer, M_MACTEMP);
2744105694Srwatson	free(elements, M_MACTEMP);
2745105694Srwatson
2746105694Srwatson	return (error);
2747100979Srwatson}
2748100979Srwatson
2749100979Srwatsonint
2750100979Srwatsonmac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2751100979Srwatson    struct ifnet *ifnet)
2752100979Srwatson{
2753100979Srwatson	struct label intlabel;
2754105694Srwatson	struct mac mac;
2755105694Srwatson	char *buffer;
2756100979Srwatson	int error;
2757100979Srwatson
2758105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2759100979Srwatson	if (error)
2760100979Srwatson		return (error);
2761100979Srwatson
2762105694Srwatson	error = mac_check_structmac_consistent(&mac);
2763100979Srwatson	if (error)
2764100979Srwatson		return (error);
2765100979Srwatson
2766105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2767105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2768105694Srwatson	if (error) {
2769105694Srwatson		free(buffer, M_MACTEMP);
2770105694Srwatson		return (error);
2771105694Srwatson	}
2772105694Srwatson
2773105694Srwatson	mac_init_ifnet_label(&intlabel);
2774105694Srwatson	error = mac_internalize_ifnet_label(&intlabel, buffer);
2775105694Srwatson	free(buffer, M_MACTEMP);
2776105694Srwatson	if (error) {
2777105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2778105694Srwatson		return (error);
2779105694Srwatson	}
2780105694Srwatson
2781100979Srwatson	/*
2782100979Srwatson	 * XXX: Note that this is a redundant privilege check, since
2783100979Srwatson	 * policies impose this check themselves if required by the
2784100979Srwatson	 * policy.  Eventually, this should go away.
2785100979Srwatson	 */
2786100979Srwatson	error = suser_cred(cred, 0);
2787105694Srwatson	if (error) {
2788105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2789105694Srwatson		return (error);
2790105694Srwatson	}
2791100979Srwatson
2792100979Srwatson	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2793100979Srwatson	    &intlabel);
2794105694Srwatson	if (error) {
2795105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2796105694Srwatson		return (error);
2797105694Srwatson	}
2798100979Srwatson
2799100979Srwatson	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2800100979Srwatson
2801105694Srwatson	mac_destroy_ifnet_label(&intlabel);
2802105694Srwatson	return (0);
2803100979Srwatson}
2804100979Srwatson
2805100979Srwatsonvoid
2806107698Srwatsonmac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
2807100979Srwatson{
2808100979Srwatson
2809107698Srwatson	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
2810100979Srwatson}
2811100979Srwatson
2812104533Srwatsonvoid
2813107698Srwatsonmac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
2814107698Srwatson    struct devfs_dirent *dd, struct devfs_dirent *de)
2815104533Srwatson{
2816104533Srwatson
2817107698Srwatson	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
2818104533Srwatson	    &de->de_label);
2819104533Srwatson}
2820104533Srwatson
2821100979Srwatsonvoid
2822107698Srwatsonmac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
2823100979Srwatson    struct devfs_dirent *de)
2824100979Srwatson{
2825100979Srwatson
2826107698Srwatson	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
2827100979Srwatson	    &de->de_label);
2828100979Srwatson}
2829100979Srwatson
2830100979Srwatsonint
2831100979Srwatsonmac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2832105694Srwatson    struct mac *mac)
2833100979Srwatson{
2834100979Srwatson	struct label intlabel;
2835105694Srwatson	char *buffer;
2836100979Srwatson	int error;
2837100979Srwatson
2838105694Srwatson	error = mac_check_structmac_consistent(mac);
2839100979Srwatson	if (error)
2840100979Srwatson		return (error);
2841100979Srwatson
2842105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2843105694Srwatson	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2844105694Srwatson	if (error) {
2845105694Srwatson		free(buffer, M_MACTEMP);
2846105694Srwatson		return (error);
2847105694Srwatson	}
2848105694Srwatson
2849105694Srwatson	mac_init_socket_label(&intlabel, M_WAITOK);
2850105694Srwatson	error = mac_internalize_socket_label(&intlabel, buffer);
2851105694Srwatson	free(buffer, M_MACTEMP);
2852105694Srwatson	if (error) {
2853105694Srwatson		mac_destroy_socket_label(&intlabel);
2854105694Srwatson		return (error);
2855105694Srwatson	}
2856105694Srwatson
2857100979Srwatson	mac_check_socket_relabel(cred, so, &intlabel);
2858100979Srwatson	if (error) {
2859105694Srwatson		mac_destroy_socket_label(&intlabel);
2860100979Srwatson		return (error);
2861100979Srwatson	}
2862100979Srwatson
2863100979Srwatson	mac_relabel_socket(cred, so, &intlabel);
2864100979Srwatson
2865105694Srwatson	mac_destroy_socket_label(&intlabel);
2866100979Srwatson	return (0);
2867100979Srwatson}
2868100979Srwatson
2869100979Srwatsonint
2870100979Srwatsonmac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2871100979Srwatson{
2872100979Srwatson	int error;
2873100979Srwatson
2874104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2875104269Srwatson
2876100979Srwatson	error = mac_check_pipe_relabel(cred, pipe, label);
2877100979Srwatson	if (error)
2878100979Srwatson		return (error);
2879100979Srwatson
2880100979Srwatson	mac_relabel_pipe(cred, pipe, label);
2881100979Srwatson
2882100979Srwatson	return (0);
2883100979Srwatson}
2884100979Srwatson
2885100979Srwatsonint
2886100979Srwatsonmac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2887105694Srwatson    struct mac *mac)
2888100979Srwatson{
2889105694Srwatson	char *buffer, *elements;
2890105694Srwatson	int error;
2891100979Srwatson
2892105694Srwatson	error = mac_check_structmac_consistent(mac);
2893105694Srwatson	if (error)
2894105694Srwatson		return (error);
2895105694Srwatson
2896105694Srwatson	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2897105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2898105694Srwatson	if (error) {
2899105694Srwatson		free(elements, M_MACTEMP);
2900105694Srwatson		return (error);
2901105694Srwatson	}
2902105694Srwatson
2903105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2904105694Srwatson	error = mac_externalize_socket_label(&so->so_label, elements,
2905105694Srwatson	    buffer, mac->m_buflen, M_WAITOK);
2906105694Srwatson	if (error == 0)
2907105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2908105694Srwatson
2909105694Srwatson	free(buffer, M_MACTEMP);
2910105694Srwatson	free(elements, M_MACTEMP);
2911105694Srwatson
2912105694Srwatson	return (error);
2913100979Srwatson}
2914100979Srwatson
2915100979Srwatsonint
2916100979Srwatsonmac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2917105694Srwatson    struct mac *mac)
2918100979Srwatson{
2919105694Srwatson	char *elements, *buffer;
2920105694Srwatson	int error;
2921100979Srwatson
2922105694Srwatson	error = mac_check_structmac_consistent(mac);
2923105694Srwatson	if (error)
2924105694Srwatson		return (error);
2925105694Srwatson
2926105694Srwatson	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2927105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2928105694Srwatson	if (error) {
2929105694Srwatson		free(elements, M_MACTEMP);
2930105694Srwatson		return (error);
2931105694Srwatson	}
2932105694Srwatson
2933105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2934105694Srwatson	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2935105694Srwatson	    elements, buffer, mac->m_buflen, M_WAITOK);
2936105694Srwatson	if (error == 0)
2937105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2938105694Srwatson
2939105694Srwatson	free(buffer, M_MACTEMP);
2940105694Srwatson	free(elements, M_MACTEMP);
2941105694Srwatson
2942105694Srwatson	return (error);
2943100979Srwatson}
2944100979Srwatson
2945100979Srwatson/*
2946100979Srwatson * Implementation of VOP_SETLABEL() that relies on extended attributes
2947100979Srwatson * to store label data.  Can be referenced by filesystems supporting
2948100979Srwatson * extended attributes.
2949100979Srwatson */
2950100979Srwatsonint
2951100979Srwatsonvop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2952100979Srwatson{
2953100979Srwatson	struct vnode *vp = ap->a_vp;
2954100979Srwatson	struct label *intlabel = ap->a_label;
2955100979Srwatson	int error;
2956100979Srwatson
2957100979Srwatson	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2958100979Srwatson
2959105988Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2960105988Srwatson		return (EOPNOTSUPP);
2961100979Srwatson
2962105988Srwatson	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2963100979Srwatson	if (error)
2964100979Srwatson		return (error);
2965100979Srwatson
2966100979Srwatson	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2967100979Srwatson
2968100979Srwatson	return (0);
2969100979Srwatson}
2970100979Srwatson
2971100979Srwatsonstatic int
2972100979Srwatsonvn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2973100979Srwatson{
2974100979Srwatson	int error;
2975100979Srwatson
2976100979Srwatson	if (vp->v_mount == NULL) {
2977100979Srwatson		/* printf("vn_setlabel: null v_mount\n"); */
2978103314Snjl		if (vp->v_type != VNON)
2979103314Snjl			printf("vn_setlabel: null v_mount with non-VNON\n");
2980100979Srwatson		return (EBADF);
2981100979Srwatson	}
2982100979Srwatson
2983100979Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2984100979Srwatson		return (EOPNOTSUPP);
2985100979Srwatson
2986100979Srwatson	/*
2987100979Srwatson	 * Multi-phase commit.  First check the policies to confirm the
2988100979Srwatson	 * change is OK.  Then commit via the filesystem.  Finally,
2989100979Srwatson	 * update the actual vnode label.  Question: maybe the filesystem
2990100979Srwatson	 * should update the vnode at the end as part of VOP_SETLABEL()?
2991100979Srwatson	 */
2992100979Srwatson	error = mac_check_vnode_relabel(cred, vp, intlabel);
2993100979Srwatson	if (error)
2994100979Srwatson		return (error);
2995100979Srwatson
2996100979Srwatson	/*
2997100979Srwatson	 * VADMIN provides the opportunity for the filesystem to make
2998100979Srwatson	 * decisions about who is and is not able to modify labels
2999100979Srwatson	 * and protections on files.  This might not be right.  We can't
3000100979Srwatson	 * assume VOP_SETLABEL() will do it, because we might implement
3001100979Srwatson	 * that as part of vop_stdsetlabel_ea().
3002100979Srwatson	 */
3003100979Srwatson	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3004100979Srwatson	if (error)
3005100979Srwatson		return (error);
3006100979Srwatson
3007100979Srwatson	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3008100979Srwatson	if (error)
3009100979Srwatson		return (error);
3010100979Srwatson
3011100979Srwatson	return (0);
3012100979Srwatson}
3013100979Srwatson
3014105694Srwatsonint
3015105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3016105694Srwatson{
3017105694Srwatson	char *elements, *buffer;
3018105694Srwatson	struct mac mac;
3019105694Srwatson	struct proc *tproc;
3020105694Srwatson	struct ucred *tcred;
3021105694Srwatson	int error;
3022105694Srwatson
3023105694Srwatson	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3024105694Srwatson	if (error)
3025105694Srwatson		return (error);
3026105694Srwatson
3027105694Srwatson	error = mac_check_structmac_consistent(&mac);
3028105694Srwatson	if (error)
3029105694Srwatson		return (error);
3030105694Srwatson
3031105694Srwatson	tproc = pfind(uap->pid);
3032105694Srwatson	if (tproc == NULL)
3033105694Srwatson		return (ESRCH);
3034105694Srwatson
3035105694Srwatson	tcred = NULL;				/* Satisfy gcc. */
3036105694Srwatson	error = p_cansee(td, tproc);
3037105694Srwatson	if (error == 0)
3038105694Srwatson		tcred = crhold(tproc->p_ucred);
3039105694Srwatson	PROC_UNLOCK(tproc);
3040105694Srwatson	if (error)
3041105694Srwatson		return (error);
3042105694Srwatson
3043105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3044105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3045105694Srwatson	if (error) {
3046105694Srwatson		free(elements, M_MACTEMP);
3047105694Srwatson		crfree(tcred);
3048105694Srwatson		return (error);
3049105694Srwatson	}
3050105694Srwatson
3051105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3052105694Srwatson	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3053105694Srwatson	    buffer, mac.m_buflen, M_WAITOK);
3054105694Srwatson	if (error == 0)
3055105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3056105694Srwatson
3057105694Srwatson	free(buffer, M_MACTEMP);
3058105694Srwatson	free(elements, M_MACTEMP);
3059105694Srwatson	crfree(tcred);
3060105694Srwatson	return (error);
3061105694Srwatson}
3062105694Srwatson
3063100979Srwatson/*
3064100979Srwatson * MPSAFE
3065100979Srwatson */
3066100979Srwatsonint
3067100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3068100894Srwatson{
3069105694Srwatson	char *elements, *buffer;
3070105694Srwatson	struct mac mac;
3071100979Srwatson	int error;
3072100894Srwatson
3073105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3074105694Srwatson	if (error)
3075105694Srwatson		return (error);
3076105694Srwatson
3077105694Srwatson	error = mac_check_structmac_consistent(&mac);
3078105694Srwatson	if (error)
3079105694Srwatson		return (error);
3080105694Srwatson
3081105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3082105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3083105694Srwatson	if (error) {
3084105694Srwatson		free(elements, M_MACTEMP);
3085105694Srwatson		return (error);
3086105694Srwatson	}
3087105694Srwatson
3088105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3089105694Srwatson	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3090105694Srwatson	    elements, buffer, mac.m_buflen, M_WAITOK);
3091100979Srwatson	if (error == 0)
3092105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3093100979Srwatson
3094105694Srwatson	free(buffer, M_MACTEMP);
3095105694Srwatson	free(elements, M_MACTEMP);
3096100979Srwatson	return (error);
3097100979Srwatson}
3098100979Srwatson
3099100979Srwatson/*
3100100979Srwatson * MPSAFE
3101100979Srwatson */
3102100979Srwatsonint
3103100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3104100979Srwatson{
3105100979Srwatson	struct ucred *newcred, *oldcred;
3106105694Srwatson	struct label intlabel;
3107100979Srwatson	struct proc *p;
3108105694Srwatson	struct mac mac;
3109105694Srwatson	char *buffer;
3110100979Srwatson	int error;
3111100979Srwatson
3112105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3113100979Srwatson	if (error)
3114100979Srwatson		return (error);
3115100979Srwatson
3116105694Srwatson	error = mac_check_structmac_consistent(&mac);
3117100979Srwatson	if (error)
3118100979Srwatson		return (error);
3119100979Srwatson
3120105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3121105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3122105694Srwatson	if (error) {
3123105694Srwatson		free(buffer, M_MACTEMP);
3124105694Srwatson		return (error);
3125105694Srwatson	}
3126105694Srwatson
3127105694Srwatson	mac_init_cred_label(&intlabel);
3128105694Srwatson	error = mac_internalize_cred_label(&intlabel, buffer);
3129105694Srwatson	free(buffer, M_MACTEMP);
3130105694Srwatson	if (error) {
3131105694Srwatson		mac_destroy_cred_label(&intlabel);
3132105694Srwatson		return (error);
3133105694Srwatson	}
3134105694Srwatson
3135100979Srwatson	newcred = crget();
3136100979Srwatson
3137100979Srwatson	p = td->td_proc;
3138100979Srwatson	PROC_LOCK(p);
3139100979Srwatson	oldcred = p->p_ucred;
3140100979Srwatson
3141100979Srwatson	error = mac_check_cred_relabel(oldcred, &intlabel);
3142100979Srwatson	if (error) {
3143100979Srwatson		PROC_UNLOCK(p);
3144100979Srwatson		crfree(newcred);
3145105694Srwatson		goto out;
3146100979Srwatson	}
3147100979Srwatson
3148100979Srwatson	setsugid(p);
3149100979Srwatson	crcopy(newcred, oldcred);
3150100979Srwatson	mac_relabel_cred(newcred, &intlabel);
3151102136Srwatson	p->p_ucred = newcred;
3152100979Srwatson
3153102136Srwatson	/*
3154102136Srwatson	 * Grab additional reference for use while revoking mmaps, prior
3155102136Srwatson	 * to releasing the proc lock and sharing the cred.
3156102136Srwatson	 */
3157102136Srwatson	crhold(newcred);
3158100979Srwatson	PROC_UNLOCK(p);
3159102136Srwatson
3160105694Srwatson	if (mac_enforce_vm) {
3161105694Srwatson		mtx_lock(&Giant);
3162105694Srwatson		mac_cred_mmapped_drop_perms(td, newcred);
3163105694Srwatson		mtx_unlock(&Giant);
3164105694Srwatson	}
3165102136Srwatson
3166102136Srwatson	crfree(newcred);	/* Free revocation reference. */
3167100979Srwatson	crfree(oldcred);
3168105694Srwatson
3169105694Srwatsonout:
3170105694Srwatson	mac_destroy_cred_label(&intlabel);
3171105694Srwatson	return (error);
3172100979Srwatson}
3173100979Srwatson
3174100979Srwatson/*
3175100979Srwatson * MPSAFE
3176100979Srwatson */
3177100979Srwatsonint
3178100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3179100979Srwatson{
3180105694Srwatson	char *elements, *buffer;
3181105694Srwatson	struct label intlabel;
3182100979Srwatson	struct file *fp;
3183105694Srwatson	struct mac mac;
3184100979Srwatson	struct vnode *vp;
3185100979Srwatson	struct pipe *pipe;
3186105694Srwatson	short label_type;
3187100979Srwatson	int error;
3188100979Srwatson
3189105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3190105694Srwatson	if (error)
3191105694Srwatson		return (error);
3192100979Srwatson
3193105694Srwatson	error = mac_check_structmac_consistent(&mac);
3194105694Srwatson	if (error)
3195105694Srwatson		return (error);
3196105694Srwatson
3197105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3198105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3199105694Srwatson	if (error) {
3200105694Srwatson		free(elements, M_MACTEMP);
3201105694Srwatson		return (error);
3202105694Srwatson	}
3203105694Srwatson
3204105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3205105694Srwatson	mtx_lock(&Giant);				/* VFS */
3206100979Srwatson	error = fget(td, SCARG(uap, fd), &fp);
3207100979Srwatson	if (error)
3208100979Srwatson		goto out;
3209100979Srwatson
3210105694Srwatson	label_type = fp->f_type;
3211100979Srwatson	switch (fp->f_type) {
3212100979Srwatson	case DTYPE_FIFO:
3213100979Srwatson	case DTYPE_VNODE:
3214100979Srwatson		vp = (struct vnode *)fp->f_data;
3215100979Srwatson
3216105694Srwatson		mac_init_vnode_label(&intlabel);
3217105694Srwatson
3218100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3219105988Srwatson		mac_copy_vnode_label(&vp->v_label, &intlabel);
3220100979Srwatson		VOP_UNLOCK(vp, 0, td);
3221105694Srwatson
3222100979Srwatson		break;
3223100979Srwatson	case DTYPE_PIPE:
3224100979Srwatson		pipe = (struct pipe *)fp->f_data;
3225105694Srwatson
3226105694Srwatson		mac_init_pipe_label(&intlabel);
3227105694Srwatson
3228105694Srwatson		PIPE_LOCK(pipe);
3229105694Srwatson		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3230105694Srwatson		PIPE_UNLOCK(pipe);
3231100979Srwatson		break;
3232100979Srwatson	default:
3233100979Srwatson		error = EINVAL;
3234105694Srwatson		fdrop(fp, td);
3235105694Srwatson		goto out;
3236100979Srwatson	}
3237105694Srwatson	fdrop(fp, td);
3238100979Srwatson
3239105694Srwatson	switch (label_type) {
3240105694Srwatson	case DTYPE_FIFO:
3241105694Srwatson	case DTYPE_VNODE:
3242105694Srwatson		if (error == 0)
3243105694Srwatson			error = mac_externalize_vnode_label(&intlabel,
3244105694Srwatson			    elements, buffer, mac.m_buflen, M_WAITOK);
3245105694Srwatson		mac_destroy_vnode_label(&intlabel);
3246105694Srwatson		break;
3247105694Srwatson	case DTYPE_PIPE:
3248105694Srwatson		error = mac_externalize_pipe_label(&intlabel, elements,
3249105694Srwatson		    buffer, mac.m_buflen, M_WAITOK);
3250105694Srwatson		mac_destroy_pipe_label(&intlabel);
3251105694Srwatson		break;
3252105694Srwatson	default:
3253105694Srwatson		panic("__mac_get_fd: corrupted label_type");
3254105694Srwatson	}
3255105694Srwatson
3256100979Srwatson	if (error == 0)
3257105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3258100979Srwatson
3259105694Srwatsonout:
3260105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3261105694Srwatson	free(buffer, M_MACTEMP);
3262105694Srwatson	free(elements, M_MACTEMP);
3263100979Srwatson
3264100979Srwatson	return (error);
3265100979Srwatson}
3266100979Srwatson
3267100979Srwatson/*
3268100979Srwatson * MPSAFE
3269100979Srwatson */
3270100979Srwatsonint
3271100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3272100979Srwatson{
3273105694Srwatson	char *elements, *buffer;
3274100979Srwatson	struct nameidata nd;
3275105694Srwatson	struct label intlabel;
3276105694Srwatson	struct mac mac;
3277100979Srwatson	int error;
3278100979Srwatson
3279105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3280105694Srwatson	if (error)
3281105694Srwatson		return (error);
3282105694Srwatson
3283105694Srwatson	error = mac_check_structmac_consistent(&mac);
3284105694Srwatson	if (error)
3285105694Srwatson		return (error);
3286105694Srwatson
3287105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3288105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3289105694Srwatson	if (error) {
3290105694Srwatson		free(elements, M_MACTEMP);
3291105694Srwatson		return (error);
3292105694Srwatson	}
3293105694Srwatson
3294105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3295105694Srwatson	mtx_lock(&Giant);				/* VFS */
3296105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3297105694Srwatson	    td);
3298100979Srwatson	error = namei(&nd);
3299100979Srwatson	if (error)
3300100979Srwatson		goto out;
3301100979Srwatson
3302105694Srwatson	mac_init_vnode_label(&intlabel);
3303105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3304105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3305105988Srwatson	    mac.m_buflen, M_WAITOK);
3306105694Srwatson
3307100979Srwatson	NDFREE(&nd, 0);
3308105694Srwatson	mac_destroy_vnode_label(&intlabel);
3309105694Srwatson
3310105694Srwatson	if (error == 0)
3311105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3312105694Srwatson
3313105694Srwatsonout:
3314105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3315105694Srwatson
3316105694Srwatson	free(buffer, M_MACTEMP);
3317105694Srwatson	free(elements, M_MACTEMP);
3318105694Srwatson
3319105694Srwatson	return (error);
3320105694Srwatson}
3321105694Srwatson
3322105694Srwatson/*
3323105694Srwatson * MPSAFE
3324105694Srwatson */
3325105694Srwatsonint
3326105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3327105694Srwatson{
3328105694Srwatson	char *elements, *buffer;
3329105694Srwatson	struct nameidata nd;
3330105694Srwatson	struct label intlabel;
3331105694Srwatson	struct mac mac;
3332105694Srwatson	int error;
3333105694Srwatson
3334105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3335100979Srwatson	if (error)
3336105694Srwatson		return (error);
3337105694Srwatson
3338105694Srwatson	error = mac_check_structmac_consistent(&mac);
3339105694Srwatson	if (error)
3340105694Srwatson		return (error);
3341105694Srwatson
3342105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3343105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3344105694Srwatson	if (error) {
3345105694Srwatson		free(elements, M_MACTEMP);
3346105694Srwatson		return (error);
3347105694Srwatson	}
3348105694Srwatson
3349105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3350105694Srwatson	mtx_lock(&Giant);				/* VFS */
3351105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3352105694Srwatson	    td);
3353105694Srwatson	error = namei(&nd);
3354105694Srwatson	if (error)
3355100979Srwatson		goto out;
3356100979Srwatson
3357105694Srwatson	mac_init_vnode_label(&intlabel);
3358105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3359105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3360105988Srwatson	    mac.m_buflen, M_WAITOK);
3361105694Srwatson	NDFREE(&nd, 0);
3362105694Srwatson	mac_destroy_vnode_label(&intlabel);
3363100979Srwatson
3364105694Srwatson	if (error == 0)
3365105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3366105694Srwatson
3367100979Srwatsonout:
3368105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3369105694Srwatson
3370105694Srwatson	free(buffer, M_MACTEMP);
3371105694Srwatson	free(elements, M_MACTEMP);
3372105694Srwatson
3373100979Srwatson	return (error);
3374100979Srwatson}
3375100979Srwatson
3376100979Srwatson/*
3377100979Srwatson * MPSAFE
3378100979Srwatson */
3379100979Srwatsonint
3380100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3381100979Srwatson{
3382105694Srwatson	struct label intlabel;
3383105694Srwatson	struct pipe *pipe;
3384100979Srwatson	struct file *fp;
3385100979Srwatson	struct mount *mp;
3386100979Srwatson	struct vnode *vp;
3387105694Srwatson	struct mac mac;
3388105694Srwatson	char *buffer;
3389100979Srwatson	int error;
3390100979Srwatson
3391105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3392100979Srwatson	if (error)
3393105694Srwatson		return (error);
3394100979Srwatson
3395105694Srwatson	error = mac_check_structmac_consistent(&mac);
3396100979Srwatson	if (error)
3397105694Srwatson		return (error);
3398100979Srwatson
3399105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3400105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3401105694Srwatson	if (error) {
3402105694Srwatson		free(buffer, M_MACTEMP);
3403105694Srwatson		return (error);
3404105694Srwatson	}
3405105694Srwatson
3406105694Srwatson	mtx_lock(&Giant);				/* VFS */
3407105694Srwatson
3408105694Srwatson	error = fget(td, SCARG(uap, fd), &fp);
3409100979Srwatson	if (error)
3410105694Srwatson		goto out;
3411100979Srwatson
3412100979Srwatson	switch (fp->f_type) {
3413100979Srwatson	case DTYPE_FIFO:
3414100979Srwatson	case DTYPE_VNODE:
3415105694Srwatson		mac_init_vnode_label(&intlabel);
3416105694Srwatson		error = mac_internalize_vnode_label(&intlabel, buffer);
3417105694Srwatson		if (error) {
3418105694Srwatson			mac_destroy_vnode_label(&intlabel);
3419105694Srwatson			break;
3420105694Srwatson		}
3421105694Srwatson
3422100979Srwatson		vp = (struct vnode *)fp->f_data;
3423100979Srwatson		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3424105694Srwatson		if (error != 0) {
3425105694Srwatson			mac_destroy_vnode_label(&intlabel);
3426100979Srwatson			break;
3427105694Srwatson		}
3428100979Srwatson
3429100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3430100979Srwatson		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3431100979Srwatson		VOP_UNLOCK(vp, 0, td);
3432100979Srwatson		vn_finished_write(mp);
3433105694Srwatson
3434105694Srwatson		mac_destroy_vnode_label(&intlabel);
3435100979Srwatson		break;
3436105694Srwatson
3437100979Srwatson	case DTYPE_PIPE:
3438105694Srwatson		mac_init_pipe_label(&intlabel);
3439105694Srwatson		error = mac_internalize_pipe_label(&intlabel, buffer);
3440105694Srwatson		if (error == 0) {
3441105694Srwatson			pipe = (struct pipe *)fp->f_data;
3442105694Srwatson			PIPE_LOCK(pipe);
3443105694Srwatson			error = mac_pipe_label_set(td->td_ucred, pipe,
3444105694Srwatson			    &intlabel);
3445105694Srwatson			PIPE_UNLOCK(pipe);
3446105694Srwatson		}
3447105694Srwatson
3448105694Srwatson		mac_destroy_pipe_label(&intlabel);
3449100979Srwatson		break;
3450105694Srwatson
3451100979Srwatson	default:
3452100979Srwatson		error = EINVAL;
3453100979Srwatson	}
3454100979Srwatson
3455100979Srwatson	fdrop(fp, td);
3456105694Srwatsonout:
3457105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3458105694Srwatson
3459105694Srwatson	free(buffer, M_MACTEMP);
3460105694Srwatson
3461100979Srwatson	return (error);
3462100979Srwatson}
3463100979Srwatson
3464100979Srwatson/*
3465100979Srwatson * MPSAFE
3466100979Srwatson */
3467100979Srwatsonint
3468100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3469100979Srwatson{
3470105694Srwatson	struct label intlabel;
3471100979Srwatson	struct nameidata nd;
3472100979Srwatson	struct mount *mp;
3473105694Srwatson	struct mac mac;
3474105694Srwatson	char *buffer;
3475100979Srwatson	int error;
3476100979Srwatson
3477105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3478100979Srwatson	if (error)
3479105694Srwatson		return (error);
3480100979Srwatson
3481105694Srwatson	error = mac_check_structmac_consistent(&mac);
3482100979Srwatson	if (error)
3483105694Srwatson		return (error);
3484100979Srwatson
3485105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3486105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3487105694Srwatson	if (error) {
3488105694Srwatson		free(buffer, M_MACTEMP);
3489105694Srwatson		return (error);
3490105694Srwatson	}
3491105694Srwatson
3492105694Srwatson	mac_init_vnode_label(&intlabel);
3493105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3494105694Srwatson	free(buffer, M_MACTEMP);
3495105694Srwatson	if (error) {
3496105694Srwatson		mac_destroy_vnode_label(&intlabel);
3497105694Srwatson		return (error);
3498105694Srwatson	}
3499105694Srwatson
3500105694Srwatson	mtx_lock(&Giant);				/* VFS */
3501105694Srwatson
3502105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3503105694Srwatson	    td);
3504100979Srwatson	error = namei(&nd);
3505105694Srwatson	if (error == 0) {
3506105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3507105694Srwatson		if (error == 0)
3508105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3509105694Srwatson			    td->td_ucred);
3510105694Srwatson		vn_finished_write(mp);
3511105694Srwatson	}
3512105694Srwatson
3513105694Srwatson	NDFREE(&nd, 0);
3514105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3515105694Srwatson	mac_destroy_vnode_label(&intlabel);
3516105694Srwatson
3517105694Srwatson	return (error);
3518105694Srwatson}
3519105694Srwatson
3520105694Srwatson/*
3521105694Srwatson * MPSAFE
3522105694Srwatson */
3523105694Srwatsonint
3524105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3525105694Srwatson{
3526105694Srwatson	struct label intlabel;
3527105694Srwatson	struct nameidata nd;
3528105694Srwatson	struct mount *mp;
3529105694Srwatson	struct mac mac;
3530105694Srwatson	char *buffer;
3531105694Srwatson	int error;
3532105694Srwatson
3533105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3534100979Srwatson	if (error)
3535105694Srwatson		return (error);
3536105694Srwatson
3537105694Srwatson	error = mac_check_structmac_consistent(&mac);
3538100979Srwatson	if (error)
3539105694Srwatson		return (error);
3540100979Srwatson
3541105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3542105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3543105694Srwatson	if (error) {
3544105694Srwatson		free(buffer, M_MACTEMP);
3545105694Srwatson		return (error);
3546105694Srwatson	}
3547105694Srwatson
3548105694Srwatson	mac_init_vnode_label(&intlabel);
3549105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3550105694Srwatson	free(buffer, M_MACTEMP);
3551105694Srwatson	if (error) {
3552105694Srwatson		mac_destroy_vnode_label(&intlabel);
3553105694Srwatson		return (error);
3554105694Srwatson	}
3555105694Srwatson
3556105694Srwatson	mtx_lock(&Giant);				/* VFS */
3557105694Srwatson
3558105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3559105694Srwatson	    td);
3560105694Srwatson	error = namei(&nd);
3561105694Srwatson	if (error == 0) {
3562105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3563105694Srwatson		if (error == 0)
3564105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3565105694Srwatson			    td->td_ucred);
3566105694Srwatson		vn_finished_write(mp);
3567105694Srwatson	}
3568105694Srwatson
3569100979Srwatson	NDFREE(&nd, 0);
3570105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3571105694Srwatson	mac_destroy_vnode_label(&intlabel);
3572105694Srwatson
3573100979Srwatson	return (error);
3574100979Srwatson}
3575100979Srwatson
3576105694Srwatson/*
3577105694Srwatson * MPSAFE
3578105694Srwatson */
3579102123Srwatsonint
3580102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3581102123Srwatson{
3582102123Srwatson	struct mac_policy_conf *mpc;
3583102123Srwatson	char target[MAC_MAX_POLICY_NAME];
3584102123Srwatson	int error;
3585102123Srwatson
3586102123Srwatson	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3587102123Srwatson	if (error)
3588102123Srwatson		return (error);
3589102123Srwatson
3590102123Srwatson	error = ENOSYS;
3591102123Srwatson	MAC_POLICY_LIST_BUSY();
3592102123Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3593102123Srwatson		if (strcmp(mpc->mpc_name, target) == 0 &&
3594102123Srwatson		    mpc->mpc_ops->mpo_syscall != NULL) {
3595102123Srwatson			error = mpc->mpc_ops->mpo_syscall(td,
3596102123Srwatson			    SCARG(uap, call), SCARG(uap, arg));
3597102123Srwatson			goto out;
3598102123Srwatson		}
3599102123Srwatson	}
3600102123Srwatson
3601102123Srwatsonout:
3602102123Srwatson	MAC_POLICY_LIST_UNBUSY();
3603102123Srwatson	return (error);
3604102123Srwatson}
3605102123Srwatson
3606100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3607100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3608100979Srwatson
3609100979Srwatson#else /* !MAC */
3610100979Srwatson
3611100979Srwatsonint
3612105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3613105694Srwatson{
3614105694Srwatson
3615105694Srwatson	return (ENOSYS);
3616105694Srwatson}
3617105694Srwatson
3618105694Srwatsonint
3619100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3620100979Srwatson{
3621100979Srwatson
3622100894Srwatson	return (ENOSYS);
3623100894Srwatson}
3624100894Srwatson
3625100894Srwatsonint
3626100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3627100894Srwatson{
3628100894Srwatson
3629100894Srwatson	return (ENOSYS);
3630100894Srwatson}
3631100894Srwatson
3632100894Srwatsonint
3633100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3634100894Srwatson{
3635100894Srwatson
3636100894Srwatson	return (ENOSYS);
3637100894Srwatson}
3638100894Srwatson
3639100894Srwatsonint
3640100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3641100894Srwatson{
3642100894Srwatson
3643100894Srwatson	return (ENOSYS);
3644100894Srwatson}
3645100894Srwatson
3646100894Srwatsonint
3647105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3648105694Srwatson{
3649105694Srwatson
3650105694Srwatson	return (ENOSYS);
3651105694Srwatson}
3652105694Srwatson
3653105694Srwatsonint
3654100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3655100894Srwatson{
3656100894Srwatson
3657100894Srwatson	return (ENOSYS);
3658100894Srwatson}
3659100894Srwatson
3660100894Srwatsonint
3661100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3662100894Srwatson{
3663100894Srwatson
3664100894Srwatson	return (ENOSYS);
3665100894Srwatson}
3666100979Srwatson
3667102123Srwatsonint
3668105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3669105694Srwatson{
3670105694Srwatson
3671105694Srwatson	return (ENOSYS);
3672105694Srwatson}
3673105694Srwatson
3674105694Srwatsonint
3675102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3676102123Srwatson{
3677102123Srwatson
3678102123Srwatson	return (ENOSYS);
3679102123Srwatson}
3680102123Srwatson
3681105694Srwatson#endif
3682