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