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_system.c 106217 2002-10-30 18:48:51Z 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_mount_stat(struct ucred *cred, struct mount *mount)
2174{
2175 int error;
2176
2177 if (!mac_enforce_fs)
2178 return (0);
2179
2180 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2181
2182 return (error);
2183}
2184
2185int
2186mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2187 void *data)
2188{
2189 int error;
2190
2191 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2192
2193 if (!mac_enforce_pipe)
2194 return (0);
2195
2196 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2197
2198 return (error);
2199}
2200
2201int
2202mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2203{
2204 int error;
2205
2206 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2207
2208 if (!mac_enforce_pipe)
2209 return (0);
2210
2211 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2212
2213 return (error);
2214}
2215
2216int
2217mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2218{
2219 int error;
2220
2221 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2222
2223 if (!mac_enforce_pipe)
2224 return (0);
2225
2226 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2227
2228 return (error);
2229}
2230
2231static int
2232mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2233 struct label *newlabel)
2234{
2235 int error;
2236
2237 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2238
2239 if (!mac_enforce_pipe)
2240 return (0);
2241
2242 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2243
2244 return (error);
2245}
2246
2247int
2248mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2249{
2250 int error;
2251
2252 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2253
2254 if (!mac_enforce_pipe)
2255 return (0);
2256
2257 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2258
2259 return (error);
2260}
2261
2262int
2263mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2264{
2265 int error;
2266
2267 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2268
2269 if (!mac_enforce_pipe)
2270 return (0);
2271
2272 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2273
2274 return (error);
2275}
2276
2277int
2278mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2279{
2280 int error;
2281
2282 PROC_LOCK_ASSERT(proc, MA_OWNED);
2283
2284 if (!mac_enforce_process)
2285 return (0);
2286
2287 MAC_CHECK(check_proc_debug, cred, proc);
2288
2289 return (error);
2290}
2291
2292int
2293mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2294{
2295 int error;
2296
2297 PROC_LOCK_ASSERT(proc, MA_OWNED);
2298
2299 if (!mac_enforce_process)
2300 return (0);
2301
2302 MAC_CHECK(check_proc_sched, cred, proc);
2303
2304 return (error);
2305}
2306
2307int
2308mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2309{
2310 int error;
2311
2312 PROC_LOCK_ASSERT(proc, MA_OWNED);
2313
2314 if (!mac_enforce_process)
2315 return (0);
2316
2317 MAC_CHECK(check_proc_signal, cred, proc, signum);
2318
2319 return (error);
2320}
2321
2322int
2323mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2324 struct sockaddr *sockaddr)
2325{
2326 int error;
2327
2328 if (!mac_enforce_socket)
2329 return (0);
2330
2331 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2332 sockaddr);
2333
2334 return (error);
2335}
2336
2337int
2338mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2339 struct sockaddr *sockaddr)
2340{
2341 int error;
2342
2343 if (!mac_enforce_socket)
2344 return (0);
2345
2346 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2347 sockaddr);
2348
2349 return (error);
2350}
2351
2352int
2353mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2354{
2355 int error;
2356
2357 if (!mac_enforce_socket)
2358 return (0);
2359
2360 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2361 &mbuf->m_pkthdr.label);
2362
2363 return (error);
2364}
2365
2366int
2367mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2368{
2369 int error;
2370
2371 if (!mac_enforce_socket)
2372 return (0);
2373
2374 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2375 return (error);
2376}
2377
2378int
2379mac_check_socket_receive(struct ucred *cred, struct socket *so)
2380{
2381 int error;
2382
2383 if (!mac_enforce_socket)
2384 return (0);
2385
2386 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2387
2388 return (error);
2389}
2390
2391static int
2392mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2393 struct label *newlabel)
2394{
2395 int error;
2396
2397 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2398 newlabel);
2399
2400 return (error);
2401}
2402
2403int
2404mac_check_socket_send(struct ucred *cred, struct socket *so)
2405{
2406 int error;
2407
2408 if (!mac_enforce_socket)
2409 return (0);
2410
2411 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2412
2413 return (error);
2414}
2415
2416int
2417mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2418{
2419 int error;
2420
2421 if (!mac_enforce_socket)
2422 return (0);
2423
2424 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2425
2426 return (error);
2427}
2428
2429int
2430mac_check_system_reboot(struct ucred *cred, int howto)
2431{
2432 int error;
2433
2434 if (!mac_enforce_system)
2435 return (0);
2436
2437 MAC_CHECK(check_system_reboot, cred, howto);
2438
2439 return (error);
2440}
2441
2442int
2443mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2444{
2445 int error;
2446
2447 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2448
2449 if (!mac_enforce_system)
2450 return (0);
2451
2452 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2453 return (error);
2454}
2455
2456int
2457mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2458 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2459{
2460 int error;
2461
2462 /*
2463 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2464 * but since it's not exported from kern_sysctl.c, we can't.
2465 */
2466 if (!mac_enforce_system)
2467 return (0);
2468
2469 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2470 inkernel, new, newlen);
2471
2472 return (error);
2473}
2474
2475int
2476mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2477 struct ifnet *ifnet)
2478{
2479 char *elements, *buffer;
2480 struct mac mac;
2481 int error;
2482
2483 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2484 if (error)
2485 return (error);
2486
2487 error = mac_check_structmac_consistent(&mac);
2488 if (error)
2489 return (error);
2490
2491 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2492 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2493 if (error) {
2494 free(elements, M_MACTEMP);
2495 return (error);
2496 }
2497
2498 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2499 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2500 buffer, mac.m_buflen, M_WAITOK);
2501 if (error == 0)
2502 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2503
2504 free(buffer, M_MACTEMP);
2505 free(elements, M_MACTEMP);
2506
2507 return (error);
2508}
2509
2510int
2511mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2512 struct ifnet *ifnet)
2513{
2514 struct label intlabel;
2515 struct mac mac;
2516 char *buffer;
2517 int error;
2518
2519 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2520 if (error)
2521 return (error);
2522
2523 error = mac_check_structmac_consistent(&mac);
2524 if (error)
2525 return (error);
2526
2527 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2528 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2529 if (error) {
2530 free(buffer, M_MACTEMP);
2531 return (error);
2532 }
2533
2534 mac_init_ifnet_label(&intlabel);
2535 error = mac_internalize_ifnet_label(&intlabel, buffer);
2536 free(buffer, M_MACTEMP);
2537 if (error) {
2538 mac_destroy_ifnet_label(&intlabel);
2539 return (error);
2540 }
2541
2542 /*
2543 * XXX: Note that this is a redundant privilege check, since
2544 * policies impose this check themselves if required by the
2545 * policy. Eventually, this should go away.
2546 */
2547 error = suser_cred(cred, 0);
2548 if (error) {
2549 mac_destroy_ifnet_label(&intlabel);
2550 return (error);
2551 }
2552
2553 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2554 &intlabel);
2555 if (error) {
2556 mac_destroy_ifnet_label(&intlabel);
2557 return (error);
2558 }
2559
2560 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2561
2562 mac_destroy_ifnet_label(&intlabel);
2563 return (0);
2564}
2565
2566void
2567mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2568{
2569
2570 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2571}
2572
2573void
2574mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2575{
2576
2577 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2578}
2579
2580void
2581mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2582 struct devfs_dirent *de)
2583{
2584
2585 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2586 &de->de_label);
2587}
2588
2589void
2590mac_create_devfs_directory(char *dirname, int dirnamelen,
2591 struct devfs_dirent *de)
2592{
2593
2594 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2595 &de->de_label);
2596}
2597
2598int
2599mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2600 struct mac *mac)
2601{
2602 struct label intlabel;
2603 char *buffer;
2604 int error;
2605
2606 error = mac_check_structmac_consistent(mac);
2607 if (error)
2608 return (error);
2609
2610 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2611 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2612 if (error) {
2613 free(buffer, M_MACTEMP);
2614 return (error);
2615 }
2616
2617 mac_init_socket_label(&intlabel, M_WAITOK);
2618 error = mac_internalize_socket_label(&intlabel, buffer);
2619 free(buffer, M_MACTEMP);
2620 if (error) {
2621 mac_destroy_socket_label(&intlabel);
2622 return (error);
2623 }
2624
2625 mac_check_socket_relabel(cred, so, &intlabel);
2626 if (error) {
2627 mac_destroy_socket_label(&intlabel);
2628 return (error);
2629 }
2630
2631 mac_relabel_socket(cred, so, &intlabel);
2632
2633 mac_destroy_socket_label(&intlabel);
2634 return (0);
2635}
2636
2637int
2638mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2639{
2640 int error;
2641
2642 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2643
2644 error = mac_check_pipe_relabel(cred, pipe, label);
2645 if (error)
2646 return (error);
2647
2648 mac_relabel_pipe(cred, pipe, label);
2649
2650 return (0);
2651}
2652
2653int
2654mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2655 struct mac *mac)
2656{
2657 char *buffer, *elements;
2658 int error;
2659
2660 error = mac_check_structmac_consistent(mac);
2661 if (error)
2662 return (error);
2663
2664 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2665 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2666 if (error) {
2667 free(elements, M_MACTEMP);
2668 return (error);
2669 }
2670
2671 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2672 error = mac_externalize_socket_label(&so->so_label, elements,
2673 buffer, mac->m_buflen, M_WAITOK);
2674 if (error == 0)
2675 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2676
2677 free(buffer, M_MACTEMP);
2678 free(elements, M_MACTEMP);
2679
2680 return (error);
2681}
2682
2683int
2684mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2685 struct mac *mac)
2686{
2687 char *elements, *buffer;
2688 int error;
2689
2690 error = mac_check_structmac_consistent(mac);
2691 if (error)
2692 return (error);
2693
2694 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2695 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2696 if (error) {
2697 free(elements, M_MACTEMP);
2698 return (error);
2699 }
2700
2701 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2702 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2703 elements, buffer, mac->m_buflen, M_WAITOK);
2704 if (error == 0)
2705 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2706
2707 free(buffer, M_MACTEMP);
2708 free(elements, M_MACTEMP);
2709
2710 return (error);
2711}
2712
2713/*
2714 * Implementation of VOP_SETLABEL() that relies on extended attributes
2715 * to store label data. Can be referenced by filesystems supporting
2716 * extended attributes.
2717 */
2718int
2719vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2720{
2721 struct vnode *vp = ap->a_vp;
2722 struct label *intlabel = ap->a_label;
2723 int error;
2724
2725 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2726
2727 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2728 return (EOPNOTSUPP);
2729
2730 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2731 if (error)
2732 return (error);
2733
2734 mac_relabel_vnode(ap->a_cred, vp, intlabel);
2735
2736 return (0);
2737}
2738
2739static int
2740vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2741{
2742 int error;
2743
2744 if (vp->v_mount == NULL) {
2745 /* printf("vn_setlabel: null v_mount\n"); */
2746 if (vp->v_type != VNON)
2747 printf("vn_setlabel: null v_mount with non-VNON\n");
2748 return (EBADF);
2749 }
2750
2751 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2752 return (EOPNOTSUPP);
2753
2754 /*
2755 * Multi-phase commit. First check the policies to confirm the
2756 * change is OK. Then commit via the filesystem. Finally,
2757 * update the actual vnode label. Question: maybe the filesystem
2758 * should update the vnode at the end as part of VOP_SETLABEL()?
2759 */
2760 error = mac_check_vnode_relabel(cred, vp, intlabel);
2761 if (error)
2762 return (error);
2763
2764 /*
2765 * VADMIN provides the opportunity for the filesystem to make
2766 * decisions about who is and is not able to modify labels
2767 * and protections on files. This might not be right. We can't
2768 * assume VOP_SETLABEL() will do it, because we might implement
2769 * that as part of vop_stdsetlabel_ea().
2770 */
2771 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2772 if (error)
2773 return (error);
2774
2775 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2776 if (error)
2777 return (error);
2778
2779 return (0);
2780}
2781
2782int
2783__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
2784{
2785 char *elements, *buffer;
2786 struct mac mac;
2787 struct proc *tproc;
2788 struct ucred *tcred;
2789 int error;
2790
2791 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
2792 if (error)
2793 return (error);
2794
2795 error = mac_check_structmac_consistent(&mac);
2796 if (error)
2797 return (error);
2798
2799 tproc = pfind(uap->pid);
2800 if (tproc == NULL)
2801 return (ESRCH);
2802
2803 tcred = NULL; /* Satisfy gcc. */
2804 error = p_cansee(td, tproc);
2805 if (error == 0)
2806 tcred = crhold(tproc->p_ucred);
2807 PROC_UNLOCK(tproc);
2808 if (error)
2809 return (error);
2810
2811 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2812 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2813 if (error) {
2814 free(elements, M_MACTEMP);
2815 crfree(tcred);
2816 return (error);
2817 }
2818
2819 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2820 error = mac_externalize_cred_label(&tcred->cr_label, elements,
2821 buffer, mac.m_buflen, M_WAITOK);
2822 if (error == 0)
2823 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2824
2825 free(buffer, M_MACTEMP);
2826 free(elements, M_MACTEMP);
2827 crfree(tcred);
2828 return (error);
2829}
2830
2831/*
2832 * MPSAFE
2833 */
2834int
2835__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2836{
2837 char *elements, *buffer;
2838 struct mac mac;
2839 int error;
2840
2841 error = copyin(uap->mac_p, &mac, sizeof(mac));
2842 if (error)
2843 return (error);
2844
2845 error = mac_check_structmac_consistent(&mac);
2846 if (error)
2847 return (error);
2848
2849 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2850 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2851 if (error) {
2852 free(elements, M_MACTEMP);
2853 return (error);
2854 }
2855
2856 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2857 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
2858 elements, buffer, mac.m_buflen, M_WAITOK);
2859 if (error == 0)
2860 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2861
2862 free(buffer, M_MACTEMP);
2863 free(elements, M_MACTEMP);
2864 return (error);
2865}
2866
2867/*
2868 * MPSAFE
2869 */
2870int
2871__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2872{
2873 struct ucred *newcred, *oldcred;
2874 struct label intlabel;
2875 struct proc *p;
2876 struct mac mac;
2877 char *buffer;
2878 int error;
2879
2880 error = copyin(uap->mac_p, &mac, sizeof(mac));
2881 if (error)
2882 return (error);
2883
2884 error = mac_check_structmac_consistent(&mac);
2885 if (error)
2886 return (error);
2887
2888 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2889 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2890 if (error) {
2891 free(buffer, M_MACTEMP);
2892 return (error);
2893 }
2894
2895 mac_init_cred_label(&intlabel);
2896 error = mac_internalize_cred_label(&intlabel, buffer);
2897 free(buffer, M_MACTEMP);
2898 if (error) {
2899 mac_destroy_cred_label(&intlabel);
2900 return (error);
2901 }
2902
2903 newcred = crget();
2904
2905 p = td->td_proc;
2906 PROC_LOCK(p);
2907 oldcred = p->p_ucred;
2908
2909 error = mac_check_cred_relabel(oldcred, &intlabel);
2910 if (error) {
2911 PROC_UNLOCK(p);
2912 crfree(newcred);
2913 goto out;
2914 }
2915
2916 setsugid(p);
2917 crcopy(newcred, oldcred);
2918 mac_relabel_cred(newcred, &intlabel);
2919 p->p_ucred = newcred;
2920
2921 /*
2922 * Grab additional reference for use while revoking mmaps, prior
2923 * to releasing the proc lock and sharing the cred.
2924 */
2925 crhold(newcred);
2926 PROC_UNLOCK(p);
2927
2928 if (mac_enforce_vm) {
2929 mtx_lock(&Giant);
2930 mac_cred_mmapped_drop_perms(td, newcred);
2931 mtx_unlock(&Giant);
2932 }
2933
2934 crfree(newcred); /* Free revocation reference. */
2935 crfree(oldcred);
2936
2937out:
2938 mac_destroy_cred_label(&intlabel);
2939 return (error);
2940}
2941
2942/*
2943 * MPSAFE
2944 */
2945int
2946__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
2947{
2948 char *elements, *buffer;
2949 struct label intlabel;
2950 struct file *fp;
2951 struct mac mac;
2952 struct vnode *vp;
2953 struct pipe *pipe;
2954 short label_type;
2955 int error;
2956
2957 error = copyin(uap->mac_p, &mac, sizeof(mac));
2958 if (error)
2959 return (error);
2960
2961 error = mac_check_structmac_consistent(&mac);
2962 if (error)
2963 return (error);
2964
2965 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2966 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2967 if (error) {
2968 free(elements, M_MACTEMP);
2969 return (error);
2970 }
2971
2972 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2973 mtx_lock(&Giant); /* VFS */
2974 error = fget(td, SCARG(uap, fd), &fp);
2975 if (error)
2976 goto out;
2977
2978 label_type = fp->f_type;
2979 switch (fp->f_type) {
2980 case DTYPE_FIFO:
2981 case DTYPE_VNODE:
2982 vp = (struct vnode *)fp->f_data;
2983
2984 mac_init_vnode_label(&intlabel);
2985
2986 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2987 mac_copy_vnode_label(&vp->v_label, &intlabel);
2988 VOP_UNLOCK(vp, 0, td);
2989
2990 break;
2991 case DTYPE_PIPE:
2992 pipe = (struct pipe *)fp->f_data;
2993
2994 mac_init_pipe_label(&intlabel);
2995
2996 PIPE_LOCK(pipe);
2997 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
2998 PIPE_UNLOCK(pipe);
2999 break;
3000 default:
3001 error = EINVAL;
3002 fdrop(fp, td);
3003 goto out;
3004 }
3005 fdrop(fp, td);
3006
3007 switch (label_type) {
3008 case DTYPE_FIFO:
3009 case DTYPE_VNODE:
3010 if (error == 0)
3011 error = mac_externalize_vnode_label(&intlabel,
3012 elements, buffer, mac.m_buflen, M_WAITOK);
3013 mac_destroy_vnode_label(&intlabel);
3014 break;
3015 case DTYPE_PIPE:
3016 error = mac_externalize_pipe_label(&intlabel, elements,
3017 buffer, mac.m_buflen, M_WAITOK);
3018 mac_destroy_pipe_label(&intlabel);
3019 break;
3020 default:
3021 panic("__mac_get_fd: corrupted label_type");
3022 }
3023
3024 if (error == 0)
3025 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3026
3027out:
3028 mtx_unlock(&Giant); /* VFS */
3029 free(buffer, M_MACTEMP);
3030 free(elements, M_MACTEMP);
3031
3032 return (error);
3033}
3034
3035/*
3036 * MPSAFE
3037 */
3038int
3039__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3040{
3041 char *elements, *buffer;
3042 struct nameidata nd;
3043 struct label intlabel;
3044 struct mac mac;
3045 int error;
3046
3047 error = copyin(uap->mac_p, &mac, sizeof(mac));
3048 if (error)
3049 return (error);
3050
3051 error = mac_check_structmac_consistent(&mac);
3052 if (error)
3053 return (error);
3054
3055 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3056 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3057 if (error) {
3058 free(elements, M_MACTEMP);
3059 return (error);
3060 }
3061
3062 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3063 mtx_lock(&Giant); /* VFS */
3064 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3065 td);
3066 error = namei(&nd);
3067 if (error)
3068 goto out;
3069
3070 mac_init_vnode_label(&intlabel);
3071 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3072 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3073 mac.m_buflen, M_WAITOK);
3074
3075 NDFREE(&nd, 0);
3076 mac_destroy_vnode_label(&intlabel);
3077
3078 if (error == 0)
3079 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3080
3081out:
3082 mtx_unlock(&Giant); /* VFS */
3083
3084 free(buffer, M_MACTEMP);
3085 free(elements, M_MACTEMP);
3086
3087 return (error);
3088}
3089
3090/*
3091 * MPSAFE
3092 */
3093int
3094__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3095{
3096 char *elements, *buffer;
3097 struct nameidata nd;
3098 struct label intlabel;
3099 struct mac mac;
3100 int error;
3101
3102 error = copyin(uap->mac_p, &mac, sizeof(mac));
3103 if (error)
3104 return (error);
3105
3106 error = mac_check_structmac_consistent(&mac);
3107 if (error)
3108 return (error);
3109
3110 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3111 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3112 if (error) {
3113 free(elements, M_MACTEMP);
3114 return (error);
3115 }
3116
3117 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3118 mtx_lock(&Giant); /* VFS */
3119 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3120 td);
3121 error = namei(&nd);
3122 if (error)
3123 goto out;
3124
3125 mac_init_vnode_label(&intlabel);
3126 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3127 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3128 mac.m_buflen, M_WAITOK);
3129 NDFREE(&nd, 0);
3130 mac_destroy_vnode_label(&intlabel);
3131
3132 if (error == 0)
3133 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3134
3135out:
3136 mtx_unlock(&Giant); /* VFS */
3137
3138 free(buffer, M_MACTEMP);
3139 free(elements, M_MACTEMP);
3140
3141 return (error);
3142}
3143
3144/*
3145 * MPSAFE
3146 */
3147int
3148__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3149{
3150 struct label intlabel;
3151 struct pipe *pipe;
3152 struct file *fp;
3153 struct mount *mp;
3154 struct vnode *vp;
3155 struct mac mac;
3156 char *buffer;
3157 int error;
3158
3159 error = copyin(uap->mac_p, &mac, sizeof(mac));
3160 if (error)
3161 return (error);
3162
3163 error = mac_check_structmac_consistent(&mac);
3164 if (error)
3165 return (error);
3166
3167 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3168 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3169 if (error) {
3170 free(buffer, M_MACTEMP);
3171 return (error);
3172 }
3173
3174 mtx_lock(&Giant); /* VFS */
3175
3176 error = fget(td, SCARG(uap, fd), &fp);
3177 if (error)
3178 goto out;
3179
3180 switch (fp->f_type) {
3181 case DTYPE_FIFO:
3182 case DTYPE_VNODE:
3183 mac_init_vnode_label(&intlabel);
3184 error = mac_internalize_vnode_label(&intlabel, buffer);
3185 if (error) {
3186 mac_destroy_vnode_label(&intlabel);
3187 break;
3188 }
3189
3190 vp = (struct vnode *)fp->f_data;
3191 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3192 if (error != 0) {
3193 mac_destroy_vnode_label(&intlabel);
3194 break;
3195 }
3196
3197 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3198 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3199 VOP_UNLOCK(vp, 0, td);
3200 vn_finished_write(mp);
3201
3202 mac_destroy_vnode_label(&intlabel);
3203 break;
3204
3205 case DTYPE_PIPE:
3206 mac_init_pipe_label(&intlabel);
3207 error = mac_internalize_pipe_label(&intlabel, buffer);
3208 if (error == 0) {
3209 pipe = (struct pipe *)fp->f_data;
3210 PIPE_LOCK(pipe);
3211 error = mac_pipe_label_set(td->td_ucred, pipe,
3212 &intlabel);
3213 PIPE_UNLOCK(pipe);
3214 }
3215
3216 mac_destroy_pipe_label(&intlabel);
3217 break;
3218
3219 default:
3220 error = EINVAL;
3221 }
3222
3223 fdrop(fp, td);
3224out:
3225 mtx_unlock(&Giant); /* VFS */
3226
3227 free(buffer, M_MACTEMP);
3228
3229 return (error);
3230}
3231
3232/*
3233 * MPSAFE
3234 */
3235int
3236__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3237{
3238 struct label intlabel;
3239 struct nameidata nd;
3240 struct mount *mp;
3241 struct mac mac;
3242 char *buffer;
3243 int error;
3244
3245 error = copyin(uap->mac_p, &mac, sizeof(mac));
3246 if (error)
3247 return (error);
3248
3249 error = mac_check_structmac_consistent(&mac);
3250 if (error)
3251 return (error);
3252
3253 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3254 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3255 if (error) {
3256 free(buffer, M_MACTEMP);
3257 return (error);
3258 }
3259
3260 mac_init_vnode_label(&intlabel);
3261 error = mac_internalize_vnode_label(&intlabel, buffer);
3262 free(buffer, M_MACTEMP);
3263 if (error) {
3264 mac_destroy_vnode_label(&intlabel);
3265 return (error);
3266 }
3267
3268 mtx_lock(&Giant); /* VFS */
3269
3270 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3271 td);
3272 error = namei(&nd);
3273 if (error == 0) {
3274 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3275 if (error == 0)
3276 error = vn_setlabel(nd.ni_vp, &intlabel,
3277 td->td_ucred);
3278 vn_finished_write(mp);
3279 }
3280
3281 NDFREE(&nd, 0);
3282 mtx_unlock(&Giant); /* VFS */
3283 mac_destroy_vnode_label(&intlabel);
3284
3285 return (error);
3286}
3287
3288/*
3289 * MPSAFE
3290 */
3291int
3292__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3293{
3294 struct label intlabel;
3295 struct nameidata nd;
3296 struct mount *mp;
3297 struct mac mac;
3298 char *buffer;
3299 int error;
3300
3301 error = copyin(uap->mac_p, &mac, sizeof(mac));
3302 if (error)
3303 return (error);
3304
3305 error = mac_check_structmac_consistent(&mac);
3306 if (error)
3307 return (error);
3308
3309 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3310 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3311 if (error) {
3312 free(buffer, M_MACTEMP);
3313 return (error);
3314 }
3315
3316 mac_init_vnode_label(&intlabel);
3317 error = mac_internalize_vnode_label(&intlabel, buffer);
3318 free(buffer, M_MACTEMP);
3319 if (error) {
3320 mac_destroy_vnode_label(&intlabel);
3321 return (error);
3322 }
3323
3324 mtx_lock(&Giant); /* VFS */
3325
3326 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3327 td);
3328 error = namei(&nd);
3329 if (error == 0) {
3330 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3331 if (error == 0)
3332 error = vn_setlabel(nd.ni_vp, &intlabel,
3333 td->td_ucred);
3334 vn_finished_write(mp);
3335 }
3336
3337 NDFREE(&nd, 0);
3338 mtx_unlock(&Giant); /* VFS */
3339 mac_destroy_vnode_label(&intlabel);
3340
3341 return (error);
3342}
3343
3344/*
3345 * MPSAFE
3346 */
3347int
3348mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3349{
3350 struct mac_policy_conf *mpc;
3351 char target[MAC_MAX_POLICY_NAME];
3352 int error;
3353
3354 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3355 if (error)
3356 return (error);
3357
3358 error = ENOSYS;
3359 MAC_POLICY_LIST_BUSY();
3360 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3361 if (strcmp(mpc->mpc_name, target) == 0 &&
3362 mpc->mpc_ops->mpo_syscall != NULL) {
3363 error = mpc->mpc_ops->mpo_syscall(td,
3364 SCARG(uap, call), SCARG(uap, arg));
3365 goto out;
3366 }
3367 }
3368
3369out:
3370 MAC_POLICY_LIST_UNBUSY();
3371 return (error);
3372}
3373
3374SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3375SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3376
3377#else /* !MAC */
3378
3379int
3380__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3381{
3382
3383 return (ENOSYS);
3384}
3385
3386int
3387__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3388{
3389
3390 return (ENOSYS);
3391}
3392
3393int
3394__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3395{
3396
3397 return (ENOSYS);
3398}
3399
3400int
3401__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3402{
3403
3404 return (ENOSYS);
3405}
3406
3407int
3408__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3409{
3410
3411 return (ENOSYS);
3412}
3413
3414int
3415__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3416{
3417
3418 return (ENOSYS);
3419}
3420
3421int
3422__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3423{
3424
3425 return (ENOSYS);
3426}
3427
3428int
3429__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3430{
3431
3432 return (ENOSYS);
3433}
3434
3435int
3436__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3437{
3438
3439 return (ENOSYS);
3440}
3441
3442int
3443mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3444{
3445
3446 return (ENOSYS);
3447}
3448
3449#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_system.c 106217 2002-10-30 18:48:51Z 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_mount_stat(struct ucred *cred, struct mount *mount)
2174{
2175 int error;
2176
2177 if (!mac_enforce_fs)
2178 return (0);
2179
2180 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2181
2182 return (error);
2183}
2184
2185int
2186mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2187 void *data)
2188{
2189 int error;
2190
2191 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2192
2193 if (!mac_enforce_pipe)
2194 return (0);
2195
2196 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2197
2198 return (error);
2199}
2200
2201int
2202mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2203{
2204 int error;
2205
2206 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2207
2208 if (!mac_enforce_pipe)
2209 return (0);
2210
2211 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2212
2213 return (error);
2214}
2215
2216int
2217mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2218{
2219 int error;
2220
2221 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2222
2223 if (!mac_enforce_pipe)
2224 return (0);
2225
2226 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2227
2228 return (error);
2229}
2230
2231static int
2232mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2233 struct label *newlabel)
2234{
2235 int error;
2236
2237 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2238
2239 if (!mac_enforce_pipe)
2240 return (0);
2241
2242 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2243
2244 return (error);
2245}
2246
2247int
2248mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2249{
2250 int error;
2251
2252 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2253
2254 if (!mac_enforce_pipe)
2255 return (0);
2256
2257 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2258
2259 return (error);
2260}
2261
2262int
2263mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2264{
2265 int error;
2266
2267 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2268
2269 if (!mac_enforce_pipe)
2270 return (0);
2271
2272 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2273
2274 return (error);
2275}
2276
2277int
2278mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2279{
2280 int error;
2281
2282 PROC_LOCK_ASSERT(proc, MA_OWNED);
2283
2284 if (!mac_enforce_process)
2285 return (0);
2286
2287 MAC_CHECK(check_proc_debug, cred, proc);
2288
2289 return (error);
2290}
2291
2292int
2293mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2294{
2295 int error;
2296
2297 PROC_LOCK_ASSERT(proc, MA_OWNED);
2298
2299 if (!mac_enforce_process)
2300 return (0);
2301
2302 MAC_CHECK(check_proc_sched, cred, proc);
2303
2304 return (error);
2305}
2306
2307int
2308mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2309{
2310 int error;
2311
2312 PROC_LOCK_ASSERT(proc, MA_OWNED);
2313
2314 if (!mac_enforce_process)
2315 return (0);
2316
2317 MAC_CHECK(check_proc_signal, cred, proc, signum);
2318
2319 return (error);
2320}
2321
2322int
2323mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2324 struct sockaddr *sockaddr)
2325{
2326 int error;
2327
2328 if (!mac_enforce_socket)
2329 return (0);
2330
2331 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2332 sockaddr);
2333
2334 return (error);
2335}
2336
2337int
2338mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2339 struct sockaddr *sockaddr)
2340{
2341 int error;
2342
2343 if (!mac_enforce_socket)
2344 return (0);
2345
2346 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2347 sockaddr);
2348
2349 return (error);
2350}
2351
2352int
2353mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2354{
2355 int error;
2356
2357 if (!mac_enforce_socket)
2358 return (0);
2359
2360 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2361 &mbuf->m_pkthdr.label);
2362
2363 return (error);
2364}
2365
2366int
2367mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2368{
2369 int error;
2370
2371 if (!mac_enforce_socket)
2372 return (0);
2373
2374 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2375 return (error);
2376}
2377
2378int
2379mac_check_socket_receive(struct ucred *cred, struct socket *so)
2380{
2381 int error;
2382
2383 if (!mac_enforce_socket)
2384 return (0);
2385
2386 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2387
2388 return (error);
2389}
2390
2391static int
2392mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2393 struct label *newlabel)
2394{
2395 int error;
2396
2397 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2398 newlabel);
2399
2400 return (error);
2401}
2402
2403int
2404mac_check_socket_send(struct ucred *cred, struct socket *so)
2405{
2406 int error;
2407
2408 if (!mac_enforce_socket)
2409 return (0);
2410
2411 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2412
2413 return (error);
2414}
2415
2416int
2417mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2418{
2419 int error;
2420
2421 if (!mac_enforce_socket)
2422 return (0);
2423
2424 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2425
2426 return (error);
2427}
2428
2429int
2430mac_check_system_reboot(struct ucred *cred, int howto)
2431{
2432 int error;
2433
2434 if (!mac_enforce_system)
2435 return (0);
2436
2437 MAC_CHECK(check_system_reboot, cred, howto);
2438
2439 return (error);
2440}
2441
2442int
2443mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2444{
2445 int error;
2446
2447 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2448
2449 if (!mac_enforce_system)
2450 return (0);
2451
2452 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2453 return (error);
2454}
2455
2456int
2457mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2458 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2459{
2460 int error;
2461
2462 /*
2463 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2464 * but since it's not exported from kern_sysctl.c, we can't.
2465 */
2466 if (!mac_enforce_system)
2467 return (0);
2468
2469 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2470 inkernel, new, newlen);
2471
2472 return (error);
2473}
2474
2475int
2476mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2477 struct ifnet *ifnet)
2478{
2479 char *elements, *buffer;
2480 struct mac mac;
2481 int error;
2482
2483 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2484 if (error)
2485 return (error);
2486
2487 error = mac_check_structmac_consistent(&mac);
2488 if (error)
2489 return (error);
2490
2491 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2492 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2493 if (error) {
2494 free(elements, M_MACTEMP);
2495 return (error);
2496 }
2497
2498 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2499 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2500 buffer, mac.m_buflen, M_WAITOK);
2501 if (error == 0)
2502 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2503
2504 free(buffer, M_MACTEMP);
2505 free(elements, M_MACTEMP);
2506
2507 return (error);
2508}
2509
2510int
2511mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2512 struct ifnet *ifnet)
2513{
2514 struct label intlabel;
2515 struct mac mac;
2516 char *buffer;
2517 int error;
2518
2519 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2520 if (error)
2521 return (error);
2522
2523 error = mac_check_structmac_consistent(&mac);
2524 if (error)
2525 return (error);
2526
2527 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2528 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2529 if (error) {
2530 free(buffer, M_MACTEMP);
2531 return (error);
2532 }
2533
2534 mac_init_ifnet_label(&intlabel);
2535 error = mac_internalize_ifnet_label(&intlabel, buffer);
2536 free(buffer, M_MACTEMP);
2537 if (error) {
2538 mac_destroy_ifnet_label(&intlabel);
2539 return (error);
2540 }
2541
2542 /*
2543 * XXX: Note that this is a redundant privilege check, since
2544 * policies impose this check themselves if required by the
2545 * policy. Eventually, this should go away.
2546 */
2547 error = suser_cred(cred, 0);
2548 if (error) {
2549 mac_destroy_ifnet_label(&intlabel);
2550 return (error);
2551 }
2552
2553 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2554 &intlabel);
2555 if (error) {
2556 mac_destroy_ifnet_label(&intlabel);
2557 return (error);
2558 }
2559
2560 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2561
2562 mac_destroy_ifnet_label(&intlabel);
2563 return (0);
2564}
2565
2566void
2567mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2568{
2569
2570 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2571}
2572
2573void
2574mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2575{
2576
2577 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2578}
2579
2580void
2581mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
2582 struct devfs_dirent *de)
2583{
2584
2585 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
2586 &de->de_label);
2587}
2588
2589void
2590mac_create_devfs_directory(char *dirname, int dirnamelen,
2591 struct devfs_dirent *de)
2592{
2593
2594 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2595 &de->de_label);
2596}
2597
2598int
2599mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2600 struct mac *mac)
2601{
2602 struct label intlabel;
2603 char *buffer;
2604 int error;
2605
2606 error = mac_check_structmac_consistent(mac);
2607 if (error)
2608 return (error);
2609
2610 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2611 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
2612 if (error) {
2613 free(buffer, M_MACTEMP);
2614 return (error);
2615 }
2616
2617 mac_init_socket_label(&intlabel, M_WAITOK);
2618 error = mac_internalize_socket_label(&intlabel, buffer);
2619 free(buffer, M_MACTEMP);
2620 if (error) {
2621 mac_destroy_socket_label(&intlabel);
2622 return (error);
2623 }
2624
2625 mac_check_socket_relabel(cred, so, &intlabel);
2626 if (error) {
2627 mac_destroy_socket_label(&intlabel);
2628 return (error);
2629 }
2630
2631 mac_relabel_socket(cred, so, &intlabel);
2632
2633 mac_destroy_socket_label(&intlabel);
2634 return (0);
2635}
2636
2637int
2638mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2639{
2640 int error;
2641
2642 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2643
2644 error = mac_check_pipe_relabel(cred, pipe, label);
2645 if (error)
2646 return (error);
2647
2648 mac_relabel_pipe(cred, pipe, label);
2649
2650 return (0);
2651}
2652
2653int
2654mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2655 struct mac *mac)
2656{
2657 char *buffer, *elements;
2658 int error;
2659
2660 error = mac_check_structmac_consistent(mac);
2661 if (error)
2662 return (error);
2663
2664 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2665 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2666 if (error) {
2667 free(elements, M_MACTEMP);
2668 return (error);
2669 }
2670
2671 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2672 error = mac_externalize_socket_label(&so->so_label, elements,
2673 buffer, mac->m_buflen, M_WAITOK);
2674 if (error == 0)
2675 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2676
2677 free(buffer, M_MACTEMP);
2678 free(elements, M_MACTEMP);
2679
2680 return (error);
2681}
2682
2683int
2684mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2685 struct mac *mac)
2686{
2687 char *elements, *buffer;
2688 int error;
2689
2690 error = mac_check_structmac_consistent(mac);
2691 if (error)
2692 return (error);
2693
2694 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
2695 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
2696 if (error) {
2697 free(elements, M_MACTEMP);
2698 return (error);
2699 }
2700
2701 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2702 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
2703 elements, buffer, mac->m_buflen, M_WAITOK);
2704 if (error == 0)
2705 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
2706
2707 free(buffer, M_MACTEMP);
2708 free(elements, M_MACTEMP);
2709
2710 return (error);
2711}
2712
2713/*
2714 * Implementation of VOP_SETLABEL() that relies on extended attributes
2715 * to store label data. Can be referenced by filesystems supporting
2716 * extended attributes.
2717 */
2718int
2719vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2720{
2721 struct vnode *vp = ap->a_vp;
2722 struct label *intlabel = ap->a_label;
2723 int error;
2724
2725 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2726
2727 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2728 return (EOPNOTSUPP);
2729
2730 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
2731 if (error)
2732 return (error);
2733
2734 mac_relabel_vnode(ap->a_cred, vp, intlabel);
2735
2736 return (0);
2737}
2738
2739static int
2740vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
2741{
2742 int error;
2743
2744 if (vp->v_mount == NULL) {
2745 /* printf("vn_setlabel: null v_mount\n"); */
2746 if (vp->v_type != VNON)
2747 printf("vn_setlabel: null v_mount with non-VNON\n");
2748 return (EBADF);
2749 }
2750
2751 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2752 return (EOPNOTSUPP);
2753
2754 /*
2755 * Multi-phase commit. First check the policies to confirm the
2756 * change is OK. Then commit via the filesystem. Finally,
2757 * update the actual vnode label. Question: maybe the filesystem
2758 * should update the vnode at the end as part of VOP_SETLABEL()?
2759 */
2760 error = mac_check_vnode_relabel(cred, vp, intlabel);
2761 if (error)
2762 return (error);
2763
2764 /*
2765 * VADMIN provides the opportunity for the filesystem to make
2766 * decisions about who is and is not able to modify labels
2767 * and protections on files. This might not be right. We can't
2768 * assume VOP_SETLABEL() will do it, because we might implement
2769 * that as part of vop_stdsetlabel_ea().
2770 */
2771 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2772 if (error)
2773 return (error);
2774
2775 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2776 if (error)
2777 return (error);
2778
2779 return (0);
2780}
2781
2782int
2783__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
2784{
2785 char *elements, *buffer;
2786 struct mac mac;
2787 struct proc *tproc;
2788 struct ucred *tcred;
2789 int error;
2790
2791 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
2792 if (error)
2793 return (error);
2794
2795 error = mac_check_structmac_consistent(&mac);
2796 if (error)
2797 return (error);
2798
2799 tproc = pfind(uap->pid);
2800 if (tproc == NULL)
2801 return (ESRCH);
2802
2803 tcred = NULL; /* Satisfy gcc. */
2804 error = p_cansee(td, tproc);
2805 if (error == 0)
2806 tcred = crhold(tproc->p_ucred);
2807 PROC_UNLOCK(tproc);
2808 if (error)
2809 return (error);
2810
2811 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2812 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2813 if (error) {
2814 free(elements, M_MACTEMP);
2815 crfree(tcred);
2816 return (error);
2817 }
2818
2819 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2820 error = mac_externalize_cred_label(&tcred->cr_label, elements,
2821 buffer, mac.m_buflen, M_WAITOK);
2822 if (error == 0)
2823 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2824
2825 free(buffer, M_MACTEMP);
2826 free(elements, M_MACTEMP);
2827 crfree(tcred);
2828 return (error);
2829}
2830
2831/*
2832 * MPSAFE
2833 */
2834int
2835__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2836{
2837 char *elements, *buffer;
2838 struct mac mac;
2839 int error;
2840
2841 error = copyin(uap->mac_p, &mac, sizeof(mac));
2842 if (error)
2843 return (error);
2844
2845 error = mac_check_structmac_consistent(&mac);
2846 if (error)
2847 return (error);
2848
2849 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2850 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2851 if (error) {
2852 free(elements, M_MACTEMP);
2853 return (error);
2854 }
2855
2856 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2857 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
2858 elements, buffer, mac.m_buflen, M_WAITOK);
2859 if (error == 0)
2860 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2861
2862 free(buffer, M_MACTEMP);
2863 free(elements, M_MACTEMP);
2864 return (error);
2865}
2866
2867/*
2868 * MPSAFE
2869 */
2870int
2871__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2872{
2873 struct ucred *newcred, *oldcred;
2874 struct label intlabel;
2875 struct proc *p;
2876 struct mac mac;
2877 char *buffer;
2878 int error;
2879
2880 error = copyin(uap->mac_p, &mac, sizeof(mac));
2881 if (error)
2882 return (error);
2883
2884 error = mac_check_structmac_consistent(&mac);
2885 if (error)
2886 return (error);
2887
2888 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2889 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2890 if (error) {
2891 free(buffer, M_MACTEMP);
2892 return (error);
2893 }
2894
2895 mac_init_cred_label(&intlabel);
2896 error = mac_internalize_cred_label(&intlabel, buffer);
2897 free(buffer, M_MACTEMP);
2898 if (error) {
2899 mac_destroy_cred_label(&intlabel);
2900 return (error);
2901 }
2902
2903 newcred = crget();
2904
2905 p = td->td_proc;
2906 PROC_LOCK(p);
2907 oldcred = p->p_ucred;
2908
2909 error = mac_check_cred_relabel(oldcred, &intlabel);
2910 if (error) {
2911 PROC_UNLOCK(p);
2912 crfree(newcred);
2913 goto out;
2914 }
2915
2916 setsugid(p);
2917 crcopy(newcred, oldcred);
2918 mac_relabel_cred(newcred, &intlabel);
2919 p->p_ucred = newcred;
2920
2921 /*
2922 * Grab additional reference for use while revoking mmaps, prior
2923 * to releasing the proc lock and sharing the cred.
2924 */
2925 crhold(newcred);
2926 PROC_UNLOCK(p);
2927
2928 if (mac_enforce_vm) {
2929 mtx_lock(&Giant);
2930 mac_cred_mmapped_drop_perms(td, newcred);
2931 mtx_unlock(&Giant);
2932 }
2933
2934 crfree(newcred); /* Free revocation reference. */
2935 crfree(oldcred);
2936
2937out:
2938 mac_destroy_cred_label(&intlabel);
2939 return (error);
2940}
2941
2942/*
2943 * MPSAFE
2944 */
2945int
2946__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
2947{
2948 char *elements, *buffer;
2949 struct label intlabel;
2950 struct file *fp;
2951 struct mac mac;
2952 struct vnode *vp;
2953 struct pipe *pipe;
2954 short label_type;
2955 int error;
2956
2957 error = copyin(uap->mac_p, &mac, sizeof(mac));
2958 if (error)
2959 return (error);
2960
2961 error = mac_check_structmac_consistent(&mac);
2962 if (error)
2963 return (error);
2964
2965 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2966 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2967 if (error) {
2968 free(elements, M_MACTEMP);
2969 return (error);
2970 }
2971
2972 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2973 mtx_lock(&Giant); /* VFS */
2974 error = fget(td, SCARG(uap, fd), &fp);
2975 if (error)
2976 goto out;
2977
2978 label_type = fp->f_type;
2979 switch (fp->f_type) {
2980 case DTYPE_FIFO:
2981 case DTYPE_VNODE:
2982 vp = (struct vnode *)fp->f_data;
2983
2984 mac_init_vnode_label(&intlabel);
2985
2986 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2987 mac_copy_vnode_label(&vp->v_label, &intlabel);
2988 VOP_UNLOCK(vp, 0, td);
2989
2990 break;
2991 case DTYPE_PIPE:
2992 pipe = (struct pipe *)fp->f_data;
2993
2994 mac_init_pipe_label(&intlabel);
2995
2996 PIPE_LOCK(pipe);
2997 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
2998 PIPE_UNLOCK(pipe);
2999 break;
3000 default:
3001 error = EINVAL;
3002 fdrop(fp, td);
3003 goto out;
3004 }
3005 fdrop(fp, td);
3006
3007 switch (label_type) {
3008 case DTYPE_FIFO:
3009 case DTYPE_VNODE:
3010 if (error == 0)
3011 error = mac_externalize_vnode_label(&intlabel,
3012 elements, buffer, mac.m_buflen, M_WAITOK);
3013 mac_destroy_vnode_label(&intlabel);
3014 break;
3015 case DTYPE_PIPE:
3016 error = mac_externalize_pipe_label(&intlabel, elements,
3017 buffer, mac.m_buflen, M_WAITOK);
3018 mac_destroy_pipe_label(&intlabel);
3019 break;
3020 default:
3021 panic("__mac_get_fd: corrupted label_type");
3022 }
3023
3024 if (error == 0)
3025 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3026
3027out:
3028 mtx_unlock(&Giant); /* VFS */
3029 free(buffer, M_MACTEMP);
3030 free(elements, M_MACTEMP);
3031
3032 return (error);
3033}
3034
3035/*
3036 * MPSAFE
3037 */
3038int
3039__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3040{
3041 char *elements, *buffer;
3042 struct nameidata nd;
3043 struct label intlabel;
3044 struct mac mac;
3045 int error;
3046
3047 error = copyin(uap->mac_p, &mac, sizeof(mac));
3048 if (error)
3049 return (error);
3050
3051 error = mac_check_structmac_consistent(&mac);
3052 if (error)
3053 return (error);
3054
3055 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3056 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3057 if (error) {
3058 free(elements, M_MACTEMP);
3059 return (error);
3060 }
3061
3062 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3063 mtx_lock(&Giant); /* VFS */
3064 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3065 td);
3066 error = namei(&nd);
3067 if (error)
3068 goto out;
3069
3070 mac_init_vnode_label(&intlabel);
3071 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3072 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3073 mac.m_buflen, M_WAITOK);
3074
3075 NDFREE(&nd, 0);
3076 mac_destroy_vnode_label(&intlabel);
3077
3078 if (error == 0)
3079 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3080
3081out:
3082 mtx_unlock(&Giant); /* VFS */
3083
3084 free(buffer, M_MACTEMP);
3085 free(elements, M_MACTEMP);
3086
3087 return (error);
3088}
3089
3090/*
3091 * MPSAFE
3092 */
3093int
3094__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3095{
3096 char *elements, *buffer;
3097 struct nameidata nd;
3098 struct label intlabel;
3099 struct mac mac;
3100 int error;
3101
3102 error = copyin(uap->mac_p, &mac, sizeof(mac));
3103 if (error)
3104 return (error);
3105
3106 error = mac_check_structmac_consistent(&mac);
3107 if (error)
3108 return (error);
3109
3110 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3111 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3112 if (error) {
3113 free(elements, M_MACTEMP);
3114 return (error);
3115 }
3116
3117 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3118 mtx_lock(&Giant); /* VFS */
3119 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3120 td);
3121 error = namei(&nd);
3122 if (error)
3123 goto out;
3124
3125 mac_init_vnode_label(&intlabel);
3126 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3127 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3128 mac.m_buflen, M_WAITOK);
3129 NDFREE(&nd, 0);
3130 mac_destroy_vnode_label(&intlabel);
3131
3132 if (error == 0)
3133 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3134
3135out:
3136 mtx_unlock(&Giant); /* VFS */
3137
3138 free(buffer, M_MACTEMP);
3139 free(elements, M_MACTEMP);
3140
3141 return (error);
3142}
3143
3144/*
3145 * MPSAFE
3146 */
3147int
3148__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3149{
3150 struct label intlabel;
3151 struct pipe *pipe;
3152 struct file *fp;
3153 struct mount *mp;
3154 struct vnode *vp;
3155 struct mac mac;
3156 char *buffer;
3157 int error;
3158
3159 error = copyin(uap->mac_p, &mac, sizeof(mac));
3160 if (error)
3161 return (error);
3162
3163 error = mac_check_structmac_consistent(&mac);
3164 if (error)
3165 return (error);
3166
3167 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3168 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3169 if (error) {
3170 free(buffer, M_MACTEMP);
3171 return (error);
3172 }
3173
3174 mtx_lock(&Giant); /* VFS */
3175
3176 error = fget(td, SCARG(uap, fd), &fp);
3177 if (error)
3178 goto out;
3179
3180 switch (fp->f_type) {
3181 case DTYPE_FIFO:
3182 case DTYPE_VNODE:
3183 mac_init_vnode_label(&intlabel);
3184 error = mac_internalize_vnode_label(&intlabel, buffer);
3185 if (error) {
3186 mac_destroy_vnode_label(&intlabel);
3187 break;
3188 }
3189
3190 vp = (struct vnode *)fp->f_data;
3191 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3192 if (error != 0) {
3193 mac_destroy_vnode_label(&intlabel);
3194 break;
3195 }
3196
3197 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3198 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3199 VOP_UNLOCK(vp, 0, td);
3200 vn_finished_write(mp);
3201
3202 mac_destroy_vnode_label(&intlabel);
3203 break;
3204
3205 case DTYPE_PIPE:
3206 mac_init_pipe_label(&intlabel);
3207 error = mac_internalize_pipe_label(&intlabel, buffer);
3208 if (error == 0) {
3209 pipe = (struct pipe *)fp->f_data;
3210 PIPE_LOCK(pipe);
3211 error = mac_pipe_label_set(td->td_ucred, pipe,
3212 &intlabel);
3213 PIPE_UNLOCK(pipe);
3214 }
3215
3216 mac_destroy_pipe_label(&intlabel);
3217 break;
3218
3219 default:
3220 error = EINVAL;
3221 }
3222
3223 fdrop(fp, td);
3224out:
3225 mtx_unlock(&Giant); /* VFS */
3226
3227 free(buffer, M_MACTEMP);
3228
3229 return (error);
3230}
3231
3232/*
3233 * MPSAFE
3234 */
3235int
3236__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3237{
3238 struct label intlabel;
3239 struct nameidata nd;
3240 struct mount *mp;
3241 struct mac mac;
3242 char *buffer;
3243 int error;
3244
3245 error = copyin(uap->mac_p, &mac, sizeof(mac));
3246 if (error)
3247 return (error);
3248
3249 error = mac_check_structmac_consistent(&mac);
3250 if (error)
3251 return (error);
3252
3253 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3254 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3255 if (error) {
3256 free(buffer, M_MACTEMP);
3257 return (error);
3258 }
3259
3260 mac_init_vnode_label(&intlabel);
3261 error = mac_internalize_vnode_label(&intlabel, buffer);
3262 free(buffer, M_MACTEMP);
3263 if (error) {
3264 mac_destroy_vnode_label(&intlabel);
3265 return (error);
3266 }
3267
3268 mtx_lock(&Giant); /* VFS */
3269
3270 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3271 td);
3272 error = namei(&nd);
3273 if (error == 0) {
3274 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3275 if (error == 0)
3276 error = vn_setlabel(nd.ni_vp, &intlabel,
3277 td->td_ucred);
3278 vn_finished_write(mp);
3279 }
3280
3281 NDFREE(&nd, 0);
3282 mtx_unlock(&Giant); /* VFS */
3283 mac_destroy_vnode_label(&intlabel);
3284
3285 return (error);
3286}
3287
3288/*
3289 * MPSAFE
3290 */
3291int
3292__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3293{
3294 struct label intlabel;
3295 struct nameidata nd;
3296 struct mount *mp;
3297 struct mac mac;
3298 char *buffer;
3299 int error;
3300
3301 error = copyin(uap->mac_p, &mac, sizeof(mac));
3302 if (error)
3303 return (error);
3304
3305 error = mac_check_structmac_consistent(&mac);
3306 if (error)
3307 return (error);
3308
3309 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3310 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3311 if (error) {
3312 free(buffer, M_MACTEMP);
3313 return (error);
3314 }
3315
3316 mac_init_vnode_label(&intlabel);
3317 error = mac_internalize_vnode_label(&intlabel, buffer);
3318 free(buffer, M_MACTEMP);
3319 if (error) {
3320 mac_destroy_vnode_label(&intlabel);
3321 return (error);
3322 }
3323
3324 mtx_lock(&Giant); /* VFS */
3325
3326 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3327 td);
3328 error = namei(&nd);
3329 if (error == 0) {
3330 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3331 if (error == 0)
3332 error = vn_setlabel(nd.ni_vp, &intlabel,
3333 td->td_ucred);
3334 vn_finished_write(mp);
3335 }
3336
3337 NDFREE(&nd, 0);
3338 mtx_unlock(&Giant); /* VFS */
3339 mac_destroy_vnode_label(&intlabel);
3340
3341 return (error);
3342}
3343
3344/*
3345 * MPSAFE
3346 */
3347int
3348mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3349{
3350 struct mac_policy_conf *mpc;
3351 char target[MAC_MAX_POLICY_NAME];
3352 int error;
3353
3354 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3355 if (error)
3356 return (error);
3357
3358 error = ENOSYS;
3359 MAC_POLICY_LIST_BUSY();
3360 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3361 if (strcmp(mpc->mpc_name, target) == 0 &&
3362 mpc->mpc_ops->mpo_syscall != NULL) {
3363 error = mpc->mpc_ops->mpo_syscall(td,
3364 SCARG(uap, call), SCARG(uap, arg));
3365 goto out;
3366 }
3367 }
3368
3369out:
3370 MAC_POLICY_LIST_UNBUSY();
3371 return (error);
3372}
3373
3374SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3375SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3376
3377#else /* !MAC */
3378
3379int
3380__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3381{
3382
3383 return (ENOSYS);
3384}
3385
3386int
3387__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3388{
3389
3390 return (ENOSYS);
3391}
3392
3393int
3394__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3395{
3396
3397 return (ENOSYS);
3398}
3399
3400int
3401__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3402{
3403
3404 return (ENOSYS);
3405}
3406
3407int
3408__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3409{
3410
3411 return (ENOSYS);
3412}
3413
3414int
3415__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3416{
3417
3418 return (ENOSYS);
3419}
3420
3421int
3422__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3423{
3424
3425 return (ENOSYS);
3426}
3427
3428int
3429__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3430{
3431
3432 return (ENOSYS);
3433}
3434
3435int
3436__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3437{
3438
3439 return (ENOSYS);
3440}
3441
3442int
3443mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3444{
3445
3446 return (ENOSYS);
3447}
3448
3449#endif