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