mac_framework.c revision 116182
1100894Srwatson/*-
2100894Srwatson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3100894Srwatson * Copyright (c) 2001 Ilmar S. Habibulin
4113681Srwatson * Copyright (c) 2001, 2002, 2003 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 */
36116182Sobrien
37100894Srwatson/*
38100894Srwatson * Framework for extensible kernel access control.  Kernel and userland
39100894Srwatson * interface to the framework, policy registration and composition.
40100894Srwatson */
41100894Srwatson
42116182Sobrien#include <sys/cdefs.h>
43116182Sobrien__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 116182 2003-06-11 00:56:59Z obrien $");
44116182Sobrien
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
101114846Srwatson#if MAC_MAX_SLOTS > 32
102114846Srwatson#error "MAC_MAX_SLOTS too large"
103100979Srwatson#endif
104105497Srwatson
105114846Srwatsonstatic unsigned int mac_max_slots = MAC_MAX_SLOTS;
106114846Srwatsonstatic unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
107114846SrwatsonSYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
108114846Srwatson    &mac_max_slots, 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
123113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
124113487Srwatson/*
125113487Srwatson * Flag to indicate whether or not we should allocate label storage for
126113487Srwatson * new mbufs.  Since most dynamic policies we currently work with don't
127113487Srwatson * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
128113487Srwatson * unless specifically notified of interest.  One result of this is
129113487Srwatson * that if a dynamically loaded policy requests mbuf labels, it must
130113487Srwatson * be able to deal with a NULL label being returned on any mbufs that
131113487Srwatson * were already in flight when the policy was loaded.  Since the policy
132113487Srwatson * already has to deal with uninitialized labels, this probably won't
133113487Srwatson * be a problem.  Note: currently no locking.  Will this be a problem?
134113487Srwatson */
135113487Srwatsonstatic int	mac_labelmbufs = 0;
136113487Srwatson#endif
137113487Srwatson
138100979Srwatsonstatic int	mac_enforce_fs = 1;
139100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
140100979Srwatson    &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
141100979SrwatsonTUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
142100979Srwatson
143107089Srwatsonstatic int	mac_enforce_kld = 1;
144107089SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
145107089Srwatson    &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
146107089SrwatsonTUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
147107089Srwatson
148100979Srwatsonstatic int	mac_enforce_network = 1;
149100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
150100979Srwatson    &mac_enforce_network, 0, "Enforce MAC policy on network packets");
151100979SrwatsonTUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
152100979Srwatson
153103513Srwatsonstatic int	mac_enforce_pipe = 1;
154103513SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
155103513Srwatson    &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
156104236SrwatsonTUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
157103513Srwatson
158100979Srwatsonstatic int	mac_enforce_process = 1;
159100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
160100979Srwatson    &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
161100979SrwatsonTUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
162100979Srwatson
163100979Srwatsonstatic int	mac_enforce_socket = 1;
164100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
165100979Srwatson    &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
166100979SrwatsonTUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
167100979Srwatson
168106045Srwatsonstatic int	mac_enforce_system = 1;
169106045SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
170106045Srwatson    &mac_enforce_system, 0, "Enforce MAC policy on system operations");
171106045SrwatsonTUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
172106025Srwatson
173106045Srwatsonstatic int	mac_enforce_vm = 1;
174103514SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
175103514Srwatson    &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
176104236SrwatsonTUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
177103514Srwatson
178103136Srwatsonstatic int	mac_mmap_revocation = 1;
179103136SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
180103136Srwatson    &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
181103136Srwatson    "relabel");
182101892Srwatsonstatic int	mac_mmap_revocation_via_cow = 0;
183100979SrwatsonSYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
184100979Srwatson    &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
185100979Srwatson    "copy-on-write semantics, or by removing all write access");
186100979Srwatson
187101988Srwatson#ifdef MAC_DEBUG
188104268SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
189104268Srwatson    "TrustedBSD MAC debug info");
190104268Srwatson
191104268Srwatsonstatic int	mac_debug_label_fallback = 0;
192104268SrwatsonSYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
193104268Srwatson    &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
194104268Srwatson    "when label is corrupted.");
195104268SrwatsonTUNABLE_INT("security.mac.debug_label_fallback",
196104268Srwatson    &mac_debug_label_fallback);
197104268Srwatson
198104517SrwatsonSYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
199104517Srwatson    "TrustedBSD MAC object counters");
200104517Srwatson
201100979Srwatsonstatic unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
202100979Srwatson    nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
203107105Srwatson    nmacipqs, nmacpipes, nmacprocs;
204104517Srwatson
205104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
206100979Srwatson    &nmacmbufs, 0, "number of mbufs in use");
207104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
208100979Srwatson    &nmaccreds, 0, "number of ucreds in use");
209104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
210100979Srwatson    &nmacifnets, 0, "number of ifnets in use");
211104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
212100979Srwatson    &nmacipqs, 0, "number of ipqs in use");
213104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
214100979Srwatson    &nmacbpfdescs, 0, "number of bpfdescs in use");
215104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
216100979Srwatson    &nmacsockets, 0, "number of sockets in use");
217104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
218100979Srwatson    &nmacpipes, 0, "number of pipes in use");
219107105SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
220107105Srwatson    &nmacprocs, 0, "number of procs in use");
221104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
222100979Srwatson    &nmacmounts, 0, "number of mounts in use");
223104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
224100979Srwatson    &nmactemp, 0, "number of temporary labels in use");
225104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
226100979Srwatson    &nmacvnodes, 0, "number of vnodes in use");
227104517SrwatsonSYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
228100979Srwatson    &nmacdevfsdirents, 0, "number of devfs dirents inuse");
229101988Srwatson#endif
230100979Srwatson
231100979Srwatsonstatic int	error_select(int error1, int error2);
232100979Srwatsonstatic int	mac_policy_register(struct mac_policy_conf *mpc);
233100979Srwatsonstatic int	mac_policy_unregister(struct mac_policy_conf *mpc);
234100979Srwatson
235104546Srwatsonstatic void	mac_check_vnode_mmap_downgrade(struct ucred *cred,
236104546Srwatson		    struct vnode *vp, int *prot);
237100979Srwatsonstatic void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
238100979Srwatson		    struct ucred *cred, struct vm_map *map);
239100979Srwatson
240104541Srwatsonstatic void	mac_destroy_socket_label(struct label *label);
241104541Srwatson
242105988Srwatsonstatic int	mac_setlabel_vnode_extattr(struct ucred *cred,
243105988Srwatson		    struct vnode *vp, struct label *intlabel);
244105988Srwatson
245100979SrwatsonMALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
246105694SrwatsonMALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
247100979Srwatson
248100979Srwatson/*
249114806Srwatson * mac_static_policy_list holds a list of policy modules that are not
250114806Srwatson * loaded while the system is "live", and cannot be unloaded.  These
251114806Srwatson * policies can be invoked without holding the busy count.
252114806Srwatson *
253114806Srwatson * mac_policy_list stores the list of dynamic policies.  A busy count is
254106856Srwatson * maintained for the list, stored in mac_policy_busy.  The busy count
255114806Srwatson * is protected by mac_policy_mtx; the list may be modified only
256106856Srwatson * while the busy count is 0, requiring that the lock be held to
257106856Srwatson * prevent new references to the list from being acquired.  For almost
258106856Srwatson * all operations, incrementing the busy count is sufficient to
259106856Srwatson * guarantee consistency, as the list cannot be modified while the
260106856Srwatson * busy count is elevated.  For a few special operations involving a
261114806Srwatson * change to the list of active policies, the mtx itself must be held.
262114806Srwatson * A condition variable, mac_policy_cv, is used to signal potential
263114806Srwatson * exclusive consumers that they should try to acquire the lock if a
264114806Srwatson * first attempt at exclusive access fails.
265100979Srwatson */
266114806Srwatsonstatic struct mtx mac_policy_mtx;
267114806Srwatsonstatic struct cv mac_policy_cv;
268114806Srwatsonstatic int mac_policy_count;
269100979Srwatsonstatic LIST_HEAD(, mac_policy_conf) mac_policy_list;
270114806Srwatsonstatic LIST_HEAD(, mac_policy_conf) mac_static_policy_list;
271100979Srwatson
272106856Srwatson/*
273111883Sjhb * We manually invoke WITNESS_WARN() to allow Witness to generate
274106856Srwatson * warnings even if we don't end up ever triggering the wait at
275106856Srwatson * run-time.  The consumer of the exclusive interface must not hold
276106856Srwatson * any locks (other than potentially Giant) since we may sleep for
277106856Srwatson * long (potentially indefinite) periods of time waiting for the
278106856Srwatson * framework to become quiescent so that a policy list change may
279106856Srwatson * be made.
280106856Srwatson */
281114806Srwatsonstatic __inline void
282114806Srwatsonmac_policy_grab_exclusive(void)
283114806Srwatson{
284114806Srwatson	WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
285114806Srwatson 	    "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
286114806Srwatson	mtx_lock(&mac_policy_mtx);
287114806Srwatson	while (mac_policy_count != 0)
288114806Srwatson		cv_wait(&mac_policy_cv, &mac_policy_mtx);
289114806Srwatson}
290106856Srwatson
291114806Srwatsonstatic __inline void
292114806Srwatsonmac_policy_assert_exclusive(void)
293114806Srwatson{
294114806Srwatson	mtx_assert(&mac_policy_mtx, MA_OWNED);
295114806Srwatson	KASSERT(mac_policy_count == 0,
296114806Srwatson	    ("mac_policy_assert_exclusive(): not exclusive"));
297114806Srwatson}
298113487Srwatson
299114806Srwatsonstatic __inline void
300114806Srwatsonmac_policy_release_exclusive(void)
301114806Srwatson{
302100979Srwatson
303114806Srwatson	KASSERT(mac_policy_count == 0,
304114806Srwatson	    ("mac_policy_release_exclusive(): not exclusive"));
305114806Srwatson	mtx_unlock(&mac_policy_mtx);
306114806Srwatson	cv_signal(&mac_policy_cv);
307114806Srwatson}
308100979Srwatson
309114806Srwatsonstatic __inline void
310114806Srwatsonmac_policy_list_busy(void)
311114806Srwatson{
312114806Srwatson	mtx_lock(&mac_policy_mtx);
313114806Srwatson	mac_policy_count++;
314114806Srwatson	mtx_unlock(&mac_policy_mtx);
315114806Srwatson}
316114806Srwatson
317114806Srwatsonstatic __inline int
318114806Srwatsonmac_policy_list_conditional_busy(void)
319114806Srwatson{
320114806Srwatson	int ret;
321114806Srwatson
322114806Srwatson	mtx_lock(&mac_policy_mtx);
323114806Srwatson	if (!LIST_EMPTY(&mac_policy_list)) {
324114806Srwatson		mac_policy_count++;
325114806Srwatson		ret = 1;
326114806Srwatson	} else
327114806Srwatson		ret = 0;
328114806Srwatson	mtx_unlock(&mac_policy_mtx);
329114806Srwatson	return (ret);
330114806Srwatson}
331114806Srwatson
332114806Srwatsonstatic __inline void
333114806Srwatsonmac_policy_list_unbusy(void)
334114806Srwatson{
335114806Srwatson	mtx_lock(&mac_policy_mtx);
336114806Srwatson	mac_policy_count--;
337114806Srwatson	KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
338114806Srwatson	if (mac_policy_count == 0)
339114806Srwatson		cv_signal(&mac_policy_cv);
340114806Srwatson	mtx_unlock(&mac_policy_mtx);
341114806Srwatson}
342114806Srwatson
343100979Srwatson/*
344100979Srwatson * MAC_CHECK performs the designated check by walking the policy
345100979Srwatson * module list and checking with each as to how it feels about the
346100979Srwatson * request.  Note that it returns its value via 'error' in the scope
347100979Srwatson * of the caller.
348100979Srwatson */
349100979Srwatson#define	MAC_CHECK(check, args...) do {					\
350100979Srwatson	struct mac_policy_conf *mpc;					\
351114806Srwatson	int entrycount;							\
352100979Srwatson									\
353100979Srwatson	error = 0;							\
354114806Srwatson	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
355100979Srwatson		if (mpc->mpc_ops->mpo_ ## check != NULL)		\
356100979Srwatson			error = error_select(				\
357100979Srwatson			    mpc->mpc_ops->mpo_ ## check (args),		\
358100979Srwatson			    error);					\
359100979Srwatson	}								\
360114806Srwatson	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
361114806Srwatson		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
362114806Srwatson			if (mpc->mpc_ops->mpo_ ## check != NULL)	\
363114806Srwatson				error = error_select(			\
364114806Srwatson				    mpc->mpc_ops->mpo_ ## check (args),	\
365114806Srwatson				    error);				\
366114806Srwatson		}							\
367114806Srwatson		mac_policy_list_unbusy();				\
368114806Srwatson	}								\
369100979Srwatson} while (0)
370100979Srwatson
371100979Srwatson/*
372100979Srwatson * MAC_BOOLEAN performs the designated boolean composition by walking
373100979Srwatson * the module list, invoking each instance of the operation, and
374100979Srwatson * combining the results using the passed C operator.  Note that it
375100979Srwatson * returns its value via 'result' in the scope of the caller, which
376100979Srwatson * should be initialized by the caller in a meaningful way to get
377100979Srwatson * a meaningful result.
378100979Srwatson */
379100979Srwatson#define	MAC_BOOLEAN(operation, composition, args...) do {		\
380100979Srwatson	struct mac_policy_conf *mpc;					\
381114806Srwatson	int entrycount;							\
382100979Srwatson									\
383114806Srwatson	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
384100979Srwatson		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
385100979Srwatson			result = result composition			\
386100979Srwatson			    mpc->mpc_ops->mpo_ ## operation (args);	\
387100979Srwatson	}								\
388114806Srwatson	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
389114806Srwatson		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
390114806Srwatson			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
391114806Srwatson				result = result composition		\
392114806Srwatson				    mpc->mpc_ops->mpo_ ## operation	\
393114806Srwatson				    (args);				\
394114806Srwatson		}							\
395114806Srwatson		mac_policy_list_unbusy();				\
396114806Srwatson	}								\
397100979Srwatson} while (0)
398100979Srwatson
399105694Srwatson#define	MAC_EXTERNALIZE(type, label, elementlist, outbuf, 		\
400105694Srwatson    outbuflen) do {							\
401105694Srwatson	char *curptr, *curptr_start, *element_name, *element_temp;	\
402105694Srwatson	size_t left, left_start, len;					\
403105694Srwatson	int claimed, first, first_start, ignorenotfound;		\
404105694Srwatson									\
405105694Srwatson	error = 0;							\
406105694Srwatson	element_temp = elementlist;					\
407105694Srwatson	curptr = outbuf;						\
408105694Srwatson	curptr[0] = '\0';						\
409105694Srwatson	left = outbuflen;						\
410105694Srwatson	first = 1;							\
411105694Srwatson	while ((element_name = strsep(&element_temp, ",")) != NULL) {	\
412105694Srwatson		curptr_start = curptr;					\
413105694Srwatson		left_start = left;					\
414105694Srwatson		first_start = first;					\
415105694Srwatson		if (element_name[0] == '?') {				\
416105694Srwatson			element_name++;					\
417105694Srwatson			ignorenotfound = 1;				\
418105694Srwatson		} else							\
419105694Srwatson			ignorenotfound = 0;				\
420105694Srwatson		claimed = 0;						\
421105694Srwatson		if (first) {						\
422105694Srwatson			len = snprintf(curptr, left, "%s/",		\
423105694Srwatson			    element_name);				\
424105694Srwatson			first = 0;					\
425105694Srwatson		} else							\
426105694Srwatson			len = snprintf(curptr, left, ",%s/",		\
427105694Srwatson			    element_name);				\
428105694Srwatson		if (len >= left) {					\
429105694Srwatson			error = EINVAL;		/* XXXMAC: E2BIG */	\
430105694Srwatson			break;						\
431105694Srwatson		}							\
432105694Srwatson		curptr += len;						\
433105694Srwatson		left -= len;						\
434105694Srwatson									\
435105694Srwatson		MAC_CHECK(externalize_ ## type, label, element_name,	\
436105694Srwatson		    curptr, left, &len, &claimed);			\
437105694Srwatson		if (error)						\
438105694Srwatson			break;						\
439105694Srwatson		if (claimed == 1) {					\
440105694Srwatson			if (len >= outbuflen) {				\
441105694Srwatson				error = EINVAL;	/* XXXMAC: E2BIG */	\
442105694Srwatson				break;					\
443105694Srwatson			}						\
444105694Srwatson			curptr += len;					\
445105694Srwatson			left -= len;					\
446105694Srwatson		} else if (claimed == 0 && ignorenotfound) {		\
447105694Srwatson			/*						\
448105694Srwatson			 * Revert addition of the label element		\
449105694Srwatson			 * name.					\
450105694Srwatson			 */						\
451105694Srwatson			curptr = curptr_start;				\
452105694Srwatson			*curptr = '\0';					\
453105694Srwatson			left = left_start;				\
454105694Srwatson			first = first_start;				\
455105694Srwatson		} else {						\
456105694Srwatson			error = EINVAL;		/* XXXMAC: ENOLABEL */	\
457105694Srwatson			break;						\
458105694Srwatson		}							\
459105694Srwatson	}								\
460105694Srwatson} while (0)
461105694Srwatson
462105694Srwatson#define	MAC_INTERNALIZE(type, label, instring) do {			\
463105694Srwatson	char *element, *element_name, *element_data;			\
464105694Srwatson	int claimed;							\
465105694Srwatson									\
466105694Srwatson	error = 0;							\
467105694Srwatson	element = instring;						\
468105694Srwatson	while ((element_name = strsep(&element, ",")) != NULL) {	\
469105694Srwatson		element_data = element_name;				\
470105694Srwatson		element_name = strsep(&element_data, "/");		\
471105694Srwatson		if (element_data == NULL) {				\
472105694Srwatson			error = EINVAL;					\
473105694Srwatson			break;						\
474105694Srwatson		}							\
475105694Srwatson		claimed = 0;						\
476105694Srwatson		MAC_CHECK(internalize_ ## type, label, element_name,	\
477105694Srwatson		    element_data, &claimed);				\
478105694Srwatson		if (error)						\
479105694Srwatson			break;						\
480105694Srwatson		if (claimed != 1) {					\
481105694Srwatson			/* XXXMAC: Another error here? */		\
482105694Srwatson			error = EINVAL;					\
483105694Srwatson			break;						\
484105694Srwatson		}							\
485105694Srwatson	}								\
486105694Srwatson} while (0)
487105694Srwatson
488100979Srwatson/*
489100979Srwatson * MAC_PERFORM performs the designated operation by walking the policy
490100979Srwatson * module list and invoking that operation for each policy.
491100979Srwatson */
492100979Srwatson#define	MAC_PERFORM(operation, args...) do {				\
493100979Srwatson	struct mac_policy_conf *mpc;					\
494114806Srwatson	int entrycount;							\
495100979Srwatson									\
496114806Srwatson	LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {		\
497100979Srwatson		if (mpc->mpc_ops->mpo_ ## operation != NULL)		\
498100979Srwatson			mpc->mpc_ops->mpo_ ## operation (args);		\
499100979Srwatson	}								\
500114806Srwatson	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {	\
501114806Srwatson		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {		\
502114806Srwatson			if (mpc->mpc_ops->mpo_ ## operation != NULL)	\
503114806Srwatson				mpc->mpc_ops->mpo_ ## operation (args);	\
504114806Srwatson		}							\
505114806Srwatson		mac_policy_list_unbusy();				\
506114806Srwatson	}								\
507100979Srwatson} while (0)
508100979Srwatson
509100979Srwatson/*
510100979Srwatson * Initialize the MAC subsystem, including appropriate SMP locks.
511100979Srwatson */
512100979Srwatsonstatic void
513100979Srwatsonmac_init(void)
514100979Srwatson{
515100979Srwatson
516114806Srwatson	LIST_INIT(&mac_static_policy_list);
517100979Srwatson	LIST_INIT(&mac_policy_list);
518114806Srwatson
519114806Srwatson	mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
520114806Srwatson	cv_init(&mac_policy_cv, "mac_policy_cv");
521100979Srwatson}
522100979Srwatson
523100979Srwatson/*
524100979Srwatson * For the purposes of modules that want to know if they were loaded
525100979Srwatson * "early", set the mac_late flag once we've processed modules either
526100979Srwatson * linked into the kernel, or loaded before the kernel startup.
527100979Srwatson */
528100979Srwatsonstatic void
529100979Srwatsonmac_late_init(void)
530100979Srwatson{
531100979Srwatson
532100979Srwatson	mac_late = 1;
533100979Srwatson}
534100979Srwatson
535100979Srwatson/*
536113487Srwatson * After the policy list has changed, walk the list to update any global
537113487Srwatson * flags.
538113487Srwatson */
539113487Srwatsonstatic void
540113487Srwatsonmac_policy_updateflags(void)
541113487Srwatson{
542113487Srwatson	struct mac_policy_conf *tmpc;
543113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
544113487Srwatson	int labelmbufs;
545113487Srwatson#endif
546113487Srwatson
547114806Srwatson	mac_policy_assert_exclusive();
548113487Srwatson
549113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
550113487Srwatson	labelmbufs = 0;
551113487Srwatson#endif
552114806Srwatson
553114806Srwatson	LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
554114806Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
555114806Srwatson		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
556114806Srwatson			labelmbufs++;
557114806Srwatson#endif
558114806Srwatson	}
559113487Srwatson	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
560113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
561113487Srwatson		if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
562113487Srwatson			labelmbufs++;
563113487Srwatson#endif
564113487Srwatson	}
565113487Srwatson
566113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
567113487Srwatson	mac_labelmbufs = (labelmbufs != 0);
568113487Srwatson#endif
569113487Srwatson}
570113487Srwatson
571113487Srwatson/*
572100979Srwatson * Allow MAC policy modules to register during boot, etc.
573100979Srwatson */
574100894Srwatsonint
575100979Srwatsonmac_policy_modevent(module_t mod, int type, void *data)
576100979Srwatson{
577100979Srwatson	struct mac_policy_conf *mpc;
578100979Srwatson	int error;
579100979Srwatson
580100979Srwatson	error = 0;
581100979Srwatson	mpc = (struct mac_policy_conf *) data;
582100979Srwatson
583100979Srwatson	switch (type) {
584100979Srwatson	case MOD_LOAD:
585100979Srwatson		if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
586100979Srwatson		    mac_late) {
587100979Srwatson			printf("mac_policy_modevent: can't load %s policy "
588100979Srwatson			    "after booting\n", mpc->mpc_name);
589100979Srwatson			error = EBUSY;
590100979Srwatson			break;
591100979Srwatson		}
592100979Srwatson		error = mac_policy_register(mpc);
593100979Srwatson		break;
594100979Srwatson	case MOD_UNLOAD:
595100979Srwatson		/* Don't unregister the module if it was never registered. */
596100979Srwatson		if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
597100979Srwatson		    != 0)
598100979Srwatson			error = mac_policy_unregister(mpc);
599100979Srwatson		else
600100979Srwatson			error = 0;
601100979Srwatson		break;
602100979Srwatson	default:
603100979Srwatson		break;
604100979Srwatson	}
605100979Srwatson
606100979Srwatson	return (error);
607100979Srwatson}
608100979Srwatson
609100979Srwatsonstatic int
610100979Srwatsonmac_policy_register(struct mac_policy_conf *mpc)
611100979Srwatson{
612100979Srwatson	struct mac_policy_conf *tmpc;
613114806Srwatson	int error, slot, static_entry;
614100979Srwatson
615114806Srwatson	error = 0;
616114806Srwatson
617114806Srwatson	/*
618114806Srwatson	 * We don't technically need exclusive access while !mac_late,
619114806Srwatson	 * but hold it for assertion consistency.
620114806Srwatson	 */
621114806Srwatson	mac_policy_grab_exclusive();
622114806Srwatson
623114806Srwatson	/*
624114806Srwatson	 * If the module can potentially be unloaded, or we're loading
625114806Srwatson	 * late, we have to stick it in the non-static list and pay
626114806Srwatson	 * an extra performance overhead.  Otherwise, we can pay a
627114806Srwatson	 * light locking cost and stick it in the static list.
628114806Srwatson	 */
629114806Srwatson	static_entry = (!mac_late &&
630114806Srwatson	    !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
631114806Srwatson
632114806Srwatson	if (static_entry) {
633114806Srwatson		LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
634114806Srwatson			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
635114806Srwatson				error = EEXIST;
636114806Srwatson				goto out;
637114806Srwatson			}
638100979Srwatson		}
639114806Srwatson	} else {
640114806Srwatson		LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
641114806Srwatson			if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
642114806Srwatson				error = EEXIST;
643114806Srwatson				goto out;
644114806Srwatson			}
645114806Srwatson		}
646100979Srwatson	}
647100979Srwatson	if (mpc->mpc_field_off != NULL) {
648114846Srwatson		slot = ffs(mac_slot_offsets_free);
649100979Srwatson		if (slot == 0) {
650114806Srwatson			error = ENOMEM;
651114806Srwatson			goto out;
652100979Srwatson		}
653100979Srwatson		slot--;
654114846Srwatson		mac_slot_offsets_free &= ~(1 << slot);
655100979Srwatson		*mpc->mpc_field_off = slot;
656100979Srwatson	}
657100979Srwatson	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
658100979Srwatson
659114806Srwatson	/*
660114806Srwatson	 * If we're loading a MAC module after the framework has
661114806Srwatson	 * initialized, it has to go into the dynamic list.  If
662114806Srwatson	 * we're loading it before we've finished initializing,
663114806Srwatson	 * it can go into the static list with weaker locker
664114806Srwatson	 * requirements.
665114806Srwatson	 */
666114806Srwatson	if (static_entry)
667114806Srwatson		LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
668114806Srwatson	else
669114806Srwatson		LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
670114806Srwatson
671100979Srwatson	/* Per-policy initialization. */
672100979Srwatson	if (mpc->mpc_ops->mpo_init != NULL)
673100979Srwatson		(*(mpc->mpc_ops->mpo_init))(mpc);
674113487Srwatson	mac_policy_updateflags();
675100979Srwatson
676100979Srwatson	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
677100979Srwatson	    mpc->mpc_name);
678100979Srwatson
679114806Srwatsonout:
680114806Srwatson	mac_policy_release_exclusive();
681114806Srwatson	return (error);
682100979Srwatson}
683100979Srwatson
684100979Srwatsonstatic int
685100979Srwatsonmac_policy_unregister(struct mac_policy_conf *mpc)
686100979Srwatson{
687100979Srwatson
688104520Srwatson	/*
689104520Srwatson	 * If we fail the load, we may get a request to unload.  Check
690104520Srwatson	 * to see if we did the run-time registration, and if not,
691104520Srwatson	 * silently succeed.
692104520Srwatson	 */
693114806Srwatson	mac_policy_grab_exclusive();
694104520Srwatson	if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
695114806Srwatson		mac_policy_release_exclusive();
696104520Srwatson		return (0);
697104520Srwatson	}
698100979Srwatson#if 0
699100979Srwatson	/*
700100979Srwatson	 * Don't allow unloading modules with private data.
701100979Srwatson	 */
702104520Srwatson	if (mpc->mpc_field_off != NULL) {
703104520Srwatson		MAC_POLICY_LIST_UNLOCK();
704100979Srwatson		return (EBUSY);
705104520Srwatson	}
706100979Srwatson#endif
707104520Srwatson	/*
708104520Srwatson	 * Only allow the unload to proceed if the module is unloadable
709104520Srwatson	 * by its own definition.
710104520Srwatson	 */
711104520Srwatson	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
712114806Srwatson		mac_policy_release_exclusive();
713100979Srwatson		return (EBUSY);
714104520Srwatson	}
715100979Srwatson	if (mpc->mpc_ops->mpo_destroy != NULL)
716100979Srwatson		(*(mpc->mpc_ops->mpo_destroy))(mpc);
717100979Srwatson
718100979Srwatson	LIST_REMOVE(mpc, mpc_list);
719106856Srwatson	mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
720113487Srwatson	mac_policy_updateflags();
721100979Srwatson
722114806Srwatson	mac_policy_release_exclusive();
723114806Srwatson
724100979Srwatson	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
725100979Srwatson	    mpc->mpc_name);
726100979Srwatson
727100979Srwatson	return (0);
728100979Srwatson}
729100979Srwatson
730100979Srwatson/*
731100979Srwatson * Define an error value precedence, and given two arguments, selects the
732100979Srwatson * value with the higher precedence.
733100979Srwatson */
734100979Srwatsonstatic int
735100979Srwatsonerror_select(int error1, int error2)
736100979Srwatson{
737100979Srwatson
738100979Srwatson	/* Certain decision-making errors take top priority. */
739100979Srwatson	if (error1 == EDEADLK || error2 == EDEADLK)
740100979Srwatson		return (EDEADLK);
741100979Srwatson
742100979Srwatson	/* Invalid arguments should be reported where possible. */
743100979Srwatson	if (error1 == EINVAL || error2 == EINVAL)
744100979Srwatson		return (EINVAL);
745100979Srwatson
746100979Srwatson	/* Precedence goes to "visibility", with both process and file. */
747100979Srwatson	if (error1 == ESRCH || error2 == ESRCH)
748100979Srwatson		return (ESRCH);
749100979Srwatson
750100979Srwatson	if (error1 == ENOENT || error2 == ENOENT)
751100979Srwatson		return (ENOENT);
752100979Srwatson
753100979Srwatson	/* Precedence goes to DAC/MAC protections. */
754100979Srwatson	if (error1 == EACCES || error2 == EACCES)
755100979Srwatson		return (EACCES);
756100979Srwatson
757100979Srwatson	/* Precedence goes to privilege. */
758100979Srwatson	if (error1 == EPERM || error2 == EPERM)
759100979Srwatson		return (EPERM);
760100979Srwatson
761100979Srwatson	/* Precedence goes to error over success; otherwise, arbitrary. */
762100979Srwatson	if (error1 != 0)
763100979Srwatson		return (error1);
764100979Srwatson	return (error2);
765100979Srwatson}
766100979Srwatson
767113482Srwatsonstatic struct label *
768113482Srwatsonmbuf_to_label(struct mbuf *mbuf)
769113482Srwatson{
770113487Srwatson	struct m_tag *tag;
771113482Srwatson	struct label *label;
772113482Srwatson
773113487Srwatson	tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
774113487Srwatson	label = (struct label *)(tag+1);
775113482Srwatson
776113482Srwatson	return (label);
777113482Srwatson}
778113482Srwatson
779104521Srwatsonstatic void
780104521Srwatsonmac_init_label(struct label *label)
781104521Srwatson{
782104521Srwatson
783104521Srwatson	bzero(label, sizeof(*label));
784104521Srwatson	label->l_flags = MAC_FLAG_INITIALIZED;
785104521Srwatson}
786104521Srwatson
787104521Srwatsonstatic void
788104521Srwatsonmac_destroy_label(struct label *label)
789104521Srwatson{
790104521Srwatson
791104521Srwatson	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
792104521Srwatson	    ("destroying uninitialized label"));
793104521Srwatson
794104521Srwatson	bzero(label, sizeof(*label));
795104521Srwatson	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
796104521Srwatson}
797104521Srwatson
798100979Srwatsonvoid
799104527Srwatsonmac_init_bpfdesc(struct bpf_d *bpf_d)
800104521Srwatson{
801104521Srwatson
802104527Srwatson	mac_init_label(&bpf_d->bd_label);
803104527Srwatson	MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
804104521Srwatson#ifdef MAC_DEBUG
805104527Srwatson	atomic_add_int(&nmacbpfdescs, 1);
806104521Srwatson#endif
807104521Srwatson}
808104521Srwatson
809105694Srwatsonstatic void
810105694Srwatsonmac_init_cred_label(struct label *label)
811104521Srwatson{
812104521Srwatson
813105694Srwatson	mac_init_label(label);
814105694Srwatson	MAC_PERFORM(init_cred_label, label);
815104521Srwatson#ifdef MAC_DEBUG
816104521Srwatson	atomic_add_int(&nmaccreds, 1);
817104521Srwatson#endif
818104521Srwatson}
819104521Srwatson
820104521Srwatsonvoid
821105694Srwatsonmac_init_cred(struct ucred *cred)
822105694Srwatson{
823105694Srwatson
824105694Srwatson	mac_init_cred_label(&cred->cr_label);
825105694Srwatson}
826105694Srwatson
827105694Srwatsonvoid
828104527Srwatsonmac_init_devfsdirent(struct devfs_dirent *de)
829104521Srwatson{
830104521Srwatson
831104527Srwatson	mac_init_label(&de->de_label);
832104527Srwatson	MAC_PERFORM(init_devfsdirent_label, &de->de_label);
833104521Srwatson#ifdef MAC_DEBUG
834104527Srwatson	atomic_add_int(&nmacdevfsdirents, 1);
835104521Srwatson#endif
836104521Srwatson}
837104521Srwatson
838105694Srwatsonstatic void
839105694Srwatsonmac_init_ifnet_label(struct label *label)
840104521Srwatson{
841104521Srwatson
842105694Srwatson	mac_init_label(label);
843105694Srwatson	MAC_PERFORM(init_ifnet_label, label);
844104521Srwatson#ifdef MAC_DEBUG
845104521Srwatson	atomic_add_int(&nmacifnets, 1);
846104521Srwatson#endif
847104521Srwatson}
848104521Srwatson
849104521Srwatsonvoid
850105694Srwatsonmac_init_ifnet(struct ifnet *ifp)
851105694Srwatson{
852105694Srwatson
853105694Srwatson	mac_init_ifnet_label(&ifp->if_label);
854105694Srwatson}
855105694Srwatson
856112675Srwatsonint
857112675Srwatsonmac_init_ipq(struct ipq *ipq, int flag)
858104521Srwatson{
859112675Srwatson	int error;
860104521Srwatson
861104527Srwatson	mac_init_label(&ipq->ipq_label);
862112675Srwatson
863112675Srwatson	MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
864112675Srwatson	if (error) {
865112675Srwatson		MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
866112675Srwatson		mac_destroy_label(&ipq->ipq_label);
867112675Srwatson	}
868104521Srwatson#ifdef MAC_DEBUG
869112675Srwatson	if (error == 0)
870112675Srwatson		atomic_add_int(&nmacipqs, 1);
871104521Srwatson#endif
872112675Srwatson	return (error);
873104521Srwatson}
874104521Srwatson
875104527Srwatsonint
876113487Srwatsonmac_init_mbuf_tag(struct m_tag *tag, int flag)
877104527Srwatson{
878113487Srwatson	struct label *label;
879113526Srwatson	int error;
880104528Srwatson
881113487Srwatson	label = (struct label *) (tag + 1);
882113487Srwatson	mac_init_label(label);
883104527Srwatson
884113526Srwatson	MAC_CHECK(init_mbuf_label, label, flag);
885104528Srwatson	if (error) {
886113487Srwatson		MAC_PERFORM(destroy_mbuf_label, label);
887113487Srwatson		mac_destroy_label(label);
888104528Srwatson	}
889104527Srwatson#ifdef MAC_DEBUG
890104528Srwatson	if (error == 0)
891104528Srwatson		atomic_add_int(&nmacmbufs, 1);
892104527Srwatson#endif
893104528Srwatson	return (error);
894104527Srwatson}
895104527Srwatson
896113487Srwatsonint
897113487Srwatsonmac_init_mbuf(struct mbuf *m, int flag)
898113487Srwatson{
899113487Srwatson	struct m_tag *tag;
900113487Srwatson	int error;
901113487Srwatson
902113487Srwatson	M_ASSERTPKTHDR(m);
903113487Srwatson
904113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
905113487Srwatson	/*
906113487Srwatson	 * Don't reserve space for labels on mbufs unless we have a policy
907113487Srwatson	 * that uses the labels.
908113487Srwatson	 */
909113487Srwatson	if (mac_labelmbufs) {
910113487Srwatson#endif
911113487Srwatson		tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
912113487Srwatson		    flag);
913113487Srwatson		if (tag == NULL)
914113487Srwatson			return (ENOMEM);
915113487Srwatson		error = mac_init_mbuf_tag(tag, flag);
916113487Srwatson		if (error) {
917113487Srwatson			m_tag_free(tag);
918113487Srwatson			return (error);
919113487Srwatson		}
920113487Srwatson		m_tag_prepend(m, tag);
921113487Srwatson#ifndef MAC_ALWAYS_LABEL_MBUF
922113487Srwatson	}
923113487Srwatson#endif
924113487Srwatson	return (0);
925113487Srwatson}
926113487Srwatson
927104521Srwatsonvoid
928104527Srwatsonmac_init_mount(struct mount *mp)
929104521Srwatson{
930104521Srwatson
931104527Srwatson	mac_init_label(&mp->mnt_mntlabel);
932104527Srwatson	mac_init_label(&mp->mnt_fslabel);
933104527Srwatson	MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
934104527Srwatson	MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
935104521Srwatson#ifdef MAC_DEBUG
936104527Srwatson	atomic_add_int(&nmacmounts, 1);
937104521Srwatson#endif
938104521Srwatson}
939104521Srwatson
940105694Srwatsonstatic void
941105694Srwatsonmac_init_pipe_label(struct label *label)
942105694Srwatson{
943105694Srwatson
944105694Srwatson	mac_init_label(label);
945105694Srwatson	MAC_PERFORM(init_pipe_label, label);
946105694Srwatson#ifdef MAC_DEBUG
947105694Srwatson	atomic_add_int(&nmacpipes, 1);
948105694Srwatson#endif
949105694Srwatson}
950105694Srwatson
951104521Srwatsonvoid
952104527Srwatsonmac_init_pipe(struct pipe *pipe)
953104521Srwatson{
954104527Srwatson	struct label *label;
955104521Srwatson
956111119Simp	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
957104527Srwatson	pipe->pipe_label = label;
958104527Srwatson	pipe->pipe_peer->pipe_label = label;
959105694Srwatson	mac_init_pipe_label(label);
960104521Srwatson}
961104521Srwatson
962107105Srwatsonvoid
963107105Srwatsonmac_init_proc(struct proc *p)
964107105Srwatson{
965107105Srwatson
966107105Srwatson	mac_init_label(&p->p_label);
967107105Srwatson	MAC_PERFORM(init_proc_label, &p->p_label);
968107105Srwatson#ifdef MAC_DEBUG
969107105Srwatson	atomic_add_int(&nmacprocs, 1);
970107105Srwatson#endif
971107105Srwatson}
972107105Srwatson
973104541Srwatsonstatic int
974104541Srwatsonmac_init_socket_label(struct label *label, int flag)
975104521Srwatson{
976104541Srwatson	int error;
977104521Srwatson
978104541Srwatson	mac_init_label(label);
979104541Srwatson
980104541Srwatson	MAC_CHECK(init_socket_label, label, flag);
981104541Srwatson	if (error) {
982104541Srwatson		MAC_PERFORM(destroy_socket_label, label);
983104541Srwatson		mac_destroy_label(label);
984104541Srwatson	}
985104541Srwatson
986104521Srwatson#ifdef MAC_DEBUG
987104541Srwatson	if (error == 0)
988104541Srwatson		atomic_add_int(&nmacsockets, 1);
989104521Srwatson#endif
990104541Srwatson
991104541Srwatson	return (error);
992104521Srwatson}
993104521Srwatson
994104541Srwatsonstatic int
995104541Srwatsonmac_init_socket_peer_label(struct label *label, int flag)
996104541Srwatson{
997104541Srwatson	int error;
998104541Srwatson
999104541Srwatson	mac_init_label(label);
1000104541Srwatson
1001104541Srwatson	MAC_CHECK(init_socket_peer_label, label, flag);
1002104541Srwatson	if (error) {
1003104541Srwatson		MAC_PERFORM(destroy_socket_label, label);
1004104541Srwatson		mac_destroy_label(label);
1005104541Srwatson	}
1006104541Srwatson
1007104541Srwatson	return (error);
1008104541Srwatson}
1009104541Srwatson
1010104541Srwatsonint
1011104541Srwatsonmac_init_socket(struct socket *socket, int flag)
1012104541Srwatson{
1013104541Srwatson	int error;
1014104541Srwatson
1015104541Srwatson	error = mac_init_socket_label(&socket->so_label, flag);
1016104541Srwatson	if (error)
1017104541Srwatson		return (error);
1018104541Srwatson
1019104541Srwatson	error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1020104541Srwatson	if (error)
1021104541Srwatson		mac_destroy_socket_label(&socket->so_label);
1022104541Srwatson
1023104541Srwatson	return (error);
1024104541Srwatson}
1025104541Srwatson
1026105988Srwatsonvoid
1027105694Srwatsonmac_init_vnode_label(struct label *label)
1028104521Srwatson{
1029104521Srwatson
1030104527Srwatson	mac_init_label(label);
1031105694Srwatson	MAC_PERFORM(init_vnode_label, label);
1032104521Srwatson#ifdef MAC_DEBUG
1033105694Srwatson	atomic_add_int(&nmacvnodes, 1);
1034104521Srwatson#endif
1035104521Srwatson}
1036104521Srwatson
1037104521Srwatsonvoid
1038104527Srwatsonmac_init_vnode(struct vnode *vp)
1039104521Srwatson{
1040104521Srwatson
1041105694Srwatson	mac_init_vnode_label(&vp->v_label);
1042104521Srwatson}
1043104521Srwatson
1044104521Srwatsonvoid
1045104527Srwatsonmac_destroy_bpfdesc(struct bpf_d *bpf_d)
1046104521Srwatson{
1047104521Srwatson
1048104527Srwatson	MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1049104527Srwatson	mac_destroy_label(&bpf_d->bd_label);
1050104521Srwatson#ifdef MAC_DEBUG
1051104527Srwatson	atomic_subtract_int(&nmacbpfdescs, 1);
1052104521Srwatson#endif
1053104521Srwatson}
1054104521Srwatson
1055105694Srwatsonstatic void
1056105694Srwatsonmac_destroy_cred_label(struct label *label)
1057104521Srwatson{
1058104521Srwatson
1059105694Srwatson	MAC_PERFORM(destroy_cred_label, label);
1060105694Srwatson	mac_destroy_label(label);
1061104521Srwatson#ifdef MAC_DEBUG
1062104527Srwatson	atomic_subtract_int(&nmaccreds, 1);
1063104521Srwatson#endif
1064104521Srwatson}
1065104521Srwatson
1066104521Srwatsonvoid
1067105694Srwatsonmac_destroy_cred(struct ucred *cred)
1068105694Srwatson{
1069105694Srwatson
1070105694Srwatson	mac_destroy_cred_label(&cred->cr_label);
1071105694Srwatson}
1072105694Srwatson
1073105694Srwatsonvoid
1074104527Srwatsonmac_destroy_devfsdirent(struct devfs_dirent *de)
1075104521Srwatson{
1076104521Srwatson
1077104527Srwatson	MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1078104527Srwatson	mac_destroy_label(&de->de_label);
1079104521Srwatson#ifdef MAC_DEBUG
1080104527Srwatson	atomic_subtract_int(&nmacdevfsdirents, 1);
1081104521Srwatson#endif
1082104521Srwatson}
1083104521Srwatson
1084105694Srwatsonstatic void
1085105694Srwatsonmac_destroy_ifnet_label(struct label *label)
1086104521Srwatson{
1087104521Srwatson
1088105694Srwatson	MAC_PERFORM(destroy_ifnet_label, label);
1089105694Srwatson	mac_destroy_label(label);
1090104521Srwatson#ifdef MAC_DEBUG
1091104527Srwatson	atomic_subtract_int(&nmacifnets, 1);
1092104521Srwatson#endif
1093104521Srwatson}
1094104521Srwatson
1095104521Srwatsonvoid
1096105694Srwatsonmac_destroy_ifnet(struct ifnet *ifp)
1097105694Srwatson{
1098105694Srwatson
1099105694Srwatson	mac_destroy_ifnet_label(&ifp->if_label);
1100105694Srwatson}
1101105694Srwatson
1102105694Srwatsonvoid
1103104527Srwatsonmac_destroy_ipq(struct ipq *ipq)
1104104521Srwatson{
1105104521Srwatson
1106104527Srwatson	MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1107104527Srwatson	mac_destroy_label(&ipq->ipq_label);
1108104521Srwatson#ifdef MAC_DEBUG
1109104527Srwatson	atomic_subtract_int(&nmacipqs, 1);
1110104521Srwatson#endif
1111104521Srwatson}
1112104521Srwatson
1113104527Srwatsonvoid
1114113487Srwatsonmac_destroy_mbuf_tag(struct m_tag *tag)
1115104521Srwatson{
1116113487Srwatson	struct label *label;
1117104521Srwatson
1118113487Srwatson	label = (struct label *)(tag+1);
1119113487Srwatson
1120113487Srwatson	MAC_PERFORM(destroy_mbuf_label, label);
1121113487Srwatson	mac_destroy_label(label);
1122104521Srwatson#ifdef MAC_DEBUG
1123104527Srwatson	atomic_subtract_int(&nmacmbufs, 1);
1124104521Srwatson#endif
1125104521Srwatson}
1126104521Srwatson
1127104527Srwatsonvoid
1128104527Srwatsonmac_destroy_mount(struct mount *mp)
1129104521Srwatson{
1130104521Srwatson
1131104527Srwatson	MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1132104527Srwatson	MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1133104527Srwatson	mac_destroy_label(&mp->mnt_fslabel);
1134104527Srwatson	mac_destroy_label(&mp->mnt_mntlabel);
1135104521Srwatson#ifdef MAC_DEBUG
1136104527Srwatson	atomic_subtract_int(&nmacmounts, 1);
1137104521Srwatson#endif
1138104521Srwatson}
1139104521Srwatson
1140105694Srwatsonstatic void
1141105694Srwatsonmac_destroy_pipe_label(struct label *label)
1142104521Srwatson{
1143104521Srwatson
1144105694Srwatson	MAC_PERFORM(destroy_pipe_label, label);
1145105694Srwatson	mac_destroy_label(label);
1146104521Srwatson#ifdef MAC_DEBUG
1147104527Srwatson	atomic_subtract_int(&nmacpipes, 1);
1148104521Srwatson#endif
1149104521Srwatson}
1150104521Srwatson
1151105694Srwatsonvoid
1152105694Srwatsonmac_destroy_pipe(struct pipe *pipe)
1153105694Srwatson{
1154105694Srwatson
1155105694Srwatson	mac_destroy_pipe_label(pipe->pipe_label);
1156105694Srwatson	free(pipe->pipe_label, M_MACPIPELABEL);
1157105694Srwatson}
1158105694Srwatson
1159107105Srwatsonvoid
1160107105Srwatsonmac_destroy_proc(struct proc *p)
1161107105Srwatson{
1162107105Srwatson
1163107105Srwatson	MAC_PERFORM(destroy_proc_label, &p->p_label);
1164107105Srwatson	mac_destroy_label(&p->p_label);
1165107105Srwatson#ifdef MAC_DEBUG
1166107105Srwatson	atomic_subtract_int(&nmacprocs, 1);
1167107105Srwatson#endif
1168107105Srwatson}
1169107105Srwatson
1170104541Srwatsonstatic void
1171104541Srwatsonmac_destroy_socket_label(struct label *label)
1172104521Srwatson{
1173104521Srwatson
1174104541Srwatson	MAC_PERFORM(destroy_socket_label, label);
1175104541Srwatson	mac_destroy_label(label);
1176104521Srwatson#ifdef MAC_DEBUG
1177104527Srwatson	atomic_subtract_int(&nmacsockets, 1);
1178104521Srwatson#endif
1179104521Srwatson}
1180104521Srwatson
1181104527Srwatsonstatic void
1182104541Srwatsonmac_destroy_socket_peer_label(struct label *label)
1183104541Srwatson{
1184104541Srwatson
1185104541Srwatson	MAC_PERFORM(destroy_socket_peer_label, label);
1186104541Srwatson	mac_destroy_label(label);
1187104541Srwatson}
1188104541Srwatson
1189104541Srwatsonvoid
1190104541Srwatsonmac_destroy_socket(struct socket *socket)
1191104541Srwatson{
1192104541Srwatson
1193104541Srwatson	mac_destroy_socket_label(&socket->so_label);
1194104541Srwatson	mac_destroy_socket_peer_label(&socket->so_peerlabel);
1195104541Srwatson}
1196104541Srwatson
1197105988Srwatsonvoid
1198105694Srwatsonmac_destroy_vnode_label(struct label *label)
1199104521Srwatson{
1200104521Srwatson
1201105694Srwatson	MAC_PERFORM(destroy_vnode_label, label);
1202104527Srwatson	mac_destroy_label(label);
1203104521Srwatson#ifdef MAC_DEBUG
1204105694Srwatson	atomic_subtract_int(&nmacvnodes, 1);
1205104521Srwatson#endif
1206104521Srwatson}
1207104521Srwatson
1208104521Srwatsonvoid
1209104527Srwatsonmac_destroy_vnode(struct vnode *vp)
1210104521Srwatson{
1211104521Srwatson
1212105694Srwatson	mac_destroy_vnode_label(&vp->v_label);
1213104521Srwatson}
1214104521Srwatson
1215113487Srwatsonvoid
1216113487Srwatsonmac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1217113487Srwatson{
1218113487Srwatson	struct label *src_label, *dest_label;
1219113487Srwatson
1220113487Srwatson	src_label = (struct label *)(src+1);
1221113487Srwatson	dest_label = (struct label *)(dest+1);
1222113487Srwatson
1223113487Srwatson	/*
1224113487Srwatson	 * mac_init_mbuf_tag() is called on the target tag in
1225113487Srwatson	 * m_tag_copy(), so we don't need to call it here.
1226113487Srwatson	 */
1227113487Srwatson	MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1228113487Srwatson}
1229113487Srwatson
1230105694Srwatsonstatic void
1231105694Srwatsonmac_copy_pipe_label(struct label *src, struct label *dest)
1232105694Srwatson{
1233105694Srwatson
1234105694Srwatson	MAC_PERFORM(copy_pipe_label, src, dest);
1235105694Srwatson}
1236105694Srwatson
1237105988Srwatsonvoid
1238105694Srwatsonmac_copy_vnode_label(struct label *src, struct label *dest)
1239105694Srwatson{
1240105694Srwatson
1241105694Srwatson	MAC_PERFORM(copy_vnode_label, src, dest);
1242105694Srwatson}
1243105694Srwatson
1244104522Srwatsonstatic int
1245105694Srwatsonmac_check_structmac_consistent(struct mac *mac)
1246104522Srwatson{
1247105694Srwatson
1248105694Srwatson	if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1249105694Srwatson		return (EINVAL);
1250105694Srwatson
1251105694Srwatson	return (0);
1252105694Srwatson}
1253105694Srwatson
1254105694Srwatsonstatic int
1255105694Srwatsonmac_externalize_cred_label(struct label *label, char *elements,
1256105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1257105694Srwatson{
1258104522Srwatson	int error;
1259104522Srwatson
1260105694Srwatson	MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1261104522Srwatson
1262104522Srwatson	return (error);
1263104522Srwatson}
1264104522Srwatson
1265104522Srwatsonstatic int
1266105694Srwatsonmac_externalize_ifnet_label(struct label *label, char *elements,
1267105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1268104522Srwatson{
1269104522Srwatson	int error;
1270104522Srwatson
1271105694Srwatson	MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1272104522Srwatson
1273104522Srwatson	return (error);
1274104522Srwatson}
1275104522Srwatson
1276105694Srwatsonstatic int
1277105694Srwatsonmac_externalize_pipe_label(struct label *label, char *elements,
1278105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1279105694Srwatson{
1280105694Srwatson	int error;
1281105694Srwatson
1282105694Srwatson	MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1283105694Srwatson
1284105694Srwatson	return (error);
1285105694Srwatson}
1286105694Srwatson
1287105694Srwatsonstatic int
1288105694Srwatsonmac_externalize_socket_label(struct label *label, char *elements,
1289105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1290105694Srwatson{
1291105694Srwatson	int error;
1292105694Srwatson
1293105694Srwatson	MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1294105694Srwatson
1295105694Srwatson	return (error);
1296105694Srwatson}
1297105694Srwatson
1298105694Srwatsonstatic int
1299105694Srwatsonmac_externalize_socket_peer_label(struct label *label, char *elements,
1300105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1301105694Srwatson{
1302105694Srwatson	int error;
1303105694Srwatson
1304105694Srwatson	MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1305105694Srwatson
1306105694Srwatson	return (error);
1307105694Srwatson}
1308105694Srwatson
1309105694Srwatsonstatic int
1310105694Srwatsonmac_externalize_vnode_label(struct label *label, char *elements,
1311105694Srwatson    char *outbuf, size_t outbuflen, int flags)
1312105694Srwatson{
1313105694Srwatson	int error;
1314105694Srwatson
1315105694Srwatson	MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1316105694Srwatson
1317105694Srwatson	return (error);
1318105694Srwatson}
1319105694Srwatson
1320105694Srwatsonstatic int
1321105694Srwatsonmac_internalize_cred_label(struct label *label, char *string)
1322105694Srwatson{
1323105694Srwatson	int error;
1324105694Srwatson
1325105694Srwatson	MAC_INTERNALIZE(cred_label, label, string);
1326105694Srwatson
1327105694Srwatson	return (error);
1328105694Srwatson}
1329105694Srwatson
1330105694Srwatsonstatic int
1331105694Srwatsonmac_internalize_ifnet_label(struct label *label, char *string)
1332105694Srwatson{
1333105694Srwatson	int error;
1334105694Srwatson
1335105694Srwatson	MAC_INTERNALIZE(ifnet_label, label, string);
1336105694Srwatson
1337105694Srwatson	return (error);
1338105694Srwatson}
1339105694Srwatson
1340105694Srwatsonstatic int
1341105694Srwatsonmac_internalize_pipe_label(struct label *label, char *string)
1342105694Srwatson{
1343105694Srwatson	int error;
1344105694Srwatson
1345105694Srwatson	MAC_INTERNALIZE(pipe_label, label, string);
1346105694Srwatson
1347105694Srwatson	return (error);
1348105694Srwatson}
1349105694Srwatson
1350105694Srwatsonstatic int
1351105694Srwatsonmac_internalize_socket_label(struct label *label, char *string)
1352105694Srwatson{
1353105694Srwatson	int error;
1354105694Srwatson
1355105694Srwatson	MAC_INTERNALIZE(socket_label, label, string);
1356105694Srwatson
1357105694Srwatson	return (error);
1358105694Srwatson}
1359105694Srwatson
1360105694Srwatsonstatic int
1361105694Srwatsonmac_internalize_vnode_label(struct label *label, char *string)
1362105694Srwatson{
1363105694Srwatson	int error;
1364105694Srwatson
1365105694Srwatson	MAC_INTERNALIZE(vnode_label, label, string);
1366105694Srwatson
1367105694Srwatson	return (error);
1368105694Srwatson}
1369105694Srwatson
1370104522Srwatson/*
1371104522Srwatson * Initialize MAC label for the first kernel process, from which other
1372104522Srwatson * kernel processes and threads are spawned.
1373104522Srwatson */
1374104521Srwatsonvoid
1375104522Srwatsonmac_create_proc0(struct ucred *cred)
1376104522Srwatson{
1377104522Srwatson
1378104522Srwatson	MAC_PERFORM(create_proc0, cred);
1379104522Srwatson}
1380104522Srwatson
1381104522Srwatson/*
1382104522Srwatson * Initialize MAC label for the first userland process, from which other
1383104522Srwatson * userland processes and threads are spawned.
1384104522Srwatson */
1385104522Srwatsonvoid
1386104522Srwatsonmac_create_proc1(struct ucred *cred)
1387104522Srwatson{
1388104522Srwatson
1389104522Srwatson	MAC_PERFORM(create_proc1, cred);
1390104522Srwatson}
1391104522Srwatson
1392104522Srwatsonvoid
1393104522Srwatsonmac_thread_userret(struct thread *td)
1394104522Srwatson{
1395104522Srwatson
1396104522Srwatson	MAC_PERFORM(thread_userret, td);
1397104522Srwatson}
1398104522Srwatson
1399104522Srwatson/*
1400104522Srwatson * When a new process is created, its label must be initialized.  Generally,
1401104522Srwatson * this involves inheritence from the parent process, modulo possible
1402104522Srwatson * deltas.  This function allows that processing to take place.
1403104522Srwatson */
1404104522Srwatsonvoid
1405104522Srwatsonmac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1406104522Srwatson{
1407104522Srwatson
1408104522Srwatson	MAC_PERFORM(create_cred, parent_cred, child_cred);
1409104522Srwatson}
1410104522Srwatson
1411104522Srwatsonvoid
1412107698Srwatsonmac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1413107698Srwatson    struct vnode *vp)
1414100979Srwatson{
1415100979Srwatson
1416107698Srwatson	MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1417107698Srwatson	    &vp->v_label);
1418100979Srwatson}
1419100979Srwatson
1420100979Srwatsonvoid
1421105988Srwatsonmac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1422105988Srwatson    struct vnode *vp)
1423100979Srwatson{
1424100979Srwatson
1425105988Srwatson	MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1426105988Srwatson	    &de->de_label, vp, &vp->v_label);
1427100979Srwatson}
1428100979Srwatson
1429105988Srwatsonint
1430105988Srwatsonmac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1431100979Srwatson{
1432100979Srwatson	int error;
1433100979Srwatson
1434105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1435100979Srwatson
1436105988Srwatson	MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1437105988Srwatson	    &vp->v_label);
1438100979Srwatson
1439100979Srwatson	return (error);
1440100979Srwatson}
1441100979Srwatson
1442100979Srwatsonvoid
1443105988Srwatsonmac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1444100979Srwatson{
1445100979Srwatson
1446105988Srwatson	MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1447105988Srwatson	    &vp->v_label);
1448100979Srwatson}
1449100979Srwatson
1450100979Srwatsonint
1451105988Srwatsonmac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1452105988Srwatson    struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1453100979Srwatson{
1454105988Srwatson	int error;
1455100979Srwatson
1456105988Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1457105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1458100979Srwatson
1459105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1460105988Srwatson	if (error == EOPNOTSUPP) {
1461105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1462105988Srwatson		if (ea_warn_once == 0) {
1463105988Srwatson			printf("Warning: transactions not supported "
1464105988Srwatson			    "in EA write.\n");
1465105988Srwatson			ea_warn_once = 1;
1466105988Srwatson		}
1467105988Srwatson	} else if (error)
1468100979Srwatson		return (error);
1469100979Srwatson
1470105988Srwatson	MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1471105988Srwatson	    dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1472100979Srwatson
1473105988Srwatson	if (error) {
1474105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1475100979Srwatson		return (error);
1476100979Srwatson	}
1477100979Srwatson
1478105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1479100979Srwatson
1480105988Srwatson	if (error == EOPNOTSUPP)
1481105988Srwatson		error = 0;				/* XXX */
1482100979Srwatson
1483100979Srwatson	return (error);
1484100979Srwatson}
1485100979Srwatson
1486100979Srwatsonstatic int
1487105988Srwatsonmac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1488105988Srwatson    struct label *intlabel)
1489100979Srwatson{
1490100979Srwatson	int error;
1491100979Srwatson
1492105988Srwatson	ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1493100979Srwatson
1494105988Srwatson	error = VOP_OPENEXTATTR(vp, cred, curthread);
1495105988Srwatson	if (error == EOPNOTSUPP) {
1496105988Srwatson		/* XXX: Optionally abort if transactions not supported. */
1497105988Srwatson		if (ea_warn_once == 0) {
1498105988Srwatson			printf("Warning: transactions not supported "
1499105988Srwatson			    "in EA write.\n");
1500105988Srwatson			ea_warn_once = 1;
1501105988Srwatson		}
1502105988Srwatson	} else if (error)
1503105988Srwatson		return (error);
1504100979Srwatson
1505105988Srwatson	MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1506100979Srwatson
1507105988Srwatson	if (error) {
1508105988Srwatson		VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1509100979Srwatson		return (error);
1510100979Srwatson	}
1511100979Srwatson
1512105988Srwatson	error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1513100979Srwatson
1514105988Srwatson	if (error == EOPNOTSUPP)
1515105988Srwatson		error = 0;				/* XXX */
1516100979Srwatson
1517105988Srwatson	return (error);
1518100979Srwatson}
1519100979Srwatson
1520106468Srwatsonint
1521106468Srwatsonmac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1522106468Srwatson    struct label *execlabelstorage)
1523106468Srwatson{
1524106468Srwatson	struct mac mac;
1525106468Srwatson	char *buffer;
1526106468Srwatson	int error;
1527106468Srwatson
1528106468Srwatson	if (mac_p == NULL)
1529106468Srwatson		return (0);
1530106468Srwatson
1531106468Srwatson	error = copyin(mac_p, &mac, sizeof(mac));
1532106468Srwatson	if (error)
1533106468Srwatson		return (error);
1534106468Srwatson
1535106468Srwatson	error = mac_check_structmac_consistent(&mac);
1536106468Srwatson	if (error)
1537106468Srwatson		return (error);
1538106468Srwatson
1539111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1540106468Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1541106468Srwatson	if (error) {
1542106468Srwatson		free(buffer, M_MACTEMP);
1543106468Srwatson		return (error);
1544106468Srwatson	}
1545106468Srwatson
1546106468Srwatson	mac_init_cred_label(execlabelstorage);
1547106468Srwatson	error = mac_internalize_cred_label(execlabelstorage, buffer);
1548106468Srwatson	free(buffer, M_MACTEMP);
1549106468Srwatson	if (error) {
1550106468Srwatson		mac_destroy_cred_label(execlabelstorage);
1551106468Srwatson		return (error);
1552106468Srwatson	}
1553106468Srwatson	imgp->execlabel = execlabelstorage;
1554106468Srwatson	return (0);
1555106468Srwatson}
1556106468Srwatson
1557100979Srwatsonvoid
1558106468Srwatsonmac_execve_exit(struct image_params *imgp)
1559100979Srwatson{
1560106468Srwatson	if (imgp->execlabel != NULL)
1561106468Srwatson		mac_destroy_cred_label(imgp->execlabel);
1562106468Srwatson}
1563100979Srwatson
1564106468Srwatsonvoid
1565106468Srwatsonmac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1566106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1567106468Srwatson{
1568106468Srwatson
1569100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1570100979Srwatson
1571106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1572106460Srwatson		return;
1573106460Srwatson
1574106468Srwatson	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1575106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1576100979Srwatson}
1577100979Srwatson
1578100979Srwatsonint
1579106468Srwatsonmac_execve_will_transition(struct ucred *old, struct vnode *vp,
1580106468Srwatson    struct label *interpvnodelabel, struct image_params *imgp)
1581100979Srwatson{
1582105988Srwatson	int result;
1583100979Srwatson
1584106460Srwatson	ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1585106460Srwatson
1586106460Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1587106460Srwatson		return (0);
1588106460Srwatson
1589100979Srwatson	result = 0;
1590106468Srwatson	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1591106647Srwatson	    interpvnodelabel, imgp, imgp->execlabel);
1592100979Srwatson
1593100979Srwatson	return (result);
1594100979Srwatson}
1595100979Srwatson
1596100979Srwatsonint
1597106212Srwatsonmac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1598100979Srwatson{
1599100979Srwatson	int error;
1600100979Srwatson
1601100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1602100979Srwatson
1603100979Srwatson	if (!mac_enforce_fs)
1604100979Srwatson		return (0);
1605100979Srwatson
1606106212Srwatson	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1607100979Srwatson	return (error);
1608100979Srwatson}
1609100979Srwatson
1610100979Srwatsonint
1611100979Srwatsonmac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1612100979Srwatson{
1613100979Srwatson	int error;
1614100979Srwatson
1615100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1616100979Srwatson
1617100979Srwatson	if (!mac_enforce_fs)
1618100979Srwatson		return (0);
1619100979Srwatson
1620100979Srwatson	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1621100979Srwatson	return (error);
1622100979Srwatson}
1623100979Srwatson
1624100979Srwatsonint
1625100979Srwatsonmac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1626100979Srwatson{
1627100979Srwatson	int error;
1628100979Srwatson
1629100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1630100979Srwatson
1631100979Srwatson	if (!mac_enforce_fs)
1632100979Srwatson		return (0);
1633100979Srwatson
1634100979Srwatson	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1635100979Srwatson	return (error);
1636100979Srwatson}
1637100979Srwatson
1638100979Srwatsonint
1639100979Srwatsonmac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1640100979Srwatson    struct componentname *cnp, struct vattr *vap)
1641100979Srwatson{
1642100979Srwatson	int error;
1643100979Srwatson
1644100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1645100979Srwatson
1646100979Srwatson	if (!mac_enforce_fs)
1647100979Srwatson		return (0);
1648100979Srwatson
1649100979Srwatson	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1650100979Srwatson	return (error);
1651100979Srwatson}
1652100979Srwatson
1653100979Srwatsonint
1654100979Srwatsonmac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1655100979Srwatson    struct componentname *cnp)
1656100979Srwatson{
1657100979Srwatson	int error;
1658100979Srwatson
1659100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1660100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1661100979Srwatson
1662100979Srwatson	if (!mac_enforce_fs)
1663100979Srwatson		return (0);
1664100979Srwatson
1665100979Srwatson	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1666100979Srwatson	    &vp->v_label, cnp);
1667100979Srwatson	return (error);
1668100979Srwatson}
1669100979Srwatson
1670100979Srwatsonint
1671100979Srwatsonmac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1672100979Srwatson    acl_type_t type)
1673100979Srwatson{
1674100979Srwatson	int error;
1675100979Srwatson
1676100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1677100979Srwatson
1678100979Srwatson	if (!mac_enforce_fs)
1679100979Srwatson		return (0);
1680100979Srwatson
1681100979Srwatson	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1682100979Srwatson	return (error);
1683100979Srwatson}
1684100979Srwatson
1685100979Srwatsonint
1686106468Srwatsonmac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1687106468Srwatson    struct image_params *imgp)
1688100979Srwatson{
1689100979Srwatson	int error;
1690100979Srwatson
1691102102Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1692102102Srwatson
1693100979Srwatson	if (!mac_enforce_process && !mac_enforce_fs)
1694100979Srwatson		return (0);
1695100979Srwatson
1696106647Srwatson	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1697106647Srwatson	    imgp->execlabel);
1698100979Srwatson
1699100979Srwatson	return (error);
1700100979Srwatson}
1701100979Srwatson
1702100979Srwatsonint
1703100979Srwatsonmac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1704100979Srwatson{
1705100979Srwatson	int error;
1706100979Srwatson
1707100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1708100979Srwatson
1709100979Srwatson	if (!mac_enforce_fs)
1710100979Srwatson		return (0);
1711100979Srwatson
1712100979Srwatson	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1713100979Srwatson	return (error);
1714100979Srwatson}
1715100979Srwatson
1716100979Srwatsonint
1717100979Srwatsonmac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1718100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1719100979Srwatson{
1720100979Srwatson	int error;
1721100979Srwatson
1722100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1723100979Srwatson
1724100979Srwatson	if (!mac_enforce_fs)
1725100979Srwatson		return (0);
1726100979Srwatson
1727100979Srwatson	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1728100979Srwatson	    attrnamespace, name, uio);
1729100979Srwatson	return (error);
1730100979Srwatson}
1731100979Srwatson
1732100979Srwatsonint
1733104529Srwatsonmac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1734104529Srwatson    struct vnode *vp, struct componentname *cnp)
1735104529Srwatson{
1736104529Srwatson	int error;
1737104529Srwatson
1738104529Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1739104529Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1740104529Srwatson
1741104529Srwatson	if (!mac_enforce_fs)
1742104529Srwatson		return (0);
1743104529Srwatson
1744104529Srwatson	MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1745104529Srwatson	    &vp->v_label, cnp);
1746104529Srwatson	return (error);
1747104529Srwatson}
1748104529Srwatson
1749104529Srwatsonint
1750100979Srwatsonmac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1751100979Srwatson    struct componentname *cnp)
1752100979Srwatson{
1753100979Srwatson	int error;
1754100979Srwatson
1755100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1756100979Srwatson
1757100979Srwatson	if (!mac_enforce_fs)
1758100979Srwatson		return (0);
1759100979Srwatson
1760100979Srwatson	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1761100979Srwatson	return (error);
1762100979Srwatson}
1763100979Srwatson
1764104546Srwatsonint
1765104546Srwatsonmac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1766100979Srwatson{
1767104546Srwatson	int error;
1768100979Srwatson
1769104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1770103514Srwatson
1771104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1772104546Srwatson		return (0);
1773104546Srwatson
1774104546Srwatson	MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1775104546Srwatson	return (error);
1776100979Srwatson}
1777100979Srwatson
1778104546Srwatsonvoid
1779104546Srwatsonmac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1780104546Srwatson{
1781104546Srwatson	int result = *prot;
1782104546Srwatson
1783104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1784104546Srwatson
1785104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1786104546Srwatson		return;
1787104546Srwatson
1788104546Srwatson	MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1789104546Srwatson	    &result);
1790104546Srwatson
1791104546Srwatson	*prot = result;
1792104546Srwatson}
1793104546Srwatson
1794100979Srwatsonint
1795104546Srwatsonmac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1796104546Srwatson{
1797104546Srwatson	int error;
1798104546Srwatson
1799104546Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1800104546Srwatson
1801104546Srwatson	if (!mac_enforce_fs || !mac_enforce_vm)
1802104546Srwatson		return (0);
1803104546Srwatson
1804104546Srwatson	MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1805104546Srwatson	return (error);
1806104546Srwatson}
1807104546Srwatson
1808104546Srwatsonint
1809106212Srwatsonmac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1810100979Srwatson{
1811100979Srwatson	int error;
1812100979Srwatson
1813102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1814102112Srwatson
1815100979Srwatson	if (!mac_enforce_fs)
1816100979Srwatson		return (0);
1817100979Srwatson
1818102112Srwatson	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1819102112Srwatson	return (error);
1820102112Srwatson}
1821102112Srwatson
1822102112Srwatsonint
1823102129Srwatsonmac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1824102129Srwatson    struct vnode *vp)
1825102112Srwatson{
1826102112Srwatson	int error;
1827102112Srwatson
1828102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1829102112Srwatson
1830102112Srwatson	if (!mac_enforce_fs)
1831102112Srwatson		return (0);
1832102112Srwatson
1833102129Srwatson	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1834102129Srwatson	    &vp->v_label);
1835100979Srwatson
1836100979Srwatson	return (error);
1837100979Srwatson}
1838100979Srwatson
1839100979Srwatsonint
1840102129Srwatsonmac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1841102129Srwatson    struct vnode *vp)
1842100979Srwatson{
1843100979Srwatson	int error;
1844100979Srwatson
1845102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1846100979Srwatson
1847100979Srwatson	if (!mac_enforce_fs)
1848100979Srwatson		return (0);
1849100979Srwatson
1850102129Srwatson	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1851102129Srwatson	    &vp->v_label);
1852102112Srwatson
1853100979Srwatson	return (error);
1854100979Srwatson}
1855100979Srwatson
1856100979Srwatsonint
1857100979Srwatsonmac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1858100979Srwatson{
1859100979Srwatson	int error;
1860100979Srwatson
1861100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1862100979Srwatson
1863100979Srwatson	if (!mac_enforce_fs)
1864100979Srwatson		return (0);
1865100979Srwatson
1866100979Srwatson	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1867100979Srwatson	return (error);
1868100979Srwatson}
1869100979Srwatson
1870100979Srwatsonint
1871100979Srwatsonmac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1872100979Srwatson{
1873100979Srwatson	int error;
1874100979Srwatson
1875100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1876100979Srwatson
1877100979Srwatson	if (!mac_enforce_fs)
1878100979Srwatson		return (0);
1879100979Srwatson
1880100979Srwatson	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1881100979Srwatson	return (error);
1882100979Srwatson}
1883100979Srwatson
1884100979Srwatsonstatic int
1885100979Srwatsonmac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1886100979Srwatson    struct label *newlabel)
1887100979Srwatson{
1888100979Srwatson	int error;
1889100979Srwatson
1890100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1891100979Srwatson
1892100979Srwatson	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1893100979Srwatson
1894100979Srwatson	return (error);
1895100979Srwatson}
1896100979Srwatson
1897100979Srwatsonint
1898100979Srwatsonmac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1899100979Srwatson    struct vnode *vp, struct componentname *cnp)
1900100979Srwatson{
1901100979Srwatson	int error;
1902100979Srwatson
1903100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1904100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1905100979Srwatson
1906100979Srwatson	if (!mac_enforce_fs)
1907100979Srwatson		return (0);
1908100979Srwatson
1909100979Srwatson	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1910100979Srwatson	    &vp->v_label, cnp);
1911100979Srwatson	return (error);
1912100979Srwatson}
1913100979Srwatson
1914100979Srwatsonint
1915100979Srwatsonmac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1916100979Srwatson    struct vnode *vp, int samedir, struct componentname *cnp)
1917100979Srwatson{
1918100979Srwatson	int error;
1919100979Srwatson
1920100979Srwatson	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1921100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1922100979Srwatson
1923100979Srwatson	if (!mac_enforce_fs)
1924100979Srwatson		return (0);
1925100979Srwatson
1926100979Srwatson	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1927100979Srwatson	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1928100979Srwatson	return (error);
1929100979Srwatson}
1930100979Srwatson
1931100979Srwatsonint
1932100979Srwatsonmac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1933100979Srwatson{
1934100979Srwatson	int error;
1935100979Srwatson
1936100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1937100979Srwatson
1938100979Srwatson	if (!mac_enforce_fs)
1939100979Srwatson		return (0);
1940100979Srwatson
1941100979Srwatson	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1942100979Srwatson	return (error);
1943100979Srwatson}
1944100979Srwatson
1945100979Srwatsonint
1946100979Srwatsonmac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1947100979Srwatson    struct acl *acl)
1948100979Srwatson{
1949100979Srwatson	int error;
1950100979Srwatson
1951100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1952100979Srwatson
1953100979Srwatson	if (!mac_enforce_fs)
1954100979Srwatson		return (0);
1955100979Srwatson
1956100979Srwatson	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1957100979Srwatson	return (error);
1958100979Srwatson}
1959100979Srwatson
1960100979Srwatsonint
1961100979Srwatsonmac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1962100979Srwatson    int attrnamespace, const char *name, struct uio *uio)
1963100979Srwatson{
1964100979Srwatson	int error;
1965100979Srwatson
1966100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1967100979Srwatson
1968100979Srwatson	if (!mac_enforce_fs)
1969100979Srwatson		return (0);
1970100979Srwatson
1971100979Srwatson	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1972100979Srwatson	    attrnamespace, name, uio);
1973100979Srwatson	return (error);
1974100979Srwatson}
1975100979Srwatson
1976100979Srwatsonint
1977100979Srwatsonmac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1978100979Srwatson{
1979100979Srwatson	int error;
1980100979Srwatson
1981100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1982100979Srwatson
1983100979Srwatson	if (!mac_enforce_fs)
1984100979Srwatson		return (0);
1985100979Srwatson
1986100979Srwatson	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1987100979Srwatson	return (error);
1988100979Srwatson}
1989100979Srwatson
1990100979Srwatsonint
1991100979Srwatsonmac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1992100979Srwatson{
1993100979Srwatson	int error;
1994100979Srwatson
1995100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1996100979Srwatson
1997100979Srwatson	if (!mac_enforce_fs)
1998100979Srwatson		return (0);
1999100979Srwatson
2000100979Srwatson	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2001100979Srwatson	return (error);
2002100979Srwatson}
2003100979Srwatson
2004100979Srwatsonint
2005100979Srwatsonmac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2006100979Srwatson    gid_t gid)
2007100979Srwatson{
2008100979Srwatson	int error;
2009100979Srwatson
2010100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2011100979Srwatson
2012100979Srwatson	if (!mac_enforce_fs)
2013100979Srwatson		return (0);
2014100979Srwatson
2015100979Srwatson	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2016100979Srwatson	return (error);
2017100979Srwatson}
2018100979Srwatson
2019100979Srwatsonint
2020100979Srwatsonmac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2021100979Srwatson    struct timespec atime, struct timespec mtime)
2022100979Srwatson{
2023100979Srwatson	int error;
2024100979Srwatson
2025100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2026100979Srwatson
2027100979Srwatson	if (!mac_enforce_fs)
2028100979Srwatson		return (0);
2029100979Srwatson
2030100979Srwatson	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2031100979Srwatson	    mtime);
2032100979Srwatson	return (error);
2033100979Srwatson}
2034100979Srwatson
2035100979Srwatsonint
2036102129Srwatsonmac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2037102129Srwatson    struct vnode *vp)
2038100979Srwatson{
2039100979Srwatson	int error;
2040100979Srwatson
2041100979Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2042100979Srwatson
2043100979Srwatson	if (!mac_enforce_fs)
2044100979Srwatson		return (0);
2045100979Srwatson
2046102129Srwatson	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2047102129Srwatson	    &vp->v_label);
2048100979Srwatson	return (error);
2049100979Srwatson}
2050100979Srwatson
2051102112Srwatsonint
2052102129Srwatsonmac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2053102129Srwatson    struct vnode *vp)
2054102112Srwatson{
2055102112Srwatson	int error;
2056102112Srwatson
2057102112Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2058102112Srwatson
2059102112Srwatson	if (!mac_enforce_fs)
2060102112Srwatson		return (0);
2061102112Srwatson
2062102129Srwatson	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2063102129Srwatson	    &vp->v_label);
2064102112Srwatson
2065102112Srwatson	return (error);
2066102112Srwatson}
2067102112Srwatson
2068100979Srwatson/*
2069100979Srwatson * When relabeling a process, call out to the policies for the maximum
2070100979Srwatson * permission allowed for each object type we know about in its
2071100979Srwatson * memory space, and revoke access (in the least surprising ways we
2072100979Srwatson * know) when necessary.  The process lock is not held here.
2073100979Srwatson */
2074107271Srwatsonvoid
2075100979Srwatsonmac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2076100979Srwatson{
2077100979Srwatson
2078100979Srwatson	/* XXX freeze all other threads */
2079100979Srwatson	mac_cred_mmapped_drop_perms_recurse(td, cred,
2080100979Srwatson	    &td->td_proc->p_vmspace->vm_map);
2081100979Srwatson	/* XXX allow other threads to continue */
2082100979Srwatson}
2083100979Srwatson
2084100979Srwatsonstatic __inline const char *
2085100979Srwatsonprot2str(vm_prot_t prot)
2086100979Srwatson{
2087100979Srwatson
2088100979Srwatson	switch (prot & VM_PROT_ALL) {
2089100979Srwatson	case VM_PROT_READ:
2090100979Srwatson		return ("r--");
2091100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE:
2092100979Srwatson		return ("rw-");
2093100979Srwatson	case VM_PROT_READ | VM_PROT_EXECUTE:
2094100979Srwatson		return ("r-x");
2095100979Srwatson	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2096100979Srwatson		return ("rwx");
2097100979Srwatson	case VM_PROT_WRITE:
2098100979Srwatson		return ("-w-");
2099100979Srwatson	case VM_PROT_EXECUTE:
2100100979Srwatson		return ("--x");
2101100979Srwatson	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2102100979Srwatson		return ("-wx");
2103100979Srwatson	default:
2104100979Srwatson		return ("---");
2105100979Srwatson	}
2106100979Srwatson}
2107100979Srwatson
2108100979Srwatsonstatic void
2109100979Srwatsonmac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2110100979Srwatson    struct vm_map *map)
2111100979Srwatson{
2112100979Srwatson	struct vm_map_entry *vme;
2113104546Srwatson	int result;
2114104546Srwatson	vm_prot_t revokeperms;
2115100979Srwatson	vm_object_t object;
2116100979Srwatson	vm_ooffset_t offset;
2117100979Srwatson	struct vnode *vp;
2118100979Srwatson
2119103136Srwatson	if (!mac_mmap_revocation)
2120103136Srwatson		return;
2121103136Srwatson
2122100979Srwatson	vm_map_lock_read(map);
2123100979Srwatson	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2124100979Srwatson		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2125100979Srwatson			mac_cred_mmapped_drop_perms_recurse(td, cred,
2126100979Srwatson			    vme->object.sub_map);
2127100979Srwatson			continue;
2128100979Srwatson		}
2129100979Srwatson		/*
2130100979Srwatson		 * Skip over entries that obviously are not shared.
2131100979Srwatson		 */
2132100979Srwatson		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2133100979Srwatson		    !vme->max_protection)
2134100979Srwatson			continue;
2135100979Srwatson		/*
2136100979Srwatson		 * Drill down to the deepest backing object.
2137100979Srwatson		 */
2138100979Srwatson		offset = vme->offset;
2139100979Srwatson		object = vme->object.vm_object;
2140100979Srwatson		if (object == NULL)
2141100979Srwatson			continue;
2142100979Srwatson		while (object->backing_object != NULL) {
2143100979Srwatson			object = object->backing_object;
2144100979Srwatson			offset += object->backing_object_offset;
2145100979Srwatson		}
2146100979Srwatson		/*
2147100979Srwatson		 * At the moment, vm_maps and objects aren't considered
2148100979Srwatson		 * by the MAC system, so only things with backing by a
2149100979Srwatson		 * normal object (read: vnodes) are checked.
2150100979Srwatson		 */
2151100979Srwatson		if (object->type != OBJT_VNODE)
2152100979Srwatson			continue;
2153100979Srwatson		vp = (struct vnode *)object->handle;
2154100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2155104546Srwatson		result = vme->max_protection;
2156104546Srwatson		mac_check_vnode_mmap_downgrade(cred, vp, &result);
2157100979Srwatson		VOP_UNLOCK(vp, 0, td);
2158100979Srwatson		/*
2159100979Srwatson		 * Find out what maximum protection we may be allowing
2160100979Srwatson		 * now but a policy needs to get removed.
2161100979Srwatson		 */
2162100979Srwatson		revokeperms = vme->max_protection & ~result;
2163100979Srwatson		if (!revokeperms)
2164100979Srwatson			continue;
2165102949Sbde		printf("pid %ld: revoking %s perms from %#lx:%ld "
2166102949Sbde		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2167102949Sbde		    prot2str(revokeperms), (u_long)vme->start,
2168102949Sbde		    (long)(vme->end - vme->start),
2169100979Srwatson		    prot2str(vme->max_protection), prot2str(vme->protection));
2170100979Srwatson		vm_map_lock_upgrade(map);
2171100979Srwatson		/*
2172100979Srwatson		 * This is the really simple case: if a map has more
2173100979Srwatson		 * max_protection than is allowed, but it's not being
2174100979Srwatson		 * actually used (that is, the current protection is
2175100979Srwatson		 * still allowed), we can just wipe it out and do
2176100979Srwatson		 * nothing more.
2177100979Srwatson		 */
2178100979Srwatson		if ((vme->protection & revokeperms) == 0) {
2179100979Srwatson			vme->max_protection -= revokeperms;
2180100979Srwatson		} else {
2181100979Srwatson			if (revokeperms & VM_PROT_WRITE) {
2182100979Srwatson				/*
2183100979Srwatson				 * In the more complicated case, flush out all
2184100979Srwatson				 * pending changes to the object then turn it
2185100979Srwatson				 * copy-on-write.
2186100979Srwatson				 */
2187100979Srwatson				vm_object_reference(object);
2188100979Srwatson				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2189113955Salc				VM_OBJECT_LOCK(object);
2190100979Srwatson				vm_object_page_clean(object,
2191100979Srwatson				    OFF_TO_IDX(offset),
2192100979Srwatson				    OFF_TO_IDX(offset + vme->end - vme->start +
2193100979Srwatson					PAGE_MASK),
2194100979Srwatson				    OBJPC_SYNC);
2195113955Salc				VM_OBJECT_UNLOCK(object);
2196100979Srwatson				VOP_UNLOCK(vp, 0, td);
2197100979Srwatson				vm_object_deallocate(object);
2198100979Srwatson				/*
2199100979Srwatson				 * Why bother if there's no read permissions
2200100979Srwatson				 * anymore?  For the rest, we need to leave
2201100979Srwatson				 * the write permissions on for COW, or
2202100979Srwatson				 * remove them entirely if configured to.
2203100979Srwatson				 */
2204100979Srwatson				if (!mac_mmap_revocation_via_cow) {
2205100979Srwatson					vme->max_protection &= ~VM_PROT_WRITE;
2206100979Srwatson					vme->protection &= ~VM_PROT_WRITE;
2207100979Srwatson				} if ((revokeperms & VM_PROT_READ) == 0)
2208100979Srwatson					vme->eflags |= MAP_ENTRY_COW |
2209100979Srwatson					    MAP_ENTRY_NEEDS_COPY;
2210100979Srwatson			}
2211100979Srwatson			if (revokeperms & VM_PROT_EXECUTE) {
2212100979Srwatson				vme->max_protection &= ~VM_PROT_EXECUTE;
2213100979Srwatson				vme->protection &= ~VM_PROT_EXECUTE;
2214100979Srwatson			}
2215100979Srwatson			if (revokeperms & VM_PROT_READ) {
2216100979Srwatson				vme->max_protection = 0;
2217100979Srwatson				vme->protection = 0;
2218100979Srwatson			}
2219100979Srwatson			pmap_protect(map->pmap, vme->start, vme->end,
2220100979Srwatson			    vme->protection & ~revokeperms);
2221100979Srwatson			vm_map_simplify_entry(map, vme);
2222100979Srwatson		}
2223100979Srwatson		vm_map_lock_downgrade(map);
2224100979Srwatson	}
2225100979Srwatson	vm_map_unlock_read(map);
2226100979Srwatson}
2227100979Srwatson
2228100979Srwatson/*
2229100979Srwatson * When the subject's label changes, it may require revocation of privilege
2230100979Srwatson * to mapped objects.  This can't be done on-the-fly later with a unified
2231100979Srwatson * buffer cache.
2232100979Srwatson */
2233100979Srwatsonstatic void
2234100979Srwatsonmac_relabel_cred(struct ucred *cred, struct label *newlabel)
2235100979Srwatson{
2236100979Srwatson
2237100979Srwatson	MAC_PERFORM(relabel_cred, cred, newlabel);
2238100979Srwatson}
2239100979Srwatson
2240100979Srwatsonvoid
2241100979Srwatsonmac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2242100979Srwatson{
2243100979Srwatson
2244100979Srwatson	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2245100979Srwatson}
2246100979Srwatson
2247100979Srwatsonvoid
2248100979Srwatsonmac_create_ifnet(struct ifnet *ifnet)
2249100979Srwatson{
2250100979Srwatson
2251100979Srwatson	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2252100979Srwatson}
2253100979Srwatson
2254100979Srwatsonvoid
2255100979Srwatsonmac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2256100979Srwatson{
2257100979Srwatson
2258100979Srwatson	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2259100979Srwatson}
2260100979Srwatson
2261100979Srwatsonvoid
2262100979Srwatsonmac_create_socket(struct ucred *cred, struct socket *socket)
2263100979Srwatson{
2264100979Srwatson
2265100979Srwatson	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2266100979Srwatson}
2267100979Srwatson
2268100979Srwatsonvoid
2269100979Srwatsonmac_create_pipe(struct ucred *cred, struct pipe *pipe)
2270100979Srwatson{
2271100979Srwatson
2272100979Srwatson	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2273100979Srwatson}
2274100979Srwatson
2275100979Srwatsonvoid
2276100979Srwatsonmac_create_socket_from_socket(struct socket *oldsocket,
2277100979Srwatson    struct socket *newsocket)
2278100979Srwatson{
2279100979Srwatson
2280100979Srwatson	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2281100979Srwatson	    newsocket, &newsocket->so_label);
2282100979Srwatson}
2283100979Srwatson
2284100979Srwatsonstatic void
2285100979Srwatsonmac_relabel_socket(struct ucred *cred, struct socket *socket,
2286100979Srwatson    struct label *newlabel)
2287100979Srwatson{
2288100979Srwatson
2289100979Srwatson	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2290100979Srwatson}
2291100979Srwatson
2292100979Srwatsonstatic void
2293100979Srwatsonmac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2294100979Srwatson{
2295100979Srwatson
2296100979Srwatson	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2297100979Srwatson}
2298100979Srwatson
2299100979Srwatsonvoid
2300100979Srwatsonmac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2301100979Srwatson{
2302113482Srwatson	struct label *label;
2303100979Srwatson
2304113482Srwatson	label = mbuf_to_label(mbuf);
2305113482Srwatson
2306113482Srwatson	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2307113482Srwatson	    &socket->so_peerlabel);
2308100979Srwatson}
2309100979Srwatson
2310100979Srwatsonvoid
2311100979Srwatsonmac_set_socket_peer_from_socket(struct socket *oldsocket,
2312100979Srwatson    struct socket *newsocket)
2313100979Srwatson{
2314100979Srwatson
2315100979Srwatson	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2316100979Srwatson	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2317100979Srwatson}
2318100979Srwatson
2319100979Srwatsonvoid
2320100979Srwatsonmac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2321100979Srwatson{
2322113482Srwatson	struct label *label;
2323100979Srwatson
2324113482Srwatson	label = mbuf_to_label(datagram);
2325113482Srwatson
2326100979Srwatson	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2327113482Srwatson	    datagram, label);
2328100979Srwatson}
2329100979Srwatson
2330100979Srwatsonvoid
2331100979Srwatsonmac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2332100979Srwatson{
2333113482Srwatson	struct label *datagramlabel, *fragmentlabel;
2334100979Srwatson
2335113482Srwatson	datagramlabel = mbuf_to_label(datagram);
2336113482Srwatson	fragmentlabel = mbuf_to_label(fragment);
2337113482Srwatson
2338113482Srwatson	MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2339113482Srwatson	    fragmentlabel);
2340100979Srwatson}
2341100979Srwatson
2342100979Srwatsonvoid
2343100979Srwatsonmac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2344100979Srwatson{
2345113482Srwatson	struct label *label;
2346100979Srwatson
2347113482Srwatson	label = mbuf_to_label(fragment);
2348113482Srwatson
2349113482Srwatson	MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2350100979Srwatson}
2351100979Srwatson
2352100979Srwatsonvoid
2353100979Srwatsonmac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2354100979Srwatson{
2355113482Srwatson	struct label *oldmbuflabel, *newmbuflabel;
2356100979Srwatson
2357113482Srwatson	oldmbuflabel = mbuf_to_label(oldmbuf);
2358113482Srwatson	newmbuflabel = mbuf_to_label(newmbuf);
2359113482Srwatson
2360113482Srwatson	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2361113482Srwatson	    newmbuflabel);
2362100979Srwatson}
2363100979Srwatson
2364100979Srwatsonvoid
2365100979Srwatsonmac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2366100979Srwatson{
2367113482Srwatson	struct label *label;
2368100979Srwatson
2369113482Srwatson	label = mbuf_to_label(mbuf);
2370113482Srwatson
2371100979Srwatson	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2372113482Srwatson	    label);
2373100979Srwatson}
2374100979Srwatson
2375100979Srwatsonvoid
2376100979Srwatsonmac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2377100979Srwatson{
2378113482Srwatson	struct label *label;
2379100979Srwatson
2380113482Srwatson	label = mbuf_to_label(mbuf);
2381113482Srwatson
2382100979Srwatson	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2383113482Srwatson	    label);
2384100979Srwatson}
2385100979Srwatson
2386100979Srwatsonvoid
2387100979Srwatsonmac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2388100979Srwatson{
2389113482Srwatson	struct label *label;
2390100979Srwatson
2391113482Srwatson	label = mbuf_to_label(mbuf);
2392113482Srwatson
2393100979Srwatson	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2394113482Srwatson	    label);
2395100979Srwatson}
2396100979Srwatson
2397100979Srwatsonvoid
2398100979Srwatsonmac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2399100979Srwatson    struct mbuf *newmbuf)
2400100979Srwatson{
2401113482Srwatson	struct label *oldmbuflabel, *newmbuflabel;
2402100979Srwatson
2403113482Srwatson	oldmbuflabel = mbuf_to_label(oldmbuf);
2404113482Srwatson	newmbuflabel = mbuf_to_label(newmbuf);
2405113482Srwatson
2406113482Srwatson	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2407113482Srwatson	    ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2408100979Srwatson}
2409100979Srwatson
2410100979Srwatsonvoid
2411100979Srwatsonmac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2412100979Srwatson{
2413113482Srwatson	struct label *oldmbuflabel, *newmbuflabel;
2414100979Srwatson
2415113482Srwatson	oldmbuflabel = mbuf_to_label(oldmbuf);
2416113482Srwatson	newmbuflabel = mbuf_to_label(newmbuf);
2417113482Srwatson
2418113482Srwatson	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2419113482Srwatson	    newmbuflabel);
2420100979Srwatson}
2421100979Srwatson
2422100979Srwatsonint
2423100979Srwatsonmac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2424100979Srwatson{
2425113482Srwatson	struct label *label;
2426100979Srwatson	int result;
2427100979Srwatson
2428113482Srwatson	label = mbuf_to_label(fragment);
2429113482Srwatson
2430100979Srwatson	result = 1;
2431113482Srwatson	MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2432113482Srwatson	    &ipq->ipq_label);
2433100979Srwatson
2434100979Srwatson	return (result);
2435100979Srwatson}
2436100979Srwatson
2437100979Srwatsonvoid
2438100979Srwatsonmac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2439100979Srwatson{
2440113482Srwatson	struct label *label;
2441100979Srwatson
2442113482Srwatson	label = mbuf_to_label(fragment);
2443113482Srwatson
2444113482Srwatson	MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2445100979Srwatson}
2446100979Srwatson
2447100979Srwatsonvoid
2448100979Srwatsonmac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2449100979Srwatson{
2450113482Srwatson	struct label *label;
2451100979Srwatson
2452113482Srwatson	label = mbuf_to_label(mbuf);
2453113482Srwatson
2454100979Srwatson	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2455113482Srwatson	    label);
2456100979Srwatson}
2457100979Srwatson
2458100979Srwatsonvoid
2459100979Srwatsonmac_create_mount(struct ucred *cred, struct mount *mp)
2460100979Srwatson{
2461100979Srwatson
2462100979Srwatson	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2463100979Srwatson	    &mp->mnt_fslabel);
2464100979Srwatson}
2465100979Srwatson
2466100979Srwatsonvoid
2467100979Srwatsonmac_create_root_mount(struct ucred *cred, struct mount *mp)
2468100979Srwatson{
2469100979Srwatson
2470100979Srwatson	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2471100979Srwatson	    &mp->mnt_fslabel);
2472100979Srwatson}
2473100979Srwatson
2474100979Srwatsonint
2475100979Srwatsonmac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2476100979Srwatson{
2477100979Srwatson	int error;
2478100979Srwatson
2479100979Srwatson	if (!mac_enforce_network)
2480100979Srwatson		return (0);
2481100979Srwatson
2482100979Srwatson	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2483100979Srwatson	    &ifnet->if_label);
2484100979Srwatson
2485100979Srwatson	return (error);
2486100979Srwatson}
2487100979Srwatson
2488100979Srwatsonstatic int
2489100979Srwatsonmac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2490100979Srwatson{
2491100979Srwatson	int error;
2492100979Srwatson
2493100979Srwatson	MAC_CHECK(check_cred_relabel, cred, newlabel);
2494100979Srwatson
2495100979Srwatson	return (error);
2496100979Srwatson}
2497100979Srwatson
2498100979Srwatsonint
2499100979Srwatsonmac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2500100979Srwatson{
2501100979Srwatson	int error;
2502100979Srwatson
2503100979Srwatson	if (!mac_enforce_process)
2504100979Srwatson		return (0);
2505100979Srwatson
2506100979Srwatson	MAC_CHECK(check_cred_visible, u1, u2);
2507100979Srwatson
2508100979Srwatson	return (error);
2509100979Srwatson}
2510100979Srwatson
2511100979Srwatsonint
2512100979Srwatsonmac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2513100979Srwatson{
2514113482Srwatson	struct label *label;
2515100979Srwatson	int error;
2516100979Srwatson
2517113487Srwatson	M_ASSERTPKTHDR(mbuf);
2518113487Srwatson
2519100979Srwatson	if (!mac_enforce_network)
2520100979Srwatson		return (0);
2521100979Srwatson
2522113482Srwatson	label = mbuf_to_label(mbuf);
2523100979Srwatson
2524100979Srwatson	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2525113482Srwatson	    label);
2526100979Srwatson
2527100979Srwatson	return (error);
2528100979Srwatson}
2529100979Srwatson
2530100979Srwatsonint
2531106308Srwatsonmac_check_kenv_dump(struct ucred *cred)
2532106308Srwatson{
2533106308Srwatson	int error;
2534106308Srwatson
2535106308Srwatson	if (!mac_enforce_system)
2536106308Srwatson		return (0);
2537106308Srwatson
2538106308Srwatson	MAC_CHECK(check_kenv_dump, cred);
2539106308Srwatson
2540106308Srwatson	return (error);
2541106308Srwatson}
2542106308Srwatson
2543106308Srwatsonint
2544106308Srwatsonmac_check_kenv_get(struct ucred *cred, char *name)
2545106308Srwatson{
2546106308Srwatson	int error;
2547106308Srwatson
2548106308Srwatson	if (!mac_enforce_system)
2549106308Srwatson		return (0);
2550106308Srwatson
2551106308Srwatson	MAC_CHECK(check_kenv_get, cred, name);
2552106308Srwatson
2553106308Srwatson	return (error);
2554106308Srwatson}
2555106308Srwatson
2556106308Srwatsonint
2557106308Srwatsonmac_check_kenv_set(struct ucred *cred, char *name, char *value)
2558106308Srwatson{
2559106308Srwatson	int error;
2560106308Srwatson
2561106308Srwatson	if (!mac_enforce_system)
2562106308Srwatson		return (0);
2563106308Srwatson
2564106308Srwatson	MAC_CHECK(check_kenv_set, cred, name, value);
2565106308Srwatson
2566106308Srwatson	return (error);
2567106308Srwatson}
2568106308Srwatson
2569106308Srwatsonint
2570106308Srwatsonmac_check_kenv_unset(struct ucred *cred, char *name)
2571106308Srwatson{
2572106308Srwatson	int error;
2573106308Srwatson
2574106308Srwatson	if (!mac_enforce_system)
2575106308Srwatson		return (0);
2576106308Srwatson
2577106308Srwatson	MAC_CHECK(check_kenv_unset, cred, name);
2578106308Srwatson
2579106308Srwatson	return (error);
2580106308Srwatson}
2581106308Srwatson
2582106308Srwatsonint
2583107089Srwatsonmac_check_kld_load(struct ucred *cred, struct vnode *vp)
2584107089Srwatson{
2585107089Srwatson	int error;
2586107089Srwatson
2587107089Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2588107089Srwatson
2589107089Srwatson	if (!mac_enforce_kld)
2590107089Srwatson		return (0);
2591107089Srwatson
2592107089Srwatson	MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2593107089Srwatson
2594107089Srwatson	return (error);
2595107089Srwatson}
2596107089Srwatson
2597107089Srwatsonint
2598107089Srwatsonmac_check_kld_stat(struct ucred *cred)
2599107089Srwatson{
2600107089Srwatson	int error;
2601107089Srwatson
2602107089Srwatson	if (!mac_enforce_kld)
2603107089Srwatson		return (0);
2604107089Srwatson
2605107089Srwatson	MAC_CHECK(check_kld_stat, cred);
2606107089Srwatson
2607107089Srwatson	return (error);
2608107089Srwatson}
2609107089Srwatson
2610107089Srwatsonint
2611107089Srwatsonmac_check_kld_unload(struct ucred *cred)
2612107089Srwatson{
2613107089Srwatson	int error;
2614107089Srwatson
2615107089Srwatson	if (!mac_enforce_kld)
2616107089Srwatson		return (0);
2617107089Srwatson
2618107089Srwatson	MAC_CHECK(check_kld_unload, cred);
2619107089Srwatson
2620107089Srwatson	return (error);
2621107089Srwatson}
2622107089Srwatson
2623107089Srwatsonint
2624100979Srwatsonmac_check_mount_stat(struct ucred *cred, struct mount *mount)
2625100979Srwatson{
2626100979Srwatson	int error;
2627100979Srwatson
2628100979Srwatson	if (!mac_enforce_fs)
2629100979Srwatson		return (0);
2630100979Srwatson
2631100979Srwatson	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2632100979Srwatson
2633100979Srwatson	return (error);
2634100979Srwatson}
2635100979Srwatson
2636100979Srwatsonint
2637100979Srwatsonmac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2638100979Srwatson    void *data)
2639100979Srwatson{
2640100979Srwatson	int error;
2641100979Srwatson
2642104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2643104269Srwatson
2644104269Srwatson	if (!mac_enforce_pipe)
2645104269Srwatson		return (0);
2646104269Srwatson
2647100979Srwatson	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2648100979Srwatson
2649100979Srwatson	return (error);
2650100979Srwatson}
2651100979Srwatson
2652100979Srwatsonint
2653102115Srwatsonmac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2654100979Srwatson{
2655100979Srwatson	int error;
2656100979Srwatson
2657104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2658104269Srwatson
2659104269Srwatson	if (!mac_enforce_pipe)
2660104269Srwatson		return (0);
2661104269Srwatson
2662102115Srwatson	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2663100979Srwatson
2664100979Srwatson	return (error);
2665100979Srwatson}
2666100979Srwatson
2667102115Srwatsonint
2668102115Srwatsonmac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2669102115Srwatson{
2670102115Srwatson	int error;
2671102115Srwatson
2672104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2673104269Srwatson
2674104269Srwatson	if (!mac_enforce_pipe)
2675104269Srwatson		return (0);
2676104269Srwatson
2677102115Srwatson	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2678102115Srwatson
2679102115Srwatson	return (error);
2680102115Srwatson}
2681102115Srwatson
2682100979Srwatsonstatic int
2683100979Srwatsonmac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2684100979Srwatson    struct label *newlabel)
2685100979Srwatson{
2686100979Srwatson	int error;
2687100979Srwatson
2688104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2689104269Srwatson
2690104269Srwatson	if (!mac_enforce_pipe)
2691104269Srwatson		return (0);
2692104269Srwatson
2693100979Srwatson	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2694100979Srwatson
2695100979Srwatson	return (error);
2696100979Srwatson}
2697100979Srwatson
2698100979Srwatsonint
2699102115Srwatsonmac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2700102115Srwatson{
2701102115Srwatson	int error;
2702102115Srwatson
2703104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2704104269Srwatson
2705104269Srwatson	if (!mac_enforce_pipe)
2706104269Srwatson		return (0);
2707104269Srwatson
2708102115Srwatson	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2709102115Srwatson
2710102115Srwatson	return (error);
2711102115Srwatson}
2712102115Srwatson
2713102115Srwatsonint
2714102115Srwatsonmac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2715102115Srwatson{
2716102115Srwatson	int error;
2717102115Srwatson
2718104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2719104269Srwatson
2720104269Srwatson	if (!mac_enforce_pipe)
2721104269Srwatson		return (0);
2722104269Srwatson
2723102115Srwatson	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2724102115Srwatson
2725102115Srwatson	return (error);
2726102115Srwatson}
2727102115Srwatson
2728102115Srwatsonint
2729100979Srwatsonmac_check_proc_debug(struct ucred *cred, struct proc *proc)
2730100979Srwatson{
2731100979Srwatson	int error;
2732100979Srwatson
2733102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2734102103Srwatson
2735100979Srwatson	if (!mac_enforce_process)
2736100979Srwatson		return (0);
2737100979Srwatson
2738100979Srwatson	MAC_CHECK(check_proc_debug, cred, proc);
2739100979Srwatson
2740100979Srwatson	return (error);
2741100979Srwatson}
2742100979Srwatson
2743100979Srwatsonint
2744100979Srwatsonmac_check_proc_sched(struct ucred *cred, struct proc *proc)
2745100979Srwatson{
2746100979Srwatson	int error;
2747100979Srwatson
2748102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2749102103Srwatson
2750100979Srwatson	if (!mac_enforce_process)
2751100979Srwatson		return (0);
2752100979Srwatson
2753100979Srwatson	MAC_CHECK(check_proc_sched, cred, proc);
2754100979Srwatson
2755100979Srwatson	return (error);
2756100979Srwatson}
2757100979Srwatson
2758100979Srwatsonint
2759100979Srwatsonmac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2760100979Srwatson{
2761100979Srwatson	int error;
2762100979Srwatson
2763102103Srwatson	PROC_LOCK_ASSERT(proc, MA_OWNED);
2764102103Srwatson
2765100979Srwatson	if (!mac_enforce_process)
2766100979Srwatson		return (0);
2767100979Srwatson
2768100979Srwatson	MAC_CHECK(check_proc_signal, cred, proc, signum);
2769100979Srwatson
2770100979Srwatson	return (error);
2771100979Srwatson}
2772100979Srwatson
2773100979Srwatsonint
2774100979Srwatsonmac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2775100979Srwatson    struct sockaddr *sockaddr)
2776100979Srwatson{
2777100979Srwatson	int error;
2778100979Srwatson
2779100979Srwatson	if (!mac_enforce_socket)
2780100979Srwatson		return (0);
2781100979Srwatson
2782100979Srwatson	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2783100979Srwatson	    sockaddr);
2784100979Srwatson
2785100979Srwatson	return (error);
2786100979Srwatson}
2787100979Srwatson
2788100979Srwatsonint
2789100979Srwatsonmac_check_socket_connect(struct ucred *cred, struct socket *socket,
2790100979Srwatson    struct sockaddr *sockaddr)
2791100979Srwatson{
2792100979Srwatson	int error;
2793100979Srwatson
2794100979Srwatson	if (!mac_enforce_socket)
2795100979Srwatson		return (0);
2796100979Srwatson
2797100979Srwatson	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2798100979Srwatson	    sockaddr);
2799100979Srwatson
2800100979Srwatson	return (error);
2801100979Srwatson}
2802100979Srwatson
2803100979Srwatsonint
2804101933Srwatsonmac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2805100979Srwatson{
2806113482Srwatson	struct label *label;
2807100979Srwatson	int error;
2808100979Srwatson
2809100979Srwatson	if (!mac_enforce_socket)
2810100979Srwatson		return (0);
2811100979Srwatson
2812113482Srwatson	label = mbuf_to_label(mbuf);
2813113482Srwatson
2814101933Srwatson	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2815113482Srwatson	    label);
2816101933Srwatson
2817100979Srwatson	return (error);
2818100979Srwatson}
2819100979Srwatson
2820100979Srwatsonint
2821101933Srwatsonmac_check_socket_listen(struct ucred *cred, struct socket *socket)
2822100979Srwatson{
2823100979Srwatson	int error;
2824100979Srwatson
2825100979Srwatson	if (!mac_enforce_socket)
2826100979Srwatson		return (0);
2827100979Srwatson
2828101933Srwatson	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2829100979Srwatson	return (error);
2830100979Srwatson}
2831100979Srwatson
2832104571Srwatsonint
2833104571Srwatsonmac_check_socket_receive(struct ucred *cred, struct socket *so)
2834104571Srwatson{
2835104571Srwatson	int error;
2836104571Srwatson
2837104571Srwatson	if (!mac_enforce_socket)
2838104571Srwatson		return (0);
2839104571Srwatson
2840104571Srwatson	MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2841104571Srwatson
2842104571Srwatson	return (error);
2843104571Srwatson}
2844104571Srwatson
2845100979Srwatsonstatic int
2846100979Srwatsonmac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2847100979Srwatson    struct label *newlabel)
2848100979Srwatson{
2849100979Srwatson	int error;
2850100979Srwatson
2851100979Srwatson	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2852100979Srwatson	    newlabel);
2853100979Srwatson
2854100979Srwatson	return (error);
2855100979Srwatson}
2856100979Srwatson
2857100979Srwatsonint
2858104571Srwatsonmac_check_socket_send(struct ucred *cred, struct socket *so)
2859104571Srwatson{
2860104571Srwatson	int error;
2861104571Srwatson
2862104571Srwatson	if (!mac_enforce_socket)
2863104571Srwatson		return (0);
2864104571Srwatson
2865104571Srwatson	MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2866104571Srwatson
2867104571Srwatson	return (error);
2868104571Srwatson}
2869104571Srwatson
2870104571Srwatsonint
2871100979Srwatsonmac_check_socket_visible(struct ucred *cred, struct socket *socket)
2872100979Srwatson{
2873100979Srwatson	int error;
2874100979Srwatson
2875100979Srwatson	if (!mac_enforce_socket)
2876100979Srwatson		return (0);
2877105694Srwatson
2878100979Srwatson	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2879105694Srwatson
2880100979Srwatson	return (error);
2881100979Srwatson}
2882100979Srwatson
2883100979Srwatsonint
2884111939Srwatsonmac_check_sysarch_ioperm(struct ucred *cred)
2885111939Srwatson{
2886111939Srwatson	int error;
2887111939Srwatson
2888111939Srwatson	if (!mac_enforce_system)
2889111939Srwatson		return (0);
2890111939Srwatson
2891111939Srwatson	MAC_CHECK(check_sysarch_ioperm, cred);
2892111939Srwatson	return (error);
2893111939Srwatson}
2894111939Srwatson
2895111939Srwatsonint
2896106412Srwatsonmac_check_system_acct(struct ucred *cred, struct vnode *vp)
2897106412Srwatson{
2898106412Srwatson	int error;
2899106412Srwatson
2900106412Srwatson	if (vp != NULL) {
2901106412Srwatson		ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2902106412Srwatson	}
2903106412Srwatson
2904106412Srwatson	if (!mac_enforce_system)
2905106412Srwatson		return (0);
2906106412Srwatson
2907106412Srwatson	MAC_CHECK(check_system_acct, cred, vp,
2908106412Srwatson	    vp != NULL ? &vp->v_label : NULL);
2909106412Srwatson
2910106412Srwatson	return (error);
2911106412Srwatson}
2912106412Srwatson
2913106412Srwatsonint
2914106412Srwatsonmac_check_system_nfsd(struct ucred *cred)
2915106412Srwatson{
2916106412Srwatson	int error;
2917106412Srwatson
2918106412Srwatson	if (!mac_enforce_system)
2919106412Srwatson		return (0);
2920106412Srwatson
2921106412Srwatson	MAC_CHECK(check_system_nfsd, cred);
2922106412Srwatson
2923106412Srwatson	return (error);
2924106412Srwatson}
2925106412Srwatson
2926106412Srwatsonint
2927106024Srwatsonmac_check_system_reboot(struct ucred *cred, int howto)
2928106024Srwatson{
2929106024Srwatson	int error;
2930106024Srwatson
2931106045Srwatson	if (!mac_enforce_system)
2932106024Srwatson		return (0);
2933106024Srwatson
2934106024Srwatson	MAC_CHECK(check_system_reboot, cred, howto);
2935106045Srwatson
2936106024Srwatson	return (error);
2937106024Srwatson}
2938106024Srwatson
2939106024Srwatsonint
2940106369Srwatsonmac_check_system_settime(struct ucred *cred)
2941106369Srwatson{
2942106369Srwatson	int error;
2943106369Srwatson
2944106369Srwatson	if (!mac_enforce_system)
2945106369Srwatson		return (0);
2946106369Srwatson
2947106369Srwatson	MAC_CHECK(check_system_settime, cred);
2948106369Srwatson
2949106369Srwatson	return (error);
2950106369Srwatson}
2951106369Srwatson
2952106369Srwatsonint
2953106023Srwatsonmac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2954106023Srwatson{
2955106023Srwatson	int error;
2956106023Srwatson
2957106023Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2958106023Srwatson
2959106045Srwatson	if (!mac_enforce_system)
2960106023Srwatson		return (0);
2961106023Srwatson
2962106023Srwatson	MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2963106023Srwatson	return (error);
2964106023Srwatson}
2965106023Srwatson
2966106023Srwatsonint
2967111936Srwatsonmac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2968111936Srwatson{
2969111936Srwatson	int error;
2970111936Srwatson
2971111936Srwatson	ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2972111936Srwatson
2973111936Srwatson	if (!mac_enforce_system)
2974111936Srwatson		return (0);
2975111936Srwatson
2976111936Srwatson	MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2977111936Srwatson	return (error);
2978111936Srwatson}
2979111936Srwatson
2980111936Srwatsonint
2981106025Srwatsonmac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2982106025Srwatson    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2983106025Srwatson{
2984106025Srwatson	int error;
2985106025Srwatson
2986106025Srwatson	/*
2987106025Srwatson	 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2988106025Srwatson	 * but since it's not exported from kern_sysctl.c, we can't.
2989106025Srwatson	 */
2990106045Srwatson	if (!mac_enforce_system)
2991106025Srwatson		return (0);
2992106025Srwatson
2993106025Srwatson	MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2994106025Srwatson	    inkernel, new, newlen);
2995106025Srwatson
2996106025Srwatson	return (error);
2997106025Srwatson}
2998106025Srwatson
2999106025Srwatsonint
3000100979Srwatsonmac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3001100979Srwatson    struct ifnet *ifnet)
3002100979Srwatson{
3003105694Srwatson	char *elements, *buffer;
3004105694Srwatson	struct mac mac;
3005100979Srwatson	int error;
3006100979Srwatson
3007105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3008100979Srwatson	if (error)
3009100979Srwatson		return (error);
3010100979Srwatson
3011105694Srwatson	error = mac_check_structmac_consistent(&mac);
3012105694Srwatson	if (error)
3013105694Srwatson		return (error);
3014105694Srwatson
3015111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3016105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3017105694Srwatson	if (error) {
3018105694Srwatson		free(elements, M_MACTEMP);
3019105694Srwatson		return (error);
3020105694Srwatson	}
3021105694Srwatson
3022111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3023105694Srwatson	error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3024111119Simp	    buffer, mac.m_buflen, M_WAITOK);
3025105694Srwatson	if (error == 0)
3026105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3027105694Srwatson
3028105694Srwatson	free(buffer, M_MACTEMP);
3029105694Srwatson	free(elements, M_MACTEMP);
3030105694Srwatson
3031105694Srwatson	return (error);
3032100979Srwatson}
3033100979Srwatson
3034100979Srwatsonint
3035100979Srwatsonmac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3036100979Srwatson    struct ifnet *ifnet)
3037100979Srwatson{
3038100979Srwatson	struct label intlabel;
3039105694Srwatson	struct mac mac;
3040105694Srwatson	char *buffer;
3041100979Srwatson	int error;
3042100979Srwatson
3043105694Srwatson	error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3044100979Srwatson	if (error)
3045100979Srwatson		return (error);
3046100979Srwatson
3047105694Srwatson	error = mac_check_structmac_consistent(&mac);
3048100979Srwatson	if (error)
3049100979Srwatson		return (error);
3050100979Srwatson
3051111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3052105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3053105694Srwatson	if (error) {
3054105694Srwatson		free(buffer, M_MACTEMP);
3055105694Srwatson		return (error);
3056105694Srwatson	}
3057105694Srwatson
3058105694Srwatson	mac_init_ifnet_label(&intlabel);
3059105694Srwatson	error = mac_internalize_ifnet_label(&intlabel, buffer);
3060105694Srwatson	free(buffer, M_MACTEMP);
3061105694Srwatson	if (error) {
3062105694Srwatson		mac_destroy_ifnet_label(&intlabel);
3063105694Srwatson		return (error);
3064105694Srwatson	}
3065105694Srwatson
3066100979Srwatson	/*
3067100979Srwatson	 * XXX: Note that this is a redundant privilege check, since
3068100979Srwatson	 * policies impose this check themselves if required by the
3069100979Srwatson	 * policy.  Eventually, this should go away.
3070100979Srwatson	 */
3071100979Srwatson	error = suser_cred(cred, 0);
3072105694Srwatson	if (error) {
3073105694Srwatson		mac_destroy_ifnet_label(&intlabel);
3074105694Srwatson		return (error);
3075105694Srwatson	}
3076100979Srwatson
3077100979Srwatson	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3078100979Srwatson	    &intlabel);
3079105694Srwatson	if (error) {
3080105694Srwatson		mac_destroy_ifnet_label(&intlabel);
3081105694Srwatson		return (error);
3082105694Srwatson	}
3083100979Srwatson
3084100979Srwatson	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3085100979Srwatson
3086105694Srwatson	mac_destroy_ifnet_label(&intlabel);
3087105694Srwatson	return (0);
3088100979Srwatson}
3089100979Srwatson
3090100979Srwatsonvoid
3091107698Srwatsonmac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
3092100979Srwatson{
3093100979Srwatson
3094107698Srwatson	MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3095100979Srwatson}
3096100979Srwatson
3097104533Srwatsonvoid
3098107698Srwatsonmac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3099107698Srwatson    struct devfs_dirent *dd, struct devfs_dirent *de)
3100104533Srwatson{
3101104533Srwatson
3102107698Srwatson	MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3103104533Srwatson	    &de->de_label);
3104104533Srwatson}
3105104533Srwatson
3106100979Srwatsonvoid
3107107698Srwatsonmac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3108100979Srwatson    struct devfs_dirent *de)
3109100979Srwatson{
3110100979Srwatson
3111107698Srwatson	MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3112100979Srwatson	    &de->de_label);
3113100979Srwatson}
3114100979Srwatson
3115100979Srwatsonint
3116100979Srwatsonmac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3117105694Srwatson    struct mac *mac)
3118100979Srwatson{
3119100979Srwatson	struct label intlabel;
3120105694Srwatson	char *buffer;
3121100979Srwatson	int error;
3122100979Srwatson
3123105694Srwatson	error = mac_check_structmac_consistent(mac);
3124100979Srwatson	if (error)
3125100979Srwatson		return (error);
3126100979Srwatson
3127111119Simp	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3128105694Srwatson	error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3129105694Srwatson	if (error) {
3130105694Srwatson		free(buffer, M_MACTEMP);
3131105694Srwatson		return (error);
3132105694Srwatson	}
3133105694Srwatson
3134111119Simp	mac_init_socket_label(&intlabel, M_WAITOK);
3135105694Srwatson	error = mac_internalize_socket_label(&intlabel, buffer);
3136105694Srwatson	free(buffer, M_MACTEMP);
3137105694Srwatson	if (error) {
3138105694Srwatson		mac_destroy_socket_label(&intlabel);
3139105694Srwatson		return (error);
3140105694Srwatson	}
3141105694Srwatson
3142100979Srwatson	mac_check_socket_relabel(cred, so, &intlabel);
3143100979Srwatson	if (error) {
3144105694Srwatson		mac_destroy_socket_label(&intlabel);
3145100979Srwatson		return (error);
3146100979Srwatson	}
3147100979Srwatson
3148100979Srwatson	mac_relabel_socket(cred, so, &intlabel);
3149100979Srwatson
3150105694Srwatson	mac_destroy_socket_label(&intlabel);
3151100979Srwatson	return (0);
3152100979Srwatson}
3153100979Srwatson
3154100979Srwatsonint
3155100979Srwatsonmac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3156100979Srwatson{
3157100979Srwatson	int error;
3158100979Srwatson
3159104269Srwatson	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3160104269Srwatson
3161100979Srwatson	error = mac_check_pipe_relabel(cred, pipe, label);
3162100979Srwatson	if (error)
3163100979Srwatson		return (error);
3164100979Srwatson
3165100979Srwatson	mac_relabel_pipe(cred, pipe, label);
3166100979Srwatson
3167100979Srwatson	return (0);
3168100979Srwatson}
3169100979Srwatson
3170100979Srwatsonint
3171100979Srwatsonmac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3172105694Srwatson    struct mac *mac)
3173100979Srwatson{
3174105694Srwatson	char *buffer, *elements;
3175105694Srwatson	int error;
3176100979Srwatson
3177105694Srwatson	error = mac_check_structmac_consistent(mac);
3178105694Srwatson	if (error)
3179105694Srwatson		return (error);
3180105694Srwatson
3181111119Simp	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3182105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3183105694Srwatson	if (error) {
3184105694Srwatson		free(elements, M_MACTEMP);
3185105694Srwatson		return (error);
3186105694Srwatson	}
3187105694Srwatson
3188111119Simp	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3189105694Srwatson	error = mac_externalize_socket_label(&so->so_label, elements,
3190111119Simp	    buffer, mac->m_buflen, M_WAITOK);
3191105694Srwatson	if (error == 0)
3192105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3193105694Srwatson
3194105694Srwatson	free(buffer, M_MACTEMP);
3195105694Srwatson	free(elements, M_MACTEMP);
3196105694Srwatson
3197105694Srwatson	return (error);
3198100979Srwatson}
3199100979Srwatson
3200100979Srwatsonint
3201100979Srwatsonmac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3202105694Srwatson    struct mac *mac)
3203100979Srwatson{
3204105694Srwatson	char *elements, *buffer;
3205105694Srwatson	int error;
3206100979Srwatson
3207105694Srwatson	error = mac_check_structmac_consistent(mac);
3208105694Srwatson	if (error)
3209105694Srwatson		return (error);
3210105694Srwatson
3211111119Simp	elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3212105694Srwatson	error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3213105694Srwatson	if (error) {
3214105694Srwatson		free(elements, M_MACTEMP);
3215105694Srwatson		return (error);
3216105694Srwatson	}
3217105694Srwatson
3218111119Simp	buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3219105694Srwatson	error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3220111119Simp	    elements, buffer, mac->m_buflen, M_WAITOK);
3221105694Srwatson	if (error == 0)
3222105694Srwatson		error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3223105694Srwatson
3224105694Srwatson	free(buffer, M_MACTEMP);
3225105694Srwatson	free(elements, M_MACTEMP);
3226105694Srwatson
3227105694Srwatson	return (error);
3228100979Srwatson}
3229100979Srwatson
3230100979Srwatson/*
3231100979Srwatson * Implementation of VOP_SETLABEL() that relies on extended attributes
3232100979Srwatson * to store label data.  Can be referenced by filesystems supporting
3233100979Srwatson * extended attributes.
3234100979Srwatson */
3235100979Srwatsonint
3236100979Srwatsonvop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3237100979Srwatson{
3238100979Srwatson	struct vnode *vp = ap->a_vp;
3239100979Srwatson	struct label *intlabel = ap->a_label;
3240100979Srwatson	int error;
3241100979Srwatson
3242100979Srwatson	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3243100979Srwatson
3244105988Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3245105988Srwatson		return (EOPNOTSUPP);
3246100979Srwatson
3247105988Srwatson	error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3248100979Srwatson	if (error)
3249100979Srwatson		return (error);
3250100979Srwatson
3251100979Srwatson	mac_relabel_vnode(ap->a_cred, vp, intlabel);
3252100979Srwatson
3253100979Srwatson	return (0);
3254100979Srwatson}
3255100979Srwatson
3256100979Srwatsonstatic int
3257100979Srwatsonvn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3258100979Srwatson{
3259100979Srwatson	int error;
3260100979Srwatson
3261100979Srwatson	if (vp->v_mount == NULL) {
3262100979Srwatson		/* printf("vn_setlabel: null v_mount\n"); */
3263103314Snjl		if (vp->v_type != VNON)
3264103314Snjl			printf("vn_setlabel: null v_mount with non-VNON\n");
3265100979Srwatson		return (EBADF);
3266100979Srwatson	}
3267100979Srwatson
3268100979Srwatson	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3269100979Srwatson		return (EOPNOTSUPP);
3270100979Srwatson
3271100979Srwatson	/*
3272100979Srwatson	 * Multi-phase commit.  First check the policies to confirm the
3273100979Srwatson	 * change is OK.  Then commit via the filesystem.  Finally,
3274100979Srwatson	 * update the actual vnode label.  Question: maybe the filesystem
3275100979Srwatson	 * should update the vnode at the end as part of VOP_SETLABEL()?
3276100979Srwatson	 */
3277100979Srwatson	error = mac_check_vnode_relabel(cred, vp, intlabel);
3278100979Srwatson	if (error)
3279100979Srwatson		return (error);
3280100979Srwatson
3281100979Srwatson	/*
3282100979Srwatson	 * VADMIN provides the opportunity for the filesystem to make
3283100979Srwatson	 * decisions about who is and is not able to modify labels
3284100979Srwatson	 * and protections on files.  This might not be right.  We can't
3285100979Srwatson	 * assume VOP_SETLABEL() will do it, because we might implement
3286100979Srwatson	 * that as part of vop_stdsetlabel_ea().
3287100979Srwatson	 */
3288100979Srwatson	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3289100979Srwatson	if (error)
3290100979Srwatson		return (error);
3291100979Srwatson
3292100979Srwatson	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3293100979Srwatson	if (error)
3294100979Srwatson		return (error);
3295100979Srwatson
3296100979Srwatson	return (0);
3297100979Srwatson}
3298100979Srwatson
3299105694Srwatsonint
3300105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3301105694Srwatson{
3302105694Srwatson	char *elements, *buffer;
3303105694Srwatson	struct mac mac;
3304105694Srwatson	struct proc *tproc;
3305105694Srwatson	struct ucred *tcred;
3306105694Srwatson	int error;
3307105694Srwatson
3308107849Salfred	error = copyin(uap->mac_p, &mac, sizeof(mac));
3309105694Srwatson	if (error)
3310105694Srwatson		return (error);
3311105694Srwatson
3312105694Srwatson	error = mac_check_structmac_consistent(&mac);
3313105694Srwatson	if (error)
3314105694Srwatson		return (error);
3315105694Srwatson
3316105694Srwatson	tproc = pfind(uap->pid);
3317105694Srwatson	if (tproc == NULL)
3318105694Srwatson		return (ESRCH);
3319105694Srwatson
3320105694Srwatson	tcred = NULL;				/* Satisfy gcc. */
3321105694Srwatson	error = p_cansee(td, tproc);
3322105694Srwatson	if (error == 0)
3323105694Srwatson		tcred = crhold(tproc->p_ucred);
3324105694Srwatson	PROC_UNLOCK(tproc);
3325105694Srwatson	if (error)
3326105694Srwatson		return (error);
3327105694Srwatson
3328111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3329105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3330105694Srwatson	if (error) {
3331105694Srwatson		free(elements, M_MACTEMP);
3332105694Srwatson		crfree(tcred);
3333105694Srwatson		return (error);
3334105694Srwatson	}
3335105694Srwatson
3336111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3337105694Srwatson	error = mac_externalize_cred_label(&tcred->cr_label, elements,
3338111119Simp	    buffer, mac.m_buflen, M_WAITOK);
3339105694Srwatson	if (error == 0)
3340105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3341105694Srwatson
3342105694Srwatson	free(buffer, M_MACTEMP);
3343105694Srwatson	free(elements, M_MACTEMP);
3344105694Srwatson	crfree(tcred);
3345105694Srwatson	return (error);
3346105694Srwatson}
3347105694Srwatson
3348100979Srwatson/*
3349100979Srwatson * MPSAFE
3350100979Srwatson */
3351100979Srwatsonint
3352100894Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3353100894Srwatson{
3354105694Srwatson	char *elements, *buffer;
3355105694Srwatson	struct mac mac;
3356100979Srwatson	int error;
3357100894Srwatson
3358105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3359105694Srwatson	if (error)
3360105694Srwatson		return (error);
3361105694Srwatson
3362105694Srwatson	error = mac_check_structmac_consistent(&mac);
3363105694Srwatson	if (error)
3364105694Srwatson		return (error);
3365105694Srwatson
3366111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3367105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3368105694Srwatson	if (error) {
3369105694Srwatson		free(elements, M_MACTEMP);
3370105694Srwatson		return (error);
3371105694Srwatson	}
3372105694Srwatson
3373111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3374105694Srwatson	error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3375111119Simp	    elements, buffer, mac.m_buflen, M_WAITOK);
3376100979Srwatson	if (error == 0)
3377105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3378100979Srwatson
3379105694Srwatson	free(buffer, M_MACTEMP);
3380105694Srwatson	free(elements, M_MACTEMP);
3381100979Srwatson	return (error);
3382100979Srwatson}
3383100979Srwatson
3384100979Srwatson/*
3385100979Srwatson * MPSAFE
3386100979Srwatson */
3387100979Srwatsonint
3388100979Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3389100979Srwatson{
3390100979Srwatson	struct ucred *newcred, *oldcred;
3391105694Srwatson	struct label intlabel;
3392100979Srwatson	struct proc *p;
3393105694Srwatson	struct mac mac;
3394105694Srwatson	char *buffer;
3395100979Srwatson	int error;
3396100979Srwatson
3397105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3398100979Srwatson	if (error)
3399100979Srwatson		return (error);
3400100979Srwatson
3401105694Srwatson	error = mac_check_structmac_consistent(&mac);
3402100979Srwatson	if (error)
3403100979Srwatson		return (error);
3404100979Srwatson
3405111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3406105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3407105694Srwatson	if (error) {
3408105694Srwatson		free(buffer, M_MACTEMP);
3409105694Srwatson		return (error);
3410105694Srwatson	}
3411105694Srwatson
3412105694Srwatson	mac_init_cred_label(&intlabel);
3413105694Srwatson	error = mac_internalize_cred_label(&intlabel, buffer);
3414105694Srwatson	free(buffer, M_MACTEMP);
3415105694Srwatson	if (error) {
3416105694Srwatson		mac_destroy_cred_label(&intlabel);
3417105694Srwatson		return (error);
3418105694Srwatson	}
3419105694Srwatson
3420100979Srwatson	newcred = crget();
3421100979Srwatson
3422100979Srwatson	p = td->td_proc;
3423100979Srwatson	PROC_LOCK(p);
3424100979Srwatson	oldcred = p->p_ucred;
3425100979Srwatson
3426100979Srwatson	error = mac_check_cred_relabel(oldcred, &intlabel);
3427100979Srwatson	if (error) {
3428100979Srwatson		PROC_UNLOCK(p);
3429100979Srwatson		crfree(newcred);
3430105694Srwatson		goto out;
3431100979Srwatson	}
3432100979Srwatson
3433100979Srwatson	setsugid(p);
3434100979Srwatson	crcopy(newcred, oldcred);
3435100979Srwatson	mac_relabel_cred(newcred, &intlabel);
3436102136Srwatson	p->p_ucred = newcred;
3437100979Srwatson
3438102136Srwatson	/*
3439102136Srwatson	 * Grab additional reference for use while revoking mmaps, prior
3440102136Srwatson	 * to releasing the proc lock and sharing the cred.
3441102136Srwatson	 */
3442102136Srwatson	crhold(newcred);
3443100979Srwatson	PROC_UNLOCK(p);
3444102136Srwatson
3445105694Srwatson	if (mac_enforce_vm) {
3446105694Srwatson		mtx_lock(&Giant);
3447105694Srwatson		mac_cred_mmapped_drop_perms(td, newcred);
3448105694Srwatson		mtx_unlock(&Giant);
3449105694Srwatson	}
3450102136Srwatson
3451102136Srwatson	crfree(newcred);	/* Free revocation reference. */
3452100979Srwatson	crfree(oldcred);
3453105694Srwatson
3454105694Srwatsonout:
3455105694Srwatson	mac_destroy_cred_label(&intlabel);
3456105694Srwatson	return (error);
3457100979Srwatson}
3458100979Srwatson
3459100979Srwatson/*
3460100979Srwatson * MPSAFE
3461100979Srwatson */
3462100979Srwatsonint
3463100979Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3464100979Srwatson{
3465105694Srwatson	char *elements, *buffer;
3466105694Srwatson	struct label intlabel;
3467100979Srwatson	struct file *fp;
3468105694Srwatson	struct mac mac;
3469100979Srwatson	struct vnode *vp;
3470100979Srwatson	struct pipe *pipe;
3471105694Srwatson	short label_type;
3472100979Srwatson	int error;
3473100979Srwatson
3474105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3475105694Srwatson	if (error)
3476105694Srwatson		return (error);
3477100979Srwatson
3478105694Srwatson	error = mac_check_structmac_consistent(&mac);
3479105694Srwatson	if (error)
3480105694Srwatson		return (error);
3481105694Srwatson
3482111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3483105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3484105694Srwatson	if (error) {
3485105694Srwatson		free(elements, M_MACTEMP);
3486105694Srwatson		return (error);
3487105694Srwatson	}
3488105694Srwatson
3489111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3490105694Srwatson	mtx_lock(&Giant);				/* VFS */
3491107849Salfred	error = fget(td, uap->fd, &fp);
3492100979Srwatson	if (error)
3493100979Srwatson		goto out;
3494100979Srwatson
3495105694Srwatson	label_type = fp->f_type;
3496100979Srwatson	switch (fp->f_type) {
3497100979Srwatson	case DTYPE_FIFO:
3498100979Srwatson	case DTYPE_VNODE:
3499109153Sdillon		vp = fp->f_data;
3500100979Srwatson
3501105694Srwatson		mac_init_vnode_label(&intlabel);
3502105694Srwatson
3503100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3504105988Srwatson		mac_copy_vnode_label(&vp->v_label, &intlabel);
3505100979Srwatson		VOP_UNLOCK(vp, 0, td);
3506105694Srwatson
3507100979Srwatson		break;
3508100979Srwatson	case DTYPE_PIPE:
3509109153Sdillon		pipe = fp->f_data;
3510105694Srwatson
3511105694Srwatson		mac_init_pipe_label(&intlabel);
3512105694Srwatson
3513105694Srwatson		PIPE_LOCK(pipe);
3514105694Srwatson		mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3515105694Srwatson		PIPE_UNLOCK(pipe);
3516100979Srwatson		break;
3517100979Srwatson	default:
3518100979Srwatson		error = EINVAL;
3519105694Srwatson		fdrop(fp, td);
3520105694Srwatson		goto out;
3521100979Srwatson	}
3522105694Srwatson	fdrop(fp, td);
3523100979Srwatson
3524105694Srwatson	switch (label_type) {
3525105694Srwatson	case DTYPE_FIFO:
3526105694Srwatson	case DTYPE_VNODE:
3527105694Srwatson		if (error == 0)
3528105694Srwatson			error = mac_externalize_vnode_label(&intlabel,
3529111119Simp			    elements, buffer, mac.m_buflen, M_WAITOK);
3530105694Srwatson		mac_destroy_vnode_label(&intlabel);
3531105694Srwatson		break;
3532105694Srwatson	case DTYPE_PIPE:
3533105694Srwatson		error = mac_externalize_pipe_label(&intlabel, elements,
3534111119Simp		    buffer, mac.m_buflen, M_WAITOK);
3535105694Srwatson		mac_destroy_pipe_label(&intlabel);
3536105694Srwatson		break;
3537105694Srwatson	default:
3538105694Srwatson		panic("__mac_get_fd: corrupted label_type");
3539105694Srwatson	}
3540105694Srwatson
3541100979Srwatson	if (error == 0)
3542105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3543100979Srwatson
3544105694Srwatsonout:
3545105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3546105694Srwatson	free(buffer, M_MACTEMP);
3547105694Srwatson	free(elements, M_MACTEMP);
3548100979Srwatson
3549100979Srwatson	return (error);
3550100979Srwatson}
3551100979Srwatson
3552100979Srwatson/*
3553100979Srwatson * MPSAFE
3554100979Srwatson */
3555100979Srwatsonint
3556100979Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3557100979Srwatson{
3558105694Srwatson	char *elements, *buffer;
3559100979Srwatson	struct nameidata nd;
3560105694Srwatson	struct label intlabel;
3561105694Srwatson	struct mac mac;
3562100979Srwatson	int error;
3563100979Srwatson
3564105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3565105694Srwatson	if (error)
3566105694Srwatson		return (error);
3567105694Srwatson
3568105694Srwatson	error = mac_check_structmac_consistent(&mac);
3569105694Srwatson	if (error)
3570105694Srwatson		return (error);
3571105694Srwatson
3572111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3573105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3574105694Srwatson	if (error) {
3575105694Srwatson		free(elements, M_MACTEMP);
3576105694Srwatson		return (error);
3577105694Srwatson	}
3578105694Srwatson
3579111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3580105694Srwatson	mtx_lock(&Giant);				/* VFS */
3581105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3582105694Srwatson	    td);
3583100979Srwatson	error = namei(&nd);
3584100979Srwatson	if (error)
3585100979Srwatson		goto out;
3586100979Srwatson
3587105694Srwatson	mac_init_vnode_label(&intlabel);
3588105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3589105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3590111119Simp	    mac.m_buflen, M_WAITOK);
3591105694Srwatson
3592100979Srwatson	NDFREE(&nd, 0);
3593105694Srwatson	mac_destroy_vnode_label(&intlabel);
3594105694Srwatson
3595105694Srwatson	if (error == 0)
3596105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3597105694Srwatson
3598105694Srwatsonout:
3599105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3600105694Srwatson
3601105694Srwatson	free(buffer, M_MACTEMP);
3602105694Srwatson	free(elements, M_MACTEMP);
3603105694Srwatson
3604105694Srwatson	return (error);
3605105694Srwatson}
3606105694Srwatson
3607105694Srwatson/*
3608105694Srwatson * MPSAFE
3609105694Srwatson */
3610105694Srwatsonint
3611105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3612105694Srwatson{
3613105694Srwatson	char *elements, *buffer;
3614105694Srwatson	struct nameidata nd;
3615105694Srwatson	struct label intlabel;
3616105694Srwatson	struct mac mac;
3617105694Srwatson	int error;
3618105694Srwatson
3619105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3620100979Srwatson	if (error)
3621105694Srwatson		return (error);
3622105694Srwatson
3623105694Srwatson	error = mac_check_structmac_consistent(&mac);
3624105694Srwatson	if (error)
3625105694Srwatson		return (error);
3626105694Srwatson
3627111119Simp	elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3628105694Srwatson	error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3629105694Srwatson	if (error) {
3630105694Srwatson		free(elements, M_MACTEMP);
3631105694Srwatson		return (error);
3632105694Srwatson	}
3633105694Srwatson
3634111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3635105694Srwatson	mtx_lock(&Giant);				/* VFS */
3636105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3637105694Srwatson	    td);
3638105694Srwatson	error = namei(&nd);
3639105694Srwatson	if (error)
3640100979Srwatson		goto out;
3641100979Srwatson
3642105694Srwatson	mac_init_vnode_label(&intlabel);
3643105988Srwatson	mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3644105988Srwatson	error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3645111119Simp	    mac.m_buflen, M_WAITOK);
3646105694Srwatson	NDFREE(&nd, 0);
3647105694Srwatson	mac_destroy_vnode_label(&intlabel);
3648100979Srwatson
3649105694Srwatson	if (error == 0)
3650105694Srwatson		error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3651105694Srwatson
3652100979Srwatsonout:
3653105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3654105694Srwatson
3655105694Srwatson	free(buffer, M_MACTEMP);
3656105694Srwatson	free(elements, M_MACTEMP);
3657105694Srwatson
3658100979Srwatson	return (error);
3659100979Srwatson}
3660100979Srwatson
3661100979Srwatson/*
3662100979Srwatson * MPSAFE
3663100979Srwatson */
3664100979Srwatsonint
3665100979Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3666100979Srwatson{
3667105694Srwatson	struct label intlabel;
3668105694Srwatson	struct pipe *pipe;
3669100979Srwatson	struct file *fp;
3670100979Srwatson	struct mount *mp;
3671100979Srwatson	struct vnode *vp;
3672105694Srwatson	struct mac mac;
3673105694Srwatson	char *buffer;
3674100979Srwatson	int error;
3675100979Srwatson
3676105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3677100979Srwatson	if (error)
3678105694Srwatson		return (error);
3679100979Srwatson
3680105694Srwatson	error = mac_check_structmac_consistent(&mac);
3681100979Srwatson	if (error)
3682105694Srwatson		return (error);
3683100979Srwatson
3684111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3685105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3686105694Srwatson	if (error) {
3687105694Srwatson		free(buffer, M_MACTEMP);
3688105694Srwatson		return (error);
3689105694Srwatson	}
3690105694Srwatson
3691105694Srwatson	mtx_lock(&Giant);				/* VFS */
3692105694Srwatson
3693107849Salfred	error = fget(td, uap->fd, &fp);
3694100979Srwatson	if (error)
3695105694Srwatson		goto out;
3696100979Srwatson
3697100979Srwatson	switch (fp->f_type) {
3698100979Srwatson	case DTYPE_FIFO:
3699100979Srwatson	case DTYPE_VNODE:
3700105694Srwatson		mac_init_vnode_label(&intlabel);
3701105694Srwatson		error = mac_internalize_vnode_label(&intlabel, buffer);
3702105694Srwatson		if (error) {
3703105694Srwatson			mac_destroy_vnode_label(&intlabel);
3704105694Srwatson			break;
3705105694Srwatson		}
3706105694Srwatson
3707109153Sdillon		vp = fp->f_data;
3708100979Srwatson		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3709105694Srwatson		if (error != 0) {
3710105694Srwatson			mac_destroy_vnode_label(&intlabel);
3711100979Srwatson			break;
3712105694Srwatson		}
3713100979Srwatson
3714100979Srwatson		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3715100979Srwatson		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3716100979Srwatson		VOP_UNLOCK(vp, 0, td);
3717100979Srwatson		vn_finished_write(mp);
3718105694Srwatson
3719105694Srwatson		mac_destroy_vnode_label(&intlabel);
3720100979Srwatson		break;
3721105694Srwatson
3722100979Srwatson	case DTYPE_PIPE:
3723105694Srwatson		mac_init_pipe_label(&intlabel);
3724105694Srwatson		error = mac_internalize_pipe_label(&intlabel, buffer);
3725105694Srwatson		if (error == 0) {
3726109153Sdillon			pipe = fp->f_data;
3727105694Srwatson			PIPE_LOCK(pipe);
3728105694Srwatson			error = mac_pipe_label_set(td->td_ucred, pipe,
3729105694Srwatson			    &intlabel);
3730105694Srwatson			PIPE_UNLOCK(pipe);
3731105694Srwatson		}
3732105694Srwatson
3733105694Srwatson		mac_destroy_pipe_label(&intlabel);
3734100979Srwatson		break;
3735105694Srwatson
3736100979Srwatson	default:
3737100979Srwatson		error = EINVAL;
3738100979Srwatson	}
3739100979Srwatson
3740100979Srwatson	fdrop(fp, td);
3741105694Srwatsonout:
3742105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3743105694Srwatson
3744105694Srwatson	free(buffer, M_MACTEMP);
3745105694Srwatson
3746100979Srwatson	return (error);
3747100979Srwatson}
3748100979Srwatson
3749100979Srwatson/*
3750100979Srwatson * MPSAFE
3751100979Srwatson */
3752100979Srwatsonint
3753100979Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3754100979Srwatson{
3755105694Srwatson	struct label intlabel;
3756100979Srwatson	struct nameidata nd;
3757100979Srwatson	struct mount *mp;
3758105694Srwatson	struct mac mac;
3759105694Srwatson	char *buffer;
3760100979Srwatson	int error;
3761100979Srwatson
3762105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3763100979Srwatson	if (error)
3764105694Srwatson		return (error);
3765100979Srwatson
3766105694Srwatson	error = mac_check_structmac_consistent(&mac);
3767100979Srwatson	if (error)
3768105694Srwatson		return (error);
3769100979Srwatson
3770111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3771105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3772105694Srwatson	if (error) {
3773105694Srwatson		free(buffer, M_MACTEMP);
3774105694Srwatson		return (error);
3775105694Srwatson	}
3776105694Srwatson
3777105694Srwatson	mac_init_vnode_label(&intlabel);
3778105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3779105694Srwatson	free(buffer, M_MACTEMP);
3780105694Srwatson	if (error) {
3781105694Srwatson		mac_destroy_vnode_label(&intlabel);
3782105694Srwatson		return (error);
3783105694Srwatson	}
3784105694Srwatson
3785105694Srwatson	mtx_lock(&Giant);				/* VFS */
3786105694Srwatson
3787105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3788105694Srwatson	    td);
3789100979Srwatson	error = namei(&nd);
3790105694Srwatson	if (error == 0) {
3791105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3792105694Srwatson		if (error == 0)
3793105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3794105694Srwatson			    td->td_ucred);
3795105694Srwatson		vn_finished_write(mp);
3796105694Srwatson	}
3797105694Srwatson
3798105694Srwatson	NDFREE(&nd, 0);
3799105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3800105694Srwatson	mac_destroy_vnode_label(&intlabel);
3801105694Srwatson
3802105694Srwatson	return (error);
3803105694Srwatson}
3804105694Srwatson
3805105694Srwatson/*
3806105694Srwatson * MPSAFE
3807105694Srwatson */
3808105694Srwatsonint
3809105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3810105694Srwatson{
3811105694Srwatson	struct label intlabel;
3812105694Srwatson	struct nameidata nd;
3813105694Srwatson	struct mount *mp;
3814105694Srwatson	struct mac mac;
3815105694Srwatson	char *buffer;
3816105694Srwatson	int error;
3817105694Srwatson
3818105694Srwatson	error = copyin(uap->mac_p, &mac, sizeof(mac));
3819100979Srwatson	if (error)
3820105694Srwatson		return (error);
3821105694Srwatson
3822105694Srwatson	error = mac_check_structmac_consistent(&mac);
3823100979Srwatson	if (error)
3824105694Srwatson		return (error);
3825100979Srwatson
3826111119Simp	buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3827105694Srwatson	error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3828105694Srwatson	if (error) {
3829105694Srwatson		free(buffer, M_MACTEMP);
3830105694Srwatson		return (error);
3831105694Srwatson	}
3832105694Srwatson
3833105694Srwatson	mac_init_vnode_label(&intlabel);
3834105694Srwatson	error = mac_internalize_vnode_label(&intlabel, buffer);
3835105694Srwatson	free(buffer, M_MACTEMP);
3836105694Srwatson	if (error) {
3837105694Srwatson		mac_destroy_vnode_label(&intlabel);
3838105694Srwatson		return (error);
3839105694Srwatson	}
3840105694Srwatson
3841105694Srwatson	mtx_lock(&Giant);				/* VFS */
3842105694Srwatson
3843105694Srwatson	NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3844105694Srwatson	    td);
3845105694Srwatson	error = namei(&nd);
3846105694Srwatson	if (error == 0) {
3847105694Srwatson		error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3848105694Srwatson		if (error == 0)
3849105694Srwatson			error = vn_setlabel(nd.ni_vp, &intlabel,
3850105694Srwatson			    td->td_ucred);
3851105694Srwatson		vn_finished_write(mp);
3852105694Srwatson	}
3853105694Srwatson
3854100979Srwatson	NDFREE(&nd, 0);
3855105694Srwatson	mtx_unlock(&Giant);				/* VFS */
3856105694Srwatson	mac_destroy_vnode_label(&intlabel);
3857105694Srwatson
3858100979Srwatson	return (error);
3859100979Srwatson}
3860100979Srwatson
3861105694Srwatson/*
3862105694Srwatson * MPSAFE
3863105694Srwatson */
3864102123Srwatsonint
3865102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3866102123Srwatson{
3867102123Srwatson	struct mac_policy_conf *mpc;
3868102123Srwatson	char target[MAC_MAX_POLICY_NAME];
3869114806Srwatson	int entrycount, error;
3870102123Srwatson
3871107849Salfred	error = copyinstr(uap->policy, target, sizeof(target), NULL);
3872102123Srwatson	if (error)
3873102123Srwatson		return (error);
3874102123Srwatson
3875102123Srwatson	error = ENOSYS;
3876102123Srwatson	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3877102123Srwatson		if (strcmp(mpc->mpc_name, target) == 0 &&
3878102123Srwatson		    mpc->mpc_ops->mpo_syscall != NULL) {
3879102123Srwatson			error = mpc->mpc_ops->mpo_syscall(td,
3880107849Salfred			    uap->call, uap->arg);
3881102123Srwatson			goto out;
3882102123Srwatson		}
3883102123Srwatson	}
3884102123Srwatson
3885114806Srwatson	if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
3886114806Srwatson		LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3887114806Srwatson			if (strcmp(mpc->mpc_name, target) == 0 &&
3888114806Srwatson			    mpc->mpc_ops->mpo_syscall != NULL) {
3889114806Srwatson				error = mpc->mpc_ops->mpo_syscall(td,
3890114806Srwatson				    uap->call, uap->arg);
3891114806Srwatson				break;
3892114806Srwatson			}
3893114806Srwatson		}
3894114806Srwatson		mac_policy_list_unbusy();
3895114806Srwatson	}
3896102123Srwatsonout:
3897102123Srwatson	return (error);
3898102123Srwatson}
3899102123Srwatson
3900100979SrwatsonSYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3901100979SrwatsonSYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3902100979Srwatson
3903100979Srwatson#else /* !MAC */
3904100979Srwatson
3905100979Srwatsonint
3906105694Srwatson__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3907105694Srwatson{
3908105694Srwatson
3909105694Srwatson	return (ENOSYS);
3910105694Srwatson}
3911105694Srwatson
3912105694Srwatsonint
3913100979Srwatson__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3914100979Srwatson{
3915100979Srwatson
3916100894Srwatson	return (ENOSYS);
3917100894Srwatson}
3918100894Srwatson
3919100894Srwatsonint
3920100894Srwatson__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3921100894Srwatson{
3922100894Srwatson
3923100894Srwatson	return (ENOSYS);
3924100894Srwatson}
3925100894Srwatson
3926100894Srwatsonint
3927100894Srwatson__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3928100894Srwatson{
3929100894Srwatson
3930100894Srwatson	return (ENOSYS);
3931100894Srwatson}
3932100894Srwatson
3933100894Srwatsonint
3934100894Srwatson__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3935100894Srwatson{
3936100894Srwatson
3937100894Srwatson	return (ENOSYS);
3938100894Srwatson}
3939100894Srwatson
3940100894Srwatsonint
3941105694Srwatson__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3942105694Srwatson{
3943105694Srwatson
3944105694Srwatson	return (ENOSYS);
3945105694Srwatson}
3946105694Srwatson
3947105694Srwatsonint
3948100894Srwatson__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3949100894Srwatson{
3950100894Srwatson
3951100894Srwatson	return (ENOSYS);
3952100894Srwatson}
3953100894Srwatson
3954100894Srwatsonint
3955100894Srwatson__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3956100894Srwatson{
3957100894Srwatson
3958100894Srwatson	return (ENOSYS);
3959100894Srwatson}
3960100979Srwatson
3961102123Srwatsonint
3962105694Srwatson__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3963105694Srwatson{
3964105694Srwatson
3965105694Srwatson	return (ENOSYS);
3966105694Srwatson}
3967105694Srwatson
3968105694Srwatsonint
3969102123Srwatsonmac_syscall(struct thread *td, struct mac_syscall_args *uap)
3970102123Srwatson{
3971102123Srwatson
3972102123Srwatson	return (ENOSYS);
3973102123Srwatson}
3974102123Srwatson
3975105694Srwatson#endif
3976