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