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