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