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