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