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