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