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