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