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