Deleted Added
full compact
mac_framework.c (122454) mac_framework.c (122524)
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. This file contains
39 * Kernel and userland interface to the framework, policy registration
40 * and composition. Per-object interfaces, controls, and labeling may be
41 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*.
42 */
43
44#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. This file contains
39 * Kernel and userland interface to the framework, policy registration
40 * and composition. Per-object interfaces, controls, and labeling may be
41 * found in src/sys/mac/. Sample policies may be found in src/sys/mac*.
42 */
43
44#include <sys/cdefs.h>
45__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 122454 2003-11-11 03:40:04Z rwatson $");
45__FBSDID("$FreeBSD: head/sys/security/mac/mac_framework.c 122524 2003-11-12 03:14:31Z rwatson $");
46
47#include "opt_mac.h"
48#include "opt_devfs.h"
49
50#include <sys/param.h>
51#include <sys/condvar.h>
52#include <sys/extattr.h>
53#include <sys/imgact.h>
54#include <sys/kernel.h>
55#include <sys/lock.h>
56#include <sys/malloc.h>
57#include <sys/mutex.h>
58#include <sys/mac.h>
59#include <sys/module.h>
60#include <sys/proc.h>
61#include <sys/sbuf.h>
62#include <sys/systm.h>
63#include <sys/sysproto.h>
64#include <sys/sysent.h>
65#include <sys/vnode.h>
66#include <sys/mount.h>
67#include <sys/file.h>
68#include <sys/namei.h>
69#include <sys/socket.h>
70#include <sys/pipe.h>
71#include <sys/socketvar.h>
72#include <sys/sysctl.h>
73
74#include <vm/vm.h>
75#include <vm/pmap.h>
76#include <vm/vm_map.h>
77#include <vm/vm_object.h>
78
79#include <sys/mac_policy.h>
80
81#include <fs/devfs/devfs.h>
82
83#include <net/bpfdesc.h>
84#include <net/if.h>
85#include <net/if_var.h>
86
87#include <netinet/in.h>
88#include <netinet/ip_var.h>
89
90#include <security/mac/mac_internal.h>
91
92#ifdef MAC
93
94/*
95 * Declare that the kernel provides MAC support, version 1. This permits
96 * modules to refuse to be loaded if the necessary support isn't present,
97 * even if it's pre-boot.
98 */
99MODULE_VERSION(kernel_mac_support, 1);
100
101SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
102 "TrustedBSD MAC policy controls");
103
104#if MAC_MAX_SLOTS > 32
105#error "MAC_MAX_SLOTS too large"
106#endif
107
108static unsigned int mac_max_slots = MAC_MAX_SLOTS;
109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
110SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
111 &mac_max_slots, 0, "");
112
113/*
114 * Has the kernel started generating labeled objects yet? All read/write
115 * access to this variable is serialized during the boot process. Following
116 * the end of serialization, we don't update this flag; no locking.
117 */
118int mac_late = 0;
119
120/*
121 * Flag to indicate whether or not we should allocate label storage for
122 * new mbufs. Since most dynamic policies we currently work with don't
123 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
124 * unless specifically notified of interest. One result of this is
125 * that if a dynamically loaded policy requests mbuf labels, it must
126 * be able to deal with a NULL label being returned on any mbufs that
127 * were already in flight when the policy was loaded. Since the policy
128 * already has to deal with uninitialized labels, this probably won't
129 * be a problem. Note: currently no locking. Will this be a problem?
130 */
131#ifndef MAC_ALWAYS_LABEL_MBUF
132int mac_labelmbufs = 0;
133#endif
134
135#ifdef MAC_DEBUG
136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
137 "TrustedBSD MAC debug info");
138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
139 "TrustedBSD MAC object counters");
140
141static unsigned int nmactemp;
142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
143 &nmactemp, 0, "number of temporary labels in use");
144#endif
145
146static int mac_policy_register(struct mac_policy_conf *mpc);
147static int mac_policy_unregister(struct mac_policy_conf *mpc);
148
149MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
150
151/*
152 * mac_static_policy_list holds a list of policy modules that are not
153 * loaded while the system is "live", and cannot be unloaded. These
154 * policies can be invoked without holding the busy count.
155 *
156 * mac_policy_list stores the list of dynamic policies. A busy count is
157 * maintained for the list, stored in mac_policy_busy. The busy count
158 * is protected by mac_policy_mtx; the list may be modified only
159 * while the busy count is 0, requiring that the lock be held to
160 * prevent new references to the list from being acquired. For almost
161 * all operations, incrementing the busy count is sufficient to
162 * guarantee consistency, as the list cannot be modified while the
163 * busy count is elevated. For a few special operations involving a
164 * change to the list of active policies, the mtx itself must be held.
165 * A condition variable, mac_policy_cv, is used to signal potential
166 * exclusive consumers that they should try to acquire the lock if a
167 * first attempt at exclusive access fails.
168 */
169static struct mtx mac_policy_mtx;
170static struct cv mac_policy_cv;
171static int mac_policy_count;
172struct mac_policy_list_head mac_policy_list;
173struct mac_policy_list_head mac_static_policy_list;
174
175/*
176 * We manually invoke WITNESS_WARN() to allow Witness to generate
177 * warnings even if we don't end up ever triggering the wait at
178 * run-time. The consumer of the exclusive interface must not hold
179 * any locks (other than potentially Giant) since we may sleep for
180 * long (potentially indefinite) periods of time waiting for the
181 * framework to become quiescent so that a policy list change may
182 * be made.
183 */
184void
185mac_policy_grab_exclusive(void)
186{
187
188 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
189 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
190 mtx_lock(&mac_policy_mtx);
191 while (mac_policy_count != 0)
192 cv_wait(&mac_policy_cv, &mac_policy_mtx);
193}
194
195void
196mac_policy_assert_exclusive(void)
197{
198
199 mtx_assert(&mac_policy_mtx, MA_OWNED);
200 KASSERT(mac_policy_count == 0,
201 ("mac_policy_assert_exclusive(): not exclusive"));
202}
203
204void
205mac_policy_release_exclusive(void)
206{
207
208 KASSERT(mac_policy_count == 0,
209 ("mac_policy_release_exclusive(): not exclusive"));
210 mtx_unlock(&mac_policy_mtx);
211 cv_signal(&mac_policy_cv);
212}
213
214void
215mac_policy_list_busy(void)
216{
217
218 mtx_lock(&mac_policy_mtx);
219 mac_policy_count++;
220 mtx_unlock(&mac_policy_mtx);
221}
222
223int
224mac_policy_list_conditional_busy(void)
225{
226 int ret;
227
228 mtx_lock(&mac_policy_mtx);
229 if (!LIST_EMPTY(&mac_policy_list)) {
230 mac_policy_count++;
231 ret = 1;
232 } else
233 ret = 0;
234 mtx_unlock(&mac_policy_mtx);
235 return (ret);
236}
237
238void
239mac_policy_list_unbusy(void)
240{
241
242 mtx_lock(&mac_policy_mtx);
243 mac_policy_count--;
244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
245 if (mac_policy_count == 0)
246 cv_signal(&mac_policy_cv);
247 mtx_unlock(&mac_policy_mtx);
248}
249
250/*
251 * Initialize the MAC subsystem, including appropriate SMP locks.
252 */
253static void
254mac_init(void)
255{
256
257 LIST_INIT(&mac_static_policy_list);
258 LIST_INIT(&mac_policy_list);
46
47#include "opt_mac.h"
48#include "opt_devfs.h"
49
50#include <sys/param.h>
51#include <sys/condvar.h>
52#include <sys/extattr.h>
53#include <sys/imgact.h>
54#include <sys/kernel.h>
55#include <sys/lock.h>
56#include <sys/malloc.h>
57#include <sys/mutex.h>
58#include <sys/mac.h>
59#include <sys/module.h>
60#include <sys/proc.h>
61#include <sys/sbuf.h>
62#include <sys/systm.h>
63#include <sys/sysproto.h>
64#include <sys/sysent.h>
65#include <sys/vnode.h>
66#include <sys/mount.h>
67#include <sys/file.h>
68#include <sys/namei.h>
69#include <sys/socket.h>
70#include <sys/pipe.h>
71#include <sys/socketvar.h>
72#include <sys/sysctl.h>
73
74#include <vm/vm.h>
75#include <vm/pmap.h>
76#include <vm/vm_map.h>
77#include <vm/vm_object.h>
78
79#include <sys/mac_policy.h>
80
81#include <fs/devfs/devfs.h>
82
83#include <net/bpfdesc.h>
84#include <net/if.h>
85#include <net/if_var.h>
86
87#include <netinet/in.h>
88#include <netinet/ip_var.h>
89
90#include <security/mac/mac_internal.h>
91
92#ifdef MAC
93
94/*
95 * Declare that the kernel provides MAC support, version 1. This permits
96 * modules to refuse to be loaded if the necessary support isn't present,
97 * even if it's pre-boot.
98 */
99MODULE_VERSION(kernel_mac_support, 1);
100
101SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
102 "TrustedBSD MAC policy controls");
103
104#if MAC_MAX_SLOTS > 32
105#error "MAC_MAX_SLOTS too large"
106#endif
107
108static unsigned int mac_max_slots = MAC_MAX_SLOTS;
109static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
110SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
111 &mac_max_slots, 0, "");
112
113/*
114 * Has the kernel started generating labeled objects yet? All read/write
115 * access to this variable is serialized during the boot process. Following
116 * the end of serialization, we don't update this flag; no locking.
117 */
118int mac_late = 0;
119
120/*
121 * Flag to indicate whether or not we should allocate label storage for
122 * new mbufs. Since most dynamic policies we currently work with don't
123 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
124 * unless specifically notified of interest. One result of this is
125 * that if a dynamically loaded policy requests mbuf labels, it must
126 * be able to deal with a NULL label being returned on any mbufs that
127 * were already in flight when the policy was loaded. Since the policy
128 * already has to deal with uninitialized labels, this probably won't
129 * be a problem. Note: currently no locking. Will this be a problem?
130 */
131#ifndef MAC_ALWAYS_LABEL_MBUF
132int mac_labelmbufs = 0;
133#endif
134
135#ifdef MAC_DEBUG
136SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
137 "TrustedBSD MAC debug info");
138SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
139 "TrustedBSD MAC object counters");
140
141static unsigned int nmactemp;
142SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
143 &nmactemp, 0, "number of temporary labels in use");
144#endif
145
146static int mac_policy_register(struct mac_policy_conf *mpc);
147static int mac_policy_unregister(struct mac_policy_conf *mpc);
148
149MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
150
151/*
152 * mac_static_policy_list holds a list of policy modules that are not
153 * loaded while the system is "live", and cannot be unloaded. These
154 * policies can be invoked without holding the busy count.
155 *
156 * mac_policy_list stores the list of dynamic policies. A busy count is
157 * maintained for the list, stored in mac_policy_busy. The busy count
158 * is protected by mac_policy_mtx; the list may be modified only
159 * while the busy count is 0, requiring that the lock be held to
160 * prevent new references to the list from being acquired. For almost
161 * all operations, incrementing the busy count is sufficient to
162 * guarantee consistency, as the list cannot be modified while the
163 * busy count is elevated. For a few special operations involving a
164 * change to the list of active policies, the mtx itself must be held.
165 * A condition variable, mac_policy_cv, is used to signal potential
166 * exclusive consumers that they should try to acquire the lock if a
167 * first attempt at exclusive access fails.
168 */
169static struct mtx mac_policy_mtx;
170static struct cv mac_policy_cv;
171static int mac_policy_count;
172struct mac_policy_list_head mac_policy_list;
173struct mac_policy_list_head mac_static_policy_list;
174
175/*
176 * We manually invoke WITNESS_WARN() to allow Witness to generate
177 * warnings even if we don't end up ever triggering the wait at
178 * run-time. The consumer of the exclusive interface must not hold
179 * any locks (other than potentially Giant) since we may sleep for
180 * long (potentially indefinite) periods of time waiting for the
181 * framework to become quiescent so that a policy list change may
182 * be made.
183 */
184void
185mac_policy_grab_exclusive(void)
186{
187
188 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
189 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
190 mtx_lock(&mac_policy_mtx);
191 while (mac_policy_count != 0)
192 cv_wait(&mac_policy_cv, &mac_policy_mtx);
193}
194
195void
196mac_policy_assert_exclusive(void)
197{
198
199 mtx_assert(&mac_policy_mtx, MA_OWNED);
200 KASSERT(mac_policy_count == 0,
201 ("mac_policy_assert_exclusive(): not exclusive"));
202}
203
204void
205mac_policy_release_exclusive(void)
206{
207
208 KASSERT(mac_policy_count == 0,
209 ("mac_policy_release_exclusive(): not exclusive"));
210 mtx_unlock(&mac_policy_mtx);
211 cv_signal(&mac_policy_cv);
212}
213
214void
215mac_policy_list_busy(void)
216{
217
218 mtx_lock(&mac_policy_mtx);
219 mac_policy_count++;
220 mtx_unlock(&mac_policy_mtx);
221}
222
223int
224mac_policy_list_conditional_busy(void)
225{
226 int ret;
227
228 mtx_lock(&mac_policy_mtx);
229 if (!LIST_EMPTY(&mac_policy_list)) {
230 mac_policy_count++;
231 ret = 1;
232 } else
233 ret = 0;
234 mtx_unlock(&mac_policy_mtx);
235 return (ret);
236}
237
238void
239mac_policy_list_unbusy(void)
240{
241
242 mtx_lock(&mac_policy_mtx);
243 mac_policy_count--;
244 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
245 if (mac_policy_count == 0)
246 cv_signal(&mac_policy_cv);
247 mtx_unlock(&mac_policy_mtx);
248}
249
250/*
251 * Initialize the MAC subsystem, including appropriate SMP locks.
252 */
253static void
254mac_init(void)
255{
256
257 LIST_INIT(&mac_static_policy_list);
258 LIST_INIT(&mac_policy_list);
259 mac_labelzone_init();
259
260 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
261 cv_init(&mac_policy_cv, "mac_policy_cv");
262}
263
264/*
265 * For the purposes of modules that want to know if they were loaded
266 * "early", set the mac_late flag once we've processed modules either
267 * linked into the kernel, or loaded before the kernel startup.
268 */
269static void
270mac_late_init(void)
271{
272
273 mac_late = 1;
274}
275
276/*
277 * After the policy list has changed, walk the list to update any global
278 * flags. Currently, we support only one flag, and it's conditionally
279 * defined; as a result, the entire function is conditional. Eventually,
280 * the #else case might also iterate across the policies.
281 */
282static void
283mac_policy_updateflags(void)
284{
285#ifndef MAC_ALWAYS_LABEL_MBUF
286 struct mac_policy_conf *tmpc;
287 int labelmbufs;
288
289 mac_policy_assert_exclusive();
290
291 labelmbufs = 0;
292 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
293 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
294 labelmbufs++;
295 }
296 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
297 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
298 labelmbufs++;
299 }
300 mac_labelmbufs = (labelmbufs != 0);
301#endif
302}
303
304/*
305 * Allow MAC policy modules to register during boot, etc.
306 */
307int
308mac_policy_modevent(module_t mod, int type, void *data)
309{
310 struct mac_policy_conf *mpc;
311 int error;
312
313 error = 0;
314 mpc = (struct mac_policy_conf *) data;
315
316 switch (type) {
317 case MOD_LOAD:
318 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
319 mac_late) {
320 printf("mac_policy_modevent: can't load %s policy "
321 "after booting\n", mpc->mpc_name);
322 error = EBUSY;
323 break;
324 }
325 error = mac_policy_register(mpc);
326 break;
327 case MOD_UNLOAD:
328 /* Don't unregister the module if it was never registered. */
329 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
330 != 0)
331 error = mac_policy_unregister(mpc);
332 else
333 error = 0;
334 break;
335 default:
336 break;
337 }
338
339 return (error);
340}
341
342static int
343mac_policy_register(struct mac_policy_conf *mpc)
344{
345 struct mac_policy_conf *tmpc;
346 int error, slot, static_entry;
347
348 error = 0;
349
350 /*
351 * We don't technically need exclusive access while !mac_late,
352 * but hold it for assertion consistency.
353 */
354 mac_policy_grab_exclusive();
355
356 /*
357 * If the module can potentially be unloaded, or we're loading
358 * late, we have to stick it in the non-static list and pay
359 * an extra performance overhead. Otherwise, we can pay a
360 * light locking cost and stick it in the static list.
361 */
362 static_entry = (!mac_late &&
363 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
364
365 if (static_entry) {
366 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
367 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
368 error = EEXIST;
369 goto out;
370 }
371 }
372 } else {
373 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
374 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
375 error = EEXIST;
376 goto out;
377 }
378 }
379 }
380 if (mpc->mpc_field_off != NULL) {
381 slot = ffs(mac_slot_offsets_free);
382 if (slot == 0) {
383 error = ENOMEM;
384 goto out;
385 }
386 slot--;
387 mac_slot_offsets_free &= ~(1 << slot);
388 *mpc->mpc_field_off = slot;
389 }
390 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
391
392 /*
393 * If we're loading a MAC module after the framework has
394 * initialized, it has to go into the dynamic list. If
395 * we're loading it before we've finished initializing,
396 * it can go into the static list with weaker locker
397 * requirements.
398 */
399 if (static_entry)
400 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
401 else
402 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
403
404 /* Per-policy initialization. */
405 if (mpc->mpc_ops->mpo_init != NULL)
406 (*(mpc->mpc_ops->mpo_init))(mpc);
407 mac_policy_updateflags();
408
409 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
410 mpc->mpc_name);
411
412out:
413 mac_policy_release_exclusive();
414 return (error);
415}
416
417static int
418mac_policy_unregister(struct mac_policy_conf *mpc)
419{
420
421 /*
422 * If we fail the load, we may get a request to unload. Check
423 * to see if we did the run-time registration, and if not,
424 * silently succeed.
425 */
426 mac_policy_grab_exclusive();
427 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
428 mac_policy_release_exclusive();
429 return (0);
430 }
431#if 0
432 /*
433 * Don't allow unloading modules with private data.
434 */
435 if (mpc->mpc_field_off != NULL) {
436 MAC_POLICY_LIST_UNLOCK();
437 return (EBUSY);
438 }
439#endif
440 /*
441 * Only allow the unload to proceed if the module is unloadable
442 * by its own definition.
443 */
444 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
445 mac_policy_release_exclusive();
446 return (EBUSY);
447 }
448 if (mpc->mpc_ops->mpo_destroy != NULL)
449 (*(mpc->mpc_ops->mpo_destroy))(mpc);
450
451 LIST_REMOVE(mpc, mpc_list);
452 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
453 mac_policy_updateflags();
454
455 mac_policy_release_exclusive();
456
457 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
458 mpc->mpc_name);
459
460 return (0);
461}
462
463/*
464 * Define an error value precedence, and given two arguments, selects the
465 * value with the higher precedence.
466 */
467int
468mac_error_select(int error1, int error2)
469{
470
471 /* Certain decision-making errors take top priority. */
472 if (error1 == EDEADLK || error2 == EDEADLK)
473 return (EDEADLK);
474
475 /* Invalid arguments should be reported where possible. */
476 if (error1 == EINVAL || error2 == EINVAL)
477 return (EINVAL);
478
479 /* Precedence goes to "visibility", with both process and file. */
480 if (error1 == ESRCH || error2 == ESRCH)
481 return (ESRCH);
482
483 if (error1 == ENOENT || error2 == ENOENT)
484 return (ENOENT);
485
486 /* Precedence goes to DAC/MAC protections. */
487 if (error1 == EACCES || error2 == EACCES)
488 return (EACCES);
489
490 /* Precedence goes to privilege. */
491 if (error1 == EPERM || error2 == EPERM)
492 return (EPERM);
493
494 /* Precedence goes to error over success; otherwise, arbitrary. */
495 if (error1 != 0)
496 return (error1);
497 return (error2);
498}
499
500void
501mac_init_label(struct label *label)
502{
503
504 bzero(label, sizeof(*label));
505 label->l_flags = MAC_FLAG_INITIALIZED;
506}
507
508void
509mac_destroy_label(struct label *label)
510{
511
512 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
513 ("destroying uninitialized label"));
514
515 bzero(label, sizeof(*label));
516 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
517}
518
519int
520mac_check_structmac_consistent(struct mac *mac)
521{
522
523 if (mac->m_buflen < 0 ||
524 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
525 return (EINVAL);
526
527 return (0);
528}
529
530int
531__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
532{
533 char *elements, *buffer;
534 struct mac mac;
535 struct proc *tproc;
536 struct ucred *tcred;
537 int error;
538
539 error = copyin(uap->mac_p, &mac, sizeof(mac));
540 if (error)
541 return (error);
542
543 error = mac_check_structmac_consistent(&mac);
544 if (error)
545 return (error);
546
547 tproc = pfind(uap->pid);
548 if (tproc == NULL)
549 return (ESRCH);
550
551 tcred = NULL; /* Satisfy gcc. */
552 error = p_cansee(td, tproc);
553 if (error == 0)
554 tcred = crhold(tproc->p_ucred);
555 PROC_UNLOCK(tproc);
556 if (error)
557 return (error);
558
559 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
560 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
561 if (error) {
562 free(elements, M_MACTEMP);
563 crfree(tcred);
564 return (error);
565 }
566
567 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
260
261 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
262 cv_init(&mac_policy_cv, "mac_policy_cv");
263}
264
265/*
266 * For the purposes of modules that want to know if they were loaded
267 * "early", set the mac_late flag once we've processed modules either
268 * linked into the kernel, or loaded before the kernel startup.
269 */
270static void
271mac_late_init(void)
272{
273
274 mac_late = 1;
275}
276
277/*
278 * After the policy list has changed, walk the list to update any global
279 * flags. Currently, we support only one flag, and it's conditionally
280 * defined; as a result, the entire function is conditional. Eventually,
281 * the #else case might also iterate across the policies.
282 */
283static void
284mac_policy_updateflags(void)
285{
286#ifndef MAC_ALWAYS_LABEL_MBUF
287 struct mac_policy_conf *tmpc;
288 int labelmbufs;
289
290 mac_policy_assert_exclusive();
291
292 labelmbufs = 0;
293 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
294 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
295 labelmbufs++;
296 }
297 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
298 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
299 labelmbufs++;
300 }
301 mac_labelmbufs = (labelmbufs != 0);
302#endif
303}
304
305/*
306 * Allow MAC policy modules to register during boot, etc.
307 */
308int
309mac_policy_modevent(module_t mod, int type, void *data)
310{
311 struct mac_policy_conf *mpc;
312 int error;
313
314 error = 0;
315 mpc = (struct mac_policy_conf *) data;
316
317 switch (type) {
318 case MOD_LOAD:
319 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
320 mac_late) {
321 printf("mac_policy_modevent: can't load %s policy "
322 "after booting\n", mpc->mpc_name);
323 error = EBUSY;
324 break;
325 }
326 error = mac_policy_register(mpc);
327 break;
328 case MOD_UNLOAD:
329 /* Don't unregister the module if it was never registered. */
330 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
331 != 0)
332 error = mac_policy_unregister(mpc);
333 else
334 error = 0;
335 break;
336 default:
337 break;
338 }
339
340 return (error);
341}
342
343static int
344mac_policy_register(struct mac_policy_conf *mpc)
345{
346 struct mac_policy_conf *tmpc;
347 int error, slot, static_entry;
348
349 error = 0;
350
351 /*
352 * We don't technically need exclusive access while !mac_late,
353 * but hold it for assertion consistency.
354 */
355 mac_policy_grab_exclusive();
356
357 /*
358 * If the module can potentially be unloaded, or we're loading
359 * late, we have to stick it in the non-static list and pay
360 * an extra performance overhead. Otherwise, we can pay a
361 * light locking cost and stick it in the static list.
362 */
363 static_entry = (!mac_late &&
364 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
365
366 if (static_entry) {
367 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
368 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
369 error = EEXIST;
370 goto out;
371 }
372 }
373 } else {
374 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
375 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
376 error = EEXIST;
377 goto out;
378 }
379 }
380 }
381 if (mpc->mpc_field_off != NULL) {
382 slot = ffs(mac_slot_offsets_free);
383 if (slot == 0) {
384 error = ENOMEM;
385 goto out;
386 }
387 slot--;
388 mac_slot_offsets_free &= ~(1 << slot);
389 *mpc->mpc_field_off = slot;
390 }
391 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
392
393 /*
394 * If we're loading a MAC module after the framework has
395 * initialized, it has to go into the dynamic list. If
396 * we're loading it before we've finished initializing,
397 * it can go into the static list with weaker locker
398 * requirements.
399 */
400 if (static_entry)
401 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
402 else
403 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
404
405 /* Per-policy initialization. */
406 if (mpc->mpc_ops->mpo_init != NULL)
407 (*(mpc->mpc_ops->mpo_init))(mpc);
408 mac_policy_updateflags();
409
410 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
411 mpc->mpc_name);
412
413out:
414 mac_policy_release_exclusive();
415 return (error);
416}
417
418static int
419mac_policy_unregister(struct mac_policy_conf *mpc)
420{
421
422 /*
423 * If we fail the load, we may get a request to unload. Check
424 * to see if we did the run-time registration, and if not,
425 * silently succeed.
426 */
427 mac_policy_grab_exclusive();
428 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
429 mac_policy_release_exclusive();
430 return (0);
431 }
432#if 0
433 /*
434 * Don't allow unloading modules with private data.
435 */
436 if (mpc->mpc_field_off != NULL) {
437 MAC_POLICY_LIST_UNLOCK();
438 return (EBUSY);
439 }
440#endif
441 /*
442 * Only allow the unload to proceed if the module is unloadable
443 * by its own definition.
444 */
445 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
446 mac_policy_release_exclusive();
447 return (EBUSY);
448 }
449 if (mpc->mpc_ops->mpo_destroy != NULL)
450 (*(mpc->mpc_ops->mpo_destroy))(mpc);
451
452 LIST_REMOVE(mpc, mpc_list);
453 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
454 mac_policy_updateflags();
455
456 mac_policy_release_exclusive();
457
458 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
459 mpc->mpc_name);
460
461 return (0);
462}
463
464/*
465 * Define an error value precedence, and given two arguments, selects the
466 * value with the higher precedence.
467 */
468int
469mac_error_select(int error1, int error2)
470{
471
472 /* Certain decision-making errors take top priority. */
473 if (error1 == EDEADLK || error2 == EDEADLK)
474 return (EDEADLK);
475
476 /* Invalid arguments should be reported where possible. */
477 if (error1 == EINVAL || error2 == EINVAL)
478 return (EINVAL);
479
480 /* Precedence goes to "visibility", with both process and file. */
481 if (error1 == ESRCH || error2 == ESRCH)
482 return (ESRCH);
483
484 if (error1 == ENOENT || error2 == ENOENT)
485 return (ENOENT);
486
487 /* Precedence goes to DAC/MAC protections. */
488 if (error1 == EACCES || error2 == EACCES)
489 return (EACCES);
490
491 /* Precedence goes to privilege. */
492 if (error1 == EPERM || error2 == EPERM)
493 return (EPERM);
494
495 /* Precedence goes to error over success; otherwise, arbitrary. */
496 if (error1 != 0)
497 return (error1);
498 return (error2);
499}
500
501void
502mac_init_label(struct label *label)
503{
504
505 bzero(label, sizeof(*label));
506 label->l_flags = MAC_FLAG_INITIALIZED;
507}
508
509void
510mac_destroy_label(struct label *label)
511{
512
513 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
514 ("destroying uninitialized label"));
515
516 bzero(label, sizeof(*label));
517 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
518}
519
520int
521mac_check_structmac_consistent(struct mac *mac)
522{
523
524 if (mac->m_buflen < 0 ||
525 mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
526 return (EINVAL);
527
528 return (0);
529}
530
531int
532__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
533{
534 char *elements, *buffer;
535 struct mac mac;
536 struct proc *tproc;
537 struct ucred *tcred;
538 int error;
539
540 error = copyin(uap->mac_p, &mac, sizeof(mac));
541 if (error)
542 return (error);
543
544 error = mac_check_structmac_consistent(&mac);
545 if (error)
546 return (error);
547
548 tproc = pfind(uap->pid);
549 if (tproc == NULL)
550 return (ESRCH);
551
552 tcred = NULL; /* Satisfy gcc. */
553 error = p_cansee(td, tproc);
554 if (error == 0)
555 tcred = crhold(tproc->p_ucred);
556 PROC_UNLOCK(tproc);
557 if (error)
558 return (error);
559
560 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
561 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
562 if (error) {
563 free(elements, M_MACTEMP);
564 crfree(tcred);
565 return (error);
566 }
567
568 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
568 error = mac_externalize_cred_label(&tcred->cr_label, elements,
569 error = mac_externalize_cred_label(tcred->cr_label, elements,
569 buffer, mac.m_buflen);
570 if (error == 0)
571 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
572
573 free(buffer, M_MACTEMP);
574 free(elements, M_MACTEMP);
575 crfree(tcred);
576 return (error);
577}
578
579/*
580 * MPSAFE
581 */
582int
583__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
584{
585 char *elements, *buffer;
586 struct mac mac;
587 int error;
588
589 error = copyin(uap->mac_p, &mac, sizeof(mac));
590 if (error)
591 return (error);
592
593 error = mac_check_structmac_consistent(&mac);
594 if (error)
595 return (error);
596
597 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
598 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
599 if (error) {
600 free(elements, M_MACTEMP);
601 return (error);
602 }
603
604 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
570 buffer, mac.m_buflen);
571 if (error == 0)
572 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
573
574 free(buffer, M_MACTEMP);
575 free(elements, M_MACTEMP);
576 crfree(tcred);
577 return (error);
578}
579
580/*
581 * MPSAFE
582 */
583int
584__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
585{
586 char *elements, *buffer;
587 struct mac mac;
588 int error;
589
590 error = copyin(uap->mac_p, &mac, sizeof(mac));
591 if (error)
592 return (error);
593
594 error = mac_check_structmac_consistent(&mac);
595 if (error)
596 return (error);
597
598 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
599 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
600 if (error) {
601 free(elements, M_MACTEMP);
602 return (error);
603 }
604
605 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
605 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
606 error = mac_externalize_cred_label(td->td_ucred->cr_label,
606 elements, buffer, mac.m_buflen);
607 if (error == 0)
608 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
609
610 free(buffer, M_MACTEMP);
611 free(elements, M_MACTEMP);
612 return (error);
613}
614
615/*
616 * MPSAFE
617 */
618int
619__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
620{
621 struct ucred *newcred, *oldcred;
607 elements, buffer, mac.m_buflen);
608 if (error == 0)
609 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
610
611 free(buffer, M_MACTEMP);
612 free(elements, M_MACTEMP);
613 return (error);
614}
615
616/*
617 * MPSAFE
618 */
619int
620__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
621{
622 struct ucred *newcred, *oldcred;
622 struct label intlabel;
623 struct label *intlabel;
623 struct proc *p;
624 struct mac mac;
625 char *buffer;
626 int error;
627
628 error = copyin(uap->mac_p, &mac, sizeof(mac));
629 if (error)
630 return (error);
631
632 error = mac_check_structmac_consistent(&mac);
633 if (error)
634 return (error);
635
636 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
637 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
638 if (error) {
639 free(buffer, M_MACTEMP);
640 return (error);
641 }
642
624 struct proc *p;
625 struct mac mac;
626 char *buffer;
627 int error;
628
629 error = copyin(uap->mac_p, &mac, sizeof(mac));
630 if (error)
631 return (error);
632
633 error = mac_check_structmac_consistent(&mac);
634 if (error)
635 return (error);
636
637 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
638 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
639 if (error) {
640 free(buffer, M_MACTEMP);
641 return (error);
642 }
643
643 mac_init_cred_label(&intlabel);
644 error = mac_internalize_cred_label(&intlabel, buffer);
644 intlabel = mac_cred_label_alloc();
645 error = mac_internalize_cred_label(intlabel, buffer);
645 free(buffer, M_MACTEMP);
646 free(buffer, M_MACTEMP);
646 if (error) {
647 mac_destroy_cred_label(&intlabel);
648 return (error);
649 }
647 if (error)
648 goto out;
650
651 newcred = crget();
652
653 p = td->td_proc;
654 PROC_LOCK(p);
655 oldcred = p->p_ucred;
656
649
650 newcred = crget();
651
652 p = td->td_proc;
653 PROC_LOCK(p);
654 oldcred = p->p_ucred;
655
657 error = mac_check_cred_relabel(oldcred, &intlabel);
656 error = mac_check_cred_relabel(oldcred, intlabel);
658 if (error) {
659 PROC_UNLOCK(p);
660 crfree(newcred);
661 goto out;
662 }
663
664 setsugid(p);
665 crcopy(newcred, oldcred);
657 if (error) {
658 PROC_UNLOCK(p);
659 crfree(newcred);
660 goto out;
661 }
662
663 setsugid(p);
664 crcopy(newcred, oldcred);
666 mac_relabel_cred(newcred, &intlabel);
665 mac_relabel_cred(newcred, intlabel);
667 p->p_ucred = newcred;
668
669 /*
670 * Grab additional reference for use while revoking mmaps, prior
671 * to releasing the proc lock and sharing the cred.
672 */
673 crhold(newcred);
674 PROC_UNLOCK(p);
675
676 if (mac_enforce_vm) {
677 mtx_lock(&Giant);
678 mac_cred_mmapped_drop_perms(td, newcred);
679 mtx_unlock(&Giant);
680 }
681
682 crfree(newcred); /* Free revocation reference. */
683 crfree(oldcred);
684
685out:
666 p->p_ucred = newcred;
667
668 /*
669 * Grab additional reference for use while revoking mmaps, prior
670 * to releasing the proc lock and sharing the cred.
671 */
672 crhold(newcred);
673 PROC_UNLOCK(p);
674
675 if (mac_enforce_vm) {
676 mtx_lock(&Giant);
677 mac_cred_mmapped_drop_perms(td, newcred);
678 mtx_unlock(&Giant);
679 }
680
681 crfree(newcred); /* Free revocation reference. */
682 crfree(oldcred);
683
684out:
686 mac_destroy_cred_label(&intlabel);
685 mac_cred_label_free(intlabel);
687 return (error);
688}
689
690/*
691 * MPSAFE
692 */
693int
694__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
695{
696 char *elements, *buffer;
686 return (error);
687}
688
689/*
690 * MPSAFE
691 */
692int
693__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
694{
695 char *elements, *buffer;
697 struct label intlabel;
696 struct label *intlabel;
698 struct file *fp;
699 struct mac mac;
700 struct vnode *vp;
701 struct pipe *pipe;
702 short label_type;
703 int error;
704
705 error = copyin(uap->mac_p, &mac, sizeof(mac));
706 if (error)
707 return (error);
708
709 error = mac_check_structmac_consistent(&mac);
710 if (error)
711 return (error);
712
713 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
714 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
715 if (error) {
716 free(elements, M_MACTEMP);
717 return (error);
718 }
719
720 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
721 mtx_lock(&Giant); /* VFS */
722 error = fget(td, uap->fd, &fp);
723 if (error)
724 goto out;
725
726 label_type = fp->f_type;
727 switch (fp->f_type) {
728 case DTYPE_FIFO:
729 case DTYPE_VNODE:
730 vp = fp->f_vnode;
731
697 struct file *fp;
698 struct mac mac;
699 struct vnode *vp;
700 struct pipe *pipe;
701 short label_type;
702 int error;
703
704 error = copyin(uap->mac_p, &mac, sizeof(mac));
705 if (error)
706 return (error);
707
708 error = mac_check_structmac_consistent(&mac);
709 if (error)
710 return (error);
711
712 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
713 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
714 if (error) {
715 free(elements, M_MACTEMP);
716 return (error);
717 }
718
719 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
720 mtx_lock(&Giant); /* VFS */
721 error = fget(td, uap->fd, &fp);
722 if (error)
723 goto out;
724
725 label_type = fp->f_type;
726 switch (fp->f_type) {
727 case DTYPE_FIFO:
728 case DTYPE_VNODE:
729 vp = fp->f_vnode;
730
732 mac_init_vnode_label(&intlabel);
731 intlabel = mac_vnode_label_alloc();
733
734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
732
733 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
735 mac_copy_vnode_label(&vp->v_label, &intlabel);
734 mac_copy_vnode_label(vp->v_label, intlabel);
736 VOP_UNLOCK(vp, 0, td);
737
738 break;
739 case DTYPE_PIPE:
740 pipe = fp->f_data;
741
735 VOP_UNLOCK(vp, 0, td);
736
737 break;
738 case DTYPE_PIPE:
739 pipe = fp->f_data;
740
742 mac_init_pipe_label(&intlabel);
741 intlabel = mac_pipe_label_alloc();
743
744 PIPE_LOCK(pipe);
742
743 PIPE_LOCK(pipe);
745 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
744 mac_copy_pipe_label(pipe->pipe_label, intlabel);
746 PIPE_UNLOCK(pipe);
747 break;
748 default:
749 error = EINVAL;
750 fdrop(fp, td);
751 goto out;
752 }
753 fdrop(fp, td);
754
755 switch (label_type) {
756 case DTYPE_FIFO:
757 case DTYPE_VNODE:
758 if (error == 0)
745 PIPE_UNLOCK(pipe);
746 break;
747 default:
748 error = EINVAL;
749 fdrop(fp, td);
750 goto out;
751 }
752 fdrop(fp, td);
753
754 switch (label_type) {
755 case DTYPE_FIFO:
756 case DTYPE_VNODE:
757 if (error == 0)
759 error = mac_externalize_vnode_label(&intlabel,
758 error = mac_externalize_vnode_label(intlabel,
760 elements, buffer, mac.m_buflen);
759 elements, buffer, mac.m_buflen);
761 mac_destroy_vnode_label(&intlabel);
760 mac_vnode_label_free(intlabel);
762 break;
763 case DTYPE_PIPE:
761 break;
762 case DTYPE_PIPE:
764 error = mac_externalize_pipe_label(&intlabel, elements,
763 error = mac_externalize_pipe_label(intlabel, elements,
765 buffer, mac.m_buflen);
764 buffer, mac.m_buflen);
766 mac_destroy_pipe_label(&intlabel);
765 mac_pipe_label_free(intlabel);
767 break;
768 default:
769 panic("__mac_get_fd: corrupted label_type");
770 }
771
772 if (error == 0)
773 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
774
775out:
776 mtx_unlock(&Giant); /* VFS */
777 free(buffer, M_MACTEMP);
778 free(elements, M_MACTEMP);
779
780 return (error);
781}
782
783/*
784 * MPSAFE
785 */
786int
787__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
788{
789 char *elements, *buffer;
790 struct nameidata nd;
766 break;
767 default:
768 panic("__mac_get_fd: corrupted label_type");
769 }
770
771 if (error == 0)
772 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
773
774out:
775 mtx_unlock(&Giant); /* VFS */
776 free(buffer, M_MACTEMP);
777 free(elements, M_MACTEMP);
778
779 return (error);
780}
781
782/*
783 * MPSAFE
784 */
785int
786__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
787{
788 char *elements, *buffer;
789 struct nameidata nd;
791 struct label intlabel;
790 struct label *intlabel;
792 struct mac mac;
793 int error;
794
795 error = copyin(uap->mac_p, &mac, sizeof(mac));
796 if (error)
797 return (error);
798
799 error = mac_check_structmac_consistent(&mac);
800 if (error)
801 return (error);
802
803 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
804 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
805 if (error) {
806 free(elements, M_MACTEMP);
807 return (error);
808 }
809
810 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
811 mtx_lock(&Giant); /* VFS */
812 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
813 td);
814 error = namei(&nd);
815 if (error)
816 goto out;
817
791 struct mac mac;
792 int error;
793
794 error = copyin(uap->mac_p, &mac, sizeof(mac));
795 if (error)
796 return (error);
797
798 error = mac_check_structmac_consistent(&mac);
799 if (error)
800 return (error);
801
802 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
803 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
804 if (error) {
805 free(elements, M_MACTEMP);
806 return (error);
807 }
808
809 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
810 mtx_lock(&Giant); /* VFS */
811 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
812 td);
813 error = namei(&nd);
814 if (error)
815 goto out;
816
818 mac_init_vnode_label(&intlabel);
819 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
820 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
817 intlabel = mac_vnode_label_alloc();
818 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
819 error = mac_externalize_vnode_label(intlabel, elements, buffer,
821 mac.m_buflen);
822
823 NDFREE(&nd, 0);
820 mac.m_buflen);
821
822 NDFREE(&nd, 0);
824 mac_destroy_vnode_label(&intlabel);
823 mac_vnode_label_free(intlabel);
825
826 if (error == 0)
827 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
828
829out:
830 mtx_unlock(&Giant); /* VFS */
831
832 free(buffer, M_MACTEMP);
833 free(elements, M_MACTEMP);
834
835 return (error);
836}
837
838/*
839 * MPSAFE
840 */
841int
842__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
843{
844 char *elements, *buffer;
845 struct nameidata nd;
824
825 if (error == 0)
826 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
827
828out:
829 mtx_unlock(&Giant); /* VFS */
830
831 free(buffer, M_MACTEMP);
832 free(elements, M_MACTEMP);
833
834 return (error);
835}
836
837/*
838 * MPSAFE
839 */
840int
841__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
842{
843 char *elements, *buffer;
844 struct nameidata nd;
846 struct label intlabel;
845 struct label *intlabel;
847 struct mac mac;
848 int error;
849
850 error = copyin(uap->mac_p, &mac, sizeof(mac));
851 if (error)
852 return (error);
853
854 error = mac_check_structmac_consistent(&mac);
855 if (error)
856 return (error);
857
858 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
859 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
860 if (error) {
861 free(elements, M_MACTEMP);
862 return (error);
863 }
864
865 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
866 mtx_lock(&Giant); /* VFS */
867 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
868 td);
869 error = namei(&nd);
870 if (error)
871 goto out;
872
846 struct mac mac;
847 int error;
848
849 error = copyin(uap->mac_p, &mac, sizeof(mac));
850 if (error)
851 return (error);
852
853 error = mac_check_structmac_consistent(&mac);
854 if (error)
855 return (error);
856
857 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
858 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
859 if (error) {
860 free(elements, M_MACTEMP);
861 return (error);
862 }
863
864 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
865 mtx_lock(&Giant); /* VFS */
866 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
867 td);
868 error = namei(&nd);
869 if (error)
870 goto out;
871
873 mac_init_vnode_label(&intlabel);
874 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
875 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
872 intlabel = mac_vnode_label_alloc();
873 mac_copy_vnode_label(nd.ni_vp->v_label, intlabel);
874 error = mac_externalize_vnode_label(intlabel, elements, buffer,
876 mac.m_buflen);
877 NDFREE(&nd, 0);
875 mac.m_buflen);
876 NDFREE(&nd, 0);
878 mac_destroy_vnode_label(&intlabel);
877 mac_vnode_label_free(intlabel);
879
880 if (error == 0)
881 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
882
883out:
884 mtx_unlock(&Giant); /* VFS */
885
886 free(buffer, M_MACTEMP);
887 free(elements, M_MACTEMP);
888
889 return (error);
890}
891
892/*
893 * MPSAFE
894 */
895int
896__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
897{
878
879 if (error == 0)
880 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
881
882out:
883 mtx_unlock(&Giant); /* VFS */
884
885 free(buffer, M_MACTEMP);
886 free(elements, M_MACTEMP);
887
888 return (error);
889}
890
891/*
892 * MPSAFE
893 */
894int
895__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
896{
898 struct label intlabel;
897 struct label *intlabel;
899 struct pipe *pipe;
900 struct file *fp;
901 struct mount *mp;
902 struct vnode *vp;
903 struct mac mac;
904 char *buffer;
905 int error;
906
907 error = copyin(uap->mac_p, &mac, sizeof(mac));
908 if (error)
909 return (error);
910
911 error = mac_check_structmac_consistent(&mac);
912 if (error)
913 return (error);
914
915 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
916 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
917 if (error) {
918 free(buffer, M_MACTEMP);
919 return (error);
920 }
921
922 mtx_lock(&Giant); /* VFS */
923
924 error = fget(td, uap->fd, &fp);
925 if (error)
926 goto out;
927
928 switch (fp->f_type) {
929 case DTYPE_FIFO:
930 case DTYPE_VNODE:
898 struct pipe *pipe;
899 struct file *fp;
900 struct mount *mp;
901 struct vnode *vp;
902 struct mac mac;
903 char *buffer;
904 int error;
905
906 error = copyin(uap->mac_p, &mac, sizeof(mac));
907 if (error)
908 return (error);
909
910 error = mac_check_structmac_consistent(&mac);
911 if (error)
912 return (error);
913
914 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
915 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
916 if (error) {
917 free(buffer, M_MACTEMP);
918 return (error);
919 }
920
921 mtx_lock(&Giant); /* VFS */
922
923 error = fget(td, uap->fd, &fp);
924 if (error)
925 goto out;
926
927 switch (fp->f_type) {
928 case DTYPE_FIFO:
929 case DTYPE_VNODE:
931 mac_init_vnode_label(&intlabel);
932 error = mac_internalize_vnode_label(&intlabel, buffer);
930 intlabel = mac_vnode_label_alloc();
931 error = mac_internalize_vnode_label(intlabel, buffer);
933 if (error) {
932 if (error) {
934 mac_destroy_vnode_label(&intlabel);
933 mac_vnode_label_free(intlabel);
935 break;
936 }
937
938 vp = fp->f_vnode;
939 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
940 if (error != 0) {
934 break;
935 }
936
937 vp = fp->f_vnode;
938 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
939 if (error != 0) {
941 mac_destroy_vnode_label(&intlabel);
940 mac_vnode_label_free(intlabel);
942 break;
943 }
944
945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
941 break;
942 }
943
944 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
946 error = vn_setlabel(vp, &intlabel, td->td_ucred);
945 error = vn_setlabel(vp, intlabel, td->td_ucred);
947 VOP_UNLOCK(vp, 0, td);
948 vn_finished_write(mp);
949
946 VOP_UNLOCK(vp, 0, td);
947 vn_finished_write(mp);
948
950 mac_destroy_vnode_label(&intlabel);
949 mac_vnode_label_free(intlabel);
951 break;
952
953 case DTYPE_PIPE:
950 break;
951
952 case DTYPE_PIPE:
954 mac_init_pipe_label(&intlabel);
955 error = mac_internalize_pipe_label(&intlabel, buffer);
953 intlabel = mac_pipe_label_alloc();
954 error = mac_internalize_pipe_label(intlabel, buffer);
956 if (error == 0) {
957 pipe = fp->f_data;
958 PIPE_LOCK(pipe);
959 error = mac_pipe_label_set(td->td_ucred, pipe,
955 if (error == 0) {
956 pipe = fp->f_data;
957 PIPE_LOCK(pipe);
958 error = mac_pipe_label_set(td->td_ucred, pipe,
960 &intlabel);
959 intlabel);
961 PIPE_UNLOCK(pipe);
962 }
963
960 PIPE_UNLOCK(pipe);
961 }
962
964 mac_destroy_pipe_label(&intlabel);
963 mac_pipe_label_free(intlabel);
965 break;
966
967 default:
968 error = EINVAL;
969 }
970
971 fdrop(fp, td);
972out:
973 mtx_unlock(&Giant); /* VFS */
974
975 free(buffer, M_MACTEMP);
976
977 return (error);
978}
979
980/*
981 * MPSAFE
982 */
983int
984__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
985{
964 break;
965
966 default:
967 error = EINVAL;
968 }
969
970 fdrop(fp, td);
971out:
972 mtx_unlock(&Giant); /* VFS */
973
974 free(buffer, M_MACTEMP);
975
976 return (error);
977}
978
979/*
980 * MPSAFE
981 */
982int
983__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
984{
986 struct label intlabel;
985 struct label *intlabel;
987 struct nameidata nd;
988 struct mount *mp;
989 struct mac mac;
990 char *buffer;
991 int error;
992
993 error = copyin(uap->mac_p, &mac, sizeof(mac));
994 if (error)
995 return (error);
996
997 error = mac_check_structmac_consistent(&mac);
998 if (error)
999 return (error);
1000
1001 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1002 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1003 if (error) {
1004 free(buffer, M_MACTEMP);
1005 return (error);
1006 }
1007
986 struct nameidata nd;
987 struct mount *mp;
988 struct mac mac;
989 char *buffer;
990 int error;
991
992 error = copyin(uap->mac_p, &mac, sizeof(mac));
993 if (error)
994 return (error);
995
996 error = mac_check_structmac_consistent(&mac);
997 if (error)
998 return (error);
999
1000 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1001 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1002 if (error) {
1003 free(buffer, M_MACTEMP);
1004 return (error);
1005 }
1006
1008 mac_init_vnode_label(&intlabel);
1009 error = mac_internalize_vnode_label(&intlabel, buffer);
1007 intlabel = mac_vnode_label_alloc();
1008 error = mac_internalize_vnode_label(intlabel, buffer);
1010 free(buffer, M_MACTEMP);
1009 free(buffer, M_MACTEMP);
1011 if (error) {
1012 mac_destroy_vnode_label(&intlabel);
1013 return (error);
1014 }
1010 if (error)
1011 goto out;
1015
1016 mtx_lock(&Giant); /* VFS */
1017
1018 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1019 td);
1020 error = namei(&nd);
1021 if (error == 0) {
1022 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1023 if (error == 0)
1012
1013 mtx_lock(&Giant); /* VFS */
1014
1015 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
1016 td);
1017 error = namei(&nd);
1018 if (error == 0) {
1019 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1020 if (error == 0)
1024 error = vn_setlabel(nd.ni_vp, &intlabel,
1021 error = vn_setlabel(nd.ni_vp, intlabel,
1025 td->td_ucred);
1026 vn_finished_write(mp);
1027 }
1028
1029 NDFREE(&nd, 0);
1030 mtx_unlock(&Giant); /* VFS */
1022 td->td_ucred);
1023 vn_finished_write(mp);
1024 }
1025
1026 NDFREE(&nd, 0);
1027 mtx_unlock(&Giant); /* VFS */
1031 mac_destroy_vnode_label(&intlabel);
1032
1028out:
1029 mac_vnode_label_free(intlabel);
1033 return (error);
1034}
1035
1036/*
1037 * MPSAFE
1038 */
1039int
1040__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1041{
1030 return (error);
1031}
1032
1033/*
1034 * MPSAFE
1035 */
1036int
1037__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1038{
1042 struct label intlabel;
1039 struct label *intlabel;
1043 struct nameidata nd;
1044 struct mount *mp;
1045 struct mac mac;
1046 char *buffer;
1047 int error;
1048
1049 error = copyin(uap->mac_p, &mac, sizeof(mac));
1050 if (error)
1051 return (error);
1052
1053 error = mac_check_structmac_consistent(&mac);
1054 if (error)
1055 return (error);
1056
1057 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1058 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1059 if (error) {
1060 free(buffer, M_MACTEMP);
1061 return (error);
1062 }
1063
1040 struct nameidata nd;
1041 struct mount *mp;
1042 struct mac mac;
1043 char *buffer;
1044 int error;
1045
1046 error = copyin(uap->mac_p, &mac, sizeof(mac));
1047 if (error)
1048 return (error);
1049
1050 error = mac_check_structmac_consistent(&mac);
1051 if (error)
1052 return (error);
1053
1054 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1055 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1056 if (error) {
1057 free(buffer, M_MACTEMP);
1058 return (error);
1059 }
1060
1064 mac_init_vnode_label(&intlabel);
1065 error = mac_internalize_vnode_label(&intlabel, buffer);
1061 intlabel = mac_vnode_label_alloc();
1062 error = mac_internalize_vnode_label(intlabel, buffer);
1066 free(buffer, M_MACTEMP);
1063 free(buffer, M_MACTEMP);
1067 if (error) {
1068 mac_destroy_vnode_label(&intlabel);
1069 return (error);
1070 }
1064 if (error)
1065 goto out;
1071
1072 mtx_lock(&Giant); /* VFS */
1073
1074 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
1075 td);
1076 error = namei(&nd);
1077 if (error == 0) {
1078 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1079 if (error == 0)
1066
1067 mtx_lock(&Giant); /* VFS */
1068
1069 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
1070 td);
1071 error = namei(&nd);
1072 if (error == 0) {
1073 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
1074 if (error == 0)
1080 error = vn_setlabel(nd.ni_vp, &intlabel,
1075 error = vn_setlabel(nd.ni_vp, intlabel,
1081 td->td_ucred);
1082 vn_finished_write(mp);
1083 }
1084
1085 NDFREE(&nd, 0);
1086 mtx_unlock(&Giant); /* VFS */
1076 td->td_ucred);
1077 vn_finished_write(mp);
1078 }
1079
1080 NDFREE(&nd, 0);
1081 mtx_unlock(&Giant); /* VFS */
1087 mac_destroy_vnode_label(&intlabel);
1088
1082out:
1083 mac_vnode_label_free(intlabel);
1089 return (error);
1090}
1091
1092/*
1093 * MPSAFE
1094 */
1095int
1096mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1097{
1098 struct mac_policy_conf *mpc;
1099 char target[MAC_MAX_POLICY_NAME];
1100 int entrycount, error;
1101
1102 error = copyinstr(uap->policy, target, sizeof(target), NULL);
1103 if (error)
1104 return (error);
1105
1106 error = ENOSYS;
1107 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
1108 if (strcmp(mpc->mpc_name, target) == 0 &&
1109 mpc->mpc_ops->mpo_syscall != NULL) {
1110 error = mpc->mpc_ops->mpo_syscall(td,
1111 uap->call, uap->arg);
1112 goto out;
1113 }
1114 }
1115
1116 if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
1117 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
1118 if (strcmp(mpc->mpc_name, target) == 0 &&
1119 mpc->mpc_ops->mpo_syscall != NULL) {
1120 error = mpc->mpc_ops->mpo_syscall(td,
1121 uap->call, uap->arg);
1122 break;
1123 }
1124 }
1125 mac_policy_list_unbusy();
1126 }
1127out:
1128 return (error);
1129}
1130
1131SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1132SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1133
1134#else /* !MAC */
1135
1136int
1137__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1138{
1139
1140 return (ENOSYS);
1141}
1142
1143int
1144__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1145{
1146
1147 return (ENOSYS);
1148}
1149
1150int
1151__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1152{
1153
1154 return (ENOSYS);
1155}
1156
1157int
1158__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1159{
1160
1161 return (ENOSYS);
1162}
1163
1164int
1165__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1166{
1167
1168 return (ENOSYS);
1169}
1170
1171int
1172__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1173{
1174
1175 return (ENOSYS);
1176}
1177
1178int
1179__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1180{
1181
1182 return (ENOSYS);
1183}
1184
1185int
1186__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1187{
1188
1189 return (ENOSYS);
1190}
1191
1192int
1193__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1194{
1195
1196 return (ENOSYS);
1197}
1198
1199int
1200mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1201{
1202
1203 return (ENOSYS);
1204}
1205
1206#endif
1084 return (error);
1085}
1086
1087/*
1088 * MPSAFE
1089 */
1090int
1091mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1092{
1093 struct mac_policy_conf *mpc;
1094 char target[MAC_MAX_POLICY_NAME];
1095 int entrycount, error;
1096
1097 error = copyinstr(uap->policy, target, sizeof(target), NULL);
1098 if (error)
1099 return (error);
1100
1101 error = ENOSYS;
1102 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) {
1103 if (strcmp(mpc->mpc_name, target) == 0 &&
1104 mpc->mpc_ops->mpo_syscall != NULL) {
1105 error = mpc->mpc_ops->mpo_syscall(td,
1106 uap->call, uap->arg);
1107 goto out;
1108 }
1109 }
1110
1111 if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
1112 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
1113 if (strcmp(mpc->mpc_name, target) == 0 &&
1114 mpc->mpc_ops->mpo_syscall != NULL) {
1115 error = mpc->mpc_ops->mpo_syscall(td,
1116 uap->call, uap->arg);
1117 break;
1118 }
1119 }
1120 mac_policy_list_unbusy();
1121 }
1122out:
1123 return (error);
1124}
1125
1126SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
1127SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
1128
1129#else /* !MAC */
1130
1131int
1132__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
1133{
1134
1135 return (ENOSYS);
1136}
1137
1138int
1139__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
1140{
1141
1142 return (ENOSYS);
1143}
1144
1145int
1146__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
1147{
1148
1149 return (ENOSYS);
1150}
1151
1152int
1153__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
1154{
1155
1156 return (ENOSYS);
1157}
1158
1159int
1160__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
1161{
1162
1163 return (ENOSYS);
1164}
1165
1166int
1167__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
1168{
1169
1170 return (ENOSYS);
1171}
1172
1173int
1174__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
1175{
1176
1177 return (ENOSYS);
1178}
1179
1180int
1181__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
1182{
1183
1184 return (ENOSYS);
1185}
1186
1187int
1188__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1189{
1190
1191 return (ENOSYS);
1192}
1193
1194int
1195mac_syscall(struct thread *td, struct mac_syscall_args *uap)
1196{
1197
1198 return (ENOSYS);
1199}
1200
1201#endif