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.
7 * This software was developed by Robert Watson and Ilmar Habibulin for the
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.
15 * Redistribution and use in source and binary forms, with or without
16 * modification, are permitted provided that the following conditions
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
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
42 * Developed by the TrustedBSD Project.
44 * Framework for extensible kernel access control. Kernel and userland
45 * interface to the framework, policy registration and composition.
50 #include <sys/param.h>
51 #include <sys/extattr.h>
52 #include <sys/kernel.h>
54 #include <sys/mutex.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>
64 #include <sys/namei.h>
65 #include <sys/socket.h>
67 #include <sys/socketvar.h>
69 #include <sys/sysctl.h>
73 #include <vm/vm_map.h>
74 #include <vm/vm_object.h>
76 #include <sys/mac_policy.h>
78 #include <fs/devfs/devfs.h>
81 #include <net/bpfdesc.h>
83 #include <net/if_var.h>
85 #include <netinet/in.h>
86 #include <netinet/ip_var.h>
90 SYSCTL_DECL(_security);
92 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
93 "TrustedBSD MAC policy controls");
94 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
95 "TrustedBSD MAC debug info");
97 static int mac_debug_label_fallback = 0;
98 SYSCTL_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.");
101 TUNABLE_INT("security.mac.debug_label_fallback",
102 &mac_debug_label_fallback);
104 #ifndef MAC_MAX_POLICIES
105 #define MAC_MAX_POLICIES 8
107 #if MAC_MAX_POLICIES > 32
108 #error "MAC_MAX_POLICIES too large"
110 static unsigned int mac_max_policies = MAC_MAX_POLICIES;
111 static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
112 SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
113 &mac_max_policies, 0, "");
115 static int mac_late = 0;
117 static int mac_enforce_fs = 1;
118 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
119 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
120 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
122 static int mac_enforce_network = 1;
123 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
124 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
125 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
127 static int mac_enforce_process = 1;
128 SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
129 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
130 TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
132 static int mac_enforce_socket = 1;
133 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
134 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
135 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
137 static int mac_enforce_pipe = 1;
138 SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
139 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
141 static int mac_label_size = sizeof(struct mac);
142 SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD,
143 &mac_label_size, 0, "Pre-compiled MAC label size");
145 static int mac_cache_fslabel_in_vnode = 1;
146 SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
147 &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
148 TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
149 &mac_cache_fslabel_in_vnode);
151 static int mac_vnode_label_cache_hits = 0;
152 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD,
153 &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels");
154 static int mac_vnode_label_cache_misses = 0;
155 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD,
156 &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels");
157 static int mac_mmap_revocation_via_cow = 1;
158 SYSCTL_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");
162 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
163 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
165 SYSCTL_UINT(_security_mac_debug, OID_AUTO, mbufs, CTLFLAG_RD,
166 &nmacmbufs, 0, "number of mbufs in use");
167 SYSCTL_UINT(_security_mac_debug, OID_AUTO, creds, CTLFLAG_RD,
168 &nmaccreds, 0, "number of ucreds in use");
169 SYSCTL_UINT(_security_mac_debug, OID_AUTO, ifnets, CTLFLAG_RD,
170 &nmacifnets, 0, "number of ifnets in use");
171 SYSCTL_UINT(_security_mac_debug, OID_AUTO, ipqs, CTLFLAG_RD,
172 &nmacipqs, 0, "number of ipqs in use");
173 SYSCTL_UINT(_security_mac_debug, OID_AUTO, bpfdescs, CTLFLAG_RD,
174 &nmacbpfdescs, 0, "number of bpfdescs in use");
175 SYSCTL_UINT(_security_mac_debug, OID_AUTO, sockets, CTLFLAG_RD,
176 &nmacsockets, 0, "number of sockets in use");
177 SYSCTL_UINT(_security_mac_debug, OID_AUTO, pipes, CTLFLAG_RD,
178 &nmacpipes, 0, "number of pipes in use");
179 SYSCTL_UINT(_security_mac_debug, OID_AUTO, mounts, CTLFLAG_RD,
180 &nmacmounts, 0, "number of mounts in use");
181 SYSCTL_UINT(_security_mac_debug, OID_AUTO, temp, CTLFLAG_RD,
182 &nmactemp, 0, "number of temporary labels in use");
183 SYSCTL_UINT(_security_mac_debug, OID_AUTO, vnodes, CTLFLAG_RD,
184 &nmacvnodes, 0, "number of vnodes in use");
185 SYSCTL_UINT(_security_mac_debug, OID_AUTO, devfsdirents, CTLFLAG_RD,
186 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
188 static int error_select(int error1, int error2);
189 static int mac_externalize(struct label *label, struct mac *mac);
190 static int mac_policy_register(struct mac_policy_conf *mpc);
191 static int mac_policy_unregister(struct mac_policy_conf *mpc);
193 static int mac_stdcreatevnode_ea(struct vnode *vp);
194 static void mac_cred_mmapped_drop_perms(struct thread *td,
196 static void mac_cred_mmapped_drop_perms_recurse(struct thread *td,
197 struct ucred *cred, struct vm_map *map);
199 MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
200 MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
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.
210 static struct mtx mac_policy_list_lock;
211 static LIST_HEAD(, mac_policy_conf) mac_policy_list;
212 static 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);
218 #define MAC_POLICY_LIST_BUSY() do { \
219 MAC_POLICY_LIST_LOCK(); \
220 mac_policy_list_busy++; \
221 MAC_POLICY_LIST_UNLOCK(); \
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(); \
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
238 #define MAC_CHECK(check, args...) do { \
239 struct mac_policy_conf *mpc; \
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), \
249 MAC_POLICY_LIST_UNBUSY(); \
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.
260 #define MAC_BOOLEAN(operation, composition, args...) do { \
261 struct mac_policy_conf *mpc; \
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); \
269 MAC_POLICY_LIST_UNBUSY(); \
273 * MAC_PERFORM performs the designated operation by walking the policy
274 * module list and invoking that operation for each policy.
276 #define MAC_PERFORM(operation, args...) do { \
277 struct mac_policy_conf *mpc; \
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); \
284 MAC_POLICY_LIST_UNBUSY(); \
288 * Initialize the MAC subsystem, including appropriate SMP locks.
294 LIST_INIT(&mac_policy_list);
295 MAC_POLICY_LIST_LOCKINIT();
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.
311 * Allow MAC policy modules to register during boot, etc.
314 mac_policy_modevent(module_t mod, int type, void *data)
316 struct mac_policy_conf *mpc;
320 mpc = (struct mac_policy_conf *) data;
324 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
326 printf("mac_policy_modevent: can't load %s policy "
327 "after booting\n", mpc->mpc_name);
331 error = mac_policy_register(mpc);
334 /* Don't unregister the module if it was never registered. */
335 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
337 error = mac_policy_unregister(mpc);
349 mac_policy_register(struct mac_policy_conf *mpc)
351 struct mac_policy_conf *tmpc;
352 struct mac_policy_ops *ops;
353 struct mac_policy_op_entry *mpe;
356 MALLOC(mpc->mpc_ops, struct mac_policy_ops *, sizeof(*ops), M_MACOPVEC,
358 for (mpe = mpc->mpc_entries; mpe->mpe_constant != MAC_OP_LAST; mpe++) {
359 switch (mpe->mpe_constant) {
362 * Doesn't actually happen, but this allows checking
363 * that all enumerated values are handled.
367 mpc->mpc_ops->mpo_destroy =
371 mpc->mpc_ops->mpo_init =
374 case MAC_INIT_BPFDESC:
375 mpc->mpc_ops->mpo_init_bpfdesc =
379 mpc->mpc_ops->mpo_init_cred =
382 case MAC_INIT_DEVFSDIRENT:
383 mpc->mpc_ops->mpo_init_devfsdirent =
387 mpc->mpc_ops->mpo_init_ifnet =
391 mpc->mpc_ops->mpo_init_ipq =
395 mpc->mpc_ops->mpo_init_mbuf =
399 mpc->mpc_ops->mpo_init_mount =
403 mpc->mpc_ops->mpo_init_pipe =
406 case MAC_INIT_SOCKET:
407 mpc->mpc_ops->mpo_init_socket =
411 mpc->mpc_ops->mpo_init_temp =
415 mpc->mpc_ops->mpo_init_vnode =
418 case MAC_DESTROY_BPFDESC:
419 mpc->mpc_ops->mpo_destroy_bpfdesc =
422 case MAC_DESTROY_CRED:
423 mpc->mpc_ops->mpo_destroy_cred =
426 case MAC_DESTROY_DEVFSDIRENT:
427 mpc->mpc_ops->mpo_destroy_devfsdirent =
430 case MAC_DESTROY_IFNET:
431 mpc->mpc_ops->mpo_destroy_ifnet =
434 case MAC_DESTROY_IPQ:
435 mpc->mpc_ops->mpo_destroy_ipq =
438 case MAC_DESTROY_MBUF:
439 mpc->mpc_ops->mpo_destroy_mbuf =
442 case MAC_DESTROY_MOUNT:
443 mpc->mpc_ops->mpo_destroy_mount =
446 case MAC_DESTROY_PIPE:
447 mpc->mpc_ops->mpo_destroy_pipe =
450 case MAC_DESTROY_SOCKET:
451 mpc->mpc_ops->mpo_destroy_socket =
454 case MAC_DESTROY_TEMP:
455 mpc->mpc_ops->mpo_destroy_temp =
458 case MAC_DESTROY_VNODE:
459 mpc->mpc_ops->mpo_destroy_vnode =
462 case MAC_EXTERNALIZE:
463 mpc->mpc_ops->mpo_externalize =
466 case MAC_INTERNALIZE:
467 mpc->mpc_ops->mpo_internalize =
470 case MAC_CREATE_DEVFS_DEVICE:
471 mpc->mpc_ops->mpo_create_devfs_device =
474 case MAC_CREATE_DEVFS_DIRECTORY:
475 mpc->mpc_ops->mpo_create_devfs_directory =
478 case MAC_CREATE_DEVFS_VNODE:
479 mpc->mpc_ops->mpo_create_devfs_vnode =
482 case MAC_STDCREATEVNODE_EA:
483 mpc->mpc_ops->mpo_stdcreatevnode_ea =
486 case MAC_CREATE_VNODE:
487 mpc->mpc_ops->mpo_create_vnode =
490 case MAC_CREATE_MOUNT:
491 mpc->mpc_ops->mpo_create_mount =
494 case MAC_CREATE_ROOT_MOUNT:
495 mpc->mpc_ops->mpo_create_root_mount =
498 case MAC_RELABEL_VNODE:
499 mpc->mpc_ops->mpo_relabel_vnode =
502 case MAC_UPDATE_DEVFSDIRENT:
503 mpc->mpc_ops->mpo_update_devfsdirent =
506 case MAC_UPDATE_PROCFSVNODE:
507 mpc->mpc_ops->mpo_update_procfsvnode =
510 case MAC_UPDATE_VNODE_FROM_EXTATTR:
511 mpc->mpc_ops->mpo_update_vnode_from_extattr =
514 case MAC_UPDATE_VNODE_FROM_EXTERNALIZED:
515 mpc->mpc_ops->mpo_update_vnode_from_externalized =
518 case MAC_UPDATE_VNODE_FROM_MOUNT:
519 mpc->mpc_ops->mpo_update_vnode_from_mount =
522 case MAC_CREATE_MBUF_FROM_SOCKET:
523 mpc->mpc_ops->mpo_create_mbuf_from_socket =
526 case MAC_CREATE_PIPE:
527 mpc->mpc_ops->mpo_create_pipe =
530 case MAC_CREATE_SOCKET:
531 mpc->mpc_ops->mpo_create_socket =
534 case MAC_CREATE_SOCKET_FROM_SOCKET:
535 mpc->mpc_ops->mpo_create_socket_from_socket =
538 case MAC_RELABEL_PIPE:
539 mpc->mpc_ops->mpo_relabel_pipe =
542 case MAC_RELABEL_SOCKET:
543 mpc->mpc_ops->mpo_relabel_socket =
546 case MAC_SET_SOCKET_PEER_FROM_MBUF:
547 mpc->mpc_ops->mpo_set_socket_peer_from_mbuf =
550 case MAC_SET_SOCKET_PEER_FROM_SOCKET:
551 mpc->mpc_ops->mpo_set_socket_peer_from_socket =
554 case MAC_CREATE_BPFDESC:
555 mpc->mpc_ops->mpo_create_bpfdesc =
558 case MAC_CREATE_DATAGRAM_FROM_IPQ:
559 mpc->mpc_ops->mpo_create_datagram_from_ipq =
562 case MAC_CREATE_FRAGMENT:
563 mpc->mpc_ops->mpo_create_fragment =
566 case MAC_CREATE_IFNET:
567 mpc->mpc_ops->mpo_create_ifnet =
571 mpc->mpc_ops->mpo_create_ipq =
574 case MAC_CREATE_MBUF_FROM_MBUF:
575 mpc->mpc_ops->mpo_create_mbuf_from_mbuf =
578 case MAC_CREATE_MBUF_LINKLAYER:
579 mpc->mpc_ops->mpo_create_mbuf_linklayer =
582 case MAC_CREATE_MBUF_FROM_BPFDESC:
583 mpc->mpc_ops->mpo_create_mbuf_from_bpfdesc =
586 case MAC_CREATE_MBUF_FROM_IFNET:
587 mpc->mpc_ops->mpo_create_mbuf_from_ifnet =
590 case MAC_CREATE_MBUF_MULTICAST_ENCAP:
591 mpc->mpc_ops->mpo_create_mbuf_multicast_encap =
594 case MAC_CREATE_MBUF_NETLAYER:
595 mpc->mpc_ops->mpo_create_mbuf_netlayer =
598 case MAC_FRAGMENT_MATCH:
599 mpc->mpc_ops->mpo_fragment_match =
602 case MAC_RELABEL_IFNET:
603 mpc->mpc_ops->mpo_relabel_ifnet =
607 mpc->mpc_ops->mpo_update_ipq =
610 case MAC_CREATE_CRED:
611 mpc->mpc_ops->mpo_create_cred =
614 case MAC_EXECVE_TRANSITION:
615 mpc->mpc_ops->mpo_execve_transition =
618 case MAC_EXECVE_WILL_TRANSITION:
619 mpc->mpc_ops->mpo_execve_will_transition =
622 case MAC_CREATE_PROC0:
623 mpc->mpc_ops->mpo_create_proc0 = mpe->mpe_function;
625 case MAC_CREATE_PROC1:
626 mpc->mpc_ops->mpo_create_proc1 = mpe->mpe_function;
628 case MAC_RELABEL_CRED:
629 mpc->mpc_ops->mpo_relabel_cred =
632 case MAC_CHECK_BPFDESC_RECEIVE:
633 mpc->mpc_ops->mpo_check_bpfdesc_receive =
636 case MAC_CHECK_CRED_RELABEL:
637 mpc->mpc_ops->mpo_check_cred_relabel =
640 case MAC_CHECK_CRED_VISIBLE:
641 mpc->mpc_ops->mpo_check_cred_visible =
644 case MAC_CHECK_IFNET_RELABEL:
645 mpc->mpc_ops->mpo_check_ifnet_relabel =
648 case MAC_CHECK_IFNET_TRANSMIT:
649 mpc->mpc_ops->mpo_check_ifnet_transmit =
652 case MAC_CHECK_MOUNT_STAT:
653 mpc->mpc_ops->mpo_check_mount_stat =
656 case MAC_CHECK_PIPE_IOCTL:
657 mpc->mpc_ops->mpo_check_pipe_ioctl =
660 case MAC_CHECK_PIPE_OP:
661 mpc->mpc_ops->mpo_check_pipe_op =
664 case MAC_CHECK_PIPE_RELABEL:
665 mpc->mpc_ops->mpo_check_pipe_relabel =
668 case MAC_CHECK_PROC_DEBUG:
669 mpc->mpc_ops->mpo_check_proc_debug =
672 case MAC_CHECK_PROC_SCHED:
673 mpc->mpc_ops->mpo_check_proc_sched =
676 case MAC_CHECK_PROC_SIGNAL:
677 mpc->mpc_ops->mpo_check_proc_signal =
680 case MAC_CHECK_SOCKET_BIND:
681 mpc->mpc_ops->mpo_check_socket_bind =
684 case MAC_CHECK_SOCKET_CONNECT:
685 mpc->mpc_ops->mpo_check_socket_connect =
688 case MAC_CHECK_SOCKET_LISTEN:
689 mpc->mpc_ops->mpo_check_socket_listen =
692 case MAC_CHECK_SOCKET_RECEIVE:
693 mpc->mpc_ops->mpo_check_socket_receive =
696 case MAC_CHECK_SOCKET_RELABEL:
697 mpc->mpc_ops->mpo_check_socket_relabel =
700 case MAC_CHECK_SOCKET_VISIBLE:
701 mpc->mpc_ops->mpo_check_socket_visible =
704 case MAC_CHECK_VNODE_ACCESS:
705 mpc->mpc_ops->mpo_check_vnode_access =
708 case MAC_CHECK_VNODE_CHDIR:
709 mpc->mpc_ops->mpo_check_vnode_chdir =
712 case MAC_CHECK_VNODE_CHROOT:
713 mpc->mpc_ops->mpo_check_vnode_chroot =
716 case MAC_CHECK_VNODE_CREATE:
717 mpc->mpc_ops->mpo_check_vnode_create =
720 case MAC_CHECK_VNODE_DELETE:
721 mpc->mpc_ops->mpo_check_vnode_delete =
724 case MAC_CHECK_VNODE_DELETEACL:
725 mpc->mpc_ops->mpo_check_vnode_deleteacl =
728 case MAC_CHECK_VNODE_EXEC:
729 mpc->mpc_ops->mpo_check_vnode_exec =
732 case MAC_CHECK_VNODE_GETACL:
733 mpc->mpc_ops->mpo_check_vnode_getacl =
736 case MAC_CHECK_VNODE_GETEXTATTR:
737 mpc->mpc_ops->mpo_check_vnode_getextattr =
740 case MAC_CHECK_VNODE_LOOKUP:
741 mpc->mpc_ops->mpo_check_vnode_lookup =
744 case MAC_CHECK_VNODE_MMAP_PERMS:
745 mpc->mpc_ops->mpo_check_vnode_mmap_perms =
748 case MAC_CHECK_VNODE_OP:
749 mpc->mpc_ops->mpo_check_vnode_op =
752 case MAC_CHECK_VNODE_OPEN:
753 mpc->mpc_ops->mpo_check_vnode_open =
756 case MAC_CHECK_VNODE_READDIR:
757 mpc->mpc_ops->mpo_check_vnode_readdir =
760 case MAC_CHECK_VNODE_READLINK:
761 mpc->mpc_ops->mpo_check_vnode_readlink =
764 case MAC_CHECK_VNODE_RELABEL:
765 mpc->mpc_ops->mpo_check_vnode_relabel =
768 case MAC_CHECK_VNODE_RENAME_FROM:
769 mpc->mpc_ops->mpo_check_vnode_rename_from =
772 case MAC_CHECK_VNODE_RENAME_TO:
773 mpc->mpc_ops->mpo_check_vnode_rename_to =
776 case MAC_CHECK_VNODE_REVOKE:
777 mpc->mpc_ops->mpo_check_vnode_revoke =
780 case MAC_CHECK_VNODE_SETACL:
781 mpc->mpc_ops->mpo_check_vnode_setacl =
784 case MAC_CHECK_VNODE_SETEXTATTR:
785 mpc->mpc_ops->mpo_check_vnode_setextattr =
788 case MAC_CHECK_VNODE_SETFLAGS:
789 mpc->mpc_ops->mpo_check_vnode_setflags =
792 case MAC_CHECK_VNODE_SETMODE:
793 mpc->mpc_ops->mpo_check_vnode_setmode =
796 case MAC_CHECK_VNODE_SETOWNER:
797 mpc->mpc_ops->mpo_check_vnode_setowner =
800 case MAC_CHECK_VNODE_SETUTIMES:
801 mpc->mpc_ops->mpo_check_vnode_setutimes =
804 case MAC_CHECK_VNODE_STAT:
805 mpc->mpc_ops->mpo_check_vnode_stat =
810 printf("MAC policy `%s': unknown operation %d\n",
811 mpc->mpc_name, mpe->mpe_constant);
816 MAC_POLICY_LIST_LOCK();
817 if (mac_policy_list_busy > 0) {
818 MAC_POLICY_LIST_UNLOCK();
819 FREE(mpc->mpc_ops, M_MACOPVEC);
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);
831 if (mpc->mpc_field_off != NULL) {
832 slot = ffs(mac_policy_offsets_free);
834 MAC_POLICY_LIST_UNLOCK();
835 FREE(mpc->mpc_ops, M_MACOPVEC);
840 mac_policy_offsets_free &= ~(1 << slot);
841 *mpc->mpc_field_off = slot;
843 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
844 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
846 /* Per-policy initialization. */
847 if (mpc->mpc_ops->mpo_init != NULL)
848 (*(mpc->mpc_ops->mpo_init))(mpc);
849 MAC_POLICY_LIST_UNLOCK();
851 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
858 mac_policy_unregister(struct mac_policy_conf *mpc)
863 * Don't allow unloading modules with private data.
865 if (mpc->mpc_field_off != NULL)
868 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0)
870 MAC_POLICY_LIST_LOCK();
871 if (mac_policy_list_busy > 0) {
872 MAC_POLICY_LIST_UNLOCK();
875 if (mpc->mpc_ops->mpo_destroy != NULL)
876 (*(mpc->mpc_ops->mpo_destroy))(mpc);
878 LIST_REMOVE(mpc, mpc_list);
879 MAC_POLICY_LIST_UNLOCK();
881 FREE(mpc->mpc_ops, M_MACOPVEC);
884 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
891 * Define an error value precedence, and given two arguments, selects the
892 * value with the higher precedence.
895 error_select(int error1, int error2)
898 /* Certain decision-making errors take top priority. */
899 if (error1 == EDEADLK || error2 == EDEADLK)
902 /* Invalid arguments should be reported where possible. */
903 if (error1 == EINVAL || error2 == EINVAL)
906 /* Precedence goes to "visibility", with both process and file. */
907 if (error1 == ESRCH || error2 == ESRCH)
910 if (error1 == ENOENT || error2 == ENOENT)
913 /* Precedence goes to DAC/MAC protections. */
914 if (error1 == EACCES || error2 == EACCES)
917 /* Precedence goes to privilege. */
918 if (error1 == EPERM || error2 == EPERM)
921 /* Precedence goes to error over success; otherwise, arbitrary. */
928 mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
931 MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
935 mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
938 MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
942 * Support callout for policies that manage their own externalization
943 * using extended attributes.
946 mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
950 MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
957 * Given an externalized mac label, internalize it and stamp it on a
961 mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
965 MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
971 * Call out to individual policies to update the label in a vnode from
975 mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
978 MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
981 ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
982 if (mac_cache_fslabel_in_vnode)
983 vp->v_vflag |= VV_CACHEDLABEL;
987 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
988 * to store label data. Can be referenced by filesystems supporting
989 * extended attributes.
992 vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
994 struct vnode *vp = ap->a_vp;
998 ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1001 * Call out to external policies first. Order doesn't really
1002 * matter, as long as failure of one assures failure of all.
1004 error = mac_update_vnode_from_extattr(vp, vp->v_mount);
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);
1019 * Use the label from the mount point.
1021 mac_update_vnode_from_mount(vp, vp->v_mount);
1026 /* Fail horribly. */
1030 if (buflen != sizeof(extmac))
1031 error = EPERM; /* Fail very closed. */
1033 error = mac_update_vnode_from_externalized(vp, &extmac);
1035 vp->v_vflag |= VV_CACHEDLABEL;
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);
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
1066 vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1070 ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1072 if (vp->v_mount == NULL) {
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.
1078 mac_update_vnode_deadfs(vp);
1081 /* printf("vn_refreshlabel: null v_mount\n"); */
1082 if (vp->v_tag != VT_NON)
1084 "vn_refreshlabel: null v_mount with non-VT_NON\n");
1088 if (vp->v_vflag & VV_CACHEDLABEL) {
1089 mac_vnode_label_cache_hits++;
1092 mac_vnode_label_cache_misses++;
1094 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1095 mac_update_vnode_from_mount(vp, vp->v_mount);
1099 error = VOP_REFRESHLABEL(vp, cred, curthread);
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
1108 mac_update_vnode_from_mount(vp, vp->v_mount);
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.
1123 vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
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);
1132 error = vn_refreshlabel(dvp, cred);
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
1143 mac_create_vnode(cred, dvp, tvp);
1145 error = mac_stdcreatevnode_ea(tvp);
1150 * XXX: Eventually this will go away and all policies will
1151 * directly manage their extended attributes.
1153 error = mac_externalize(&tvp->v_label, &extmac);
1157 error = vn_extattr_set(tvp, IO_NODELOCKED,
1158 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1159 sizeof(extmac), (char *)&extmac, curthread);
1161 tvp->v_vflag |= VV_CACHEDLABEL;
1165 * In theory, we could have fall-back behavior here.
1166 * It would probably be incorrect.
1177 mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1181 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1183 error = vn_refreshlabel(vp, old);
1185 printf("mac_execve_transition: vn_refreshlabel returned %d\n",
1187 printf("mac_execve_transition: using old vnode label\n");
1190 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1194 mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1198 error = vn_refreshlabel(vp, old);
1203 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1209 mac_init_label(struct label *label)
1212 bzero(label, sizeof(*label));
1213 label->l_flags = MAC_FLAG_INITIALIZED;
1217 mac_init_structmac(struct mac *mac)
1220 bzero(mac, sizeof(*mac));
1221 mac->m_macflags = MAC_FLAG_INITIALIZED;
1225 mac_destroy_label(struct label *label)
1228 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1229 ("destroying uninitialized label"));
1231 bzero(label, sizeof(*label));
1232 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1236 mac_init_mbuf(struct mbuf *m, int how)
1238 KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
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);
1248 mac_destroy_mbuf(struct mbuf *m)
1251 MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label);
1252 mac_destroy_label(&m->m_pkthdr.label);
1253 atomic_subtract_int(&nmacmbufs, 1);
1257 mac_init_cred(struct ucred *cr)
1260 mac_init_label(&cr->cr_label);
1261 MAC_PERFORM(init_cred, cr, &cr->cr_label);
1262 atomic_add_int(&nmaccreds, 1);
1266 mac_destroy_cred(struct ucred *cr)
1269 MAC_PERFORM(destroy_cred, cr, &cr->cr_label);
1270 mac_destroy_label(&cr->cr_label);
1271 atomic_subtract_int(&nmaccreds, 1);
1275 mac_init_ifnet(struct ifnet *ifp)
1278 mac_init_label(&ifp->if_label);
1279 MAC_PERFORM(init_ifnet, ifp, &ifp->if_label);
1280 atomic_add_int(&nmacifnets, 1);
1284 mac_destroy_ifnet(struct ifnet *ifp)
1287 MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label);
1288 mac_destroy_label(&ifp->if_label);
1289 atomic_subtract_int(&nmacifnets, 1);
1293 mac_init_ipq(struct ipq *ipq)
1296 mac_init_label(&ipq->ipq_label);
1297 MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label);
1298 atomic_add_int(&nmacipqs, 1);
1302 mac_destroy_ipq(struct ipq *ipq)
1305 MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label);
1306 mac_destroy_label(&ipq->ipq_label);
1307 atomic_subtract_int(&nmacipqs, 1);
1311 mac_init_socket(struct socket *socket)
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);
1322 mac_destroy_socket(struct socket *socket)
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);
1333 mac_init_pipe(struct pipe *pipe)
1335 struct label *label;
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);
1346 mac_destroy_pipe(struct pipe *pipe)
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);
1356 mac_init_bpfdesc(struct bpf_d *bpf_d)
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);
1365 mac_destroy_bpfdesc(struct bpf_d *bpf_d)
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);
1374 mac_init_mount(struct mount *mp)
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);
1384 mac_destroy_mount(struct mount *mp)
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);
1394 mac_init_temp(struct label *label)
1397 mac_init_label(label);
1398 MAC_PERFORM(init_temp, label);
1399 atomic_add_int(&nmactemp, 1);
1403 mac_destroy_temp(struct label *label)
1406 MAC_PERFORM(destroy_temp, label);
1407 mac_destroy_label(label);
1408 atomic_subtract_int(&nmactemp, 1);
1412 mac_init_vnode(struct vnode *vp)
1415 mac_init_label(&vp->v_label);
1416 MAC_PERFORM(init_vnode, vp, &vp->v_label);
1417 atomic_add_int(&nmacvnodes, 1);
1421 mac_destroy_vnode(struct vnode *vp)
1424 MAC_PERFORM(destroy_vnode, vp, &vp->v_label);
1425 mac_destroy_label(&vp->v_label);
1426 atomic_subtract_int(&nmacvnodes, 1);
1430 mac_init_devfsdirent(struct devfs_dirent *de)
1433 mac_init_label(&de->de_label);
1434 MAC_PERFORM(init_devfsdirent, de, &de->de_label);
1435 atomic_add_int(&nmacdevfsdirents, 1);
1439 mac_destroy_devfsdirent(struct devfs_dirent *de)
1442 MAC_PERFORM(destroy_devfsdirent, de, &de->de_label);
1443 mac_destroy_label(&de->de_label);
1444 atomic_subtract_int(&nmacdevfsdirents, 1);
1448 mac_externalize(struct label *label, struct mac *mac)
1452 mac_init_structmac(mac);
1453 MAC_CHECK(externalize, label, mac);
1459 mac_internalize(struct label *label, struct mac *mac)
1463 mac_init_temp(label);
1464 MAC_CHECK(internalize, label, mac);
1466 mac_destroy_temp(label);
1472 * Initialize MAC label for the first kernel process, from which other
1473 * kernel processes and threads are spawned.
1476 mac_create_proc0(struct ucred *cred)
1479 MAC_PERFORM(create_proc0, cred);
1483 * Initialize MAC label for the first userland process, from which other
1484 * userland processes and threads are spawned.
1487 mac_create_proc1(struct ucred *cred)
1490 MAC_PERFORM(create_proc1, cred);
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.
1499 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1502 MAC_PERFORM(create_cred, parent_cred, child_cred);
1506 mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
1510 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1512 if (!mac_enforce_fs)
1515 error = vn_refreshlabel(vp, cred);
1519 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
1524 mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1528 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1530 if (!mac_enforce_fs)
1533 error = vn_refreshlabel(dvp, cred);
1537 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1542 mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1546 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1548 if (!mac_enforce_fs)
1551 error = vn_refreshlabel(dvp, cred);
1555 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1560 mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1561 struct componentname *cnp, struct vattr *vap)
1565 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1567 if (!mac_enforce_fs)
1570 error = vn_refreshlabel(dvp, cred);
1574 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1579 mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1580 struct componentname *cnp)
1584 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1585 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1587 if (!mac_enforce_fs)
1590 error = vn_refreshlabel(dvp, cred);
1593 error = vn_refreshlabel(vp, cred);
1597 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1603 mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1608 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1610 if (!mac_enforce_fs)
1613 error = vn_refreshlabel(vp, cred);
1617 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1622 mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1626 if (!mac_enforce_process && !mac_enforce_fs)
1629 error = vn_refreshlabel(vp, cred);
1632 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1638 mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1642 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1644 if (!mac_enforce_fs)
1647 error = vn_refreshlabel(vp, cred);
1651 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1656 mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1657 int attrnamespace, const char *name, struct uio *uio)
1661 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1663 if (!mac_enforce_fs)
1666 error = vn_refreshlabel(vp, cred);
1670 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1671 attrnamespace, name, uio);
1676 mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1677 struct componentname *cnp)
1681 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1683 if (!mac_enforce_fs)
1686 error = vn_refreshlabel(dvp, cred);
1690 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1695 mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping)
1697 vm_prot_t result = VM_PROT_ALL;
1700 * This should be some sort of MAC_BITWISE, maybe :)
1702 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms");
1703 MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label,
1709 mac_check_vnode_op(struct ucred *cred, struct vnode *vp, int op)
1713 if (!mac_enforce_fs)
1716 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_op");
1718 error = vn_refreshlabel(vp, cred);
1722 MAC_CHECK(check_vnode_op, cred, vp, &vp->v_label, op);
1728 mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
1732 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1734 if (!mac_enforce_fs)
1737 error = vn_refreshlabel(vp, cred);
1741 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1746 mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1750 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1752 if (!mac_enforce_fs)
1755 error = vn_refreshlabel(dvp, cred);
1759 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1764 mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1768 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1770 if (!mac_enforce_fs)
1773 error = vn_refreshlabel(vp, cred);
1777 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1782 mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1783 struct label *newlabel)
1787 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1789 error = vn_refreshlabel(vp, cred);
1793 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1799 mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1800 struct vnode *vp, struct componentname *cnp)
1804 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1805 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1807 if (!mac_enforce_fs)
1810 error = vn_refreshlabel(dvp, cred);
1813 error = vn_refreshlabel(vp, cred);
1817 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1823 mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1824 struct vnode *vp, int samedir, struct componentname *cnp)
1828 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1829 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1831 if (!mac_enforce_fs)
1834 error = vn_refreshlabel(dvp, cred);
1838 error = vn_refreshlabel(vp, cred);
1842 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1843 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1848 mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1852 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1854 if (!mac_enforce_fs)
1857 error = vn_refreshlabel(vp, cred);
1861 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1866 mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1871 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1873 if (!mac_enforce_fs)
1876 error = vn_refreshlabel(vp, cred);
1880 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1885 mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1886 int attrnamespace, const char *name, struct uio *uio)
1890 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1892 if (!mac_enforce_fs)
1895 error = vn_refreshlabel(vp, cred);
1899 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1900 attrnamespace, name, uio);
1905 mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1909 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1911 if (!mac_enforce_fs)
1914 error = vn_refreshlabel(vp, cred);
1918 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1923 mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1927 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1929 if (!mac_enforce_fs)
1932 error = vn_refreshlabel(vp, cred);
1936 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1941 mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1946 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1948 if (!mac_enforce_fs)
1951 error = vn_refreshlabel(vp, cred);
1955 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1960 mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1961 struct timespec atime, struct timespec mtime)
1965 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1967 if (!mac_enforce_fs)
1970 error = vn_refreshlabel(vp, cred);
1974 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1980 mac_check_vnode_stat(struct ucred *cred, struct vnode *vp)
1984 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1986 if (!mac_enforce_fs)
1989 error = vn_refreshlabel(vp, cred);
1993 MAC_CHECK(check_vnode_stat, cred, vp, &vp->v_label);
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.
2004 mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2007 /* XXX freeze all other threads */
2009 mac_cred_mmapped_drop_perms_recurse(td, cred,
2010 &td->td_proc->p_vmspace->vm_map);
2012 /* XXX allow other threads to continue */
2015 static __inline const char *
2016 prot2str(vm_prot_t prot)
2019 switch (prot & VM_PROT_ALL) {
2022 case VM_PROT_READ | VM_PROT_WRITE:
2024 case VM_PROT_READ | VM_PROT_EXECUTE:
2026 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2030 case VM_PROT_EXECUTE:
2032 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2040 mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2043 struct vm_map_entry *vme;
2044 vm_prot_t result, revokeperms;
2046 vm_ooffset_t offset;
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);
2057 * Skip over entries that obviously are not shared.
2059 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2060 !vme->max_protection)
2063 * Drill down to the deepest backing object.
2065 offset = vme->offset;
2066 object = vme->object.vm_object;
2069 while (object->backing_object != NULL) {
2070 object = object->backing_object;
2071 offset += object->backing_object_offset;
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.
2078 if (object->type != OBJT_VNODE)
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);
2085 * Find out what maximum protection we may be allowing
2086 * now but a policy needs to get removed.
2088 revokeperms = vme->max_protection & ~result;
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);
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
2103 if ((vme->protection & revokeperms) == 0) {
2104 vme->max_protection -= revokeperms;
2106 if (revokeperms & VM_PROT_WRITE) {
2108 * In the more complicated case, flush out all
2109 * pending changes to the object then turn it
2112 vm_object_reference(object);
2113 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2114 vm_object_page_clean(object,
2116 OFF_TO_IDX(offset + vme->end - vme->start +
2119 VOP_UNLOCK(vp, 0, td);
2120 vm_object_deallocate(object);
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.
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;
2134 if (revokeperms & VM_PROT_EXECUTE) {
2135 vme->max_protection &= ~VM_PROT_EXECUTE;
2136 vme->protection &= ~VM_PROT_EXECUTE;
2138 if (revokeperms & VM_PROT_READ) {
2139 vme->max_protection = 0;
2140 vme->protection = 0;
2142 pmap_protect(map->pmap, vme->start, vme->end,
2143 vme->protection & ~revokeperms);
2144 vm_map_simplify_entry(map, vme);
2146 vm_map_lock_downgrade(map);
2148 vm_map_unlock_read(map);
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
2157 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2160 MAC_PERFORM(relabel_cred, cred, newlabel);
2161 mac_cred_mmapped_drop_perms(curthread, cred);
2165 mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2168 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2172 mac_create_ifnet(struct ifnet *ifnet)
2175 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2179 mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2182 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2186 mac_create_socket(struct ucred *cred, struct socket *socket)
2189 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2193 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2196 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2200 mac_create_socket_from_socket(struct socket *oldsocket,
2201 struct socket *newsocket)
2204 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2205 newsocket, &newsocket->so_label);
2209 mac_relabel_socket(struct ucred *cred, struct socket *socket,
2210 struct label *newlabel)
2213 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2217 mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2220 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2224 mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2227 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2228 socket, &socket->so_peerlabel);
2232 mac_set_socket_peer_from_socket(struct socket *oldsocket,
2233 struct socket *newsocket)
2236 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2237 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2241 mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2244 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2245 datagram, &datagram->m_pkthdr.label);
2249 mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2252 MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2253 fragment, &fragment->m_pkthdr.label);
2257 mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2260 MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2265 mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2268 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2269 newmbuf, &newmbuf->m_pkthdr.label);
2273 mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2276 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2277 &mbuf->m_pkthdr.label);
2281 mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2284 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2285 &mbuf->m_pkthdr.label);
2289 mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2292 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2293 &mbuf->m_pkthdr.label);
2297 mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2298 struct mbuf *newmbuf)
2301 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2302 &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2303 &newmbuf->m_pkthdr.label);
2307 mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2310 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2311 newmbuf, &newmbuf->m_pkthdr.label);
2315 mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2320 MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2321 ipq, &ipq->ipq_label);
2327 mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2330 MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2335 mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2338 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2339 &mbuf->m_pkthdr.label);
2343 mac_create_mount(struct ucred *cred, struct mount *mp)
2346 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2351 mac_create_root_mount(struct ucred *cred, struct mount *mp)
2354 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2359 mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2363 if (!mac_enforce_network)
2366 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2373 mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2377 MAC_CHECK(check_cred_relabel, cred, newlabel);
2383 mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2387 if (!mac_enforce_process)
2390 MAC_CHECK(check_cred_visible, u1, u2);
2396 mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2400 if (!mac_enforce_network)
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,
2408 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2409 &mbuf->m_pkthdr.label);
2415 mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2419 if (!mac_enforce_fs)
2422 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2428 mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2433 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2439 mac_check_pipe_op(struct ucred *cred, struct pipe *pipe, int op)
2443 MAC_CHECK(check_pipe_op, cred, pipe, pipe->pipe_label, op);
2449 mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2450 struct label *newlabel)
2454 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2460 mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2464 if (!mac_enforce_process)
2467 MAC_CHECK(check_proc_debug, cred, proc);
2473 mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2477 if (!mac_enforce_process)
2480 MAC_CHECK(check_proc_sched, cred, proc);
2486 mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2490 if (!mac_enforce_process)
2493 MAC_CHECK(check_proc_signal, cred, proc, signum);
2499 mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2500 struct sockaddr *sockaddr)
2504 if (!mac_enforce_socket)
2507 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2514 mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2515 struct sockaddr *sockaddr)
2519 if (!mac_enforce_socket)
2522 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2529 mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2533 if (!mac_enforce_socket)
2536 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2541 mac_check_socket_receive(struct socket *socket, struct mbuf *mbuf)
2545 if (!mac_enforce_socket)
2548 MAC_CHECK(check_socket_receive, socket, &socket->so_label, mbuf,
2549 &mbuf->m_pkthdr.label);
2555 mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2556 struct label *newlabel)
2560 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2567 mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2571 if (!mac_enforce_socket)
2574 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2580 mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2581 struct ifnet *ifnet)
2586 error = mac_externalize(&ifnet->if_label, &label);
2590 return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label)));
2594 mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2595 struct ifnet *ifnet)
2597 struct mac newlabel;
2598 struct label intlabel;
2601 error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel));
2605 error = mac_internalize(&intlabel, &newlabel);
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.
2614 error = suser_cred(cred, 0);
2618 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2623 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2626 mac_destroy_temp(&intlabel);
2631 mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2634 MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2638 mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2641 MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2645 mac_stdcreatevnode_ea(struct vnode *vp)
2649 MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
2655 mac_create_devfs_directory(char *dirname, int dirnamelen,
2656 struct devfs_dirent *de)
2659 MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2664 * When a new vnode is created, this call will initialize its label.
2667 mac_create_vnode(struct ucred *cred, struct vnode *parent,
2668 struct vnode *child)
2672 ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
2673 ASSERT_VOP_LOCKED(child, "mac_create_vnode");
2675 error = vn_refreshlabel(parent, cred);
2677 printf("mac_create_vnode: vn_refreshlabel returned %d\n",
2679 printf("mac_create_vnode: using old vnode label\n");
2682 MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
2687 mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2690 struct label intlabel;
2693 error = mac_internalize(&intlabel, extmac);
2697 mac_check_socket_relabel(cred, so, &intlabel);
2699 mac_destroy_temp(&intlabel);
2703 mac_relabel_socket(cred, so, &intlabel);
2705 mac_destroy_temp(&intlabel);
2710 mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2714 error = mac_check_pipe_relabel(cred, pipe, label);
2718 mac_relabel_pipe(cred, pipe, label);
2724 mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2728 return (mac_externalize(&so->so_label, extmac));
2732 mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2736 return (mac_externalize(&so->so_peerlabel, extmac));
2740 * Implementation of VOP_SETLABEL() that relies on extended attributes
2741 * to store label data. Can be referenced by filesystems supporting
2742 * extended attributes.
2745 vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2747 struct vnode *vp = ap->a_vp;
2748 struct label *intlabel = ap->a_label;
2752 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
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
2764 error = mac_externalize(intlabel, &extmac);
2768 error = vn_extattr_set(vp, IO_NODELOCKED,
2769 FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
2770 sizeof(extmac), (char *)&extmac, curthread);
2774 mac_relabel_vnode(ap->a_cred, vp, intlabel);
2776 vp->v_vflag |= VV_CACHEDLABEL;
2782 vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
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");
2793 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
2794 return (EOPNOTSUPP);
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()?
2802 error = mac_check_vnode_relabel(cred, vp, intlabel);
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().
2813 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
2817 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
2828 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
2833 error = mac_externalize(&td->td_ucred->cr_label, &extmac);
2835 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
2843 * XXX: Needs to be re-written for proc locking.
2846 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
2848 struct ucred *newcred, *oldcred;
2851 struct label intlabel;
2854 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
2858 error = mac_internalize(&intlabel, &extmac);
2866 oldcred = p->p_ucred;
2868 error = mac_check_cred_relabel(oldcred, &intlabel);
2871 mac_destroy_temp(&intlabel);
2877 crcopy(newcred, oldcred);
2879 mac_relabel_cred(newcred, &intlabel);
2882 p->p_ucred = newcred;
2885 mac_destroy_temp(&intlabel);
2893 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
2903 error = fget(td, SCARG(uap, fd), &fp);
2907 switch (fp->f_type) {
2910 vp = (struct vnode *)fp->f_data;
2912 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2913 error = vn_refreshlabel(vp, td->td_ucred);
2915 error = mac_externalize(&vp->v_label, &extmac);
2916 VOP_UNLOCK(vp, 0, td);
2919 pipe = (struct pipe *)fp->f_data;
2920 error = mac_externalize(pipe->pipe_label, &extmac);
2927 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
2940 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
2942 struct nameidata nd;
2947 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
2948 SCARG(uap, path_p), td);
2953 error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
2955 error = mac_externalize(&nd.ni_vp->v_label, &extmac);
2960 error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
2971 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
2975 struct label intlabel;
2982 error = fget(td, SCARG(uap, fd), &fp);
2986 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
2990 error = mac_internalize(&intlabel, &extmac);
2994 switch (fp->f_type) {
2997 vp = (struct vnode *)fp->f_data;
2998 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
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);
3009 pipe = (struct pipe *)fp->f_data;
3010 error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel);
3027 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3029 struct nameidata nd;
3031 struct label intlabel;
3037 error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3041 error = mac_internalize(&intlabel, &extmac);
3045 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3046 SCARG(uap, path_p), td);
3050 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3054 error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred);
3056 vn_finished_write(mp);
3058 mac_destroy_temp(&intlabel);
3065 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3066 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3071 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3078 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3085 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3092 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3099 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3106 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)