Deleted Added
full compact
mac_system.c (104524) mac_system.c (104527)
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 *
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_system.c 104524 2002-10-05 17:18:43Z rwatson $
39 * $FreeBSD: head/sys/security/mac/mac_system.c 104527 2002-10-05 17:38:45Z 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 =
668 mpe->mpe_function;
669 break;
670 case MAC_CREATE_PROC1:
671 mpc->mpc_ops->mpo_create_proc1 =
672 mpe->mpe_function;
673 break;
674 case MAC_RELABEL_CRED:
675 mpc->mpc_ops->mpo_relabel_cred =
676 mpe->mpe_function;
677 break;
678 case MAC_THREAD_USERRET:
679 mpc->mpc_ops->mpo_thread_userret =
680 mpe->mpe_function;
681 break;
682 case MAC_CHECK_BPFDESC_RECEIVE:
683 mpc->mpc_ops->mpo_check_bpfdesc_receive =
684 mpe->mpe_function;
685 break;
686 case MAC_CHECK_CRED_RELABEL:
687 mpc->mpc_ops->mpo_check_cred_relabel =
688 mpe->mpe_function;
689 break;
690 case MAC_CHECK_CRED_VISIBLE:
691 mpc->mpc_ops->mpo_check_cred_visible =
692 mpe->mpe_function;
693 break;
694 case MAC_CHECK_IFNET_RELABEL:
695 mpc->mpc_ops->mpo_check_ifnet_relabel =
696 mpe->mpe_function;
697 break;
698 case MAC_CHECK_IFNET_TRANSMIT:
699 mpc->mpc_ops->mpo_check_ifnet_transmit =
700 mpe->mpe_function;
701 break;
702 case MAC_CHECK_MOUNT_STAT:
703 mpc->mpc_ops->mpo_check_mount_stat =
704 mpe->mpe_function;
705 break;
706 case MAC_CHECK_PIPE_IOCTL:
707 mpc->mpc_ops->mpo_check_pipe_ioctl =
708 mpe->mpe_function;
709 break;
710 case MAC_CHECK_PIPE_POLL:
711 mpc->mpc_ops->mpo_check_pipe_poll =
712 mpe->mpe_function;
713 break;
714 case MAC_CHECK_PIPE_READ:
715 mpc->mpc_ops->mpo_check_pipe_read =
716 mpe->mpe_function;
717 break;
718 case MAC_CHECK_PIPE_RELABEL:
719 mpc->mpc_ops->mpo_check_pipe_relabel =
720 mpe->mpe_function;
721 break;
722 case MAC_CHECK_PIPE_STAT:
723 mpc->mpc_ops->mpo_check_pipe_stat =
724 mpe->mpe_function;
725 break;
726 case MAC_CHECK_PIPE_WRITE:
727 mpc->mpc_ops->mpo_check_pipe_write =
728 mpe->mpe_function;
729 break;
730 case MAC_CHECK_PROC_DEBUG:
731 mpc->mpc_ops->mpo_check_proc_debug =
732 mpe->mpe_function;
733 break;
734 case MAC_CHECK_PROC_SCHED:
735 mpc->mpc_ops->mpo_check_proc_sched =
736 mpe->mpe_function;
737 break;
738 case MAC_CHECK_PROC_SIGNAL:
739 mpc->mpc_ops->mpo_check_proc_signal =
740 mpe->mpe_function;
741 break;
742 case MAC_CHECK_SOCKET_BIND:
743 mpc->mpc_ops->mpo_check_socket_bind =
744 mpe->mpe_function;
745 break;
746 case MAC_CHECK_SOCKET_CONNECT:
747 mpc->mpc_ops->mpo_check_socket_connect =
748 mpe->mpe_function;
749 break;
750 case MAC_CHECK_SOCKET_DELIVER:
751 mpc->mpc_ops->mpo_check_socket_deliver =
752 mpe->mpe_function;
753 break;
754 case MAC_CHECK_SOCKET_LISTEN:
755 mpc->mpc_ops->mpo_check_socket_listen =
756 mpe->mpe_function;
757 break;
758 case MAC_CHECK_SOCKET_RELABEL:
759 mpc->mpc_ops->mpo_check_socket_relabel =
760 mpe->mpe_function;
761 break;
762 case MAC_CHECK_SOCKET_VISIBLE:
763 mpc->mpc_ops->mpo_check_socket_visible =
764 mpe->mpe_function;
765 break;
766 case MAC_CHECK_VNODE_ACCESS:
767 mpc->mpc_ops->mpo_check_vnode_access =
768 mpe->mpe_function;
769 break;
770 case MAC_CHECK_VNODE_CHDIR:
771 mpc->mpc_ops->mpo_check_vnode_chdir =
772 mpe->mpe_function;
773 break;
774 case MAC_CHECK_VNODE_CHROOT:
775 mpc->mpc_ops->mpo_check_vnode_chroot =
776 mpe->mpe_function;
777 break;
778 case MAC_CHECK_VNODE_CREATE:
779 mpc->mpc_ops->mpo_check_vnode_create =
780 mpe->mpe_function;
781 break;
782 case MAC_CHECK_VNODE_DELETE:
783 mpc->mpc_ops->mpo_check_vnode_delete =
784 mpe->mpe_function;
785 break;
786 case MAC_CHECK_VNODE_DELETEACL:
787 mpc->mpc_ops->mpo_check_vnode_deleteacl =
788 mpe->mpe_function;
789 break;
790 case MAC_CHECK_VNODE_EXEC:
791 mpc->mpc_ops->mpo_check_vnode_exec =
792 mpe->mpe_function;
793 break;
794 case MAC_CHECK_VNODE_GETACL:
795 mpc->mpc_ops->mpo_check_vnode_getacl =
796 mpe->mpe_function;
797 break;
798 case MAC_CHECK_VNODE_GETEXTATTR:
799 mpc->mpc_ops->mpo_check_vnode_getextattr =
800 mpe->mpe_function;
801 break;
802 case MAC_CHECK_VNODE_LOOKUP:
803 mpc->mpc_ops->mpo_check_vnode_lookup =
804 mpe->mpe_function;
805 break;
806 case MAC_CHECK_VNODE_MMAP_PERMS:
807 mpc->mpc_ops->mpo_check_vnode_mmap_perms =
808 mpe->mpe_function;
809 break;
810 case MAC_CHECK_VNODE_OPEN:
811 mpc->mpc_ops->mpo_check_vnode_open =
812 mpe->mpe_function;
813 break;
814 case MAC_CHECK_VNODE_POLL:
815 mpc->mpc_ops->mpo_check_vnode_poll =
816 mpe->mpe_function;
817 break;
818 case MAC_CHECK_VNODE_READ:
819 mpc->mpc_ops->mpo_check_vnode_read =
820 mpe->mpe_function;
821 break;
822 case MAC_CHECK_VNODE_READDIR:
823 mpc->mpc_ops->mpo_check_vnode_readdir =
824 mpe->mpe_function;
825 break;
826 case MAC_CHECK_VNODE_READLINK:
827 mpc->mpc_ops->mpo_check_vnode_readlink =
828 mpe->mpe_function;
829 break;
830 case MAC_CHECK_VNODE_RELABEL:
831 mpc->mpc_ops->mpo_check_vnode_relabel =
832 mpe->mpe_function;
833 break;
834 case MAC_CHECK_VNODE_RENAME_FROM:
835 mpc->mpc_ops->mpo_check_vnode_rename_from =
836 mpe->mpe_function;
837 break;
838 case MAC_CHECK_VNODE_RENAME_TO:
839 mpc->mpc_ops->mpo_check_vnode_rename_to =
840 mpe->mpe_function;
841 break;
842 case MAC_CHECK_VNODE_REVOKE:
843 mpc->mpc_ops->mpo_check_vnode_revoke =
844 mpe->mpe_function;
845 break;
846 case MAC_CHECK_VNODE_SETACL:
847 mpc->mpc_ops->mpo_check_vnode_setacl =
848 mpe->mpe_function;
849 break;
850 case MAC_CHECK_VNODE_SETEXTATTR:
851 mpc->mpc_ops->mpo_check_vnode_setextattr =
852 mpe->mpe_function;
853 break;
854 case MAC_CHECK_VNODE_SETFLAGS:
855 mpc->mpc_ops->mpo_check_vnode_setflags =
856 mpe->mpe_function;
857 break;
858 case MAC_CHECK_VNODE_SETMODE:
859 mpc->mpc_ops->mpo_check_vnode_setmode =
860 mpe->mpe_function;
861 break;
862 case MAC_CHECK_VNODE_SETOWNER:
863 mpc->mpc_ops->mpo_check_vnode_setowner =
864 mpe->mpe_function;
865 break;
866 case MAC_CHECK_VNODE_SETUTIMES:
867 mpc->mpc_ops->mpo_check_vnode_setutimes =
868 mpe->mpe_function;
869 break;
870 case MAC_CHECK_VNODE_STAT:
871 mpc->mpc_ops->mpo_check_vnode_stat =
872 mpe->mpe_function;
873 break;
874 case MAC_CHECK_VNODE_WRITE:
875 mpc->mpc_ops->mpo_check_vnode_write =
876 mpe->mpe_function;
877 break;
878/*
879 default:
880 printf("MAC policy `%s': unknown operation %d\n",
881 mpc->mpc_name, mpe->mpe_constant);
882 return (EINVAL);
883*/
884 }
885 }
886 MAC_POLICY_LIST_LOCK();
887 if (mac_policy_list_busy > 0) {
888 MAC_POLICY_LIST_UNLOCK();
889 FREE(mpc->mpc_ops, M_MACOPVEC);
890 mpc->mpc_ops = NULL;
891 return (EBUSY);
892 }
893 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
894 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
895 MAC_POLICY_LIST_UNLOCK();
896 FREE(mpc->mpc_ops, M_MACOPVEC);
897 mpc->mpc_ops = NULL;
898 return (EEXIST);
899 }
900 }
901 if (mpc->mpc_field_off != NULL) {
902 slot = ffs(mac_policy_offsets_free);
903 if (slot == 0) {
904 MAC_POLICY_LIST_UNLOCK();
905 FREE(mpc->mpc_ops, M_MACOPVEC);
906 mpc->mpc_ops = NULL;
907 return (ENOMEM);
908 }
909 slot--;
910 mac_policy_offsets_free &= ~(1 << slot);
911 *mpc->mpc_field_off = slot;
912 }
913 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
914 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
915
916 /* Per-policy initialization. */
917 if (mpc->mpc_ops->mpo_init != NULL)
918 (*(mpc->mpc_ops->mpo_init))(mpc);
919 MAC_POLICY_LIST_UNLOCK();
920
921 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
922 mpc->mpc_name);
923
924 return (0);
925}
926
927static int
928mac_policy_unregister(struct mac_policy_conf *mpc)
929{
930
931 /*
932 * If we fail the load, we may get a request to unload. Check
933 * to see if we did the run-time registration, and if not,
934 * silently succeed.
935 */
936 MAC_POLICY_LIST_LOCK();
937 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
938 MAC_POLICY_LIST_UNLOCK();
939 return (0);
940 }
941#if 0
942 /*
943 * Don't allow unloading modules with private data.
944 */
945 if (mpc->mpc_field_off != NULL) {
946 MAC_POLICY_LIST_UNLOCK();
947 return (EBUSY);
948 }
949#endif
950 /*
951 * Only allow the unload to proceed if the module is unloadable
952 * by its own definition.
953 */
954 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
955 MAC_POLICY_LIST_UNLOCK();
956 return (EBUSY);
957 }
958 /*
959 * Right now, we EBUSY if the list is in use. In the future,
960 * for reliability reasons, we might want to sleep and wakeup
961 * later to try again.
962 */
963 if (mac_policy_list_busy > 0) {
964 MAC_POLICY_LIST_UNLOCK();
965 return (EBUSY);
966 }
967 if (mpc->mpc_ops->mpo_destroy != NULL)
968 (*(mpc->mpc_ops->mpo_destroy))(mpc);
969
970 LIST_REMOVE(mpc, mpc_list);
971 MAC_POLICY_LIST_UNLOCK();
972
973 FREE(mpc->mpc_ops, M_MACOPVEC);
974 mpc->mpc_ops = NULL;
975
976 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
977 mpc->mpc_name);
978
979 return (0);
980}
981
982/*
983 * Define an error value precedence, and given two arguments, selects the
984 * value with the higher precedence.
985 */
986static int
987error_select(int error1, int error2)
988{
989
990 /* Certain decision-making errors take top priority. */
991 if (error1 == EDEADLK || error2 == EDEADLK)
992 return (EDEADLK);
993
994 /* Invalid arguments should be reported where possible. */
995 if (error1 == EINVAL || error2 == EINVAL)
996 return (EINVAL);
997
998 /* Precedence goes to "visibility", with both process and file. */
999 if (error1 == ESRCH || error2 == ESRCH)
1000 return (ESRCH);
1001
1002 if (error1 == ENOENT || error2 == ENOENT)
1003 return (ENOENT);
1004
1005 /* Precedence goes to DAC/MAC protections. */
1006 if (error1 == EACCES || error2 == EACCES)
1007 return (EACCES);
1008
1009 /* Precedence goes to privilege. */
1010 if (error1 == EPERM || error2 == EPERM)
1011 return (EPERM);
1012
1013 /* Precedence goes to error over success; otherwise, arbitrary. */
1014 if (error1 != 0)
1015 return (error1);
1016 return (error2);
1017}
1018
1019static void
1020mac_init_label(struct label *label)
1021{
1022
1023 bzero(label, sizeof(*label));
1024 label->l_flags = MAC_FLAG_INITIALIZED;
1025}
1026
1027static void
1028mac_destroy_label(struct label *label)
1029{
1030
1031 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1032 ("destroying uninitialized label"));
1033
1034 bzero(label, sizeof(*label));
1035 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1036}
1037
1038static void
1039mac_init_structmac(struct mac *mac)
1040{
1041
1042 bzero(mac, sizeof(*mac));
1043 mac->m_macflags = MAC_FLAG_INITIALIZED;
1044}
1045
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 =
668 mpe->mpe_function;
669 break;
670 case MAC_CREATE_PROC1:
671 mpc->mpc_ops->mpo_create_proc1 =
672 mpe->mpe_function;
673 break;
674 case MAC_RELABEL_CRED:
675 mpc->mpc_ops->mpo_relabel_cred =
676 mpe->mpe_function;
677 break;
678 case MAC_THREAD_USERRET:
679 mpc->mpc_ops->mpo_thread_userret =
680 mpe->mpe_function;
681 break;
682 case MAC_CHECK_BPFDESC_RECEIVE:
683 mpc->mpc_ops->mpo_check_bpfdesc_receive =
684 mpe->mpe_function;
685 break;
686 case MAC_CHECK_CRED_RELABEL:
687 mpc->mpc_ops->mpo_check_cred_relabel =
688 mpe->mpe_function;
689 break;
690 case MAC_CHECK_CRED_VISIBLE:
691 mpc->mpc_ops->mpo_check_cred_visible =
692 mpe->mpe_function;
693 break;
694 case MAC_CHECK_IFNET_RELABEL:
695 mpc->mpc_ops->mpo_check_ifnet_relabel =
696 mpe->mpe_function;
697 break;
698 case MAC_CHECK_IFNET_TRANSMIT:
699 mpc->mpc_ops->mpo_check_ifnet_transmit =
700 mpe->mpe_function;
701 break;
702 case MAC_CHECK_MOUNT_STAT:
703 mpc->mpc_ops->mpo_check_mount_stat =
704 mpe->mpe_function;
705 break;
706 case MAC_CHECK_PIPE_IOCTL:
707 mpc->mpc_ops->mpo_check_pipe_ioctl =
708 mpe->mpe_function;
709 break;
710 case MAC_CHECK_PIPE_POLL:
711 mpc->mpc_ops->mpo_check_pipe_poll =
712 mpe->mpe_function;
713 break;
714 case MAC_CHECK_PIPE_READ:
715 mpc->mpc_ops->mpo_check_pipe_read =
716 mpe->mpe_function;
717 break;
718 case MAC_CHECK_PIPE_RELABEL:
719 mpc->mpc_ops->mpo_check_pipe_relabel =
720 mpe->mpe_function;
721 break;
722 case MAC_CHECK_PIPE_STAT:
723 mpc->mpc_ops->mpo_check_pipe_stat =
724 mpe->mpe_function;
725 break;
726 case MAC_CHECK_PIPE_WRITE:
727 mpc->mpc_ops->mpo_check_pipe_write =
728 mpe->mpe_function;
729 break;
730 case MAC_CHECK_PROC_DEBUG:
731 mpc->mpc_ops->mpo_check_proc_debug =
732 mpe->mpe_function;
733 break;
734 case MAC_CHECK_PROC_SCHED:
735 mpc->mpc_ops->mpo_check_proc_sched =
736 mpe->mpe_function;
737 break;
738 case MAC_CHECK_PROC_SIGNAL:
739 mpc->mpc_ops->mpo_check_proc_signal =
740 mpe->mpe_function;
741 break;
742 case MAC_CHECK_SOCKET_BIND:
743 mpc->mpc_ops->mpo_check_socket_bind =
744 mpe->mpe_function;
745 break;
746 case MAC_CHECK_SOCKET_CONNECT:
747 mpc->mpc_ops->mpo_check_socket_connect =
748 mpe->mpe_function;
749 break;
750 case MAC_CHECK_SOCKET_DELIVER:
751 mpc->mpc_ops->mpo_check_socket_deliver =
752 mpe->mpe_function;
753 break;
754 case MAC_CHECK_SOCKET_LISTEN:
755 mpc->mpc_ops->mpo_check_socket_listen =
756 mpe->mpe_function;
757 break;
758 case MAC_CHECK_SOCKET_RELABEL:
759 mpc->mpc_ops->mpo_check_socket_relabel =
760 mpe->mpe_function;
761 break;
762 case MAC_CHECK_SOCKET_VISIBLE:
763 mpc->mpc_ops->mpo_check_socket_visible =
764 mpe->mpe_function;
765 break;
766 case MAC_CHECK_VNODE_ACCESS:
767 mpc->mpc_ops->mpo_check_vnode_access =
768 mpe->mpe_function;
769 break;
770 case MAC_CHECK_VNODE_CHDIR:
771 mpc->mpc_ops->mpo_check_vnode_chdir =
772 mpe->mpe_function;
773 break;
774 case MAC_CHECK_VNODE_CHROOT:
775 mpc->mpc_ops->mpo_check_vnode_chroot =
776 mpe->mpe_function;
777 break;
778 case MAC_CHECK_VNODE_CREATE:
779 mpc->mpc_ops->mpo_check_vnode_create =
780 mpe->mpe_function;
781 break;
782 case MAC_CHECK_VNODE_DELETE:
783 mpc->mpc_ops->mpo_check_vnode_delete =
784 mpe->mpe_function;
785 break;
786 case MAC_CHECK_VNODE_DELETEACL:
787 mpc->mpc_ops->mpo_check_vnode_deleteacl =
788 mpe->mpe_function;
789 break;
790 case MAC_CHECK_VNODE_EXEC:
791 mpc->mpc_ops->mpo_check_vnode_exec =
792 mpe->mpe_function;
793 break;
794 case MAC_CHECK_VNODE_GETACL:
795 mpc->mpc_ops->mpo_check_vnode_getacl =
796 mpe->mpe_function;
797 break;
798 case MAC_CHECK_VNODE_GETEXTATTR:
799 mpc->mpc_ops->mpo_check_vnode_getextattr =
800 mpe->mpe_function;
801 break;
802 case MAC_CHECK_VNODE_LOOKUP:
803 mpc->mpc_ops->mpo_check_vnode_lookup =
804 mpe->mpe_function;
805 break;
806 case MAC_CHECK_VNODE_MMAP_PERMS:
807 mpc->mpc_ops->mpo_check_vnode_mmap_perms =
808 mpe->mpe_function;
809 break;
810 case MAC_CHECK_VNODE_OPEN:
811 mpc->mpc_ops->mpo_check_vnode_open =
812 mpe->mpe_function;
813 break;
814 case MAC_CHECK_VNODE_POLL:
815 mpc->mpc_ops->mpo_check_vnode_poll =
816 mpe->mpe_function;
817 break;
818 case MAC_CHECK_VNODE_READ:
819 mpc->mpc_ops->mpo_check_vnode_read =
820 mpe->mpe_function;
821 break;
822 case MAC_CHECK_VNODE_READDIR:
823 mpc->mpc_ops->mpo_check_vnode_readdir =
824 mpe->mpe_function;
825 break;
826 case MAC_CHECK_VNODE_READLINK:
827 mpc->mpc_ops->mpo_check_vnode_readlink =
828 mpe->mpe_function;
829 break;
830 case MAC_CHECK_VNODE_RELABEL:
831 mpc->mpc_ops->mpo_check_vnode_relabel =
832 mpe->mpe_function;
833 break;
834 case MAC_CHECK_VNODE_RENAME_FROM:
835 mpc->mpc_ops->mpo_check_vnode_rename_from =
836 mpe->mpe_function;
837 break;
838 case MAC_CHECK_VNODE_RENAME_TO:
839 mpc->mpc_ops->mpo_check_vnode_rename_to =
840 mpe->mpe_function;
841 break;
842 case MAC_CHECK_VNODE_REVOKE:
843 mpc->mpc_ops->mpo_check_vnode_revoke =
844 mpe->mpe_function;
845 break;
846 case MAC_CHECK_VNODE_SETACL:
847 mpc->mpc_ops->mpo_check_vnode_setacl =
848 mpe->mpe_function;
849 break;
850 case MAC_CHECK_VNODE_SETEXTATTR:
851 mpc->mpc_ops->mpo_check_vnode_setextattr =
852 mpe->mpe_function;
853 break;
854 case MAC_CHECK_VNODE_SETFLAGS:
855 mpc->mpc_ops->mpo_check_vnode_setflags =
856 mpe->mpe_function;
857 break;
858 case MAC_CHECK_VNODE_SETMODE:
859 mpc->mpc_ops->mpo_check_vnode_setmode =
860 mpe->mpe_function;
861 break;
862 case MAC_CHECK_VNODE_SETOWNER:
863 mpc->mpc_ops->mpo_check_vnode_setowner =
864 mpe->mpe_function;
865 break;
866 case MAC_CHECK_VNODE_SETUTIMES:
867 mpc->mpc_ops->mpo_check_vnode_setutimes =
868 mpe->mpe_function;
869 break;
870 case MAC_CHECK_VNODE_STAT:
871 mpc->mpc_ops->mpo_check_vnode_stat =
872 mpe->mpe_function;
873 break;
874 case MAC_CHECK_VNODE_WRITE:
875 mpc->mpc_ops->mpo_check_vnode_write =
876 mpe->mpe_function;
877 break;
878/*
879 default:
880 printf("MAC policy `%s': unknown operation %d\n",
881 mpc->mpc_name, mpe->mpe_constant);
882 return (EINVAL);
883*/
884 }
885 }
886 MAC_POLICY_LIST_LOCK();
887 if (mac_policy_list_busy > 0) {
888 MAC_POLICY_LIST_UNLOCK();
889 FREE(mpc->mpc_ops, M_MACOPVEC);
890 mpc->mpc_ops = NULL;
891 return (EBUSY);
892 }
893 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
894 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
895 MAC_POLICY_LIST_UNLOCK();
896 FREE(mpc->mpc_ops, M_MACOPVEC);
897 mpc->mpc_ops = NULL;
898 return (EEXIST);
899 }
900 }
901 if (mpc->mpc_field_off != NULL) {
902 slot = ffs(mac_policy_offsets_free);
903 if (slot == 0) {
904 MAC_POLICY_LIST_UNLOCK();
905 FREE(mpc->mpc_ops, M_MACOPVEC);
906 mpc->mpc_ops = NULL;
907 return (ENOMEM);
908 }
909 slot--;
910 mac_policy_offsets_free &= ~(1 << slot);
911 *mpc->mpc_field_off = slot;
912 }
913 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
914 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
915
916 /* Per-policy initialization. */
917 if (mpc->mpc_ops->mpo_init != NULL)
918 (*(mpc->mpc_ops->mpo_init))(mpc);
919 MAC_POLICY_LIST_UNLOCK();
920
921 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
922 mpc->mpc_name);
923
924 return (0);
925}
926
927static int
928mac_policy_unregister(struct mac_policy_conf *mpc)
929{
930
931 /*
932 * If we fail the load, we may get a request to unload. Check
933 * to see if we did the run-time registration, and if not,
934 * silently succeed.
935 */
936 MAC_POLICY_LIST_LOCK();
937 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
938 MAC_POLICY_LIST_UNLOCK();
939 return (0);
940 }
941#if 0
942 /*
943 * Don't allow unloading modules with private data.
944 */
945 if (mpc->mpc_field_off != NULL) {
946 MAC_POLICY_LIST_UNLOCK();
947 return (EBUSY);
948 }
949#endif
950 /*
951 * Only allow the unload to proceed if the module is unloadable
952 * by its own definition.
953 */
954 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
955 MAC_POLICY_LIST_UNLOCK();
956 return (EBUSY);
957 }
958 /*
959 * Right now, we EBUSY if the list is in use. In the future,
960 * for reliability reasons, we might want to sleep and wakeup
961 * later to try again.
962 */
963 if (mac_policy_list_busy > 0) {
964 MAC_POLICY_LIST_UNLOCK();
965 return (EBUSY);
966 }
967 if (mpc->mpc_ops->mpo_destroy != NULL)
968 (*(mpc->mpc_ops->mpo_destroy))(mpc);
969
970 LIST_REMOVE(mpc, mpc_list);
971 MAC_POLICY_LIST_UNLOCK();
972
973 FREE(mpc->mpc_ops, M_MACOPVEC);
974 mpc->mpc_ops = NULL;
975
976 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
977 mpc->mpc_name);
978
979 return (0);
980}
981
982/*
983 * Define an error value precedence, and given two arguments, selects the
984 * value with the higher precedence.
985 */
986static int
987error_select(int error1, int error2)
988{
989
990 /* Certain decision-making errors take top priority. */
991 if (error1 == EDEADLK || error2 == EDEADLK)
992 return (EDEADLK);
993
994 /* Invalid arguments should be reported where possible. */
995 if (error1 == EINVAL || error2 == EINVAL)
996 return (EINVAL);
997
998 /* Precedence goes to "visibility", with both process and file. */
999 if (error1 == ESRCH || error2 == ESRCH)
1000 return (ESRCH);
1001
1002 if (error1 == ENOENT || error2 == ENOENT)
1003 return (ENOENT);
1004
1005 /* Precedence goes to DAC/MAC protections. */
1006 if (error1 == EACCES || error2 == EACCES)
1007 return (EACCES);
1008
1009 /* Precedence goes to privilege. */
1010 if (error1 == EPERM || error2 == EPERM)
1011 return (EPERM);
1012
1013 /* Precedence goes to error over success; otherwise, arbitrary. */
1014 if (error1 != 0)
1015 return (error1);
1016 return (error2);
1017}
1018
1019static void
1020mac_init_label(struct label *label)
1021{
1022
1023 bzero(label, sizeof(*label));
1024 label->l_flags = MAC_FLAG_INITIALIZED;
1025}
1026
1027static void
1028mac_destroy_label(struct label *label)
1029{
1030
1031 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1032 ("destroying uninitialized label"));
1033
1034 bzero(label, sizeof(*label));
1035 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1036}
1037
1038static void
1039mac_init_structmac(struct mac *mac)
1040{
1041
1042 bzero(mac, sizeof(*mac));
1043 mac->m_macflags = MAC_FLAG_INITIALIZED;
1044}
1045
1046int
1047mac_init_mbuf(struct mbuf *m, int flag)
1048{
1049 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1050
1051 mac_init_label(&m->m_pkthdr.label);
1052
1053 MAC_PERFORM(init_mbuf_label, &m->m_pkthdr.label, flag);
1054#ifdef MAC_DEBUG
1055 atomic_add_int(&nmacmbufs, 1);
1056#endif
1057 return (0);
1058}
1059
1060void
1046void
1061mac_destroy_mbuf(struct mbuf *m)
1047mac_init_bpfdesc(struct bpf_d *bpf_d)
1062{
1063
1048{
1049
1064 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1065 mac_destroy_label(&m->m_pkthdr.label);
1050 mac_init_label(&bpf_d->bd_label);
1051 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1066#ifdef MAC_DEBUG
1052#ifdef MAC_DEBUG
1067 atomic_subtract_int(&nmacmbufs, 1);
1053 atomic_add_int(&nmacbpfdescs, 1);
1068#endif
1069}
1070
1071void
1072mac_init_cred(struct ucred *cr)
1073{
1074
1075 mac_init_label(&cr->cr_label);
1076 MAC_PERFORM(init_cred_label, &cr->cr_label);
1077#ifdef MAC_DEBUG
1078 atomic_add_int(&nmaccreds, 1);
1079#endif
1080}
1081
1082void
1054#endif
1055}
1056
1057void
1058mac_init_cred(struct ucred *cr)
1059{
1060
1061 mac_init_label(&cr->cr_label);
1062 MAC_PERFORM(init_cred_label, &cr->cr_label);
1063#ifdef MAC_DEBUG
1064 atomic_add_int(&nmaccreds, 1);
1065#endif
1066}
1067
1068void
1083mac_destroy_cred(struct ucred *cr)
1069mac_init_devfsdirent(struct devfs_dirent *de)
1084{
1085
1070{
1071
1086 MAC_PERFORM(destroy_cred_label, &cr->cr_label);
1087 mac_destroy_label(&cr->cr_label);
1072 mac_init_label(&de->de_label);
1073 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1088#ifdef MAC_DEBUG
1074#ifdef MAC_DEBUG
1089 atomic_subtract_int(&nmaccreds, 1);
1075 atomic_add_int(&nmacdevfsdirents, 1);
1090#endif
1091}
1092
1093void
1094mac_init_ifnet(struct ifnet *ifp)
1095{
1096
1097 mac_init_label(&ifp->if_label);
1098 MAC_PERFORM(init_ifnet_label, &ifp->if_label);
1099#ifdef MAC_DEBUG
1100 atomic_add_int(&nmacifnets, 1);
1101#endif
1102}
1103
1104void
1076#endif
1077}
1078
1079void
1080mac_init_ifnet(struct ifnet *ifp)
1081{
1082
1083 mac_init_label(&ifp->if_label);
1084 MAC_PERFORM(init_ifnet_label, &ifp->if_label);
1085#ifdef MAC_DEBUG
1086 atomic_add_int(&nmacifnets, 1);
1087#endif
1088}
1089
1090void
1105mac_destroy_ifnet(struct ifnet *ifp)
1091mac_init_ipq(struct ipq *ipq)
1106{
1107
1092{
1093
1108 MAC_PERFORM(destroy_ifnet_label, &ifp->if_label);
1109 mac_destroy_label(&ifp->if_label);
1094 mac_init_label(&ipq->ipq_label);
1095 MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1110#ifdef MAC_DEBUG
1096#ifdef MAC_DEBUG
1111 atomic_subtract_int(&nmacifnets, 1);
1097 atomic_add_int(&nmacipqs, 1);
1112#endif
1113}
1114
1098#endif
1099}
1100
1101int
1102mac_init_mbuf(struct mbuf *m, int flag)
1103{
1104 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1105
1106 mac_init_label(&m->m_pkthdr.label);
1107
1108 MAC_PERFORM(init_mbuf_label, &m->m_pkthdr.label, flag);
1109#ifdef MAC_DEBUG
1110 atomic_add_int(&nmacmbufs, 1);
1111#endif
1112 return (0);
1113}
1114
1115void
1115void
1116mac_init_ipq(struct ipq *ipq)
1116mac_init_mount(struct mount *mp)
1117{
1118
1117{
1118
1119 mac_init_label(&ipq->ipq_label);
1120 MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1119 mac_init_label(&mp->mnt_mntlabel);
1120 mac_init_label(&mp->mnt_fslabel);
1121 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1122 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1121#ifdef MAC_DEBUG
1123#ifdef MAC_DEBUG
1122 atomic_add_int(&nmacipqs, 1);
1124 atomic_add_int(&nmacmounts, 1);
1123#endif
1124}
1125
1126void
1125#endif
1126}
1127
1128void
1127mac_destroy_ipq(struct ipq *ipq)
1129mac_init_pipe(struct pipe *pipe)
1128{
1130{
1131 struct label *label;
1129
1132
1130 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1131 mac_destroy_label(&ipq->ipq_label);
1133 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1134 mac_init_label(label);
1135 pipe->pipe_label = label;
1136 pipe->pipe_peer->pipe_label = label;
1137 MAC_PERFORM(init_pipe_label, pipe->pipe_label);
1132#ifdef MAC_DEBUG
1138#ifdef MAC_DEBUG
1133 atomic_subtract_int(&nmacipqs, 1);
1139 atomic_add_int(&nmacpipes, 1);
1134#endif
1135}
1136
1137void
1138mac_init_socket(struct socket *socket)
1139{
1140
1141 mac_init_label(&socket->so_label);
1142 mac_init_label(&socket->so_peerlabel);
1143 MAC_PERFORM(init_socket_label, &socket->so_label);
1144 MAC_PERFORM(init_socket_peer_label, &socket->so_peerlabel);
1145#ifdef MAC_DEBUG
1146 atomic_add_int(&nmacsockets, 1);
1147#endif
1148}
1149
1140#endif
1141}
1142
1143void
1144mac_init_socket(struct socket *socket)
1145{
1146
1147 mac_init_label(&socket->so_label);
1148 mac_init_label(&socket->so_peerlabel);
1149 MAC_PERFORM(init_socket_label, &socket->so_label);
1150 MAC_PERFORM(init_socket_peer_label, &socket->so_peerlabel);
1151#ifdef MAC_DEBUG
1152 atomic_add_int(&nmacsockets, 1);
1153#endif
1154}
1155
1150void
1151mac_destroy_socket(struct socket *socket)
1156static void
1157mac_init_temp(struct label *label)
1152{
1153
1158{
1159
1154 MAC_PERFORM(destroy_socket_label, &socket->so_label);
1155 MAC_PERFORM(destroy_socket_peer_label, &socket->so_peerlabel);
1156 mac_destroy_label(&socket->so_label);
1157 mac_destroy_label(&socket->so_peerlabel);
1160 mac_init_label(label);
1161 MAC_PERFORM(init_temp_label, label);
1158#ifdef MAC_DEBUG
1162#ifdef MAC_DEBUG
1159 atomic_subtract_int(&nmacsockets, 1);
1163 atomic_add_int(&nmactemp, 1);
1160#endif
1161}
1162
1163void
1164#endif
1165}
1166
1167void
1164mac_init_pipe(struct pipe *pipe)
1168mac_init_vnode(struct vnode *vp)
1165{
1169{
1166 struct label *label;
1167
1170
1168 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1169 mac_init_label(label);
1170 pipe->pipe_label = label;
1171 pipe->pipe_peer->pipe_label = label;
1172 MAC_PERFORM(init_pipe_label, pipe->pipe_label);
1171 mac_init_label(&vp->v_label);
1172 MAC_PERFORM(init_vnode_label, &vp->v_label);
1173#ifdef MAC_DEBUG
1173#ifdef MAC_DEBUG
1174 atomic_add_int(&nmacpipes, 1);
1174 atomic_add_int(&nmacvnodes, 1);
1175#endif
1176}
1177
1178void
1175#endif
1176}
1177
1178void
1179mac_destroy_pipe(struct pipe *pipe)
1179mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1180{
1181
1180{
1181
1182 MAC_PERFORM(destroy_pipe_label, pipe->pipe_label);
1183 mac_destroy_label(pipe->pipe_label);
1184 free(pipe->pipe_label, M_MACPIPELABEL);
1182 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1183 mac_destroy_label(&bpf_d->bd_label);
1185#ifdef MAC_DEBUG
1184#ifdef MAC_DEBUG
1186 atomic_subtract_int(&nmacpipes, 1);
1185 atomic_subtract_int(&nmacbpfdescs, 1);
1187#endif
1188}
1189
1190void
1186#endif
1187}
1188
1189void
1191mac_init_bpfdesc(struct bpf_d *bpf_d)
1190mac_destroy_cred(struct ucred *cr)
1192{
1193
1191{
1192
1194 mac_init_label(&bpf_d->bd_label);
1195 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1193 MAC_PERFORM(destroy_cred_label, &cr->cr_label);
1194 mac_destroy_label(&cr->cr_label);
1196#ifdef MAC_DEBUG
1195#ifdef MAC_DEBUG
1197 atomic_add_int(&nmacbpfdescs, 1);
1196 atomic_subtract_int(&nmaccreds, 1);
1198#endif
1199}
1200
1201void
1197#endif
1198}
1199
1200void
1202mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1201mac_destroy_devfsdirent(struct devfs_dirent *de)
1203{
1204
1202{
1203
1205 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1206 mac_destroy_label(&bpf_d->bd_label);
1204 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1205 mac_destroy_label(&de->de_label);
1207#ifdef MAC_DEBUG
1206#ifdef MAC_DEBUG
1208 atomic_subtract_int(&nmacbpfdescs, 1);
1207 atomic_subtract_int(&nmacdevfsdirents, 1);
1209#endif
1210}
1211
1212void
1208#endif
1209}
1210
1211void
1213mac_init_mount(struct mount *mp)
1212mac_destroy_ifnet(struct ifnet *ifp)
1214{
1215
1213{
1214
1216 mac_init_label(&mp->mnt_mntlabel);
1217 mac_init_label(&mp->mnt_fslabel);
1218 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1219 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1215 MAC_PERFORM(destroy_ifnet_label, &ifp->if_label);
1216 mac_destroy_label(&ifp->if_label);
1220#ifdef MAC_DEBUG
1217#ifdef MAC_DEBUG
1221 atomic_add_int(&nmacmounts, 1);
1218 atomic_subtract_int(&nmacifnets, 1);
1222#endif
1223}
1224
1225void
1219#endif
1220}
1221
1222void
1226mac_destroy_mount(struct mount *mp)
1223mac_destroy_ipq(struct ipq *ipq)
1227{
1228
1224{
1225
1229 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1230 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1231 mac_destroy_label(&mp->mnt_fslabel);
1232 mac_destroy_label(&mp->mnt_mntlabel);
1226 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1227 mac_destroy_label(&ipq->ipq_label);
1233#ifdef MAC_DEBUG
1228#ifdef MAC_DEBUG
1234 atomic_subtract_int(&nmacmounts, 1);
1229 atomic_subtract_int(&nmacipqs, 1);
1235#endif
1236}
1237
1230#endif
1231}
1232
1238static void
1239mac_init_temp(struct label *label)
1233void
1234mac_destroy_mbuf(struct mbuf *m)
1240{
1241
1235{
1236
1242 mac_init_label(label);
1243 MAC_PERFORM(init_temp_label, label);
1237 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1238 mac_destroy_label(&m->m_pkthdr.label);
1244#ifdef MAC_DEBUG
1239#ifdef MAC_DEBUG
1245 atomic_add_int(&nmactemp, 1);
1240 atomic_subtract_int(&nmacmbufs, 1);
1246#endif
1247}
1248
1241#endif
1242}
1243
1249static void
1250mac_destroy_temp(struct label *label)
1244void
1245mac_destroy_mount(struct mount *mp)
1251{
1252
1246{
1247
1253 MAC_PERFORM(destroy_temp_label, label);
1254 mac_destroy_label(label);
1248 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1249 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1250 mac_destroy_label(&mp->mnt_fslabel);
1251 mac_destroy_label(&mp->mnt_mntlabel);
1255#ifdef MAC_DEBUG
1252#ifdef MAC_DEBUG
1256 atomic_subtract_int(&nmactemp, 1);
1253 atomic_subtract_int(&nmacmounts, 1);
1257#endif
1258}
1259
1260void
1254#endif
1255}
1256
1257void
1261mac_init_vnode(struct vnode *vp)
1258mac_destroy_pipe(struct pipe *pipe)
1262{
1263
1259{
1260
1264 mac_init_label(&vp->v_label);
1265 MAC_PERFORM(init_vnode_label, &vp->v_label);
1261 MAC_PERFORM(destroy_pipe_label, pipe->pipe_label);
1262 mac_destroy_label(pipe->pipe_label);
1263 free(pipe->pipe_label, M_MACPIPELABEL);
1266#ifdef MAC_DEBUG
1264#ifdef MAC_DEBUG
1267 atomic_add_int(&nmacvnodes, 1);
1265 atomic_subtract_int(&nmacpipes, 1);
1268#endif
1269}
1270
1271void
1266#endif
1267}
1268
1269void
1272mac_destroy_vnode(struct vnode *vp)
1270mac_destroy_socket(struct socket *socket)
1273{
1274
1271{
1272
1275 MAC_PERFORM(destroy_vnode_label, &vp->v_label);
1276 mac_destroy_label(&vp->v_label);
1273 MAC_PERFORM(destroy_socket_label, &socket->so_label);
1274 MAC_PERFORM(destroy_socket_peer_label, &socket->so_peerlabel);
1275 mac_destroy_label(&socket->so_label);
1276 mac_destroy_label(&socket->so_peerlabel);
1277#ifdef MAC_DEBUG
1277#ifdef MAC_DEBUG
1278 atomic_subtract_int(&nmacvnodes, 1);
1278 atomic_subtract_int(&nmacsockets, 1);
1279#endif
1280}
1281
1279#endif
1280}
1281
1282void
1283mac_init_devfsdirent(struct devfs_dirent *de)
1282static void
1283mac_destroy_temp(struct label *label)
1284{
1285
1284{
1285
1286 mac_init_label(&de->de_label);
1287 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1286 MAC_PERFORM(destroy_temp_label, label);
1287 mac_destroy_label(label);
1288#ifdef MAC_DEBUG
1288#ifdef MAC_DEBUG
1289 atomic_add_int(&nmacdevfsdirents, 1);
1289 atomic_subtract_int(&nmactemp, 1);
1290#endif
1291}
1292
1293void
1290#endif
1291}
1292
1293void
1294mac_destroy_devfsdirent(struct devfs_dirent *de)
1294mac_destroy_vnode(struct vnode *vp)
1295{
1296
1295{
1296
1297 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1298 mac_destroy_label(&de->de_label);
1297 MAC_PERFORM(destroy_vnode_label, &vp->v_label);
1298 mac_destroy_label(&vp->v_label);
1299#ifdef MAC_DEBUG
1299#ifdef MAC_DEBUG
1300 atomic_subtract_int(&nmacdevfsdirents, 1);
1300 atomic_subtract_int(&nmacvnodes, 1);
1301#endif
1302}
1303
1304static int
1305mac_externalize(struct label *label, struct mac *mac)
1306{
1307 int error;
1308
1309 mac_init_structmac(mac);
1310 MAC_CHECK(externalize, label, mac);
1311
1312 return (error);
1313}
1314
1315static int
1316mac_internalize(struct label *label, struct mac *mac)
1317{
1318 int error;
1319
1320 mac_init_temp(label);
1321 MAC_CHECK(internalize, label, mac);
1322 if (error)
1323 mac_destroy_temp(label);
1324
1325 return (error);
1326}
1327
1328/*
1329 * Initialize MAC label for the first kernel process, from which other
1330 * kernel processes and threads are spawned.
1331 */
1332void
1333mac_create_proc0(struct ucred *cred)
1334{
1335
1336 MAC_PERFORM(create_proc0, cred);
1337}
1338
1339/*
1340 * Initialize MAC label for the first userland process, from which other
1341 * userland processes and threads are spawned.
1342 */
1343void
1344mac_create_proc1(struct ucred *cred)
1345{
1346
1347 MAC_PERFORM(create_proc1, cred);
1348}
1349
1350void
1351mac_thread_userret(struct thread *td)
1352{
1353
1354 MAC_PERFORM(thread_userret, td);
1355}
1356
1357/*
1358 * When a new process is created, its label must be initialized. Generally,
1359 * this involves inheritence from the parent process, modulo possible
1360 * deltas. This function allows that processing to take place.
1361 */
1362void
1363mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1364{
1365
1366 MAC_PERFORM(create_cred, parent_cred, child_cred);
1367}
1368
1369void
1370mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1371{
1372
1373 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1374}
1375
1376void
1377mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1378{
1379
1380 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1381}
1382
1383/*
1384 * Support callout for policies that manage their own externalization
1385 * using extended attributes.
1386 */
1387static int
1388mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1389{
1390 int error;
1391
1392 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1393 &mp->mnt_fslabel);
1394
1395 return (error);
1396}
1397
1398/*
1399 * Given an externalized mac label, internalize it and stamp it on a
1400 * vnode.
1401 */
1402static int
1403mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
1404{
1405 int error;
1406
1407 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1408
1409 return (error);
1410}
1411
1412/*
1413 * Call out to individual policies to update the label in a vnode from
1414 * the mountpoint.
1415 */
1416void
1417mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1418{
1419
1420 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1421 &mp->mnt_fslabel);
1422
1423 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1424 if (mac_cache_fslabel_in_vnode)
1425 vp->v_vflag |= VV_CACHEDLABEL;
1426}
1427
1428/*
1429 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1430 * to store label data. Can be referenced by filesystems supporting
1431 * extended attributes.
1432 */
1433int
1434vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1435{
1436 struct vnode *vp = ap->a_vp;
1437 struct mac extmac;
1438 int buflen, error;
1439
1440 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1441
1442 /*
1443 * Call out to external policies first. Order doesn't really
1444 * matter, as long as failure of one assures failure of all.
1445 */
1446 error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1447 if (error)
1448 return (error);
1449
1450 buflen = sizeof(extmac);
1451 error = vn_extattr_get(vp, IO_NODELOCKED,
1452 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1453 (char *)&extmac, curthread);
1454 switch (error) {
1455 case 0:
1456 /* Got it */
1457 break;
1458
1459 case ENOATTR:
1460 /*
1461 * Use the label from the mount point.
1462 */
1463 mac_update_vnode_from_mount(vp, vp->v_mount);
1464 return (0);
1465
1466 case EOPNOTSUPP:
1467 default:
1468 /* Fail horribly. */
1469 return (error);
1470 }
1471
1472 if (buflen != sizeof(extmac))
1473 error = EPERM; /* Fail very closed. */
1474 if (error == 0)
1475 error = mac_update_vnode_from_externalized(vp, &extmac);
1476 if (error == 0)
1477 vp->v_vflag |= VV_CACHEDLABEL;
1478 else {
1479 struct vattr va;
1480
1481 printf("Corrupted label on %s",
1482 vp->v_mount->mnt_stat.f_mntonname);
1483 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1484 printf(" inum %ld", va.va_fileid);
1485#ifdef MAC_DEBUG
1486 if (mac_debug_label_fallback) {
1487 printf(", falling back.\n");
1488 mac_update_vnode_from_mount(vp, vp->v_mount);
1489 error = 0;
1490 } else {
1491#endif
1492 printf(".\n");
1493 error = EPERM;
1494#ifdef MAC_DEBUG
1495 }
1496#endif
1497 }
1498
1499 return (error);
1500}
1501
1502/*
1503 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
1504 * the labeling activity outselves. Filesystems should be careful not
1505 * to change their minds regarding whether they support vop_refreshlabel()
1506 * for a vnode or not. Don't cache the vnode here, allow the file
1507 * system code to determine if it's safe to cache. If we update from
1508 * the mount, don't cache since a change to the mount label should affect
1509 * all vnodes.
1510 */
1511static int
1512vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1513{
1514 int error;
1515
1516 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1517
1518 if (vp->v_mount == NULL) {
1519/*
1520 Eventually, we probably want to special-case refreshing
1521 of deadfs vnodes, and if there's a lock-free race somewhere,
1522 that case might be handled here.
1523
1524 mac_update_vnode_deadfs(vp);
1525 return (0);
1526 */
1527 /* printf("vn_refreshlabel: null v_mount\n"); */
1528 if (vp->v_type != VNON)
1529 printf(
1530 "vn_refreshlabel: null v_mount with non-VNON\n");
1531 return (EBADF);
1532 }
1533
1534 if (vp->v_vflag & VV_CACHEDLABEL) {
1535 mac_vnode_label_cache_hits++;
1536 return (0);
1537 } else
1538 mac_vnode_label_cache_misses++;
1539
1540 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1541 mac_update_vnode_from_mount(vp, vp->v_mount);
1542 return (0);
1543 }
1544
1545 error = VOP_REFRESHLABEL(vp, cred, curthread);
1546 switch (error) {
1547 case EOPNOTSUPP:
1548 /*
1549 * If labels are not supported on this vnode, fall back to
1550 * the label in the mount and propagate it to the vnode.
1551 * There should probably be some sort of policy/flag/decision
1552 * about doing this.
1553 */
1554 mac_update_vnode_from_mount(vp, vp->v_mount);
1555 error = 0;
1556 default:
1557 return (error);
1558 }
1559}
1560
1561/*
1562 * Helper function for file systems using the vop_std*_ea() calls. This
1563 * function must be called after EA service is available for the vnode,
1564 * but before it's hooked up to the namespace so that the node persists
1565 * if there's a crash, or before it can be accessed. On successful
1566 * commit of the label to disk (etc), do cache the label.
1567 */
1568int
1569vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1570{
1571 struct mac extmac;
1572 int error;
1573
1574 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1575 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1576 mac_update_vnode_from_mount(tvp, tvp->v_mount);
1577 } else {
1578 error = vn_refreshlabel(dvp, cred);
1579 if (error)
1580 return (error);
1581
1582 /*
1583 * Stick the label in the vnode. Then try to write to
1584 * disk. If we fail, return a failure to abort the
1585 * create operation. Really, this failure shouldn't
1586 * happen except in fairly unusual circumstances (out
1587 * of disk, etc).
1588 */
1589 mac_create_vnode(cred, dvp, tvp);
1590
1591 error = mac_stdcreatevnode_ea(tvp);
1592 if (error)
1593 return (error);
1594
1595 /*
1596 * XXX: Eventually this will go away and all policies will
1597 * directly manage their extended attributes.
1598 */
1599 error = mac_externalize(&tvp->v_label, &extmac);
1600 if (error)
1601 return (error);
1602
1603 error = vn_extattr_set(tvp, IO_NODELOCKED,
1604 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1605 sizeof(extmac), (char *)&extmac, curthread);
1606 if (error == 0)
1607 tvp->v_vflag |= VV_CACHEDLABEL;
1608 else {
1609#if 0
1610 /*
1611 * In theory, we could have fall-back behavior here.
1612 * It would probably be incorrect.
1613 */
1614#endif
1615 return (error);
1616 }
1617 }
1618
1619 return (0);
1620}
1621
1622void
1623mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1624{
1625 int error;
1626
1627 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1628
1629 error = vn_refreshlabel(vp, old);
1630 if (error) {
1631 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
1632 error);
1633 printf("mac_execve_transition: using old vnode label\n");
1634 }
1635
1636 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1637}
1638
1639int
1640mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1641{
1642 int error, result;
1643
1644 error = vn_refreshlabel(vp, old);
1645 if (error)
1646 return (error);
1647
1648 result = 0;
1649 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1650
1651 return (result);
1652}
1653
1654int
1655mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
1656{
1657 int error;
1658
1659 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1660
1661 if (!mac_enforce_fs)
1662 return (0);
1663
1664 error = vn_refreshlabel(vp, cred);
1665 if (error)
1666 return (error);
1667
1668 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
1669 return (error);
1670}
1671
1672int
1673mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1674{
1675 int error;
1676
1677 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1678
1679 if (!mac_enforce_fs)
1680 return (0);
1681
1682 error = vn_refreshlabel(dvp, cred);
1683 if (error)
1684 return (error);
1685
1686 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1687 return (error);
1688}
1689
1690int
1691mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1692{
1693 int error;
1694
1695 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1696
1697 if (!mac_enforce_fs)
1698 return (0);
1699
1700 error = vn_refreshlabel(dvp, cred);
1701 if (error)
1702 return (error);
1703
1704 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1705 return (error);
1706}
1707
1708int
1709mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1710 struct componentname *cnp, struct vattr *vap)
1711{
1712 int error;
1713
1714 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1715
1716 if (!mac_enforce_fs)
1717 return (0);
1718
1719 error = vn_refreshlabel(dvp, cred);
1720 if (error)
1721 return (error);
1722
1723 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1724 return (error);
1725}
1726
1727int
1728mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1729 struct componentname *cnp)
1730{
1731 int error;
1732
1733 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1734 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1735
1736 if (!mac_enforce_fs)
1737 return (0);
1738
1739 error = vn_refreshlabel(dvp, cred);
1740 if (error)
1741 return (error);
1742 error = vn_refreshlabel(vp, cred);
1743 if (error)
1744 return (error);
1745
1746 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1747 &vp->v_label, cnp);
1748 return (error);
1749}
1750
1751int
1752mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1753 acl_type_t type)
1754{
1755 int error;
1756
1757 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1758
1759 if (!mac_enforce_fs)
1760 return (0);
1761
1762 error = vn_refreshlabel(vp, cred);
1763 if (error)
1764 return (error);
1765
1766 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1767 return (error);
1768}
1769
1770int
1771mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1772{
1773 int error;
1774
1775 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1776
1777 if (!mac_enforce_process && !mac_enforce_fs)
1778 return (0);
1779
1780 error = vn_refreshlabel(vp, cred);
1781 if (error)
1782 return (error);
1783 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1784
1785 return (error);
1786}
1787
1788int
1789mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1790{
1791 int error;
1792
1793 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1794
1795 if (!mac_enforce_fs)
1796 return (0);
1797
1798 error = vn_refreshlabel(vp, cred);
1799 if (error)
1800 return (error);
1801
1802 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1803 return (error);
1804}
1805
1806int
1807mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1808 int attrnamespace, const char *name, struct uio *uio)
1809{
1810 int error;
1811
1812 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1813
1814 if (!mac_enforce_fs)
1815 return (0);
1816
1817 error = vn_refreshlabel(vp, cred);
1818 if (error)
1819 return (error);
1820
1821 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1822 attrnamespace, name, uio);
1823 return (error);
1824}
1825
1826int
1827mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1828 struct componentname *cnp)
1829{
1830 int error;
1831
1832 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1833
1834 if (!mac_enforce_fs)
1835 return (0);
1836
1837 error = vn_refreshlabel(dvp, cred);
1838 if (error)
1839 return (error);
1840
1841 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1842 return (error);
1843}
1844
1845vm_prot_t
1846mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping)
1847{
1848 vm_prot_t result = VM_PROT_ALL;
1849
1850 if (!mac_enforce_vm)
1851 return (result);
1852
1853 /*
1854 * This should be some sort of MAC_BITWISE, maybe :)
1855 */
1856 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms");
1857 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label,
1858 newmapping);
1859 return (result);
1860}
1861
1862int
1863mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
1864{
1865 int error;
1866
1867 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1868
1869 if (!mac_enforce_fs)
1870 return (0);
1871
1872 error = vn_refreshlabel(vp, cred);
1873 if (error)
1874 return (error);
1875
1876 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1877 return (error);
1878}
1879
1880int
1881mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1882 struct vnode *vp)
1883{
1884 int error;
1885
1886 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1887
1888 if (!mac_enforce_fs)
1889 return (0);
1890
1891 error = vn_refreshlabel(vp, active_cred);
1892 if (error)
1893 return (error);
1894
1895 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1896 &vp->v_label);
1897
1898 return (error);
1899}
1900
1901int
1902mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1903 struct vnode *vp)
1904{
1905 int error;
1906
1907 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1908
1909 if (!mac_enforce_fs)
1910 return (0);
1911
1912 error = vn_refreshlabel(vp, active_cred);
1913 if (error)
1914 return (error);
1915
1916 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1917 &vp->v_label);
1918
1919 return (error);
1920}
1921
1922int
1923mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1924{
1925 int error;
1926
1927 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1928
1929 if (!mac_enforce_fs)
1930 return (0);
1931
1932 error = vn_refreshlabel(dvp, cred);
1933 if (error)
1934 return (error);
1935
1936 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1937 return (error);
1938}
1939
1940int
1941mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1942{
1943 int error;
1944
1945 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1946
1947 if (!mac_enforce_fs)
1948 return (0);
1949
1950 error = vn_refreshlabel(vp, cred);
1951 if (error)
1952 return (error);
1953
1954 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1955 return (error);
1956}
1957
1958static int
1959mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1960 struct label *newlabel)
1961{
1962 int error;
1963
1964 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1965
1966 error = vn_refreshlabel(vp, cred);
1967 if (error)
1968 return (error);
1969
1970 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1971
1972 return (error);
1973}
1974
1975int
1976mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1977 struct vnode *vp, struct componentname *cnp)
1978{
1979 int error;
1980
1981 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1982 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1983
1984 if (!mac_enforce_fs)
1985 return (0);
1986
1987 error = vn_refreshlabel(dvp, cred);
1988 if (error)
1989 return (error);
1990 error = vn_refreshlabel(vp, cred);
1991 if (error)
1992 return (error);
1993
1994 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1995 &vp->v_label, cnp);
1996 return (error);
1997}
1998
1999int
2000mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2001 struct vnode *vp, int samedir, struct componentname *cnp)
2002{
2003 int error;
2004
2005 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2006 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2007
2008 if (!mac_enforce_fs)
2009 return (0);
2010
2011 error = vn_refreshlabel(dvp, cred);
2012 if (error)
2013 return (error);
2014 if (vp != NULL) {
2015 error = vn_refreshlabel(vp, cred);
2016 if (error)
2017 return (error);
2018 }
2019 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2020 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2021 return (error);
2022}
2023
2024int
2025mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2026{
2027 int error;
2028
2029 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2030
2031 if (!mac_enforce_fs)
2032 return (0);
2033
2034 error = vn_refreshlabel(vp, cred);
2035 if (error)
2036 return (error);
2037
2038 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2039 return (error);
2040}
2041
2042int
2043mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2044 struct acl *acl)
2045{
2046 int error;
2047
2048 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2049
2050 if (!mac_enforce_fs)
2051 return (0);
2052
2053 error = vn_refreshlabel(vp, cred);
2054 if (error)
2055 return (error);
2056
2057 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2058 return (error);
2059}
2060
2061int
2062mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2063 int attrnamespace, const char *name, struct uio *uio)
2064{
2065 int error;
2066
2067 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2068
2069 if (!mac_enforce_fs)
2070 return (0);
2071
2072 error = vn_refreshlabel(vp, cred);
2073 if (error)
2074 return (error);
2075
2076 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2077 attrnamespace, name, uio);
2078 return (error);
2079}
2080
2081int
2082mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2083{
2084 int error;
2085
2086 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2087
2088 if (!mac_enforce_fs)
2089 return (0);
2090
2091 error = vn_refreshlabel(vp, cred);
2092 if (error)
2093 return (error);
2094
2095 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2096 return (error);
2097}
2098
2099int
2100mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2101{
2102 int error;
2103
2104 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2105
2106 if (!mac_enforce_fs)
2107 return (0);
2108
2109 error = vn_refreshlabel(vp, cred);
2110 if (error)
2111 return (error);
2112
2113 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2114 return (error);
2115}
2116
2117int
2118mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2119 gid_t gid)
2120{
2121 int error;
2122
2123 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2124
2125 if (!mac_enforce_fs)
2126 return (0);
2127
2128 error = vn_refreshlabel(vp, cred);
2129 if (error)
2130 return (error);
2131
2132 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2133 return (error);
2134}
2135
2136int
2137mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2138 struct timespec atime, struct timespec mtime)
2139{
2140 int error;
2141
2142 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2143
2144 if (!mac_enforce_fs)
2145 return (0);
2146
2147 error = vn_refreshlabel(vp, cred);
2148 if (error)
2149 return (error);
2150
2151 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2152 mtime);
2153 return (error);
2154}
2155
2156int
2157mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2158 struct vnode *vp)
2159{
2160 int error;
2161
2162 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2163
2164 if (!mac_enforce_fs)
2165 return (0);
2166
2167 error = vn_refreshlabel(vp, active_cred);
2168 if (error)
2169 return (error);
2170
2171 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2172 &vp->v_label);
2173 return (error);
2174}
2175
2176int
2177mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2178 struct vnode *vp)
2179{
2180 int error;
2181
2182 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2183
2184 if (!mac_enforce_fs)
2185 return (0);
2186
2187 error = vn_refreshlabel(vp, active_cred);
2188 if (error)
2189 return (error);
2190
2191 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2192 &vp->v_label);
2193
2194 return (error);
2195}
2196
2197/*
2198 * When relabeling a process, call out to the policies for the maximum
2199 * permission allowed for each object type we know about in its
2200 * memory space, and revoke access (in the least surprising ways we
2201 * know) when necessary. The process lock is not held here.
2202 */
2203static void
2204mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2205{
2206
2207 /* XXX freeze all other threads */
2208 mac_cred_mmapped_drop_perms_recurse(td, cred,
2209 &td->td_proc->p_vmspace->vm_map);
2210 /* XXX allow other threads to continue */
2211}
2212
2213static __inline const char *
2214prot2str(vm_prot_t prot)
2215{
2216
2217 switch (prot & VM_PROT_ALL) {
2218 case VM_PROT_READ:
2219 return ("r--");
2220 case VM_PROT_READ | VM_PROT_WRITE:
2221 return ("rw-");
2222 case VM_PROT_READ | VM_PROT_EXECUTE:
2223 return ("r-x");
2224 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2225 return ("rwx");
2226 case VM_PROT_WRITE:
2227 return ("-w-");
2228 case VM_PROT_EXECUTE:
2229 return ("--x");
2230 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2231 return ("-wx");
2232 default:
2233 return ("---");
2234 }
2235}
2236
2237static void
2238mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2239 struct vm_map *map)
2240{
2241 struct vm_map_entry *vme;
2242 vm_prot_t result, revokeperms;
2243 vm_object_t object;
2244 vm_ooffset_t offset;
2245 struct vnode *vp;
2246
2247 if (!mac_mmap_revocation)
2248 return;
2249
2250 vm_map_lock_read(map);
2251 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2252 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2253 mac_cred_mmapped_drop_perms_recurse(td, cred,
2254 vme->object.sub_map);
2255 continue;
2256 }
2257 /*
2258 * Skip over entries that obviously are not shared.
2259 */
2260 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2261 !vme->max_protection)
2262 continue;
2263 /*
2264 * Drill down to the deepest backing object.
2265 */
2266 offset = vme->offset;
2267 object = vme->object.vm_object;
2268 if (object == NULL)
2269 continue;
2270 while (object->backing_object != NULL) {
2271 object = object->backing_object;
2272 offset += object->backing_object_offset;
2273 }
2274 /*
2275 * At the moment, vm_maps and objects aren't considered
2276 * by the MAC system, so only things with backing by a
2277 * normal object (read: vnodes) are checked.
2278 */
2279 if (object->type != OBJT_VNODE)
2280 continue;
2281 vp = (struct vnode *)object->handle;
2282 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2283 result = mac_check_vnode_mmap_prot(cred, vp, 0);
2284 VOP_UNLOCK(vp, 0, td);
2285 /*
2286 * Find out what maximum protection we may be allowing
2287 * now but a policy needs to get removed.
2288 */
2289 revokeperms = vme->max_protection & ~result;
2290 if (!revokeperms)
2291 continue;
2292 printf("pid %ld: revoking %s perms from %#lx:%ld "
2293 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2294 prot2str(revokeperms), (u_long)vme->start,
2295 (long)(vme->end - vme->start),
2296 prot2str(vme->max_protection), prot2str(vme->protection));
2297 vm_map_lock_upgrade(map);
2298 /*
2299 * This is the really simple case: if a map has more
2300 * max_protection than is allowed, but it's not being
2301 * actually used (that is, the current protection is
2302 * still allowed), we can just wipe it out and do
2303 * nothing more.
2304 */
2305 if ((vme->protection & revokeperms) == 0) {
2306 vme->max_protection -= revokeperms;
2307 } else {
2308 if (revokeperms & VM_PROT_WRITE) {
2309 /*
2310 * In the more complicated case, flush out all
2311 * pending changes to the object then turn it
2312 * copy-on-write.
2313 */
2314 vm_object_reference(object);
2315 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2316 vm_object_page_clean(object,
2317 OFF_TO_IDX(offset),
2318 OFF_TO_IDX(offset + vme->end - vme->start +
2319 PAGE_MASK),
2320 OBJPC_SYNC);
2321 VOP_UNLOCK(vp, 0, td);
2322 vm_object_deallocate(object);
2323 /*
2324 * Why bother if there's no read permissions
2325 * anymore? For the rest, we need to leave
2326 * the write permissions on for COW, or
2327 * remove them entirely if configured to.
2328 */
2329 if (!mac_mmap_revocation_via_cow) {
2330 vme->max_protection &= ~VM_PROT_WRITE;
2331 vme->protection &= ~VM_PROT_WRITE;
2332 } if ((revokeperms & VM_PROT_READ) == 0)
2333 vme->eflags |= MAP_ENTRY_COW |
2334 MAP_ENTRY_NEEDS_COPY;
2335 }
2336 if (revokeperms & VM_PROT_EXECUTE) {
2337 vme->max_protection &= ~VM_PROT_EXECUTE;
2338 vme->protection &= ~VM_PROT_EXECUTE;
2339 }
2340 if (revokeperms & VM_PROT_READ) {
2341 vme->max_protection = 0;
2342 vme->protection = 0;
2343 }
2344 pmap_protect(map->pmap, vme->start, vme->end,
2345 vme->protection & ~revokeperms);
2346 vm_map_simplify_entry(map, vme);
2347 }
2348 vm_map_lock_downgrade(map);
2349 }
2350 vm_map_unlock_read(map);
2351}
2352
2353/*
2354 * When the subject's label changes, it may require revocation of privilege
2355 * to mapped objects. This can't be done on-the-fly later with a unified
2356 * buffer cache.
2357 */
2358static void
2359mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2360{
2361
2362 MAC_PERFORM(relabel_cred, cred, newlabel);
2363}
2364
2365void
2366mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2367{
2368
2369 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2370}
2371
2372void
2373mac_create_ifnet(struct ifnet *ifnet)
2374{
2375
2376 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2377}
2378
2379void
2380mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2381{
2382
2383 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2384}
2385
2386void
2387mac_create_socket(struct ucred *cred, struct socket *socket)
2388{
2389
2390 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2391}
2392
2393void
2394mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2395{
2396
2397 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2398}
2399
2400void
2401mac_create_socket_from_socket(struct socket *oldsocket,
2402 struct socket *newsocket)
2403{
2404
2405 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2406 newsocket, &newsocket->so_label);
2407}
2408
2409static void
2410mac_relabel_socket(struct ucred *cred, struct socket *socket,
2411 struct label *newlabel)
2412{
2413
2414 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2415}
2416
2417static void
2418mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2419{
2420
2421 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2422}
2423
2424void
2425mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2426{
2427
2428 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2429 socket, &socket->so_peerlabel);
2430}
2431
2432void
2433mac_set_socket_peer_from_socket(struct socket *oldsocket,
2434 struct socket *newsocket)
2435{
2436
2437 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2438 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2439}
2440
2441void
2442mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2443{
2444
2445 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2446 datagram, &datagram->m_pkthdr.label);
2447}
2448
2449void
2450mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2451{
2452
2453 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2454 fragment, &fragment->m_pkthdr.label);
2455}
2456
2457void
2458mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2459{
2460
2461 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2462 &ipq->ipq_label);
2463}
2464
2465void
2466mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2467{
2468
2469 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2470 newmbuf, &newmbuf->m_pkthdr.label);
2471}
2472
2473void
2474mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2475{
2476
2477 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2478 &mbuf->m_pkthdr.label);
2479}
2480
2481void
2482mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2483{
2484
2485 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2486 &mbuf->m_pkthdr.label);
2487}
2488
2489void
2490mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2491{
2492
2493 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2494 &mbuf->m_pkthdr.label);
2495}
2496
2497void
2498mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2499 struct mbuf *newmbuf)
2500{
2501
2502 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2503 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2504 &newmbuf->m_pkthdr.label);
2505}
2506
2507void
2508mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2509{
2510
2511 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2512 newmbuf, &newmbuf->m_pkthdr.label);
2513}
2514
2515int
2516mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2517{
2518 int result;
2519
2520 result = 1;
2521 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2522 ipq, &ipq->ipq_label);
2523
2524 return (result);
2525}
2526
2527void
2528mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2529{
2530
2531 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2532 &ipq->ipq_label);
2533}
2534
2535void
2536mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2537{
2538
2539 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2540 &mbuf->m_pkthdr.label);
2541}
2542
2543void
2544mac_create_mount(struct ucred *cred, struct mount *mp)
2545{
2546
2547 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2548 &mp->mnt_fslabel);
2549}
2550
2551void
2552mac_create_root_mount(struct ucred *cred, struct mount *mp)
2553{
2554
2555 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2556 &mp->mnt_fslabel);
2557}
2558
2559int
2560mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2561{
2562 int error;
2563
2564 if (!mac_enforce_network)
2565 return (0);
2566
2567 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2568 &ifnet->if_label);
2569
2570 return (error);
2571}
2572
2573static int
2574mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2575{
2576 int error;
2577
2578 MAC_CHECK(check_cred_relabel, cred, newlabel);
2579
2580 return (error);
2581}
2582
2583int
2584mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2585{
2586 int error;
2587
2588 if (!mac_enforce_process)
2589 return (0);
2590
2591 MAC_CHECK(check_cred_visible, u1, u2);
2592
2593 return (error);
2594}
2595
2596int
2597mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2598{
2599 int error;
2600
2601 if (!mac_enforce_network)
2602 return (0);
2603
2604 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2605 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2606 printf("%s%d: not initialized\n", ifnet->if_name,
2607 ifnet->if_unit);
2608
2609 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2610 &mbuf->m_pkthdr.label);
2611
2612 return (error);
2613}
2614
2615int
2616mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2617{
2618 int error;
2619
2620 if (!mac_enforce_fs)
2621 return (0);
2622
2623 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2624
2625 return (error);
2626}
2627
2628int
2629mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2630 void *data)
2631{
2632 int error;
2633
2634 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2635
2636 if (!mac_enforce_pipe)
2637 return (0);
2638
2639 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2640
2641 return (error);
2642}
2643
2644int
2645mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2646{
2647 int error;
2648
2649 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2650
2651 if (!mac_enforce_pipe)
2652 return (0);
2653
2654 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2655
2656 return (error);
2657}
2658
2659int
2660mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2661{
2662 int error;
2663
2664 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2665
2666 if (!mac_enforce_pipe)
2667 return (0);
2668
2669 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2670
2671 return (error);
2672}
2673
2674static int
2675mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2676 struct label *newlabel)
2677{
2678 int error;
2679
2680 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2681
2682 if (!mac_enforce_pipe)
2683 return (0);
2684
2685 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2686
2687 return (error);
2688}
2689
2690int
2691mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2692{
2693 int error;
2694
2695 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2696
2697 if (!mac_enforce_pipe)
2698 return (0);
2699
2700 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2701
2702 return (error);
2703}
2704
2705int
2706mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2707{
2708 int error;
2709
2710 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2711
2712 if (!mac_enforce_pipe)
2713 return (0);
2714
2715 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2716
2717 return (error);
2718}
2719
2720int
2721mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2722{
2723 int error;
2724
2725 PROC_LOCK_ASSERT(proc, MA_OWNED);
2726
2727 if (!mac_enforce_process)
2728 return (0);
2729
2730 MAC_CHECK(check_proc_debug, cred, proc);
2731
2732 return (error);
2733}
2734
2735int
2736mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2737{
2738 int error;
2739
2740 PROC_LOCK_ASSERT(proc, MA_OWNED);
2741
2742 if (!mac_enforce_process)
2743 return (0);
2744
2745 MAC_CHECK(check_proc_sched, cred, proc);
2746
2747 return (error);
2748}
2749
2750int
2751mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2752{
2753 int error;
2754
2755 PROC_LOCK_ASSERT(proc, MA_OWNED);
2756
2757 if (!mac_enforce_process)
2758 return (0);
2759
2760 MAC_CHECK(check_proc_signal, cred, proc, signum);
2761
2762 return (error);
2763}
2764
2765int
2766mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2767 struct sockaddr *sockaddr)
2768{
2769 int error;
2770
2771 if (!mac_enforce_socket)
2772 return (0);
2773
2774 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2775 sockaddr);
2776
2777 return (error);
2778}
2779
2780int
2781mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2782 struct sockaddr *sockaddr)
2783{
2784 int error;
2785
2786 if (!mac_enforce_socket)
2787 return (0);
2788
2789 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2790 sockaddr);
2791
2792 return (error);
2793}
2794
2795int
2796mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2797{
2798 int error;
2799
2800 if (!mac_enforce_socket)
2801 return (0);
2802
2803 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2804 &mbuf->m_pkthdr.label);
2805
2806 return (error);
2807}
2808
2809int
2810mac_check_socket_listen(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_listen, cred, socket, &socket->so_label);
2818 return (error);
2819}
2820
2821static int
2822mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2823 struct label *newlabel)
2824{
2825 int error;
2826
2827 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2828 newlabel);
2829
2830 return (error);
2831}
2832
2833int
2834mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2835{
2836 int error;
2837
2838 if (!mac_enforce_socket)
2839 return (0);
2840
2841 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2842
2843 return (error);
2844}
2845
2846int
2847mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2848 struct ifnet *ifnet)
2849{
2850 struct mac label;
2851 int error;
2852
2853 error = mac_externalize(&ifnet->if_label, &label);
2854 if (error)
2855 return (error);
2856
2857 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label)));
2858}
2859
2860int
2861mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2862 struct ifnet *ifnet)
2863{
2864 struct mac newlabel;
2865 struct label intlabel;
2866 int error;
2867
2868 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel));
2869 if (error)
2870 return (error);
2871
2872 error = mac_internalize(&intlabel, &newlabel);
2873 if (error)
2874 return (error);
2875
2876 /*
2877 * XXX: Note that this is a redundant privilege check, since
2878 * policies impose this check themselves if required by the
2879 * policy. Eventually, this should go away.
2880 */
2881 error = suser_cred(cred, 0);
2882 if (error)
2883 goto out;
2884
2885 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2886 &intlabel);
2887 if (error)
2888 goto out;
2889
2890 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2891
2892out:
2893 mac_destroy_temp(&intlabel);
2894 return (error);
2895}
2896
2897void
2898mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2899{
2900
2901 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2902}
2903
2904void
2905mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2906{
2907
2908 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2909}
2910
2911static int
2912mac_stdcreatevnode_ea(struct vnode *vp)
2913{
2914 int error;
2915
2916 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
2917
2918 return (error);
2919}
2920
2921void
2922mac_create_devfs_directory(char *dirname, int dirnamelen,
2923 struct devfs_dirent *de)
2924{
2925
2926 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2927 &de->de_label);
2928}
2929
2930/*
2931 * When a new vnode is created, this call will initialize its label.
2932 */
2933void
2934mac_create_vnode(struct ucred *cred, struct vnode *parent,
2935 struct vnode *child)
2936{
2937 int error;
2938
2939 ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
2940 ASSERT_VOP_LOCKED(child, "mac_create_vnode");
2941
2942 error = vn_refreshlabel(parent, cred);
2943 if (error) {
2944 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
2945 error);
2946 printf("mac_create_vnode: using old vnode label\n");
2947 }
2948
2949 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
2950 &child->v_label);
2951}
2952
2953int
2954mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2955 struct mac *extmac)
2956{
2957 struct label intlabel;
2958 int error;
2959
2960 error = mac_internalize(&intlabel, extmac);
2961 if (error)
2962 return (error);
2963
2964 mac_check_socket_relabel(cred, so, &intlabel);
2965 if (error) {
2966 mac_destroy_temp(&intlabel);
2967 return (error);
2968 }
2969
2970 mac_relabel_socket(cred, so, &intlabel);
2971
2972 mac_destroy_temp(&intlabel);
2973 return (0);
2974}
2975
2976int
2977mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2978{
2979 int error;
2980
2981 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2982
2983 error = mac_check_pipe_relabel(cred, pipe, label);
2984 if (error)
2985 return (error);
2986
2987 mac_relabel_pipe(cred, pipe, label);
2988
2989 return (0);
2990}
2991
2992int
2993mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2994 struct mac *extmac)
2995{
2996
2997 return (mac_externalize(&so->so_label, extmac));
2998}
2999
3000int
3001mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3002 struct mac *extmac)
3003{
3004
3005 return (mac_externalize(&so->so_peerlabel, extmac));
3006}
3007
3008/*
3009 * Implementation of VOP_SETLABEL() that relies on extended attributes
3010 * to store label data. Can be referenced by filesystems supporting
3011 * extended attributes.
3012 */
3013int
3014vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3015{
3016 struct vnode *vp = ap->a_vp;
3017 struct label *intlabel = ap->a_label;
3018 struct mac extmac;
3019 int error;
3020
3021 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3022
3023 /*
3024 * XXX: Eventually call out to EA check/set calls here.
3025 * Be particularly careful to avoid race conditions,
3026 * consistency problems, and stability problems when
3027 * dealing with multiple EAs. In particular, we require
3028 * the ability to write multiple EAs on the same file in
3029 * a single transaction, which the current EA interface
3030 * does not provide.
3031 */
3032
3033 error = mac_externalize(intlabel, &extmac);
3034 if (error)
3035 return (error);
3036
3037 error = vn_extattr_set(vp, IO_NODELOCKED,
3038 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3039 sizeof(extmac), (char *)&extmac, curthread);
3040 if (error)
3041 return (error);
3042
3043 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3044
3045 vp->v_vflag |= VV_CACHEDLABEL;
3046
3047 return (0);
3048}
3049
3050static int
3051vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3052{
3053 int error;
3054
3055 if (vp->v_mount == NULL) {
3056 /* printf("vn_setlabel: null v_mount\n"); */
3057 if (vp->v_type != VNON)
3058 printf("vn_setlabel: null v_mount with non-VNON\n");
3059 return (EBADF);
3060 }
3061
3062 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3063 return (EOPNOTSUPP);
3064
3065 /*
3066 * Multi-phase commit. First check the policies to confirm the
3067 * change is OK. Then commit via the filesystem. Finally,
3068 * update the actual vnode label. Question: maybe the filesystem
3069 * should update the vnode at the end as part of VOP_SETLABEL()?
3070 */
3071 error = mac_check_vnode_relabel(cred, vp, intlabel);
3072 if (error)
3073 return (error);
3074
3075 /*
3076 * VADMIN provides the opportunity for the filesystem to make
3077 * decisions about who is and is not able to modify labels
3078 * and protections on files. This might not be right. We can't
3079 * assume VOP_SETLABEL() will do it, because we might implement
3080 * that as part of vop_stdsetlabel_ea().
3081 */
3082 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3083 if (error)
3084 return (error);
3085
3086 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3087 if (error)
3088 return (error);
3089
3090 return (0);
3091}
3092
3093/*
3094 * MPSAFE
3095 */
3096int
3097__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3098{
3099 struct mac extmac;
3100 int error;
3101
3102 error = mac_externalize(&td->td_ucred->cr_label, &extmac);
3103 if (error == 0)
3104 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3105
3106 return (error);
3107}
3108
3109/*
3110 * MPSAFE
3111 */
3112int
3113__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3114{
3115 struct ucred *newcred, *oldcred;
3116 struct proc *p;
3117 struct mac extmac;
3118 struct label intlabel;
3119 int error;
3120
3121 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3122 if (error)
3123 return (error);
3124
3125 error = mac_internalize(&intlabel, &extmac);
3126 if (error)
3127 return (error);
3128
3129 newcred = crget();
3130
3131 p = td->td_proc;
3132 PROC_LOCK(p);
3133 oldcred = p->p_ucred;
3134
3135 error = mac_check_cred_relabel(oldcred, &intlabel);
3136 if (error) {
3137 PROC_UNLOCK(p);
3138 mac_destroy_temp(&intlabel);
3139 crfree(newcred);
3140 return (error);
3141 }
3142
3143 setsugid(p);
3144 crcopy(newcred, oldcred);
3145 mac_relabel_cred(newcred, &intlabel);
3146 p->p_ucred = newcred;
3147
3148 /*
3149 * Grab additional reference for use while revoking mmaps, prior
3150 * to releasing the proc lock and sharing the cred.
3151 */
3152 crhold(newcred);
3153 PROC_UNLOCK(p);
3154
3155 mtx_lock(&Giant);
3156 mac_cred_mmapped_drop_perms(td, newcred);
3157 mtx_unlock(&Giant);
3158
3159 crfree(newcred); /* Free revocation reference. */
3160 crfree(oldcred);
3161 mac_destroy_temp(&intlabel);
3162 return (0);
3163}
3164
3165/*
3166 * MPSAFE
3167 */
3168int
3169__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3170{
3171 struct file *fp;
3172 struct mac extmac;
3173 struct vnode *vp;
3174 struct pipe *pipe;
3175 int error;
3176
3177 mtx_lock(&Giant);
3178
3179 error = fget(td, SCARG(uap, fd), &fp);
3180 if (error)
3181 goto out;
3182
3183 switch (fp->f_type) {
3184 case DTYPE_FIFO:
3185 case DTYPE_VNODE:
3186 vp = (struct vnode *)fp->f_data;
3187
3188 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3189 error = vn_refreshlabel(vp, td->td_ucred);
3190 if (error == 0)
3191 error = mac_externalize(&vp->v_label, &extmac);
3192 VOP_UNLOCK(vp, 0, td);
3193 break;
3194 case DTYPE_PIPE:
3195 pipe = (struct pipe *)fp->f_data;
3196 error = mac_externalize(pipe->pipe_label, &extmac);
3197 break;
3198 default:
3199 error = EINVAL;
3200 }
3201
3202 if (error == 0)
3203 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3204
3205 fdrop(fp, td);
3206
3207out:
3208 mtx_unlock(&Giant);
3209 return (error);
3210}
3211
3212/*
3213 * MPSAFE
3214 */
3215int
3216__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3217{
3218 struct nameidata nd;
3219 struct mac extmac;
3220 int error;
3221
3222 mtx_lock(&Giant);
3223 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3224 SCARG(uap, path_p), td);
3225 error = namei(&nd);
3226 if (error)
3227 goto out;
3228
3229 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3230 if (error == 0)
3231 error = mac_externalize(&nd.ni_vp->v_label, &extmac);
3232 NDFREE(&nd, 0);
3233 if (error)
3234 goto out;
3235
3236 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3237
3238out:
3239 mtx_unlock(&Giant);
3240 return (error);
3241}
3242
3243/*
3244 * MPSAFE
3245 */
3246int
3247__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3248{
3249 struct file *fp;
3250 struct mac extmac;
3251 struct label intlabel;
3252 struct mount *mp;
3253 struct vnode *vp;
3254 struct pipe *pipe;
3255 int error;
3256
3257 mtx_lock(&Giant);
3258 error = fget(td, SCARG(uap, fd), &fp);
3259 if (error)
3260 goto out1;
3261
3262 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3263 if (error)
3264 goto out2;
3265
3266 error = mac_internalize(&intlabel, &extmac);
3267 if (error)
3268 goto out2;
3269
3270 switch (fp->f_type) {
3271 case DTYPE_FIFO:
3272 case DTYPE_VNODE:
3273 vp = (struct vnode *)fp->f_data;
3274 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3275 if (error != 0)
3276 break;
3277
3278 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3279 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3280 VOP_UNLOCK(vp, 0, td);
3281 vn_finished_write(mp);
3282 mac_destroy_temp(&intlabel);
3283 break;
3284 case DTYPE_PIPE:
3285 pipe = (struct pipe *)fp->f_data;
3286 PIPE_LOCK(pipe);
3287 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel);
3288 PIPE_UNLOCK(pipe);
3289 break;
3290 default:
3291 error = EINVAL;
3292 }
3293
3294out2:
3295 fdrop(fp, td);
3296out1:
3297 mtx_unlock(&Giant);
3298 return (error);
3299}
3300
3301/*
3302 * MPSAFE
3303 */
3304int
3305__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3306{
3307 struct nameidata nd;
3308 struct mac extmac;
3309 struct label intlabel;
3310 struct mount *mp;
3311 int error;
3312
3313 mtx_lock(&Giant);
3314
3315 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3316 if (error)
3317 goto out;
3318
3319 error = mac_internalize(&intlabel, &extmac);
3320 if (error)
3321 goto out;
3322
3323 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3324 SCARG(uap, path_p), td);
3325 error = namei(&nd);
3326 if (error)
3327 goto out2;
3328 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3329 if (error)
3330 goto out2;
3331
3332 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred);
3333
3334 vn_finished_write(mp);
3335out2:
3336 mac_destroy_temp(&intlabel);
3337 NDFREE(&nd, 0);
3338out:
3339 mtx_unlock(&Giant);
3340 return (error);
3341}
3342
3343int
3344mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3345{
3346 struct mac_policy_conf *mpc;
3347 char target[MAC_MAX_POLICY_NAME];
3348 int error;
3349
3350 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3351 if (error)
3352 return (error);
3353
3354 error = ENOSYS;
3355 MAC_POLICY_LIST_BUSY();
3356 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3357 if (strcmp(mpc->mpc_name, target) == 0 &&
3358 mpc->mpc_ops->mpo_syscall != NULL) {
3359 error = mpc->mpc_ops->mpo_syscall(td,
3360 SCARG(uap, call), SCARG(uap, arg));
3361 goto out;
3362 }
3363 }
3364
3365out:
3366 MAC_POLICY_LIST_UNBUSY();
3367 return (error);
3368}
3369
3370SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3371SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3372
3373#else /* !MAC */
3374
3375int
3376__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3377{
3378
3379 return (ENOSYS);
3380}
3381
3382int
3383__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3384{
3385
3386 return (ENOSYS);
3387}
3388
3389int
3390__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3391{
3392
3393 return (ENOSYS);
3394}
3395
3396int
3397__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3398{
3399
3400 return (ENOSYS);
3401}
3402
3403int
3404__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3405{
3406
3407 return (ENOSYS);
3408}
3409
3410int
3411__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3412{
3413
3414 return (ENOSYS);
3415}
3416
3417int
3418mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3419{
3420
3421 return (ENOSYS);
3422}
3423
3424#endif /* !MAC */
1301#endif
1302}
1303
1304static int
1305mac_externalize(struct label *label, struct mac *mac)
1306{
1307 int error;
1308
1309 mac_init_structmac(mac);
1310 MAC_CHECK(externalize, label, mac);
1311
1312 return (error);
1313}
1314
1315static int
1316mac_internalize(struct label *label, struct mac *mac)
1317{
1318 int error;
1319
1320 mac_init_temp(label);
1321 MAC_CHECK(internalize, label, mac);
1322 if (error)
1323 mac_destroy_temp(label);
1324
1325 return (error);
1326}
1327
1328/*
1329 * Initialize MAC label for the first kernel process, from which other
1330 * kernel processes and threads are spawned.
1331 */
1332void
1333mac_create_proc0(struct ucred *cred)
1334{
1335
1336 MAC_PERFORM(create_proc0, cred);
1337}
1338
1339/*
1340 * Initialize MAC label for the first userland process, from which other
1341 * userland processes and threads are spawned.
1342 */
1343void
1344mac_create_proc1(struct ucred *cred)
1345{
1346
1347 MAC_PERFORM(create_proc1, cred);
1348}
1349
1350void
1351mac_thread_userret(struct thread *td)
1352{
1353
1354 MAC_PERFORM(thread_userret, td);
1355}
1356
1357/*
1358 * When a new process is created, its label must be initialized. Generally,
1359 * this involves inheritence from the parent process, modulo possible
1360 * deltas. This function allows that processing to take place.
1361 */
1362void
1363mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1364{
1365
1366 MAC_PERFORM(create_cred, parent_cred, child_cred);
1367}
1368
1369void
1370mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1371{
1372
1373 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1374}
1375
1376void
1377mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1378{
1379
1380 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1381}
1382
1383/*
1384 * Support callout for policies that manage their own externalization
1385 * using extended attributes.
1386 */
1387static int
1388mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1389{
1390 int error;
1391
1392 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1393 &mp->mnt_fslabel);
1394
1395 return (error);
1396}
1397
1398/*
1399 * Given an externalized mac label, internalize it and stamp it on a
1400 * vnode.
1401 */
1402static int
1403mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
1404{
1405 int error;
1406
1407 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1408
1409 return (error);
1410}
1411
1412/*
1413 * Call out to individual policies to update the label in a vnode from
1414 * the mountpoint.
1415 */
1416void
1417mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1418{
1419
1420 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1421 &mp->mnt_fslabel);
1422
1423 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1424 if (mac_cache_fslabel_in_vnode)
1425 vp->v_vflag |= VV_CACHEDLABEL;
1426}
1427
1428/*
1429 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1430 * to store label data. Can be referenced by filesystems supporting
1431 * extended attributes.
1432 */
1433int
1434vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1435{
1436 struct vnode *vp = ap->a_vp;
1437 struct mac extmac;
1438 int buflen, error;
1439
1440 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1441
1442 /*
1443 * Call out to external policies first. Order doesn't really
1444 * matter, as long as failure of one assures failure of all.
1445 */
1446 error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1447 if (error)
1448 return (error);
1449
1450 buflen = sizeof(extmac);
1451 error = vn_extattr_get(vp, IO_NODELOCKED,
1452 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1453 (char *)&extmac, curthread);
1454 switch (error) {
1455 case 0:
1456 /* Got it */
1457 break;
1458
1459 case ENOATTR:
1460 /*
1461 * Use the label from the mount point.
1462 */
1463 mac_update_vnode_from_mount(vp, vp->v_mount);
1464 return (0);
1465
1466 case EOPNOTSUPP:
1467 default:
1468 /* Fail horribly. */
1469 return (error);
1470 }
1471
1472 if (buflen != sizeof(extmac))
1473 error = EPERM; /* Fail very closed. */
1474 if (error == 0)
1475 error = mac_update_vnode_from_externalized(vp, &extmac);
1476 if (error == 0)
1477 vp->v_vflag |= VV_CACHEDLABEL;
1478 else {
1479 struct vattr va;
1480
1481 printf("Corrupted label on %s",
1482 vp->v_mount->mnt_stat.f_mntonname);
1483 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1484 printf(" inum %ld", va.va_fileid);
1485#ifdef MAC_DEBUG
1486 if (mac_debug_label_fallback) {
1487 printf(", falling back.\n");
1488 mac_update_vnode_from_mount(vp, vp->v_mount);
1489 error = 0;
1490 } else {
1491#endif
1492 printf(".\n");
1493 error = EPERM;
1494#ifdef MAC_DEBUG
1495 }
1496#endif
1497 }
1498
1499 return (error);
1500}
1501
1502/*
1503 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
1504 * the labeling activity outselves. Filesystems should be careful not
1505 * to change their minds regarding whether they support vop_refreshlabel()
1506 * for a vnode or not. Don't cache the vnode here, allow the file
1507 * system code to determine if it's safe to cache. If we update from
1508 * the mount, don't cache since a change to the mount label should affect
1509 * all vnodes.
1510 */
1511static int
1512vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1513{
1514 int error;
1515
1516 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1517
1518 if (vp->v_mount == NULL) {
1519/*
1520 Eventually, we probably want to special-case refreshing
1521 of deadfs vnodes, and if there's a lock-free race somewhere,
1522 that case might be handled here.
1523
1524 mac_update_vnode_deadfs(vp);
1525 return (0);
1526 */
1527 /* printf("vn_refreshlabel: null v_mount\n"); */
1528 if (vp->v_type != VNON)
1529 printf(
1530 "vn_refreshlabel: null v_mount with non-VNON\n");
1531 return (EBADF);
1532 }
1533
1534 if (vp->v_vflag & VV_CACHEDLABEL) {
1535 mac_vnode_label_cache_hits++;
1536 return (0);
1537 } else
1538 mac_vnode_label_cache_misses++;
1539
1540 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1541 mac_update_vnode_from_mount(vp, vp->v_mount);
1542 return (0);
1543 }
1544
1545 error = VOP_REFRESHLABEL(vp, cred, curthread);
1546 switch (error) {
1547 case EOPNOTSUPP:
1548 /*
1549 * If labels are not supported on this vnode, fall back to
1550 * the label in the mount and propagate it to the vnode.
1551 * There should probably be some sort of policy/flag/decision
1552 * about doing this.
1553 */
1554 mac_update_vnode_from_mount(vp, vp->v_mount);
1555 error = 0;
1556 default:
1557 return (error);
1558 }
1559}
1560
1561/*
1562 * Helper function for file systems using the vop_std*_ea() calls. This
1563 * function must be called after EA service is available for the vnode,
1564 * but before it's hooked up to the namespace so that the node persists
1565 * if there's a crash, or before it can be accessed. On successful
1566 * commit of the label to disk (etc), do cache the label.
1567 */
1568int
1569vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1570{
1571 struct mac extmac;
1572 int error;
1573
1574 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1575 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1576 mac_update_vnode_from_mount(tvp, tvp->v_mount);
1577 } else {
1578 error = vn_refreshlabel(dvp, cred);
1579 if (error)
1580 return (error);
1581
1582 /*
1583 * Stick the label in the vnode. Then try to write to
1584 * disk. If we fail, return a failure to abort the
1585 * create operation. Really, this failure shouldn't
1586 * happen except in fairly unusual circumstances (out
1587 * of disk, etc).
1588 */
1589 mac_create_vnode(cred, dvp, tvp);
1590
1591 error = mac_stdcreatevnode_ea(tvp);
1592 if (error)
1593 return (error);
1594
1595 /*
1596 * XXX: Eventually this will go away and all policies will
1597 * directly manage their extended attributes.
1598 */
1599 error = mac_externalize(&tvp->v_label, &extmac);
1600 if (error)
1601 return (error);
1602
1603 error = vn_extattr_set(tvp, IO_NODELOCKED,
1604 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1605 sizeof(extmac), (char *)&extmac, curthread);
1606 if (error == 0)
1607 tvp->v_vflag |= VV_CACHEDLABEL;
1608 else {
1609#if 0
1610 /*
1611 * In theory, we could have fall-back behavior here.
1612 * It would probably be incorrect.
1613 */
1614#endif
1615 return (error);
1616 }
1617 }
1618
1619 return (0);
1620}
1621
1622void
1623mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1624{
1625 int error;
1626
1627 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1628
1629 error = vn_refreshlabel(vp, old);
1630 if (error) {
1631 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
1632 error);
1633 printf("mac_execve_transition: using old vnode label\n");
1634 }
1635
1636 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1637}
1638
1639int
1640mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1641{
1642 int error, result;
1643
1644 error = vn_refreshlabel(vp, old);
1645 if (error)
1646 return (error);
1647
1648 result = 0;
1649 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1650
1651 return (result);
1652}
1653
1654int
1655mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
1656{
1657 int error;
1658
1659 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1660
1661 if (!mac_enforce_fs)
1662 return (0);
1663
1664 error = vn_refreshlabel(vp, cred);
1665 if (error)
1666 return (error);
1667
1668 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
1669 return (error);
1670}
1671
1672int
1673mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1674{
1675 int error;
1676
1677 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1678
1679 if (!mac_enforce_fs)
1680 return (0);
1681
1682 error = vn_refreshlabel(dvp, cred);
1683 if (error)
1684 return (error);
1685
1686 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1687 return (error);
1688}
1689
1690int
1691mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1692{
1693 int error;
1694
1695 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1696
1697 if (!mac_enforce_fs)
1698 return (0);
1699
1700 error = vn_refreshlabel(dvp, cred);
1701 if (error)
1702 return (error);
1703
1704 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1705 return (error);
1706}
1707
1708int
1709mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1710 struct componentname *cnp, struct vattr *vap)
1711{
1712 int error;
1713
1714 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1715
1716 if (!mac_enforce_fs)
1717 return (0);
1718
1719 error = vn_refreshlabel(dvp, cred);
1720 if (error)
1721 return (error);
1722
1723 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1724 return (error);
1725}
1726
1727int
1728mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1729 struct componentname *cnp)
1730{
1731 int error;
1732
1733 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1734 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1735
1736 if (!mac_enforce_fs)
1737 return (0);
1738
1739 error = vn_refreshlabel(dvp, cred);
1740 if (error)
1741 return (error);
1742 error = vn_refreshlabel(vp, cred);
1743 if (error)
1744 return (error);
1745
1746 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1747 &vp->v_label, cnp);
1748 return (error);
1749}
1750
1751int
1752mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1753 acl_type_t type)
1754{
1755 int error;
1756
1757 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1758
1759 if (!mac_enforce_fs)
1760 return (0);
1761
1762 error = vn_refreshlabel(vp, cred);
1763 if (error)
1764 return (error);
1765
1766 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1767 return (error);
1768}
1769
1770int
1771mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1772{
1773 int error;
1774
1775 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1776
1777 if (!mac_enforce_process && !mac_enforce_fs)
1778 return (0);
1779
1780 error = vn_refreshlabel(vp, cred);
1781 if (error)
1782 return (error);
1783 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1784
1785 return (error);
1786}
1787
1788int
1789mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1790{
1791 int error;
1792
1793 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1794
1795 if (!mac_enforce_fs)
1796 return (0);
1797
1798 error = vn_refreshlabel(vp, cred);
1799 if (error)
1800 return (error);
1801
1802 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1803 return (error);
1804}
1805
1806int
1807mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1808 int attrnamespace, const char *name, struct uio *uio)
1809{
1810 int error;
1811
1812 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1813
1814 if (!mac_enforce_fs)
1815 return (0);
1816
1817 error = vn_refreshlabel(vp, cred);
1818 if (error)
1819 return (error);
1820
1821 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1822 attrnamespace, name, uio);
1823 return (error);
1824}
1825
1826int
1827mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1828 struct componentname *cnp)
1829{
1830 int error;
1831
1832 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1833
1834 if (!mac_enforce_fs)
1835 return (0);
1836
1837 error = vn_refreshlabel(dvp, cred);
1838 if (error)
1839 return (error);
1840
1841 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1842 return (error);
1843}
1844
1845vm_prot_t
1846mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping)
1847{
1848 vm_prot_t result = VM_PROT_ALL;
1849
1850 if (!mac_enforce_vm)
1851 return (result);
1852
1853 /*
1854 * This should be some sort of MAC_BITWISE, maybe :)
1855 */
1856 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms");
1857 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label,
1858 newmapping);
1859 return (result);
1860}
1861
1862int
1863mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
1864{
1865 int error;
1866
1867 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1868
1869 if (!mac_enforce_fs)
1870 return (0);
1871
1872 error = vn_refreshlabel(vp, cred);
1873 if (error)
1874 return (error);
1875
1876 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1877 return (error);
1878}
1879
1880int
1881mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1882 struct vnode *vp)
1883{
1884 int error;
1885
1886 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1887
1888 if (!mac_enforce_fs)
1889 return (0);
1890
1891 error = vn_refreshlabel(vp, active_cred);
1892 if (error)
1893 return (error);
1894
1895 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1896 &vp->v_label);
1897
1898 return (error);
1899}
1900
1901int
1902mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1903 struct vnode *vp)
1904{
1905 int error;
1906
1907 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1908
1909 if (!mac_enforce_fs)
1910 return (0);
1911
1912 error = vn_refreshlabel(vp, active_cred);
1913 if (error)
1914 return (error);
1915
1916 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1917 &vp->v_label);
1918
1919 return (error);
1920}
1921
1922int
1923mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1924{
1925 int error;
1926
1927 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1928
1929 if (!mac_enforce_fs)
1930 return (0);
1931
1932 error = vn_refreshlabel(dvp, cred);
1933 if (error)
1934 return (error);
1935
1936 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1937 return (error);
1938}
1939
1940int
1941mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1942{
1943 int error;
1944
1945 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1946
1947 if (!mac_enforce_fs)
1948 return (0);
1949
1950 error = vn_refreshlabel(vp, cred);
1951 if (error)
1952 return (error);
1953
1954 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1955 return (error);
1956}
1957
1958static int
1959mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1960 struct label *newlabel)
1961{
1962 int error;
1963
1964 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1965
1966 error = vn_refreshlabel(vp, cred);
1967 if (error)
1968 return (error);
1969
1970 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1971
1972 return (error);
1973}
1974
1975int
1976mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1977 struct vnode *vp, struct componentname *cnp)
1978{
1979 int error;
1980
1981 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1982 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1983
1984 if (!mac_enforce_fs)
1985 return (0);
1986
1987 error = vn_refreshlabel(dvp, cred);
1988 if (error)
1989 return (error);
1990 error = vn_refreshlabel(vp, cred);
1991 if (error)
1992 return (error);
1993
1994 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1995 &vp->v_label, cnp);
1996 return (error);
1997}
1998
1999int
2000mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2001 struct vnode *vp, int samedir, struct componentname *cnp)
2002{
2003 int error;
2004
2005 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2006 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2007
2008 if (!mac_enforce_fs)
2009 return (0);
2010
2011 error = vn_refreshlabel(dvp, cred);
2012 if (error)
2013 return (error);
2014 if (vp != NULL) {
2015 error = vn_refreshlabel(vp, cred);
2016 if (error)
2017 return (error);
2018 }
2019 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2020 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2021 return (error);
2022}
2023
2024int
2025mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2026{
2027 int error;
2028
2029 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2030
2031 if (!mac_enforce_fs)
2032 return (0);
2033
2034 error = vn_refreshlabel(vp, cred);
2035 if (error)
2036 return (error);
2037
2038 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2039 return (error);
2040}
2041
2042int
2043mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2044 struct acl *acl)
2045{
2046 int error;
2047
2048 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2049
2050 if (!mac_enforce_fs)
2051 return (0);
2052
2053 error = vn_refreshlabel(vp, cred);
2054 if (error)
2055 return (error);
2056
2057 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2058 return (error);
2059}
2060
2061int
2062mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2063 int attrnamespace, const char *name, struct uio *uio)
2064{
2065 int error;
2066
2067 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2068
2069 if (!mac_enforce_fs)
2070 return (0);
2071
2072 error = vn_refreshlabel(vp, cred);
2073 if (error)
2074 return (error);
2075
2076 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2077 attrnamespace, name, uio);
2078 return (error);
2079}
2080
2081int
2082mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2083{
2084 int error;
2085
2086 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2087
2088 if (!mac_enforce_fs)
2089 return (0);
2090
2091 error = vn_refreshlabel(vp, cred);
2092 if (error)
2093 return (error);
2094
2095 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2096 return (error);
2097}
2098
2099int
2100mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2101{
2102 int error;
2103
2104 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2105
2106 if (!mac_enforce_fs)
2107 return (0);
2108
2109 error = vn_refreshlabel(vp, cred);
2110 if (error)
2111 return (error);
2112
2113 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2114 return (error);
2115}
2116
2117int
2118mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2119 gid_t gid)
2120{
2121 int error;
2122
2123 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2124
2125 if (!mac_enforce_fs)
2126 return (0);
2127
2128 error = vn_refreshlabel(vp, cred);
2129 if (error)
2130 return (error);
2131
2132 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2133 return (error);
2134}
2135
2136int
2137mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2138 struct timespec atime, struct timespec mtime)
2139{
2140 int error;
2141
2142 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2143
2144 if (!mac_enforce_fs)
2145 return (0);
2146
2147 error = vn_refreshlabel(vp, cred);
2148 if (error)
2149 return (error);
2150
2151 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2152 mtime);
2153 return (error);
2154}
2155
2156int
2157mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2158 struct vnode *vp)
2159{
2160 int error;
2161
2162 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2163
2164 if (!mac_enforce_fs)
2165 return (0);
2166
2167 error = vn_refreshlabel(vp, active_cred);
2168 if (error)
2169 return (error);
2170
2171 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2172 &vp->v_label);
2173 return (error);
2174}
2175
2176int
2177mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2178 struct vnode *vp)
2179{
2180 int error;
2181
2182 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2183
2184 if (!mac_enforce_fs)
2185 return (0);
2186
2187 error = vn_refreshlabel(vp, active_cred);
2188 if (error)
2189 return (error);
2190
2191 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2192 &vp->v_label);
2193
2194 return (error);
2195}
2196
2197/*
2198 * When relabeling a process, call out to the policies for the maximum
2199 * permission allowed for each object type we know about in its
2200 * memory space, and revoke access (in the least surprising ways we
2201 * know) when necessary. The process lock is not held here.
2202 */
2203static void
2204mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2205{
2206
2207 /* XXX freeze all other threads */
2208 mac_cred_mmapped_drop_perms_recurse(td, cred,
2209 &td->td_proc->p_vmspace->vm_map);
2210 /* XXX allow other threads to continue */
2211}
2212
2213static __inline const char *
2214prot2str(vm_prot_t prot)
2215{
2216
2217 switch (prot & VM_PROT_ALL) {
2218 case VM_PROT_READ:
2219 return ("r--");
2220 case VM_PROT_READ | VM_PROT_WRITE:
2221 return ("rw-");
2222 case VM_PROT_READ | VM_PROT_EXECUTE:
2223 return ("r-x");
2224 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2225 return ("rwx");
2226 case VM_PROT_WRITE:
2227 return ("-w-");
2228 case VM_PROT_EXECUTE:
2229 return ("--x");
2230 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2231 return ("-wx");
2232 default:
2233 return ("---");
2234 }
2235}
2236
2237static void
2238mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2239 struct vm_map *map)
2240{
2241 struct vm_map_entry *vme;
2242 vm_prot_t result, revokeperms;
2243 vm_object_t object;
2244 vm_ooffset_t offset;
2245 struct vnode *vp;
2246
2247 if (!mac_mmap_revocation)
2248 return;
2249
2250 vm_map_lock_read(map);
2251 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2252 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2253 mac_cred_mmapped_drop_perms_recurse(td, cred,
2254 vme->object.sub_map);
2255 continue;
2256 }
2257 /*
2258 * Skip over entries that obviously are not shared.
2259 */
2260 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2261 !vme->max_protection)
2262 continue;
2263 /*
2264 * Drill down to the deepest backing object.
2265 */
2266 offset = vme->offset;
2267 object = vme->object.vm_object;
2268 if (object == NULL)
2269 continue;
2270 while (object->backing_object != NULL) {
2271 object = object->backing_object;
2272 offset += object->backing_object_offset;
2273 }
2274 /*
2275 * At the moment, vm_maps and objects aren't considered
2276 * by the MAC system, so only things with backing by a
2277 * normal object (read: vnodes) are checked.
2278 */
2279 if (object->type != OBJT_VNODE)
2280 continue;
2281 vp = (struct vnode *)object->handle;
2282 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2283 result = mac_check_vnode_mmap_prot(cred, vp, 0);
2284 VOP_UNLOCK(vp, 0, td);
2285 /*
2286 * Find out what maximum protection we may be allowing
2287 * now but a policy needs to get removed.
2288 */
2289 revokeperms = vme->max_protection & ~result;
2290 if (!revokeperms)
2291 continue;
2292 printf("pid %ld: revoking %s perms from %#lx:%ld "
2293 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2294 prot2str(revokeperms), (u_long)vme->start,
2295 (long)(vme->end - vme->start),
2296 prot2str(vme->max_protection), prot2str(vme->protection));
2297 vm_map_lock_upgrade(map);
2298 /*
2299 * This is the really simple case: if a map has more
2300 * max_protection than is allowed, but it's not being
2301 * actually used (that is, the current protection is
2302 * still allowed), we can just wipe it out and do
2303 * nothing more.
2304 */
2305 if ((vme->protection & revokeperms) == 0) {
2306 vme->max_protection -= revokeperms;
2307 } else {
2308 if (revokeperms & VM_PROT_WRITE) {
2309 /*
2310 * In the more complicated case, flush out all
2311 * pending changes to the object then turn it
2312 * copy-on-write.
2313 */
2314 vm_object_reference(object);
2315 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2316 vm_object_page_clean(object,
2317 OFF_TO_IDX(offset),
2318 OFF_TO_IDX(offset + vme->end - vme->start +
2319 PAGE_MASK),
2320 OBJPC_SYNC);
2321 VOP_UNLOCK(vp, 0, td);
2322 vm_object_deallocate(object);
2323 /*
2324 * Why bother if there's no read permissions
2325 * anymore? For the rest, we need to leave
2326 * the write permissions on for COW, or
2327 * remove them entirely if configured to.
2328 */
2329 if (!mac_mmap_revocation_via_cow) {
2330 vme->max_protection &= ~VM_PROT_WRITE;
2331 vme->protection &= ~VM_PROT_WRITE;
2332 } if ((revokeperms & VM_PROT_READ) == 0)
2333 vme->eflags |= MAP_ENTRY_COW |
2334 MAP_ENTRY_NEEDS_COPY;
2335 }
2336 if (revokeperms & VM_PROT_EXECUTE) {
2337 vme->max_protection &= ~VM_PROT_EXECUTE;
2338 vme->protection &= ~VM_PROT_EXECUTE;
2339 }
2340 if (revokeperms & VM_PROT_READ) {
2341 vme->max_protection = 0;
2342 vme->protection = 0;
2343 }
2344 pmap_protect(map->pmap, vme->start, vme->end,
2345 vme->protection & ~revokeperms);
2346 vm_map_simplify_entry(map, vme);
2347 }
2348 vm_map_lock_downgrade(map);
2349 }
2350 vm_map_unlock_read(map);
2351}
2352
2353/*
2354 * When the subject's label changes, it may require revocation of privilege
2355 * to mapped objects. This can't be done on-the-fly later with a unified
2356 * buffer cache.
2357 */
2358static void
2359mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2360{
2361
2362 MAC_PERFORM(relabel_cred, cred, newlabel);
2363}
2364
2365void
2366mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2367{
2368
2369 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2370}
2371
2372void
2373mac_create_ifnet(struct ifnet *ifnet)
2374{
2375
2376 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2377}
2378
2379void
2380mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2381{
2382
2383 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2384}
2385
2386void
2387mac_create_socket(struct ucred *cred, struct socket *socket)
2388{
2389
2390 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2391}
2392
2393void
2394mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2395{
2396
2397 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2398}
2399
2400void
2401mac_create_socket_from_socket(struct socket *oldsocket,
2402 struct socket *newsocket)
2403{
2404
2405 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2406 newsocket, &newsocket->so_label);
2407}
2408
2409static void
2410mac_relabel_socket(struct ucred *cred, struct socket *socket,
2411 struct label *newlabel)
2412{
2413
2414 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2415}
2416
2417static void
2418mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2419{
2420
2421 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2422}
2423
2424void
2425mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2426{
2427
2428 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2429 socket, &socket->so_peerlabel);
2430}
2431
2432void
2433mac_set_socket_peer_from_socket(struct socket *oldsocket,
2434 struct socket *newsocket)
2435{
2436
2437 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2438 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2439}
2440
2441void
2442mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2443{
2444
2445 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2446 datagram, &datagram->m_pkthdr.label);
2447}
2448
2449void
2450mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2451{
2452
2453 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2454 fragment, &fragment->m_pkthdr.label);
2455}
2456
2457void
2458mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2459{
2460
2461 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2462 &ipq->ipq_label);
2463}
2464
2465void
2466mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2467{
2468
2469 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2470 newmbuf, &newmbuf->m_pkthdr.label);
2471}
2472
2473void
2474mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2475{
2476
2477 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2478 &mbuf->m_pkthdr.label);
2479}
2480
2481void
2482mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2483{
2484
2485 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2486 &mbuf->m_pkthdr.label);
2487}
2488
2489void
2490mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2491{
2492
2493 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2494 &mbuf->m_pkthdr.label);
2495}
2496
2497void
2498mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2499 struct mbuf *newmbuf)
2500{
2501
2502 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2503 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2504 &newmbuf->m_pkthdr.label);
2505}
2506
2507void
2508mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2509{
2510
2511 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2512 newmbuf, &newmbuf->m_pkthdr.label);
2513}
2514
2515int
2516mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2517{
2518 int result;
2519
2520 result = 1;
2521 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2522 ipq, &ipq->ipq_label);
2523
2524 return (result);
2525}
2526
2527void
2528mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2529{
2530
2531 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2532 &ipq->ipq_label);
2533}
2534
2535void
2536mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2537{
2538
2539 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2540 &mbuf->m_pkthdr.label);
2541}
2542
2543void
2544mac_create_mount(struct ucred *cred, struct mount *mp)
2545{
2546
2547 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2548 &mp->mnt_fslabel);
2549}
2550
2551void
2552mac_create_root_mount(struct ucred *cred, struct mount *mp)
2553{
2554
2555 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2556 &mp->mnt_fslabel);
2557}
2558
2559int
2560mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2561{
2562 int error;
2563
2564 if (!mac_enforce_network)
2565 return (0);
2566
2567 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2568 &ifnet->if_label);
2569
2570 return (error);
2571}
2572
2573static int
2574mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2575{
2576 int error;
2577
2578 MAC_CHECK(check_cred_relabel, cred, newlabel);
2579
2580 return (error);
2581}
2582
2583int
2584mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2585{
2586 int error;
2587
2588 if (!mac_enforce_process)
2589 return (0);
2590
2591 MAC_CHECK(check_cred_visible, u1, u2);
2592
2593 return (error);
2594}
2595
2596int
2597mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2598{
2599 int error;
2600
2601 if (!mac_enforce_network)
2602 return (0);
2603
2604 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2605 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2606 printf("%s%d: not initialized\n", ifnet->if_name,
2607 ifnet->if_unit);
2608
2609 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2610 &mbuf->m_pkthdr.label);
2611
2612 return (error);
2613}
2614
2615int
2616mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2617{
2618 int error;
2619
2620 if (!mac_enforce_fs)
2621 return (0);
2622
2623 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2624
2625 return (error);
2626}
2627
2628int
2629mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2630 void *data)
2631{
2632 int error;
2633
2634 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2635
2636 if (!mac_enforce_pipe)
2637 return (0);
2638
2639 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2640
2641 return (error);
2642}
2643
2644int
2645mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2646{
2647 int error;
2648
2649 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2650
2651 if (!mac_enforce_pipe)
2652 return (0);
2653
2654 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2655
2656 return (error);
2657}
2658
2659int
2660mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2661{
2662 int error;
2663
2664 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2665
2666 if (!mac_enforce_pipe)
2667 return (0);
2668
2669 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2670
2671 return (error);
2672}
2673
2674static int
2675mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2676 struct label *newlabel)
2677{
2678 int error;
2679
2680 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2681
2682 if (!mac_enforce_pipe)
2683 return (0);
2684
2685 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2686
2687 return (error);
2688}
2689
2690int
2691mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2692{
2693 int error;
2694
2695 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2696
2697 if (!mac_enforce_pipe)
2698 return (0);
2699
2700 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2701
2702 return (error);
2703}
2704
2705int
2706mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2707{
2708 int error;
2709
2710 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2711
2712 if (!mac_enforce_pipe)
2713 return (0);
2714
2715 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2716
2717 return (error);
2718}
2719
2720int
2721mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2722{
2723 int error;
2724
2725 PROC_LOCK_ASSERT(proc, MA_OWNED);
2726
2727 if (!mac_enforce_process)
2728 return (0);
2729
2730 MAC_CHECK(check_proc_debug, cred, proc);
2731
2732 return (error);
2733}
2734
2735int
2736mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2737{
2738 int error;
2739
2740 PROC_LOCK_ASSERT(proc, MA_OWNED);
2741
2742 if (!mac_enforce_process)
2743 return (0);
2744
2745 MAC_CHECK(check_proc_sched, cred, proc);
2746
2747 return (error);
2748}
2749
2750int
2751mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2752{
2753 int error;
2754
2755 PROC_LOCK_ASSERT(proc, MA_OWNED);
2756
2757 if (!mac_enforce_process)
2758 return (0);
2759
2760 MAC_CHECK(check_proc_signal, cred, proc, signum);
2761
2762 return (error);
2763}
2764
2765int
2766mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2767 struct sockaddr *sockaddr)
2768{
2769 int error;
2770
2771 if (!mac_enforce_socket)
2772 return (0);
2773
2774 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2775 sockaddr);
2776
2777 return (error);
2778}
2779
2780int
2781mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2782 struct sockaddr *sockaddr)
2783{
2784 int error;
2785
2786 if (!mac_enforce_socket)
2787 return (0);
2788
2789 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2790 sockaddr);
2791
2792 return (error);
2793}
2794
2795int
2796mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2797{
2798 int error;
2799
2800 if (!mac_enforce_socket)
2801 return (0);
2802
2803 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2804 &mbuf->m_pkthdr.label);
2805
2806 return (error);
2807}
2808
2809int
2810mac_check_socket_listen(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_listen, cred, socket, &socket->so_label);
2818 return (error);
2819}
2820
2821static int
2822mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2823 struct label *newlabel)
2824{
2825 int error;
2826
2827 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2828 newlabel);
2829
2830 return (error);
2831}
2832
2833int
2834mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2835{
2836 int error;
2837
2838 if (!mac_enforce_socket)
2839 return (0);
2840
2841 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2842
2843 return (error);
2844}
2845
2846int
2847mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2848 struct ifnet *ifnet)
2849{
2850 struct mac label;
2851 int error;
2852
2853 error = mac_externalize(&ifnet->if_label, &label);
2854 if (error)
2855 return (error);
2856
2857 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label)));
2858}
2859
2860int
2861mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2862 struct ifnet *ifnet)
2863{
2864 struct mac newlabel;
2865 struct label intlabel;
2866 int error;
2867
2868 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel));
2869 if (error)
2870 return (error);
2871
2872 error = mac_internalize(&intlabel, &newlabel);
2873 if (error)
2874 return (error);
2875
2876 /*
2877 * XXX: Note that this is a redundant privilege check, since
2878 * policies impose this check themselves if required by the
2879 * policy. Eventually, this should go away.
2880 */
2881 error = suser_cred(cred, 0);
2882 if (error)
2883 goto out;
2884
2885 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2886 &intlabel);
2887 if (error)
2888 goto out;
2889
2890 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2891
2892out:
2893 mac_destroy_temp(&intlabel);
2894 return (error);
2895}
2896
2897void
2898mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2899{
2900
2901 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2902}
2903
2904void
2905mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2906{
2907
2908 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2909}
2910
2911static int
2912mac_stdcreatevnode_ea(struct vnode *vp)
2913{
2914 int error;
2915
2916 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
2917
2918 return (error);
2919}
2920
2921void
2922mac_create_devfs_directory(char *dirname, int dirnamelen,
2923 struct devfs_dirent *de)
2924{
2925
2926 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2927 &de->de_label);
2928}
2929
2930/*
2931 * When a new vnode is created, this call will initialize its label.
2932 */
2933void
2934mac_create_vnode(struct ucred *cred, struct vnode *parent,
2935 struct vnode *child)
2936{
2937 int error;
2938
2939 ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
2940 ASSERT_VOP_LOCKED(child, "mac_create_vnode");
2941
2942 error = vn_refreshlabel(parent, cred);
2943 if (error) {
2944 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
2945 error);
2946 printf("mac_create_vnode: using old vnode label\n");
2947 }
2948
2949 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
2950 &child->v_label);
2951}
2952
2953int
2954mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2955 struct mac *extmac)
2956{
2957 struct label intlabel;
2958 int error;
2959
2960 error = mac_internalize(&intlabel, extmac);
2961 if (error)
2962 return (error);
2963
2964 mac_check_socket_relabel(cred, so, &intlabel);
2965 if (error) {
2966 mac_destroy_temp(&intlabel);
2967 return (error);
2968 }
2969
2970 mac_relabel_socket(cred, so, &intlabel);
2971
2972 mac_destroy_temp(&intlabel);
2973 return (0);
2974}
2975
2976int
2977mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2978{
2979 int error;
2980
2981 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2982
2983 error = mac_check_pipe_relabel(cred, pipe, label);
2984 if (error)
2985 return (error);
2986
2987 mac_relabel_pipe(cred, pipe, label);
2988
2989 return (0);
2990}
2991
2992int
2993mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2994 struct mac *extmac)
2995{
2996
2997 return (mac_externalize(&so->so_label, extmac));
2998}
2999
3000int
3001mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3002 struct mac *extmac)
3003{
3004
3005 return (mac_externalize(&so->so_peerlabel, extmac));
3006}
3007
3008/*
3009 * Implementation of VOP_SETLABEL() that relies on extended attributes
3010 * to store label data. Can be referenced by filesystems supporting
3011 * extended attributes.
3012 */
3013int
3014vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3015{
3016 struct vnode *vp = ap->a_vp;
3017 struct label *intlabel = ap->a_label;
3018 struct mac extmac;
3019 int error;
3020
3021 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3022
3023 /*
3024 * XXX: Eventually call out to EA check/set calls here.
3025 * Be particularly careful to avoid race conditions,
3026 * consistency problems, and stability problems when
3027 * dealing with multiple EAs. In particular, we require
3028 * the ability to write multiple EAs on the same file in
3029 * a single transaction, which the current EA interface
3030 * does not provide.
3031 */
3032
3033 error = mac_externalize(intlabel, &extmac);
3034 if (error)
3035 return (error);
3036
3037 error = vn_extattr_set(vp, IO_NODELOCKED,
3038 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3039 sizeof(extmac), (char *)&extmac, curthread);
3040 if (error)
3041 return (error);
3042
3043 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3044
3045 vp->v_vflag |= VV_CACHEDLABEL;
3046
3047 return (0);
3048}
3049
3050static int
3051vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3052{
3053 int error;
3054
3055 if (vp->v_mount == NULL) {
3056 /* printf("vn_setlabel: null v_mount\n"); */
3057 if (vp->v_type != VNON)
3058 printf("vn_setlabel: null v_mount with non-VNON\n");
3059 return (EBADF);
3060 }
3061
3062 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3063 return (EOPNOTSUPP);
3064
3065 /*
3066 * Multi-phase commit. First check the policies to confirm the
3067 * change is OK. Then commit via the filesystem. Finally,
3068 * update the actual vnode label. Question: maybe the filesystem
3069 * should update the vnode at the end as part of VOP_SETLABEL()?
3070 */
3071 error = mac_check_vnode_relabel(cred, vp, intlabel);
3072 if (error)
3073 return (error);
3074
3075 /*
3076 * VADMIN provides the opportunity for the filesystem to make
3077 * decisions about who is and is not able to modify labels
3078 * and protections on files. This might not be right. We can't
3079 * assume VOP_SETLABEL() will do it, because we might implement
3080 * that as part of vop_stdsetlabel_ea().
3081 */
3082 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3083 if (error)
3084 return (error);
3085
3086 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3087 if (error)
3088 return (error);
3089
3090 return (0);
3091}
3092
3093/*
3094 * MPSAFE
3095 */
3096int
3097__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3098{
3099 struct mac extmac;
3100 int error;
3101
3102 error = mac_externalize(&td->td_ucred->cr_label, &extmac);
3103 if (error == 0)
3104 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3105
3106 return (error);
3107}
3108
3109/*
3110 * MPSAFE
3111 */
3112int
3113__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3114{
3115 struct ucred *newcred, *oldcred;
3116 struct proc *p;
3117 struct mac extmac;
3118 struct label intlabel;
3119 int error;
3120
3121 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3122 if (error)
3123 return (error);
3124
3125 error = mac_internalize(&intlabel, &extmac);
3126 if (error)
3127 return (error);
3128
3129 newcred = crget();
3130
3131 p = td->td_proc;
3132 PROC_LOCK(p);
3133 oldcred = p->p_ucred;
3134
3135 error = mac_check_cred_relabel(oldcred, &intlabel);
3136 if (error) {
3137 PROC_UNLOCK(p);
3138 mac_destroy_temp(&intlabel);
3139 crfree(newcred);
3140 return (error);
3141 }
3142
3143 setsugid(p);
3144 crcopy(newcred, oldcred);
3145 mac_relabel_cred(newcred, &intlabel);
3146 p->p_ucred = newcred;
3147
3148 /*
3149 * Grab additional reference for use while revoking mmaps, prior
3150 * to releasing the proc lock and sharing the cred.
3151 */
3152 crhold(newcred);
3153 PROC_UNLOCK(p);
3154
3155 mtx_lock(&Giant);
3156 mac_cred_mmapped_drop_perms(td, newcred);
3157 mtx_unlock(&Giant);
3158
3159 crfree(newcred); /* Free revocation reference. */
3160 crfree(oldcred);
3161 mac_destroy_temp(&intlabel);
3162 return (0);
3163}
3164
3165/*
3166 * MPSAFE
3167 */
3168int
3169__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3170{
3171 struct file *fp;
3172 struct mac extmac;
3173 struct vnode *vp;
3174 struct pipe *pipe;
3175 int error;
3176
3177 mtx_lock(&Giant);
3178
3179 error = fget(td, SCARG(uap, fd), &fp);
3180 if (error)
3181 goto out;
3182
3183 switch (fp->f_type) {
3184 case DTYPE_FIFO:
3185 case DTYPE_VNODE:
3186 vp = (struct vnode *)fp->f_data;
3187
3188 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3189 error = vn_refreshlabel(vp, td->td_ucred);
3190 if (error == 0)
3191 error = mac_externalize(&vp->v_label, &extmac);
3192 VOP_UNLOCK(vp, 0, td);
3193 break;
3194 case DTYPE_PIPE:
3195 pipe = (struct pipe *)fp->f_data;
3196 error = mac_externalize(pipe->pipe_label, &extmac);
3197 break;
3198 default:
3199 error = EINVAL;
3200 }
3201
3202 if (error == 0)
3203 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3204
3205 fdrop(fp, td);
3206
3207out:
3208 mtx_unlock(&Giant);
3209 return (error);
3210}
3211
3212/*
3213 * MPSAFE
3214 */
3215int
3216__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3217{
3218 struct nameidata nd;
3219 struct mac extmac;
3220 int error;
3221
3222 mtx_lock(&Giant);
3223 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3224 SCARG(uap, path_p), td);
3225 error = namei(&nd);
3226 if (error)
3227 goto out;
3228
3229 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3230 if (error == 0)
3231 error = mac_externalize(&nd.ni_vp->v_label, &extmac);
3232 NDFREE(&nd, 0);
3233 if (error)
3234 goto out;
3235
3236 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3237
3238out:
3239 mtx_unlock(&Giant);
3240 return (error);
3241}
3242
3243/*
3244 * MPSAFE
3245 */
3246int
3247__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3248{
3249 struct file *fp;
3250 struct mac extmac;
3251 struct label intlabel;
3252 struct mount *mp;
3253 struct vnode *vp;
3254 struct pipe *pipe;
3255 int error;
3256
3257 mtx_lock(&Giant);
3258 error = fget(td, SCARG(uap, fd), &fp);
3259 if (error)
3260 goto out1;
3261
3262 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3263 if (error)
3264 goto out2;
3265
3266 error = mac_internalize(&intlabel, &extmac);
3267 if (error)
3268 goto out2;
3269
3270 switch (fp->f_type) {
3271 case DTYPE_FIFO:
3272 case DTYPE_VNODE:
3273 vp = (struct vnode *)fp->f_data;
3274 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3275 if (error != 0)
3276 break;
3277
3278 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3279 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3280 VOP_UNLOCK(vp, 0, td);
3281 vn_finished_write(mp);
3282 mac_destroy_temp(&intlabel);
3283 break;
3284 case DTYPE_PIPE:
3285 pipe = (struct pipe *)fp->f_data;
3286 PIPE_LOCK(pipe);
3287 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel);
3288 PIPE_UNLOCK(pipe);
3289 break;
3290 default:
3291 error = EINVAL;
3292 }
3293
3294out2:
3295 fdrop(fp, td);
3296out1:
3297 mtx_unlock(&Giant);
3298 return (error);
3299}
3300
3301/*
3302 * MPSAFE
3303 */
3304int
3305__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3306{
3307 struct nameidata nd;
3308 struct mac extmac;
3309 struct label intlabel;
3310 struct mount *mp;
3311 int error;
3312
3313 mtx_lock(&Giant);
3314
3315 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3316 if (error)
3317 goto out;
3318
3319 error = mac_internalize(&intlabel, &extmac);
3320 if (error)
3321 goto out;
3322
3323 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3324 SCARG(uap, path_p), td);
3325 error = namei(&nd);
3326 if (error)
3327 goto out2;
3328 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3329 if (error)
3330 goto out2;
3331
3332 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred);
3333
3334 vn_finished_write(mp);
3335out2:
3336 mac_destroy_temp(&intlabel);
3337 NDFREE(&nd, 0);
3338out:
3339 mtx_unlock(&Giant);
3340 return (error);
3341}
3342
3343int
3344mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3345{
3346 struct mac_policy_conf *mpc;
3347 char target[MAC_MAX_POLICY_NAME];
3348 int error;
3349
3350 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3351 if (error)
3352 return (error);
3353
3354 error = ENOSYS;
3355 MAC_POLICY_LIST_BUSY();
3356 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3357 if (strcmp(mpc->mpc_name, target) == 0 &&
3358 mpc->mpc_ops->mpo_syscall != NULL) {
3359 error = mpc->mpc_ops->mpo_syscall(td,
3360 SCARG(uap, call), SCARG(uap, arg));
3361 goto out;
3362 }
3363 }
3364
3365out:
3366 MAC_POLICY_LIST_UNBUSY();
3367 return (error);
3368}
3369
3370SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3371SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3372
3373#else /* !MAC */
3374
3375int
3376__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3377{
3378
3379 return (ENOSYS);
3380}
3381
3382int
3383__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3384{
3385
3386 return (ENOSYS);
3387}
3388
3389int
3390__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3391{
3392
3393 return (ENOSYS);
3394}
3395
3396int
3397__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3398{
3399
3400 return (ENOSYS);
3401}
3402
3403int
3404__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3405{
3406
3407 return (ENOSYS);
3408}
3409
3410int
3411__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3412{
3413
3414 return (ENOSYS);
3415}
3416
3417int
3418mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3419{
3420
3421 return (ENOSYS);
3422}
3423
3424#endif /* !MAC */