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