Deleted Added
full compact
mac_pipe.c (105717) mac_pipe.c (105959)
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_pipe.c 105717 2002-10-22 15:53:43Z rwatson $
39 * $FreeBSD: head/sys/security/mac/mac_pipe.c 105959 2002-10-25 20:45:27Z rwatson $
40 */
41/*
42 * Developed by the TrustedBSD Project.
43 *
44 * Framework for extensible kernel access control. Kernel and userland
45 * interface to the framework, policy registration and composition.
46 */
47
48#include "opt_mac.h"
49#include "opt_devfs.h"
50
51#include <sys/param.h>
52#include <sys/extattr.h>
53#include <sys/kernel.h>
54#include <sys/lock.h>
55#include <sys/malloc.h>
56#include <sys/mutex.h>
57#include <sys/mac.h>
58#include <sys/module.h>
59#include <sys/proc.h>
60#include <sys/systm.h>
61#include <sys/sysproto.h>
62#include <sys/sysent.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/file.h>
66#include <sys/namei.h>
67#include <sys/socket.h>
68#include <sys/pipe.h>
69#include <sys/socketvar.h>
70#include <sys/sysctl.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76
77#include <sys/mac_policy.h>
78
79#include <fs/devfs/devfs.h>
80
81#include <net/bpfdesc.h>
82#include <net/if.h>
83#include <net/if_var.h>
84
85#include <netinet/in.h>
86#include <netinet/ip_var.h>
87
88#ifdef MAC
89
90/*
91 * Declare that the kernel provides MAC support, version 1. This permits
92 * modules to refuse to be loaded if the necessary support isn't present,
93 * even if it's pre-boot.
94 */
95MODULE_VERSION(kernel_mac_support, 1);
96
97SYSCTL_DECL(_security);
98
99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100 "TrustedBSD MAC policy controls");
101
102#if MAC_MAX_POLICIES > 32
103#error "MAC_MAX_POLICIES too large"
104#endif
105
106static unsigned int mac_max_policies = MAC_MAX_POLICIES;
107static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
108SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
109 &mac_max_policies, 0, "");
110
40 */
41/*
42 * Developed by the TrustedBSD Project.
43 *
44 * Framework for extensible kernel access control. Kernel and userland
45 * interface to the framework, policy registration and composition.
46 */
47
48#include "opt_mac.h"
49#include "opt_devfs.h"
50
51#include <sys/param.h>
52#include <sys/extattr.h>
53#include <sys/kernel.h>
54#include <sys/lock.h>
55#include <sys/malloc.h>
56#include <sys/mutex.h>
57#include <sys/mac.h>
58#include <sys/module.h>
59#include <sys/proc.h>
60#include <sys/systm.h>
61#include <sys/sysproto.h>
62#include <sys/sysent.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/file.h>
66#include <sys/namei.h>
67#include <sys/socket.h>
68#include <sys/pipe.h>
69#include <sys/socketvar.h>
70#include <sys/sysctl.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76
77#include <sys/mac_policy.h>
78
79#include <fs/devfs/devfs.h>
80
81#include <net/bpfdesc.h>
82#include <net/if.h>
83#include <net/if_var.h>
84
85#include <netinet/in.h>
86#include <netinet/ip_var.h>
87
88#ifdef MAC
89
90/*
91 * Declare that the kernel provides MAC support, version 1. This permits
92 * modules to refuse to be loaded if the necessary support isn't present,
93 * even if it's pre-boot.
94 */
95MODULE_VERSION(kernel_mac_support, 1);
96
97SYSCTL_DECL(_security);
98
99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100 "TrustedBSD MAC policy controls");
101
102#if MAC_MAX_POLICIES > 32
103#error "MAC_MAX_POLICIES too large"
104#endif
105
106static unsigned int mac_max_policies = MAC_MAX_POLICIES;
107static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
108SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
109 &mac_max_policies, 0, "");
110
111/*
112 * Has the kernel started generating labeled objects yet? All read/write
113 * access to this variable is serialized during the boot process. Following
114 * the end of serialization, we don't update this flag; no locking.
115 */
111static int mac_late = 0;
112
113static int mac_enforce_fs = 1;
114SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
115 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
116TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
117
118static int mac_enforce_network = 1;
119SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
120 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
121TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
122
123static int mac_enforce_pipe = 1;
124SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
125 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
126TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
127
128static int mac_enforce_process = 1;
129SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
130 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
131TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
132
133static int mac_enforce_socket = 1;
134SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
135 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
136TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
137
138static int mac_enforce_vm = 1;
139SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
140 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
141TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
142
143static int mac_label_size = sizeof(struct oldmac);
144SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD,
145 &mac_label_size, 0, "Pre-compiled MAC label size");
146
147static int mac_cache_fslabel_in_vnode = 1;
148SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
149 &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
150TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
151 &mac_cache_fslabel_in_vnode);
152
153static int mac_vnode_label_cache_hits = 0;
154SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD,
155 &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels");
156static int mac_vnode_label_cache_misses = 0;
157SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD,
158 &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels");
159
160static int mac_mmap_revocation = 1;
161SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
162 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
163 "relabel");
164static int mac_mmap_revocation_via_cow = 0;
165SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
166 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
167 "copy-on-write semantics, or by removing all write access");
168
169#ifdef MAC_DEBUG
170SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
171 "TrustedBSD MAC debug info");
172
173static int mac_debug_label_fallback = 0;
174SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
175 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
176 "when label is corrupted.");
177TUNABLE_INT("security.mac.debug_label_fallback",
178 &mac_debug_label_fallback);
179
180SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
181 "TrustedBSD MAC object counters");
182
183static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
184 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
185 nmacipqs, nmacpipes;
186
187SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
188 &nmacmbufs, 0, "number of mbufs in use");
189SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
190 &nmaccreds, 0, "number of ucreds in use");
191SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
192 &nmacifnets, 0, "number of ifnets in use");
193SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
194 &nmacipqs, 0, "number of ipqs in use");
195SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
196 &nmacbpfdescs, 0, "number of bpfdescs in use");
197SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
198 &nmacsockets, 0, "number of sockets in use");
199SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
200 &nmacpipes, 0, "number of pipes in use");
201SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
202 &nmacmounts, 0, "number of mounts in use");
203SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
204 &nmactemp, 0, "number of temporary labels in use");
205SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
206 &nmacvnodes, 0, "number of vnodes in use");
207SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
208 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
209#endif
210
211static int error_select(int error1, int error2);
212static int mac_externalize_vnode_oldmac(struct label *label,
213 struct oldmac *extmac);
214static int mac_policy_register(struct mac_policy_conf *mpc);
215static int mac_policy_unregister(struct mac_policy_conf *mpc);
216
217static int mac_stdcreatevnode_ea(struct vnode *vp);
218static void mac_check_vnode_mmap_downgrade(struct ucred *cred,
219 struct vnode *vp, int *prot);
220static void mac_cred_mmapped_drop_perms_recurse(struct thread *td,
221 struct ucred *cred, struct vm_map *map);
222
223static void mac_destroy_socket_label(struct label *label);
224
225MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
226MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
227MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
228
229/*
230 * mac_policy_list_lock protects the consistency of 'mac_policy_list',
231 * the linked list of attached policy modules. Read-only consumers of
232 * the list must acquire a shared lock for the duration of their use;
233 * writers must acquire an exclusive lock. Note that for compound
234 * operations, locks should be held for the entire compound operation,
235 * and that this is not yet done for relabel requests.
236 */
237static struct mtx mac_policy_list_lock;
238static LIST_HEAD(, mac_policy_conf) mac_policy_list;
239static int mac_policy_list_busy;
240#define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \
241 "mac_policy_list_lock", NULL, MTX_DEF);
242#define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock);
243#define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock);
244
245#define MAC_POLICY_LIST_BUSY() do { \
246 MAC_POLICY_LIST_LOCK(); \
247 mac_policy_list_busy++; \
248 MAC_POLICY_LIST_UNLOCK(); \
249} while (0)
250
251#define MAC_POLICY_LIST_UNBUSY() do { \
252 MAC_POLICY_LIST_LOCK(); \
253 mac_policy_list_busy--; \
254 if (mac_policy_list_busy < 0) \
255 panic("Extra mac_policy_list_busy--"); \
256 MAC_POLICY_LIST_UNLOCK(); \
257} while (0)
258
259/*
260 * MAC_CHECK performs the designated check by walking the policy
261 * module list and checking with each as to how it feels about the
262 * request. Note that it returns its value via 'error' in the scope
263 * of the caller.
264 */
265#define MAC_CHECK(check, args...) do { \
266 struct mac_policy_conf *mpc; \
267 \
268 error = 0; \
269 MAC_POLICY_LIST_BUSY(); \
270 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
271 if (mpc->mpc_ops->mpo_ ## check != NULL) \
272 error = error_select( \
273 mpc->mpc_ops->mpo_ ## check (args), \
274 error); \
275 } \
276 MAC_POLICY_LIST_UNBUSY(); \
277} while (0)
278
279/*
280 * MAC_BOOLEAN performs the designated boolean composition by walking
281 * the module list, invoking each instance of the operation, and
282 * combining the results using the passed C operator. Note that it
283 * returns its value via 'result' in the scope of the caller, which
284 * should be initialized by the caller in a meaningful way to get
285 * a meaningful result.
286 */
287#define MAC_BOOLEAN(operation, composition, args...) do { \
288 struct mac_policy_conf *mpc; \
289 \
290 MAC_POLICY_LIST_BUSY(); \
291 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
292 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
293 result = result composition \
294 mpc->mpc_ops->mpo_ ## operation (args); \
295 } \
296 MAC_POLICY_LIST_UNBUSY(); \
297} while (0)
298
299#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \
300 outbuflen) do { \
301 char *curptr, *curptr_start, *element_name, *element_temp; \
302 size_t left, left_start, len; \
303 int claimed, first, first_start, ignorenotfound; \
304 \
305 error = 0; \
306 element_temp = elementlist; \
307 curptr = outbuf; \
308 curptr[0] = '\0'; \
309 left = outbuflen; \
310 first = 1; \
311 while ((element_name = strsep(&element_temp, ",")) != NULL) { \
312 curptr_start = curptr; \
313 left_start = left; \
314 first_start = first; \
315 if (element_name[0] == '?') { \
316 element_name++; \
317 ignorenotfound = 1; \
318 } else \
319 ignorenotfound = 0; \
320 claimed = 0; \
321 if (first) { \
322 len = snprintf(curptr, left, "%s/", \
323 element_name); \
324 first = 0; \
325 } else \
326 len = snprintf(curptr, left, ",%s/", \
327 element_name); \
328 if (len >= left) { \
329 error = EINVAL; /* XXXMAC: E2BIG */ \
330 break; \
331 } \
332 curptr += len; \
333 left -= len; \
334 \
335 MAC_CHECK(externalize_ ## type, label, element_name, \
336 curptr, left, &len, &claimed); \
337 if (error) \
338 break; \
339 if (claimed == 1) { \
340 if (len >= outbuflen) { \
341 error = EINVAL; /* XXXMAC: E2BIG */ \
342 break; \
343 } \
344 curptr += len; \
345 left -= len; \
346 } else if (claimed == 0 && ignorenotfound) { \
347 /* \
348 * Revert addition of the label element \
349 * name. \
350 */ \
351 curptr = curptr_start; \
352 *curptr = '\0'; \
353 left = left_start; \
354 first = first_start; \
355 } else { \
356 error = EINVAL; /* XXXMAC: ENOLABEL */ \
357 break; \
358 } \
359 } \
360} while (0)
361
362#define MAC_INTERNALIZE(type, label, instring) do { \
363 char *element, *element_name, *element_data; \
364 int claimed; \
365 \
366 error = 0; \
367 element = instring; \
368 while ((element_name = strsep(&element, ",")) != NULL) { \
369 element_data = element_name; \
370 element_name = strsep(&element_data, "/"); \
371 if (element_data == NULL) { \
372 error = EINVAL; \
373 break; \
374 } \
375 claimed = 0; \
376 MAC_CHECK(internalize_ ## type, label, element_name, \
377 element_data, &claimed); \
378 if (error) \
379 break; \
380 if (claimed != 1) { \
381 /* XXXMAC: Another error here? */ \
382 error = EINVAL; \
383 break; \
384 } \
385 } \
386} while (0)
387
388/*
389 * MAC_PERFORM performs the designated operation by walking the policy
390 * module list and invoking that operation for each policy.
391 */
392#define MAC_PERFORM(operation, args...) do { \
393 struct mac_policy_conf *mpc; \
394 \
395 MAC_POLICY_LIST_BUSY(); \
396 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
397 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
398 mpc->mpc_ops->mpo_ ## operation (args); \
399 } \
400 MAC_POLICY_LIST_UNBUSY(); \
401} while (0)
402
403/*
404 * Initialize the MAC subsystem, including appropriate SMP locks.
405 */
406static void
407mac_init(void)
408{
409
410 LIST_INIT(&mac_policy_list);
411 MAC_POLICY_LIST_LOCKINIT();
412}
413
414/*
415 * For the purposes of modules that want to know if they were loaded
416 * "early", set the mac_late flag once we've processed modules either
417 * linked into the kernel, or loaded before the kernel startup.
418 */
419static void
420mac_late_init(void)
421{
422
423 mac_late = 1;
424}
425
426/*
427 * Allow MAC policy modules to register during boot, etc.
428 */
429int
430mac_policy_modevent(module_t mod, int type, void *data)
431{
432 struct mac_policy_conf *mpc;
433 int error;
434
435 error = 0;
436 mpc = (struct mac_policy_conf *) data;
437
438 switch (type) {
439 case MOD_LOAD:
440 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
441 mac_late) {
442 printf("mac_policy_modevent: can't load %s policy "
443 "after booting\n", mpc->mpc_name);
444 error = EBUSY;
445 break;
446 }
447 error = mac_policy_register(mpc);
448 break;
449 case MOD_UNLOAD:
450 /* Don't unregister the module if it was never registered. */
451 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
452 != 0)
453 error = mac_policy_unregister(mpc);
454 else
455 error = 0;
456 break;
457 default:
458 break;
459 }
460
461 return (error);
462}
463
464static int
465mac_policy_register(struct mac_policy_conf *mpc)
466{
467 struct mac_policy_conf *tmpc;
468 struct mac_policy_op_entry *mpe;
469 int slot;
470
471 MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops),
472 M_MACOPVEC, M_WAITOK | M_ZERO);
473 for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
474 switch (mpe->mpe_constant) {
475 case MAC_OP_LAST:
476 /*
477 * Doesn't actually happen, but this allows checking
478 * that all enumerated values are handled.
479 */
480 break;
481 case MAC_DESTROY:
482 mpc->mpc_ops->mpo_destroy =
483 mpe->mpe_function;
484 break;
485 case MAC_INIT:
486 mpc->mpc_ops->mpo_init =
487 mpe->mpe_function;
488 break;
489 case MAC_SYSCALL:
490 mpc->mpc_ops->mpo_syscall =
491 mpe->mpe_function;
492 break;
493 case MAC_INIT_BPFDESC_LABEL:
494 mpc->mpc_ops->mpo_init_bpfdesc_label =
495 mpe->mpe_function;
496 break;
497 case MAC_INIT_CRED_LABEL:
498 mpc->mpc_ops->mpo_init_cred_label =
499 mpe->mpe_function;
500 break;
501 case MAC_INIT_DEVFSDIRENT_LABEL:
502 mpc->mpc_ops->mpo_init_devfsdirent_label =
503 mpe->mpe_function;
504 break;
505 case MAC_INIT_IFNET_LABEL:
506 mpc->mpc_ops->mpo_init_ifnet_label =
507 mpe->mpe_function;
508 break;
509 case MAC_INIT_IPQ_LABEL:
510 mpc->mpc_ops->mpo_init_ipq_label =
511 mpe->mpe_function;
512 break;
513 case MAC_INIT_MBUF_LABEL:
514 mpc->mpc_ops->mpo_init_mbuf_label =
515 mpe->mpe_function;
516 break;
517 case MAC_INIT_MOUNT_LABEL:
518 mpc->mpc_ops->mpo_init_mount_label =
519 mpe->mpe_function;
520 break;
521 case MAC_INIT_MOUNT_FS_LABEL:
522 mpc->mpc_ops->mpo_init_mount_fs_label =
523 mpe->mpe_function;
524 break;
525 case MAC_INIT_PIPE_LABEL:
526 mpc->mpc_ops->mpo_init_pipe_label =
527 mpe->mpe_function;
528 break;
529 case MAC_INIT_SOCKET_LABEL:
530 mpc->mpc_ops->mpo_init_socket_label =
531 mpe->mpe_function;
532 break;
533 case MAC_INIT_SOCKET_PEER_LABEL:
534 mpc->mpc_ops->mpo_init_socket_peer_label =
535 mpe->mpe_function;
536 break;
537 case MAC_INIT_VNODE_LABEL:
538 mpc->mpc_ops->mpo_init_vnode_label =
539 mpe->mpe_function;
540 break;
541 case MAC_DESTROY_BPFDESC_LABEL:
542 mpc->mpc_ops->mpo_destroy_bpfdesc_label =
543 mpe->mpe_function;
544 break;
545 case MAC_DESTROY_CRED_LABEL:
546 mpc->mpc_ops->mpo_destroy_cred_label =
547 mpe->mpe_function;
548 break;
549 case MAC_DESTROY_DEVFSDIRENT_LABEL:
550 mpc->mpc_ops->mpo_destroy_devfsdirent_label =
551 mpe->mpe_function;
552 break;
553 case MAC_DESTROY_IFNET_LABEL:
554 mpc->mpc_ops->mpo_destroy_ifnet_label =
555 mpe->mpe_function;
556 break;
557 case MAC_DESTROY_IPQ_LABEL:
558 mpc->mpc_ops->mpo_destroy_ipq_label =
559 mpe->mpe_function;
560 break;
561 case MAC_DESTROY_MBUF_LABEL:
562 mpc->mpc_ops->mpo_destroy_mbuf_label =
563 mpe->mpe_function;
564 break;
565 case MAC_DESTROY_MOUNT_LABEL:
566 mpc->mpc_ops->mpo_destroy_mount_label =
567 mpe->mpe_function;
568 break;
569 case MAC_DESTROY_MOUNT_FS_LABEL:
570 mpc->mpc_ops->mpo_destroy_mount_fs_label =
571 mpe->mpe_function;
572 break;
573 case MAC_DESTROY_PIPE_LABEL:
574 mpc->mpc_ops->mpo_destroy_pipe_label =
575 mpe->mpe_function;
576 break;
577 case MAC_DESTROY_SOCKET_LABEL:
578 mpc->mpc_ops->mpo_destroy_socket_label =
579 mpe->mpe_function;
580 break;
581 case MAC_DESTROY_SOCKET_PEER_LABEL:
582 mpc->mpc_ops->mpo_destroy_socket_peer_label =
583 mpe->mpe_function;
584 break;
585 case MAC_DESTROY_VNODE_LABEL:
586 mpc->mpc_ops->mpo_destroy_vnode_label =
587 mpe->mpe_function;
588 break;
589 case MAC_COPY_PIPE_LABEL:
590 mpc->mpc_ops->mpo_copy_pipe_label =
591 mpe->mpe_function;
592 break;
593 case MAC_COPY_VNODE_LABEL:
594 mpc->mpc_ops->mpo_copy_vnode_label =
595 mpe->mpe_function;
596 break;
597 case MAC_EXTERNALIZE_CRED_LABEL:
598 mpc->mpc_ops->mpo_externalize_cred_label =
599 mpe->mpe_function;
600 break;
601 case MAC_EXTERNALIZE_IFNET_LABEL:
602 mpc->mpc_ops->mpo_externalize_ifnet_label =
603 mpe->mpe_function;
604 break;
605 case MAC_EXTERNALIZE_PIPE_LABEL:
606 mpc->mpc_ops->mpo_externalize_pipe_label =
607 mpe->mpe_function;
608 break;
609 case MAC_EXTERNALIZE_SOCKET_LABEL:
610 mpc->mpc_ops->mpo_externalize_socket_label =
611 mpe->mpe_function;
612 break;
613 case MAC_EXTERNALIZE_SOCKET_PEER_LABEL:
614 mpc->mpc_ops->mpo_externalize_socket_peer_label =
615 mpe->mpe_function;
616 break;
617 case MAC_EXTERNALIZE_VNODE_LABEL:
618 mpc->mpc_ops->mpo_externalize_vnode_label =
619 mpe->mpe_function;
620 break;
621 case MAC_EXTERNALIZE_VNODE_OLDMAC:
622 mpc->mpc_ops->mpo_externalize_vnode_oldmac =
623 mpe->mpe_function;
624 break;
625 case MAC_INTERNALIZE_CRED_LABEL:
626 mpc->mpc_ops->mpo_internalize_cred_label =
627 mpe->mpe_function;
628 break;
629 case MAC_INTERNALIZE_IFNET_LABEL:
630 mpc->mpc_ops->mpo_internalize_ifnet_label =
631 mpe->mpe_function;
632 break;
633 case MAC_INTERNALIZE_PIPE_LABEL:
634 mpc->mpc_ops->mpo_internalize_pipe_label =
635 mpe->mpe_function;
636 break;
637 case MAC_INTERNALIZE_SOCKET_LABEL:
638 mpc->mpc_ops->mpo_internalize_socket_label =
639 mpe->mpe_function;
640 break;
641 case MAC_INTERNALIZE_VNODE_LABEL:
642 mpc->mpc_ops->mpo_internalize_vnode_label =
643 mpe->mpe_function;
644 break;
645 case MAC_CREATE_DEVFS_DEVICE:
646 mpc->mpc_ops->mpo_create_devfs_device =
647 mpe->mpe_function;
648 break;
649 case MAC_CREATE_DEVFS_DIRECTORY:
650 mpc->mpc_ops->mpo_create_devfs_directory =
651 mpe->mpe_function;
652 break;
653 case MAC_CREATE_DEVFS_SYMLINK:
654 mpc->mpc_ops->mpo_create_devfs_symlink =
655 mpe->mpe_function;
656 break;
657 case MAC_CREATE_DEVFS_VNODE:
658 mpc->mpc_ops->mpo_create_devfs_vnode =
659 mpe->mpe_function;
660 break;
661 case MAC_STDCREATEVNODE_EA:
662 mpc->mpc_ops->mpo_stdcreatevnode_ea =
663 mpe->mpe_function;
664 break;
665 case MAC_CREATE_VNODE:
666 mpc->mpc_ops->mpo_create_vnode =
667 mpe->mpe_function;
668 break;
669 case MAC_CREATE_MOUNT:
670 mpc->mpc_ops->mpo_create_mount =
671 mpe->mpe_function;
672 break;
673 case MAC_CREATE_ROOT_MOUNT:
674 mpc->mpc_ops->mpo_create_root_mount =
675 mpe->mpe_function;
676 break;
677 case MAC_RELABEL_VNODE:
678 mpc->mpc_ops->mpo_relabel_vnode =
679 mpe->mpe_function;
680 break;
681 case MAC_UPDATE_DEVFSDIRENT:
682 mpc->mpc_ops->mpo_update_devfsdirent =
683 mpe->mpe_function;
684 break;
685 case MAC_UPDATE_PROCFSVNODE:
686 mpc->mpc_ops->mpo_update_procfsvnode =
687 mpe->mpe_function;
688 break;
689 case MAC_UPDATE_VNODE_FROM_EXTATTR:
690 mpc->mpc_ops->mpo_update_vnode_from_extattr =
691 mpe->mpe_function;
692 break;
693 case MAC_UPDATE_VNODE_FROM_EXTERNALIZED:
694 mpc->mpc_ops->mpo_update_vnode_from_externalized =
695 mpe->mpe_function;
696 break;
697 case MAC_UPDATE_VNODE_FROM_MOUNT:
698 mpc->mpc_ops->mpo_update_vnode_from_mount =
699 mpe->mpe_function;
700 break;
701 case MAC_CREATE_MBUF_FROM_SOCKET:
702 mpc->mpc_ops->mpo_create_mbuf_from_socket =
703 mpe->mpe_function;
704 break;
705 case MAC_CREATE_PIPE:
706 mpc->mpc_ops->mpo_create_pipe =
707 mpe->mpe_function;
708 break;
709 case MAC_CREATE_SOCKET:
710 mpc->mpc_ops->mpo_create_socket =
711 mpe->mpe_function;
712 break;
713 case MAC_CREATE_SOCKET_FROM_SOCKET:
714 mpc->mpc_ops->mpo_create_socket_from_socket =
715 mpe->mpe_function;
716 break;
717 case MAC_RELABEL_PIPE:
718 mpc->mpc_ops->mpo_relabel_pipe =
719 mpe->mpe_function;
720 break;
721 case MAC_RELABEL_SOCKET:
722 mpc->mpc_ops->mpo_relabel_socket =
723 mpe->mpe_function;
724 break;
725 case MAC_SET_SOCKET_PEER_FROM_MBUF:
726 mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
727 mpe->mpe_function;
728 break;
729 case MAC_SET_SOCKET_PEER_FROM_SOCKET:
730 mpc->mpc_ops->mpo_set_socket_peer_from_socket =
731 mpe->mpe_function;
732 break;
733 case MAC_CREATE_BPFDESC:
734 mpc->mpc_ops->mpo_create_bpfdesc =
735 mpe->mpe_function;
736 break;
737 case MAC_CREATE_DATAGRAM_FROM_IPQ:
738 mpc->mpc_ops->mpo_create_datagram_from_ipq =
739 mpe->mpe_function;
740 break;
741 case MAC_CREATE_FRAGMENT:
742 mpc->mpc_ops->mpo_create_fragment =
743 mpe->mpe_function;
744 break;
745 case MAC_CREATE_IFNET:
746 mpc->mpc_ops->mpo_create_ifnet =
747 mpe->mpe_function;
748 break;
749 case MAC_CREATE_IPQ:
750 mpc->mpc_ops->mpo_create_ipq =
751 mpe->mpe_function;
752 break;
753 case MAC_CREATE_MBUF_FROM_MBUF:
754 mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
755 mpe->mpe_function;
756 break;
757 case MAC_CREATE_MBUF_LINKLAYER:
758 mpc->mpc_ops->mpo_create_mbuf_linklayer =
759 mpe->mpe_function;
760 break;
761 case MAC_CREATE_MBUF_FROM_BPFDESC:
762 mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
763 mpe->mpe_function;
764 break;
765 case MAC_CREATE_MBUF_FROM_IFNET:
766 mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
767 mpe->mpe_function;
768 break;
769 case MAC_CREATE_MBUF_MULTICAST_ENCAP:
770 mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
771 mpe->mpe_function;
772 break;
773 case MAC_CREATE_MBUF_NETLAYER:
774 mpc->mpc_ops->mpo_create_mbuf_netlayer =
775 mpe->mpe_function;
776 break;
777 case MAC_FRAGMENT_MATCH:
778 mpc->mpc_ops->mpo_fragment_match =
779 mpe->mpe_function;
780 break;
781 case MAC_RELABEL_IFNET:
782 mpc->mpc_ops->mpo_relabel_ifnet =
783 mpe->mpe_function;
784 break;
785 case MAC_UPDATE_IPQ:
786 mpc->mpc_ops->mpo_update_ipq =
787 mpe->mpe_function;
788 break;
789 case MAC_CREATE_CRED:
790 mpc->mpc_ops->mpo_create_cred =
791 mpe->mpe_function;
792 break;
793 case MAC_EXECVE_TRANSITION:
794 mpc->mpc_ops->mpo_execve_transition =
795 mpe->mpe_function;
796 break;
797 case MAC_EXECVE_WILL_TRANSITION:
798 mpc->mpc_ops->mpo_execve_will_transition =
799 mpe->mpe_function;
800 break;
801 case MAC_CREATE_PROC0:
802 mpc->mpc_ops->mpo_create_proc0 =
803 mpe->mpe_function;
804 break;
805 case MAC_CREATE_PROC1:
806 mpc->mpc_ops->mpo_create_proc1 =
807 mpe->mpe_function;
808 break;
809 case MAC_RELABEL_CRED:
810 mpc->mpc_ops->mpo_relabel_cred =
811 mpe->mpe_function;
812 break;
813 case MAC_THREAD_USERRET:
814 mpc->mpc_ops->mpo_thread_userret =
815 mpe->mpe_function;
816 break;
817 case MAC_CHECK_BPFDESC_RECEIVE:
818 mpc->mpc_ops->mpo_check_bpfdesc_receive =
819 mpe->mpe_function;
820 break;
821 case MAC_CHECK_CRED_RELABEL:
822 mpc->mpc_ops->mpo_check_cred_relabel =
823 mpe->mpe_function;
824 break;
825 case MAC_CHECK_CRED_VISIBLE:
826 mpc->mpc_ops->mpo_check_cred_visible =
827 mpe->mpe_function;
828 break;
829 case MAC_CHECK_IFNET_RELABEL:
830 mpc->mpc_ops->mpo_check_ifnet_relabel =
831 mpe->mpe_function;
832 break;
833 case MAC_CHECK_IFNET_TRANSMIT:
834 mpc->mpc_ops->mpo_check_ifnet_transmit =
835 mpe->mpe_function;
836 break;
837 case MAC_CHECK_MOUNT_STAT:
838 mpc->mpc_ops->mpo_check_mount_stat =
839 mpe->mpe_function;
840 break;
841 case MAC_CHECK_PIPE_IOCTL:
842 mpc->mpc_ops->mpo_check_pipe_ioctl =
843 mpe->mpe_function;
844 break;
845 case MAC_CHECK_PIPE_POLL:
846 mpc->mpc_ops->mpo_check_pipe_poll =
847 mpe->mpe_function;
848 break;
849 case MAC_CHECK_PIPE_READ:
850 mpc->mpc_ops->mpo_check_pipe_read =
851 mpe->mpe_function;
852 break;
853 case MAC_CHECK_PIPE_RELABEL:
854 mpc->mpc_ops->mpo_check_pipe_relabel =
855 mpe->mpe_function;
856 break;
857 case MAC_CHECK_PIPE_STAT:
858 mpc->mpc_ops->mpo_check_pipe_stat =
859 mpe->mpe_function;
860 break;
861 case MAC_CHECK_PIPE_WRITE:
862 mpc->mpc_ops->mpo_check_pipe_write =
863 mpe->mpe_function;
864 break;
865 case MAC_CHECK_PROC_DEBUG:
866 mpc->mpc_ops->mpo_check_proc_debug =
867 mpe->mpe_function;
868 break;
869 case MAC_CHECK_PROC_SCHED:
870 mpc->mpc_ops->mpo_check_proc_sched =
871 mpe->mpe_function;
872 break;
873 case MAC_CHECK_PROC_SIGNAL:
874 mpc->mpc_ops->mpo_check_proc_signal =
875 mpe->mpe_function;
876 break;
877 case MAC_CHECK_SOCKET_BIND:
878 mpc->mpc_ops->mpo_check_socket_bind =
879 mpe->mpe_function;
880 break;
881 case MAC_CHECK_SOCKET_CONNECT:
882 mpc->mpc_ops->mpo_check_socket_connect =
883 mpe->mpe_function;
884 break;
885 case MAC_CHECK_SOCKET_DELIVER:
886 mpc->mpc_ops->mpo_check_socket_deliver =
887 mpe->mpe_function;
888 break;
889 case MAC_CHECK_SOCKET_LISTEN:
890 mpc->mpc_ops->mpo_check_socket_listen =
891 mpe->mpe_function;
892 break;
893 case MAC_CHECK_SOCKET_RECEIVE:
894 mpc->mpc_ops->mpo_check_socket_receive =
895 mpe->mpe_function;
896 break;
897 case MAC_CHECK_SOCKET_RELABEL:
898 mpc->mpc_ops->mpo_check_socket_relabel =
899 mpe->mpe_function;
900 break;
901 case MAC_CHECK_SOCKET_SEND:
902 mpc->mpc_ops->mpo_check_socket_send =
903 mpe->mpe_function;
904 break;
905 case MAC_CHECK_SOCKET_VISIBLE:
906 mpc->mpc_ops->mpo_check_socket_visible =
907 mpe->mpe_function;
908 break;
909 case MAC_CHECK_VNODE_ACCESS:
910 mpc->mpc_ops->mpo_check_vnode_access =
911 mpe->mpe_function;
912 break;
913 case MAC_CHECK_VNODE_CHDIR:
914 mpc->mpc_ops->mpo_check_vnode_chdir =
915 mpe->mpe_function;
916 break;
917 case MAC_CHECK_VNODE_CHROOT:
918 mpc->mpc_ops->mpo_check_vnode_chroot =
919 mpe->mpe_function;
920 break;
921 case MAC_CHECK_VNODE_CREATE:
922 mpc->mpc_ops->mpo_check_vnode_create =
923 mpe->mpe_function;
924 break;
925 case MAC_CHECK_VNODE_DELETE:
926 mpc->mpc_ops->mpo_check_vnode_delete =
927 mpe->mpe_function;
928 break;
929 case MAC_CHECK_VNODE_DELETEACL:
930 mpc->mpc_ops->mpo_check_vnode_deleteacl =
931 mpe->mpe_function;
932 break;
933 case MAC_CHECK_VNODE_EXEC:
934 mpc->mpc_ops->mpo_check_vnode_exec =
935 mpe->mpe_function;
936 break;
937 case MAC_CHECK_VNODE_GETACL:
938 mpc->mpc_ops->mpo_check_vnode_getacl =
939 mpe->mpe_function;
940 break;
941 case MAC_CHECK_VNODE_GETEXTATTR:
942 mpc->mpc_ops->mpo_check_vnode_getextattr =
943 mpe->mpe_function;
944 break;
945 case MAC_CHECK_VNODE_LINK:
946 mpc->mpc_ops->mpo_check_vnode_link =
947 mpe->mpe_function;
948 break;
949 case MAC_CHECK_VNODE_LOOKUP:
950 mpc->mpc_ops->mpo_check_vnode_lookup =
951 mpe->mpe_function;
952 break;
953 case MAC_CHECK_VNODE_MMAP:
954 mpc->mpc_ops->mpo_check_vnode_mmap =
955 mpe->mpe_function;
956 break;
957 case MAC_CHECK_VNODE_MMAP_DOWNGRADE:
958 mpc->mpc_ops->mpo_check_vnode_mmap_downgrade =
959 mpe->mpe_function;
960 break;
961 case MAC_CHECK_VNODE_MPROTECT:
962 mpc->mpc_ops->mpo_check_vnode_mprotect =
963 mpe->mpe_function;
964 break;
965 case MAC_CHECK_VNODE_OPEN:
966 mpc->mpc_ops->mpo_check_vnode_open =
967 mpe->mpe_function;
968 break;
969 case MAC_CHECK_VNODE_POLL:
970 mpc->mpc_ops->mpo_check_vnode_poll =
971 mpe->mpe_function;
972 break;
973 case MAC_CHECK_VNODE_READ:
974 mpc->mpc_ops->mpo_check_vnode_read =
975 mpe->mpe_function;
976 break;
977 case MAC_CHECK_VNODE_READDIR:
978 mpc->mpc_ops->mpo_check_vnode_readdir =
979 mpe->mpe_function;
980 break;
981 case MAC_CHECK_VNODE_READLINK:
982 mpc->mpc_ops->mpo_check_vnode_readlink =
983 mpe->mpe_function;
984 break;
985 case MAC_CHECK_VNODE_RELABEL:
986 mpc->mpc_ops->mpo_check_vnode_relabel =
987 mpe->mpe_function;
988 break;
989 case MAC_CHECK_VNODE_RENAME_FROM:
990 mpc->mpc_ops->mpo_check_vnode_rename_from =
991 mpe->mpe_function;
992 break;
993 case MAC_CHECK_VNODE_RENAME_TO:
994 mpc->mpc_ops->mpo_check_vnode_rename_to =
995 mpe->mpe_function;
996 break;
997 case MAC_CHECK_VNODE_REVOKE:
998 mpc->mpc_ops->mpo_check_vnode_revoke =
999 mpe->mpe_function;
1000 break;
1001 case MAC_CHECK_VNODE_SETACL:
1002 mpc->mpc_ops->mpo_check_vnode_setacl =
1003 mpe->mpe_function;
1004 break;
1005 case MAC_CHECK_VNODE_SETEXTATTR:
1006 mpc->mpc_ops->mpo_check_vnode_setextattr =
1007 mpe->mpe_function;
1008 break;
1009 case MAC_CHECK_VNODE_SETFLAGS:
1010 mpc->mpc_ops->mpo_check_vnode_setflags =
1011 mpe->mpe_function;
1012 break;
1013 case MAC_CHECK_VNODE_SETMODE:
1014 mpc->mpc_ops->mpo_check_vnode_setmode =
1015 mpe->mpe_function;
1016 break;
1017 case MAC_CHECK_VNODE_SETOWNER:
1018 mpc->mpc_ops->mpo_check_vnode_setowner =
1019 mpe->mpe_function;
1020 break;
1021 case MAC_CHECK_VNODE_SETUTIMES:
1022 mpc->mpc_ops->mpo_check_vnode_setutimes =
1023 mpe->mpe_function;
1024 break;
1025 case MAC_CHECK_VNODE_STAT:
1026 mpc->mpc_ops->mpo_check_vnode_stat =
1027 mpe->mpe_function;
1028 break;
1029 case MAC_CHECK_VNODE_SWAPON:
1030 mpc->mpc_ops->mpo_check_vnode_swapon =
1031 mpe->mpe_function;
1032 break;
1033 case MAC_CHECK_VNODE_WRITE:
1034 mpc->mpc_ops->mpo_check_vnode_write =
1035 mpe->mpe_function;
1036 break;
1037/*
1038 default:
1039 printf("MAC policy `%s': unknown operation %d\n",
1040 mpc->mpc_name, mpe->mpe_constant);
1041 return (EINVAL);
1042*/
1043 }
1044 }
1045 MAC_POLICY_LIST_LOCK();
1046 if (mac_policy_list_busy > 0) {
1047 MAC_POLICY_LIST_UNLOCK();
1048 FREE(mpc->mpc_ops, M_MACOPVEC);
1049 mpc->mpc_ops = NULL;
1050 return (EBUSY);
1051 }
1052 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
1053 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
1054 MAC_POLICY_LIST_UNLOCK();
1055 FREE(mpc->mpc_ops, M_MACOPVEC);
1056 mpc->mpc_ops = NULL;
1057 return (EEXIST);
1058 }
1059 }
1060 if (mpc->mpc_field_off != NULL) {
1061 slot = ffs(mac_policy_offsets_free);
1062 if (slot == 0) {
1063 MAC_POLICY_LIST_UNLOCK();
1064 FREE(mpc->mpc_ops, M_MACOPVEC);
1065 mpc->mpc_ops = NULL;
1066 return (ENOMEM);
1067 }
1068 slot--;
1069 mac_policy_offsets_free &= ~(1 << slot);
1070 *mpc->mpc_field_off = slot;
1071 }
1072 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
1073 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
1074
1075 /* Per-policy initialization. */
1076 if (mpc->mpc_ops->mpo_init != NULL)
1077 (*(mpc->mpc_ops->mpo_init))(mpc);
1078 MAC_POLICY_LIST_UNLOCK();
1079
1080 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
1081 mpc->mpc_name);
1082
1083 return (0);
1084}
1085
1086static int
1087mac_policy_unregister(struct mac_policy_conf *mpc)
1088{
1089
1090 /*
1091 * If we fail the load, we may get a request to unload. Check
1092 * to see if we did the run-time registration, and if not,
1093 * silently succeed.
1094 */
1095 MAC_POLICY_LIST_LOCK();
1096 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
1097 MAC_POLICY_LIST_UNLOCK();
1098 return (0);
1099 }
1100#if 0
1101 /*
1102 * Don't allow unloading modules with private data.
1103 */
1104 if (mpc->mpc_field_off != NULL) {
1105 MAC_POLICY_LIST_UNLOCK();
1106 return (EBUSY);
1107 }
1108#endif
1109 /*
1110 * Only allow the unload to proceed if the module is unloadable
1111 * by its own definition.
1112 */
1113 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
1114 MAC_POLICY_LIST_UNLOCK();
1115 return (EBUSY);
1116 }
1117 /*
1118 * Right now, we EBUSY if the list is in use. In the future,
1119 * for reliability reasons, we might want to sleep and wakeup
1120 * later to try again.
1121 */
1122 if (mac_policy_list_busy > 0) {
1123 MAC_POLICY_LIST_UNLOCK();
1124 return (EBUSY);
1125 }
1126 if (mpc->mpc_ops->mpo_destroy != NULL)
1127 (*(mpc->mpc_ops->mpo_destroy))(mpc);
1128
1129 LIST_REMOVE(mpc, mpc_list);
1130 MAC_POLICY_LIST_UNLOCK();
1131
1132 FREE(mpc->mpc_ops, M_MACOPVEC);
1133 mpc->mpc_ops = NULL;
1134 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
1135
1136 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
1137 mpc->mpc_name);
1138
1139 return (0);
1140}
1141
1142/*
1143 * Define an error value precedence, and given two arguments, selects the
1144 * value with the higher precedence.
1145 */
1146static int
1147error_select(int error1, int error2)
1148{
1149
1150 /* Certain decision-making errors take top priority. */
1151 if (error1 == EDEADLK || error2 == EDEADLK)
1152 return (EDEADLK);
1153
1154 /* Invalid arguments should be reported where possible. */
1155 if (error1 == EINVAL || error2 == EINVAL)
1156 return (EINVAL);
1157
1158 /* Precedence goes to "visibility", with both process and file. */
1159 if (error1 == ESRCH || error2 == ESRCH)
1160 return (ESRCH);
1161
1162 if (error1 == ENOENT || error2 == ENOENT)
1163 return (ENOENT);
1164
1165 /* Precedence goes to DAC/MAC protections. */
1166 if (error1 == EACCES || error2 == EACCES)
1167 return (EACCES);
1168
1169 /* Precedence goes to privilege. */
1170 if (error1 == EPERM || error2 == EPERM)
1171 return (EPERM);
1172
1173 /* Precedence goes to error over success; otherwise, arbitrary. */
1174 if (error1 != 0)
1175 return (error1);
1176 return (error2);
1177}
1178
1179static void
1180mac_init_label(struct label *label)
1181{
1182
1183 bzero(label, sizeof(*label));
1184 label->l_flags = MAC_FLAG_INITIALIZED;
1185}
1186
1187static void
1188mac_destroy_label(struct label *label)
1189{
1190
1191 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1192 ("destroying uninitialized label"));
1193
1194 bzero(label, sizeof(*label));
1195 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1196}
1197
1198void
1199mac_init_bpfdesc(struct bpf_d *bpf_d)
1200{
1201
1202 mac_init_label(&bpf_d->bd_label);
1203 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1204#ifdef MAC_DEBUG
1205 atomic_add_int(&nmacbpfdescs, 1);
1206#endif
1207}
1208
1209static void
1210mac_init_cred_label(struct label *label)
1211{
1212
1213 mac_init_label(label);
1214 MAC_PERFORM(init_cred_label, label);
1215#ifdef MAC_DEBUG
1216 atomic_add_int(&nmaccreds, 1);
1217#endif
1218}
1219
1220void
1221mac_init_cred(struct ucred *cred)
1222{
1223
1224 mac_init_cred_label(&cred->cr_label);
1225}
1226
1227void
1228mac_init_devfsdirent(struct devfs_dirent *de)
1229{
1230
1231 mac_init_label(&de->de_label);
1232 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1233#ifdef MAC_DEBUG
1234 atomic_add_int(&nmacdevfsdirents, 1);
1235#endif
1236}
1237
1238static void
1239mac_init_ifnet_label(struct label *label)
1240{
1241
1242 mac_init_label(label);
1243 MAC_PERFORM(init_ifnet_label, label);
1244#ifdef MAC_DEBUG
1245 atomic_add_int(&nmacifnets, 1);
1246#endif
1247}
1248
1249void
1250mac_init_ifnet(struct ifnet *ifp)
1251{
1252
1253 mac_init_ifnet_label(&ifp->if_label);
1254}
1255
1256void
1257mac_init_ipq(struct ipq *ipq)
1258{
1259
1260 mac_init_label(&ipq->ipq_label);
1261 MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1262#ifdef MAC_DEBUG
1263 atomic_add_int(&nmacipqs, 1);
1264#endif
1265}
1266
1267int
1268mac_init_mbuf(struct mbuf *m, int flag)
1269{
1270 int error;
1271
1272 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1273
1274 mac_init_label(&m->m_pkthdr.label);
1275
1276 MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
1277 if (error) {
1278 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1279 mac_destroy_label(&m->m_pkthdr.label);
1280 }
1281
1282#ifdef MAC_DEBUG
1283 if (error == 0)
1284 atomic_add_int(&nmacmbufs, 1);
1285#endif
1286 return (error);
1287}
1288
1289void
1290mac_init_mount(struct mount *mp)
1291{
1292
1293 mac_init_label(&mp->mnt_mntlabel);
1294 mac_init_label(&mp->mnt_fslabel);
1295 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1296 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1297#ifdef MAC_DEBUG
1298 atomic_add_int(&nmacmounts, 1);
1299#endif
1300}
1301
1302static void
1303mac_init_pipe_label(struct label *label)
1304{
1305
1306 mac_init_label(label);
1307 MAC_PERFORM(init_pipe_label, label);
1308#ifdef MAC_DEBUG
1309 atomic_add_int(&nmacpipes, 1);
1310#endif
1311}
1312
1313void
1314mac_init_pipe(struct pipe *pipe)
1315{
1316 struct label *label;
1317
1318 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1319 pipe->pipe_label = label;
1320 pipe->pipe_peer->pipe_label = label;
1321 mac_init_pipe_label(label);
1322}
1323
1324static int
1325mac_init_socket_label(struct label *label, int flag)
1326{
1327 int error;
1328
1329 mac_init_label(label);
1330
1331 MAC_CHECK(init_socket_label, label, flag);
1332 if (error) {
1333 MAC_PERFORM(destroy_socket_label, label);
1334 mac_destroy_label(label);
1335 }
1336
1337#ifdef MAC_DEBUG
1338 if (error == 0)
1339 atomic_add_int(&nmacsockets, 1);
1340#endif
1341
1342 return (error);
1343}
1344
1345static int
1346mac_init_socket_peer_label(struct label *label, int flag)
1347{
1348 int error;
1349
1350 mac_init_label(label);
1351
1352 MAC_CHECK(init_socket_peer_label, label, flag);
1353 if (error) {
1354 MAC_PERFORM(destroy_socket_label, label);
1355 mac_destroy_label(label);
1356 }
1357
1358 return (error);
1359}
1360
1361int
1362mac_init_socket(struct socket *socket, int flag)
1363{
1364 int error;
1365
1366 error = mac_init_socket_label(&socket->so_label, flag);
1367 if (error)
1368 return (error);
1369
1370 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1371 if (error)
1372 mac_destroy_socket_label(&socket->so_label);
1373
1374 return (error);
1375}
1376
1377static void
1378mac_init_vnode_label(struct label *label)
1379{
1380
1381 mac_init_label(label);
1382 MAC_PERFORM(init_vnode_label, label);
1383#ifdef MAC_DEBUG
1384 atomic_add_int(&nmacvnodes, 1);
1385#endif
1386}
1387
1388void
1389mac_init_vnode(struct vnode *vp)
1390{
1391
1392 mac_init_vnode_label(&vp->v_label);
1393}
1394
1395void
1396mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1397{
1398
1399 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1400 mac_destroy_label(&bpf_d->bd_label);
1401#ifdef MAC_DEBUG
1402 atomic_subtract_int(&nmacbpfdescs, 1);
1403#endif
1404}
1405
1406static void
1407mac_destroy_cred_label(struct label *label)
1408{
1409
1410 MAC_PERFORM(destroy_cred_label, label);
1411 mac_destroy_label(label);
1412#ifdef MAC_DEBUG
1413 atomic_subtract_int(&nmaccreds, 1);
1414#endif
1415}
1416
1417void
1418mac_destroy_cred(struct ucred *cred)
1419{
1420
1421 mac_destroy_cred_label(&cred->cr_label);
1422}
1423
1424void
1425mac_destroy_devfsdirent(struct devfs_dirent *de)
1426{
1427
1428 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1429 mac_destroy_label(&de->de_label);
1430#ifdef MAC_DEBUG
1431 atomic_subtract_int(&nmacdevfsdirents, 1);
1432#endif
1433}
1434
1435static void
1436mac_destroy_ifnet_label(struct label *label)
1437{
1438
1439 MAC_PERFORM(destroy_ifnet_label, label);
1440 mac_destroy_label(label);
1441#ifdef MAC_DEBUG
1442 atomic_subtract_int(&nmacifnets, 1);
1443#endif
1444}
1445
1446void
1447mac_destroy_ifnet(struct ifnet *ifp)
1448{
1449
1450 mac_destroy_ifnet_label(&ifp->if_label);
1451}
1452
1453void
1454mac_destroy_ipq(struct ipq *ipq)
1455{
1456
1457 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1458 mac_destroy_label(&ipq->ipq_label);
1459#ifdef MAC_DEBUG
1460 atomic_subtract_int(&nmacipqs, 1);
1461#endif
1462}
1463
1464void
1465mac_destroy_mbuf(struct mbuf *m)
1466{
1467
1468 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1469 mac_destroy_label(&m->m_pkthdr.label);
1470#ifdef MAC_DEBUG
1471 atomic_subtract_int(&nmacmbufs, 1);
1472#endif
1473}
1474
1475void
1476mac_destroy_mount(struct mount *mp)
1477{
1478
1479 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1480 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1481 mac_destroy_label(&mp->mnt_fslabel);
1482 mac_destroy_label(&mp->mnt_mntlabel);
1483#ifdef MAC_DEBUG
1484 atomic_subtract_int(&nmacmounts, 1);
1485#endif
1486}
1487
1488static void
1489mac_destroy_pipe_label(struct label *label)
1490{
1491
1492 MAC_PERFORM(destroy_pipe_label, label);
1493 mac_destroy_label(label);
1494#ifdef MAC_DEBUG
1495 atomic_subtract_int(&nmacpipes, 1);
1496#endif
1497}
1498
1499void
1500mac_destroy_pipe(struct pipe *pipe)
1501{
1502
1503 mac_destroy_pipe_label(pipe->pipe_label);
1504 free(pipe->pipe_label, M_MACPIPELABEL);
1505}
1506
1507static void
1508mac_destroy_socket_label(struct label *label)
1509{
1510
1511 MAC_PERFORM(destroy_socket_label, label);
1512 mac_destroy_label(label);
1513#ifdef MAC_DEBUG
1514 atomic_subtract_int(&nmacsockets, 1);
1515#endif
1516}
1517
1518static void
1519mac_destroy_socket_peer_label(struct label *label)
1520{
1521
1522 MAC_PERFORM(destroy_socket_peer_label, label);
1523 mac_destroy_label(label);
1524}
1525
1526void
1527mac_destroy_socket(struct socket *socket)
1528{
1529
1530 mac_destroy_socket_label(&socket->so_label);
1531 mac_destroy_socket_peer_label(&socket->so_peerlabel);
1532}
1533
1534static void
1535mac_destroy_vnode_label(struct label *label)
1536{
1537
1538 MAC_PERFORM(destroy_vnode_label, label);
1539 mac_destroy_label(label);
1540#ifdef MAC_DEBUG
1541 atomic_subtract_int(&nmacvnodes, 1);
1542#endif
1543}
1544
1545void
1546mac_destroy_vnode(struct vnode *vp)
1547{
1548
1549 mac_destroy_vnode_label(&vp->v_label);
1550}
1551
1552static void
1553mac_copy_pipe_label(struct label *src, struct label *dest)
1554{
1555
1556 MAC_PERFORM(copy_pipe_label, src, dest);
1557}
1558
1559static void
1560mac_copy_vnode_label(struct label *src, struct label *dest)
1561{
1562
1563 MAC_PERFORM(copy_vnode_label, src, dest);
1564}
1565
1566static int
1567mac_check_structmac_consistent(struct mac *mac)
1568{
1569
1570 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1571 return (EINVAL);
1572
1573 return (0);
1574}
1575
1576static int
1577mac_externalize_cred_label(struct label *label, char *elements,
1578 char *outbuf, size_t outbuflen, int flags)
1579{
1580 int error;
1581
1582 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1583
1584 return (error);
1585}
1586
1587static int
1588mac_externalize_ifnet_label(struct label *label, char *elements,
1589 char *outbuf, size_t outbuflen, int flags)
1590{
1591 int error;
1592
1593 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1594
1595 return (error);
1596}
1597
1598static int
1599mac_externalize_pipe_label(struct label *label, char *elements,
1600 char *outbuf, size_t outbuflen, int flags)
1601{
1602 int error;
1603
1604 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1605
1606 return (error);
1607}
1608
1609static int
1610mac_externalize_socket_label(struct label *label, char *elements,
1611 char *outbuf, size_t outbuflen, int flags)
1612{
1613 int error;
1614
1615 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1616
1617 return (error);
1618}
1619
1620static int
1621mac_externalize_socket_peer_label(struct label *label, char *elements,
1622 char *outbuf, size_t outbuflen, int flags)
1623{
1624 int error;
1625
1626 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1627
1628 return (error);
1629}
1630
1631static int
1632mac_externalize_vnode_label(struct label *label, char *elements,
1633 char *outbuf, size_t outbuflen, int flags)
1634{
1635 int error;
1636
1637 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1638
1639 return (error);
1640}
1641
1642static int
1643mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac)
1644{
1645 int error;
1646
1647 MAC_CHECK(externalize_vnode_oldmac, label, extmac);
1648
1649 return (error);
1650}
1651
1652static int
1653mac_internalize_cred_label(struct label *label, char *string)
1654{
1655 int error;
1656
1657 MAC_INTERNALIZE(cred_label, label, string);
1658
1659 return (error);
1660}
1661
1662static int
1663mac_internalize_ifnet_label(struct label *label, char *string)
1664{
1665 int error;
1666
1667 MAC_INTERNALIZE(ifnet_label, label, string);
1668
1669 return (error);
1670}
1671
1672static int
1673mac_internalize_pipe_label(struct label *label, char *string)
1674{
1675 int error;
1676
1677 MAC_INTERNALIZE(pipe_label, label, string);
1678
1679 return (error);
1680}
1681
1682static int
1683mac_internalize_socket_label(struct label *label, char *string)
1684{
1685 int error;
1686
1687 MAC_INTERNALIZE(socket_label, label, string);
1688
1689 return (error);
1690}
1691
1692static int
1693mac_internalize_vnode_label(struct label *label, char *string)
1694{
1695 int error;
1696
1697 MAC_INTERNALIZE(vnode_label, label, string);
1698
1699 return (error);
1700}
1701
1702/*
1703 * Initialize MAC label for the first kernel process, from which other
1704 * kernel processes and threads are spawned.
1705 */
1706void
1707mac_create_proc0(struct ucred *cred)
1708{
1709
1710 MAC_PERFORM(create_proc0, cred);
1711}
1712
1713/*
1714 * Initialize MAC label for the first userland process, from which other
1715 * userland processes and threads are spawned.
1716 */
1717void
1718mac_create_proc1(struct ucred *cred)
1719{
1720
1721 MAC_PERFORM(create_proc1, cred);
1722}
1723
1724void
1725mac_thread_userret(struct thread *td)
1726{
1727
1728 MAC_PERFORM(thread_userret, td);
1729}
1730
1731/*
1732 * When a new process is created, its label must be initialized. Generally,
1733 * this involves inheritence from the parent process, modulo possible
1734 * deltas. This function allows that processing to take place.
1735 */
1736void
1737mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1738{
1739
1740 MAC_PERFORM(create_cred, parent_cred, child_cred);
1741}
1742
1743void
1744mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1745{
1746
1747 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1748}
1749
1750void
1751mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1752{
1753
1754 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1755}
1756
1757/*
1758 * Support callout for policies that manage their own externalization
1759 * using extended attributes.
1760 */
1761static int
1762mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1763{
1764 int error;
1765
1766 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1767 &mp->mnt_fslabel);
1768
1769 return (error);
1770}
1771
1772/*
1773 * Given an externalized mac label, internalize it and stamp it on a
1774 * vnode.
1775 */
1776static int
1777mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac)
1778{
1779 int error;
1780
1781 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1782
1783 return (error);
1784}
1785
1786/*
1787 * Call out to individual policies to update the label in a vnode from
1788 * the mountpoint.
1789 */
1790void
1791mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1792{
1793
1794 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1795 &mp->mnt_fslabel);
1796
1797 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1798 if (mac_cache_fslabel_in_vnode)
1799 vp->v_vflag |= VV_CACHEDLABEL;
1800}
1801
1802/*
1803 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1804 * to store label data. Can be referenced by filesystems supporting
1805 * extended attributes.
1806 */
1807int
1808vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1809{
1810 struct vnode *vp = ap->a_vp;
1811 struct oldmac extmac;
1812 int buflen, error;
1813
1814 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1815
1816 /*
1817 * Call out to external policies first. Order doesn't really
1818 * matter, as long as failure of one assures failure of all.
1819 */
1820 error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1821 if (error)
1822 return (error);
1823
1824 buflen = sizeof(extmac);
1825 error = vn_extattr_get(vp, IO_NODELOCKED,
1826 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1827 (char *)&extmac, curthread);
1828 switch (error) {
1829 case 0:
1830 /* Got it */
1831 break;
1832
1833 case ENOATTR:
1834 /*
1835 * Use the label from the mount point.
1836 */
1837 mac_update_vnode_from_mount(vp, vp->v_mount);
1838 return (0);
1839
1840 case EOPNOTSUPP:
1841 default:
1842 /* Fail horribly. */
1843 return (error);
1844 }
1845
1846 if (buflen != sizeof(extmac))
1847 error = EPERM; /* Fail very closed. */
1848 if (error == 0)
1849 error = mac_update_vnode_from_externalized(vp, &extmac);
1850 if (error == 0)
1851 vp->v_vflag |= VV_CACHEDLABEL;
1852 else {
1853 struct vattr va;
1854
1855 printf("Corrupted label on %s",
1856 vp->v_mount->mnt_stat.f_mntonname);
1857 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1858 printf(" inum %ld", va.va_fileid);
1859#ifdef MAC_DEBUG
1860 if (mac_debug_label_fallback) {
1861 printf(", falling back.\n");
1862 mac_update_vnode_from_mount(vp, vp->v_mount);
1863 error = 0;
1864 } else {
1865#endif
1866 printf(".\n");
1867 error = EPERM;
1868#ifdef MAC_DEBUG
1869 }
1870#endif
1871 }
1872
1873 return (error);
1874}
1875
1876/*
1877 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
1878 * the labeling activity outselves. Filesystems should be careful not
1879 * to change their minds regarding whether they support vop_refreshlabel()
1880 * for a vnode or not. Don't cache the vnode here, allow the file
1881 * system code to determine if it's safe to cache. If we update from
1882 * the mount, don't cache since a change to the mount label should affect
1883 * all vnodes.
1884 */
1885static int
1886vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1887{
1888 int error;
1889
1890 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1891
1892 if (vp->v_mount == NULL) {
1893/*
1894 Eventually, we probably want to special-case refreshing
1895 of deadfs vnodes, and if there's a lock-free race somewhere,
1896 that case might be handled here.
1897
1898 mac_update_vnode_deadfs(vp);
1899 return (0);
1900 */
1901 /* printf("vn_refreshlabel: null v_mount\n"); */
1902 if (vp->v_type != VNON)
1903 printf(
1904 "vn_refreshlabel: null v_mount with non-VNON\n");
1905 return (EBADF);
1906 }
1907
1908 if (vp->v_vflag & VV_CACHEDLABEL) {
1909 mac_vnode_label_cache_hits++;
1910 return (0);
1911 } else
1912 mac_vnode_label_cache_misses++;
1913
1914 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1915 mac_update_vnode_from_mount(vp, vp->v_mount);
1916 return (0);
1917 }
1918
1919 error = VOP_REFRESHLABEL(vp, cred, curthread);
1920 switch (error) {
1921 case EOPNOTSUPP:
1922 /*
1923 * If labels are not supported on this vnode, fall back to
1924 * the label in the mount and propagate it to the vnode.
1925 * There should probably be some sort of policy/flag/decision
1926 * about doing this.
1927 */
1928 mac_update_vnode_from_mount(vp, vp->v_mount);
1929 error = 0;
1930 default:
1931 return (error);
1932 }
1933}
1934
1935/*
1936 * Helper function for file systems using the vop_std*_ea() calls. This
1937 * function must be called after EA service is available for the vnode,
1938 * but before it's hooked up to the namespace so that the node persists
1939 * if there's a crash, or before it can be accessed. On successful
1940 * commit of the label to disk (etc), do cache the label.
1941 */
1942int
1943vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1944{
1945 struct oldmac extmac;
1946 int error;
1947
1948 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1949 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1950 mac_update_vnode_from_mount(tvp, tvp->v_mount);
1951 } else {
1952 error = vn_refreshlabel(dvp, cred);
1953 if (error)
1954 return (error);
1955
1956 /*
1957 * Stick the label in the vnode. Then try to write to
1958 * disk. If we fail, return a failure to abort the
1959 * create operation. Really, this failure shouldn't
1960 * happen except in fairly unusual circumstances (out
1961 * of disk, etc).
1962 */
1963 mac_create_vnode(cred, dvp, tvp);
1964
1965 error = mac_stdcreatevnode_ea(tvp);
1966 if (error)
1967 return (error);
1968
1969 /*
1970 * XXX: Eventually this will go away and all policies will
1971 * directly manage their extended attributes.
1972 */
1973 error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac);
1974 if (error)
1975 return (error);
1976
1977 error = vn_extattr_set(tvp, IO_NODELOCKED,
1978 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1979 sizeof(extmac), (char *)&extmac, curthread);
1980 if (error == 0)
1981 tvp->v_vflag |= VV_CACHEDLABEL;
1982 else {
1983#if 0
1984 /*
1985 * In theory, we could have fall-back behavior here.
1986 * It would probably be incorrect.
1987 */
1988#endif
1989 return (error);
1990 }
1991 }
1992
1993 return (0);
1994}
1995
1996void
1997mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1998{
1999 int error;
2000
2001 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
2002
2003 error = vn_refreshlabel(vp, old);
2004 if (error) {
2005 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
2006 error);
2007 printf("mac_execve_transition: using old vnode label\n");
2008 }
2009
2010 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
2011}
2012
2013int
2014mac_execve_will_transition(struct ucred *old, struct vnode *vp)
2015{
2016 int error, result;
2017
2018 error = vn_refreshlabel(vp, old);
2019 if (error)
2020 return (error);
2021
2022 result = 0;
2023 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
2024
2025 return (result);
2026}
2027
2028int
2029mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
2030{
2031 int error;
2032
2033 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
2034
2035 if (!mac_enforce_fs)
2036 return (0);
2037
2038 error = vn_refreshlabel(vp, cred);
2039 if (error)
2040 return (error);
2041
2042 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
2043 return (error);
2044}
2045
2046int
2047mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
2048{
2049 int error;
2050
2051 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
2052
2053 if (!mac_enforce_fs)
2054 return (0);
2055
2056 error = vn_refreshlabel(dvp, cred);
2057 if (error)
2058 return (error);
2059
2060 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
2061 return (error);
2062}
2063
2064int
2065mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
2066{
2067 int error;
2068
2069 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
2070
2071 if (!mac_enforce_fs)
2072 return (0);
2073
2074 error = vn_refreshlabel(dvp, cred);
2075 if (error)
2076 return (error);
2077
2078 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
2079 return (error);
2080}
2081
2082int
2083mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2084 struct componentname *cnp, struct vattr *vap)
2085{
2086 int error;
2087
2088 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
2089
2090 if (!mac_enforce_fs)
2091 return (0);
2092
2093 error = vn_refreshlabel(dvp, cred);
2094 if (error)
2095 return (error);
2096
2097 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
2098 return (error);
2099}
2100
2101int
2102mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
2103 struct componentname *cnp)
2104{
2105 int error;
2106
2107 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
2108 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
2109
2110 if (!mac_enforce_fs)
2111 return (0);
2112
2113 error = vn_refreshlabel(dvp, cred);
2114 if (error)
2115 return (error);
2116 error = vn_refreshlabel(vp, cred);
2117 if (error)
2118 return (error);
2119
2120 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
2121 &vp->v_label, cnp);
2122 return (error);
2123}
2124
2125int
2126mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2127 acl_type_t type)
2128{
2129 int error;
2130
2131 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
2132
2133 if (!mac_enforce_fs)
2134 return (0);
2135
2136 error = vn_refreshlabel(vp, cred);
2137 if (error)
2138 return (error);
2139
2140 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
2141 return (error);
2142}
2143
2144int
2145mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
2146{
2147 int error;
2148
2149 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
2150
2151 if (!mac_enforce_process && !mac_enforce_fs)
2152 return (0);
2153
2154 error = vn_refreshlabel(vp, cred);
2155 if (error)
2156 return (error);
2157 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
2158
2159 return (error);
2160}
2161
2162int
2163mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
2164{
2165 int error;
2166
2167 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
2168
2169 if (!mac_enforce_fs)
2170 return (0);
2171
2172 error = vn_refreshlabel(vp, cred);
2173 if (error)
2174 return (error);
2175
2176 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
2177 return (error);
2178}
2179
2180int
2181mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2182 int attrnamespace, const char *name, struct uio *uio)
2183{
2184 int error;
2185
2186 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
2187
2188 if (!mac_enforce_fs)
2189 return (0);
2190
2191 error = vn_refreshlabel(vp, cred);
2192 if (error)
2193 return (error);
2194
2195 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
2196 attrnamespace, name, uio);
2197 return (error);
2198}
2199
2200int
2201mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2202 struct vnode *vp, struct componentname *cnp)
2203{
2204 int error;
2205
2206 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
2207 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
2208
2209 if (!mac_enforce_fs)
2210 return (0);
2211
2212 error = vn_refreshlabel(dvp, cred);
2213 if (error)
2214 return (error);
2215
2216 error = vn_refreshlabel(vp, cred);
2217 if (error)
2218 return (error);
2219
2220 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
2221 &vp->v_label, cnp);
2222 return (error);
2223}
2224
2225int
2226mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2227 struct componentname *cnp)
2228{
2229 int error;
2230
2231 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
2232
2233 if (!mac_enforce_fs)
2234 return (0);
2235
2236 error = vn_refreshlabel(dvp, cred);
2237 if (error)
2238 return (error);
2239
2240 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
2241 return (error);
2242}
2243
2244int
2245mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
2246{
2247 int error;
2248
2249 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
2250
2251 if (!mac_enforce_fs || !mac_enforce_vm)
2252 return (0);
2253
2254 error = vn_refreshlabel(vp, cred);
2255 if (error)
2256 return (error);
2257
2258 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
2259 return (error);
2260}
2261
2262void
2263mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
2264{
2265 int result = *prot;
2266
2267 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
2268
2269 if (!mac_enforce_fs || !mac_enforce_vm)
2270 return;
2271
2272 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
2273 &result);
2274
2275 *prot = result;
2276}
2277
2278int
2279mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
2280{
2281 int error;
2282
2283 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
2284
2285 if (!mac_enforce_fs || !mac_enforce_vm)
2286 return (0);
2287
2288 error = vn_refreshlabel(vp, cred);
2289 if (error)
2290 return (error);
2291
2292 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
2293 return (error);
2294}
2295
2296int
2297mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
2298{
2299 int error;
2300
2301 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
2302
2303 if (!mac_enforce_fs)
2304 return (0);
2305
2306 error = vn_refreshlabel(vp, cred);
2307 if (error)
2308 return (error);
2309
2310 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
2311 return (error);
2312}
2313
2314int
2315mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2316 struct vnode *vp)
2317{
2318 int error;
2319
2320 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
2321
2322 if (!mac_enforce_fs)
2323 return (0);
2324
2325 error = vn_refreshlabel(vp, active_cred);
2326 if (error)
2327 return (error);
2328
2329 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
2330 &vp->v_label);
2331
2332 return (error);
2333}
2334
2335int
2336mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2337 struct vnode *vp)
2338{
2339 int error;
2340
2341 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
2342
2343 if (!mac_enforce_fs)
2344 return (0);
2345
2346 error = vn_refreshlabel(vp, active_cred);
2347 if (error)
2348 return (error);
2349
2350 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
2351 &vp->v_label);
2352
2353 return (error);
2354}
2355
2356int
2357mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
2358{
2359 int error;
2360
2361 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
2362
2363 if (!mac_enforce_fs)
2364 return (0);
2365
2366 error = vn_refreshlabel(dvp, cred);
2367 if (error)
2368 return (error);
2369
2370 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
2371 return (error);
2372}
2373
2374int
2375mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
2376{
2377 int error;
2378
2379 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
2380
2381 if (!mac_enforce_fs)
2382 return (0);
2383
2384 error = vn_refreshlabel(vp, cred);
2385 if (error)
2386 return (error);
2387
2388 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
2389 return (error);
2390}
2391
2392static int
2393mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2394 struct label *newlabel)
2395{
2396 int error;
2397
2398 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
2399
2400 error = vn_refreshlabel(vp, cred);
2401 if (error)
2402 return (error);
2403
2404 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
2405
2406 return (error);
2407}
2408
2409int
2410mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2411 struct vnode *vp, struct componentname *cnp)
2412{
2413 int error;
2414
2415 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
2416 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
2417
2418 if (!mac_enforce_fs)
2419 return (0);
2420
2421 error = vn_refreshlabel(dvp, cred);
2422 if (error)
2423 return (error);
2424 error = vn_refreshlabel(vp, cred);
2425 if (error)
2426 return (error);
2427
2428 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
2429 &vp->v_label, cnp);
2430 return (error);
2431}
2432
2433int
2434mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2435 struct vnode *vp, int samedir, struct componentname *cnp)
2436{
2437 int error;
2438
2439 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2440 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2441
2442 if (!mac_enforce_fs)
2443 return (0);
2444
2445 error = vn_refreshlabel(dvp, cred);
2446 if (error)
2447 return (error);
2448 if (vp != NULL) {
2449 error = vn_refreshlabel(vp, cred);
2450 if (error)
2451 return (error);
2452 }
2453 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2454 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2455 return (error);
2456}
2457
2458int
2459mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2460{
2461 int error;
2462
2463 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2464
2465 if (!mac_enforce_fs)
2466 return (0);
2467
2468 error = vn_refreshlabel(vp, cred);
2469 if (error)
2470 return (error);
2471
2472 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2473 return (error);
2474}
2475
2476int
2477mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2478 struct acl *acl)
2479{
2480 int error;
2481
2482 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2483
2484 if (!mac_enforce_fs)
2485 return (0);
2486
2487 error = vn_refreshlabel(vp, cred);
2488 if (error)
2489 return (error);
2490
2491 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2492 return (error);
2493}
2494
2495int
2496mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2497 int attrnamespace, const char *name, struct uio *uio)
2498{
2499 int error;
2500
2501 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2502
2503 if (!mac_enforce_fs)
2504 return (0);
2505
2506 error = vn_refreshlabel(vp, cred);
2507 if (error)
2508 return (error);
2509
2510 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2511 attrnamespace, name, uio);
2512 return (error);
2513}
2514
2515int
2516mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2517{
2518 int error;
2519
2520 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2521
2522 if (!mac_enforce_fs)
2523 return (0);
2524
2525 error = vn_refreshlabel(vp, cred);
2526 if (error)
2527 return (error);
2528
2529 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2530 return (error);
2531}
2532
2533int
2534mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2535{
2536 int error;
2537
2538 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2539
2540 if (!mac_enforce_fs)
2541 return (0);
2542
2543 error = vn_refreshlabel(vp, cred);
2544 if (error)
2545 return (error);
2546
2547 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2548 return (error);
2549}
2550
2551int
2552mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2553 gid_t gid)
2554{
2555 int error;
2556
2557 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2558
2559 if (!mac_enforce_fs)
2560 return (0);
2561
2562 error = vn_refreshlabel(vp, cred);
2563 if (error)
2564 return (error);
2565
2566 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2567 return (error);
2568}
2569
2570int
2571mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2572 struct timespec atime, struct timespec mtime)
2573{
2574 int error;
2575
2576 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2577
2578 if (!mac_enforce_fs)
2579 return (0);
2580
2581 error = vn_refreshlabel(vp, cred);
2582 if (error)
2583 return (error);
2584
2585 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2586 mtime);
2587 return (error);
2588}
2589
2590int
2591mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2592 struct vnode *vp)
2593{
2594 int error;
2595
2596 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2597
2598 if (!mac_enforce_fs)
2599 return (0);
2600
2601 error = vn_refreshlabel(vp, active_cred);
2602 if (error)
2603 return (error);
2604
2605 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2606 &vp->v_label);
2607 return (error);
2608}
2609
2610int
2611mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp)
2612{
2613 int error;
2614
2615 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon");
2616
116static int mac_late = 0;
117
118static int mac_enforce_fs = 1;
119SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
120 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
121TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
122
123static int mac_enforce_network = 1;
124SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
125 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
126TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
127
128static int mac_enforce_pipe = 1;
129SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
130 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
131TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
132
133static int mac_enforce_process = 1;
134SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
135 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
136TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
137
138static int mac_enforce_socket = 1;
139SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
140 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
141TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
142
143static int mac_enforce_vm = 1;
144SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
145 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
146TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
147
148static int mac_label_size = sizeof(struct oldmac);
149SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD,
150 &mac_label_size, 0, "Pre-compiled MAC label size");
151
152static int mac_cache_fslabel_in_vnode = 1;
153SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
154 &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
155TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
156 &mac_cache_fslabel_in_vnode);
157
158static int mac_vnode_label_cache_hits = 0;
159SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD,
160 &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels");
161static int mac_vnode_label_cache_misses = 0;
162SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD,
163 &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels");
164
165static int mac_mmap_revocation = 1;
166SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
167 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
168 "relabel");
169static int mac_mmap_revocation_via_cow = 0;
170SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
171 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
172 "copy-on-write semantics, or by removing all write access");
173
174#ifdef MAC_DEBUG
175SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
176 "TrustedBSD MAC debug info");
177
178static int mac_debug_label_fallback = 0;
179SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
180 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
181 "when label is corrupted.");
182TUNABLE_INT("security.mac.debug_label_fallback",
183 &mac_debug_label_fallback);
184
185SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
186 "TrustedBSD MAC object counters");
187
188static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
189 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
190 nmacipqs, nmacpipes;
191
192SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
193 &nmacmbufs, 0, "number of mbufs in use");
194SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
195 &nmaccreds, 0, "number of ucreds in use");
196SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
197 &nmacifnets, 0, "number of ifnets in use");
198SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
199 &nmacipqs, 0, "number of ipqs in use");
200SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
201 &nmacbpfdescs, 0, "number of bpfdescs in use");
202SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
203 &nmacsockets, 0, "number of sockets in use");
204SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
205 &nmacpipes, 0, "number of pipes in use");
206SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
207 &nmacmounts, 0, "number of mounts in use");
208SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
209 &nmactemp, 0, "number of temporary labels in use");
210SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
211 &nmacvnodes, 0, "number of vnodes in use");
212SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
213 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
214#endif
215
216static int error_select(int error1, int error2);
217static int mac_externalize_vnode_oldmac(struct label *label,
218 struct oldmac *extmac);
219static int mac_policy_register(struct mac_policy_conf *mpc);
220static int mac_policy_unregister(struct mac_policy_conf *mpc);
221
222static int mac_stdcreatevnode_ea(struct vnode *vp);
223static void mac_check_vnode_mmap_downgrade(struct ucred *cred,
224 struct vnode *vp, int *prot);
225static void mac_cred_mmapped_drop_perms_recurse(struct thread *td,
226 struct ucred *cred, struct vm_map *map);
227
228static void mac_destroy_socket_label(struct label *label);
229
230MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
231MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
232MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
233
234/*
235 * mac_policy_list_lock protects the consistency of 'mac_policy_list',
236 * the linked list of attached policy modules. Read-only consumers of
237 * the list must acquire a shared lock for the duration of their use;
238 * writers must acquire an exclusive lock. Note that for compound
239 * operations, locks should be held for the entire compound operation,
240 * and that this is not yet done for relabel requests.
241 */
242static struct mtx mac_policy_list_lock;
243static LIST_HEAD(, mac_policy_conf) mac_policy_list;
244static int mac_policy_list_busy;
245#define MAC_POLICY_LIST_LOCKINIT() mtx_init(&mac_policy_list_lock, \
246 "mac_policy_list_lock", NULL, MTX_DEF);
247#define MAC_POLICY_LIST_LOCK() mtx_lock(&mac_policy_list_lock);
248#define MAC_POLICY_LIST_UNLOCK() mtx_unlock(&mac_policy_list_lock);
249
250#define MAC_POLICY_LIST_BUSY() do { \
251 MAC_POLICY_LIST_LOCK(); \
252 mac_policy_list_busy++; \
253 MAC_POLICY_LIST_UNLOCK(); \
254} while (0)
255
256#define MAC_POLICY_LIST_UNBUSY() do { \
257 MAC_POLICY_LIST_LOCK(); \
258 mac_policy_list_busy--; \
259 if (mac_policy_list_busy < 0) \
260 panic("Extra mac_policy_list_busy--"); \
261 MAC_POLICY_LIST_UNLOCK(); \
262} while (0)
263
264/*
265 * MAC_CHECK performs the designated check by walking the policy
266 * module list and checking with each as to how it feels about the
267 * request. Note that it returns its value via 'error' in the scope
268 * of the caller.
269 */
270#define MAC_CHECK(check, args...) do { \
271 struct mac_policy_conf *mpc; \
272 \
273 error = 0; \
274 MAC_POLICY_LIST_BUSY(); \
275 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
276 if (mpc->mpc_ops->mpo_ ## check != NULL) \
277 error = error_select( \
278 mpc->mpc_ops->mpo_ ## check (args), \
279 error); \
280 } \
281 MAC_POLICY_LIST_UNBUSY(); \
282} while (0)
283
284/*
285 * MAC_BOOLEAN performs the designated boolean composition by walking
286 * the module list, invoking each instance of the operation, and
287 * combining the results using the passed C operator. Note that it
288 * returns its value via 'result' in the scope of the caller, which
289 * should be initialized by the caller in a meaningful way to get
290 * a meaningful result.
291 */
292#define MAC_BOOLEAN(operation, composition, args...) do { \
293 struct mac_policy_conf *mpc; \
294 \
295 MAC_POLICY_LIST_BUSY(); \
296 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
297 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
298 result = result composition \
299 mpc->mpc_ops->mpo_ ## operation (args); \
300 } \
301 MAC_POLICY_LIST_UNBUSY(); \
302} while (0)
303
304#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \
305 outbuflen) do { \
306 char *curptr, *curptr_start, *element_name, *element_temp; \
307 size_t left, left_start, len; \
308 int claimed, first, first_start, ignorenotfound; \
309 \
310 error = 0; \
311 element_temp = elementlist; \
312 curptr = outbuf; \
313 curptr[0] = '\0'; \
314 left = outbuflen; \
315 first = 1; \
316 while ((element_name = strsep(&element_temp, ",")) != NULL) { \
317 curptr_start = curptr; \
318 left_start = left; \
319 first_start = first; \
320 if (element_name[0] == '?') { \
321 element_name++; \
322 ignorenotfound = 1; \
323 } else \
324 ignorenotfound = 0; \
325 claimed = 0; \
326 if (first) { \
327 len = snprintf(curptr, left, "%s/", \
328 element_name); \
329 first = 0; \
330 } else \
331 len = snprintf(curptr, left, ",%s/", \
332 element_name); \
333 if (len >= left) { \
334 error = EINVAL; /* XXXMAC: E2BIG */ \
335 break; \
336 } \
337 curptr += len; \
338 left -= len; \
339 \
340 MAC_CHECK(externalize_ ## type, label, element_name, \
341 curptr, left, &len, &claimed); \
342 if (error) \
343 break; \
344 if (claimed == 1) { \
345 if (len >= outbuflen) { \
346 error = EINVAL; /* XXXMAC: E2BIG */ \
347 break; \
348 } \
349 curptr += len; \
350 left -= len; \
351 } else if (claimed == 0 && ignorenotfound) { \
352 /* \
353 * Revert addition of the label element \
354 * name. \
355 */ \
356 curptr = curptr_start; \
357 *curptr = '\0'; \
358 left = left_start; \
359 first = first_start; \
360 } else { \
361 error = EINVAL; /* XXXMAC: ENOLABEL */ \
362 break; \
363 } \
364 } \
365} while (0)
366
367#define MAC_INTERNALIZE(type, label, instring) do { \
368 char *element, *element_name, *element_data; \
369 int claimed; \
370 \
371 error = 0; \
372 element = instring; \
373 while ((element_name = strsep(&element, ",")) != NULL) { \
374 element_data = element_name; \
375 element_name = strsep(&element_data, "/"); \
376 if (element_data == NULL) { \
377 error = EINVAL; \
378 break; \
379 } \
380 claimed = 0; \
381 MAC_CHECK(internalize_ ## type, label, element_name, \
382 element_data, &claimed); \
383 if (error) \
384 break; \
385 if (claimed != 1) { \
386 /* XXXMAC: Another error here? */ \
387 error = EINVAL; \
388 break; \
389 } \
390 } \
391} while (0)
392
393/*
394 * MAC_PERFORM performs the designated operation by walking the policy
395 * module list and invoking that operation for each policy.
396 */
397#define MAC_PERFORM(operation, args...) do { \
398 struct mac_policy_conf *mpc; \
399 \
400 MAC_POLICY_LIST_BUSY(); \
401 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
402 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
403 mpc->mpc_ops->mpo_ ## operation (args); \
404 } \
405 MAC_POLICY_LIST_UNBUSY(); \
406} while (0)
407
408/*
409 * Initialize the MAC subsystem, including appropriate SMP locks.
410 */
411static void
412mac_init(void)
413{
414
415 LIST_INIT(&mac_policy_list);
416 MAC_POLICY_LIST_LOCKINIT();
417}
418
419/*
420 * For the purposes of modules that want to know if they were loaded
421 * "early", set the mac_late flag once we've processed modules either
422 * linked into the kernel, or loaded before the kernel startup.
423 */
424static void
425mac_late_init(void)
426{
427
428 mac_late = 1;
429}
430
431/*
432 * Allow MAC policy modules to register during boot, etc.
433 */
434int
435mac_policy_modevent(module_t mod, int type, void *data)
436{
437 struct mac_policy_conf *mpc;
438 int error;
439
440 error = 0;
441 mpc = (struct mac_policy_conf *) data;
442
443 switch (type) {
444 case MOD_LOAD:
445 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
446 mac_late) {
447 printf("mac_policy_modevent: can't load %s policy "
448 "after booting\n", mpc->mpc_name);
449 error = EBUSY;
450 break;
451 }
452 error = mac_policy_register(mpc);
453 break;
454 case MOD_UNLOAD:
455 /* Don't unregister the module if it was never registered. */
456 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
457 != 0)
458 error = mac_policy_unregister(mpc);
459 else
460 error = 0;
461 break;
462 default:
463 break;
464 }
465
466 return (error);
467}
468
469static int
470mac_policy_register(struct mac_policy_conf *mpc)
471{
472 struct mac_policy_conf *tmpc;
473 struct mac_policy_op_entry *mpe;
474 int slot;
475
476 MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*mpc->mpc_ops),
477 M_MACOPVEC, M_WAITOK | M_ZERO);
478 for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
479 switch (mpe->mpe_constant) {
480 case MAC_OP_LAST:
481 /*
482 * Doesn't actually happen, but this allows checking
483 * that all enumerated values are handled.
484 */
485 break;
486 case MAC_DESTROY:
487 mpc->mpc_ops->mpo_destroy =
488 mpe->mpe_function;
489 break;
490 case MAC_INIT:
491 mpc->mpc_ops->mpo_init =
492 mpe->mpe_function;
493 break;
494 case MAC_SYSCALL:
495 mpc->mpc_ops->mpo_syscall =
496 mpe->mpe_function;
497 break;
498 case MAC_INIT_BPFDESC_LABEL:
499 mpc->mpc_ops->mpo_init_bpfdesc_label =
500 mpe->mpe_function;
501 break;
502 case MAC_INIT_CRED_LABEL:
503 mpc->mpc_ops->mpo_init_cred_label =
504 mpe->mpe_function;
505 break;
506 case MAC_INIT_DEVFSDIRENT_LABEL:
507 mpc->mpc_ops->mpo_init_devfsdirent_label =
508 mpe->mpe_function;
509 break;
510 case MAC_INIT_IFNET_LABEL:
511 mpc->mpc_ops->mpo_init_ifnet_label =
512 mpe->mpe_function;
513 break;
514 case MAC_INIT_IPQ_LABEL:
515 mpc->mpc_ops->mpo_init_ipq_label =
516 mpe->mpe_function;
517 break;
518 case MAC_INIT_MBUF_LABEL:
519 mpc->mpc_ops->mpo_init_mbuf_label =
520 mpe->mpe_function;
521 break;
522 case MAC_INIT_MOUNT_LABEL:
523 mpc->mpc_ops->mpo_init_mount_label =
524 mpe->mpe_function;
525 break;
526 case MAC_INIT_MOUNT_FS_LABEL:
527 mpc->mpc_ops->mpo_init_mount_fs_label =
528 mpe->mpe_function;
529 break;
530 case MAC_INIT_PIPE_LABEL:
531 mpc->mpc_ops->mpo_init_pipe_label =
532 mpe->mpe_function;
533 break;
534 case MAC_INIT_SOCKET_LABEL:
535 mpc->mpc_ops->mpo_init_socket_label =
536 mpe->mpe_function;
537 break;
538 case MAC_INIT_SOCKET_PEER_LABEL:
539 mpc->mpc_ops->mpo_init_socket_peer_label =
540 mpe->mpe_function;
541 break;
542 case MAC_INIT_VNODE_LABEL:
543 mpc->mpc_ops->mpo_init_vnode_label =
544 mpe->mpe_function;
545 break;
546 case MAC_DESTROY_BPFDESC_LABEL:
547 mpc->mpc_ops->mpo_destroy_bpfdesc_label =
548 mpe->mpe_function;
549 break;
550 case MAC_DESTROY_CRED_LABEL:
551 mpc->mpc_ops->mpo_destroy_cred_label =
552 mpe->mpe_function;
553 break;
554 case MAC_DESTROY_DEVFSDIRENT_LABEL:
555 mpc->mpc_ops->mpo_destroy_devfsdirent_label =
556 mpe->mpe_function;
557 break;
558 case MAC_DESTROY_IFNET_LABEL:
559 mpc->mpc_ops->mpo_destroy_ifnet_label =
560 mpe->mpe_function;
561 break;
562 case MAC_DESTROY_IPQ_LABEL:
563 mpc->mpc_ops->mpo_destroy_ipq_label =
564 mpe->mpe_function;
565 break;
566 case MAC_DESTROY_MBUF_LABEL:
567 mpc->mpc_ops->mpo_destroy_mbuf_label =
568 mpe->mpe_function;
569 break;
570 case MAC_DESTROY_MOUNT_LABEL:
571 mpc->mpc_ops->mpo_destroy_mount_label =
572 mpe->mpe_function;
573 break;
574 case MAC_DESTROY_MOUNT_FS_LABEL:
575 mpc->mpc_ops->mpo_destroy_mount_fs_label =
576 mpe->mpe_function;
577 break;
578 case MAC_DESTROY_PIPE_LABEL:
579 mpc->mpc_ops->mpo_destroy_pipe_label =
580 mpe->mpe_function;
581 break;
582 case MAC_DESTROY_SOCKET_LABEL:
583 mpc->mpc_ops->mpo_destroy_socket_label =
584 mpe->mpe_function;
585 break;
586 case MAC_DESTROY_SOCKET_PEER_LABEL:
587 mpc->mpc_ops->mpo_destroy_socket_peer_label =
588 mpe->mpe_function;
589 break;
590 case MAC_DESTROY_VNODE_LABEL:
591 mpc->mpc_ops->mpo_destroy_vnode_label =
592 mpe->mpe_function;
593 break;
594 case MAC_COPY_PIPE_LABEL:
595 mpc->mpc_ops->mpo_copy_pipe_label =
596 mpe->mpe_function;
597 break;
598 case MAC_COPY_VNODE_LABEL:
599 mpc->mpc_ops->mpo_copy_vnode_label =
600 mpe->mpe_function;
601 break;
602 case MAC_EXTERNALIZE_CRED_LABEL:
603 mpc->mpc_ops->mpo_externalize_cred_label =
604 mpe->mpe_function;
605 break;
606 case MAC_EXTERNALIZE_IFNET_LABEL:
607 mpc->mpc_ops->mpo_externalize_ifnet_label =
608 mpe->mpe_function;
609 break;
610 case MAC_EXTERNALIZE_PIPE_LABEL:
611 mpc->mpc_ops->mpo_externalize_pipe_label =
612 mpe->mpe_function;
613 break;
614 case MAC_EXTERNALIZE_SOCKET_LABEL:
615 mpc->mpc_ops->mpo_externalize_socket_label =
616 mpe->mpe_function;
617 break;
618 case MAC_EXTERNALIZE_SOCKET_PEER_LABEL:
619 mpc->mpc_ops->mpo_externalize_socket_peer_label =
620 mpe->mpe_function;
621 break;
622 case MAC_EXTERNALIZE_VNODE_LABEL:
623 mpc->mpc_ops->mpo_externalize_vnode_label =
624 mpe->mpe_function;
625 break;
626 case MAC_EXTERNALIZE_VNODE_OLDMAC:
627 mpc->mpc_ops->mpo_externalize_vnode_oldmac =
628 mpe->mpe_function;
629 break;
630 case MAC_INTERNALIZE_CRED_LABEL:
631 mpc->mpc_ops->mpo_internalize_cred_label =
632 mpe->mpe_function;
633 break;
634 case MAC_INTERNALIZE_IFNET_LABEL:
635 mpc->mpc_ops->mpo_internalize_ifnet_label =
636 mpe->mpe_function;
637 break;
638 case MAC_INTERNALIZE_PIPE_LABEL:
639 mpc->mpc_ops->mpo_internalize_pipe_label =
640 mpe->mpe_function;
641 break;
642 case MAC_INTERNALIZE_SOCKET_LABEL:
643 mpc->mpc_ops->mpo_internalize_socket_label =
644 mpe->mpe_function;
645 break;
646 case MAC_INTERNALIZE_VNODE_LABEL:
647 mpc->mpc_ops->mpo_internalize_vnode_label =
648 mpe->mpe_function;
649 break;
650 case MAC_CREATE_DEVFS_DEVICE:
651 mpc->mpc_ops->mpo_create_devfs_device =
652 mpe->mpe_function;
653 break;
654 case MAC_CREATE_DEVFS_DIRECTORY:
655 mpc->mpc_ops->mpo_create_devfs_directory =
656 mpe->mpe_function;
657 break;
658 case MAC_CREATE_DEVFS_SYMLINK:
659 mpc->mpc_ops->mpo_create_devfs_symlink =
660 mpe->mpe_function;
661 break;
662 case MAC_CREATE_DEVFS_VNODE:
663 mpc->mpc_ops->mpo_create_devfs_vnode =
664 mpe->mpe_function;
665 break;
666 case MAC_STDCREATEVNODE_EA:
667 mpc->mpc_ops->mpo_stdcreatevnode_ea =
668 mpe->mpe_function;
669 break;
670 case MAC_CREATE_VNODE:
671 mpc->mpc_ops->mpo_create_vnode =
672 mpe->mpe_function;
673 break;
674 case MAC_CREATE_MOUNT:
675 mpc->mpc_ops->mpo_create_mount =
676 mpe->mpe_function;
677 break;
678 case MAC_CREATE_ROOT_MOUNT:
679 mpc->mpc_ops->mpo_create_root_mount =
680 mpe->mpe_function;
681 break;
682 case MAC_RELABEL_VNODE:
683 mpc->mpc_ops->mpo_relabel_vnode =
684 mpe->mpe_function;
685 break;
686 case MAC_UPDATE_DEVFSDIRENT:
687 mpc->mpc_ops->mpo_update_devfsdirent =
688 mpe->mpe_function;
689 break;
690 case MAC_UPDATE_PROCFSVNODE:
691 mpc->mpc_ops->mpo_update_procfsvnode =
692 mpe->mpe_function;
693 break;
694 case MAC_UPDATE_VNODE_FROM_EXTATTR:
695 mpc->mpc_ops->mpo_update_vnode_from_extattr =
696 mpe->mpe_function;
697 break;
698 case MAC_UPDATE_VNODE_FROM_EXTERNALIZED:
699 mpc->mpc_ops->mpo_update_vnode_from_externalized =
700 mpe->mpe_function;
701 break;
702 case MAC_UPDATE_VNODE_FROM_MOUNT:
703 mpc->mpc_ops->mpo_update_vnode_from_mount =
704 mpe->mpe_function;
705 break;
706 case MAC_CREATE_MBUF_FROM_SOCKET:
707 mpc->mpc_ops->mpo_create_mbuf_from_socket =
708 mpe->mpe_function;
709 break;
710 case MAC_CREATE_PIPE:
711 mpc->mpc_ops->mpo_create_pipe =
712 mpe->mpe_function;
713 break;
714 case MAC_CREATE_SOCKET:
715 mpc->mpc_ops->mpo_create_socket =
716 mpe->mpe_function;
717 break;
718 case MAC_CREATE_SOCKET_FROM_SOCKET:
719 mpc->mpc_ops->mpo_create_socket_from_socket =
720 mpe->mpe_function;
721 break;
722 case MAC_RELABEL_PIPE:
723 mpc->mpc_ops->mpo_relabel_pipe =
724 mpe->mpe_function;
725 break;
726 case MAC_RELABEL_SOCKET:
727 mpc->mpc_ops->mpo_relabel_socket =
728 mpe->mpe_function;
729 break;
730 case MAC_SET_SOCKET_PEER_FROM_MBUF:
731 mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
732 mpe->mpe_function;
733 break;
734 case MAC_SET_SOCKET_PEER_FROM_SOCKET:
735 mpc->mpc_ops->mpo_set_socket_peer_from_socket =
736 mpe->mpe_function;
737 break;
738 case MAC_CREATE_BPFDESC:
739 mpc->mpc_ops->mpo_create_bpfdesc =
740 mpe->mpe_function;
741 break;
742 case MAC_CREATE_DATAGRAM_FROM_IPQ:
743 mpc->mpc_ops->mpo_create_datagram_from_ipq =
744 mpe->mpe_function;
745 break;
746 case MAC_CREATE_FRAGMENT:
747 mpc->mpc_ops->mpo_create_fragment =
748 mpe->mpe_function;
749 break;
750 case MAC_CREATE_IFNET:
751 mpc->mpc_ops->mpo_create_ifnet =
752 mpe->mpe_function;
753 break;
754 case MAC_CREATE_IPQ:
755 mpc->mpc_ops->mpo_create_ipq =
756 mpe->mpe_function;
757 break;
758 case MAC_CREATE_MBUF_FROM_MBUF:
759 mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
760 mpe->mpe_function;
761 break;
762 case MAC_CREATE_MBUF_LINKLAYER:
763 mpc->mpc_ops->mpo_create_mbuf_linklayer =
764 mpe->mpe_function;
765 break;
766 case MAC_CREATE_MBUF_FROM_BPFDESC:
767 mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
768 mpe->mpe_function;
769 break;
770 case MAC_CREATE_MBUF_FROM_IFNET:
771 mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
772 mpe->mpe_function;
773 break;
774 case MAC_CREATE_MBUF_MULTICAST_ENCAP:
775 mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
776 mpe->mpe_function;
777 break;
778 case MAC_CREATE_MBUF_NETLAYER:
779 mpc->mpc_ops->mpo_create_mbuf_netlayer =
780 mpe->mpe_function;
781 break;
782 case MAC_FRAGMENT_MATCH:
783 mpc->mpc_ops->mpo_fragment_match =
784 mpe->mpe_function;
785 break;
786 case MAC_RELABEL_IFNET:
787 mpc->mpc_ops->mpo_relabel_ifnet =
788 mpe->mpe_function;
789 break;
790 case MAC_UPDATE_IPQ:
791 mpc->mpc_ops->mpo_update_ipq =
792 mpe->mpe_function;
793 break;
794 case MAC_CREATE_CRED:
795 mpc->mpc_ops->mpo_create_cred =
796 mpe->mpe_function;
797 break;
798 case MAC_EXECVE_TRANSITION:
799 mpc->mpc_ops->mpo_execve_transition =
800 mpe->mpe_function;
801 break;
802 case MAC_EXECVE_WILL_TRANSITION:
803 mpc->mpc_ops->mpo_execve_will_transition =
804 mpe->mpe_function;
805 break;
806 case MAC_CREATE_PROC0:
807 mpc->mpc_ops->mpo_create_proc0 =
808 mpe->mpe_function;
809 break;
810 case MAC_CREATE_PROC1:
811 mpc->mpc_ops->mpo_create_proc1 =
812 mpe->mpe_function;
813 break;
814 case MAC_RELABEL_CRED:
815 mpc->mpc_ops->mpo_relabel_cred =
816 mpe->mpe_function;
817 break;
818 case MAC_THREAD_USERRET:
819 mpc->mpc_ops->mpo_thread_userret =
820 mpe->mpe_function;
821 break;
822 case MAC_CHECK_BPFDESC_RECEIVE:
823 mpc->mpc_ops->mpo_check_bpfdesc_receive =
824 mpe->mpe_function;
825 break;
826 case MAC_CHECK_CRED_RELABEL:
827 mpc->mpc_ops->mpo_check_cred_relabel =
828 mpe->mpe_function;
829 break;
830 case MAC_CHECK_CRED_VISIBLE:
831 mpc->mpc_ops->mpo_check_cred_visible =
832 mpe->mpe_function;
833 break;
834 case MAC_CHECK_IFNET_RELABEL:
835 mpc->mpc_ops->mpo_check_ifnet_relabel =
836 mpe->mpe_function;
837 break;
838 case MAC_CHECK_IFNET_TRANSMIT:
839 mpc->mpc_ops->mpo_check_ifnet_transmit =
840 mpe->mpe_function;
841 break;
842 case MAC_CHECK_MOUNT_STAT:
843 mpc->mpc_ops->mpo_check_mount_stat =
844 mpe->mpe_function;
845 break;
846 case MAC_CHECK_PIPE_IOCTL:
847 mpc->mpc_ops->mpo_check_pipe_ioctl =
848 mpe->mpe_function;
849 break;
850 case MAC_CHECK_PIPE_POLL:
851 mpc->mpc_ops->mpo_check_pipe_poll =
852 mpe->mpe_function;
853 break;
854 case MAC_CHECK_PIPE_READ:
855 mpc->mpc_ops->mpo_check_pipe_read =
856 mpe->mpe_function;
857 break;
858 case MAC_CHECK_PIPE_RELABEL:
859 mpc->mpc_ops->mpo_check_pipe_relabel =
860 mpe->mpe_function;
861 break;
862 case MAC_CHECK_PIPE_STAT:
863 mpc->mpc_ops->mpo_check_pipe_stat =
864 mpe->mpe_function;
865 break;
866 case MAC_CHECK_PIPE_WRITE:
867 mpc->mpc_ops->mpo_check_pipe_write =
868 mpe->mpe_function;
869 break;
870 case MAC_CHECK_PROC_DEBUG:
871 mpc->mpc_ops->mpo_check_proc_debug =
872 mpe->mpe_function;
873 break;
874 case MAC_CHECK_PROC_SCHED:
875 mpc->mpc_ops->mpo_check_proc_sched =
876 mpe->mpe_function;
877 break;
878 case MAC_CHECK_PROC_SIGNAL:
879 mpc->mpc_ops->mpo_check_proc_signal =
880 mpe->mpe_function;
881 break;
882 case MAC_CHECK_SOCKET_BIND:
883 mpc->mpc_ops->mpo_check_socket_bind =
884 mpe->mpe_function;
885 break;
886 case MAC_CHECK_SOCKET_CONNECT:
887 mpc->mpc_ops->mpo_check_socket_connect =
888 mpe->mpe_function;
889 break;
890 case MAC_CHECK_SOCKET_DELIVER:
891 mpc->mpc_ops->mpo_check_socket_deliver =
892 mpe->mpe_function;
893 break;
894 case MAC_CHECK_SOCKET_LISTEN:
895 mpc->mpc_ops->mpo_check_socket_listen =
896 mpe->mpe_function;
897 break;
898 case MAC_CHECK_SOCKET_RECEIVE:
899 mpc->mpc_ops->mpo_check_socket_receive =
900 mpe->mpe_function;
901 break;
902 case MAC_CHECK_SOCKET_RELABEL:
903 mpc->mpc_ops->mpo_check_socket_relabel =
904 mpe->mpe_function;
905 break;
906 case MAC_CHECK_SOCKET_SEND:
907 mpc->mpc_ops->mpo_check_socket_send =
908 mpe->mpe_function;
909 break;
910 case MAC_CHECK_SOCKET_VISIBLE:
911 mpc->mpc_ops->mpo_check_socket_visible =
912 mpe->mpe_function;
913 break;
914 case MAC_CHECK_VNODE_ACCESS:
915 mpc->mpc_ops->mpo_check_vnode_access =
916 mpe->mpe_function;
917 break;
918 case MAC_CHECK_VNODE_CHDIR:
919 mpc->mpc_ops->mpo_check_vnode_chdir =
920 mpe->mpe_function;
921 break;
922 case MAC_CHECK_VNODE_CHROOT:
923 mpc->mpc_ops->mpo_check_vnode_chroot =
924 mpe->mpe_function;
925 break;
926 case MAC_CHECK_VNODE_CREATE:
927 mpc->mpc_ops->mpo_check_vnode_create =
928 mpe->mpe_function;
929 break;
930 case MAC_CHECK_VNODE_DELETE:
931 mpc->mpc_ops->mpo_check_vnode_delete =
932 mpe->mpe_function;
933 break;
934 case MAC_CHECK_VNODE_DELETEACL:
935 mpc->mpc_ops->mpo_check_vnode_deleteacl =
936 mpe->mpe_function;
937 break;
938 case MAC_CHECK_VNODE_EXEC:
939 mpc->mpc_ops->mpo_check_vnode_exec =
940 mpe->mpe_function;
941 break;
942 case MAC_CHECK_VNODE_GETACL:
943 mpc->mpc_ops->mpo_check_vnode_getacl =
944 mpe->mpe_function;
945 break;
946 case MAC_CHECK_VNODE_GETEXTATTR:
947 mpc->mpc_ops->mpo_check_vnode_getextattr =
948 mpe->mpe_function;
949 break;
950 case MAC_CHECK_VNODE_LINK:
951 mpc->mpc_ops->mpo_check_vnode_link =
952 mpe->mpe_function;
953 break;
954 case MAC_CHECK_VNODE_LOOKUP:
955 mpc->mpc_ops->mpo_check_vnode_lookup =
956 mpe->mpe_function;
957 break;
958 case MAC_CHECK_VNODE_MMAP:
959 mpc->mpc_ops->mpo_check_vnode_mmap =
960 mpe->mpe_function;
961 break;
962 case MAC_CHECK_VNODE_MMAP_DOWNGRADE:
963 mpc->mpc_ops->mpo_check_vnode_mmap_downgrade =
964 mpe->mpe_function;
965 break;
966 case MAC_CHECK_VNODE_MPROTECT:
967 mpc->mpc_ops->mpo_check_vnode_mprotect =
968 mpe->mpe_function;
969 break;
970 case MAC_CHECK_VNODE_OPEN:
971 mpc->mpc_ops->mpo_check_vnode_open =
972 mpe->mpe_function;
973 break;
974 case MAC_CHECK_VNODE_POLL:
975 mpc->mpc_ops->mpo_check_vnode_poll =
976 mpe->mpe_function;
977 break;
978 case MAC_CHECK_VNODE_READ:
979 mpc->mpc_ops->mpo_check_vnode_read =
980 mpe->mpe_function;
981 break;
982 case MAC_CHECK_VNODE_READDIR:
983 mpc->mpc_ops->mpo_check_vnode_readdir =
984 mpe->mpe_function;
985 break;
986 case MAC_CHECK_VNODE_READLINK:
987 mpc->mpc_ops->mpo_check_vnode_readlink =
988 mpe->mpe_function;
989 break;
990 case MAC_CHECK_VNODE_RELABEL:
991 mpc->mpc_ops->mpo_check_vnode_relabel =
992 mpe->mpe_function;
993 break;
994 case MAC_CHECK_VNODE_RENAME_FROM:
995 mpc->mpc_ops->mpo_check_vnode_rename_from =
996 mpe->mpe_function;
997 break;
998 case MAC_CHECK_VNODE_RENAME_TO:
999 mpc->mpc_ops->mpo_check_vnode_rename_to =
1000 mpe->mpe_function;
1001 break;
1002 case MAC_CHECK_VNODE_REVOKE:
1003 mpc->mpc_ops->mpo_check_vnode_revoke =
1004 mpe->mpe_function;
1005 break;
1006 case MAC_CHECK_VNODE_SETACL:
1007 mpc->mpc_ops->mpo_check_vnode_setacl =
1008 mpe->mpe_function;
1009 break;
1010 case MAC_CHECK_VNODE_SETEXTATTR:
1011 mpc->mpc_ops->mpo_check_vnode_setextattr =
1012 mpe->mpe_function;
1013 break;
1014 case MAC_CHECK_VNODE_SETFLAGS:
1015 mpc->mpc_ops->mpo_check_vnode_setflags =
1016 mpe->mpe_function;
1017 break;
1018 case MAC_CHECK_VNODE_SETMODE:
1019 mpc->mpc_ops->mpo_check_vnode_setmode =
1020 mpe->mpe_function;
1021 break;
1022 case MAC_CHECK_VNODE_SETOWNER:
1023 mpc->mpc_ops->mpo_check_vnode_setowner =
1024 mpe->mpe_function;
1025 break;
1026 case MAC_CHECK_VNODE_SETUTIMES:
1027 mpc->mpc_ops->mpo_check_vnode_setutimes =
1028 mpe->mpe_function;
1029 break;
1030 case MAC_CHECK_VNODE_STAT:
1031 mpc->mpc_ops->mpo_check_vnode_stat =
1032 mpe->mpe_function;
1033 break;
1034 case MAC_CHECK_VNODE_SWAPON:
1035 mpc->mpc_ops->mpo_check_vnode_swapon =
1036 mpe->mpe_function;
1037 break;
1038 case MAC_CHECK_VNODE_WRITE:
1039 mpc->mpc_ops->mpo_check_vnode_write =
1040 mpe->mpe_function;
1041 break;
1042/*
1043 default:
1044 printf("MAC policy `%s': unknown operation %d\n",
1045 mpc->mpc_name, mpe->mpe_constant);
1046 return (EINVAL);
1047*/
1048 }
1049 }
1050 MAC_POLICY_LIST_LOCK();
1051 if (mac_policy_list_busy > 0) {
1052 MAC_POLICY_LIST_UNLOCK();
1053 FREE(mpc->mpc_ops, M_MACOPVEC);
1054 mpc->mpc_ops = NULL;
1055 return (EBUSY);
1056 }
1057 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
1058 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
1059 MAC_POLICY_LIST_UNLOCK();
1060 FREE(mpc->mpc_ops, M_MACOPVEC);
1061 mpc->mpc_ops = NULL;
1062 return (EEXIST);
1063 }
1064 }
1065 if (mpc->mpc_field_off != NULL) {
1066 slot = ffs(mac_policy_offsets_free);
1067 if (slot == 0) {
1068 MAC_POLICY_LIST_UNLOCK();
1069 FREE(mpc->mpc_ops, M_MACOPVEC);
1070 mpc->mpc_ops = NULL;
1071 return (ENOMEM);
1072 }
1073 slot--;
1074 mac_policy_offsets_free &= ~(1 << slot);
1075 *mpc->mpc_field_off = slot;
1076 }
1077 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
1078 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
1079
1080 /* Per-policy initialization. */
1081 if (mpc->mpc_ops->mpo_init != NULL)
1082 (*(mpc->mpc_ops->mpo_init))(mpc);
1083 MAC_POLICY_LIST_UNLOCK();
1084
1085 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
1086 mpc->mpc_name);
1087
1088 return (0);
1089}
1090
1091static int
1092mac_policy_unregister(struct mac_policy_conf *mpc)
1093{
1094
1095 /*
1096 * If we fail the load, we may get a request to unload. Check
1097 * to see if we did the run-time registration, and if not,
1098 * silently succeed.
1099 */
1100 MAC_POLICY_LIST_LOCK();
1101 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
1102 MAC_POLICY_LIST_UNLOCK();
1103 return (0);
1104 }
1105#if 0
1106 /*
1107 * Don't allow unloading modules with private data.
1108 */
1109 if (mpc->mpc_field_off != NULL) {
1110 MAC_POLICY_LIST_UNLOCK();
1111 return (EBUSY);
1112 }
1113#endif
1114 /*
1115 * Only allow the unload to proceed if the module is unloadable
1116 * by its own definition.
1117 */
1118 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
1119 MAC_POLICY_LIST_UNLOCK();
1120 return (EBUSY);
1121 }
1122 /*
1123 * Right now, we EBUSY if the list is in use. In the future,
1124 * for reliability reasons, we might want to sleep and wakeup
1125 * later to try again.
1126 */
1127 if (mac_policy_list_busy > 0) {
1128 MAC_POLICY_LIST_UNLOCK();
1129 return (EBUSY);
1130 }
1131 if (mpc->mpc_ops->mpo_destroy != NULL)
1132 (*(mpc->mpc_ops->mpo_destroy))(mpc);
1133
1134 LIST_REMOVE(mpc, mpc_list);
1135 MAC_POLICY_LIST_UNLOCK();
1136
1137 FREE(mpc->mpc_ops, M_MACOPVEC);
1138 mpc->mpc_ops = NULL;
1139 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
1140
1141 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
1142 mpc->mpc_name);
1143
1144 return (0);
1145}
1146
1147/*
1148 * Define an error value precedence, and given two arguments, selects the
1149 * value with the higher precedence.
1150 */
1151static int
1152error_select(int error1, int error2)
1153{
1154
1155 /* Certain decision-making errors take top priority. */
1156 if (error1 == EDEADLK || error2 == EDEADLK)
1157 return (EDEADLK);
1158
1159 /* Invalid arguments should be reported where possible. */
1160 if (error1 == EINVAL || error2 == EINVAL)
1161 return (EINVAL);
1162
1163 /* Precedence goes to "visibility", with both process and file. */
1164 if (error1 == ESRCH || error2 == ESRCH)
1165 return (ESRCH);
1166
1167 if (error1 == ENOENT || error2 == ENOENT)
1168 return (ENOENT);
1169
1170 /* Precedence goes to DAC/MAC protections. */
1171 if (error1 == EACCES || error2 == EACCES)
1172 return (EACCES);
1173
1174 /* Precedence goes to privilege. */
1175 if (error1 == EPERM || error2 == EPERM)
1176 return (EPERM);
1177
1178 /* Precedence goes to error over success; otherwise, arbitrary. */
1179 if (error1 != 0)
1180 return (error1);
1181 return (error2);
1182}
1183
1184static void
1185mac_init_label(struct label *label)
1186{
1187
1188 bzero(label, sizeof(*label));
1189 label->l_flags = MAC_FLAG_INITIALIZED;
1190}
1191
1192static void
1193mac_destroy_label(struct label *label)
1194{
1195
1196 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1197 ("destroying uninitialized label"));
1198
1199 bzero(label, sizeof(*label));
1200 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1201}
1202
1203void
1204mac_init_bpfdesc(struct bpf_d *bpf_d)
1205{
1206
1207 mac_init_label(&bpf_d->bd_label);
1208 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
1209#ifdef MAC_DEBUG
1210 atomic_add_int(&nmacbpfdescs, 1);
1211#endif
1212}
1213
1214static void
1215mac_init_cred_label(struct label *label)
1216{
1217
1218 mac_init_label(label);
1219 MAC_PERFORM(init_cred_label, label);
1220#ifdef MAC_DEBUG
1221 atomic_add_int(&nmaccreds, 1);
1222#endif
1223}
1224
1225void
1226mac_init_cred(struct ucred *cred)
1227{
1228
1229 mac_init_cred_label(&cred->cr_label);
1230}
1231
1232void
1233mac_init_devfsdirent(struct devfs_dirent *de)
1234{
1235
1236 mac_init_label(&de->de_label);
1237 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
1238#ifdef MAC_DEBUG
1239 atomic_add_int(&nmacdevfsdirents, 1);
1240#endif
1241}
1242
1243static void
1244mac_init_ifnet_label(struct label *label)
1245{
1246
1247 mac_init_label(label);
1248 MAC_PERFORM(init_ifnet_label, label);
1249#ifdef MAC_DEBUG
1250 atomic_add_int(&nmacifnets, 1);
1251#endif
1252}
1253
1254void
1255mac_init_ifnet(struct ifnet *ifp)
1256{
1257
1258 mac_init_ifnet_label(&ifp->if_label);
1259}
1260
1261void
1262mac_init_ipq(struct ipq *ipq)
1263{
1264
1265 mac_init_label(&ipq->ipq_label);
1266 MAC_PERFORM(init_ipq_label, &ipq->ipq_label);
1267#ifdef MAC_DEBUG
1268 atomic_add_int(&nmacipqs, 1);
1269#endif
1270}
1271
1272int
1273mac_init_mbuf(struct mbuf *m, int flag)
1274{
1275 int error;
1276
1277 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1278
1279 mac_init_label(&m->m_pkthdr.label);
1280
1281 MAC_CHECK(init_mbuf_label, &m->m_pkthdr.label, flag);
1282 if (error) {
1283 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1284 mac_destroy_label(&m->m_pkthdr.label);
1285 }
1286
1287#ifdef MAC_DEBUG
1288 if (error == 0)
1289 atomic_add_int(&nmacmbufs, 1);
1290#endif
1291 return (error);
1292}
1293
1294void
1295mac_init_mount(struct mount *mp)
1296{
1297
1298 mac_init_label(&mp->mnt_mntlabel);
1299 mac_init_label(&mp->mnt_fslabel);
1300 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
1301 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
1302#ifdef MAC_DEBUG
1303 atomic_add_int(&nmacmounts, 1);
1304#endif
1305}
1306
1307static void
1308mac_init_pipe_label(struct label *label)
1309{
1310
1311 mac_init_label(label);
1312 MAC_PERFORM(init_pipe_label, label);
1313#ifdef MAC_DEBUG
1314 atomic_add_int(&nmacpipes, 1);
1315#endif
1316}
1317
1318void
1319mac_init_pipe(struct pipe *pipe)
1320{
1321 struct label *label;
1322
1323 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1324 pipe->pipe_label = label;
1325 pipe->pipe_peer->pipe_label = label;
1326 mac_init_pipe_label(label);
1327}
1328
1329static int
1330mac_init_socket_label(struct label *label, int flag)
1331{
1332 int error;
1333
1334 mac_init_label(label);
1335
1336 MAC_CHECK(init_socket_label, label, flag);
1337 if (error) {
1338 MAC_PERFORM(destroy_socket_label, label);
1339 mac_destroy_label(label);
1340 }
1341
1342#ifdef MAC_DEBUG
1343 if (error == 0)
1344 atomic_add_int(&nmacsockets, 1);
1345#endif
1346
1347 return (error);
1348}
1349
1350static int
1351mac_init_socket_peer_label(struct label *label, int flag)
1352{
1353 int error;
1354
1355 mac_init_label(label);
1356
1357 MAC_CHECK(init_socket_peer_label, label, flag);
1358 if (error) {
1359 MAC_PERFORM(destroy_socket_label, label);
1360 mac_destroy_label(label);
1361 }
1362
1363 return (error);
1364}
1365
1366int
1367mac_init_socket(struct socket *socket, int flag)
1368{
1369 int error;
1370
1371 error = mac_init_socket_label(&socket->so_label, flag);
1372 if (error)
1373 return (error);
1374
1375 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
1376 if (error)
1377 mac_destroy_socket_label(&socket->so_label);
1378
1379 return (error);
1380}
1381
1382static void
1383mac_init_vnode_label(struct label *label)
1384{
1385
1386 mac_init_label(label);
1387 MAC_PERFORM(init_vnode_label, label);
1388#ifdef MAC_DEBUG
1389 atomic_add_int(&nmacvnodes, 1);
1390#endif
1391}
1392
1393void
1394mac_init_vnode(struct vnode *vp)
1395{
1396
1397 mac_init_vnode_label(&vp->v_label);
1398}
1399
1400void
1401mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1402{
1403
1404 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1405 mac_destroy_label(&bpf_d->bd_label);
1406#ifdef MAC_DEBUG
1407 atomic_subtract_int(&nmacbpfdescs, 1);
1408#endif
1409}
1410
1411static void
1412mac_destroy_cred_label(struct label *label)
1413{
1414
1415 MAC_PERFORM(destroy_cred_label, label);
1416 mac_destroy_label(label);
1417#ifdef MAC_DEBUG
1418 atomic_subtract_int(&nmaccreds, 1);
1419#endif
1420}
1421
1422void
1423mac_destroy_cred(struct ucred *cred)
1424{
1425
1426 mac_destroy_cred_label(&cred->cr_label);
1427}
1428
1429void
1430mac_destroy_devfsdirent(struct devfs_dirent *de)
1431{
1432
1433 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1434 mac_destroy_label(&de->de_label);
1435#ifdef MAC_DEBUG
1436 atomic_subtract_int(&nmacdevfsdirents, 1);
1437#endif
1438}
1439
1440static void
1441mac_destroy_ifnet_label(struct label *label)
1442{
1443
1444 MAC_PERFORM(destroy_ifnet_label, label);
1445 mac_destroy_label(label);
1446#ifdef MAC_DEBUG
1447 atomic_subtract_int(&nmacifnets, 1);
1448#endif
1449}
1450
1451void
1452mac_destroy_ifnet(struct ifnet *ifp)
1453{
1454
1455 mac_destroy_ifnet_label(&ifp->if_label);
1456}
1457
1458void
1459mac_destroy_ipq(struct ipq *ipq)
1460{
1461
1462 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1463 mac_destroy_label(&ipq->ipq_label);
1464#ifdef MAC_DEBUG
1465 atomic_subtract_int(&nmacipqs, 1);
1466#endif
1467}
1468
1469void
1470mac_destroy_mbuf(struct mbuf *m)
1471{
1472
1473 MAC_PERFORM(destroy_mbuf_label, &m->m_pkthdr.label);
1474 mac_destroy_label(&m->m_pkthdr.label);
1475#ifdef MAC_DEBUG
1476 atomic_subtract_int(&nmacmbufs, 1);
1477#endif
1478}
1479
1480void
1481mac_destroy_mount(struct mount *mp)
1482{
1483
1484 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1485 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1486 mac_destroy_label(&mp->mnt_fslabel);
1487 mac_destroy_label(&mp->mnt_mntlabel);
1488#ifdef MAC_DEBUG
1489 atomic_subtract_int(&nmacmounts, 1);
1490#endif
1491}
1492
1493static void
1494mac_destroy_pipe_label(struct label *label)
1495{
1496
1497 MAC_PERFORM(destroy_pipe_label, label);
1498 mac_destroy_label(label);
1499#ifdef MAC_DEBUG
1500 atomic_subtract_int(&nmacpipes, 1);
1501#endif
1502}
1503
1504void
1505mac_destroy_pipe(struct pipe *pipe)
1506{
1507
1508 mac_destroy_pipe_label(pipe->pipe_label);
1509 free(pipe->pipe_label, M_MACPIPELABEL);
1510}
1511
1512static void
1513mac_destroy_socket_label(struct label *label)
1514{
1515
1516 MAC_PERFORM(destroy_socket_label, label);
1517 mac_destroy_label(label);
1518#ifdef MAC_DEBUG
1519 atomic_subtract_int(&nmacsockets, 1);
1520#endif
1521}
1522
1523static void
1524mac_destroy_socket_peer_label(struct label *label)
1525{
1526
1527 MAC_PERFORM(destroy_socket_peer_label, label);
1528 mac_destroy_label(label);
1529}
1530
1531void
1532mac_destroy_socket(struct socket *socket)
1533{
1534
1535 mac_destroy_socket_label(&socket->so_label);
1536 mac_destroy_socket_peer_label(&socket->so_peerlabel);
1537}
1538
1539static void
1540mac_destroy_vnode_label(struct label *label)
1541{
1542
1543 MAC_PERFORM(destroy_vnode_label, label);
1544 mac_destroy_label(label);
1545#ifdef MAC_DEBUG
1546 atomic_subtract_int(&nmacvnodes, 1);
1547#endif
1548}
1549
1550void
1551mac_destroy_vnode(struct vnode *vp)
1552{
1553
1554 mac_destroy_vnode_label(&vp->v_label);
1555}
1556
1557static void
1558mac_copy_pipe_label(struct label *src, struct label *dest)
1559{
1560
1561 MAC_PERFORM(copy_pipe_label, src, dest);
1562}
1563
1564static void
1565mac_copy_vnode_label(struct label *src, struct label *dest)
1566{
1567
1568 MAC_PERFORM(copy_vnode_label, src, dest);
1569}
1570
1571static int
1572mac_check_structmac_consistent(struct mac *mac)
1573{
1574
1575 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1576 return (EINVAL);
1577
1578 return (0);
1579}
1580
1581static int
1582mac_externalize_cred_label(struct label *label, char *elements,
1583 char *outbuf, size_t outbuflen, int flags)
1584{
1585 int error;
1586
1587 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1588
1589 return (error);
1590}
1591
1592static int
1593mac_externalize_ifnet_label(struct label *label, char *elements,
1594 char *outbuf, size_t outbuflen, int flags)
1595{
1596 int error;
1597
1598 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1599
1600 return (error);
1601}
1602
1603static int
1604mac_externalize_pipe_label(struct label *label, char *elements,
1605 char *outbuf, size_t outbuflen, int flags)
1606{
1607 int error;
1608
1609 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1610
1611 return (error);
1612}
1613
1614static int
1615mac_externalize_socket_label(struct label *label, char *elements,
1616 char *outbuf, size_t outbuflen, int flags)
1617{
1618 int error;
1619
1620 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1621
1622 return (error);
1623}
1624
1625static int
1626mac_externalize_socket_peer_label(struct label *label, char *elements,
1627 char *outbuf, size_t outbuflen, int flags)
1628{
1629 int error;
1630
1631 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1632
1633 return (error);
1634}
1635
1636static int
1637mac_externalize_vnode_label(struct label *label, char *elements,
1638 char *outbuf, size_t outbuflen, int flags)
1639{
1640 int error;
1641
1642 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1643
1644 return (error);
1645}
1646
1647static int
1648mac_externalize_vnode_oldmac(struct label *label, struct oldmac *extmac)
1649{
1650 int error;
1651
1652 MAC_CHECK(externalize_vnode_oldmac, label, extmac);
1653
1654 return (error);
1655}
1656
1657static int
1658mac_internalize_cred_label(struct label *label, char *string)
1659{
1660 int error;
1661
1662 MAC_INTERNALIZE(cred_label, label, string);
1663
1664 return (error);
1665}
1666
1667static int
1668mac_internalize_ifnet_label(struct label *label, char *string)
1669{
1670 int error;
1671
1672 MAC_INTERNALIZE(ifnet_label, label, string);
1673
1674 return (error);
1675}
1676
1677static int
1678mac_internalize_pipe_label(struct label *label, char *string)
1679{
1680 int error;
1681
1682 MAC_INTERNALIZE(pipe_label, label, string);
1683
1684 return (error);
1685}
1686
1687static int
1688mac_internalize_socket_label(struct label *label, char *string)
1689{
1690 int error;
1691
1692 MAC_INTERNALIZE(socket_label, label, string);
1693
1694 return (error);
1695}
1696
1697static int
1698mac_internalize_vnode_label(struct label *label, char *string)
1699{
1700 int error;
1701
1702 MAC_INTERNALIZE(vnode_label, label, string);
1703
1704 return (error);
1705}
1706
1707/*
1708 * Initialize MAC label for the first kernel process, from which other
1709 * kernel processes and threads are spawned.
1710 */
1711void
1712mac_create_proc0(struct ucred *cred)
1713{
1714
1715 MAC_PERFORM(create_proc0, cred);
1716}
1717
1718/*
1719 * Initialize MAC label for the first userland process, from which other
1720 * userland processes and threads are spawned.
1721 */
1722void
1723mac_create_proc1(struct ucred *cred)
1724{
1725
1726 MAC_PERFORM(create_proc1, cred);
1727}
1728
1729void
1730mac_thread_userret(struct thread *td)
1731{
1732
1733 MAC_PERFORM(thread_userret, td);
1734}
1735
1736/*
1737 * When a new process is created, its label must be initialized. Generally,
1738 * this involves inheritence from the parent process, modulo possible
1739 * deltas. This function allows that processing to take place.
1740 */
1741void
1742mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1743{
1744
1745 MAC_PERFORM(create_cred, parent_cred, child_cred);
1746}
1747
1748void
1749mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
1750{
1751
1752 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
1753}
1754
1755void
1756mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
1757{
1758
1759 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
1760}
1761
1762/*
1763 * Support callout for policies that manage their own externalization
1764 * using extended attributes.
1765 */
1766static int
1767mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
1768{
1769 int error;
1770
1771 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
1772 &mp->mnt_fslabel);
1773
1774 return (error);
1775}
1776
1777/*
1778 * Given an externalized mac label, internalize it and stamp it on a
1779 * vnode.
1780 */
1781static int
1782mac_update_vnode_from_externalized(struct vnode *vp, struct oldmac *extmac)
1783{
1784 int error;
1785
1786 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1787
1788 return (error);
1789}
1790
1791/*
1792 * Call out to individual policies to update the label in a vnode from
1793 * the mountpoint.
1794 */
1795void
1796mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1797{
1798
1799 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1800 &mp->mnt_fslabel);
1801
1802 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1803 if (mac_cache_fslabel_in_vnode)
1804 vp->v_vflag |= VV_CACHEDLABEL;
1805}
1806
1807/*
1808 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1809 * to store label data. Can be referenced by filesystems supporting
1810 * extended attributes.
1811 */
1812int
1813vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1814{
1815 struct vnode *vp = ap->a_vp;
1816 struct oldmac extmac;
1817 int buflen, error;
1818
1819 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1820
1821 /*
1822 * Call out to external policies first. Order doesn't really
1823 * matter, as long as failure of one assures failure of all.
1824 */
1825 error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1826 if (error)
1827 return (error);
1828
1829 buflen = sizeof(extmac);
1830 error = vn_extattr_get(vp, IO_NODELOCKED,
1831 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1832 (char *)&extmac, curthread);
1833 switch (error) {
1834 case 0:
1835 /* Got it */
1836 break;
1837
1838 case ENOATTR:
1839 /*
1840 * Use the label from the mount point.
1841 */
1842 mac_update_vnode_from_mount(vp, vp->v_mount);
1843 return (0);
1844
1845 case EOPNOTSUPP:
1846 default:
1847 /* Fail horribly. */
1848 return (error);
1849 }
1850
1851 if (buflen != sizeof(extmac))
1852 error = EPERM; /* Fail very closed. */
1853 if (error == 0)
1854 error = mac_update_vnode_from_externalized(vp, &extmac);
1855 if (error == 0)
1856 vp->v_vflag |= VV_CACHEDLABEL;
1857 else {
1858 struct vattr va;
1859
1860 printf("Corrupted label on %s",
1861 vp->v_mount->mnt_stat.f_mntonname);
1862 if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1863 printf(" inum %ld", va.va_fileid);
1864#ifdef MAC_DEBUG
1865 if (mac_debug_label_fallback) {
1866 printf(", falling back.\n");
1867 mac_update_vnode_from_mount(vp, vp->v_mount);
1868 error = 0;
1869 } else {
1870#endif
1871 printf(".\n");
1872 error = EPERM;
1873#ifdef MAC_DEBUG
1874 }
1875#endif
1876 }
1877
1878 return (error);
1879}
1880
1881/*
1882 * Make sure the vnode label is up-to-date. If EOPNOTSUPP, then we handle
1883 * the labeling activity outselves. Filesystems should be careful not
1884 * to change their minds regarding whether they support vop_refreshlabel()
1885 * for a vnode or not. Don't cache the vnode here, allow the file
1886 * system code to determine if it's safe to cache. If we update from
1887 * the mount, don't cache since a change to the mount label should affect
1888 * all vnodes.
1889 */
1890static int
1891vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1892{
1893 int error;
1894
1895 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1896
1897 if (vp->v_mount == NULL) {
1898/*
1899 Eventually, we probably want to special-case refreshing
1900 of deadfs vnodes, and if there's a lock-free race somewhere,
1901 that case might be handled here.
1902
1903 mac_update_vnode_deadfs(vp);
1904 return (0);
1905 */
1906 /* printf("vn_refreshlabel: null v_mount\n"); */
1907 if (vp->v_type != VNON)
1908 printf(
1909 "vn_refreshlabel: null v_mount with non-VNON\n");
1910 return (EBADF);
1911 }
1912
1913 if (vp->v_vflag & VV_CACHEDLABEL) {
1914 mac_vnode_label_cache_hits++;
1915 return (0);
1916 } else
1917 mac_vnode_label_cache_misses++;
1918
1919 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1920 mac_update_vnode_from_mount(vp, vp->v_mount);
1921 return (0);
1922 }
1923
1924 error = VOP_REFRESHLABEL(vp, cred, curthread);
1925 switch (error) {
1926 case EOPNOTSUPP:
1927 /*
1928 * If labels are not supported on this vnode, fall back to
1929 * the label in the mount and propagate it to the vnode.
1930 * There should probably be some sort of policy/flag/decision
1931 * about doing this.
1932 */
1933 mac_update_vnode_from_mount(vp, vp->v_mount);
1934 error = 0;
1935 default:
1936 return (error);
1937 }
1938}
1939
1940/*
1941 * Helper function for file systems using the vop_std*_ea() calls. This
1942 * function must be called after EA service is available for the vnode,
1943 * but before it's hooked up to the namespace so that the node persists
1944 * if there's a crash, or before it can be accessed. On successful
1945 * commit of the label to disk (etc), do cache the label.
1946 */
1947int
1948vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1949{
1950 struct oldmac extmac;
1951 int error;
1952
1953 ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1954 if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1955 mac_update_vnode_from_mount(tvp, tvp->v_mount);
1956 } else {
1957 error = vn_refreshlabel(dvp, cred);
1958 if (error)
1959 return (error);
1960
1961 /*
1962 * Stick the label in the vnode. Then try to write to
1963 * disk. If we fail, return a failure to abort the
1964 * create operation. Really, this failure shouldn't
1965 * happen except in fairly unusual circumstances (out
1966 * of disk, etc).
1967 */
1968 mac_create_vnode(cred, dvp, tvp);
1969
1970 error = mac_stdcreatevnode_ea(tvp);
1971 if (error)
1972 return (error);
1973
1974 /*
1975 * XXX: Eventually this will go away and all policies will
1976 * directly manage their extended attributes.
1977 */
1978 error = mac_externalize_vnode_oldmac(&tvp->v_label, &extmac);
1979 if (error)
1980 return (error);
1981
1982 error = vn_extattr_set(tvp, IO_NODELOCKED,
1983 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1984 sizeof(extmac), (char *)&extmac, curthread);
1985 if (error == 0)
1986 tvp->v_vflag |= VV_CACHEDLABEL;
1987 else {
1988#if 0
1989 /*
1990 * In theory, we could have fall-back behavior here.
1991 * It would probably be incorrect.
1992 */
1993#endif
1994 return (error);
1995 }
1996 }
1997
1998 return (0);
1999}
2000
2001void
2002mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
2003{
2004 int error;
2005
2006 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
2007
2008 error = vn_refreshlabel(vp, old);
2009 if (error) {
2010 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
2011 error);
2012 printf("mac_execve_transition: using old vnode label\n");
2013 }
2014
2015 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
2016}
2017
2018int
2019mac_execve_will_transition(struct ucred *old, struct vnode *vp)
2020{
2021 int error, result;
2022
2023 error = vn_refreshlabel(vp, old);
2024 if (error)
2025 return (error);
2026
2027 result = 0;
2028 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
2029
2030 return (result);
2031}
2032
2033int
2034mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
2035{
2036 int error;
2037
2038 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
2039
2040 if (!mac_enforce_fs)
2041 return (0);
2042
2043 error = vn_refreshlabel(vp, cred);
2044 if (error)
2045 return (error);
2046
2047 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
2048 return (error);
2049}
2050
2051int
2052mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
2053{
2054 int error;
2055
2056 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
2057
2058 if (!mac_enforce_fs)
2059 return (0);
2060
2061 error = vn_refreshlabel(dvp, cred);
2062 if (error)
2063 return (error);
2064
2065 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
2066 return (error);
2067}
2068
2069int
2070mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
2071{
2072 int error;
2073
2074 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
2075
2076 if (!mac_enforce_fs)
2077 return (0);
2078
2079 error = vn_refreshlabel(dvp, cred);
2080 if (error)
2081 return (error);
2082
2083 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
2084 return (error);
2085}
2086
2087int
2088mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2089 struct componentname *cnp, struct vattr *vap)
2090{
2091 int error;
2092
2093 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
2094
2095 if (!mac_enforce_fs)
2096 return (0);
2097
2098 error = vn_refreshlabel(dvp, cred);
2099 if (error)
2100 return (error);
2101
2102 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
2103 return (error);
2104}
2105
2106int
2107mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
2108 struct componentname *cnp)
2109{
2110 int error;
2111
2112 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
2113 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
2114
2115 if (!mac_enforce_fs)
2116 return (0);
2117
2118 error = vn_refreshlabel(dvp, cred);
2119 if (error)
2120 return (error);
2121 error = vn_refreshlabel(vp, cred);
2122 if (error)
2123 return (error);
2124
2125 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
2126 &vp->v_label, cnp);
2127 return (error);
2128}
2129
2130int
2131mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2132 acl_type_t type)
2133{
2134 int error;
2135
2136 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
2137
2138 if (!mac_enforce_fs)
2139 return (0);
2140
2141 error = vn_refreshlabel(vp, cred);
2142 if (error)
2143 return (error);
2144
2145 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
2146 return (error);
2147}
2148
2149int
2150mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
2151{
2152 int error;
2153
2154 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
2155
2156 if (!mac_enforce_process && !mac_enforce_fs)
2157 return (0);
2158
2159 error = vn_refreshlabel(vp, cred);
2160 if (error)
2161 return (error);
2162 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
2163
2164 return (error);
2165}
2166
2167int
2168mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
2169{
2170 int error;
2171
2172 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
2173
2174 if (!mac_enforce_fs)
2175 return (0);
2176
2177 error = vn_refreshlabel(vp, cred);
2178 if (error)
2179 return (error);
2180
2181 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
2182 return (error);
2183}
2184
2185int
2186mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2187 int attrnamespace, const char *name, struct uio *uio)
2188{
2189 int error;
2190
2191 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
2192
2193 if (!mac_enforce_fs)
2194 return (0);
2195
2196 error = vn_refreshlabel(vp, cred);
2197 if (error)
2198 return (error);
2199
2200 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
2201 attrnamespace, name, uio);
2202 return (error);
2203}
2204
2205int
2206mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2207 struct vnode *vp, struct componentname *cnp)
2208{
2209 int error;
2210
2211 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
2212 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
2213
2214 if (!mac_enforce_fs)
2215 return (0);
2216
2217 error = vn_refreshlabel(dvp, cred);
2218 if (error)
2219 return (error);
2220
2221 error = vn_refreshlabel(vp, cred);
2222 if (error)
2223 return (error);
2224
2225 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
2226 &vp->v_label, cnp);
2227 return (error);
2228}
2229
2230int
2231mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2232 struct componentname *cnp)
2233{
2234 int error;
2235
2236 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
2237
2238 if (!mac_enforce_fs)
2239 return (0);
2240
2241 error = vn_refreshlabel(dvp, cred);
2242 if (error)
2243 return (error);
2244
2245 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
2246 return (error);
2247}
2248
2249int
2250mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
2251{
2252 int error;
2253
2254 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
2255
2256 if (!mac_enforce_fs || !mac_enforce_vm)
2257 return (0);
2258
2259 error = vn_refreshlabel(vp, cred);
2260 if (error)
2261 return (error);
2262
2263 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
2264 return (error);
2265}
2266
2267void
2268mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
2269{
2270 int result = *prot;
2271
2272 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
2273
2274 if (!mac_enforce_fs || !mac_enforce_vm)
2275 return;
2276
2277 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
2278 &result);
2279
2280 *prot = result;
2281}
2282
2283int
2284mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
2285{
2286 int error;
2287
2288 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
2289
2290 if (!mac_enforce_fs || !mac_enforce_vm)
2291 return (0);
2292
2293 error = vn_refreshlabel(vp, cred);
2294 if (error)
2295 return (error);
2296
2297 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
2298 return (error);
2299}
2300
2301int
2302mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
2303{
2304 int error;
2305
2306 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
2307
2308 if (!mac_enforce_fs)
2309 return (0);
2310
2311 error = vn_refreshlabel(vp, cred);
2312 if (error)
2313 return (error);
2314
2315 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
2316 return (error);
2317}
2318
2319int
2320mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2321 struct vnode *vp)
2322{
2323 int error;
2324
2325 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
2326
2327 if (!mac_enforce_fs)
2328 return (0);
2329
2330 error = vn_refreshlabel(vp, active_cred);
2331 if (error)
2332 return (error);
2333
2334 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
2335 &vp->v_label);
2336
2337 return (error);
2338}
2339
2340int
2341mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2342 struct vnode *vp)
2343{
2344 int error;
2345
2346 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
2347
2348 if (!mac_enforce_fs)
2349 return (0);
2350
2351 error = vn_refreshlabel(vp, active_cred);
2352 if (error)
2353 return (error);
2354
2355 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
2356 &vp->v_label);
2357
2358 return (error);
2359}
2360
2361int
2362mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
2363{
2364 int error;
2365
2366 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
2367
2368 if (!mac_enforce_fs)
2369 return (0);
2370
2371 error = vn_refreshlabel(dvp, cred);
2372 if (error)
2373 return (error);
2374
2375 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
2376 return (error);
2377}
2378
2379int
2380mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
2381{
2382 int error;
2383
2384 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
2385
2386 if (!mac_enforce_fs)
2387 return (0);
2388
2389 error = vn_refreshlabel(vp, cred);
2390 if (error)
2391 return (error);
2392
2393 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
2394 return (error);
2395}
2396
2397static int
2398mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2399 struct label *newlabel)
2400{
2401 int error;
2402
2403 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
2404
2405 error = vn_refreshlabel(vp, cred);
2406 if (error)
2407 return (error);
2408
2409 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
2410
2411 return (error);
2412}
2413
2414int
2415mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2416 struct vnode *vp, struct componentname *cnp)
2417{
2418 int error;
2419
2420 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
2421 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
2422
2423 if (!mac_enforce_fs)
2424 return (0);
2425
2426 error = vn_refreshlabel(dvp, cred);
2427 if (error)
2428 return (error);
2429 error = vn_refreshlabel(vp, cred);
2430 if (error)
2431 return (error);
2432
2433 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
2434 &vp->v_label, cnp);
2435 return (error);
2436}
2437
2438int
2439mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2440 struct vnode *vp, int samedir, struct componentname *cnp)
2441{
2442 int error;
2443
2444 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
2445 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
2446
2447 if (!mac_enforce_fs)
2448 return (0);
2449
2450 error = vn_refreshlabel(dvp, cred);
2451 if (error)
2452 return (error);
2453 if (vp != NULL) {
2454 error = vn_refreshlabel(vp, cred);
2455 if (error)
2456 return (error);
2457 }
2458 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
2459 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
2460 return (error);
2461}
2462
2463int
2464mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
2465{
2466 int error;
2467
2468 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
2469
2470 if (!mac_enforce_fs)
2471 return (0);
2472
2473 error = vn_refreshlabel(vp, cred);
2474 if (error)
2475 return (error);
2476
2477 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
2478 return (error);
2479}
2480
2481int
2482mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
2483 struct acl *acl)
2484{
2485 int error;
2486
2487 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2488
2489 if (!mac_enforce_fs)
2490 return (0);
2491
2492 error = vn_refreshlabel(vp, cred);
2493 if (error)
2494 return (error);
2495
2496 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2497 return (error);
2498}
2499
2500int
2501mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2502 int attrnamespace, const char *name, struct uio *uio)
2503{
2504 int error;
2505
2506 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2507
2508 if (!mac_enforce_fs)
2509 return (0);
2510
2511 error = vn_refreshlabel(vp, cred);
2512 if (error)
2513 return (error);
2514
2515 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2516 attrnamespace, name, uio);
2517 return (error);
2518}
2519
2520int
2521mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2522{
2523 int error;
2524
2525 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2526
2527 if (!mac_enforce_fs)
2528 return (0);
2529
2530 error = vn_refreshlabel(vp, cred);
2531 if (error)
2532 return (error);
2533
2534 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2535 return (error);
2536}
2537
2538int
2539mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2540{
2541 int error;
2542
2543 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2544
2545 if (!mac_enforce_fs)
2546 return (0);
2547
2548 error = vn_refreshlabel(vp, cred);
2549 if (error)
2550 return (error);
2551
2552 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2553 return (error);
2554}
2555
2556int
2557mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2558 gid_t gid)
2559{
2560 int error;
2561
2562 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2563
2564 if (!mac_enforce_fs)
2565 return (0);
2566
2567 error = vn_refreshlabel(vp, cred);
2568 if (error)
2569 return (error);
2570
2571 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2572 return (error);
2573}
2574
2575int
2576mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2577 struct timespec atime, struct timespec mtime)
2578{
2579 int error;
2580
2581 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2582
2583 if (!mac_enforce_fs)
2584 return (0);
2585
2586 error = vn_refreshlabel(vp, cred);
2587 if (error)
2588 return (error);
2589
2590 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2591 mtime);
2592 return (error);
2593}
2594
2595int
2596mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2597 struct vnode *vp)
2598{
2599 int error;
2600
2601 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2602
2603 if (!mac_enforce_fs)
2604 return (0);
2605
2606 error = vn_refreshlabel(vp, active_cred);
2607 if (error)
2608 return (error);
2609
2610 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2611 &vp->v_label);
2612 return (error);
2613}
2614
2615int
2616mac_check_vnode_swapon(struct ucred *cred, struct vnode *vp)
2617{
2618 int error;
2619
2620 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_swapon");
2621
2617 if (!mac_enforce_fs)
2622 if (!mac_enforce_fs)
2618 return (0);
2619
2620 error = vn_refreshlabel(vp, cred);
2621 if (error)
2622 return (error);
2623
2624 MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label);
2625 return (error);
2626}
2627
2628int
2629mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2630 struct vnode *vp)
2631{
2632 int error;
2633
2634 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2635
2636 if (!mac_enforce_fs)
2637 return (0);
2638
2639 error = vn_refreshlabel(vp, active_cred);
2640 if (error)
2641 return (error);
2642
2643 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2644 &vp->v_label);
2645
2646 return (error);
2647}
2648
2649/*
2650 * When relabeling a process, call out to the policies for the maximum
2651 * permission allowed for each object type we know about in its
2652 * memory space, and revoke access (in the least surprising ways we
2653 * know) when necessary. The process lock is not held here.
2654 */
2655static void
2656mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2657{
2658
2659 /* XXX freeze all other threads */
2660 mac_cred_mmapped_drop_perms_recurse(td, cred,
2661 &td->td_proc->p_vmspace->vm_map);
2662 /* XXX allow other threads to continue */
2663}
2664
2665static __inline const char *
2666prot2str(vm_prot_t prot)
2667{
2668
2669 switch (prot & VM_PROT_ALL) {
2670 case VM_PROT_READ:
2671 return ("r--");
2672 case VM_PROT_READ | VM_PROT_WRITE:
2673 return ("rw-");
2674 case VM_PROT_READ | VM_PROT_EXECUTE:
2675 return ("r-x");
2676 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2677 return ("rwx");
2678 case VM_PROT_WRITE:
2679 return ("-w-");
2680 case VM_PROT_EXECUTE:
2681 return ("--x");
2682 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2683 return ("-wx");
2684 default:
2685 return ("---");
2686 }
2687}
2688
2689static void
2690mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2691 struct vm_map *map)
2692{
2693 struct vm_map_entry *vme;
2694 int result;
2695 vm_prot_t revokeperms;
2696 vm_object_t object;
2697 vm_ooffset_t offset;
2698 struct vnode *vp;
2699
2700 if (!mac_mmap_revocation)
2701 return;
2702
2703 vm_map_lock_read(map);
2704 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2705 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2706 mac_cred_mmapped_drop_perms_recurse(td, cred,
2707 vme->object.sub_map);
2708 continue;
2709 }
2710 /*
2711 * Skip over entries that obviously are not shared.
2712 */
2713 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2714 !vme->max_protection)
2715 continue;
2716 /*
2717 * Drill down to the deepest backing object.
2718 */
2719 offset = vme->offset;
2720 object = vme->object.vm_object;
2721 if (object == NULL)
2722 continue;
2723 while (object->backing_object != NULL) {
2724 object = object->backing_object;
2725 offset += object->backing_object_offset;
2726 }
2727 /*
2728 * At the moment, vm_maps and objects aren't considered
2729 * by the MAC system, so only things with backing by a
2730 * normal object (read: vnodes) are checked.
2731 */
2732 if (object->type != OBJT_VNODE)
2733 continue;
2734 vp = (struct vnode *)object->handle;
2735 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2736 result = vme->max_protection;
2737 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2738 VOP_UNLOCK(vp, 0, td);
2739 /*
2740 * Find out what maximum protection we may be allowing
2741 * now but a policy needs to get removed.
2742 */
2743 revokeperms = vme->max_protection & ~result;
2744 if (!revokeperms)
2745 continue;
2746 printf("pid %ld: revoking %s perms from %#lx:%ld "
2747 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2748 prot2str(revokeperms), (u_long)vme->start,
2749 (long)(vme->end - vme->start),
2750 prot2str(vme->max_protection), prot2str(vme->protection));
2751 vm_map_lock_upgrade(map);
2752 /*
2753 * This is the really simple case: if a map has more
2754 * max_protection than is allowed, but it's not being
2755 * actually used (that is, the current protection is
2756 * still allowed), we can just wipe it out and do
2757 * nothing more.
2758 */
2759 if ((vme->protection & revokeperms) == 0) {
2760 vme->max_protection -= revokeperms;
2761 } else {
2762 if (revokeperms & VM_PROT_WRITE) {
2763 /*
2764 * In the more complicated case, flush out all
2765 * pending changes to the object then turn it
2766 * copy-on-write.
2767 */
2768 vm_object_reference(object);
2769 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2770 vm_object_page_clean(object,
2771 OFF_TO_IDX(offset),
2772 OFF_TO_IDX(offset + vme->end - vme->start +
2773 PAGE_MASK),
2774 OBJPC_SYNC);
2775 VOP_UNLOCK(vp, 0, td);
2776 vm_object_deallocate(object);
2777 /*
2778 * Why bother if there's no read permissions
2779 * anymore? For the rest, we need to leave
2780 * the write permissions on for COW, or
2781 * remove them entirely if configured to.
2782 */
2783 if (!mac_mmap_revocation_via_cow) {
2784 vme->max_protection &= ~VM_PROT_WRITE;
2785 vme->protection &= ~VM_PROT_WRITE;
2786 } if ((revokeperms & VM_PROT_READ) == 0)
2787 vme->eflags |= MAP_ENTRY_COW |
2788 MAP_ENTRY_NEEDS_COPY;
2789 }
2790 if (revokeperms & VM_PROT_EXECUTE) {
2791 vme->max_protection &= ~VM_PROT_EXECUTE;
2792 vme->protection &= ~VM_PROT_EXECUTE;
2793 }
2794 if (revokeperms & VM_PROT_READ) {
2795 vme->max_protection = 0;
2796 vme->protection = 0;
2797 }
2798 pmap_protect(map->pmap, vme->start, vme->end,
2799 vme->protection & ~revokeperms);
2800 vm_map_simplify_entry(map, vme);
2801 }
2802 vm_map_lock_downgrade(map);
2803 }
2804 vm_map_unlock_read(map);
2805}
2806
2807/*
2808 * When the subject's label changes, it may require revocation of privilege
2809 * to mapped objects. This can't be done on-the-fly later with a unified
2810 * buffer cache.
2811 */
2812static void
2813mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2814{
2815
2816 MAC_PERFORM(relabel_cred, cred, newlabel);
2817}
2818
2819void
2820mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2821{
2822
2823 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2824}
2825
2826void
2827mac_create_ifnet(struct ifnet *ifnet)
2828{
2829
2830 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2831}
2832
2833void
2834mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2835{
2836
2837 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2838}
2839
2840void
2841mac_create_socket(struct ucred *cred, struct socket *socket)
2842{
2843
2844 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2845}
2846
2847void
2848mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2849{
2850
2851 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2852}
2853
2854void
2855mac_create_socket_from_socket(struct socket *oldsocket,
2856 struct socket *newsocket)
2857{
2858
2859 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2860 newsocket, &newsocket->so_label);
2861}
2862
2863static void
2864mac_relabel_socket(struct ucred *cred, struct socket *socket,
2865 struct label *newlabel)
2866{
2867
2868 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2869}
2870
2871static void
2872mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2873{
2874
2875 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2876}
2877
2878void
2879mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2880{
2881
2882 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2883 socket, &socket->so_peerlabel);
2884}
2885
2886void
2887mac_set_socket_peer_from_socket(struct socket *oldsocket,
2888 struct socket *newsocket)
2889{
2890
2891 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2892 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2893}
2894
2895void
2896mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2897{
2898
2899 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2900 datagram, &datagram->m_pkthdr.label);
2901}
2902
2903void
2904mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2905{
2906
2907 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2908 fragment, &fragment->m_pkthdr.label);
2909}
2910
2911void
2912mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2913{
2914
2915 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2916 &ipq->ipq_label);
2917}
2918
2919void
2920mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2921{
2922
2923 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2924 newmbuf, &newmbuf->m_pkthdr.label);
2925}
2926
2927void
2928mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2929{
2930
2931 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2932 &mbuf->m_pkthdr.label);
2933}
2934
2935void
2936mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2937{
2938
2939 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2940 &mbuf->m_pkthdr.label);
2941}
2942
2943void
2944mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2945{
2946
2947 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2948 &mbuf->m_pkthdr.label);
2949}
2950
2951void
2952mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2953 struct mbuf *newmbuf)
2954{
2955
2956 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2957 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2958 &newmbuf->m_pkthdr.label);
2959}
2960
2961void
2962mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2963{
2964
2965 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2966 newmbuf, &newmbuf->m_pkthdr.label);
2967}
2968
2969int
2970mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2971{
2972 int result;
2973
2974 result = 1;
2975 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2976 ipq, &ipq->ipq_label);
2977
2978 return (result);
2979}
2980
2981void
2982mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2983{
2984
2985 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2986 &ipq->ipq_label);
2987}
2988
2989void
2990mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2991{
2992
2993 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2994 &mbuf->m_pkthdr.label);
2995}
2996
2997void
2998mac_create_mount(struct ucred *cred, struct mount *mp)
2999{
3000
3001 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
3002 &mp->mnt_fslabel);
3003}
3004
3005void
3006mac_create_root_mount(struct ucred *cred, struct mount *mp)
3007{
3008
3009 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
3010 &mp->mnt_fslabel);
3011}
3012
3013int
3014mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
3015{
3016 int error;
3017
3018 if (!mac_enforce_network)
3019 return (0);
3020
3021 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
3022 &ifnet->if_label);
3023
3024 return (error);
3025}
3026
3027static int
3028mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
3029{
3030 int error;
3031
3032 MAC_CHECK(check_cred_relabel, cred, newlabel);
3033
3034 return (error);
3035}
3036
3037int
3038mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
3039{
3040 int error;
3041
3042 if (!mac_enforce_process)
3043 return (0);
3044
3045 MAC_CHECK(check_cred_visible, u1, u2);
3046
3047 return (error);
3048}
3049
3050int
3051mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
3052{
3053 int error;
3054
3055 if (!mac_enforce_network)
3056 return (0);
3057
3058 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
3059 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
3060 if_printf(ifnet, "not initialized\n");
3061
3062 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
3063 &mbuf->m_pkthdr.label);
3064
3065 return (error);
3066}
3067
3068int
3069mac_check_mount_stat(struct ucred *cred, struct mount *mount)
3070{
3071 int error;
3072
3073 if (!mac_enforce_fs)
3074 return (0);
3075
3076 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
3077
3078 return (error);
3079}
3080
3081int
3082mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
3083 void *data)
3084{
3085 int error;
3086
3087 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3088
3089 if (!mac_enforce_pipe)
3090 return (0);
3091
3092 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
3093
3094 return (error);
3095}
3096
3097int
3098mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
3099{
3100 int error;
3101
3102 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3103
3104 if (!mac_enforce_pipe)
3105 return (0);
3106
3107 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
3108
3109 return (error);
3110}
3111
3112int
3113mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
3114{
3115 int error;
3116
3117 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3118
3119 if (!mac_enforce_pipe)
3120 return (0);
3121
3122 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
3123
3124 return (error);
3125}
3126
3127static int
3128mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
3129 struct label *newlabel)
3130{
3131 int error;
3132
3133 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3134
3135 if (!mac_enforce_pipe)
3136 return (0);
3137
3138 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
3139
3140 return (error);
3141}
3142
3143int
3144mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
3145{
3146 int error;
3147
3148 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3149
3150 if (!mac_enforce_pipe)
3151 return (0);
3152
3153 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
3154
3155 return (error);
3156}
3157
3158int
3159mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
3160{
3161 int error;
3162
3163 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3164
3165 if (!mac_enforce_pipe)
3166 return (0);
3167
3168 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
3169
3170 return (error);
3171}
3172
3173int
3174mac_check_proc_debug(struct ucred *cred, struct proc *proc)
3175{
3176 int error;
3177
3178 PROC_LOCK_ASSERT(proc, MA_OWNED);
3179
3180 if (!mac_enforce_process)
3181 return (0);
3182
3183 MAC_CHECK(check_proc_debug, cred, proc);
3184
3185 return (error);
3186}
3187
3188int
3189mac_check_proc_sched(struct ucred *cred, struct proc *proc)
3190{
3191 int error;
3192
3193 PROC_LOCK_ASSERT(proc, MA_OWNED);
3194
3195 if (!mac_enforce_process)
3196 return (0);
3197
3198 MAC_CHECK(check_proc_sched, cred, proc);
3199
3200 return (error);
3201}
3202
3203int
3204mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
3205{
3206 int error;
3207
3208 PROC_LOCK_ASSERT(proc, MA_OWNED);
3209
3210 if (!mac_enforce_process)
3211 return (0);
3212
3213 MAC_CHECK(check_proc_signal, cred, proc, signum);
3214
3215 return (error);
3216}
3217
3218int
3219mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
3220 struct sockaddr *sockaddr)
3221{
3222 int error;
3223
3224 if (!mac_enforce_socket)
3225 return (0);
3226
3227 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
3228 sockaddr);
3229
3230 return (error);
3231}
3232
3233int
3234mac_check_socket_connect(struct ucred *cred, struct socket *socket,
3235 struct sockaddr *sockaddr)
3236{
3237 int error;
3238
3239 if (!mac_enforce_socket)
3240 return (0);
3241
3242 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
3243 sockaddr);
3244
3245 return (error);
3246}
3247
3248int
3249mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
3250{
3251 int error;
3252
3253 if (!mac_enforce_socket)
3254 return (0);
3255
3256 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
3257 &mbuf->m_pkthdr.label);
3258
3259 return (error);
3260}
3261
3262int
3263mac_check_socket_listen(struct ucred *cred, struct socket *socket)
3264{
3265 int error;
3266
3267 if (!mac_enforce_socket)
3268 return (0);
3269
3270 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
3271 return (error);
3272}
3273
3274int
3275mac_check_socket_receive(struct ucred *cred, struct socket *so)
3276{
3277 int error;
3278
3279 if (!mac_enforce_socket)
3280 return (0);
3281
3282 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
3283
3284 return (error);
3285}
3286
3287static int
3288mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
3289 struct label *newlabel)
3290{
3291 int error;
3292
3293 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
3294 newlabel);
3295
3296 return (error);
3297}
3298
3299int
3300mac_check_socket_send(struct ucred *cred, struct socket *so)
3301{
3302 int error;
3303
3304 if (!mac_enforce_socket)
3305 return (0);
3306
3307 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
3308
3309 return (error);
3310}
3311
3312int
3313mac_check_socket_visible(struct ucred *cred, struct socket *socket)
3314{
3315 int error;
3316
3317 if (!mac_enforce_socket)
3318 return (0);
3319
3320 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
3321
3322 return (error);
3323}
3324
3325int
3326mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3327 struct ifnet *ifnet)
3328{
3329 char *elements, *buffer;
3330 struct mac mac;
3331 int error;
3332
3333 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3334 if (error)
3335 return (error);
3336
3337 error = mac_check_structmac_consistent(&mac);
3338 if (error)
3339 return (error);
3340
3341 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3342
3343 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3344 if (error) {
3345 free(elements, M_MACTEMP);
3346 return (error);
3347 }
3348
3349 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3350
3351 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3352 buffer, mac.m_buflen, M_WAITOK);
3353 if (error == 0)
3354 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3355
3356 free(buffer, M_MACTEMP);
3357 free(elements, M_MACTEMP);
3358
3359 return (error);
3360}
3361
3362int
3363mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3364 struct ifnet *ifnet)
3365{
3366 struct label intlabel;
3367 struct mac mac;
3368 char *buffer;
3369 int error;
3370
3371 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3372 if (error)
3373 return (error);
3374
3375 error = mac_check_structmac_consistent(&mac);
3376 if (error)
3377 return (error);
3378
3379 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3380
3381 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3382 if (error) {
3383 free(buffer, M_MACTEMP);
3384 return (error);
3385 }
3386
3387 mac_init_ifnet_label(&intlabel);
3388 error = mac_internalize_ifnet_label(&intlabel, buffer);
3389 free(buffer, M_MACTEMP);
3390 if (error) {
3391 mac_destroy_ifnet_label(&intlabel);
3392 return (error);
3393 }
3394
3395 /*
3396 * XXX: Note that this is a redundant privilege check, since
3397 * policies impose this check themselves if required by the
3398 * policy. Eventually, this should go away.
3399 */
3400 error = suser_cred(cred, 0);
3401 if (error) {
3402 mac_destroy_ifnet_label(&intlabel);
3403 return (error);
3404 }
3405
3406 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3407 &intlabel);
3408 if (error) {
3409 mac_destroy_ifnet_label(&intlabel);
3410 return (error);
3411 }
3412
3413 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3414
3415 mac_destroy_ifnet_label(&intlabel);
3416 return (0);
3417}
3418
3419void
3420mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3421{
3422
3423 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3424}
3425
3426void
3427mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3428{
3429
3430 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3431}
3432
3433void
3434mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3435 struct devfs_dirent *de)
3436{
3437
3438 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3439 &de->de_label);
3440}
3441
3442static int
3443mac_stdcreatevnode_ea(struct vnode *vp)
3444{
3445 int error;
3446
3447 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
3448
3449 return (error);
3450}
3451
3452void
3453mac_create_devfs_directory(char *dirname, int dirnamelen,
3454 struct devfs_dirent *de)
3455{
3456
3457 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3458 &de->de_label);
3459}
3460
3461/*
3462 * When a new vnode is created, this call will initialize its label.
3463 */
3464void
3465mac_create_vnode(struct ucred *cred, struct vnode *parent,
3466 struct vnode *child)
3467{
3468 int error;
3469
3470 ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
3471 ASSERT_VOP_LOCKED(child, "mac_create_vnode");
3472
3473 error = vn_refreshlabel(parent, cred);
3474 if (error) {
3475 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
3476 error);
3477 printf("mac_create_vnode: using old vnode label\n");
3478 }
3479
3480 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
3481 &child->v_label);
3482}
3483
3484int
3485mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3486 struct mac *mac)
3487{
3488 struct label intlabel;
3489 char *buffer;
3490 int error;
3491
3492 error = mac_check_structmac_consistent(mac);
3493 if (error)
3494 return (error);
3495
3496 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3497
3498 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3499 if (error) {
3500 free(buffer, M_MACTEMP);
3501 return (error);
3502 }
3503
3504 mac_init_socket_label(&intlabel, M_WAITOK);
3505 error = mac_internalize_socket_label(&intlabel, buffer);
3506 free(buffer, M_MACTEMP);
3507 if (error) {
3508 mac_destroy_socket_label(&intlabel);
3509 return (error);
3510 }
3511
3512 mac_check_socket_relabel(cred, so, &intlabel);
3513 if (error) {
3514 mac_destroy_socket_label(&intlabel);
3515 return (error);
3516 }
3517
3518 mac_relabel_socket(cred, so, &intlabel);
3519
3520 mac_destroy_socket_label(&intlabel);
3521 return (0);
3522}
3523
3524int
3525mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3526{
3527 int error;
3528
3529 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3530
3531 error = mac_check_pipe_relabel(cred, pipe, label);
3532 if (error)
3533 return (error);
3534
3535 mac_relabel_pipe(cred, pipe, label);
3536
3537 return (0);
3538}
3539
3540int
3541mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3542 struct mac *mac)
3543{
3544 char *buffer, *elements;
3545 int error;
3546
3547 error = mac_check_structmac_consistent(mac);
3548 if (error)
3549 return (error);
3550
3551 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3552
3553 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3554 if (error) {
3555 free(elements, M_MACTEMP);
3556 return (error);
3557 }
3558
3559 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3560
3561 error = mac_externalize_socket_label(&so->so_label, elements,
3562 buffer, mac->m_buflen, M_WAITOK);
3563 if (error == 0)
3564 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3565
3566 free(buffer, M_MACTEMP);
3567 free(elements, M_MACTEMP);
3568
3569 return (error);
3570}
3571
3572int
3573mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3574 struct mac *mac)
3575{
3576 char *elements, *buffer;
3577 int error;
3578
3579 error = mac_check_structmac_consistent(mac);
3580 if (error)
3581 return (error);
3582
3583 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3584
3585 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3586 if (error) {
3587 free(elements, M_MACTEMP);
3588 return (error);
3589 }
3590
3591 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3592
3593 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3594 elements, buffer, mac->m_buflen, M_WAITOK);
3595 if (error == 0)
3596 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3597
3598 free(buffer, M_MACTEMP);
3599 free(elements, M_MACTEMP);
3600
3601 return (error);
3602}
3603
3604/*
3605 * Implementation of VOP_SETLABEL() that relies on extended attributes
3606 * to store label data. Can be referenced by filesystems supporting
3607 * extended attributes.
3608 */
3609int
3610vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3611{
3612 struct vnode *vp = ap->a_vp;
3613 struct label *intlabel = ap->a_label;
3614 struct oldmac extmac;
3615 int error;
3616
3617 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3618
3619 /*
3620 * XXX: Eventually call out to EA check/set calls here.
3621 * Be particularly careful to avoid race conditions,
3622 * consistency problems, and stability problems when
3623 * dealing with multiple EAs. In particular, we require
3624 * the ability to write multiple EAs on the same file in
3625 * a single transaction, which the current EA interface
3626 * does not provide.
3627 */
3628
3629 error = mac_externalize_vnode_oldmac(intlabel, &extmac);
3630 if (error)
3631 return (error);
3632
3633 error = vn_extattr_set(vp, IO_NODELOCKED,
3634 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3635 sizeof(extmac), (char *)&extmac, curthread);
3636 if (error)
3637 return (error);
3638
3639 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3640
3641 vp->v_vflag |= VV_CACHEDLABEL;
3642
3643 return (0);
3644}
3645
3646static int
3647vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3648{
3649 int error;
3650
3651 if (vp->v_mount == NULL) {
3652 /* printf("vn_setlabel: null v_mount\n"); */
3653 if (vp->v_type != VNON)
3654 printf("vn_setlabel: null v_mount with non-VNON\n");
3655 return (EBADF);
3656 }
3657
3658 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3659 return (EOPNOTSUPP);
3660
3661 /*
3662 * Multi-phase commit. First check the policies to confirm the
3663 * change is OK. Then commit via the filesystem. Finally,
3664 * update the actual vnode label. Question: maybe the filesystem
3665 * should update the vnode at the end as part of VOP_SETLABEL()?
3666 */
3667 error = mac_check_vnode_relabel(cred, vp, intlabel);
3668 if (error)
3669 return (error);
3670
3671 /*
3672 * VADMIN provides the opportunity for the filesystem to make
3673 * decisions about who is and is not able to modify labels
3674 * and protections on files. This might not be right. We can't
3675 * assume VOP_SETLABEL() will do it, because we might implement
3676 * that as part of vop_stdsetlabel_ea().
3677 */
3678 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3679 if (error)
3680 return (error);
3681
3682 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3683 if (error)
3684 return (error);
3685
3686 return (0);
3687}
3688
3689int
3690__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3691{
3692 char *elements, *buffer;
3693 struct mac mac;
3694 struct proc *tproc;
3695 struct ucred *tcred;
3696 int error;
3697
3698 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3699 if (error)
3700 return (error);
3701
3702 error = mac_check_structmac_consistent(&mac);
3703 if (error)
3704 return (error);
3705
3706 tproc = pfind(uap->pid);
3707 if (tproc == NULL)
3708 return (ESRCH);
3709
3710 tcred = NULL; /* Satisfy gcc. */
3711 error = p_cansee(td, tproc);
3712 if (error == 0)
3713 tcred = crhold(tproc->p_ucred);
3714 PROC_UNLOCK(tproc);
3715 if (error)
3716 return (error);
3717
3718 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3719
3720 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3721 if (error) {
3722 free(elements, M_MACTEMP);
3723 crfree(tcred);
3724 return (error);
3725 }
3726
3727 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3728
3729 error = mac_externalize_cred_label(&tcred->cr_label, elements,
3730 buffer, mac.m_buflen, M_WAITOK);
3731 if (error == 0)
3732 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3733
3734 free(buffer, M_MACTEMP);
3735 free(elements, M_MACTEMP);
3736 crfree(tcred);
3737 return (error);
3738}
3739
3740/*
3741 * MPSAFE
3742 */
3743int
3744__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3745{
3746 char *elements, *buffer;
3747 struct mac mac;
3748 int error;
3749
3750 error = copyin(uap->mac_p, &mac, sizeof(mac));
3751 if (error)
3752 return (error);
3753
3754 error = mac_check_structmac_consistent(&mac);
3755 if (error)
3756 return (error);
3757
3758 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3759
3760 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3761 if (error) {
3762 free(elements, M_MACTEMP);
3763 return (error);
3764 }
3765
3766 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3767
3768 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3769 elements, buffer, mac.m_buflen, M_WAITOK);
3770 if (error == 0)
3771 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3772
3773 free(buffer, M_MACTEMP);
3774 free(elements, M_MACTEMP);
3775 return (error);
3776}
3777
3778/*
3779 * MPSAFE
3780 */
3781int
3782__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3783{
3784 struct ucred *newcred, *oldcred;
3785 struct label intlabel;
3786 struct proc *p;
3787 struct mac mac;
3788 char *buffer;
3789 int error;
3790
3791 error = copyin(uap->mac_p, &mac, sizeof(mac));
3792 if (error)
3793 return (error);
3794
3795 error = mac_check_structmac_consistent(&mac);
3796 if (error)
3797 return (error);
3798
3799 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3800
3801 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3802 if (error) {
3803 free(buffer, M_MACTEMP);
3804 return (error);
3805 }
3806
3807 mac_init_cred_label(&intlabel);
3808 error = mac_internalize_cred_label(&intlabel, buffer);
3809 free(buffer, M_MACTEMP);
3810 if (error) {
3811 mac_destroy_cred_label(&intlabel);
3812 return (error);
3813 }
3814
3815 newcred = crget();
3816
3817 p = td->td_proc;
3818 PROC_LOCK(p);
3819 oldcred = p->p_ucred;
3820
3821 error = mac_check_cred_relabel(oldcred, &intlabel);
3822 if (error) {
3823 PROC_UNLOCK(p);
3824 crfree(newcred);
3825 goto out;
3826 }
3827
3828 setsugid(p);
3829 crcopy(newcred, oldcred);
3830 mac_relabel_cred(newcred, &intlabel);
3831 p->p_ucred = newcred;
3832
3833 /*
3834 * Grab additional reference for use while revoking mmaps, prior
3835 * to releasing the proc lock and sharing the cred.
3836 */
3837 crhold(newcred);
3838 PROC_UNLOCK(p);
3839
3840 if (mac_enforce_vm) {
3841 mtx_lock(&Giant);
3842 mac_cred_mmapped_drop_perms(td, newcred);
3843 mtx_unlock(&Giant);
3844 }
3845
3846 crfree(newcred); /* Free revocation reference. */
3847 crfree(oldcred);
3848
3849out:
3850 mac_destroy_cred_label(&intlabel);
3851 return (error);
3852}
3853
3854/*
3855 * MPSAFE
3856 */
3857int
3858__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3859{
3860 char *elements, *buffer;
3861 struct label intlabel;
3862 struct file *fp;
3863 struct mac mac;
3864 struct vnode *vp;
3865 struct pipe *pipe;
3866 short label_type;
3867 int error;
3868
3869 error = copyin(uap->mac_p, &mac, sizeof(mac));
3870 if (error)
3871 return (error);
3872
3873 error = mac_check_structmac_consistent(&mac);
3874 if (error)
3875 return (error);
3876
3877 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3878
3879 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3880 if (error) {
3881 free(elements, M_MACTEMP);
3882 return (error);
3883 }
3884
3885 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3886
3887 mtx_lock(&Giant); /* VFS */
3888 error = fget(td, SCARG(uap, fd), &fp);
3889 if (error)
3890 goto out;
3891
3892 label_type = fp->f_type;
3893 switch (fp->f_type) {
3894 case DTYPE_FIFO:
3895 case DTYPE_VNODE:
3896 vp = (struct vnode *)fp->f_data;
3897
3898 mac_init_vnode_label(&intlabel);
3899
3900 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3901 error = vn_refreshlabel(vp, td->td_ucred);
3902 if (error == 0)
3903 mac_copy_vnode_label(&vp->v_label, &intlabel);
3904 VOP_UNLOCK(vp, 0, td);
3905
3906 break;
3907 case DTYPE_PIPE:
3908 pipe = (struct pipe *)fp->f_data;
3909
3910 mac_init_pipe_label(&intlabel);
3911
3912 PIPE_LOCK(pipe);
3913 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3914 PIPE_UNLOCK(pipe);
3915 break;
3916 default:
3917 error = EINVAL;
3918 fdrop(fp, td);
3919 goto out;
3920 }
3921 fdrop(fp, td);
3922
3923 switch (label_type) {
3924 case DTYPE_FIFO:
3925 case DTYPE_VNODE:
3926 if (error == 0)
3927 error = mac_externalize_vnode_label(&intlabel,
3928 elements, buffer, mac.m_buflen, M_WAITOK);
3929 mac_destroy_vnode_label(&intlabel);
3930 break;
3931 case DTYPE_PIPE:
3932 error = mac_externalize_pipe_label(&intlabel, elements,
3933 buffer, mac.m_buflen, M_WAITOK);
3934 mac_destroy_pipe_label(&intlabel);
3935 break;
3936 default:
3937 panic("__mac_get_fd: corrupted label_type");
3938 }
3939
3940 if (error == 0)
3941 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3942
3943out:
3944 mtx_unlock(&Giant); /* VFS */
3945 free(buffer, M_MACTEMP);
3946 free(elements, M_MACTEMP);
3947
3948 return (error);
3949}
3950
3951/*
3952 * MPSAFE
3953 */
3954int
3955__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3956{
3957 char *elements, *buffer;
3958 struct nameidata nd;
3959 struct label intlabel;
3960 struct mac mac;
3961 int error;
3962
3963 error = copyin(uap->mac_p, &mac, sizeof(mac));
3964 if (error)
3965 return (error);
3966
3967 error = mac_check_structmac_consistent(&mac);
3968 if (error)
3969 return (error);
3970
3971 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3972
3973 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3974 if (error) {
3975 free(elements, M_MACTEMP);
3976 return (error);
3977 }
3978
3979 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3980
3981 mtx_lock(&Giant); /* VFS */
3982 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3983 td);
3984 error = namei(&nd);
3985 if (error)
3986 goto out;
3987
3988 mac_init_vnode_label(&intlabel);
3989 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3990 if (error == 0)
3991 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3992 if (error == 0)
3993 error = mac_externalize_vnode_label(&intlabel, elements,
3994 buffer, mac.m_buflen, M_WAITOK);
3995
3996 NDFREE(&nd, 0);
3997 mac_destroy_vnode_label(&intlabel);
3998
3999 if (error == 0)
4000 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4001
4002out:
4003 mtx_unlock(&Giant); /* VFS */
4004
4005 free(buffer, M_MACTEMP);
4006 free(elements, M_MACTEMP);
4007
4008 return (error);
4009}
4010
4011/*
4012 * MPSAFE
4013 */
4014int
4015__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4016{
4017 char *elements, *buffer;
4018 struct nameidata nd;
4019 struct label intlabel;
4020 struct mac mac;
4021 int error;
4022
4023 error = copyin(uap->mac_p, &mac, sizeof(mac));
4024 if (error)
4025 return (error);
4026
4027 error = mac_check_structmac_consistent(&mac);
4028 if (error)
4029 return (error);
4030
4031 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4032
4033 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
4034 if (error) {
4035 free(elements, M_MACTEMP);
4036 return (error);
4037 }
4038
4039 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4040
4041 mtx_lock(&Giant); /* VFS */
4042 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4043 td);
4044 error = namei(&nd);
4045 if (error)
4046 goto out;
4047
4048 mac_init_vnode_label(&intlabel);
4049 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
4050 if (error == 0)
4051 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
4052 if (error == 0)
4053 error = mac_externalize_vnode_label(&intlabel, elements,
4054 buffer, mac.m_buflen, M_WAITOK);
4055 NDFREE(&nd, 0);
4056 mac_destroy_vnode_label(&intlabel);
4057
4058 if (error == 0)
4059 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4060
4061out:
4062 mtx_unlock(&Giant); /* VFS */
4063
4064 free(buffer, M_MACTEMP);
4065 free(elements, M_MACTEMP);
4066
4067 return (error);
4068}
4069
4070/*
4071 * MPSAFE
4072 */
4073int
4074__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4075{
4076 struct label intlabel;
4077 struct pipe *pipe;
4078 struct file *fp;
4079 struct mount *mp;
4080 struct vnode *vp;
4081 struct mac mac;
4082 char *buffer;
4083 int error;
4084
4085 error = copyin(uap->mac_p, &mac, sizeof(mac));
4086 if (error)
4087 return (error);
4088
4089 error = mac_check_structmac_consistent(&mac);
4090 if (error)
4091 return (error);
4092
4093 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4094
4095 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4096 if (error) {
4097 free(buffer, M_MACTEMP);
4098 return (error);
4099 }
4100
4101 mtx_lock(&Giant); /* VFS */
4102
4103 error = fget(td, SCARG(uap, fd), &fp);
4104 if (error)
4105 goto out;
4106
4107 switch (fp->f_type) {
4108 case DTYPE_FIFO:
4109 case DTYPE_VNODE:
4110 mac_init_vnode_label(&intlabel);
4111 error = mac_internalize_vnode_label(&intlabel, buffer);
4112 if (error) {
4113 mac_destroy_vnode_label(&intlabel);
4114 break;
4115 }
4116
4117 vp = (struct vnode *)fp->f_data;
4118 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4119 if (error != 0) {
4120 mac_destroy_vnode_label(&intlabel);
4121 break;
4122 }
4123
4124 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4125 error = vn_setlabel(vp, &intlabel, td->td_ucred);
4126 VOP_UNLOCK(vp, 0, td);
4127 vn_finished_write(mp);
4128
4129 mac_destroy_vnode_label(&intlabel);
4130 break;
4131
4132 case DTYPE_PIPE:
4133 mac_init_pipe_label(&intlabel);
4134 error = mac_internalize_pipe_label(&intlabel, buffer);
4135 if (error == 0) {
4136 pipe = (struct pipe *)fp->f_data;
4137 PIPE_LOCK(pipe);
4138 error = mac_pipe_label_set(td->td_ucred, pipe,
4139 &intlabel);
4140 PIPE_UNLOCK(pipe);
4141 }
4142
4143 mac_destroy_pipe_label(&intlabel);
4144 break;
4145
4146 default:
4147 error = EINVAL;
4148 }
4149
4150 fdrop(fp, td);
4151out:
4152 mtx_unlock(&Giant); /* VFS */
4153
4154 free(buffer, M_MACTEMP);
4155
4156 return (error);
4157}
4158
4159/*
4160 * MPSAFE
4161 */
4162int
4163__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4164{
4165 struct label intlabel;
4166 struct nameidata nd;
4167 struct mount *mp;
4168 struct mac mac;
4169 char *buffer;
4170 int error;
4171
4172 error = copyin(uap->mac_p, &mac, sizeof(mac));
4173 if (error)
4174 return (error);
4175
4176 error = mac_check_structmac_consistent(&mac);
4177 if (error)
4178 return (error);
4179
4180 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4181
4182 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4183 if (error) {
4184 free(buffer, M_MACTEMP);
4185 return (error);
4186 }
4187
4188 mac_init_vnode_label(&intlabel);
4189 error = mac_internalize_vnode_label(&intlabel, buffer);
4190 free(buffer, M_MACTEMP);
4191 if (error) {
4192 mac_destroy_vnode_label(&intlabel);
4193 return (error);
4194 }
4195
4196 mtx_lock(&Giant); /* VFS */
4197
4198 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
4199 td);
4200 error = namei(&nd);
4201 if (error == 0) {
4202 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4203 if (error == 0)
4204 error = vn_setlabel(nd.ni_vp, &intlabel,
4205 td->td_ucred);
4206 vn_finished_write(mp);
4207 }
4208
4209 NDFREE(&nd, 0);
4210 mtx_unlock(&Giant); /* VFS */
4211 mac_destroy_vnode_label(&intlabel);
4212
4213 return (error);
4214}
4215
4216/*
4217 * MPSAFE
4218 */
4219int
4220__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4221{
4222 struct label intlabel;
4223 struct nameidata nd;
4224 struct mount *mp;
4225 struct mac mac;
4226 char *buffer;
4227 int error;
4228
4229 error = copyin(uap->mac_p, &mac, sizeof(mac));
4230 if (error)
4231 return (error);
4232
4233 error = mac_check_structmac_consistent(&mac);
4234 if (error)
4235 return (error);
4236
4237 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4238
4239 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4240 if (error) {
4241 free(buffer, M_MACTEMP);
4242 return (error);
4243 }
4244
4245 mac_init_vnode_label(&intlabel);
4246 error = mac_internalize_vnode_label(&intlabel, buffer);
4247 free(buffer, M_MACTEMP);
4248 if (error) {
4249 mac_destroy_vnode_label(&intlabel);
4250 return (error);
4251 }
4252
4253 mtx_lock(&Giant); /* VFS */
4254
4255 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4256 td);
4257 error = namei(&nd);
4258 if (error == 0) {
4259 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4260 if (error == 0)
4261 error = vn_setlabel(nd.ni_vp, &intlabel,
4262 td->td_ucred);
4263 vn_finished_write(mp);
4264 }
4265
4266 NDFREE(&nd, 0);
4267 mtx_unlock(&Giant); /* VFS */
4268 mac_destroy_vnode_label(&intlabel);
4269
4270 return (error);
4271}
4272
4273/*
4274 * MPSAFE
4275 */
4276int
4277mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4278{
4279 struct mac_policy_conf *mpc;
4280 char target[MAC_MAX_POLICY_NAME];
4281 int error;
4282
4283 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
4284 if (error)
4285 return (error);
4286
4287 error = ENOSYS;
4288 MAC_POLICY_LIST_BUSY();
4289 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
4290 if (strcmp(mpc->mpc_name, target) == 0 &&
4291 mpc->mpc_ops->mpo_syscall != NULL) {
4292 error = mpc->mpc_ops->mpo_syscall(td,
4293 SCARG(uap, call), SCARG(uap, arg));
4294 goto out;
4295 }
4296 }
4297
4298out:
4299 MAC_POLICY_LIST_UNBUSY();
4300 return (error);
4301}
4302
4303SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
4304SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
4305
4306#else /* !MAC */
4307
4308int
4309__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
4310{
4311
4312 return (ENOSYS);
4313}
4314
4315int
4316__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
4317{
4318
4319 return (ENOSYS);
4320}
4321
4322int
4323__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
4324{
4325
4326 return (ENOSYS);
4327}
4328
4329int
4330__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
4331{
4332
4333 return (ENOSYS);
4334}
4335
4336int
4337__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
4338{
4339
4340 return (ENOSYS);
4341}
4342
4343int
4344__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4345{
4346
4347 return (ENOSYS);
4348}
4349
4350int
4351__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4352{
4353
4354 return (ENOSYS);
4355}
4356
4357int
4358__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4359{
4360
4361 return (ENOSYS);
4362}
4363
4364int
4365__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4366{
4367
4368 return (ENOSYS);
4369}
4370
4371int
4372mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4373{
4374
4375 return (ENOSYS);
4376}
4377
4378#endif
2623 return (0);
2624
2625 error = vn_refreshlabel(vp, cred);
2626 if (error)
2627 return (error);
2628
2629 MAC_CHECK(check_vnode_swapon, cred, vp, &vp->v_label);
2630 return (error);
2631}
2632
2633int
2634mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2635 struct vnode *vp)
2636{
2637 int error;
2638
2639 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2640
2641 if (!mac_enforce_fs)
2642 return (0);
2643
2644 error = vn_refreshlabel(vp, active_cred);
2645 if (error)
2646 return (error);
2647
2648 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2649 &vp->v_label);
2650
2651 return (error);
2652}
2653
2654/*
2655 * When relabeling a process, call out to the policies for the maximum
2656 * permission allowed for each object type we know about in its
2657 * memory space, and revoke access (in the least surprising ways we
2658 * know) when necessary. The process lock is not held here.
2659 */
2660static void
2661mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2662{
2663
2664 /* XXX freeze all other threads */
2665 mac_cred_mmapped_drop_perms_recurse(td, cred,
2666 &td->td_proc->p_vmspace->vm_map);
2667 /* XXX allow other threads to continue */
2668}
2669
2670static __inline const char *
2671prot2str(vm_prot_t prot)
2672{
2673
2674 switch (prot & VM_PROT_ALL) {
2675 case VM_PROT_READ:
2676 return ("r--");
2677 case VM_PROT_READ | VM_PROT_WRITE:
2678 return ("rw-");
2679 case VM_PROT_READ | VM_PROT_EXECUTE:
2680 return ("r-x");
2681 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2682 return ("rwx");
2683 case VM_PROT_WRITE:
2684 return ("-w-");
2685 case VM_PROT_EXECUTE:
2686 return ("--x");
2687 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2688 return ("-wx");
2689 default:
2690 return ("---");
2691 }
2692}
2693
2694static void
2695mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2696 struct vm_map *map)
2697{
2698 struct vm_map_entry *vme;
2699 int result;
2700 vm_prot_t revokeperms;
2701 vm_object_t object;
2702 vm_ooffset_t offset;
2703 struct vnode *vp;
2704
2705 if (!mac_mmap_revocation)
2706 return;
2707
2708 vm_map_lock_read(map);
2709 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2710 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2711 mac_cred_mmapped_drop_perms_recurse(td, cred,
2712 vme->object.sub_map);
2713 continue;
2714 }
2715 /*
2716 * Skip over entries that obviously are not shared.
2717 */
2718 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2719 !vme->max_protection)
2720 continue;
2721 /*
2722 * Drill down to the deepest backing object.
2723 */
2724 offset = vme->offset;
2725 object = vme->object.vm_object;
2726 if (object == NULL)
2727 continue;
2728 while (object->backing_object != NULL) {
2729 object = object->backing_object;
2730 offset += object->backing_object_offset;
2731 }
2732 /*
2733 * At the moment, vm_maps and objects aren't considered
2734 * by the MAC system, so only things with backing by a
2735 * normal object (read: vnodes) are checked.
2736 */
2737 if (object->type != OBJT_VNODE)
2738 continue;
2739 vp = (struct vnode *)object->handle;
2740 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2741 result = vme->max_protection;
2742 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2743 VOP_UNLOCK(vp, 0, td);
2744 /*
2745 * Find out what maximum protection we may be allowing
2746 * now but a policy needs to get removed.
2747 */
2748 revokeperms = vme->max_protection & ~result;
2749 if (!revokeperms)
2750 continue;
2751 printf("pid %ld: revoking %s perms from %#lx:%ld "
2752 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2753 prot2str(revokeperms), (u_long)vme->start,
2754 (long)(vme->end - vme->start),
2755 prot2str(vme->max_protection), prot2str(vme->protection));
2756 vm_map_lock_upgrade(map);
2757 /*
2758 * This is the really simple case: if a map has more
2759 * max_protection than is allowed, but it's not being
2760 * actually used (that is, the current protection is
2761 * still allowed), we can just wipe it out and do
2762 * nothing more.
2763 */
2764 if ((vme->protection & revokeperms) == 0) {
2765 vme->max_protection -= revokeperms;
2766 } else {
2767 if (revokeperms & VM_PROT_WRITE) {
2768 /*
2769 * In the more complicated case, flush out all
2770 * pending changes to the object then turn it
2771 * copy-on-write.
2772 */
2773 vm_object_reference(object);
2774 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2775 vm_object_page_clean(object,
2776 OFF_TO_IDX(offset),
2777 OFF_TO_IDX(offset + vme->end - vme->start +
2778 PAGE_MASK),
2779 OBJPC_SYNC);
2780 VOP_UNLOCK(vp, 0, td);
2781 vm_object_deallocate(object);
2782 /*
2783 * Why bother if there's no read permissions
2784 * anymore? For the rest, we need to leave
2785 * the write permissions on for COW, or
2786 * remove them entirely if configured to.
2787 */
2788 if (!mac_mmap_revocation_via_cow) {
2789 vme->max_protection &= ~VM_PROT_WRITE;
2790 vme->protection &= ~VM_PROT_WRITE;
2791 } if ((revokeperms & VM_PROT_READ) == 0)
2792 vme->eflags |= MAP_ENTRY_COW |
2793 MAP_ENTRY_NEEDS_COPY;
2794 }
2795 if (revokeperms & VM_PROT_EXECUTE) {
2796 vme->max_protection &= ~VM_PROT_EXECUTE;
2797 vme->protection &= ~VM_PROT_EXECUTE;
2798 }
2799 if (revokeperms & VM_PROT_READ) {
2800 vme->max_protection = 0;
2801 vme->protection = 0;
2802 }
2803 pmap_protect(map->pmap, vme->start, vme->end,
2804 vme->protection & ~revokeperms);
2805 vm_map_simplify_entry(map, vme);
2806 }
2807 vm_map_lock_downgrade(map);
2808 }
2809 vm_map_unlock_read(map);
2810}
2811
2812/*
2813 * When the subject's label changes, it may require revocation of privilege
2814 * to mapped objects. This can't be done on-the-fly later with a unified
2815 * buffer cache.
2816 */
2817static void
2818mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2819{
2820
2821 MAC_PERFORM(relabel_cred, cred, newlabel);
2822}
2823
2824void
2825mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2826{
2827
2828 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2829}
2830
2831void
2832mac_create_ifnet(struct ifnet *ifnet)
2833{
2834
2835 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2836}
2837
2838void
2839mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2840{
2841
2842 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2843}
2844
2845void
2846mac_create_socket(struct ucred *cred, struct socket *socket)
2847{
2848
2849 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2850}
2851
2852void
2853mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2854{
2855
2856 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2857}
2858
2859void
2860mac_create_socket_from_socket(struct socket *oldsocket,
2861 struct socket *newsocket)
2862{
2863
2864 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2865 newsocket, &newsocket->so_label);
2866}
2867
2868static void
2869mac_relabel_socket(struct ucred *cred, struct socket *socket,
2870 struct label *newlabel)
2871{
2872
2873 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2874}
2875
2876static void
2877mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2878{
2879
2880 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2881}
2882
2883void
2884mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2885{
2886
2887 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2888 socket, &socket->so_peerlabel);
2889}
2890
2891void
2892mac_set_socket_peer_from_socket(struct socket *oldsocket,
2893 struct socket *newsocket)
2894{
2895
2896 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2897 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2898}
2899
2900void
2901mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2902{
2903
2904 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2905 datagram, &datagram->m_pkthdr.label);
2906}
2907
2908void
2909mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2910{
2911
2912 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2913 fragment, &fragment->m_pkthdr.label);
2914}
2915
2916void
2917mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2918{
2919
2920 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2921 &ipq->ipq_label);
2922}
2923
2924void
2925mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2926{
2927
2928 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2929 newmbuf, &newmbuf->m_pkthdr.label);
2930}
2931
2932void
2933mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2934{
2935
2936 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2937 &mbuf->m_pkthdr.label);
2938}
2939
2940void
2941mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2942{
2943
2944 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2945 &mbuf->m_pkthdr.label);
2946}
2947
2948void
2949mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2950{
2951
2952 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2953 &mbuf->m_pkthdr.label);
2954}
2955
2956void
2957mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2958 struct mbuf *newmbuf)
2959{
2960
2961 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2962 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2963 &newmbuf->m_pkthdr.label);
2964}
2965
2966void
2967mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2968{
2969
2970 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2971 newmbuf, &newmbuf->m_pkthdr.label);
2972}
2973
2974int
2975mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2976{
2977 int result;
2978
2979 result = 1;
2980 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2981 ipq, &ipq->ipq_label);
2982
2983 return (result);
2984}
2985
2986void
2987mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2988{
2989
2990 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2991 &ipq->ipq_label);
2992}
2993
2994void
2995mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2996{
2997
2998 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2999 &mbuf->m_pkthdr.label);
3000}
3001
3002void
3003mac_create_mount(struct ucred *cred, struct mount *mp)
3004{
3005
3006 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
3007 &mp->mnt_fslabel);
3008}
3009
3010void
3011mac_create_root_mount(struct ucred *cred, struct mount *mp)
3012{
3013
3014 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
3015 &mp->mnt_fslabel);
3016}
3017
3018int
3019mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
3020{
3021 int error;
3022
3023 if (!mac_enforce_network)
3024 return (0);
3025
3026 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
3027 &ifnet->if_label);
3028
3029 return (error);
3030}
3031
3032static int
3033mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
3034{
3035 int error;
3036
3037 MAC_CHECK(check_cred_relabel, cred, newlabel);
3038
3039 return (error);
3040}
3041
3042int
3043mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
3044{
3045 int error;
3046
3047 if (!mac_enforce_process)
3048 return (0);
3049
3050 MAC_CHECK(check_cred_visible, u1, u2);
3051
3052 return (error);
3053}
3054
3055int
3056mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
3057{
3058 int error;
3059
3060 if (!mac_enforce_network)
3061 return (0);
3062
3063 KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
3064 if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
3065 if_printf(ifnet, "not initialized\n");
3066
3067 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
3068 &mbuf->m_pkthdr.label);
3069
3070 return (error);
3071}
3072
3073int
3074mac_check_mount_stat(struct ucred *cred, struct mount *mount)
3075{
3076 int error;
3077
3078 if (!mac_enforce_fs)
3079 return (0);
3080
3081 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
3082
3083 return (error);
3084}
3085
3086int
3087mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
3088 void *data)
3089{
3090 int error;
3091
3092 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3093
3094 if (!mac_enforce_pipe)
3095 return (0);
3096
3097 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
3098
3099 return (error);
3100}
3101
3102int
3103mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
3104{
3105 int error;
3106
3107 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3108
3109 if (!mac_enforce_pipe)
3110 return (0);
3111
3112 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
3113
3114 return (error);
3115}
3116
3117int
3118mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
3119{
3120 int error;
3121
3122 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3123
3124 if (!mac_enforce_pipe)
3125 return (0);
3126
3127 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
3128
3129 return (error);
3130}
3131
3132static int
3133mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
3134 struct label *newlabel)
3135{
3136 int error;
3137
3138 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3139
3140 if (!mac_enforce_pipe)
3141 return (0);
3142
3143 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
3144
3145 return (error);
3146}
3147
3148int
3149mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
3150{
3151 int error;
3152
3153 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3154
3155 if (!mac_enforce_pipe)
3156 return (0);
3157
3158 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
3159
3160 return (error);
3161}
3162
3163int
3164mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
3165{
3166 int error;
3167
3168 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3169
3170 if (!mac_enforce_pipe)
3171 return (0);
3172
3173 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
3174
3175 return (error);
3176}
3177
3178int
3179mac_check_proc_debug(struct ucred *cred, struct proc *proc)
3180{
3181 int error;
3182
3183 PROC_LOCK_ASSERT(proc, MA_OWNED);
3184
3185 if (!mac_enforce_process)
3186 return (0);
3187
3188 MAC_CHECK(check_proc_debug, cred, proc);
3189
3190 return (error);
3191}
3192
3193int
3194mac_check_proc_sched(struct ucred *cred, struct proc *proc)
3195{
3196 int error;
3197
3198 PROC_LOCK_ASSERT(proc, MA_OWNED);
3199
3200 if (!mac_enforce_process)
3201 return (0);
3202
3203 MAC_CHECK(check_proc_sched, cred, proc);
3204
3205 return (error);
3206}
3207
3208int
3209mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
3210{
3211 int error;
3212
3213 PROC_LOCK_ASSERT(proc, MA_OWNED);
3214
3215 if (!mac_enforce_process)
3216 return (0);
3217
3218 MAC_CHECK(check_proc_signal, cred, proc, signum);
3219
3220 return (error);
3221}
3222
3223int
3224mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
3225 struct sockaddr *sockaddr)
3226{
3227 int error;
3228
3229 if (!mac_enforce_socket)
3230 return (0);
3231
3232 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
3233 sockaddr);
3234
3235 return (error);
3236}
3237
3238int
3239mac_check_socket_connect(struct ucred *cred, struct socket *socket,
3240 struct sockaddr *sockaddr)
3241{
3242 int error;
3243
3244 if (!mac_enforce_socket)
3245 return (0);
3246
3247 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
3248 sockaddr);
3249
3250 return (error);
3251}
3252
3253int
3254mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
3255{
3256 int error;
3257
3258 if (!mac_enforce_socket)
3259 return (0);
3260
3261 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
3262 &mbuf->m_pkthdr.label);
3263
3264 return (error);
3265}
3266
3267int
3268mac_check_socket_listen(struct ucred *cred, struct socket *socket)
3269{
3270 int error;
3271
3272 if (!mac_enforce_socket)
3273 return (0);
3274
3275 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
3276 return (error);
3277}
3278
3279int
3280mac_check_socket_receive(struct ucred *cred, struct socket *so)
3281{
3282 int error;
3283
3284 if (!mac_enforce_socket)
3285 return (0);
3286
3287 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
3288
3289 return (error);
3290}
3291
3292static int
3293mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
3294 struct label *newlabel)
3295{
3296 int error;
3297
3298 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
3299 newlabel);
3300
3301 return (error);
3302}
3303
3304int
3305mac_check_socket_send(struct ucred *cred, struct socket *so)
3306{
3307 int error;
3308
3309 if (!mac_enforce_socket)
3310 return (0);
3311
3312 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
3313
3314 return (error);
3315}
3316
3317int
3318mac_check_socket_visible(struct ucred *cred, struct socket *socket)
3319{
3320 int error;
3321
3322 if (!mac_enforce_socket)
3323 return (0);
3324
3325 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
3326
3327 return (error);
3328}
3329
3330int
3331mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
3332 struct ifnet *ifnet)
3333{
3334 char *elements, *buffer;
3335 struct mac mac;
3336 int error;
3337
3338 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3339 if (error)
3340 return (error);
3341
3342 error = mac_check_structmac_consistent(&mac);
3343 if (error)
3344 return (error);
3345
3346 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3347
3348 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3349 if (error) {
3350 free(elements, M_MACTEMP);
3351 return (error);
3352 }
3353
3354 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3355
3356 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
3357 buffer, mac.m_buflen, M_WAITOK);
3358 if (error == 0)
3359 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3360
3361 free(buffer, M_MACTEMP);
3362 free(elements, M_MACTEMP);
3363
3364 return (error);
3365}
3366
3367int
3368mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3369 struct ifnet *ifnet)
3370{
3371 struct label intlabel;
3372 struct mac mac;
3373 char *buffer;
3374 int error;
3375
3376 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3377 if (error)
3378 return (error);
3379
3380 error = mac_check_structmac_consistent(&mac);
3381 if (error)
3382 return (error);
3383
3384 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3385
3386 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3387 if (error) {
3388 free(buffer, M_MACTEMP);
3389 return (error);
3390 }
3391
3392 mac_init_ifnet_label(&intlabel);
3393 error = mac_internalize_ifnet_label(&intlabel, buffer);
3394 free(buffer, M_MACTEMP);
3395 if (error) {
3396 mac_destroy_ifnet_label(&intlabel);
3397 return (error);
3398 }
3399
3400 /*
3401 * XXX: Note that this is a redundant privilege check, since
3402 * policies impose this check themselves if required by the
3403 * policy. Eventually, this should go away.
3404 */
3405 error = suser_cred(cred, 0);
3406 if (error) {
3407 mac_destroy_ifnet_label(&intlabel);
3408 return (error);
3409 }
3410
3411 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3412 &intlabel);
3413 if (error) {
3414 mac_destroy_ifnet_label(&intlabel);
3415 return (error);
3416 }
3417
3418 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3419
3420 mac_destroy_ifnet_label(&intlabel);
3421 return (0);
3422}
3423
3424void
3425mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
3426{
3427
3428 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
3429}
3430
3431void
3432mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
3433{
3434
3435 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
3436}
3437
3438void
3439mac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
3440 struct devfs_dirent *de)
3441{
3442
3443 MAC_PERFORM(create_devfs_symlink, cred, dd, &dd->de_label, de,
3444 &de->de_label);
3445}
3446
3447static int
3448mac_stdcreatevnode_ea(struct vnode *vp)
3449{
3450 int error;
3451
3452 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
3453
3454 return (error);
3455}
3456
3457void
3458mac_create_devfs_directory(char *dirname, int dirnamelen,
3459 struct devfs_dirent *de)
3460{
3461
3462 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
3463 &de->de_label);
3464}
3465
3466/*
3467 * When a new vnode is created, this call will initialize its label.
3468 */
3469void
3470mac_create_vnode(struct ucred *cred, struct vnode *parent,
3471 struct vnode *child)
3472{
3473 int error;
3474
3475 ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
3476 ASSERT_VOP_LOCKED(child, "mac_create_vnode");
3477
3478 error = vn_refreshlabel(parent, cred);
3479 if (error) {
3480 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
3481 error);
3482 printf("mac_create_vnode: using old vnode label\n");
3483 }
3484
3485 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
3486 &child->v_label);
3487}
3488
3489int
3490mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3491 struct mac *mac)
3492{
3493 struct label intlabel;
3494 char *buffer;
3495 int error;
3496
3497 error = mac_check_structmac_consistent(mac);
3498 if (error)
3499 return (error);
3500
3501 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3502
3503 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3504 if (error) {
3505 free(buffer, M_MACTEMP);
3506 return (error);
3507 }
3508
3509 mac_init_socket_label(&intlabel, M_WAITOK);
3510 error = mac_internalize_socket_label(&intlabel, buffer);
3511 free(buffer, M_MACTEMP);
3512 if (error) {
3513 mac_destroy_socket_label(&intlabel);
3514 return (error);
3515 }
3516
3517 mac_check_socket_relabel(cred, so, &intlabel);
3518 if (error) {
3519 mac_destroy_socket_label(&intlabel);
3520 return (error);
3521 }
3522
3523 mac_relabel_socket(cred, so, &intlabel);
3524
3525 mac_destroy_socket_label(&intlabel);
3526 return (0);
3527}
3528
3529int
3530mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3531{
3532 int error;
3533
3534 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3535
3536 error = mac_check_pipe_relabel(cred, pipe, label);
3537 if (error)
3538 return (error);
3539
3540 mac_relabel_pipe(cred, pipe, label);
3541
3542 return (0);
3543}
3544
3545int
3546mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3547 struct mac *mac)
3548{
3549 char *buffer, *elements;
3550 int error;
3551
3552 error = mac_check_structmac_consistent(mac);
3553 if (error)
3554 return (error);
3555
3556 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3557
3558 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3559 if (error) {
3560 free(elements, M_MACTEMP);
3561 return (error);
3562 }
3563
3564 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3565
3566 error = mac_externalize_socket_label(&so->so_label, elements,
3567 buffer, mac->m_buflen, M_WAITOK);
3568 if (error == 0)
3569 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3570
3571 free(buffer, M_MACTEMP);
3572 free(elements, M_MACTEMP);
3573
3574 return (error);
3575}
3576
3577int
3578mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3579 struct mac *mac)
3580{
3581 char *elements, *buffer;
3582 int error;
3583
3584 error = mac_check_structmac_consistent(mac);
3585 if (error)
3586 return (error);
3587
3588 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3589
3590 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3591 if (error) {
3592 free(elements, M_MACTEMP);
3593 return (error);
3594 }
3595
3596 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3597
3598 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3599 elements, buffer, mac->m_buflen, M_WAITOK);
3600 if (error == 0)
3601 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3602
3603 free(buffer, M_MACTEMP);
3604 free(elements, M_MACTEMP);
3605
3606 return (error);
3607}
3608
3609/*
3610 * Implementation of VOP_SETLABEL() that relies on extended attributes
3611 * to store label data. Can be referenced by filesystems supporting
3612 * extended attributes.
3613 */
3614int
3615vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3616{
3617 struct vnode *vp = ap->a_vp;
3618 struct label *intlabel = ap->a_label;
3619 struct oldmac extmac;
3620 int error;
3621
3622 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3623
3624 /*
3625 * XXX: Eventually call out to EA check/set calls here.
3626 * Be particularly careful to avoid race conditions,
3627 * consistency problems, and stability problems when
3628 * dealing with multiple EAs. In particular, we require
3629 * the ability to write multiple EAs on the same file in
3630 * a single transaction, which the current EA interface
3631 * does not provide.
3632 */
3633
3634 error = mac_externalize_vnode_oldmac(intlabel, &extmac);
3635 if (error)
3636 return (error);
3637
3638 error = vn_extattr_set(vp, IO_NODELOCKED,
3639 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
3640 sizeof(extmac), (char *)&extmac, curthread);
3641 if (error)
3642 return (error);
3643
3644 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3645
3646 vp->v_vflag |= VV_CACHEDLABEL;
3647
3648 return (0);
3649}
3650
3651static int
3652vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3653{
3654 int error;
3655
3656 if (vp->v_mount == NULL) {
3657 /* printf("vn_setlabel: null v_mount\n"); */
3658 if (vp->v_type != VNON)
3659 printf("vn_setlabel: null v_mount with non-VNON\n");
3660 return (EBADF);
3661 }
3662
3663 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3664 return (EOPNOTSUPP);
3665
3666 /*
3667 * Multi-phase commit. First check the policies to confirm the
3668 * change is OK. Then commit via the filesystem. Finally,
3669 * update the actual vnode label. Question: maybe the filesystem
3670 * should update the vnode at the end as part of VOP_SETLABEL()?
3671 */
3672 error = mac_check_vnode_relabel(cred, vp, intlabel);
3673 if (error)
3674 return (error);
3675
3676 /*
3677 * VADMIN provides the opportunity for the filesystem to make
3678 * decisions about who is and is not able to modify labels
3679 * and protections on files. This might not be right. We can't
3680 * assume VOP_SETLABEL() will do it, because we might implement
3681 * that as part of vop_stdsetlabel_ea().
3682 */
3683 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3684 if (error)
3685 return (error);
3686
3687 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3688 if (error)
3689 return (error);
3690
3691 return (0);
3692}
3693
3694int
3695__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3696{
3697 char *elements, *buffer;
3698 struct mac mac;
3699 struct proc *tproc;
3700 struct ucred *tcred;
3701 int error;
3702
3703 error = copyin(SCARG(uap, mac_p), &mac, sizeof(mac));
3704 if (error)
3705 return (error);
3706
3707 error = mac_check_structmac_consistent(&mac);
3708 if (error)
3709 return (error);
3710
3711 tproc = pfind(uap->pid);
3712 if (tproc == NULL)
3713 return (ESRCH);
3714
3715 tcred = NULL; /* Satisfy gcc. */
3716 error = p_cansee(td, tproc);
3717 if (error == 0)
3718 tcred = crhold(tproc->p_ucred);
3719 PROC_UNLOCK(tproc);
3720 if (error)
3721 return (error);
3722
3723 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3724
3725 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3726 if (error) {
3727 free(elements, M_MACTEMP);
3728 crfree(tcred);
3729 return (error);
3730 }
3731
3732 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3733
3734 error = mac_externalize_cred_label(&tcred->cr_label, elements,
3735 buffer, mac.m_buflen, M_WAITOK);
3736 if (error == 0)
3737 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3738
3739 free(buffer, M_MACTEMP);
3740 free(elements, M_MACTEMP);
3741 crfree(tcred);
3742 return (error);
3743}
3744
3745/*
3746 * MPSAFE
3747 */
3748int
3749__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3750{
3751 char *elements, *buffer;
3752 struct mac mac;
3753 int error;
3754
3755 error = copyin(uap->mac_p, &mac, sizeof(mac));
3756 if (error)
3757 return (error);
3758
3759 error = mac_check_structmac_consistent(&mac);
3760 if (error)
3761 return (error);
3762
3763 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3764
3765 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3766 if (error) {
3767 free(elements, M_MACTEMP);
3768 return (error);
3769 }
3770
3771 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3772
3773 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3774 elements, buffer, mac.m_buflen, M_WAITOK);
3775 if (error == 0)
3776 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3777
3778 free(buffer, M_MACTEMP);
3779 free(elements, M_MACTEMP);
3780 return (error);
3781}
3782
3783/*
3784 * MPSAFE
3785 */
3786int
3787__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3788{
3789 struct ucred *newcred, *oldcred;
3790 struct label intlabel;
3791 struct proc *p;
3792 struct mac mac;
3793 char *buffer;
3794 int error;
3795
3796 error = copyin(uap->mac_p, &mac, sizeof(mac));
3797 if (error)
3798 return (error);
3799
3800 error = mac_check_structmac_consistent(&mac);
3801 if (error)
3802 return (error);
3803
3804 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3805
3806 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3807 if (error) {
3808 free(buffer, M_MACTEMP);
3809 return (error);
3810 }
3811
3812 mac_init_cred_label(&intlabel);
3813 error = mac_internalize_cred_label(&intlabel, buffer);
3814 free(buffer, M_MACTEMP);
3815 if (error) {
3816 mac_destroy_cred_label(&intlabel);
3817 return (error);
3818 }
3819
3820 newcred = crget();
3821
3822 p = td->td_proc;
3823 PROC_LOCK(p);
3824 oldcred = p->p_ucred;
3825
3826 error = mac_check_cred_relabel(oldcred, &intlabel);
3827 if (error) {
3828 PROC_UNLOCK(p);
3829 crfree(newcred);
3830 goto out;
3831 }
3832
3833 setsugid(p);
3834 crcopy(newcred, oldcred);
3835 mac_relabel_cred(newcred, &intlabel);
3836 p->p_ucred = newcred;
3837
3838 /*
3839 * Grab additional reference for use while revoking mmaps, prior
3840 * to releasing the proc lock and sharing the cred.
3841 */
3842 crhold(newcred);
3843 PROC_UNLOCK(p);
3844
3845 if (mac_enforce_vm) {
3846 mtx_lock(&Giant);
3847 mac_cred_mmapped_drop_perms(td, newcred);
3848 mtx_unlock(&Giant);
3849 }
3850
3851 crfree(newcred); /* Free revocation reference. */
3852 crfree(oldcred);
3853
3854out:
3855 mac_destroy_cred_label(&intlabel);
3856 return (error);
3857}
3858
3859/*
3860 * MPSAFE
3861 */
3862int
3863__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3864{
3865 char *elements, *buffer;
3866 struct label intlabel;
3867 struct file *fp;
3868 struct mac mac;
3869 struct vnode *vp;
3870 struct pipe *pipe;
3871 short label_type;
3872 int error;
3873
3874 error = copyin(uap->mac_p, &mac, sizeof(mac));
3875 if (error)
3876 return (error);
3877
3878 error = mac_check_structmac_consistent(&mac);
3879 if (error)
3880 return (error);
3881
3882 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3883
3884 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3885 if (error) {
3886 free(elements, M_MACTEMP);
3887 return (error);
3888 }
3889
3890 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3891
3892 mtx_lock(&Giant); /* VFS */
3893 error = fget(td, SCARG(uap, fd), &fp);
3894 if (error)
3895 goto out;
3896
3897 label_type = fp->f_type;
3898 switch (fp->f_type) {
3899 case DTYPE_FIFO:
3900 case DTYPE_VNODE:
3901 vp = (struct vnode *)fp->f_data;
3902
3903 mac_init_vnode_label(&intlabel);
3904
3905 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3906 error = vn_refreshlabel(vp, td->td_ucred);
3907 if (error == 0)
3908 mac_copy_vnode_label(&vp->v_label, &intlabel);
3909 VOP_UNLOCK(vp, 0, td);
3910
3911 break;
3912 case DTYPE_PIPE:
3913 pipe = (struct pipe *)fp->f_data;
3914
3915 mac_init_pipe_label(&intlabel);
3916
3917 PIPE_LOCK(pipe);
3918 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3919 PIPE_UNLOCK(pipe);
3920 break;
3921 default:
3922 error = EINVAL;
3923 fdrop(fp, td);
3924 goto out;
3925 }
3926 fdrop(fp, td);
3927
3928 switch (label_type) {
3929 case DTYPE_FIFO:
3930 case DTYPE_VNODE:
3931 if (error == 0)
3932 error = mac_externalize_vnode_label(&intlabel,
3933 elements, buffer, mac.m_buflen, M_WAITOK);
3934 mac_destroy_vnode_label(&intlabel);
3935 break;
3936 case DTYPE_PIPE:
3937 error = mac_externalize_pipe_label(&intlabel, elements,
3938 buffer, mac.m_buflen, M_WAITOK);
3939 mac_destroy_pipe_label(&intlabel);
3940 break;
3941 default:
3942 panic("__mac_get_fd: corrupted label_type");
3943 }
3944
3945 if (error == 0)
3946 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3947
3948out:
3949 mtx_unlock(&Giant); /* VFS */
3950 free(buffer, M_MACTEMP);
3951 free(elements, M_MACTEMP);
3952
3953 return (error);
3954}
3955
3956/*
3957 * MPSAFE
3958 */
3959int
3960__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3961{
3962 char *elements, *buffer;
3963 struct nameidata nd;
3964 struct label intlabel;
3965 struct mac mac;
3966 int error;
3967
3968 error = copyin(uap->mac_p, &mac, sizeof(mac));
3969 if (error)
3970 return (error);
3971
3972 error = mac_check_structmac_consistent(&mac);
3973 if (error)
3974 return (error);
3975
3976 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3977
3978 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3979 if (error) {
3980 free(elements, M_MACTEMP);
3981 return (error);
3982 }
3983
3984 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3985
3986 mtx_lock(&Giant); /* VFS */
3987 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3988 td);
3989 error = namei(&nd);
3990 if (error)
3991 goto out;
3992
3993 mac_init_vnode_label(&intlabel);
3994 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3995 if (error == 0)
3996 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3997 if (error == 0)
3998 error = mac_externalize_vnode_label(&intlabel, elements,
3999 buffer, mac.m_buflen, M_WAITOK);
4000
4001 NDFREE(&nd, 0);
4002 mac_destroy_vnode_label(&intlabel);
4003
4004 if (error == 0)
4005 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4006
4007out:
4008 mtx_unlock(&Giant); /* VFS */
4009
4010 free(buffer, M_MACTEMP);
4011 free(elements, M_MACTEMP);
4012
4013 return (error);
4014}
4015
4016/*
4017 * MPSAFE
4018 */
4019int
4020__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4021{
4022 char *elements, *buffer;
4023 struct nameidata nd;
4024 struct label intlabel;
4025 struct mac mac;
4026 int error;
4027
4028 error = copyin(uap->mac_p, &mac, sizeof(mac));
4029 if (error)
4030 return (error);
4031
4032 error = mac_check_structmac_consistent(&mac);
4033 if (error)
4034 return (error);
4035
4036 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4037
4038 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
4039 if (error) {
4040 free(elements, M_MACTEMP);
4041 return (error);
4042 }
4043
4044 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
4045
4046 mtx_lock(&Giant); /* VFS */
4047 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4048 td);
4049 error = namei(&nd);
4050 if (error)
4051 goto out;
4052
4053 mac_init_vnode_label(&intlabel);
4054 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
4055 if (error == 0)
4056 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
4057 if (error == 0)
4058 error = mac_externalize_vnode_label(&intlabel, elements,
4059 buffer, mac.m_buflen, M_WAITOK);
4060 NDFREE(&nd, 0);
4061 mac_destroy_vnode_label(&intlabel);
4062
4063 if (error == 0)
4064 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
4065
4066out:
4067 mtx_unlock(&Giant); /* VFS */
4068
4069 free(buffer, M_MACTEMP);
4070 free(elements, M_MACTEMP);
4071
4072 return (error);
4073}
4074
4075/*
4076 * MPSAFE
4077 */
4078int
4079__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4080{
4081 struct label intlabel;
4082 struct pipe *pipe;
4083 struct file *fp;
4084 struct mount *mp;
4085 struct vnode *vp;
4086 struct mac mac;
4087 char *buffer;
4088 int error;
4089
4090 error = copyin(uap->mac_p, &mac, sizeof(mac));
4091 if (error)
4092 return (error);
4093
4094 error = mac_check_structmac_consistent(&mac);
4095 if (error)
4096 return (error);
4097
4098 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4099
4100 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4101 if (error) {
4102 free(buffer, M_MACTEMP);
4103 return (error);
4104 }
4105
4106 mtx_lock(&Giant); /* VFS */
4107
4108 error = fget(td, SCARG(uap, fd), &fp);
4109 if (error)
4110 goto out;
4111
4112 switch (fp->f_type) {
4113 case DTYPE_FIFO:
4114 case DTYPE_VNODE:
4115 mac_init_vnode_label(&intlabel);
4116 error = mac_internalize_vnode_label(&intlabel, buffer);
4117 if (error) {
4118 mac_destroy_vnode_label(&intlabel);
4119 break;
4120 }
4121
4122 vp = (struct vnode *)fp->f_data;
4123 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
4124 if (error != 0) {
4125 mac_destroy_vnode_label(&intlabel);
4126 break;
4127 }
4128
4129 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
4130 error = vn_setlabel(vp, &intlabel, td->td_ucred);
4131 VOP_UNLOCK(vp, 0, td);
4132 vn_finished_write(mp);
4133
4134 mac_destroy_vnode_label(&intlabel);
4135 break;
4136
4137 case DTYPE_PIPE:
4138 mac_init_pipe_label(&intlabel);
4139 error = mac_internalize_pipe_label(&intlabel, buffer);
4140 if (error == 0) {
4141 pipe = (struct pipe *)fp->f_data;
4142 PIPE_LOCK(pipe);
4143 error = mac_pipe_label_set(td->td_ucred, pipe,
4144 &intlabel);
4145 PIPE_UNLOCK(pipe);
4146 }
4147
4148 mac_destroy_pipe_label(&intlabel);
4149 break;
4150
4151 default:
4152 error = EINVAL;
4153 }
4154
4155 fdrop(fp, td);
4156out:
4157 mtx_unlock(&Giant); /* VFS */
4158
4159 free(buffer, M_MACTEMP);
4160
4161 return (error);
4162}
4163
4164/*
4165 * MPSAFE
4166 */
4167int
4168__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4169{
4170 struct label intlabel;
4171 struct nameidata nd;
4172 struct mount *mp;
4173 struct mac mac;
4174 char *buffer;
4175 int error;
4176
4177 error = copyin(uap->mac_p, &mac, sizeof(mac));
4178 if (error)
4179 return (error);
4180
4181 error = mac_check_structmac_consistent(&mac);
4182 if (error)
4183 return (error);
4184
4185 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4186
4187 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4188 if (error) {
4189 free(buffer, M_MACTEMP);
4190 return (error);
4191 }
4192
4193 mac_init_vnode_label(&intlabel);
4194 error = mac_internalize_vnode_label(&intlabel, buffer);
4195 free(buffer, M_MACTEMP);
4196 if (error) {
4197 mac_destroy_vnode_label(&intlabel);
4198 return (error);
4199 }
4200
4201 mtx_lock(&Giant); /* VFS */
4202
4203 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
4204 td);
4205 error = namei(&nd);
4206 if (error == 0) {
4207 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4208 if (error == 0)
4209 error = vn_setlabel(nd.ni_vp, &intlabel,
4210 td->td_ucred);
4211 vn_finished_write(mp);
4212 }
4213
4214 NDFREE(&nd, 0);
4215 mtx_unlock(&Giant); /* VFS */
4216 mac_destroy_vnode_label(&intlabel);
4217
4218 return (error);
4219}
4220
4221/*
4222 * MPSAFE
4223 */
4224int
4225__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4226{
4227 struct label intlabel;
4228 struct nameidata nd;
4229 struct mount *mp;
4230 struct mac mac;
4231 char *buffer;
4232 int error;
4233
4234 error = copyin(uap->mac_p, &mac, sizeof(mac));
4235 if (error)
4236 return (error);
4237
4238 error = mac_check_structmac_consistent(&mac);
4239 if (error)
4240 return (error);
4241
4242 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
4243
4244 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
4245 if (error) {
4246 free(buffer, M_MACTEMP);
4247 return (error);
4248 }
4249
4250 mac_init_vnode_label(&intlabel);
4251 error = mac_internalize_vnode_label(&intlabel, buffer);
4252 free(buffer, M_MACTEMP);
4253 if (error) {
4254 mac_destroy_vnode_label(&intlabel);
4255 return (error);
4256 }
4257
4258 mtx_lock(&Giant); /* VFS */
4259
4260 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
4261 td);
4262 error = namei(&nd);
4263 if (error == 0) {
4264 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
4265 if (error == 0)
4266 error = vn_setlabel(nd.ni_vp, &intlabel,
4267 td->td_ucred);
4268 vn_finished_write(mp);
4269 }
4270
4271 NDFREE(&nd, 0);
4272 mtx_unlock(&Giant); /* VFS */
4273 mac_destroy_vnode_label(&intlabel);
4274
4275 return (error);
4276}
4277
4278/*
4279 * MPSAFE
4280 */
4281int
4282mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4283{
4284 struct mac_policy_conf *mpc;
4285 char target[MAC_MAX_POLICY_NAME];
4286 int error;
4287
4288 error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
4289 if (error)
4290 return (error);
4291
4292 error = ENOSYS;
4293 MAC_POLICY_LIST_BUSY();
4294 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
4295 if (strcmp(mpc->mpc_name, target) == 0 &&
4296 mpc->mpc_ops->mpo_syscall != NULL) {
4297 error = mpc->mpc_ops->mpo_syscall(td,
4298 SCARG(uap, call), SCARG(uap, arg));
4299 goto out;
4300 }
4301 }
4302
4303out:
4304 MAC_POLICY_LIST_UNBUSY();
4305 return (error);
4306}
4307
4308SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
4309SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
4310
4311#else /* !MAC */
4312
4313int
4314__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
4315{
4316
4317 return (ENOSYS);
4318}
4319
4320int
4321__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
4322{
4323
4324 return (ENOSYS);
4325}
4326
4327int
4328__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
4329{
4330
4331 return (ENOSYS);
4332}
4333
4334int
4335__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
4336{
4337
4338 return (ENOSYS);
4339}
4340
4341int
4342__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
4343{
4344
4345 return (ENOSYS);
4346}
4347
4348int
4349__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
4350{
4351
4352 return (ENOSYS);
4353}
4354
4355int
4356__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
4357{
4358
4359 return (ENOSYS);
4360}
4361
4362int
4363__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
4364{
4365
4366 return (ENOSYS);
4367}
4368
4369int
4370__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
4371{
4372
4373 return (ENOSYS);
4374}
4375
4376int
4377mac_syscall(struct thread *td, struct mac_syscall_args *uap)
4378{
4379
4380 return (ENOSYS);
4381}
4382
4383#endif