mac_cred.c revision 107271
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 107271 2002-11-26 17:11:57Z 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
1199100979Srwatsonmac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1200100979Srwatson{
1201100979Srwatson
1202100979Srwatson	MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1203100979Srwatson}
1204100979Srwatson
1205100979Srwatsonvoid
1206105988Srwatsonmac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1207105988Srwatson    struct vnode *vp)
1208100979Srwatson{
1209100979Srwatson
1210105988Srwatson	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1211105988Srwatson	    &de->de_label, vp, &vp->v_label);
1212100979Srwatson}
1213100979Srwatson
1214105988Srwatsonint
1215105988Srwatsonmac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1216100979Srwatson{
1217100979Srwatson	int error;
1218100979Srwatson
1219105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1220100979Srwatson
1221105988Srwatson	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1222105988Srwatson	    &vp->v_label);
1223100979Srwatson
1224100979Srwatson	return (error);
1225100979Srwatson}
1226100979Srwatson
1227100979Srwatsonvoid
1228105988Srwatsonmac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1229100979Srwatson{
1230100979Srwatson
1231105988Srwatson	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1232105988Srwatson	    &vp->v_label);
1233100979Srwatson}
1234100979Srwatson
1235100979Srwatsonint
1236105988Srwatsonmac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1237105988Srwatson    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1238100979Srwatson{
1239105988Srwatson	int error;
1240100979Srwatson
1241105988Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1242105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1243100979Srwatson
1244105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1245105988Srwatson	if (error == EOPNOTSUPP) {
1246105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1247105988Srwatson		if (ea_warn_once == 0) {
1248105988Srwatson			printf("Warning: transactions not supported "
1249105988Srwatson			    "in EA write.\n");
1250105988Srwatson			ea_warn_once = 1;
1251105988Srwatson		}
1252105988Srwatson	} else if (error)
1253100979Srwatson		return (error);
1254100979Srwatson
1255105988Srwatson	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1256105988Srwatson	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1257100979Srwatson
1258105988Srwatson	if (error) {
1259105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1260100979Srwatson		return (error);
1261100979Srwatson	}
1262100979Srwatson
1263105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1264100979Srwatson
1265105988Srwatson	if (error == EOPNOTSUPP)
1266105988Srwatson		error = 0;				/* XXX */
1267100979Srwatson
1268100979Srwatson	return (error);
1269100979Srwatson}
1270100979Srwatson
1271100979Srwatsonstatic int
1272105988Srwatsonmac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1273105988Srwatson    struct label *intlabel)
1274100979Srwatson{
1275100979Srwatson	int error;
1276100979Srwatson
1277105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1278100979Srwatson
1279105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1280105988Srwatson	if (error == EOPNOTSUPP) {
1281105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1282105988Srwatson		if (ea_warn_once == 0) {
1283105988Srwatson			printf("Warning: transactions not supported "
1284105988Srwatson			    "in EA write.\n");
1285105988Srwatson			ea_warn_once = 1;
1286105988Srwatson		}
1287105988Srwatson	} else if (error)
1288105988Srwatson		return (error);
1289100979Srwatson
1290105988Srwatson	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1291100979Srwatson
1292105988Srwatson	if (error) {
1293105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1294100979Srwatson		return (error);
1295100979Srwatson	}
1296100979Srwatson
1297105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1298100979Srwatson
1299105988Srwatson	if (error == EOPNOTSUPP)
1300105988Srwatson		error = 0;				/* XXX */
1301100979Srwatson
1302105988Srwatson	return (error);
1303100979Srwatson}
1304100979Srwatson
1305106468Srwatsonint
1306106468Srwatsonmac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1307106468Srwatson    struct label *execlabelstorage)
1308106468Srwatson{
1309106468Srwatson	struct mac mac;
1310106468Srwatson	char *buffer;
1311106468Srwatson	int error;
1312106468Srwatson
1313106468Srwatson	if (mac_p == NULL)
1314106468Srwatson		return (0);
1315106468Srwatson
1316106468Srwatson	error = copyin(mac_p, &mac, sizeof(mac));
1317106468Srwatson	if (error)
1318106468Srwatson		return (error);
1319106468Srwatson
1320106468Srwatson	error = mac_check_structmac_consistent(&mac);
1321106468Srwatson	if (error)
1322106468Srwatson		return (error);
1323106468Srwatson
1324106468Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1325106468Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1326106468Srwatson	if (error) {
1327106468Srwatson		free(buffer, M_MACTEMP);
1328106468Srwatson		return (error);
1329106468Srwatson	}
1330106468Srwatson
1331106468Srwatson	mac_init_cred_label(execlabelstorage);
1332106468Srwatson	error = mac_internalize_cred_label(execlabelstorage, buffer);
1333106468Srwatson	free(buffer, M_MACTEMP);
1334106468Srwatson	if (error) {
1335106468Srwatson		mac_destroy_cred_label(execlabelstorage);
1336106468Srwatson		return (error);
1337106468Srwatson	}
1338106468Srwatson	imgp->execlabel = execlabelstorage;
1339106468Srwatson	return (0);
1340106468Srwatson}
1341106468Srwatson
1342100979Srwatsonvoid
1343106468Srwatsonmac_execve_exit(struct image_params *imgp)
1344100979Srwatson{
1345106468Srwatson	if (imgp->execlabel != NULL)
1346106468Srwatson		mac_destroy_cred_label(imgp->execlabel);
1347106468Srwatson}
1348100979Srwatson
1349106468Srwatsonvoid
1350106468Srwatsonmac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1351106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1352106468Srwatson{
1353106468Srwatson
1354100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1355100979Srwatson
1356106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1357106460Srwatson		return;
1358106460Srwatson
1359106468Srwatson	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1360106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1361100979Srwatson}
1362100979Srwatson
1363100979Srwatsonint
1364106468Srwatsonmac_execve_will_transition(struct ucred *old, struct vnode *vp,
1365106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1366100979Srwatson{
1367105988Srwatson	int result;
1368100979Srwatson
1369106460Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1370106460Srwatson
1371106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1372106460Srwatson		return (0);
1373106460Srwatson
1374100979Srwatson	result = 0;
1375106468Srwatson	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1376106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1377100979Srwatson
1378100979Srwatson	return (result);
1379100979Srwatson}
1380100979Srwatson
1381100979Srwatsonint
1382106212Srwatsonmac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1383100979Srwatson{
1384100979Srwatson	int error;
1385100979Srwatson
1386100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1387100979Srwatson
1388100979Srwatson	if (!mac_enforce_fs)
1389100979Srwatson		return (0);
1390100979Srwatson
1391106212Srwatson	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1392100979Srwatson	return (error);
1393100979Srwatson}
1394100979Srwatson
1395100979Srwatsonint
1396100979Srwatsonmac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1397100979Srwatson{
1398100979Srwatson	int error;
1399100979Srwatson
1400100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1401100979Srwatson
1402100979Srwatson	if (!mac_enforce_fs)
1403100979Srwatson		return (0);
1404100979Srwatson
1405100979Srwatson	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1406100979Srwatson	return (error);
1407100979Srwatson}
1408100979Srwatson
1409100979Srwatsonint
1410100979Srwatsonmac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1411100979Srwatson{
1412100979Srwatson	int error;
1413100979Srwatson
1414100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1415100979Srwatson
1416100979Srwatson	if (!mac_enforce_fs)
1417100979Srwatson		return (0);
1418100979Srwatson
1419100979Srwatson	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1420100979Srwatson	return (error);
1421100979Srwatson}
1422100979Srwatson
1423100979Srwatsonint
1424100979Srwatsonmac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1425100979Srwatson    struct componentname *cnp, struct vattr *vap)
1426100979Srwatson{
1427100979Srwatson	int error;
1428100979Srwatson
1429100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1430100979Srwatson
1431100979Srwatson	if (!mac_enforce_fs)
1432100979Srwatson		return (0);
1433100979Srwatson
1434100979Srwatson	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1435100979Srwatson	return (error);
1436100979Srwatson}
1437100979Srwatson
1438100979Srwatsonint
1439100979Srwatsonmac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1440100979Srwatson    struct componentname *cnp)
1441100979Srwatson{
1442100979Srwatson	int error;
1443100979Srwatson
1444100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1445100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1446100979Srwatson
1447100979Srwatson	if (!mac_enforce_fs)
1448100979Srwatson		return (0);
1449100979Srwatson
1450100979Srwatson	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1451100979Srwatson	    &vp->v_label, cnp);
1452100979Srwatson	return (error);
1453100979Srwatson}
1454100979Srwatson
1455100979Srwatsonint
1456100979Srwatsonmac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1457100979Srwatson    acl_type_t type)
1458100979Srwatson{
1459100979Srwatson	int error;
1460100979Srwatson
1461100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1462100979Srwatson
1463100979Srwatson	if (!mac_enforce_fs)
1464100979Srwatson		return (0);
1465100979Srwatson
1466100979Srwatson	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1467100979Srwatson	return (error);
1468100979Srwatson}
1469100979Srwatson
1470100979Srwatsonint
1471106468Srwatsonmac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1472106468Srwatson    struct image_params *imgp)
1473100979Srwatson{
1474100979Srwatson	int error;
1475100979Srwatson
1476102102Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1477102102Srwatson
1478100979Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1479100979Srwatson		return (0);
1480100979Srwatson
1481106647Srwatson	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1482106647Srwatson	    imgp->execlabel);
1483100979Srwatson
1484100979Srwatson	return (error);
1485100979Srwatson}
1486100979Srwatson
1487100979Srwatsonint
1488100979Srwatsonmac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1489100979Srwatson{
1490100979Srwatson	int error;
1491100979Srwatson
1492100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1493100979Srwatson
1494100979Srwatson	if (!mac_enforce_fs)
1495100979Srwatson		return (0);
1496100979Srwatson
1497100979Srwatson	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1498100979Srwatson	return (error);
1499100979Srwatson}
1500100979Srwatson
1501100979Srwatsonint
1502100979Srwatsonmac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1503100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1504100979Srwatson{
1505100979Srwatson	int error;
1506100979Srwatson
1507100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1508100979Srwatson
1509100979Srwatson	if (!mac_enforce_fs)
1510100979Srwatson		return (0);
1511100979Srwatson
1512100979Srwatson	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1513100979Srwatson	    attrnamespace, name, uio);
1514100979Srwatson	return (error);
1515100979Srwatson}
1516100979Srwatson
1517100979Srwatsonint
1518104529Srwatsonmac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1519104529Srwatson    struct vnode *vp, struct componentname *cnp)
1520104529Srwatson{
1521104529Srwatson	int error;
1522104529Srwatson
1523104529Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1524104529Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1525104529Srwatson
1526104529Srwatson	if (!mac_enforce_fs)
1527104529Srwatson		return (0);
1528104529Srwatson
1529104529Srwatson	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1530104529Srwatson	    &vp->v_label, cnp);
1531104529Srwatson	return (error);
1532104529Srwatson}
1533104529Srwatson
1534104529Srwatsonint
1535100979Srwatsonmac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1536100979Srwatson    struct componentname *cnp)
1537100979Srwatson{
1538100979Srwatson	int error;
1539100979Srwatson
1540100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1541100979Srwatson
1542100979Srwatson	if (!mac_enforce_fs)
1543100979Srwatson		return (0);
1544100979Srwatson
1545100979Srwatson	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1546100979Srwatson	return (error);
1547100979Srwatson}
1548100979Srwatson
1549104546Srwatsonint
1550104546Srwatsonmac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1551100979Srwatson{
1552104546Srwatson	int error;
1553100979Srwatson
1554104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1555103514Srwatson
1556104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1557104546Srwatson		return (0);
1558104546Srwatson
1559104546Srwatson	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1560104546Srwatson	return (error);
1561100979Srwatson}
1562100979Srwatson
1563104546Srwatsonvoid
1564104546Srwatsonmac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1565104546Srwatson{
1566104546Srwatson	int result = *prot;
1567104546Srwatson
1568104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1569104546Srwatson
1570104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1571104546Srwatson		return;
1572104546Srwatson
1573104546Srwatson	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1574104546Srwatson	    &result);
1575104546Srwatson
1576104546Srwatson	*prot = result;
1577104546Srwatson}
1578104546Srwatson
1579100979Srwatsonint
1580104546Srwatsonmac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1581104546Srwatson{
1582104546Srwatson	int error;
1583104546Srwatson
1584104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1585104546Srwatson
1586104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1587104546Srwatson		return (0);
1588104546Srwatson
1589104546Srwatson	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1590104546Srwatson	return (error);
1591104546Srwatson}
1592104546Srwatson
1593104546Srwatsonint
1594106212Srwatsonmac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1595100979Srwatson{
1596100979Srwatson	int error;
1597100979Srwatson
1598102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1599102112Srwatson
1600100979Srwatson	if (!mac_enforce_fs)
1601100979Srwatson		return (0);
1602100979Srwatson
1603102112Srwatson	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1604102112Srwatson	return (error);
1605102112Srwatson}
1606102112Srwatson
1607102112Srwatsonint
1608102129Srwatsonmac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1609102129Srwatson    struct vnode *vp)
1610102112Srwatson{
1611102112Srwatson	int error;
1612102112Srwatson
1613102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1614102112Srwatson
1615102112Srwatson	if (!mac_enforce_fs)
1616102112Srwatson		return (0);
1617102112Srwatson
1618102129Srwatson	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1619102129Srwatson	    &vp->v_label);
1620100979Srwatson
1621100979Srwatson	return (error);
1622100979Srwatson}
1623100979Srwatson
1624100979Srwatsonint
1625102129Srwatsonmac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1626102129Srwatson    struct vnode *vp)
1627100979Srwatson{
1628100979Srwatson	int error;
1629100979Srwatson
1630102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1631100979Srwatson
1632100979Srwatson	if (!mac_enforce_fs)
1633100979Srwatson		return (0);
1634100979Srwatson
1635102129Srwatson	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1636102129Srwatson	    &vp->v_label);
1637102112Srwatson
1638100979Srwatson	return (error);
1639100979Srwatson}
1640100979Srwatson
1641100979Srwatsonint
1642100979Srwatsonmac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1643100979Srwatson{
1644100979Srwatson	int error;
1645100979Srwatson
1646100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1647100979Srwatson
1648100979Srwatson	if (!mac_enforce_fs)
1649100979Srwatson		return (0);
1650100979Srwatson
1651100979Srwatson	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1652100979Srwatson	return (error);
1653100979Srwatson}
1654100979Srwatson
1655100979Srwatsonint
1656100979Srwatsonmac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1657100979Srwatson{
1658100979Srwatson	int error;
1659100979Srwatson
1660100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1661100979Srwatson
1662100979Srwatson	if (!mac_enforce_fs)
1663100979Srwatson		return (0);
1664100979Srwatson
1665100979Srwatson	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1666100979Srwatson	return (error);
1667100979Srwatson}
1668100979Srwatson
1669100979Srwatsonstatic int
1670100979Srwatsonmac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1671100979Srwatson    struct label *newlabel)
1672100979Srwatson{
1673100979Srwatson	int error;
1674100979Srwatson
1675100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1676100979Srwatson
1677100979Srwatson	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1678100979Srwatson
1679100979Srwatson	return (error);
1680100979Srwatson}
1681100979Srwatson
1682100979Srwatsonint
1683100979Srwatsonmac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1684100979Srwatson    struct vnode *vp, struct componentname *cnp)
1685100979Srwatson{
1686100979Srwatson	int error;
1687100979Srwatson
1688100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1689100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1690100979Srwatson
1691100979Srwatson	if (!mac_enforce_fs)
1692100979Srwatson		return (0);
1693100979Srwatson
1694100979Srwatson	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1695100979Srwatson	    &vp->v_label, cnp);
1696100979Srwatson	return (error);
1697100979Srwatson}
1698100979Srwatson
1699100979Srwatsonint
1700100979Srwatsonmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1701100979Srwatson    struct vnode *vp, int samedir, struct componentname *cnp)
1702100979Srwatson{
1703100979Srwatson	int error;
1704100979Srwatson
1705100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1706100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1707100979Srwatson
1708100979Srwatson	if (!mac_enforce_fs)
1709100979Srwatson		return (0);
1710100979Srwatson
1711100979Srwatson	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1712100979Srwatson	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1713100979Srwatson	return (error);
1714100979Srwatson}
1715100979Srwatson
1716100979Srwatsonint
1717100979Srwatsonmac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1718100979Srwatson{
1719100979Srwatson	int error;
1720100979Srwatson
1721100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1722100979Srwatson
1723100979Srwatson	if (!mac_enforce_fs)
1724100979Srwatson		return (0);
1725100979Srwatson
1726100979Srwatson	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1727100979Srwatson	return (error);
1728100979Srwatson}
1729100979Srwatson
1730100979Srwatsonint
1731100979Srwatsonmac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1732100979Srwatson    struct acl *acl)
1733100979Srwatson{
1734100979Srwatson	int error;
1735100979Srwatson
1736100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1737100979Srwatson
1738100979Srwatson	if (!mac_enforce_fs)
1739100979Srwatson		return (0);
1740100979Srwatson
1741100979Srwatson	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1742100979Srwatson	return (error);
1743100979Srwatson}
1744100979Srwatson
1745100979Srwatsonint
1746100979Srwatsonmac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1747100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1748100979Srwatson{
1749100979Srwatson	int error;
1750100979Srwatson
1751100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1752100979Srwatson
1753100979Srwatson	if (!mac_enforce_fs)
1754100979Srwatson		return (0);
1755100979Srwatson
1756100979Srwatson	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1757100979Srwatson	    attrnamespace, name, uio);
1758100979Srwatson	return (error);
1759100979Srwatson}
1760100979Srwatson
1761100979Srwatsonint
1762100979Srwatsonmac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1763100979Srwatson{
1764100979Srwatson	int error;
1765100979Srwatson
1766100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1767100979Srwatson
1768100979Srwatson	if (!mac_enforce_fs)
1769100979Srwatson		return (0);
1770100979Srwatson
1771100979Srwatson	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1772100979Srwatson	return (error);
1773100979Srwatson}
1774100979Srwatson
1775100979Srwatsonint
1776100979Srwatsonmac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1777100979Srwatson{
1778100979Srwatson	int error;
1779100979Srwatson
1780100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1781100979Srwatson
1782100979Srwatson	if (!mac_enforce_fs)
1783100979Srwatson		return (0);
1784100979Srwatson
1785100979Srwatson	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1786100979Srwatson	return (error);
1787100979Srwatson}
1788100979Srwatson
1789100979Srwatsonint
1790100979Srwatsonmac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1791100979Srwatson    gid_t gid)
1792100979Srwatson{
1793100979Srwatson	int error;
1794100979Srwatson
1795100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1796100979Srwatson
1797100979Srwatson	if (!mac_enforce_fs)
1798100979Srwatson		return (0);
1799100979Srwatson
1800100979Srwatson	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1801100979Srwatson	return (error);
1802100979Srwatson}
1803100979Srwatson
1804100979Srwatsonint
1805100979Srwatsonmac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1806100979Srwatson    struct timespec atime, struct timespec mtime)
1807100979Srwatson{
1808100979Srwatson	int error;
1809100979Srwatson
1810100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1811100979Srwatson
1812100979Srwatson	if (!mac_enforce_fs)
1813100979Srwatson		return (0);
1814100979Srwatson
1815100979Srwatson	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1816100979Srwatson	    mtime);
1817100979Srwatson	return (error);
1818100979Srwatson}
1819100979Srwatson
1820100979Srwatsonint
1821102129Srwatsonmac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1822102129Srwatson    struct vnode *vp)
1823100979Srwatson{
1824100979Srwatson	int error;
1825100979Srwatson
1826100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1827100979Srwatson
1828100979Srwatson	if (!mac_enforce_fs)
1829100979Srwatson		return (0);
1830100979Srwatson
1831102129Srwatson	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1832102129Srwatson	    &vp->v_label);
1833100979Srwatson	return (error);
1834100979Srwatson}
1835100979Srwatson
1836102112Srwatsonint
1837102129Srwatsonmac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1838102129Srwatson    struct vnode *vp)
1839102112Srwatson{
1840102112Srwatson	int error;
1841102112Srwatson
1842102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1843102112Srwatson
1844102112Srwatson	if (!mac_enforce_fs)
1845102112Srwatson		return (0);
1846102112Srwatson
1847102129Srwatson	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1848102129Srwatson	    &vp->v_label);
1849102112Srwatson
1850102112Srwatson	return (error);
1851102112Srwatson}
1852102112Srwatson
1853100979Srwatson/*
1854100979Srwatson * When relabeling a process, call out to the policies for the maximum
1855100979Srwatson * permission allowed for each object type we know about in its
1856100979Srwatson * memory space, and revoke access (in the least surprising ways we
1857100979Srwatson * know) when necessary.  The process lock is not held here.
1858100979Srwatson */
1859107271Srwatsonvoid
1860100979Srwatsonmac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
1861100979Srwatson{
1862100979Srwatson
1863100979Srwatson	/* XXX freeze all other threads */
1864100979Srwatson	mac_cred_mmapped_drop_perms_recurse(td, cred,
1865100979Srwatson	    &td->td_proc->p_vmspace->vm_map);
1866100979Srwatson	/* XXX allow other threads to continue */
1867100979Srwatson}
1868100979Srwatson
1869100979Srwatsonstatic __inline const char *
1870100979Srwatsonprot2str(vm_prot_t prot)
1871100979Srwatson{
1872100979Srwatson
1873100979Srwatson	switch (prot & VM_PROT_ALL) {
1874100979Srwatson	case VM_PROT_READ:
1875100979Srwatson		return ("r--");
1876100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE:
1877100979Srwatson		return ("rw-");
1878100979Srwatson	case VM_PROT_READ | VM_PROT_EXECUTE:
1879100979Srwatson		return ("r-x");
1880100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
1881100979Srwatson		return ("rwx");
1882100979Srwatson	case VM_PROT_WRITE:
1883100979Srwatson		return ("-w-");
1884100979Srwatson	case VM_PROT_EXECUTE:
1885100979Srwatson		return ("--x");
1886100979Srwatson	case VM_PROT_WRITE | VM_PROT_EXECUTE:
1887100979Srwatson		return ("-wx");
1888100979Srwatson	default:
1889100979Srwatson		return ("---");
1890100979Srwatson	}
1891100979Srwatson}
1892100979Srwatson
1893100979Srwatsonstatic void
1894100979Srwatsonmac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
1895100979Srwatson    struct vm_map *map)
1896100979Srwatson{
1897100979Srwatson	struct vm_map_entry *vme;
1898104546Srwatson	int result;
1899104546Srwatson	vm_prot_t revokeperms;
1900100979Srwatson	vm_object_t object;
1901100979Srwatson	vm_ooffset_t offset;
1902100979Srwatson	struct vnode *vp;
1903100979Srwatson
1904103136Srwatson	if (!mac_mmap_revocation)
1905103136Srwatson		return;
1906103136Srwatson
1907100979Srwatson	vm_map_lock_read(map);
1908100979Srwatson	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
1909100979Srwatson		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
1910100979Srwatson			mac_cred_mmapped_drop_perms_recurse(td, cred,
1911100979Srwatson			    vme->object.sub_map);
1912100979Srwatson			continue;
1913100979Srwatson		}
1914100979Srwatson		/*
1915100979Srwatson		 * Skip over entries that obviously are not shared.
1916100979Srwatson		 */
1917100979Srwatson		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
1918100979Srwatson		    !vme->max_protection)
1919100979Srwatson			continue;
1920100979Srwatson		/*
1921100979Srwatson		 * Drill down to the deepest backing object.
1922100979Srwatson		 */
1923100979Srwatson		offset = vme->offset;
1924100979Srwatson		object = vme->object.vm_object;
1925100979Srwatson		if (object == NULL)
1926100979Srwatson			continue;
1927100979Srwatson		while (object->backing_object != NULL) {
1928100979Srwatson			object = object->backing_object;
1929100979Srwatson			offset += object->backing_object_offset;
1930100979Srwatson		}
1931100979Srwatson		/*
1932100979Srwatson		 * At the moment, vm_maps and objects aren't considered
1933100979Srwatson		 * by the MAC system, so only things with backing by a
1934100979Srwatson		 * normal object (read: vnodes) are checked.
1935100979Srwatson		 */
1936100979Srwatson		if (object->type != OBJT_VNODE)
1937100979Srwatson			continue;
1938100979Srwatson		vp = (struct vnode *)object->handle;
1939100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1940104546Srwatson		result = vme->max_protection;
1941104546Srwatson		mac_check_vnode_mmap_downgrade(cred, vp, &result);
1942100979Srwatson		VOP_UNLOCK(vp, 0, td);
1943100979Srwatson		/*
1944100979Srwatson		 * Find out what maximum protection we may be allowing
1945100979Srwatson		 * now but a policy needs to get removed.
1946100979Srwatson		 */
1947100979Srwatson		revokeperms = vme->max_protection & ~result;
1948100979Srwatson		if (!revokeperms)
1949100979Srwatson			continue;
1950102949Sbde		printf("pid %ld: revoking %s perms from %#lx:%ld "
1951102949Sbde		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
1952102949Sbde		    prot2str(revokeperms), (u_long)vme->start,
1953102949Sbde		    (long)(vme->end - vme->start),
1954100979Srwatson		    prot2str(vme->max_protection), prot2str(vme->protection));
1955100979Srwatson		vm_map_lock_upgrade(map);
1956100979Srwatson		/*
1957100979Srwatson		 * This is the really simple case: if a map has more
1958100979Srwatson		 * max_protection than is allowed, but it's not being
1959100979Srwatson		 * actually used (that is, the current protection is
1960100979Srwatson		 * still allowed), we can just wipe it out and do
1961100979Srwatson		 * nothing more.
1962100979Srwatson		 */
1963100979Srwatson		if ((vme->protection & revokeperms) == 0) {
1964100979Srwatson			vme->max_protection -= revokeperms;
1965100979Srwatson		} else {
1966100979Srwatson			if (revokeperms & VM_PROT_WRITE) {
1967100979Srwatson				/*
1968100979Srwatson				 * In the more complicated case, flush out all
1969100979Srwatson				 * pending changes to the object then turn it
1970100979Srwatson				 * copy-on-write.
1971100979Srwatson				 */
1972100979Srwatson				vm_object_reference(object);
1973100979Srwatson				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
1974100979Srwatson				vm_object_page_clean(object,
1975100979Srwatson				    OFF_TO_IDX(offset),
1976100979Srwatson				    OFF_TO_IDX(offset + vme->end - vme->start +
1977100979Srwatson					PAGE_MASK),
1978100979Srwatson				    OBJPC_SYNC);
1979100979Srwatson				VOP_UNLOCK(vp, 0, td);
1980100979Srwatson				vm_object_deallocate(object);
1981100979Srwatson				/*
1982100979Srwatson				 * Why bother if there's no read permissions
1983100979Srwatson				 * anymore?  For the rest, we need to leave
1984100979Srwatson				 * the write permissions on for COW, or
1985100979Srwatson				 * remove them entirely if configured to.
1986100979Srwatson				 */
1987100979Srwatson				if (!mac_mmap_revocation_via_cow) {
1988100979Srwatson					vme->max_protection &= ~VM_PROT_WRITE;
1989100979Srwatson					vme->protection &= ~VM_PROT_WRITE;
1990100979Srwatson				} if ((revokeperms & VM_PROT_READ) == 0)
1991100979Srwatson					vme->eflags |= MAP_ENTRY_COW |
1992100979Srwatson					    MAP_ENTRY_NEEDS_COPY;
1993100979Srwatson			}
1994100979Srwatson			if (revokeperms & VM_PROT_EXECUTE) {
1995100979Srwatson				vme->max_protection &= ~VM_PROT_EXECUTE;
1996100979Srwatson				vme->protection &= ~VM_PROT_EXECUTE;
1997100979Srwatson			}
1998100979Srwatson			if (revokeperms & VM_PROT_READ) {
1999100979Srwatson				vme->max_protection = 0;
2000100979Srwatson				vme->protection = 0;
2001100979Srwatson			}
2002100979Srwatson			pmap_protect(map->pmap, vme->start, vme->end,
2003100979Srwatson			    vme->protection & ~revokeperms);
2004100979Srwatson			vm_map_simplify_entry(map, vme);
2005100979Srwatson		}
2006100979Srwatson		vm_map_lock_downgrade(map);
2007100979Srwatson	}
2008100979Srwatson	vm_map_unlock_read(map);
2009100979Srwatson}
2010100979Srwatson
2011100979Srwatson/*
2012100979Srwatson * When the subject's label changes, it may require revocation of privilege
2013100979Srwatson * to mapped objects.  This can't be done on-the-fly later with a unified
2014100979Srwatson * buffer cache.
2015100979Srwatson */
2016100979Srwatsonstatic void
2017100979Srwatsonmac_relabel_cred(struct ucred *cred, struct label *newlabel)
2018100979Srwatson{
2019100979Srwatson
2020100979Srwatson	MAC_PERFORM(relabel_cred, cred, newlabel);
2021100979Srwatson}
2022100979Srwatson
2023100979Srwatsonvoid
2024100979Srwatsonmac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2025100979Srwatson{
2026100979Srwatson
2027100979Srwatson	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2028100979Srwatson}
2029100979Srwatson
2030100979Srwatsonvoid
2031100979Srwatsonmac_create_ifnet(struct ifnet *ifnet)
2032100979Srwatson{
2033100979Srwatson
2034100979Srwatson	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2035100979Srwatson}
2036100979Srwatson
2037100979Srwatsonvoid
2038100979Srwatsonmac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2039100979Srwatson{
2040100979Srwatson
2041100979Srwatson	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2042100979Srwatson}
2043100979Srwatson
2044100979Srwatsonvoid
2045100979Srwatsonmac_create_socket(struct ucred *cred, struct socket *socket)
2046100979Srwatson{
2047100979Srwatson
2048100979Srwatson	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2049100979Srwatson}
2050100979Srwatson
2051100979Srwatsonvoid
2052100979Srwatsonmac_create_pipe(struct ucred *cred, struct pipe *pipe)
2053100979Srwatson{
2054100979Srwatson
2055100979Srwatson	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2056100979Srwatson}
2057100979Srwatson
2058100979Srwatsonvoid
2059100979Srwatsonmac_create_socket_from_socket(struct socket *oldsocket,
2060100979Srwatson    struct socket *newsocket)
2061100979Srwatson{
2062100979Srwatson
2063100979Srwatson	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2064100979Srwatson	    newsocket, &newsocket->so_label);
2065100979Srwatson}
2066100979Srwatson
2067100979Srwatsonstatic void
2068100979Srwatsonmac_relabel_socket(struct ucred *cred, struct socket *socket,
2069100979Srwatson    struct label *newlabel)
2070100979Srwatson{
2071100979Srwatson
2072100979Srwatson	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2073100979Srwatson}
2074100979Srwatson
2075100979Srwatsonstatic void
2076100979Srwatsonmac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2077100979Srwatson{
2078100979Srwatson
2079100979Srwatson	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2080100979Srwatson}
2081100979Srwatson
2082100979Srwatsonvoid
2083100979Srwatsonmac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2084100979Srwatson{
2085100979Srwatson
2086100979Srwatson	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2087100979Srwatson	    socket, &socket->so_peerlabel);
2088100979Srwatson}
2089100979Srwatson
2090100979Srwatsonvoid
2091100979Srwatsonmac_set_socket_peer_from_socket(struct socket *oldsocket,
2092100979Srwatson    struct socket *newsocket)
2093100979Srwatson{
2094100979Srwatson
2095100979Srwatson	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2096100979Srwatson	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2097100979Srwatson}
2098100979Srwatson
2099100979Srwatsonvoid
2100100979Srwatsonmac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2101100979Srwatson{
2102100979Srwatson
2103100979Srwatson	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2104100979Srwatson	    datagram, &datagram->m_pkthdr.label);
2105100979Srwatson}
2106100979Srwatson
2107100979Srwatsonvoid
2108100979Srwatsonmac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2109100979Srwatson{
2110100979Srwatson
2111100979Srwatson	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2112100979Srwatson	    fragment, &fragment->m_pkthdr.label);
2113100979Srwatson}
2114100979Srwatson
2115100979Srwatsonvoid
2116100979Srwatsonmac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2117100979Srwatson{
2118100979Srwatson
2119100979Srwatson	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2120100979Srwatson	    &ipq->ipq_label);
2121100979Srwatson}
2122100979Srwatson
2123100979Srwatsonvoid
2124100979Srwatsonmac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2125100979Srwatson{
2126100979Srwatson
2127100979Srwatson	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2128100979Srwatson	    newmbuf, &newmbuf->m_pkthdr.label);
2129100979Srwatson}
2130100979Srwatson
2131100979Srwatsonvoid
2132100979Srwatsonmac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2133100979Srwatson{
2134100979Srwatson
2135100979Srwatson	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2136100979Srwatson	    &mbuf->m_pkthdr.label);
2137100979Srwatson}
2138100979Srwatson
2139100979Srwatsonvoid
2140100979Srwatsonmac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2141100979Srwatson{
2142100979Srwatson
2143100979Srwatson	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2144100979Srwatson	    &mbuf->m_pkthdr.label);
2145100979Srwatson}
2146100979Srwatson
2147100979Srwatsonvoid
2148100979Srwatsonmac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2149100979Srwatson{
2150100979Srwatson
2151100979Srwatson	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2152100979Srwatson	    &mbuf->m_pkthdr.label);
2153100979Srwatson}
2154100979Srwatson
2155100979Srwatsonvoid
2156100979Srwatsonmac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2157100979Srwatson    struct mbuf *newmbuf)
2158100979Srwatson{
2159100979Srwatson
2160100979Srwatson	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2161100979Srwatson	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2162100979Srwatson	    &newmbuf->m_pkthdr.label);
2163100979Srwatson}
2164100979Srwatson
2165100979Srwatsonvoid
2166100979Srwatsonmac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2167100979Srwatson{
2168100979Srwatson
2169100979Srwatson	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2170100979Srwatson	    newmbuf, &newmbuf->m_pkthdr.label);
2171100979Srwatson}
2172100979Srwatson
2173100979Srwatsonint
2174100979Srwatsonmac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2175100979Srwatson{
2176100979Srwatson	int result;
2177100979Srwatson
2178100979Srwatson	result = 1;
2179100979Srwatson	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2180100979Srwatson	    ipq, &ipq->ipq_label);
2181100979Srwatson
2182100979Srwatson	return (result);
2183100979Srwatson}
2184100979Srwatson
2185100979Srwatsonvoid
2186100979Srwatsonmac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2187100979Srwatson{
2188100979Srwatson
2189100979Srwatson	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2190100979Srwatson	    &ipq->ipq_label);
2191100979Srwatson}
2192100979Srwatson
2193100979Srwatsonvoid
2194100979Srwatsonmac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2195100979Srwatson{
2196100979Srwatson
2197100979Srwatson	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2198100979Srwatson	    &mbuf->m_pkthdr.label);
2199100979Srwatson}
2200100979Srwatson
2201100979Srwatsonvoid
2202100979Srwatsonmac_create_mount(struct ucred *cred, struct mount *mp)
2203100979Srwatson{
2204100979Srwatson
2205100979Srwatson	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2206100979Srwatson	    &mp->mnt_fslabel);
2207100979Srwatson}
2208100979Srwatson
2209100979Srwatsonvoid
2210100979Srwatsonmac_create_root_mount(struct ucred *cred, struct mount *mp)
2211100979Srwatson{
2212100979Srwatson
2213100979Srwatson	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2214100979Srwatson	    &mp->mnt_fslabel);
2215100979Srwatson}
2216100979Srwatson
2217100979Srwatsonint
2218100979Srwatsonmac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2219100979Srwatson{
2220100979Srwatson	int error;
2221100979Srwatson
2222100979Srwatson	if (!mac_enforce_network)
2223100979Srwatson		return (0);
2224100979Srwatson
2225100979Srwatson	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2226100979Srwatson	    &ifnet->if_label);
2227100979Srwatson
2228100979Srwatson	return (error);
2229100979Srwatson}
2230100979Srwatson
2231100979Srwatsonstatic int
2232100979Srwatsonmac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2233100979Srwatson{
2234100979Srwatson	int error;
2235100979Srwatson
2236100979Srwatson	MAC_CHECK(check_cred_relabel, cred, newlabel);
2237100979Srwatson
2238100979Srwatson	return (error);
2239100979Srwatson}
2240100979Srwatson
2241100979Srwatsonint
2242100979Srwatsonmac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2243100979Srwatson{
2244100979Srwatson	int error;
2245100979Srwatson
2246100979Srwatson	if (!mac_enforce_process)
2247100979Srwatson		return (0);
2248100979Srwatson
2249100979Srwatson	MAC_CHECK(check_cred_visible, u1, u2);
2250100979Srwatson
2251100979Srwatson	return (error);
2252100979Srwatson}
2253100979Srwatson
2254100979Srwatsonint
2255100979Srwatsonmac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2256100979Srwatson{
2257100979Srwatson	int error;
2258100979Srwatson
2259100979Srwatson	if (!mac_enforce_network)
2260100979Srwatson		return (0);
2261100979Srwatson
2262100979Srwatson	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2263100979Srwatson	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2264105598Sbrooks		if_printf(ifnet, "not initialized\n");
2265100979Srwatson
2266100979Srwatson	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2267100979Srwatson	    &mbuf->m_pkthdr.label);
2268100979Srwatson
2269100979Srwatson	return (error);
2270100979Srwatson}
2271100979Srwatson
2272100979Srwatsonint
2273106308Srwatsonmac_check_kenv_dump(struct ucred *cred)
2274106308Srwatson{
2275106308Srwatson	int error;
2276106308Srwatson
2277106308Srwatson	if (!mac_enforce_system)
2278106308Srwatson		return (0);
2279106308Srwatson
2280106308Srwatson	MAC_CHECK(check_kenv_dump, cred);
2281106308Srwatson
2282106308Srwatson	return (error);
2283106308Srwatson}
2284106308Srwatson
2285106308Srwatsonint
2286106308Srwatsonmac_check_kenv_get(struct ucred *cred, char *name)
2287106308Srwatson{
2288106308Srwatson	int error;
2289106308Srwatson
2290106308Srwatson	if (!mac_enforce_system)
2291106308Srwatson		return (0);
2292106308Srwatson
2293106308Srwatson	MAC_CHECK(check_kenv_get, cred, name);
2294106308Srwatson
2295106308Srwatson	return (error);
2296106308Srwatson}
2297106308Srwatson
2298106308Srwatsonint
2299106308Srwatsonmac_check_kenv_set(struct ucred *cred, char *name, char *value)
2300106308Srwatson{
2301106308Srwatson	int error;
2302106308Srwatson
2303106308Srwatson	if (!mac_enforce_system)
2304106308Srwatson		return (0);
2305106308Srwatson
2306106308Srwatson	MAC_CHECK(check_kenv_set, cred, name, value);
2307106308Srwatson
2308106308Srwatson	return (error);
2309106308Srwatson}
2310106308Srwatson
2311106308Srwatsonint
2312106308Srwatsonmac_check_kenv_unset(struct ucred *cred, char *name)
2313106308Srwatson{
2314106308Srwatson	int error;
2315106308Srwatson
2316106308Srwatson	if (!mac_enforce_system)
2317106308Srwatson		return (0);
2318106308Srwatson
2319106308Srwatson	MAC_CHECK(check_kenv_unset, cred, name);
2320106308Srwatson
2321106308Srwatson	return (error);
2322106308Srwatson}
2323106308Srwatson
2324106308Srwatsonint
2325107089Srwatsonmac_check_kld_load(struct ucred *cred, struct vnode *vp)
2326107089Srwatson{
2327107089Srwatson	int error;
2328107089Srwatson
2329107089Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2330107089Srwatson
2331107089Srwatson	if (!mac_enforce_kld)
2332107089Srwatson		return (0);
2333107089Srwatson
2334107089Srwatson	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2335107089Srwatson
2336107089Srwatson	return (error);
2337107089Srwatson}
2338107089Srwatson
2339107089Srwatsonint
2340107089Srwatsonmac_check_kld_stat(struct ucred *cred)
2341107089Srwatson{
2342107089Srwatson	int error;
2343107089Srwatson
2344107089Srwatson	if (!mac_enforce_kld)
2345107089Srwatson		return (0);
2346107089Srwatson
2347107089Srwatson	MAC_CHECK(check_kld_stat, cred);
2348107089Srwatson
2349107089Srwatson	return (error);
2350107089Srwatson}
2351107089Srwatson
2352107089Srwatsonint
2353107089Srwatsonmac_check_kld_unload(struct ucred *cred)
2354107089Srwatson{
2355107089Srwatson	int error;
2356107089Srwatson
2357107089Srwatson	if (!mac_enforce_kld)
2358107089Srwatson		return (0);
2359107089Srwatson
2360107089Srwatson	MAC_CHECK(check_kld_unload, cred);
2361107089Srwatson
2362107089Srwatson	return (error);
2363107089Srwatson}
2364107089Srwatson
2365107089Srwatsonint
2366100979Srwatsonmac_check_mount_stat(struct ucred *cred, struct mount *mount)
2367100979Srwatson{
2368100979Srwatson	int error;
2369100979Srwatson
2370100979Srwatson	if (!mac_enforce_fs)
2371100979Srwatson		return (0);
2372100979Srwatson
2373100979Srwatson	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2374100979Srwatson
2375100979Srwatson	return (error);
2376100979Srwatson}
2377100979Srwatson
2378100979Srwatsonint
2379100979Srwatsonmac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2380100979Srwatson    void *data)
2381100979Srwatson{
2382100979Srwatson	int error;
2383100979Srwatson
2384104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2385104269Srwatson
2386104269Srwatson	if (!mac_enforce_pipe)
2387104269Srwatson		return (0);
2388104269Srwatson
2389100979Srwatson	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2390100979Srwatson
2391100979Srwatson	return (error);
2392100979Srwatson}
2393100979Srwatson
2394100979Srwatsonint
2395102115Srwatsonmac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2396100979Srwatson{
2397100979Srwatson	int error;
2398100979Srwatson
2399104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2400104269Srwatson
2401104269Srwatson	if (!mac_enforce_pipe)
2402104269Srwatson		return (0);
2403104269Srwatson
2404102115Srwatson	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2405100979Srwatson
2406100979Srwatson	return (error);
2407100979Srwatson}
2408100979Srwatson
2409102115Srwatsonint
2410102115Srwatsonmac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2411102115Srwatson{
2412102115Srwatson	int error;
2413102115Srwatson
2414104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2415104269Srwatson
2416104269Srwatson	if (!mac_enforce_pipe)
2417104269Srwatson		return (0);
2418104269Srwatson
2419102115Srwatson	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2420102115Srwatson
2421102115Srwatson	return (error);
2422102115Srwatson}
2423102115Srwatson
2424100979Srwatsonstatic int
2425100979Srwatsonmac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2426100979Srwatson    struct label *newlabel)
2427100979Srwatson{
2428100979Srwatson	int error;
2429100979Srwatson
2430104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2431104269Srwatson
2432104269Srwatson	if (!mac_enforce_pipe)
2433104269Srwatson		return (0);
2434104269Srwatson
2435100979Srwatson	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2436100979Srwatson
2437100979Srwatson	return (error);
2438100979Srwatson}
2439100979Srwatson
2440100979Srwatsonint
2441102115Srwatsonmac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2442102115Srwatson{
2443102115Srwatson	int error;
2444102115Srwatson
2445104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2446104269Srwatson
2447104269Srwatson	if (!mac_enforce_pipe)
2448104269Srwatson		return (0);
2449104269Srwatson
2450102115Srwatson	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2451102115Srwatson
2452102115Srwatson	return (error);
2453102115Srwatson}
2454102115Srwatson
2455102115Srwatsonint
2456102115Srwatsonmac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2457102115Srwatson{
2458102115Srwatson	int error;
2459102115Srwatson
2460104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2461104269Srwatson
2462104269Srwatson	if (!mac_enforce_pipe)
2463104269Srwatson		return (0);
2464104269Srwatson
2465102115Srwatson	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2466102115Srwatson
2467102115Srwatson	return (error);
2468102115Srwatson}
2469102115Srwatson
2470102115Srwatsonint
2471100979Srwatsonmac_check_proc_debug(struct ucred *cred, struct proc *proc)
2472100979Srwatson{
2473100979Srwatson	int error;
2474100979Srwatson
2475102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2476102103Srwatson
2477100979Srwatson	if (!mac_enforce_process)
2478100979Srwatson		return (0);
2479100979Srwatson
2480100979Srwatson	MAC_CHECK(check_proc_debug, cred, proc);
2481100979Srwatson
2482100979Srwatson	return (error);
2483100979Srwatson}
2484100979Srwatson
2485100979Srwatsonint
2486100979Srwatsonmac_check_proc_sched(struct ucred *cred, struct proc *proc)
2487100979Srwatson{
2488100979Srwatson	int error;
2489100979Srwatson
2490102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2491102103Srwatson
2492100979Srwatson	if (!mac_enforce_process)
2493100979Srwatson		return (0);
2494100979Srwatson
2495100979Srwatson	MAC_CHECK(check_proc_sched, cred, proc);
2496100979Srwatson
2497100979Srwatson	return (error);
2498100979Srwatson}
2499100979Srwatson
2500100979Srwatsonint
2501100979Srwatsonmac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2502100979Srwatson{
2503100979Srwatson	int error;
2504100979Srwatson
2505102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2506102103Srwatson
2507100979Srwatson	if (!mac_enforce_process)
2508100979Srwatson		return (0);
2509100979Srwatson
2510100979Srwatson	MAC_CHECK(check_proc_signal, cred, proc, signum);
2511100979Srwatson
2512100979Srwatson	return (error);
2513100979Srwatson}
2514100979Srwatson
2515100979Srwatsonint
2516100979Srwatsonmac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2517100979Srwatson    struct sockaddr *sockaddr)
2518100979Srwatson{
2519100979Srwatson	int error;
2520100979Srwatson
2521100979Srwatson	if (!mac_enforce_socket)
2522100979Srwatson		return (0);
2523100979Srwatson
2524100979Srwatson	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2525100979Srwatson	    sockaddr);
2526100979Srwatson
2527100979Srwatson	return (error);
2528100979Srwatson}
2529100979Srwatson
2530100979Srwatsonint
2531100979Srwatsonmac_check_socket_connect(struct ucred *cred, struct socket *socket,
2532100979Srwatson    struct sockaddr *sockaddr)
2533100979Srwatson{
2534100979Srwatson	int error;
2535100979Srwatson
2536100979Srwatson	if (!mac_enforce_socket)
2537100979Srwatson		return (0);
2538100979Srwatson
2539100979Srwatson	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2540100979Srwatson	    sockaddr);
2541100979Srwatson
2542100979Srwatson	return (error);
2543100979Srwatson}
2544100979Srwatson
2545100979Srwatsonint
2546101933Srwatsonmac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2547100979Srwatson{
2548100979Srwatson	int error;
2549100979Srwatson
2550100979Srwatson	if (!mac_enforce_socket)
2551100979Srwatson		return (0);
2552100979Srwatson
2553101933Srwatson	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2554101933Srwatson	    &mbuf->m_pkthdr.label);
2555101933Srwatson
2556100979Srwatson	return (error);
2557100979Srwatson}
2558100979Srwatson
2559100979Srwatsonint
2560101933Srwatsonmac_check_socket_listen(struct ucred *cred, struct socket *socket)
2561100979Srwatson{
2562100979Srwatson	int error;
2563100979Srwatson
2564100979Srwatson	if (!mac_enforce_socket)
2565100979Srwatson		return (0);
2566100979Srwatson
2567101933Srwatson	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2568100979Srwatson	return (error);
2569100979Srwatson}
2570100979Srwatson
2571104571Srwatsonint
2572104571Srwatsonmac_check_socket_receive(struct ucred *cred, struct socket *so)
2573104571Srwatson{
2574104571Srwatson	int error;
2575104571Srwatson
2576104571Srwatson	if (!mac_enforce_socket)
2577104571Srwatson		return (0);
2578104571Srwatson
2579104571Srwatson	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2580104571Srwatson
2581104571Srwatson	return (error);
2582104571Srwatson}
2583104571Srwatson
2584100979Srwatsonstatic int
2585100979Srwatsonmac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2586100979Srwatson    struct label *newlabel)
2587100979Srwatson{
2588100979Srwatson	int error;
2589100979Srwatson
2590100979Srwatson	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2591100979Srwatson	    newlabel);
2592100979Srwatson
2593100979Srwatson	return (error);
2594100979Srwatson}
2595100979Srwatson
2596100979Srwatsonint
2597104571Srwatsonmac_check_socket_send(struct ucred *cred, struct socket *so)
2598104571Srwatson{
2599104571Srwatson	int error;
2600104571Srwatson
2601104571Srwatson	if (!mac_enforce_socket)
2602104571Srwatson		return (0);
2603104571Srwatson
2604104571Srwatson	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2605104571Srwatson
2606104571Srwatson	return (error);
2607104571Srwatson}
2608104571Srwatson
2609104571Srwatsonint
2610100979Srwatsonmac_check_socket_visible(struct ucred *cred, struct socket *socket)
2611100979Srwatson{
2612100979Srwatson	int error;
2613100979Srwatson
2614100979Srwatson	if (!mac_enforce_socket)
2615100979Srwatson		return (0);
2616105694Srwatson
2617100979Srwatson	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2618105694Srwatson
2619100979Srwatson	return (error);
2620100979Srwatson}
2621100979Srwatson
2622100979Srwatsonint
2623106412Srwatsonmac_check_system_acct(struct ucred *cred, struct vnode *vp)
2624106412Srwatson{
2625106412Srwatson	int error;
2626106412Srwatson
2627106412Srwatson	if (vp != NULL) {
2628106412Srwatson		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2629106412Srwatson	}
2630106412Srwatson
2631106412Srwatson	if (!mac_enforce_system)
2632106412Srwatson		return (0);
2633106412Srwatson
2634106412Srwatson	MAC_CHECK(check_system_acct, cred, vp,
2635106412Srwatson	    vp != NULL ? &vp->v_label : NULL);
2636106412Srwatson
2637106412Srwatson	return (error);
2638106412Srwatson}
2639106412Srwatson
2640106412Srwatsonint
2641106412Srwatsonmac_check_system_nfsd(struct ucred *cred)
2642106412Srwatson{
2643106412Srwatson	int error;
2644106412Srwatson
2645106412Srwatson	if (!mac_enforce_system)
2646106412Srwatson		return (0);
2647106412Srwatson
2648106412Srwatson	MAC_CHECK(check_system_nfsd, cred);
2649106412Srwatson
2650106412Srwatson	return (error);
2651106412Srwatson}
2652106412Srwatson
2653106412Srwatsonint
2654106024Srwatsonmac_check_system_reboot(struct ucred *cred, int howto)
2655106024Srwatson{
2656106024Srwatson	int error;
2657106024Srwatson
2658106045Srwatson	if (!mac_enforce_system)
2659106024Srwatson		return (0);
2660106024Srwatson
2661106024Srwatson	MAC_CHECK(check_system_reboot, cred, howto);
2662106045Srwatson
2663106024Srwatson	return (error);
2664106024Srwatson}
2665106024Srwatson
2666106024Srwatsonint
2667106369Srwatsonmac_check_system_settime(struct ucred *cred)
2668106369Srwatson{
2669106369Srwatson	int error;
2670106369Srwatson
2671106369Srwatson	if (!mac_enforce_system)
2672106369Srwatson		return (0);
2673106369Srwatson
2674106369Srwatson	MAC_CHECK(check_system_settime, cred);
2675106369Srwatson
2676106369Srwatson	return (error);
2677106369Srwatson}
2678106369Srwatson
2679106369Srwatsonint
2680106023Srwatsonmac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2681106023Srwatson{
2682106023Srwatson	int error;
2683106023Srwatson
2684106023Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2685106023Srwatson
2686106045Srwatson	if (!mac_enforce_system)
2687106023Srwatson		return (0);
2688106023Srwatson
2689106023Srwatson	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2690106023Srwatson	return (error);
2691106023Srwatson}
2692106023Srwatson
2693106023Srwatsonint
2694106025Srwatsonmac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2695106025Srwatson    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2696106025Srwatson{
2697106025Srwatson	int error;
2698106025Srwatson
2699106025Srwatson	/*
2700106025Srwatson	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2701106025Srwatson	 * but since it's not exported from kern_sysctl.c, we can't.
2702106025Srwatson	 */
2703106045Srwatson	if (!mac_enforce_system)
2704106025Srwatson		return (0);
2705106025Srwatson
2706106025Srwatson	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2707106025Srwatson	    inkernel, new, newlen);
2708106025Srwatson
2709106025Srwatson	return (error);
2710106025Srwatson}
2711106025Srwatson
2712106025Srwatsonint
2713100979Srwatsonmac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2714100979Srwatson    struct ifnet *ifnet)
2715100979Srwatson{
2716105694Srwatson	char *elements, *buffer;
2717105694Srwatson	struct mac mac;
2718100979Srwatson	int error;
2719100979Srwatson
2720105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2721100979Srwatson	if (error)
2722100979Srwatson		return (error);
2723100979Srwatson
2724105694Srwatson	error = mac_check_structmac_consistent(&mac);
2725105694Srwatson	if (error)
2726105694Srwatson		return (error);
2727105694Srwatson
2728105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2729105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2730105694Srwatson	if (error) {
2731105694Srwatson		free(elements, M_MACTEMP);
2732105694Srwatson		return (error);
2733105694Srwatson	}
2734105694Srwatson
2735105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2736105694Srwatson	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2737105694Srwatson	    buffer, mac.m_buflen, M_WAITOK);
2738105694Srwatson	if (error == 0)
2739105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2740105694Srwatson
2741105694Srwatson	free(buffer, M_MACTEMP);
2742105694Srwatson	free(elements, M_MACTEMP);
2743105694Srwatson
2744105694Srwatson	return (error);
2745100979Srwatson}
2746100979Srwatson
2747100979Srwatsonint
2748100979Srwatsonmac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2749100979Srwatson    struct ifnet *ifnet)
2750100979Srwatson{
2751100979Srwatson	struct label intlabel;
2752105694Srwatson	struct mac mac;
2753105694Srwatson	char *buffer;
2754100979Srwatson	int error;
2755100979Srwatson
2756105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2757100979Srwatson	if (error)
2758100979Srwatson		return (error);
2759100979Srwatson
2760105694Srwatson	error = mac_check_structmac_consistent(&mac);
2761100979Srwatson	if (error)
2762100979Srwatson		return (error);
2763100979Srwatson
2764105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2765105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2766105694Srwatson	if (error) {
2767105694Srwatson		free(buffer, M_MACTEMP);
2768105694Srwatson		return (error);
2769105694Srwatson	}
2770105694Srwatson
2771105694Srwatson	mac_init_ifnet_label(&intlabel);
2772105694Srwatson	error = mac_internalize_ifnet_label(&intlabel, buffer);
2773105694Srwatson	free(buffer, M_MACTEMP);
2774105694Srwatson	if (error) {
2775105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2776105694Srwatson		return (error);
2777105694Srwatson	}
2778105694Srwatson
2779100979Srwatson	/*
2780100979Srwatson	 * XXX: Note that this is a redundant privilege check, since
2781100979Srwatson	 * policies impose this check themselves if required by the
2782100979Srwatson	 * policy.  Eventually, this should go away.
2783100979Srwatson	 */
2784100979Srwatson	error = suser_cred(cred, 0);
2785105694Srwatson	if (error) {
2786105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2787105694Srwatson		return (error);
2788105694Srwatson	}
2789100979Srwatson
2790100979Srwatson	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2791100979Srwatson	    &intlabel);
2792105694Srwatson	if (error) {
2793105694Srwatson		mac_destroy_ifnet_label(&intlabel);
2794105694Srwatson		return (error);
2795105694Srwatson	}
2796100979Srwatson
2797100979Srwatson	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2798100979Srwatson
2799105694Srwatson	mac_destroy_ifnet_label(&intlabel);
2800105694Srwatson	return (0);
2801100979Srwatson}
2802100979Srwatson
2803100979Srwatsonvoid
2804100979Srwatsonmac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2805100979Srwatson{
2806100979Srwatson
2807100979Srwatson	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2808100979Srwatson}
2809100979Srwatson
2810104533Srwatsonvoid
2811104533Srwatsonmac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2812104533Srwatson    struct devfs_dirent *de)
2813104533Srwatson{
2814104533Srwatson
2815104533Srwatson	MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2816104533Srwatson	    &de->de_label);
2817104533Srwatson}
2818104533Srwatson
2819100979Srwatsonvoid
2820100979Srwatsonmac_create_devfs_directory(char *dirname, int dirnamelen,
2821100979Srwatson    struct devfs_dirent *de)
2822100979Srwatson{
2823100979Srwatson
2824100979Srwatson	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2825100979Srwatson	    &de->de_label);
2826100979Srwatson}
2827100979Srwatson
2828100979Srwatsonint
2829100979Srwatsonmac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2830105694Srwatson    struct mac *mac)
2831100979Srwatson{
2832100979Srwatson	struct label intlabel;
2833105694Srwatson	char *buffer;
2834100979Srwatson	int error;
2835100979Srwatson
2836105694Srwatson	error = mac_check_structmac_consistent(mac);
2837100979Srwatson	if (error)
2838100979Srwatson		return (error);
2839100979Srwatson
2840105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2841105694Srwatson	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2842105694Srwatson	if (error) {
2843105694Srwatson		free(buffer, M_MACTEMP);
2844105694Srwatson		return (error);
2845105694Srwatson	}
2846105694Srwatson
2847105694Srwatson	mac_init_socket_label(&intlabel, M_WAITOK);
2848105694Srwatson	error = mac_internalize_socket_label(&intlabel, buffer);
2849105694Srwatson	free(buffer, M_MACTEMP);
2850105694Srwatson	if (error) {
2851105694Srwatson		mac_destroy_socket_label(&intlabel);
2852105694Srwatson		return (error);
2853105694Srwatson	}
2854105694Srwatson
2855100979Srwatson	mac_check_socket_relabel(cred, so, &intlabel);
2856100979Srwatson	if (error) {
2857105694Srwatson		mac_destroy_socket_label(&intlabel);
2858100979Srwatson		return (error);
2859100979Srwatson	}
2860100979Srwatson
2861100979Srwatson	mac_relabel_socket(cred, so, &intlabel);
2862100979Srwatson
2863105694Srwatson	mac_destroy_socket_label(&intlabel);
2864100979Srwatson	return (0);
2865100979Srwatson}
2866100979Srwatson
2867100979Srwatsonint
2868100979Srwatsonmac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2869100979Srwatson{
2870100979Srwatson	int error;
2871100979Srwatson
2872104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2873104269Srwatson
2874100979Srwatson	error = mac_check_pipe_relabel(cred, pipe, label);
2875100979Srwatson	if (error)
2876100979Srwatson		return (error);
2877100979Srwatson
2878100979Srwatson	mac_relabel_pipe(cred, pipe, label);
2879100979Srwatson
2880100979Srwatson	return (0);
2881100979Srwatson}
2882100979Srwatson
2883100979Srwatsonint
2884100979Srwatsonmac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2885105694Srwatson    struct mac *mac)
2886100979Srwatson{
2887105694Srwatson	char *buffer, *elements;
2888105694Srwatson	int error;
2889100979Srwatson
2890105694Srwatson	error = mac_check_structmac_consistent(mac);
2891105694Srwatson	if (error)
2892105694Srwatson		return (error);
2893105694Srwatson
2894105694Srwatson	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2895105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2896105694Srwatson	if (error) {
2897105694Srwatson		free(elements, M_MACTEMP);
2898105694Srwatson		return (error);
2899105694Srwatson	}
2900105694Srwatson
2901105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2902105694Srwatson	error = mac_externalize_socket_label(&so->so_label, elements,
2903105694Srwatson	    buffer, mac->m_buflen, M_WAITOK);
2904105694Srwatson	if (error == 0)
2905105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2906105694Srwatson
2907105694Srwatson	free(buffer, M_MACTEMP);
2908105694Srwatson	free(elements, M_MACTEMP);
2909105694Srwatson
2910105694Srwatson	return (error);
2911100979Srwatson}
2912100979Srwatson
2913100979Srwatsonint
2914100979Srwatsonmac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2915105694Srwatson    struct mac *mac)
2916100979Srwatson{
2917105694Srwatson	char *elements, *buffer;
2918105694Srwatson	int error;
2919100979Srwatson
2920105694Srwatson	error = mac_check_structmac_consistent(mac);
2921105694Srwatson	if (error)
2922105694Srwatson		return (error);
2923105694Srwatson
2924105694Srwatson	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2925105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2926105694Srwatson	if (error) {
2927105694Srwatson		free(elements, M_MACTEMP);
2928105694Srwatson		return (error);
2929105694Srwatson	}
2930105694Srwatson
2931105694Srwatson	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2932105694Srwatson	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2933105694Srwatson	    elements, buffer, mac->m_buflen, M_WAITOK);
2934105694Srwatson	if (error == 0)
2935105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2936105694Srwatson
2937105694Srwatson	free(buffer, M_MACTEMP);
2938105694Srwatson	free(elements, M_MACTEMP);
2939105694Srwatson
2940105694Srwatson	return (error);
2941100979Srwatson}
2942100979Srwatson
2943100979Srwatson/*
2944100979Srwatson * Implementation of VOP_SETLABEL() that relies on extended attributes
2945100979Srwatson * to store label data.  Can be referenced by filesystems supporting
2946100979Srwatson * extended attributes.
2947100979Srwatson */
2948100979Srwatsonint
2949100979Srwatsonvop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2950100979Srwatson{
2951100979Srwatson	struct vnode *vp = ap->a_vp;
2952100979Srwatson	struct label *intlabel = ap->a_label;
2953100979Srwatson	int error;
2954100979Srwatson
2955100979Srwatson	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2956100979Srwatson
2957105988Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2958105988Srwatson		return (EOPNOTSUPP);
2959100979Srwatson
2960105988Srwatson	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2961100979Srwatson	if (error)
2962100979Srwatson		return (error);
2963100979Srwatson
2964100979Srwatson	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2965100979Srwatson
2966100979Srwatson	return (0);
2967100979Srwatson}
2968100979Srwatson
2969100979Srwatsonstatic int
2970100979Srwatsonvn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2971100979Srwatson{
2972100979Srwatson	int error;
2973100979Srwatson
2974100979Srwatson	if (vp->v_mount == NULL) {
2975100979Srwatson		/* printf("vn_setlabel: null v_mount\n"); */
2976103314Snjl		if (vp->v_type != VNON)
2977103314Snjl			printf("vn_setlabel: null v_mount with non-VNON\n");
2978100979Srwatson		return (EBADF);
2979100979Srwatson	}
2980100979Srwatson
2981100979Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2982100979Srwatson		return (EOPNOTSUPP);
2983100979Srwatson
2984100979Srwatson	/*
2985100979Srwatson	 * Multi-phase commit.  First check the policies to confirm the
2986100979Srwatson	 * change is OK.  Then commit via the filesystem.  Finally,
2987100979Srwatson	 * update the actual vnode label.  Question: maybe the filesystem
2988100979Srwatson	 * should update the vnode at the end as part of VOP_SETLABEL()?
2989100979Srwatson	 */
2990100979Srwatson	error = mac_check_vnode_relabel(cred, vp, intlabel);
2991100979Srwatson	if (error)
2992100979Srwatson		return (error);
2993100979Srwatson
2994100979Srwatson	/*
2995100979Srwatson	 * VADMIN provides the opportunity for the filesystem to make
2996100979Srwatson	 * decisions about who is and is not able to modify labels
2997100979Srwatson	 * and protections on files.  This might not be right.  We can't
2998100979Srwatson	 * assume VOP_SETLABEL() will do it, because we might implement
2999100979Srwatson	 * that as part of vop_stdsetlabel_ea().
3000100979Srwatson	 */
3001100979Srwatson	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3002100979Srwatson	if (error)
3003100979Srwatson		return (error);
3004100979Srwatson
3005100979Srwatson	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3006100979Srwatson	if (error)
3007100979Srwatson		return (error);
3008100979Srwatson
3009100979Srwatson	return (0);
3010100979Srwatson}
3011100979Srwatson
3012105694Srwatsonint
3013105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3014105694Srwatson{
3015105694Srwatson	char *elements, *buffer;
3016105694Srwatson	struct mac mac;
3017105694Srwatson	struct proc *tproc;
3018105694Srwatson	struct ucred *tcred;
3019105694Srwatson	int error;
3020105694Srwatson
3021105694Srwatson	error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3022105694Srwatson	if (error)
3023105694Srwatson		return (error);
3024105694Srwatson
3025105694Srwatson	error = mac_check_structmac_consistent(&mac);
3026105694Srwatson	if (error)
3027105694Srwatson		return (error);
3028105694Srwatson
3029105694Srwatson	tproc = pfind(uap->pid);
3030105694Srwatson	if (tproc == NULL)
3031105694Srwatson		return (ESRCH);
3032105694Srwatson
3033105694Srwatson	tcred = NULL;				/* Satisfy gcc. */
3034105694Srwatson	error = p_cansee(td, tproc);
3035105694Srwatson	if (error == 0)
3036105694Srwatson		tcred = crhold(tproc->p_ucred);
3037105694Srwatson	PROC_UNLOCK(tproc);
3038105694Srwatson	if (error)
3039105694Srwatson		return (error);
3040105694Srwatson
3041105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3042105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3043105694Srwatson	if (error) {
3044105694Srwatson		free(elements, M_MACTEMP);
3045105694Srwatson		crfree(tcred);
3046105694Srwatson		return (error);
3047105694Srwatson	}
3048105694Srwatson
3049105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3050105694Srwatson	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3051105694Srwatson	    buffer, mac.m_buflen, M_WAITOK);
3052105694Srwatson	if (error == 0)
3053105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3054105694Srwatson
3055105694Srwatson	free(buffer, M_MACTEMP);
3056105694Srwatson	free(elements, M_MACTEMP);
3057105694Srwatson	crfree(tcred);
3058105694Srwatson	return (error);
3059105694Srwatson}
3060105694Srwatson
3061100979Srwatson/*
3062100979Srwatson * MPSAFE
3063100979Srwatson */
3064100979Srwatsonint
3065100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3066100894Srwatson{
3067105694Srwatson	char *elements, *buffer;
3068105694Srwatson	struct mac mac;
3069100979Srwatson	int error;
3070100894Srwatson
3071105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3072105694Srwatson	if (error)
3073105694Srwatson		return (error);
3074105694Srwatson
3075105694Srwatson	error = mac_check_structmac_consistent(&mac);
3076105694Srwatson	if (error)
3077105694Srwatson		return (error);
3078105694Srwatson
3079105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3080105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3081105694Srwatson	if (error) {
3082105694Srwatson		free(elements, M_MACTEMP);
3083105694Srwatson		return (error);
3084105694Srwatson	}
3085105694Srwatson
3086105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3087105694Srwatson	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3088105694Srwatson	    elements, buffer, mac.m_buflen, M_WAITOK);
3089100979Srwatson	if (error == 0)
3090105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3091100979Srwatson
3092105694Srwatson	free(buffer, M_MACTEMP);
3093105694Srwatson	free(elements, M_MACTEMP);
3094100979Srwatson	return (error);
3095100979Srwatson}
3096100979Srwatson
3097100979Srwatson/*
3098100979Srwatson * MPSAFE
3099100979Srwatson */
3100100979Srwatsonint
3101100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3102100979Srwatson{
3103100979Srwatson	struct ucred *newcred, *oldcred;
3104105694Srwatson	struct label intlabel;
3105100979Srwatson	struct proc *p;
3106105694Srwatson	struct mac mac;
3107105694Srwatson	char *buffer;
3108100979Srwatson	int error;
3109100979Srwatson
3110105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3111100979Srwatson	if (error)
3112100979Srwatson		return (error);
3113100979Srwatson
3114105694Srwatson	error = mac_check_structmac_consistent(&mac);
3115100979Srwatson	if (error)
3116100979Srwatson		return (error);
3117100979Srwatson
3118105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3119105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3120105694Srwatson	if (error) {
3121105694Srwatson		free(buffer, M_MACTEMP);
3122105694Srwatson		return (error);
3123105694Srwatson	}
3124105694Srwatson
3125105694Srwatson	mac_init_cred_label(&intlabel);
3126105694Srwatson	error = mac_internalize_cred_label(&intlabel, buffer);
3127105694Srwatson	free(buffer, M_MACTEMP);
3128105694Srwatson	if (error) {
3129105694Srwatson		mac_destroy_cred_label(&intlabel);
3130105694Srwatson		return (error);
3131105694Srwatson	}
3132105694Srwatson
3133100979Srwatson	newcred = crget();
3134100979Srwatson
3135100979Srwatson	p = td->td_proc;
3136100979Srwatson	PROC_LOCK(p);
3137100979Srwatson	oldcred = p->p_ucred;
3138100979Srwatson
3139100979Srwatson	error = mac_check_cred_relabel(oldcred, &intlabel);
3140100979Srwatson	if (error) {
3141100979Srwatson		PROC_UNLOCK(p);
3142100979Srwatson		crfree(newcred);
3143105694Srwatson		goto out;
3144100979Srwatson	}
3145100979Srwatson
3146100979Srwatson	setsugid(p);
3147100979Srwatson	crcopy(newcred, oldcred);
3148100979Srwatson	mac_relabel_cred(newcred, &intlabel);
3149102136Srwatson	p->p_ucred = newcred;
3150100979Srwatson
3151102136Srwatson	/*
3152102136Srwatson	 * Grab additional reference for use while revoking mmaps, prior
3153102136Srwatson	 * to releasing the proc lock and sharing the cred.
3154102136Srwatson	 */
3155102136Srwatson	crhold(newcred);
3156100979Srwatson	PROC_UNLOCK(p);
3157102136Srwatson
3158105694Srwatson	if (mac_enforce_vm) {
3159105694Srwatson		mtx_lock(&Giant);
3160105694Srwatson		mac_cred_mmapped_drop_perms(td, newcred);
3161105694Srwatson		mtx_unlock(&Giant);
3162105694Srwatson	}
3163102136Srwatson
3164102136Srwatson	crfree(newcred);	/* Free revocation reference. */
3165100979Srwatson	crfree(oldcred);
3166105694Srwatson
3167105694Srwatsonout:
3168105694Srwatson	mac_destroy_cred_label(&intlabel);
3169105694Srwatson	return (error);
3170100979Srwatson}
3171100979Srwatson
3172100979Srwatson/*
3173100979Srwatson * MPSAFE
3174100979Srwatson */
3175100979Srwatsonint
3176100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3177100979Srwatson{
3178105694Srwatson	char *elements, *buffer;
3179105694Srwatson	struct label intlabel;
3180100979Srwatson	struct file *fp;
3181105694Srwatson	struct mac mac;
3182100979Srwatson	struct vnode *vp;
3183100979Srwatson	struct pipe *pipe;
3184105694Srwatson	short label_type;
3185100979Srwatson	int error;
3186100979Srwatson
3187105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3188105694Srwatson	if (error)
3189105694Srwatson		return (error);
3190100979Srwatson
3191105694Srwatson	error = mac_check_structmac_consistent(&mac);
3192105694Srwatson	if (error)
3193105694Srwatson		return (error);
3194105694Srwatson
3195105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3196105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3197105694Srwatson	if (error) {
3198105694Srwatson		free(elements, M_MACTEMP);
3199105694Srwatson		return (error);
3200105694Srwatson	}
3201105694Srwatson
3202105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3203105694Srwatson	mtx_lock(&Giant);				/* VFS */
3204100979Srwatson	error = fget(td, SCARG(uap, fd), &fp);
3205100979Srwatson	if (error)
3206100979Srwatson		goto out;
3207100979Srwatson
3208105694Srwatson	label_type = fp->f_type;
3209100979Srwatson	switch (fp->f_type) {
3210100979Srwatson	case DTYPE_FIFO:
3211100979Srwatson	case DTYPE_VNODE:
3212100979Srwatson		vp = (struct vnode *)fp->f_data;
3213100979Srwatson
3214105694Srwatson		mac_init_vnode_label(&intlabel);
3215105694Srwatson
3216100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3217105988Srwatson		mac_copy_vnode_label(&vp->v_label, &intlabel);
3218100979Srwatson		VOP_UNLOCK(vp, 0, td);
3219105694Srwatson
3220100979Srwatson		break;
3221100979Srwatson	case DTYPE_PIPE:
3222100979Srwatson		pipe = (struct pipe *)fp->f_data;
3223105694Srwatson
3224105694Srwatson		mac_init_pipe_label(&intlabel);
3225105694Srwatson
3226105694Srwatson		PIPE_LOCK(pipe);
3227105694Srwatson		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3228105694Srwatson		PIPE_UNLOCK(pipe);
3229100979Srwatson		break;
3230100979Srwatson	default:
3231100979Srwatson		error = EINVAL;
3232105694Srwatson		fdrop(fp, td);
3233105694Srwatson		goto out;
3234100979Srwatson	}
3235105694Srwatson	fdrop(fp, td);
3236100979Srwatson
3237105694Srwatson	switch (label_type) {
3238105694Srwatson	case DTYPE_FIFO:
3239105694Srwatson	case DTYPE_VNODE:
3240105694Srwatson		if (error == 0)
3241105694Srwatson			error = mac_externalize_vnode_label(&intlabel,
3242105694Srwatson			    elements, buffer, mac.m_buflen, M_WAITOK);
3243105694Srwatson		mac_destroy_vnode_label(&intlabel);
3244105694Srwatson		break;
3245105694Srwatson	case DTYPE_PIPE:
3246105694Srwatson		error = mac_externalize_pipe_label(&intlabel, elements,
3247105694Srwatson		    buffer, mac.m_buflen, M_WAITOK);
3248105694Srwatson		mac_destroy_pipe_label(&intlabel);
3249105694Srwatson		break;
3250105694Srwatson	default:
3251105694Srwatson		panic("__mac_get_fd: corrupted label_type");
3252105694Srwatson	}
3253105694Srwatson
3254100979Srwatson	if (error == 0)
3255105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3256100979Srwatson
3257105694Srwatsonout:
3258105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3259105694Srwatson	free(buffer, M_MACTEMP);
3260105694Srwatson	free(elements, M_MACTEMP);
3261100979Srwatson
3262100979Srwatson	return (error);
3263100979Srwatson}
3264100979Srwatson
3265100979Srwatson/*
3266100979Srwatson * MPSAFE
3267100979Srwatson */
3268100979Srwatsonint
3269100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3270100979Srwatson{
3271105694Srwatson	char *elements, *buffer;
3272100979Srwatson	struct nameidata nd;
3273105694Srwatson	struct label intlabel;
3274105694Srwatson	struct mac mac;
3275100979Srwatson	int error;
3276100979Srwatson
3277105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3278105694Srwatson	if (error)
3279105694Srwatson		return (error);
3280105694Srwatson
3281105694Srwatson	error = mac_check_structmac_consistent(&mac);
3282105694Srwatson	if (error)
3283105694Srwatson		return (error);
3284105694Srwatson
3285105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3286105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3287105694Srwatson	if (error) {
3288105694Srwatson		free(elements, M_MACTEMP);
3289105694Srwatson		return (error);
3290105694Srwatson	}
3291105694Srwatson
3292105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3293105694Srwatson	mtx_lock(&Giant);				/* VFS */
3294105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3295105694Srwatson	    td);
3296100979Srwatson	error = namei(&nd);
3297100979Srwatson	if (error)
3298100979Srwatson		goto out;
3299100979Srwatson
3300105694Srwatson	mac_init_vnode_label(&intlabel);
3301105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3302105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3303105988Srwatson	    mac.m_buflen, M_WAITOK);
3304105694Srwatson
3305100979Srwatson	NDFREE(&nd, 0);
3306105694Srwatson	mac_destroy_vnode_label(&intlabel);
3307105694Srwatson
3308105694Srwatson	if (error == 0)
3309105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3310105694Srwatson
3311105694Srwatsonout:
3312105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3313105694Srwatson
3314105694Srwatson	free(buffer, M_MACTEMP);
3315105694Srwatson	free(elements, M_MACTEMP);
3316105694Srwatson
3317105694Srwatson	return (error);
3318105694Srwatson}
3319105694Srwatson
3320105694Srwatson/*
3321105694Srwatson * MPSAFE
3322105694Srwatson */
3323105694Srwatsonint
3324105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3325105694Srwatson{
3326105694Srwatson	char *elements, *buffer;
3327105694Srwatson	struct nameidata nd;
3328105694Srwatson	struct label intlabel;
3329105694Srwatson	struct mac mac;
3330105694Srwatson	int error;
3331105694Srwatson
3332105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3333100979Srwatson	if (error)
3334105694Srwatson		return (error);
3335105694Srwatson
3336105694Srwatson	error = mac_check_structmac_consistent(&mac);
3337105694Srwatson	if (error)
3338105694Srwatson		return (error);
3339105694Srwatson
3340105694Srwatson	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3341105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3342105694Srwatson	if (error) {
3343105694Srwatson		free(elements, M_MACTEMP);
3344105694Srwatson		return (error);
3345105694Srwatson	}
3346105694Srwatson
3347105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3348105694Srwatson	mtx_lock(&Giant);				/* VFS */
3349105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3350105694Srwatson	    td);
3351105694Srwatson	error = namei(&nd);
3352105694Srwatson	if (error)
3353100979Srwatson		goto out;
3354100979Srwatson
3355105694Srwatson	mac_init_vnode_label(&intlabel);
3356105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3357105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3358105988Srwatson	    mac.m_buflen, M_WAITOK);
3359105694Srwatson	NDFREE(&nd, 0);
3360105694Srwatson	mac_destroy_vnode_label(&intlabel);
3361100979Srwatson
3362105694Srwatson	if (error == 0)
3363105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3364105694Srwatson
3365100979Srwatsonout:
3366105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3367105694Srwatson
3368105694Srwatson	free(buffer, M_MACTEMP);
3369105694Srwatson	free(elements, M_MACTEMP);
3370105694Srwatson
3371100979Srwatson	return (error);
3372100979Srwatson}
3373100979Srwatson
3374100979Srwatson/*
3375100979Srwatson * MPSAFE
3376100979Srwatson */
3377100979Srwatsonint
3378100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3379100979Srwatson{
3380105694Srwatson	struct label intlabel;
3381105694Srwatson	struct pipe *pipe;
3382100979Srwatson	struct file *fp;
3383100979Srwatson	struct mount *mp;
3384100979Srwatson	struct vnode *vp;
3385105694Srwatson	struct mac mac;
3386105694Srwatson	char *buffer;
3387100979Srwatson	int error;
3388100979Srwatson
3389105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3390100979Srwatson	if (error)
3391105694Srwatson		return (error);
3392100979Srwatson
3393105694Srwatson	error = mac_check_structmac_consistent(&mac);
3394100979Srwatson	if (error)
3395105694Srwatson		return (error);
3396100979Srwatson
3397105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3398105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3399105694Srwatson	if (error) {
3400105694Srwatson		free(buffer, M_MACTEMP);
3401105694Srwatson		return (error);
3402105694Srwatson	}
3403105694Srwatson
3404105694Srwatson	mtx_lock(&Giant);				/* VFS */
3405105694Srwatson
3406105694Srwatson	error = fget(td, SCARG(uap, fd), &fp);
3407100979Srwatson	if (error)
3408105694Srwatson		goto out;
3409100979Srwatson
3410100979Srwatson	switch (fp->f_type) {
3411100979Srwatson	case DTYPE_FIFO:
3412100979Srwatson	case DTYPE_VNODE:
3413105694Srwatson		mac_init_vnode_label(&intlabel);
3414105694Srwatson		error = mac_internalize_vnode_label(&intlabel, buffer);
3415105694Srwatson		if (error) {
3416105694Srwatson			mac_destroy_vnode_label(&intlabel);
3417105694Srwatson			break;
3418105694Srwatson		}
3419105694Srwatson
3420100979Srwatson		vp = (struct vnode *)fp->f_data;
3421100979Srwatson		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3422105694Srwatson		if (error != 0) {
3423105694Srwatson			mac_destroy_vnode_label(&intlabel);
3424100979Srwatson			break;
3425105694Srwatson		}
3426100979Srwatson
3427100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3428100979Srwatson		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3429100979Srwatson		VOP_UNLOCK(vp, 0, td);
3430100979Srwatson		vn_finished_write(mp);
3431105694Srwatson
3432105694Srwatson		mac_destroy_vnode_label(&intlabel);
3433100979Srwatson		break;
3434105694Srwatson
3435100979Srwatson	case DTYPE_PIPE:
3436105694Srwatson		mac_init_pipe_label(&intlabel);
3437105694Srwatson		error = mac_internalize_pipe_label(&intlabel, buffer);
3438105694Srwatson		if (error == 0) {
3439105694Srwatson			pipe = (struct pipe *)fp->f_data;
3440105694Srwatson			PIPE_LOCK(pipe);
3441105694Srwatson			error = mac_pipe_label_set(td->td_ucred, pipe,
3442105694Srwatson			    &intlabel);
3443105694Srwatson			PIPE_UNLOCK(pipe);
3444105694Srwatson		}
3445105694Srwatson
3446105694Srwatson		mac_destroy_pipe_label(&intlabel);
3447100979Srwatson		break;
3448105694Srwatson
3449100979Srwatson	default:
3450100979Srwatson		error = EINVAL;
3451100979Srwatson	}
3452100979Srwatson
3453100979Srwatson	fdrop(fp, td);
3454105694Srwatsonout:
3455105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3456105694Srwatson
3457105694Srwatson	free(buffer, M_MACTEMP);
3458105694Srwatson
3459100979Srwatson	return (error);
3460100979Srwatson}
3461100979Srwatson
3462100979Srwatson/*
3463100979Srwatson * MPSAFE
3464100979Srwatson */
3465100979Srwatsonint
3466100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3467100979Srwatson{
3468105694Srwatson	struct label intlabel;
3469100979Srwatson	struct nameidata nd;
3470100979Srwatson	struct mount *mp;
3471105694Srwatson	struct mac mac;
3472105694Srwatson	char *buffer;
3473100979Srwatson	int error;
3474100979Srwatson
3475105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3476100979Srwatson	if (error)
3477105694Srwatson		return (error);
3478100979Srwatson
3479105694Srwatson	error = mac_check_structmac_consistent(&mac);
3480100979Srwatson	if (error)
3481105694Srwatson		return (error);
3482100979Srwatson
3483105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3484105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3485105694Srwatson	if (error) {
3486105694Srwatson		free(buffer, M_MACTEMP);
3487105694Srwatson		return (error);
3488105694Srwatson	}
3489105694Srwatson
3490105694Srwatson	mac_init_vnode_label(&intlabel);
3491105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3492105694Srwatson	free(buffer, M_MACTEMP);
3493105694Srwatson	if (error) {
3494105694Srwatson		mac_destroy_vnode_label(&intlabel);
3495105694Srwatson		return (error);
3496105694Srwatson	}
3497105694Srwatson
3498105694Srwatson	mtx_lock(&Giant);				/* VFS */
3499105694Srwatson
3500105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3501105694Srwatson	    td);
3502100979Srwatson	error = namei(&nd);
3503105694Srwatson	if (error == 0) {
3504105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3505105694Srwatson		if (error == 0)
3506105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3507105694Srwatson			    td->td_ucred);
3508105694Srwatson		vn_finished_write(mp);
3509105694Srwatson	}
3510105694Srwatson
3511105694Srwatson	NDFREE(&nd, 0);
3512105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3513105694Srwatson	mac_destroy_vnode_label(&intlabel);
3514105694Srwatson
3515105694Srwatson	return (error);
3516105694Srwatson}
3517105694Srwatson
3518105694Srwatson/*
3519105694Srwatson * MPSAFE
3520105694Srwatson */
3521105694Srwatsonint
3522105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3523105694Srwatson{
3524105694Srwatson	struct label intlabel;
3525105694Srwatson	struct nameidata nd;
3526105694Srwatson	struct mount *mp;
3527105694Srwatson	struct mac mac;
3528105694Srwatson	char *buffer;
3529105694Srwatson	int error;
3530105694Srwatson
3531105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3532100979Srwatson	if (error)
3533105694Srwatson		return (error);
3534105694Srwatson
3535105694Srwatson	error = mac_check_structmac_consistent(&mac);
3536100979Srwatson	if (error)
3537105694Srwatson		return (error);
3538100979Srwatson
3539105694Srwatson	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3540105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3541105694Srwatson	if (error) {
3542105694Srwatson		free(buffer, M_MACTEMP);
3543105694Srwatson		return (error);
3544105694Srwatson	}
3545105694Srwatson
3546105694Srwatson	mac_init_vnode_label(&intlabel);
3547105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3548105694Srwatson	free(buffer, M_MACTEMP);
3549105694Srwatson	if (error) {
3550105694Srwatson		mac_destroy_vnode_label(&intlabel);
3551105694Srwatson		return (error);
3552105694Srwatson	}
3553105694Srwatson
3554105694Srwatson	mtx_lock(&Giant);				/* VFS */
3555105694Srwatson
3556105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3557105694Srwatson	    td);
3558105694Srwatson	error = namei(&nd);
3559105694Srwatson	if (error == 0) {
3560105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3561105694Srwatson		if (error == 0)
3562105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3563105694Srwatson			    td->td_ucred);
3564105694Srwatson		vn_finished_write(mp);
3565105694Srwatson	}
3566105694Srwatson
3567100979Srwatson	NDFREE(&nd, 0);
3568105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3569105694Srwatson	mac_destroy_vnode_label(&intlabel);
3570105694Srwatson
3571100979Srwatson	return (error);
3572100979Srwatson}
3573100979Srwatson
3574105694Srwatson/*
3575105694Srwatson * MPSAFE
3576105694Srwatson */
3577102123Srwatsonint
3578102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3579102123Srwatson{
3580102123Srwatson	struct mac_policy_conf *mpc;
3581102123Srwatson	char target[MAC_MAX_POLICY_NAME];
3582102123Srwatson	int error;
3583102123Srwatson
3584102123Srwatson	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3585102123Srwatson	if (error)
3586102123Srwatson		return (error);
3587102123Srwatson
3588102123Srwatson	error = ENOSYS;
3589102123Srwatson	MAC_POLICY_LIST_BUSY();
3590102123Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3591102123Srwatson		if (strcmp(mpc->mpc_name, target) == 0 &&
3592102123Srwatson		    mpc->mpc_ops->mpo_syscall != NULL) {
3593102123Srwatson			error = mpc->mpc_ops->mpo_syscall(td,
3594102123Srwatson			    SCARG(uap, call), SCARG(uap, arg));
3595102123Srwatson			goto out;
3596102123Srwatson		}
3597102123Srwatson	}
3598102123Srwatson
3599102123Srwatsonout:
3600102123Srwatson	MAC_POLICY_LIST_UNBUSY();
3601102123Srwatson	return (error);
3602102123Srwatson}
3603102123Srwatson
3604100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3605100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3606100979Srwatson
3607100979Srwatson#else /* !MAC */
3608100979Srwatson
3609100979Srwatsonint
3610105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3611105694Srwatson{
3612105694Srwatson
3613105694Srwatson	return (ENOSYS);
3614105694Srwatson}
3615105694Srwatson
3616105694Srwatsonint
3617100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3618100979Srwatson{
3619100979Srwatson
3620100894Srwatson	return (ENOSYS);
3621100894Srwatson}
3622100894Srwatson
3623100894Srwatsonint
3624100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3625100894Srwatson{
3626100894Srwatson
3627100894Srwatson	return (ENOSYS);
3628100894Srwatson}
3629100894Srwatson
3630100894Srwatsonint
3631100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3632100894Srwatson{
3633100894Srwatson
3634100894Srwatson	return (ENOSYS);
3635100894Srwatson}
3636100894Srwatson
3637100894Srwatsonint
3638100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3639100894Srwatson{
3640100894Srwatson
3641100894Srwatson	return (ENOSYS);
3642100894Srwatson}
3643100894Srwatson
3644100894Srwatsonint
3645105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3646105694Srwatson{
3647105694Srwatson
3648105694Srwatson	return (ENOSYS);
3649105694Srwatson}
3650105694Srwatson
3651105694Srwatsonint
3652100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3653100894Srwatson{
3654100894Srwatson
3655100894Srwatson	return (ENOSYS);
3656100894Srwatson}
3657100894Srwatson
3658100894Srwatsonint
3659100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3660100894Srwatson{
3661100894Srwatson
3662100894Srwatson	return (ENOSYS);
3663100894Srwatson}
3664100979Srwatson
3665102123Srwatsonint
3666105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3667105694Srwatson{
3668105694Srwatson
3669105694Srwatson	return (ENOSYS);
3670105694Srwatson}
3671105694Srwatson
3672105694Srwatsonint
3673102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3674102123Srwatson{
3675102123Srwatson
3676102123Srwatson	return (ENOSYS);
3677102123Srwatson}
3678102123Srwatson
3679105694Srwatson#endif
3680