Deleted Added
full compact
mac_syscalls.c (122159) mac_syscalls.c (122454)
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
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.
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*.
40 */
41
42#include <sys/cdefs.h>
42 */
43
44#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 122159 2003-11-06 03:42:43Z rwatson $");
45__FBSDID("$FreeBSD: head/sys/security/mac/mac_syscalls.c 122454 2003-11-11 03:40:04Z 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
88#include <security/mac/mac_internal.h>
89
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
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
133#ifdef MAC_DEBUG
134SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
135 "TrustedBSD MAC debug info");
136SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
137 "TrustedBSD MAC object counters");
138
139static unsigned int nmactemp;
140SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
141 &nmactemp, 0, "number of temporary labels in use");
142#endif
143
144static int mac_policy_register(struct mac_policy_conf *mpc);
145static int mac_policy_unregister(struct mac_policy_conf *mpc);
146
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{
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
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{
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
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{
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
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{
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
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/*
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
494void
495mac_init_label(struct label *label)
496{
497
498 bzero(label, sizeof(*label));
499 label->l_flags = MAC_FLAG_INITIALIZED;
500}
501
502void
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
513int
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
524int
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);
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);
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);
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);
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);
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);
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
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
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);
568 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);
605 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;
622 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
643 mac_init_cred_label(&intlabel);
644 error = mac_internalize_cred_label(&intlabel, buffer);
645 free(buffer, M_MACTEMP);
646 if (error) {
647 mac_destroy_cred_label(&intlabel);
648 return (error);
649 }
650
651 newcred = crget();
652
653 p = td->td_proc;
654 PROC_LOCK(p);
655 oldcred = p->p_ucred;
656
657 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);
666 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:
686 mac_destroy_cred_label(&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;
697 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
732 mac_init_vnode_label(&intlabel);
733
734 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
735 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
742 mac_init_pipe_label(&intlabel);
743
744 PIPE_LOCK(pipe);
745 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)
759 error = mac_externalize_vnode_label(&intlabel,
760 elements, buffer, mac.m_buflen);
761 mac_destroy_vnode_label(&intlabel);
762 break;
763 case DTYPE_PIPE:
764 error = mac_externalize_pipe_label(&intlabel, elements,
765 buffer, mac.m_buflen);
766 mac_destroy_pipe_label(&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;
791 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
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,
821 mac.m_buflen);
822
823 NDFREE(&nd, 0);
824 mac_destroy_vnode_label(&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;
846 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
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,
876 mac.m_buflen);
877 NDFREE(&nd, 0);
878 mac_destroy_vnode_label(&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{
898 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:
931 mac_init_vnode_label(&intlabel);
932 error = mac_internalize_vnode_label(&intlabel, buffer);
933 if (error) {
934 mac_destroy_vnode_label(&intlabel);
935 break;
936 }
937
938 vp = fp->f_vnode;
939 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
940 if (error != 0) {
941 mac_destroy_vnode_label(&intlabel);
942 break;
943 }
944
945 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
946 error = vn_setlabel(vp, &intlabel, td->td_ucred);
947 VOP_UNLOCK(vp, 0, td);
948 vn_finished_write(mp);
949
950 mac_destroy_vnode_label(&intlabel);
951 break;
952
953 case DTYPE_PIPE:
954 mac_init_pipe_label(&intlabel);
955 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,
960 &intlabel);
961 PIPE_UNLOCK(pipe);
962 }
963
964 mac_destroy_pipe_label(&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{
986 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
1008 mac_init_vnode_label(&intlabel);
1009 error = mac_internalize_vnode_label(&intlabel, buffer);
1010 free(buffer, M_MACTEMP);
1011 if (error) {
1012 mac_destroy_vnode_label(&intlabel);
1013 return (error);
1014 }
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)
1024 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 */
1031 mac_destroy_vnode_label(&intlabel);
1032
1033 return (error);
1034}
1035
1036/*
1037 * MPSAFE
1038 */
1039int
1040__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
1041{
1042 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
1064 mac_init_vnode_label(&intlabel);
1065 error = mac_internalize_vnode_label(&intlabel, buffer);
1066 free(buffer, M_MACTEMP);
1067 if (error) {
1068 mac_destroy_vnode_label(&intlabel);
1069 return (error);
1070 }
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)
1080 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 */
1087 mac_destroy_vnode_label(&intlabel);
1088
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