Deleted Added
full compact
mac_pipe.c (118308) mac_pipe.c (119184)
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 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 Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA 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 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37/*
38 * Framework for extensible kernel access control. Kernel and userland
39 * interface to the framework, policy registration and composition.
40 */
41
42#include <sys/cdefs.h>
1/*-
2 * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3 * Copyright (c) 2001 Ilmar S. Habibulin
4 * Copyright (c) 2001, 2002, 2003 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 Network
11 * Associates Laboratories, the Security Research Division of Network
12 * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
13 * as part of the DARPA 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 *
24 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
25 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
26 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
27 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
28 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
29 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
30 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
31 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
32 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
33 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
35 */
36
37/*
38 * Framework for extensible kernel access control. Kernel and userland
39 * interface to the framework, policy registration and composition.
40 */
41
42#include <sys/cdefs.h>
43__FBSDID("$FreeBSD: head/sys/security/mac/mac_pipe.c 118308 2003-08-01 15:45:14Z rwatson $");
43__FBSDID("$FreeBSD: head/sys/security/mac/mac_pipe.c 119184 2003-08-20 19:16:49Z rwatson $");
44
45#include "opt_mac.h"
46#include "opt_devfs.h"
47
48#include <sys/param.h>
49#include <sys/condvar.h>
50#include <sys/extattr.h>
51#include <sys/imgact.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
55#include <sys/mutex.h>
56#include <sys/mac.h>
57#include <sys/module.h>
58#include <sys/proc.h>
59#include <sys/sbuf.h>
60#include <sys/systm.h>
61#include <sys/sysproto.h>
62#include <sys/sysent.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/file.h>
66#include <sys/namei.h>
67#include <sys/socket.h>
68#include <sys/pipe.h>
69#include <sys/socketvar.h>
70#include <sys/sysctl.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76
77#include <sys/mac_policy.h>
78
79#include <fs/devfs/devfs.h>
80
81#include <net/bpfdesc.h>
82#include <net/if.h>
83#include <net/if_var.h>
84
85#include <netinet/in.h>
86#include <netinet/ip_var.h>
87
88#ifdef MAC
89
90/*
91 * Declare that the kernel provides MAC support, version 1. This permits
92 * modules to refuse to be loaded if the necessary support isn't present,
93 * even if it's pre-boot.
94 */
95MODULE_VERSION(kernel_mac_support, 1);
96
97SYSCTL_DECL(_security);
98
99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100 "TrustedBSD MAC policy controls");
101
102#if MAC_MAX_SLOTS > 32
103#error "MAC_MAX_SLOTS too large"
104#endif
105
106static unsigned int mac_max_slots = MAC_MAX_SLOTS;
107static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
108SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
109 &mac_max_slots, 0, "");
110
111/*
112 * Has the kernel started generating labeled objects yet? All read/write
113 * access to this variable is serialized during the boot process. Following
114 * the end of serialization, we don't update this flag; no locking.
115 */
116static int mac_late = 0;
117
118/*
119 * Warn about EA transactions only the first time they happen.
120 * Weak coherency, no locking.
121 */
122static int ea_warn_once = 0;
123
124/*
125 * Flag to indicate whether or not we should allocate label storage for
126 * new mbufs. Since most dynamic policies we currently work with don't
127 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
128 * unless specifically notified of interest. One result of this is
129 * that if a dynamically loaded policy requests mbuf labels, it must
130 * be able to deal with a NULL label being returned on any mbufs that
131 * were already in flight when the policy was loaded. Since the policy
132 * already has to deal with uninitialized labels, this probably won't
133 * be a problem. Note: currently no locking. Will this be a problem?
134 */
135#ifndef MAC_ALWAYS_LABEL_MBUF
136static int mac_labelmbufs = 0;
137#endif
138
139static int mac_enforce_fs = 1;
140SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
141 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
142TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
143
144static int mac_enforce_kld = 1;
145SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
146 &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
147TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
148
149static int mac_enforce_network = 1;
150SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
151 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
152TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
153
154static int mac_enforce_pipe = 1;
155SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
156 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
157TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
158
159static int mac_enforce_process = 1;
160SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
161 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
162TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
163
164static int mac_enforce_socket = 1;
165SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
166 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
167TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
168
169static int mac_enforce_system = 1;
170SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
171 &mac_enforce_system, 0, "Enforce MAC policy on system operations");
172TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
173
174static int mac_enforce_vm = 1;
175SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
176 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
177TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
178
179static int mac_mmap_revocation = 1;
180SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
181 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
182 "relabel");
183static int mac_mmap_revocation_via_cow = 0;
184SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
185 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
186 "copy-on-write semantics, or by removing all write access");
187
188#ifdef MAC_DEBUG
189SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
190 "TrustedBSD MAC debug info");
191
192static int mac_debug_label_fallback = 0;
193SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
194 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
195 "when label is corrupted.");
196TUNABLE_INT("security.mac.debug_label_fallback",
197 &mac_debug_label_fallback);
198
199SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
200 "TrustedBSD MAC object counters");
201
202static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
203 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
204 nmacipqs, nmacpipes, nmacprocs;
205
44
45#include "opt_mac.h"
46#include "opt_devfs.h"
47
48#include <sys/param.h>
49#include <sys/condvar.h>
50#include <sys/extattr.h>
51#include <sys/imgact.h>
52#include <sys/kernel.h>
53#include <sys/lock.h>
54#include <sys/malloc.h>
55#include <sys/mutex.h>
56#include <sys/mac.h>
57#include <sys/module.h>
58#include <sys/proc.h>
59#include <sys/sbuf.h>
60#include <sys/systm.h>
61#include <sys/sysproto.h>
62#include <sys/sysent.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/file.h>
66#include <sys/namei.h>
67#include <sys/socket.h>
68#include <sys/pipe.h>
69#include <sys/socketvar.h>
70#include <sys/sysctl.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76
77#include <sys/mac_policy.h>
78
79#include <fs/devfs/devfs.h>
80
81#include <net/bpfdesc.h>
82#include <net/if.h>
83#include <net/if_var.h>
84
85#include <netinet/in.h>
86#include <netinet/ip_var.h>
87
88#ifdef MAC
89
90/*
91 * Declare that the kernel provides MAC support, version 1. This permits
92 * modules to refuse to be loaded if the necessary support isn't present,
93 * even if it's pre-boot.
94 */
95MODULE_VERSION(kernel_mac_support, 1);
96
97SYSCTL_DECL(_security);
98
99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100 "TrustedBSD MAC policy controls");
101
102#if MAC_MAX_SLOTS > 32
103#error "MAC_MAX_SLOTS too large"
104#endif
105
106static unsigned int mac_max_slots = MAC_MAX_SLOTS;
107static unsigned int mac_slot_offsets_free = (1 << MAC_MAX_SLOTS) - 1;
108SYSCTL_UINT(_security_mac, OID_AUTO, max_slots, CTLFLAG_RD,
109 &mac_max_slots, 0, "");
110
111/*
112 * Has the kernel started generating labeled objects yet? All read/write
113 * access to this variable is serialized during the boot process. Following
114 * the end of serialization, we don't update this flag; no locking.
115 */
116static int mac_late = 0;
117
118/*
119 * Warn about EA transactions only the first time they happen.
120 * Weak coherency, no locking.
121 */
122static int ea_warn_once = 0;
123
124/*
125 * Flag to indicate whether or not we should allocate label storage for
126 * new mbufs. Since most dynamic policies we currently work with don't
127 * rely on mbuf labeling, try to avoid paying the cost of mtag allocation
128 * unless specifically notified of interest. One result of this is
129 * that if a dynamically loaded policy requests mbuf labels, it must
130 * be able to deal with a NULL label being returned on any mbufs that
131 * were already in flight when the policy was loaded. Since the policy
132 * already has to deal with uninitialized labels, this probably won't
133 * be a problem. Note: currently no locking. Will this be a problem?
134 */
135#ifndef MAC_ALWAYS_LABEL_MBUF
136static int mac_labelmbufs = 0;
137#endif
138
139static int mac_enforce_fs = 1;
140SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
141 &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
142TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
143
144static int mac_enforce_kld = 1;
145SYSCTL_INT(_security_mac, OID_AUTO, enforce_kld, CTLFLAG_RW,
146 &mac_enforce_kld, 0, "Enforce MAC policy on kld operations");
147TUNABLE_INT("security.mac.enforce_kld", &mac_enforce_kld);
148
149static int mac_enforce_network = 1;
150SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
151 &mac_enforce_network, 0, "Enforce MAC policy on network packets");
152TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
153
154static int mac_enforce_pipe = 1;
155SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
156 &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
157TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
158
159static int mac_enforce_process = 1;
160SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
161 &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
162TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
163
164static int mac_enforce_socket = 1;
165SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
166 &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
167TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
168
169static int mac_enforce_system = 1;
170SYSCTL_INT(_security_mac, OID_AUTO, enforce_system, CTLFLAG_RW,
171 &mac_enforce_system, 0, "Enforce MAC policy on system operations");
172TUNABLE_INT("security.mac.enforce_system", &mac_enforce_system);
173
174static int mac_enforce_vm = 1;
175SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
176 &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
177TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
178
179static int mac_mmap_revocation = 1;
180SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
181 &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
182 "relabel");
183static int mac_mmap_revocation_via_cow = 0;
184SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation_via_cow, CTLFLAG_RW,
185 &mac_mmap_revocation_via_cow, 0, "Revoke mmap access to files via "
186 "copy-on-write semantics, or by removing all write access");
187
188#ifdef MAC_DEBUG
189SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
190 "TrustedBSD MAC debug info");
191
192static int mac_debug_label_fallback = 0;
193SYSCTL_INT(_security_mac_debug, OID_AUTO, label_fallback, CTLFLAG_RW,
194 &mac_debug_label_fallback, 0, "Filesystems should fall back to fs label"
195 "when label is corrupted.");
196TUNABLE_INT("security.mac.debug_label_fallback",
197 &mac_debug_label_fallback);
198
199SYSCTL_NODE(_security_mac_debug, OID_AUTO, counters, CTLFLAG_RW, 0,
200 "TrustedBSD MAC object counters");
201
202static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
203 nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
204 nmacipqs, nmacpipes, nmacprocs;
205
206#define MAC_DEBUG_COUNTER_INC(x) atomic_add_int(x, 1);
207#define MAC_DEBUG_COUNTER_DEC(x) atomic_subtract_int(x, 1);
208
206SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
207 &nmacmbufs, 0, "number of mbufs in use");
208SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
209 &nmaccreds, 0, "number of ucreds in use");
210SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
211 &nmacifnets, 0, "number of ifnets in use");
212SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
213 &nmacipqs, 0, "number of ipqs in use");
214SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
215 &nmacbpfdescs, 0, "number of bpfdescs in use");
216SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
217 &nmacsockets, 0, "number of sockets in use");
218SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
219 &nmacpipes, 0, "number of pipes in use");
220SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
221 &nmacprocs, 0, "number of procs in use");
222SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
223 &nmacmounts, 0, "number of mounts in use");
224SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
225 &nmactemp, 0, "number of temporary labels in use");
226SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
227 &nmacvnodes, 0, "number of vnodes in use");
228SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
229 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
209SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mbufs, CTLFLAG_RD,
210 &nmacmbufs, 0, "number of mbufs in use");
211SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, creds, CTLFLAG_RD,
212 &nmaccreds, 0, "number of ucreds in use");
213SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ifnets, CTLFLAG_RD,
214 &nmacifnets, 0, "number of ifnets in use");
215SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, ipqs, CTLFLAG_RD,
216 &nmacipqs, 0, "number of ipqs in use");
217SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, bpfdescs, CTLFLAG_RD,
218 &nmacbpfdescs, 0, "number of bpfdescs in use");
219SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, sockets, CTLFLAG_RD,
220 &nmacsockets, 0, "number of sockets in use");
221SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, pipes, CTLFLAG_RD,
222 &nmacpipes, 0, "number of pipes in use");
223SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, procs, CTLFLAG_RD,
224 &nmacprocs, 0, "number of procs in use");
225SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, mounts, CTLFLAG_RD,
226 &nmacmounts, 0, "number of mounts in use");
227SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, temp, CTLFLAG_RD,
228 &nmactemp, 0, "number of temporary labels in use");
229SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, vnodes, CTLFLAG_RD,
230 &nmacvnodes, 0, "number of vnodes in use");
231SYSCTL_UINT(_security_mac_debug_counters, OID_AUTO, devfsdirents, CTLFLAG_RD,
232 &nmacdevfsdirents, 0, "number of devfs dirents inuse");
233#else
234#define MAC_DEBUG_COUNTER_INC(x)
235#define MAC_DEBUG_COUNTER_DEC(x)
230#endif
231
232static int error_select(int error1, int error2);
233static int mac_policy_register(struct mac_policy_conf *mpc);
234static int mac_policy_unregister(struct mac_policy_conf *mpc);
235
236static void mac_check_vnode_mmap_downgrade(struct ucred *cred,
237 struct vnode *vp, int *prot);
238static void mac_cred_mmapped_drop_perms_recurse(struct thread *td,
239 struct ucred *cred, struct vm_map *map);
240
241static void mac_destroy_socket_label(struct label *label);
242
243static int mac_setlabel_vnode_extattr(struct ucred *cred,
244 struct vnode *vp, struct label *intlabel);
245
246MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
247MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
248
249/*
250 * mac_static_policy_list holds a list of policy modules that are not
251 * loaded while the system is "live", and cannot be unloaded. These
252 * policies can be invoked without holding the busy count.
253 *
254 * mac_policy_list stores the list of dynamic policies. A busy count is
255 * maintained for the list, stored in mac_policy_busy. The busy count
256 * is protected by mac_policy_mtx; the list may be modified only
257 * while the busy count is 0, requiring that the lock be held to
258 * prevent new references to the list from being acquired. For almost
259 * all operations, incrementing the busy count is sufficient to
260 * guarantee consistency, as the list cannot be modified while the
261 * busy count is elevated. For a few special operations involving a
262 * change to the list of active policies, the mtx itself must be held.
263 * A condition variable, mac_policy_cv, is used to signal potential
264 * exclusive consumers that they should try to acquire the lock if a
265 * first attempt at exclusive access fails.
266 */
267static struct mtx mac_policy_mtx;
268static struct cv mac_policy_cv;
269static int mac_policy_count;
270static LIST_HEAD(, mac_policy_conf) mac_policy_list;
271static LIST_HEAD(, mac_policy_conf) mac_static_policy_list;
272
273/*
274 * We manually invoke WITNESS_WARN() to allow Witness to generate
275 * warnings even if we don't end up ever triggering the wait at
276 * run-time. The consumer of the exclusive interface must not hold
277 * any locks (other than potentially Giant) since we may sleep for
278 * long (potentially indefinite) periods of time waiting for the
279 * framework to become quiescent so that a policy list change may
280 * be made.
281 */
282static __inline void
283mac_policy_grab_exclusive(void)
284{
285 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
286 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
287 mtx_lock(&mac_policy_mtx);
288 while (mac_policy_count != 0)
289 cv_wait(&mac_policy_cv, &mac_policy_mtx);
290}
291
292static __inline void
293mac_policy_assert_exclusive(void)
294{
295 mtx_assert(&mac_policy_mtx, MA_OWNED);
296 KASSERT(mac_policy_count == 0,
297 ("mac_policy_assert_exclusive(): not exclusive"));
298}
299
300static __inline void
301mac_policy_release_exclusive(void)
302{
303
304 KASSERT(mac_policy_count == 0,
305 ("mac_policy_release_exclusive(): not exclusive"));
306 mtx_unlock(&mac_policy_mtx);
307 cv_signal(&mac_policy_cv);
308}
309
310static __inline void
311mac_policy_list_busy(void)
312{
313 mtx_lock(&mac_policy_mtx);
314 mac_policy_count++;
315 mtx_unlock(&mac_policy_mtx);
316}
317
318static __inline int
319mac_policy_list_conditional_busy(void)
320{
321 int ret;
322
323 mtx_lock(&mac_policy_mtx);
324 if (!LIST_EMPTY(&mac_policy_list)) {
325 mac_policy_count++;
326 ret = 1;
327 } else
328 ret = 0;
329 mtx_unlock(&mac_policy_mtx);
330 return (ret);
331}
332
333static __inline void
334mac_policy_list_unbusy(void)
335{
336 mtx_lock(&mac_policy_mtx);
337 mac_policy_count--;
338 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
339 if (mac_policy_count == 0)
340 cv_signal(&mac_policy_cv);
341 mtx_unlock(&mac_policy_mtx);
342}
343
344/*
345 * MAC_CHECK performs the designated check by walking the policy
346 * module list and checking with each as to how it feels about the
347 * request. Note that it returns its value via 'error' in the scope
348 * of the caller.
349 */
350#define MAC_CHECK(check, args...) do { \
351 struct mac_policy_conf *mpc; \
352 int entrycount; \
353 \
354 error = 0; \
355 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
356 if (mpc->mpc_ops->mpo_ ## check != NULL) \
357 error = error_select( \
358 mpc->mpc_ops->mpo_ ## check (args), \
359 error); \
360 } \
361 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
362 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
363 if (mpc->mpc_ops->mpo_ ## check != NULL) \
364 error = error_select( \
365 mpc->mpc_ops->mpo_ ## check (args), \
366 error); \
367 } \
368 mac_policy_list_unbusy(); \
369 } \
370} while (0)
371
372/*
373 * MAC_BOOLEAN performs the designated boolean composition by walking
374 * the module list, invoking each instance of the operation, and
375 * combining the results using the passed C operator. Note that it
376 * returns its value via 'result' in the scope of the caller, which
377 * should be initialized by the caller in a meaningful way to get
378 * a meaningful result.
379 */
380#define MAC_BOOLEAN(operation, composition, args...) do { \
381 struct mac_policy_conf *mpc; \
382 int entrycount; \
383 \
384 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
385 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
386 result = result composition \
387 mpc->mpc_ops->mpo_ ## operation (args); \
388 } \
389 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
390 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
391 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
392 result = result composition \
393 mpc->mpc_ops->mpo_ ## operation \
394 (args); \
395 } \
396 mac_policy_list_unbusy(); \
397 } \
398} while (0)
399
400#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \
401 outbuflen) do { \
402 int claimed, first, ignorenotfound, savedlen; \
403 char *element_name, *element_temp; \
404 struct sbuf sb; \
405 \
406 error = 0; \
407 first = 1; \
408 sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \
409 element_temp = elementlist; \
410 while ((element_name = strsep(&element_temp, ",")) != NULL) { \
411 if (element_name[0] == '?') { \
412 element_name++; \
413 ignorenotfound = 1; \
414 } else \
415 ignorenotfound = 0; \
416 savedlen = sbuf_len(&sb); \
417 if (first) { \
418 error = sbuf_printf(&sb, "%s/", element_name); \
419 first = 0; \
420 } else \
421 error = sbuf_printf(&sb, ",%s/", element_name); \
422 if (error == -1) { \
423 error = EINVAL; /* XXX: E2BIG? */ \
424 break; \
425 } \
426 claimed = 0; \
427 MAC_CHECK(externalize_ ## type, label, element_name, \
428 &sb, &claimed); \
429 if (error) \
430 break; \
431 if (claimed == 0 && ignorenotfound) { \
432 /* Revert last label name. */ \
433 sbuf_setpos(&sb, savedlen); \
434 } else if (claimed != 1) { \
435 error = EINVAL; /* XXX: ENOLABEL? */ \
436 break; \
437 } \
438 } \
439 sbuf_finish(&sb); \
440} while (0)
441
442#define MAC_INTERNALIZE(type, label, instring) do { \
443 char *element, *element_name, *element_data; \
444 int claimed; \
445 \
446 error = 0; \
447 element = instring; \
448 while ((element_name = strsep(&element, ",")) != NULL) { \
449 element_data = element_name; \
450 element_name = strsep(&element_data, "/"); \
451 if (element_data == NULL) { \
452 error = EINVAL; \
453 break; \
454 } \
455 claimed = 0; \
456 MAC_CHECK(internalize_ ## type, label, element_name, \
457 element_data, &claimed); \
458 if (error) \
459 break; \
460 if (claimed != 1) { \
461 /* XXXMAC: Another error here? */ \
462 error = EINVAL; \
463 break; \
464 } \
465 } \
466} while (0)
467
468/*
469 * MAC_PERFORM performs the designated operation by walking the policy
470 * module list and invoking that operation for each policy.
471 */
472#define MAC_PERFORM(operation, args...) do { \
473 struct mac_policy_conf *mpc; \
474 int entrycount; \
475 \
476 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
477 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
478 mpc->mpc_ops->mpo_ ## operation (args); \
479 } \
480 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
481 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
482 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
483 mpc->mpc_ops->mpo_ ## operation (args); \
484 } \
485 mac_policy_list_unbusy(); \
486 } \
487} while (0)
488
489/*
490 * Initialize the MAC subsystem, including appropriate SMP locks.
491 */
492static void
493mac_init(void)
494{
495
496 LIST_INIT(&mac_static_policy_list);
497 LIST_INIT(&mac_policy_list);
498
499 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
500 cv_init(&mac_policy_cv, "mac_policy_cv");
501}
502
503/*
504 * For the purposes of modules that want to know if they were loaded
505 * "early", set the mac_late flag once we've processed modules either
506 * linked into the kernel, or loaded before the kernel startup.
507 */
508static void
509mac_late_init(void)
510{
511
512 mac_late = 1;
513}
514
515/*
516 * After the policy list has changed, walk the list to update any global
517 * flags. Currently, we support only one flag, and it's conditionally
518 * defined; as a result, the entire function is conditional. Eventually,
519 * the #else case might also iterate across the policies.
520 */
521static void
522mac_policy_updateflags(void)
523{
524#ifndef MAC_ALWAYS_LABEL_MBUF
525 struct mac_policy_conf *tmpc;
526 int labelmbufs;
527
528 mac_policy_assert_exclusive();
529
530 labelmbufs = 0;
531 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
532 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
533 labelmbufs++;
534 }
535 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
536 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
537 labelmbufs++;
538 }
539 mac_labelmbufs = (labelmbufs != 0);
540#endif
541}
542
543/*
544 * Allow MAC policy modules to register during boot, etc.
545 */
546int
547mac_policy_modevent(module_t mod, int type, void *data)
548{
549 struct mac_policy_conf *mpc;
550 int error;
551
552 error = 0;
553 mpc = (struct mac_policy_conf *) data;
554
555 switch (type) {
556 case MOD_LOAD:
557 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
558 mac_late) {
559 printf("mac_policy_modevent: can't load %s policy "
560 "after booting\n", mpc->mpc_name);
561 error = EBUSY;
562 break;
563 }
564 error = mac_policy_register(mpc);
565 break;
566 case MOD_UNLOAD:
567 /* Don't unregister the module if it was never registered. */
568 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
569 != 0)
570 error = mac_policy_unregister(mpc);
571 else
572 error = 0;
573 break;
574 default:
575 break;
576 }
577
578 return (error);
579}
580
581static int
582mac_policy_register(struct mac_policy_conf *mpc)
583{
584 struct mac_policy_conf *tmpc;
585 int error, slot, static_entry;
586
587 error = 0;
588
589 /*
590 * We don't technically need exclusive access while !mac_late,
591 * but hold it for assertion consistency.
592 */
593 mac_policy_grab_exclusive();
594
595 /*
596 * If the module can potentially be unloaded, or we're loading
597 * late, we have to stick it in the non-static list and pay
598 * an extra performance overhead. Otherwise, we can pay a
599 * light locking cost and stick it in the static list.
600 */
601 static_entry = (!mac_late &&
602 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
603
604 if (static_entry) {
605 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
606 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
607 error = EEXIST;
608 goto out;
609 }
610 }
611 } else {
612 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
613 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
614 error = EEXIST;
615 goto out;
616 }
617 }
618 }
619 if (mpc->mpc_field_off != NULL) {
620 slot = ffs(mac_slot_offsets_free);
621 if (slot == 0) {
622 error = ENOMEM;
623 goto out;
624 }
625 slot--;
626 mac_slot_offsets_free &= ~(1 << slot);
627 *mpc->mpc_field_off = slot;
628 }
629 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
630
631 /*
632 * If we're loading a MAC module after the framework has
633 * initialized, it has to go into the dynamic list. If
634 * we're loading it before we've finished initializing,
635 * it can go into the static list with weaker locker
636 * requirements.
637 */
638 if (static_entry)
639 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
640 else
641 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
642
643 /* Per-policy initialization. */
644 if (mpc->mpc_ops->mpo_init != NULL)
645 (*(mpc->mpc_ops->mpo_init))(mpc);
646 mac_policy_updateflags();
647
648 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
649 mpc->mpc_name);
650
651out:
652 mac_policy_release_exclusive();
653 return (error);
654}
655
656static int
657mac_policy_unregister(struct mac_policy_conf *mpc)
658{
659
660 /*
661 * If we fail the load, we may get a request to unload. Check
662 * to see if we did the run-time registration, and if not,
663 * silently succeed.
664 */
665 mac_policy_grab_exclusive();
666 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
667 mac_policy_release_exclusive();
668 return (0);
669 }
670#if 0
671 /*
672 * Don't allow unloading modules with private data.
673 */
674 if (mpc->mpc_field_off != NULL) {
675 MAC_POLICY_LIST_UNLOCK();
676 return (EBUSY);
677 }
678#endif
679 /*
680 * Only allow the unload to proceed if the module is unloadable
681 * by its own definition.
682 */
683 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
684 mac_policy_release_exclusive();
685 return (EBUSY);
686 }
687 if (mpc->mpc_ops->mpo_destroy != NULL)
688 (*(mpc->mpc_ops->mpo_destroy))(mpc);
689
690 LIST_REMOVE(mpc, mpc_list);
691 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
692 mac_policy_updateflags();
693
694 mac_policy_release_exclusive();
695
696 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
697 mpc->mpc_name);
698
699 return (0);
700}
701
702/*
703 * Define an error value precedence, and given two arguments, selects the
704 * value with the higher precedence.
705 */
706static int
707error_select(int error1, int error2)
708{
709
710 /* Certain decision-making errors take top priority. */
711 if (error1 == EDEADLK || error2 == EDEADLK)
712 return (EDEADLK);
713
714 /* Invalid arguments should be reported where possible. */
715 if (error1 == EINVAL || error2 == EINVAL)
716 return (EINVAL);
717
718 /* Precedence goes to "visibility", with both process and file. */
719 if (error1 == ESRCH || error2 == ESRCH)
720 return (ESRCH);
721
722 if (error1 == ENOENT || error2 == ENOENT)
723 return (ENOENT);
724
725 /* Precedence goes to DAC/MAC protections. */
726 if (error1 == EACCES || error2 == EACCES)
727 return (EACCES);
728
729 /* Precedence goes to privilege. */
730 if (error1 == EPERM || error2 == EPERM)
731 return (EPERM);
732
733 /* Precedence goes to error over success; otherwise, arbitrary. */
734 if (error1 != 0)
735 return (error1);
736 return (error2);
737}
738
739static struct label *
740mbuf_to_label(struct mbuf *mbuf)
741{
742 struct m_tag *tag;
743 struct label *label;
744
745 tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
746 label = (struct label *)(tag+1);
747
748 return (label);
749}
750
751static void
752mac_init_label(struct label *label)
753{
754
755 bzero(label, sizeof(*label));
756 label->l_flags = MAC_FLAG_INITIALIZED;
757}
758
759static void
760mac_destroy_label(struct label *label)
761{
762
763 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
764 ("destroying uninitialized label"));
765
766 bzero(label, sizeof(*label));
767 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
768}
769
770void
771mac_init_bpfdesc(struct bpf_d *bpf_d)
772{
773
774 mac_init_label(&bpf_d->bd_label);
775 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
236#endif
237
238static int error_select(int error1, int error2);
239static int mac_policy_register(struct mac_policy_conf *mpc);
240static int mac_policy_unregister(struct mac_policy_conf *mpc);
241
242static void mac_check_vnode_mmap_downgrade(struct ucred *cred,
243 struct vnode *vp, int *prot);
244static void mac_cred_mmapped_drop_perms_recurse(struct thread *td,
245 struct ucred *cred, struct vm_map *map);
246
247static void mac_destroy_socket_label(struct label *label);
248
249static int mac_setlabel_vnode_extattr(struct ucred *cred,
250 struct vnode *vp, struct label *intlabel);
251
252MALLOC_DEFINE(M_MACPIPELABEL, "macpipelabel", "MAC labels for pipes");
253MALLOC_DEFINE(M_MACTEMP, "mactemp", "MAC temporary label storage");
254
255/*
256 * mac_static_policy_list holds a list of policy modules that are not
257 * loaded while the system is "live", and cannot be unloaded. These
258 * policies can be invoked without holding the busy count.
259 *
260 * mac_policy_list stores the list of dynamic policies. A busy count is
261 * maintained for the list, stored in mac_policy_busy. The busy count
262 * is protected by mac_policy_mtx; the list may be modified only
263 * while the busy count is 0, requiring that the lock be held to
264 * prevent new references to the list from being acquired. For almost
265 * all operations, incrementing the busy count is sufficient to
266 * guarantee consistency, as the list cannot be modified while the
267 * busy count is elevated. For a few special operations involving a
268 * change to the list of active policies, the mtx itself must be held.
269 * A condition variable, mac_policy_cv, is used to signal potential
270 * exclusive consumers that they should try to acquire the lock if a
271 * first attempt at exclusive access fails.
272 */
273static struct mtx mac_policy_mtx;
274static struct cv mac_policy_cv;
275static int mac_policy_count;
276static LIST_HEAD(, mac_policy_conf) mac_policy_list;
277static LIST_HEAD(, mac_policy_conf) mac_static_policy_list;
278
279/*
280 * We manually invoke WITNESS_WARN() to allow Witness to generate
281 * warnings even if we don't end up ever triggering the wait at
282 * run-time. The consumer of the exclusive interface must not hold
283 * any locks (other than potentially Giant) since we may sleep for
284 * long (potentially indefinite) periods of time waiting for the
285 * framework to become quiescent so that a policy list change may
286 * be made.
287 */
288static __inline void
289mac_policy_grab_exclusive(void)
290{
291 WITNESS_WARN(WARN_GIANTOK | WARN_SLEEPOK, NULL,
292 "mac_policy_grab_exclusive() at %s:%d", __FILE__, __LINE__);
293 mtx_lock(&mac_policy_mtx);
294 while (mac_policy_count != 0)
295 cv_wait(&mac_policy_cv, &mac_policy_mtx);
296}
297
298static __inline void
299mac_policy_assert_exclusive(void)
300{
301 mtx_assert(&mac_policy_mtx, MA_OWNED);
302 KASSERT(mac_policy_count == 0,
303 ("mac_policy_assert_exclusive(): not exclusive"));
304}
305
306static __inline void
307mac_policy_release_exclusive(void)
308{
309
310 KASSERT(mac_policy_count == 0,
311 ("mac_policy_release_exclusive(): not exclusive"));
312 mtx_unlock(&mac_policy_mtx);
313 cv_signal(&mac_policy_cv);
314}
315
316static __inline void
317mac_policy_list_busy(void)
318{
319 mtx_lock(&mac_policy_mtx);
320 mac_policy_count++;
321 mtx_unlock(&mac_policy_mtx);
322}
323
324static __inline int
325mac_policy_list_conditional_busy(void)
326{
327 int ret;
328
329 mtx_lock(&mac_policy_mtx);
330 if (!LIST_EMPTY(&mac_policy_list)) {
331 mac_policy_count++;
332 ret = 1;
333 } else
334 ret = 0;
335 mtx_unlock(&mac_policy_mtx);
336 return (ret);
337}
338
339static __inline void
340mac_policy_list_unbusy(void)
341{
342 mtx_lock(&mac_policy_mtx);
343 mac_policy_count--;
344 KASSERT(mac_policy_count >= 0, ("MAC_POLICY_LIST_LOCK"));
345 if (mac_policy_count == 0)
346 cv_signal(&mac_policy_cv);
347 mtx_unlock(&mac_policy_mtx);
348}
349
350/*
351 * MAC_CHECK performs the designated check by walking the policy
352 * module list and checking with each as to how it feels about the
353 * request. Note that it returns its value via 'error' in the scope
354 * of the caller.
355 */
356#define MAC_CHECK(check, args...) do { \
357 struct mac_policy_conf *mpc; \
358 int entrycount; \
359 \
360 error = 0; \
361 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
362 if (mpc->mpc_ops->mpo_ ## check != NULL) \
363 error = error_select( \
364 mpc->mpc_ops->mpo_ ## check (args), \
365 error); \
366 } \
367 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
368 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
369 if (mpc->mpc_ops->mpo_ ## check != NULL) \
370 error = error_select( \
371 mpc->mpc_ops->mpo_ ## check (args), \
372 error); \
373 } \
374 mac_policy_list_unbusy(); \
375 } \
376} while (0)
377
378/*
379 * MAC_BOOLEAN performs the designated boolean composition by walking
380 * the module list, invoking each instance of the operation, and
381 * combining the results using the passed C operator. Note that it
382 * returns its value via 'result' in the scope of the caller, which
383 * should be initialized by the caller in a meaningful way to get
384 * a meaningful result.
385 */
386#define MAC_BOOLEAN(operation, composition, args...) do { \
387 struct mac_policy_conf *mpc; \
388 int entrycount; \
389 \
390 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
391 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
392 result = result composition \
393 mpc->mpc_ops->mpo_ ## operation (args); \
394 } \
395 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
396 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
397 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
398 result = result composition \
399 mpc->mpc_ops->mpo_ ## operation \
400 (args); \
401 } \
402 mac_policy_list_unbusy(); \
403 } \
404} while (0)
405
406#define MAC_EXTERNALIZE(type, label, elementlist, outbuf, \
407 outbuflen) do { \
408 int claimed, first, ignorenotfound, savedlen; \
409 char *element_name, *element_temp; \
410 struct sbuf sb; \
411 \
412 error = 0; \
413 first = 1; \
414 sbuf_new(&sb, outbuf, outbuflen, SBUF_FIXEDLEN); \
415 element_temp = elementlist; \
416 while ((element_name = strsep(&element_temp, ",")) != NULL) { \
417 if (element_name[0] == '?') { \
418 element_name++; \
419 ignorenotfound = 1; \
420 } else \
421 ignorenotfound = 0; \
422 savedlen = sbuf_len(&sb); \
423 if (first) { \
424 error = sbuf_printf(&sb, "%s/", element_name); \
425 first = 0; \
426 } else \
427 error = sbuf_printf(&sb, ",%s/", element_name); \
428 if (error == -1) { \
429 error = EINVAL; /* XXX: E2BIG? */ \
430 break; \
431 } \
432 claimed = 0; \
433 MAC_CHECK(externalize_ ## type, label, element_name, \
434 &sb, &claimed); \
435 if (error) \
436 break; \
437 if (claimed == 0 && ignorenotfound) { \
438 /* Revert last label name. */ \
439 sbuf_setpos(&sb, savedlen); \
440 } else if (claimed != 1) { \
441 error = EINVAL; /* XXX: ENOLABEL? */ \
442 break; \
443 } \
444 } \
445 sbuf_finish(&sb); \
446} while (0)
447
448#define MAC_INTERNALIZE(type, label, instring) do { \
449 char *element, *element_name, *element_data; \
450 int claimed; \
451 \
452 error = 0; \
453 element = instring; \
454 while ((element_name = strsep(&element, ",")) != NULL) { \
455 element_data = element_name; \
456 element_name = strsep(&element_data, "/"); \
457 if (element_data == NULL) { \
458 error = EINVAL; \
459 break; \
460 } \
461 claimed = 0; \
462 MAC_CHECK(internalize_ ## type, label, element_name, \
463 element_data, &claimed); \
464 if (error) \
465 break; \
466 if (claimed != 1) { \
467 /* XXXMAC: Another error here? */ \
468 error = EINVAL; \
469 break; \
470 } \
471 } \
472} while (0)
473
474/*
475 * MAC_PERFORM performs the designated operation by walking the policy
476 * module list and invoking that operation for each policy.
477 */
478#define MAC_PERFORM(operation, args...) do { \
479 struct mac_policy_conf *mpc; \
480 int entrycount; \
481 \
482 LIST_FOREACH(mpc, &mac_static_policy_list, mpc_list) { \
483 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
484 mpc->mpc_ops->mpo_ ## operation (args); \
485 } \
486 if ((entrycount = mac_policy_list_conditional_busy()) != 0) { \
487 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) { \
488 if (mpc->mpc_ops->mpo_ ## operation != NULL) \
489 mpc->mpc_ops->mpo_ ## operation (args); \
490 } \
491 mac_policy_list_unbusy(); \
492 } \
493} while (0)
494
495/*
496 * Initialize the MAC subsystem, including appropriate SMP locks.
497 */
498static void
499mac_init(void)
500{
501
502 LIST_INIT(&mac_static_policy_list);
503 LIST_INIT(&mac_policy_list);
504
505 mtx_init(&mac_policy_mtx, "mac_policy_mtx", NULL, MTX_DEF);
506 cv_init(&mac_policy_cv, "mac_policy_cv");
507}
508
509/*
510 * For the purposes of modules that want to know if they were loaded
511 * "early", set the mac_late flag once we've processed modules either
512 * linked into the kernel, or loaded before the kernel startup.
513 */
514static void
515mac_late_init(void)
516{
517
518 mac_late = 1;
519}
520
521/*
522 * After the policy list has changed, walk the list to update any global
523 * flags. Currently, we support only one flag, and it's conditionally
524 * defined; as a result, the entire function is conditional. Eventually,
525 * the #else case might also iterate across the policies.
526 */
527static void
528mac_policy_updateflags(void)
529{
530#ifndef MAC_ALWAYS_LABEL_MBUF
531 struct mac_policy_conf *tmpc;
532 int labelmbufs;
533
534 mac_policy_assert_exclusive();
535
536 labelmbufs = 0;
537 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
538 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
539 labelmbufs++;
540 }
541 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
542 if (tmpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_LABELMBUFS)
543 labelmbufs++;
544 }
545 mac_labelmbufs = (labelmbufs != 0);
546#endif
547}
548
549/*
550 * Allow MAC policy modules to register during boot, etc.
551 */
552int
553mac_policy_modevent(module_t mod, int type, void *data)
554{
555 struct mac_policy_conf *mpc;
556 int error;
557
558 error = 0;
559 mpc = (struct mac_policy_conf *) data;
560
561 switch (type) {
562 case MOD_LOAD:
563 if (mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_NOTLATE &&
564 mac_late) {
565 printf("mac_policy_modevent: can't load %s policy "
566 "after booting\n", mpc->mpc_name);
567 error = EBUSY;
568 break;
569 }
570 error = mac_policy_register(mpc);
571 break;
572 case MOD_UNLOAD:
573 /* Don't unregister the module if it was never registered. */
574 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED)
575 != 0)
576 error = mac_policy_unregister(mpc);
577 else
578 error = 0;
579 break;
580 default:
581 break;
582 }
583
584 return (error);
585}
586
587static int
588mac_policy_register(struct mac_policy_conf *mpc)
589{
590 struct mac_policy_conf *tmpc;
591 int error, slot, static_entry;
592
593 error = 0;
594
595 /*
596 * We don't technically need exclusive access while !mac_late,
597 * but hold it for assertion consistency.
598 */
599 mac_policy_grab_exclusive();
600
601 /*
602 * If the module can potentially be unloaded, or we're loading
603 * late, we have to stick it in the non-static list and pay
604 * an extra performance overhead. Otherwise, we can pay a
605 * light locking cost and stick it in the static list.
606 */
607 static_entry = (!mac_late &&
608 !(mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK));
609
610 if (static_entry) {
611 LIST_FOREACH(tmpc, &mac_static_policy_list, mpc_list) {
612 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
613 error = EEXIST;
614 goto out;
615 }
616 }
617 } else {
618 LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
619 if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
620 error = EEXIST;
621 goto out;
622 }
623 }
624 }
625 if (mpc->mpc_field_off != NULL) {
626 slot = ffs(mac_slot_offsets_free);
627 if (slot == 0) {
628 error = ENOMEM;
629 goto out;
630 }
631 slot--;
632 mac_slot_offsets_free &= ~(1 << slot);
633 *mpc->mpc_field_off = slot;
634 }
635 mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
636
637 /*
638 * If we're loading a MAC module after the framework has
639 * initialized, it has to go into the dynamic list. If
640 * we're loading it before we've finished initializing,
641 * it can go into the static list with weaker locker
642 * requirements.
643 */
644 if (static_entry)
645 LIST_INSERT_HEAD(&mac_static_policy_list, mpc, mpc_list);
646 else
647 LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
648
649 /* Per-policy initialization. */
650 if (mpc->mpc_ops->mpo_init != NULL)
651 (*(mpc->mpc_ops->mpo_init))(mpc);
652 mac_policy_updateflags();
653
654 printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
655 mpc->mpc_name);
656
657out:
658 mac_policy_release_exclusive();
659 return (error);
660}
661
662static int
663mac_policy_unregister(struct mac_policy_conf *mpc)
664{
665
666 /*
667 * If we fail the load, we may get a request to unload. Check
668 * to see if we did the run-time registration, and if not,
669 * silently succeed.
670 */
671 mac_policy_grab_exclusive();
672 if ((mpc->mpc_runtime_flags & MPC_RUNTIME_FLAG_REGISTERED) == 0) {
673 mac_policy_release_exclusive();
674 return (0);
675 }
676#if 0
677 /*
678 * Don't allow unloading modules with private data.
679 */
680 if (mpc->mpc_field_off != NULL) {
681 MAC_POLICY_LIST_UNLOCK();
682 return (EBUSY);
683 }
684#endif
685 /*
686 * Only allow the unload to proceed if the module is unloadable
687 * by its own definition.
688 */
689 if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0) {
690 mac_policy_release_exclusive();
691 return (EBUSY);
692 }
693 if (mpc->mpc_ops->mpo_destroy != NULL)
694 (*(mpc->mpc_ops->mpo_destroy))(mpc);
695
696 LIST_REMOVE(mpc, mpc_list);
697 mpc->mpc_runtime_flags &= ~MPC_RUNTIME_FLAG_REGISTERED;
698 mac_policy_updateflags();
699
700 mac_policy_release_exclusive();
701
702 printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
703 mpc->mpc_name);
704
705 return (0);
706}
707
708/*
709 * Define an error value precedence, and given two arguments, selects the
710 * value with the higher precedence.
711 */
712static int
713error_select(int error1, int error2)
714{
715
716 /* Certain decision-making errors take top priority. */
717 if (error1 == EDEADLK || error2 == EDEADLK)
718 return (EDEADLK);
719
720 /* Invalid arguments should be reported where possible. */
721 if (error1 == EINVAL || error2 == EINVAL)
722 return (EINVAL);
723
724 /* Precedence goes to "visibility", with both process and file. */
725 if (error1 == ESRCH || error2 == ESRCH)
726 return (ESRCH);
727
728 if (error1 == ENOENT || error2 == ENOENT)
729 return (ENOENT);
730
731 /* Precedence goes to DAC/MAC protections. */
732 if (error1 == EACCES || error2 == EACCES)
733 return (EACCES);
734
735 /* Precedence goes to privilege. */
736 if (error1 == EPERM || error2 == EPERM)
737 return (EPERM);
738
739 /* Precedence goes to error over success; otherwise, arbitrary. */
740 if (error1 != 0)
741 return (error1);
742 return (error2);
743}
744
745static struct label *
746mbuf_to_label(struct mbuf *mbuf)
747{
748 struct m_tag *tag;
749 struct label *label;
750
751 tag = m_tag_find(mbuf, PACKET_TAG_MACLABEL, NULL);
752 label = (struct label *)(tag+1);
753
754 return (label);
755}
756
757static void
758mac_init_label(struct label *label)
759{
760
761 bzero(label, sizeof(*label));
762 label->l_flags = MAC_FLAG_INITIALIZED;
763}
764
765static void
766mac_destroy_label(struct label *label)
767{
768
769 KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
770 ("destroying uninitialized label"));
771
772 bzero(label, sizeof(*label));
773 /* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
774}
775
776void
777mac_init_bpfdesc(struct bpf_d *bpf_d)
778{
779
780 mac_init_label(&bpf_d->bd_label);
781 MAC_PERFORM(init_bpfdesc_label, &bpf_d->bd_label);
776#ifdef MAC_DEBUG
777 atomic_add_int(&nmacbpfdescs, 1);
778#endif
782 MAC_DEBUG_COUNTER_INC(&nmacbpfdescs);
779}
780
781static void
782mac_init_cred_label(struct label *label)
783{
784
785 mac_init_label(label);
786 MAC_PERFORM(init_cred_label, label);
783}
784
785static void
786mac_init_cred_label(struct label *label)
787{
788
789 mac_init_label(label);
790 MAC_PERFORM(init_cred_label, label);
787#ifdef MAC_DEBUG
788 atomic_add_int(&nmaccreds, 1);
789#endif
791 MAC_DEBUG_COUNTER_INC(&nmaccreds);
790}
791
792void
793mac_init_cred(struct ucred *cred)
794{
795
796 mac_init_cred_label(&cred->cr_label);
797}
798
799void
800mac_init_devfsdirent(struct devfs_dirent *de)
801{
802
803 mac_init_label(&de->de_label);
804 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
792}
793
794void
795mac_init_cred(struct ucred *cred)
796{
797
798 mac_init_cred_label(&cred->cr_label);
799}
800
801void
802mac_init_devfsdirent(struct devfs_dirent *de)
803{
804
805 mac_init_label(&de->de_label);
806 MAC_PERFORM(init_devfsdirent_label, &de->de_label);
805#ifdef MAC_DEBUG
806 atomic_add_int(&nmacdevfsdirents, 1);
807#endif
807 MAC_DEBUG_COUNTER_INC(&nmacdevfsdirents);
808}
809
810static void
811mac_init_ifnet_label(struct label *label)
812{
813
814 mac_init_label(label);
815 MAC_PERFORM(init_ifnet_label, label);
808}
809
810static void
811mac_init_ifnet_label(struct label *label)
812{
813
814 mac_init_label(label);
815 MAC_PERFORM(init_ifnet_label, label);
816#ifdef MAC_DEBUG
817 atomic_add_int(&nmacifnets, 1);
818#endif
816 MAC_DEBUG_COUNTER_INC(&nmacifnets);
819}
820
821void
822mac_init_ifnet(struct ifnet *ifp)
823{
824
825 mac_init_ifnet_label(&ifp->if_label);
826}
827
828int
829mac_init_ipq(struct ipq *ipq, int flag)
830{
831 int error;
832
833 mac_init_label(&ipq->ipq_label);
834
835 MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
836 if (error) {
837 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
838 mac_destroy_label(&ipq->ipq_label);
817}
818
819void
820mac_init_ifnet(struct ifnet *ifp)
821{
822
823 mac_init_ifnet_label(&ifp->if_label);
824}
825
826int
827mac_init_ipq(struct ipq *ipq, int flag)
828{
829 int error;
830
831 mac_init_label(&ipq->ipq_label);
832
833 MAC_CHECK(init_ipq_label, &ipq->ipq_label, flag);
834 if (error) {
835 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
836 mac_destroy_label(&ipq->ipq_label);
837 } else {
838 MAC_DEBUG_COUNTER_INC(&nmacipqs);
839 }
839 }
840#ifdef MAC_DEBUG
841 if (error == 0)
842 atomic_add_int(&nmacipqs, 1);
843#endif
844 return (error);
845}
846
847int
848mac_init_mbuf_tag(struct m_tag *tag, int flag)
849{
850 struct label *label;
851 int error;
852
853 label = (struct label *) (tag + 1);
854 mac_init_label(label);
855
856 MAC_CHECK(init_mbuf_label, label, flag);
857 if (error) {
858 MAC_PERFORM(destroy_mbuf_label, label);
859 mac_destroy_label(label);
840 return (error);
841}
842
843int
844mac_init_mbuf_tag(struct m_tag *tag, int flag)
845{
846 struct label *label;
847 int error;
848
849 label = (struct label *) (tag + 1);
850 mac_init_label(label);
851
852 MAC_CHECK(init_mbuf_label, label, flag);
853 if (error) {
854 MAC_PERFORM(destroy_mbuf_label, label);
855 mac_destroy_label(label);
856 } else {
857 MAC_DEBUG_COUNTER_INC(&nmacmbufs);
860 }
858 }
861#ifdef MAC_DEBUG
862 if (error == 0)
863 atomic_add_int(&nmacmbufs, 1);
864#endif
865 return (error);
866}
867
868int
869mac_init_mbuf(struct mbuf *m, int flag)
870{
871 struct m_tag *tag;
872 int error;
873
874 M_ASSERTPKTHDR(m);
875
876#ifndef MAC_ALWAYS_LABEL_MBUF
877 /*
878 * If conditionally allocating mbuf labels, don't allocate unless
879 * they are required.
880 */
881 if (!mac_labelmbufs)
882 return (0);
883#endif
884 tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
885 flag);
886 if (tag == NULL)
887 return (ENOMEM);
888 error = mac_init_mbuf_tag(tag, flag);
889 if (error) {
890 m_tag_free(tag);
891 return (error);
892 }
893 m_tag_prepend(m, tag);
894 return (0);
895}
896
897void
898mac_init_mount(struct mount *mp)
899{
900
901 mac_init_label(&mp->mnt_mntlabel);
902 mac_init_label(&mp->mnt_fslabel);
903 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
904 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
859 return (error);
860}
861
862int
863mac_init_mbuf(struct mbuf *m, int flag)
864{
865 struct m_tag *tag;
866 int error;
867
868 M_ASSERTPKTHDR(m);
869
870#ifndef MAC_ALWAYS_LABEL_MBUF
871 /*
872 * If conditionally allocating mbuf labels, don't allocate unless
873 * they are required.
874 */
875 if (!mac_labelmbufs)
876 return (0);
877#endif
878 tag = m_tag_get(PACKET_TAG_MACLABEL, sizeof(struct label),
879 flag);
880 if (tag == NULL)
881 return (ENOMEM);
882 error = mac_init_mbuf_tag(tag, flag);
883 if (error) {
884 m_tag_free(tag);
885 return (error);
886 }
887 m_tag_prepend(m, tag);
888 return (0);
889}
890
891void
892mac_init_mount(struct mount *mp)
893{
894
895 mac_init_label(&mp->mnt_mntlabel);
896 mac_init_label(&mp->mnt_fslabel);
897 MAC_PERFORM(init_mount_label, &mp->mnt_mntlabel);
898 MAC_PERFORM(init_mount_fs_label, &mp->mnt_fslabel);
905#ifdef MAC_DEBUG
906 atomic_add_int(&nmacmounts, 1);
907#endif
899 MAC_DEBUG_COUNTER_INC(&nmacmounts);
908}
909
910static void
911mac_init_pipe_label(struct label *label)
912{
913
914 mac_init_label(label);
915 MAC_PERFORM(init_pipe_label, label);
900}
901
902static void
903mac_init_pipe_label(struct label *label)
904{
905
906 mac_init_label(label);
907 MAC_PERFORM(init_pipe_label, label);
916#ifdef MAC_DEBUG
917 atomic_add_int(&nmacpipes, 1);
918#endif
908 MAC_DEBUG_COUNTER_INC(&nmacpipes);
919}
920
921void
922mac_init_pipe(struct pipe *pipe)
923{
924 struct label *label;
925
926 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
927 pipe->pipe_label = label;
928 pipe->pipe_peer->pipe_label = label;
929 mac_init_pipe_label(label);
930}
931
932void
933mac_init_proc(struct proc *p)
934{
935
936 mac_init_label(&p->p_label);
937 MAC_PERFORM(init_proc_label, &p->p_label);
909}
910
911void
912mac_init_pipe(struct pipe *pipe)
913{
914 struct label *label;
915
916 label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
917 pipe->pipe_label = label;
918 pipe->pipe_peer->pipe_label = label;
919 mac_init_pipe_label(label);
920}
921
922void
923mac_init_proc(struct proc *p)
924{
925
926 mac_init_label(&p->p_label);
927 MAC_PERFORM(init_proc_label, &p->p_label);
938#ifdef MAC_DEBUG
939 atomic_add_int(&nmacprocs, 1);
940#endif
928 MAC_DEBUG_COUNTER_INC(&nmacprocs);
941}
942
943static int
944mac_init_socket_label(struct label *label, int flag)
945{
946 int error;
947
948 mac_init_label(label);
949
950 MAC_CHECK(init_socket_label, label, flag);
951 if (error) {
952 MAC_PERFORM(destroy_socket_label, label);
953 mac_destroy_label(label);
929}
930
931static int
932mac_init_socket_label(struct label *label, int flag)
933{
934 int error;
935
936 mac_init_label(label);
937
938 MAC_CHECK(init_socket_label, label, flag);
939 if (error) {
940 MAC_PERFORM(destroy_socket_label, label);
941 mac_destroy_label(label);
942 } else {
943 MAC_DEBUG_COUNTER_INC(&nmacsockets);
954 }
955
944 }
945
956#ifdef MAC_DEBUG
957 if (error == 0)
958 atomic_add_int(&nmacsockets, 1);
959#endif
960
961 return (error);
962}
963
964static int
965mac_init_socket_peer_label(struct label *label, int flag)
966{
967 int error;
968
969 mac_init_label(label);
970
971 MAC_CHECK(init_socket_peer_label, label, flag);
972 if (error) {
973 MAC_PERFORM(destroy_socket_label, label);
974 mac_destroy_label(label);
975 }
976
977 return (error);
978}
979
980int
981mac_init_socket(struct socket *socket, int flag)
982{
983 int error;
984
985 error = mac_init_socket_label(&socket->so_label, flag);
986 if (error)
987 return (error);
988
989 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
990 if (error)
991 mac_destroy_socket_label(&socket->so_label);
992
993 return (error);
994}
995
996void
997mac_init_vnode_label(struct label *label)
998{
999
1000 mac_init_label(label);
1001 MAC_PERFORM(init_vnode_label, label);
946 return (error);
947}
948
949static int
950mac_init_socket_peer_label(struct label *label, int flag)
951{
952 int error;
953
954 mac_init_label(label);
955
956 MAC_CHECK(init_socket_peer_label, label, flag);
957 if (error) {
958 MAC_PERFORM(destroy_socket_label, label);
959 mac_destroy_label(label);
960 }
961
962 return (error);
963}
964
965int
966mac_init_socket(struct socket *socket, int flag)
967{
968 int error;
969
970 error = mac_init_socket_label(&socket->so_label, flag);
971 if (error)
972 return (error);
973
974 error = mac_init_socket_peer_label(&socket->so_peerlabel, flag);
975 if (error)
976 mac_destroy_socket_label(&socket->so_label);
977
978 return (error);
979}
980
981void
982mac_init_vnode_label(struct label *label)
983{
984
985 mac_init_label(label);
986 MAC_PERFORM(init_vnode_label, label);
1002#ifdef MAC_DEBUG
1003 atomic_add_int(&nmacvnodes, 1);
1004#endif
987 MAC_DEBUG_COUNTER_INC(&nmacvnodes);
1005}
1006
1007void
1008mac_init_vnode(struct vnode *vp)
1009{
1010
1011 mac_init_vnode_label(&vp->v_label);
1012}
1013
1014void
1015mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1016{
1017
1018 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1019 mac_destroy_label(&bpf_d->bd_label);
988}
989
990void
991mac_init_vnode(struct vnode *vp)
992{
993
994 mac_init_vnode_label(&vp->v_label);
995}
996
997void
998mac_destroy_bpfdesc(struct bpf_d *bpf_d)
999{
1000
1001 MAC_PERFORM(destroy_bpfdesc_label, &bpf_d->bd_label);
1002 mac_destroy_label(&bpf_d->bd_label);
1020#ifdef MAC_DEBUG
1021 atomic_subtract_int(&nmacbpfdescs, 1);
1022#endif
1003 MAC_DEBUG_COUNTER_DEC(&nmacbpfdescs);
1023}
1024
1025static void
1026mac_destroy_cred_label(struct label *label)
1027{
1028
1029 MAC_PERFORM(destroy_cred_label, label);
1030 mac_destroy_label(label);
1004}
1005
1006static void
1007mac_destroy_cred_label(struct label *label)
1008{
1009
1010 MAC_PERFORM(destroy_cred_label, label);
1011 mac_destroy_label(label);
1031#ifdef MAC_DEBUG
1032 atomic_subtract_int(&nmaccreds, 1);
1033#endif
1012 MAC_DEBUG_COUNTER_DEC(&nmaccreds);
1034}
1035
1036void
1037mac_destroy_cred(struct ucred *cred)
1038{
1039
1040 mac_destroy_cred_label(&cred->cr_label);
1041}
1042
1043void
1044mac_destroy_devfsdirent(struct devfs_dirent *de)
1045{
1046
1047 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1048 mac_destroy_label(&de->de_label);
1013}
1014
1015void
1016mac_destroy_cred(struct ucred *cred)
1017{
1018
1019 mac_destroy_cred_label(&cred->cr_label);
1020}
1021
1022void
1023mac_destroy_devfsdirent(struct devfs_dirent *de)
1024{
1025
1026 MAC_PERFORM(destroy_devfsdirent_label, &de->de_label);
1027 mac_destroy_label(&de->de_label);
1049#ifdef MAC_DEBUG
1050 atomic_subtract_int(&nmacdevfsdirents, 1);
1051#endif
1028 MAC_DEBUG_COUNTER_DEC(&nmacdevfsdirents);
1052}
1053
1054static void
1055mac_destroy_ifnet_label(struct label *label)
1056{
1057
1058 MAC_PERFORM(destroy_ifnet_label, label);
1059 mac_destroy_label(label);
1029}
1030
1031static void
1032mac_destroy_ifnet_label(struct label *label)
1033{
1034
1035 MAC_PERFORM(destroy_ifnet_label, label);
1036 mac_destroy_label(label);
1060#ifdef MAC_DEBUG
1061 atomic_subtract_int(&nmacifnets, 1);
1062#endif
1037 MAC_DEBUG_COUNTER_DEC(&nmacifnets);
1063}
1064
1065void
1066mac_destroy_ifnet(struct ifnet *ifp)
1067{
1068
1069 mac_destroy_ifnet_label(&ifp->if_label);
1070}
1071
1072void
1073mac_destroy_ipq(struct ipq *ipq)
1074{
1075
1076 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1077 mac_destroy_label(&ipq->ipq_label);
1038}
1039
1040void
1041mac_destroy_ifnet(struct ifnet *ifp)
1042{
1043
1044 mac_destroy_ifnet_label(&ifp->if_label);
1045}
1046
1047void
1048mac_destroy_ipq(struct ipq *ipq)
1049{
1050
1051 MAC_PERFORM(destroy_ipq_label, &ipq->ipq_label);
1052 mac_destroy_label(&ipq->ipq_label);
1078#ifdef MAC_DEBUG
1079 atomic_subtract_int(&nmacipqs, 1);
1080#endif
1053 MAC_DEBUG_COUNTER_DEC(&nmacipqs);
1081}
1082
1083void
1084mac_destroy_mbuf_tag(struct m_tag *tag)
1085{
1086 struct label *label;
1087
1088 label = (struct label *)(tag+1);
1089
1090 MAC_PERFORM(destroy_mbuf_label, label);
1091 mac_destroy_label(label);
1054}
1055
1056void
1057mac_destroy_mbuf_tag(struct m_tag *tag)
1058{
1059 struct label *label;
1060
1061 label = (struct label *)(tag+1);
1062
1063 MAC_PERFORM(destroy_mbuf_label, label);
1064 mac_destroy_label(label);
1092#ifdef MAC_DEBUG
1093 atomic_subtract_int(&nmacmbufs, 1);
1094#endif
1065 MAC_DEBUG_COUNTER_DEC(&nmacmbufs);
1095}
1096
1097void
1098mac_destroy_mount(struct mount *mp)
1099{
1100
1101 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1102 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1103 mac_destroy_label(&mp->mnt_fslabel);
1104 mac_destroy_label(&mp->mnt_mntlabel);
1066}
1067
1068void
1069mac_destroy_mount(struct mount *mp)
1070{
1071
1072 MAC_PERFORM(destroy_mount_label, &mp->mnt_mntlabel);
1073 MAC_PERFORM(destroy_mount_fs_label, &mp->mnt_fslabel);
1074 mac_destroy_label(&mp->mnt_fslabel);
1075 mac_destroy_label(&mp->mnt_mntlabel);
1105#ifdef MAC_DEBUG
1106 atomic_subtract_int(&nmacmounts, 1);
1107#endif
1076 MAC_DEBUG_COUNTER_DEC(&nmacmounts);
1108}
1109
1110static void
1111mac_destroy_pipe_label(struct label *label)
1112{
1113
1114 MAC_PERFORM(destroy_pipe_label, label);
1115 mac_destroy_label(label);
1077}
1078
1079static void
1080mac_destroy_pipe_label(struct label *label)
1081{
1082
1083 MAC_PERFORM(destroy_pipe_label, label);
1084 mac_destroy_label(label);
1116#ifdef MAC_DEBUG
1117 atomic_subtract_int(&nmacpipes, 1);
1118#endif
1085 MAC_DEBUG_COUNTER_DEC(&nmacpipes);
1119}
1120
1121void
1122mac_destroy_pipe(struct pipe *pipe)
1123{
1124
1125 mac_destroy_pipe_label(pipe->pipe_label);
1126 free(pipe->pipe_label, M_MACPIPELABEL);
1127}
1128
1129void
1130mac_destroy_proc(struct proc *p)
1131{
1132
1133 MAC_PERFORM(destroy_proc_label, &p->p_label);
1134 mac_destroy_label(&p->p_label);
1086}
1087
1088void
1089mac_destroy_pipe(struct pipe *pipe)
1090{
1091
1092 mac_destroy_pipe_label(pipe->pipe_label);
1093 free(pipe->pipe_label, M_MACPIPELABEL);
1094}
1095
1096void
1097mac_destroy_proc(struct proc *p)
1098{
1099
1100 MAC_PERFORM(destroy_proc_label, &p->p_label);
1101 mac_destroy_label(&p->p_label);
1135#ifdef MAC_DEBUG
1136 atomic_subtract_int(&nmacprocs, 1);
1137#endif
1102 MAC_DEBUG_COUNTER_DEC(&nmacprocs);
1138}
1139
1140static void
1141mac_destroy_socket_label(struct label *label)
1142{
1143
1144 MAC_PERFORM(destroy_socket_label, label);
1145 mac_destroy_label(label);
1103}
1104
1105static void
1106mac_destroy_socket_label(struct label *label)
1107{
1108
1109 MAC_PERFORM(destroy_socket_label, label);
1110 mac_destroy_label(label);
1146#ifdef MAC_DEBUG
1147 atomic_subtract_int(&nmacsockets, 1);
1148#endif
1111 MAC_DEBUG_COUNTER_DEC(&nmacsockets);
1149}
1150
1151static void
1152mac_destroy_socket_peer_label(struct label *label)
1153{
1154
1155 MAC_PERFORM(destroy_socket_peer_label, label);
1156 mac_destroy_label(label);
1157}
1158
1159void
1160mac_destroy_socket(struct socket *socket)
1161{
1162
1163 mac_destroy_socket_label(&socket->so_label);
1164 mac_destroy_socket_peer_label(&socket->so_peerlabel);
1165}
1166
1167void
1168mac_destroy_vnode_label(struct label *label)
1169{
1170
1171 MAC_PERFORM(destroy_vnode_label, label);
1172 mac_destroy_label(label);
1112}
1113
1114static void
1115mac_destroy_socket_peer_label(struct label *label)
1116{
1117
1118 MAC_PERFORM(destroy_socket_peer_label, label);
1119 mac_destroy_label(label);
1120}
1121
1122void
1123mac_destroy_socket(struct socket *socket)
1124{
1125
1126 mac_destroy_socket_label(&socket->so_label);
1127 mac_destroy_socket_peer_label(&socket->so_peerlabel);
1128}
1129
1130void
1131mac_destroy_vnode_label(struct label *label)
1132{
1133
1134 MAC_PERFORM(destroy_vnode_label, label);
1135 mac_destroy_label(label);
1173#ifdef MAC_DEBUG
1174 atomic_subtract_int(&nmacvnodes, 1);
1175#endif
1136 MAC_DEBUG_COUNTER_DEC(&nmacvnodes);
1176}
1177
1178void
1179mac_destroy_vnode(struct vnode *vp)
1180{
1181
1182 mac_destroy_vnode_label(&vp->v_label);
1183}
1184
1185void
1186mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1187{
1188 struct label *src_label, *dest_label;
1189
1190 src_label = (struct label *)(src+1);
1191 dest_label = (struct label *)(dest+1);
1192
1193 /*
1194 * mac_init_mbuf_tag() is called on the target tag in
1195 * m_tag_copy(), so we don't need to call it here.
1196 */
1197 MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1198}
1199
1200static void
1201mac_copy_pipe_label(struct label *src, struct label *dest)
1202{
1203
1204 MAC_PERFORM(copy_pipe_label, src, dest);
1205}
1206
1207void
1208mac_copy_vnode_label(struct label *src, struct label *dest)
1209{
1210
1211 MAC_PERFORM(copy_vnode_label, src, dest);
1212}
1213
1214static int
1215mac_check_structmac_consistent(struct mac *mac)
1216{
1217
1218 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1219 return (EINVAL);
1220
1221 return (0);
1222}
1223
1224static int
1225mac_externalize_cred_label(struct label *label, char *elements,
1226 char *outbuf, size_t outbuflen, int flags)
1227{
1228 int error;
1229
1230 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1231
1232 return (error);
1233}
1234
1235static int
1236mac_externalize_ifnet_label(struct label *label, char *elements,
1237 char *outbuf, size_t outbuflen, int flags)
1238{
1239 int error;
1240
1241 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1242
1243 return (error);
1244}
1245
1246static int
1247mac_externalize_pipe_label(struct label *label, char *elements,
1248 char *outbuf, size_t outbuflen, int flags)
1249{
1250 int error;
1251
1252 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1253
1254 return (error);
1255}
1256
1257static int
1258mac_externalize_socket_label(struct label *label, char *elements,
1259 char *outbuf, size_t outbuflen, int flags)
1260{
1261 int error;
1262
1263 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1264
1265 return (error);
1266}
1267
1268static int
1269mac_externalize_socket_peer_label(struct label *label, char *elements,
1270 char *outbuf, size_t outbuflen, int flags)
1271{
1272 int error;
1273
1274 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1275
1276 return (error);
1277}
1278
1279static int
1280mac_externalize_vnode_label(struct label *label, char *elements,
1281 char *outbuf, size_t outbuflen, int flags)
1282{
1283 int error;
1284
1285 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1286
1287 return (error);
1288}
1289
1290static int
1291mac_internalize_cred_label(struct label *label, char *string)
1292{
1293 int error;
1294
1295 MAC_INTERNALIZE(cred_label, label, string);
1296
1297 return (error);
1298}
1299
1300static int
1301mac_internalize_ifnet_label(struct label *label, char *string)
1302{
1303 int error;
1304
1305 MAC_INTERNALIZE(ifnet_label, label, string);
1306
1307 return (error);
1308}
1309
1310static int
1311mac_internalize_pipe_label(struct label *label, char *string)
1312{
1313 int error;
1314
1315 MAC_INTERNALIZE(pipe_label, label, string);
1316
1317 return (error);
1318}
1319
1320static int
1321mac_internalize_socket_label(struct label *label, char *string)
1322{
1323 int error;
1324
1325 MAC_INTERNALIZE(socket_label, label, string);
1326
1327 return (error);
1328}
1329
1330static int
1331mac_internalize_vnode_label(struct label *label, char *string)
1332{
1333 int error;
1334
1335 MAC_INTERNALIZE(vnode_label, label, string);
1336
1337 return (error);
1338}
1339
1340/*
1341 * Initialize MAC label for the first kernel process, from which other
1342 * kernel processes and threads are spawned.
1343 */
1344void
1345mac_create_proc0(struct ucred *cred)
1346{
1347
1348 MAC_PERFORM(create_proc0, cred);
1349}
1350
1351/*
1352 * Initialize MAC label for the first userland process, from which other
1353 * userland processes and threads are spawned.
1354 */
1355void
1356mac_create_proc1(struct ucred *cred)
1357{
1358
1359 MAC_PERFORM(create_proc1, cred);
1360}
1361
1362void
1363mac_thread_userret(struct thread *td)
1364{
1365
1366 MAC_PERFORM(thread_userret, td);
1367}
1368
1369/*
1370 * When a new process is created, its label must be initialized. Generally,
1371 * this involves inheritence from the parent process, modulo possible
1372 * deltas. This function allows that processing to take place.
1373 */
1374void
1375mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1376{
1377
1378 MAC_PERFORM(create_cred, parent_cred, child_cred);
1379}
1380
1381void
1382mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1383 struct vnode *vp)
1384{
1385
1386 MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1387 &vp->v_label);
1388}
1389
1390void
1391mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1392 struct vnode *vp)
1393{
1394
1395 MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1396 &de->de_label, vp, &vp->v_label);
1397}
1398
1399int
1400mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1401{
1402 int error;
1403
1404 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1405
1406 MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1407 &vp->v_label);
1408
1409 return (error);
1410}
1411
1412void
1413mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1414{
1415
1416 MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1417 &vp->v_label);
1418}
1419
1420int
1421mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1422 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1423{
1424 int error;
1425
1426 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1427 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1428
1429 error = VOP_OPENEXTATTR(vp, cred, curthread);
1430 if (error == EOPNOTSUPP) {
1431 /* XXX: Optionally abort if transactions not supported. */
1432 if (ea_warn_once == 0) {
1433 printf("Warning: transactions not supported "
1434 "in EA write.\n");
1435 ea_warn_once = 1;
1436 }
1437 } else if (error)
1438 return (error);
1439
1440 MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1441 dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1442
1443 if (error) {
1444 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1445 return (error);
1446 }
1447
1448 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1449
1450 if (error == EOPNOTSUPP)
1451 error = 0; /* XXX */
1452
1453 return (error);
1454}
1455
1456static int
1457mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1458 struct label *intlabel)
1459{
1460 int error;
1461
1462 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1463
1464 error = VOP_OPENEXTATTR(vp, cred, curthread);
1465 if (error == EOPNOTSUPP) {
1466 /* XXX: Optionally abort if transactions not supported. */
1467 if (ea_warn_once == 0) {
1468 printf("Warning: transactions not supported "
1469 "in EA write.\n");
1470 ea_warn_once = 1;
1471 }
1472 } else if (error)
1473 return (error);
1474
1475 MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1476
1477 if (error) {
1478 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1479 return (error);
1480 }
1481
1482 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1483
1484 if (error == EOPNOTSUPP)
1485 error = 0; /* XXX */
1486
1487 return (error);
1488}
1489
1490int
1491mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1492 struct label *execlabelstorage)
1493{
1494 struct mac mac;
1495 char *buffer;
1496 int error;
1497
1498 if (mac_p == NULL)
1499 return (0);
1500
1501 error = copyin(mac_p, &mac, sizeof(mac));
1502 if (error)
1503 return (error);
1504
1505 error = mac_check_structmac_consistent(&mac);
1506 if (error)
1507 return (error);
1508
1509 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1510 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1511 if (error) {
1512 free(buffer, M_MACTEMP);
1513 return (error);
1514 }
1515
1516 mac_init_cred_label(execlabelstorage);
1517 error = mac_internalize_cred_label(execlabelstorage, buffer);
1518 free(buffer, M_MACTEMP);
1519 if (error) {
1520 mac_destroy_cred_label(execlabelstorage);
1521 return (error);
1522 }
1523 imgp->execlabel = execlabelstorage;
1524 return (0);
1525}
1526
1527void
1528mac_execve_exit(struct image_params *imgp)
1529{
1530 if (imgp->execlabel != NULL)
1531 mac_destroy_cred_label(imgp->execlabel);
1532}
1533
1534void
1535mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1536 struct label *interpvnodelabel, struct image_params *imgp)
1537{
1538
1539 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1540
1541 if (!mac_enforce_process && !mac_enforce_fs)
1542 return;
1543
1544 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1545 interpvnodelabel, imgp, imgp->execlabel);
1546}
1547
1548int
1549mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1550 struct label *interpvnodelabel, struct image_params *imgp)
1551{
1552 int result;
1553
1554 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1555
1556 if (!mac_enforce_process && !mac_enforce_fs)
1557 return (0);
1558
1559 result = 0;
1560 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1561 interpvnodelabel, imgp, imgp->execlabel);
1562
1563 return (result);
1564}
1565
1566int
1567mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1568{
1569 int error;
1570
1571 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1572
1573 if (!mac_enforce_fs)
1574 return (0);
1575
1576 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1577 return (error);
1578}
1579
1580int
1581mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1582{
1583 int error;
1584
1585 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1586
1587 if (!mac_enforce_fs)
1588 return (0);
1589
1590 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1591 return (error);
1592}
1593
1594int
1595mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1596{
1597 int error;
1598
1599 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1600
1601 if (!mac_enforce_fs)
1602 return (0);
1603
1604 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1605 return (error);
1606}
1607
1608int
1609mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1610 struct componentname *cnp, struct vattr *vap)
1611{
1612 int error;
1613
1614 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1615
1616 if (!mac_enforce_fs)
1617 return (0);
1618
1619 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1620 return (error);
1621}
1622
1623int
1624mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1625 struct componentname *cnp)
1626{
1627 int error;
1628
1629 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1630 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1631
1632 if (!mac_enforce_fs)
1633 return (0);
1634
1635 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1636 &vp->v_label, cnp);
1637 return (error);
1638}
1639
1640int
1641mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1642 acl_type_t type)
1643{
1644 int error;
1645
1646 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1647
1648 if (!mac_enforce_fs)
1649 return (0);
1650
1651 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1652 return (error);
1653}
1654
1655int
1656mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1657 struct image_params *imgp)
1658{
1659 int error;
1660
1661 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1662
1663 if (!mac_enforce_process && !mac_enforce_fs)
1664 return (0);
1665
1666 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1667 imgp->execlabel);
1668
1669 return (error);
1670}
1671
1672int
1673mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1674{
1675 int error;
1676
1677 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1678
1679 if (!mac_enforce_fs)
1680 return (0);
1681
1682 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1683 return (error);
1684}
1685
1686int
1687mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1688 int attrnamespace, const char *name, struct uio *uio)
1689{
1690 int error;
1691
1692 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1693
1694 if (!mac_enforce_fs)
1695 return (0);
1696
1697 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1698 attrnamespace, name, uio);
1699 return (error);
1700}
1701
1702int
1703mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1704 struct vnode *vp, struct componentname *cnp)
1705{
1706 int error;
1707
1708 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1709 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1710
1711 if (!mac_enforce_fs)
1712 return (0);
1713
1714 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1715 &vp->v_label, cnp);
1716 return (error);
1717}
1718
1719int
1720mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1721 struct componentname *cnp)
1722{
1723 int error;
1724
1725 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1726
1727 if (!mac_enforce_fs)
1728 return (0);
1729
1730 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1731 return (error);
1732}
1733
1734int
1735mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1736{
1737 int error;
1738
1739 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1740
1741 if (!mac_enforce_fs || !mac_enforce_vm)
1742 return (0);
1743
1744 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1745 return (error);
1746}
1747
1748void
1749mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1750{
1751 int result = *prot;
1752
1753 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1754
1755 if (!mac_enforce_fs || !mac_enforce_vm)
1756 return;
1757
1758 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1759 &result);
1760
1761 *prot = result;
1762}
1763
1764int
1765mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1766{
1767 int error;
1768
1769 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1770
1771 if (!mac_enforce_fs || !mac_enforce_vm)
1772 return (0);
1773
1774 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1775 return (error);
1776}
1777
1778int
1779mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1780{
1781 int error;
1782
1783 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1784
1785 if (!mac_enforce_fs)
1786 return (0);
1787
1788 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1789 return (error);
1790}
1791
1792int
1793mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1794 struct vnode *vp)
1795{
1796 int error;
1797
1798 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1799
1800 if (!mac_enforce_fs)
1801 return (0);
1802
1803 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1804 &vp->v_label);
1805
1806 return (error);
1807}
1808
1809int
1810mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1811 struct vnode *vp)
1812{
1813 int error;
1814
1815 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1816
1817 if (!mac_enforce_fs)
1818 return (0);
1819
1820 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1821 &vp->v_label);
1822
1823 return (error);
1824}
1825
1826int
1827mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1828{
1829 int error;
1830
1831 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1832
1833 if (!mac_enforce_fs)
1834 return (0);
1835
1836 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1837 return (error);
1838}
1839
1840int
1841mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1842{
1843 int error;
1844
1845 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1846
1847 if (!mac_enforce_fs)
1848 return (0);
1849
1850 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1851 return (error);
1852}
1853
1854static int
1855mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1856 struct label *newlabel)
1857{
1858 int error;
1859
1860 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1861
1862 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1863
1864 return (error);
1865}
1866
1867int
1868mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1869 struct vnode *vp, struct componentname *cnp)
1870{
1871 int error;
1872
1873 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1874 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1875
1876 if (!mac_enforce_fs)
1877 return (0);
1878
1879 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1880 &vp->v_label, cnp);
1881 return (error);
1882}
1883
1884int
1885mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1886 struct vnode *vp, int samedir, struct componentname *cnp)
1887{
1888 int error;
1889
1890 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1891 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1892
1893 if (!mac_enforce_fs)
1894 return (0);
1895
1896 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1897 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1898 return (error);
1899}
1900
1901int
1902mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1903{
1904 int error;
1905
1906 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1907
1908 if (!mac_enforce_fs)
1909 return (0);
1910
1911 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1912 return (error);
1913}
1914
1915int
1916mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1917 struct acl *acl)
1918{
1919 int error;
1920
1921 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1922
1923 if (!mac_enforce_fs)
1924 return (0);
1925
1926 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1927 return (error);
1928}
1929
1930int
1931mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1932 int attrnamespace, const char *name, struct uio *uio)
1933{
1934 int error;
1935
1936 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1937
1938 if (!mac_enforce_fs)
1939 return (0);
1940
1941 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1942 attrnamespace, name, uio);
1943 return (error);
1944}
1945
1946int
1947mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1948{
1949 int error;
1950
1951 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1952
1953 if (!mac_enforce_fs)
1954 return (0);
1955
1956 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1957 return (error);
1958}
1959
1960int
1961mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1962{
1963 int error;
1964
1965 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1966
1967 if (!mac_enforce_fs)
1968 return (0);
1969
1970 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1971 return (error);
1972}
1973
1974int
1975mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1976 gid_t gid)
1977{
1978 int error;
1979
1980 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1981
1982 if (!mac_enforce_fs)
1983 return (0);
1984
1985 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1986 return (error);
1987}
1988
1989int
1990mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1991 struct timespec atime, struct timespec mtime)
1992{
1993 int error;
1994
1995 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1996
1997 if (!mac_enforce_fs)
1998 return (0);
1999
2000 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2001 mtime);
2002 return (error);
2003}
2004
2005int
2006mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2007 struct vnode *vp)
2008{
2009 int error;
2010
2011 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2012
2013 if (!mac_enforce_fs)
2014 return (0);
2015
2016 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2017 &vp->v_label);
2018 return (error);
2019}
2020
2021int
2022mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2023 struct vnode *vp)
2024{
2025 int error;
2026
2027 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2028
2029 if (!mac_enforce_fs)
2030 return (0);
2031
2032 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2033 &vp->v_label);
2034
2035 return (error);
2036}
2037
2038/*
2039 * When relabeling a process, call out to the policies for the maximum
2040 * permission allowed for each object type we know about in its
2041 * memory space, and revoke access (in the least surprising ways we
2042 * know) when necessary. The process lock is not held here.
2043 */
2044void
2045mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2046{
2047
2048 /* XXX freeze all other threads */
2049 mac_cred_mmapped_drop_perms_recurse(td, cred,
2050 &td->td_proc->p_vmspace->vm_map);
2051 /* XXX allow other threads to continue */
2052}
2053
2054static __inline const char *
2055prot2str(vm_prot_t prot)
2056{
2057
2058 switch (prot & VM_PROT_ALL) {
2059 case VM_PROT_READ:
2060 return ("r--");
2061 case VM_PROT_READ | VM_PROT_WRITE:
2062 return ("rw-");
2063 case VM_PROT_READ | VM_PROT_EXECUTE:
2064 return ("r-x");
2065 case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2066 return ("rwx");
2067 case VM_PROT_WRITE:
2068 return ("-w-");
2069 case VM_PROT_EXECUTE:
2070 return ("--x");
2071 case VM_PROT_WRITE | VM_PROT_EXECUTE:
2072 return ("-wx");
2073 default:
2074 return ("---");
2075 }
2076}
2077
2078static void
2079mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2080 struct vm_map *map)
2081{
2082 struct vm_map_entry *vme;
2083 int result;
2084 vm_prot_t revokeperms;
2085 vm_object_t object;
2086 vm_ooffset_t offset;
2087 struct vnode *vp;
2088
2089 if (!mac_mmap_revocation)
2090 return;
2091
2092 vm_map_lock_read(map);
2093 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2094 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2095 mac_cred_mmapped_drop_perms_recurse(td, cred,
2096 vme->object.sub_map);
2097 continue;
2098 }
2099 /*
2100 * Skip over entries that obviously are not shared.
2101 */
2102 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2103 !vme->max_protection)
2104 continue;
2105 /*
2106 * Drill down to the deepest backing object.
2107 */
2108 offset = vme->offset;
2109 object = vme->object.vm_object;
2110 if (object == NULL)
2111 continue;
2112 while (object->backing_object != NULL) {
2113 object = object->backing_object;
2114 offset += object->backing_object_offset;
2115 }
2116 /*
2117 * At the moment, vm_maps and objects aren't considered
2118 * by the MAC system, so only things with backing by a
2119 * normal object (read: vnodes) are checked.
2120 */
2121 if (object->type != OBJT_VNODE)
2122 continue;
2123 vp = (struct vnode *)object->handle;
2124 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2125 result = vme->max_protection;
2126 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2127 VOP_UNLOCK(vp, 0, td);
2128 /*
2129 * Find out what maximum protection we may be allowing
2130 * now but a policy needs to get removed.
2131 */
2132 revokeperms = vme->max_protection & ~result;
2133 if (!revokeperms)
2134 continue;
2135 printf("pid %ld: revoking %s perms from %#lx:%ld "
2136 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2137 prot2str(revokeperms), (u_long)vme->start,
2138 (long)(vme->end - vme->start),
2139 prot2str(vme->max_protection), prot2str(vme->protection));
2140 vm_map_lock_upgrade(map);
2141 /*
2142 * This is the really simple case: if a map has more
2143 * max_protection than is allowed, but it's not being
2144 * actually used (that is, the current protection is
2145 * still allowed), we can just wipe it out and do
2146 * nothing more.
2147 */
2148 if ((vme->protection & revokeperms) == 0) {
2149 vme->max_protection -= revokeperms;
2150 } else {
2151 if (revokeperms & VM_PROT_WRITE) {
2152 /*
2153 * In the more complicated case, flush out all
2154 * pending changes to the object then turn it
2155 * copy-on-write.
2156 */
2157 vm_object_reference(object);
2158 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2159 VM_OBJECT_LOCK(object);
2160 vm_object_page_clean(object,
2161 OFF_TO_IDX(offset),
2162 OFF_TO_IDX(offset + vme->end - vme->start +
2163 PAGE_MASK),
2164 OBJPC_SYNC);
2165 VM_OBJECT_UNLOCK(object);
2166 VOP_UNLOCK(vp, 0, td);
2167 vm_object_deallocate(object);
2168 /*
2169 * Why bother if there's no read permissions
2170 * anymore? For the rest, we need to leave
2171 * the write permissions on for COW, or
2172 * remove them entirely if configured to.
2173 */
2174 if (!mac_mmap_revocation_via_cow) {
2175 vme->max_protection &= ~VM_PROT_WRITE;
2176 vme->protection &= ~VM_PROT_WRITE;
2177 } if ((revokeperms & VM_PROT_READ) == 0)
2178 vme->eflags |= MAP_ENTRY_COW |
2179 MAP_ENTRY_NEEDS_COPY;
2180 }
2181 if (revokeperms & VM_PROT_EXECUTE) {
2182 vme->max_protection &= ~VM_PROT_EXECUTE;
2183 vme->protection &= ~VM_PROT_EXECUTE;
2184 }
2185 if (revokeperms & VM_PROT_READ) {
2186 vme->max_protection = 0;
2187 vme->protection = 0;
2188 }
2189 pmap_protect(map->pmap, vme->start, vme->end,
2190 vme->protection & ~revokeperms);
2191 vm_map_simplify_entry(map, vme);
2192 }
2193 vm_map_lock_downgrade(map);
2194 }
2195 vm_map_unlock_read(map);
2196}
2197
2198/*
2199 * When the subject's label changes, it may require revocation of privilege
2200 * to mapped objects. This can't be done on-the-fly later with a unified
2201 * buffer cache.
2202 */
2203static void
2204mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2205{
2206
2207 MAC_PERFORM(relabel_cred, cred, newlabel);
2208}
2209
2210void
2211mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2212{
2213
2214 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2215}
2216
2217void
2218mac_create_ifnet(struct ifnet *ifnet)
2219{
2220
2221 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2222}
2223
2224void
2225mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2226{
2227
2228 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2229}
2230
2231void
2232mac_create_socket(struct ucred *cred, struct socket *socket)
2233{
2234
2235 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2236}
2237
2238void
2239mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2240{
2241
2242 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2243}
2244
2245void
2246mac_create_socket_from_socket(struct socket *oldsocket,
2247 struct socket *newsocket)
2248{
2249
2250 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2251 newsocket, &newsocket->so_label);
2252}
2253
2254static void
2255mac_relabel_socket(struct ucred *cred, struct socket *socket,
2256 struct label *newlabel)
2257{
2258
2259 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2260}
2261
2262static void
2263mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2264{
2265
2266 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2267}
2268
2269void
2270mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2271{
2272 struct label *label;
2273
2274 label = mbuf_to_label(mbuf);
2275
2276 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2277 &socket->so_peerlabel);
2278}
2279
2280void
2281mac_set_socket_peer_from_socket(struct socket *oldsocket,
2282 struct socket *newsocket)
2283{
2284
2285 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2286 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2287}
2288
2289void
2290mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2291{
2292 struct label *label;
2293
2294 label = mbuf_to_label(datagram);
2295
2296 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2297 datagram, label);
2298}
2299
2300void
2301mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2302{
2303 struct label *datagramlabel, *fragmentlabel;
2304
2305 datagramlabel = mbuf_to_label(datagram);
2306 fragmentlabel = mbuf_to_label(fragment);
2307
2308 MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2309 fragmentlabel);
2310}
2311
2312void
2313mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2314{
2315 struct label *label;
2316
2317 label = mbuf_to_label(fragment);
2318
2319 MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2320}
2321
2322void
2323mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2324{
2325 struct label *oldmbuflabel, *newmbuflabel;
2326
2327 oldmbuflabel = mbuf_to_label(oldmbuf);
2328 newmbuflabel = mbuf_to_label(newmbuf);
2329
2330 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2331 newmbuflabel);
2332}
2333
2334void
2335mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2336{
2337 struct label *label;
2338
2339 label = mbuf_to_label(mbuf);
2340
2341 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2342 label);
2343}
2344
2345void
2346mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2347{
2348 struct label *label;
2349
2350 label = mbuf_to_label(mbuf);
2351
2352 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2353 label);
2354}
2355
2356void
2357mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2358{
2359 struct label *label;
2360
2361 label = mbuf_to_label(mbuf);
2362
2363 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2364 label);
2365}
2366
2367void
2368mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2369 struct mbuf *newmbuf)
2370{
2371 struct label *oldmbuflabel, *newmbuflabel;
2372
2373 oldmbuflabel = mbuf_to_label(oldmbuf);
2374 newmbuflabel = mbuf_to_label(newmbuf);
2375
2376 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2377 ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2378}
2379
2380void
2381mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2382{
2383 struct label *oldmbuflabel, *newmbuflabel;
2384
2385 oldmbuflabel = mbuf_to_label(oldmbuf);
2386 newmbuflabel = mbuf_to_label(newmbuf);
2387
2388 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2389 newmbuflabel);
2390}
2391
2392int
2393mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2394{
2395 struct label *label;
2396 int result;
2397
2398 label = mbuf_to_label(fragment);
2399
2400 result = 1;
2401 MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2402 &ipq->ipq_label);
2403
2404 return (result);
2405}
2406
2407void
2408mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2409{
2410 struct label *label;
2411
2412 label = mbuf_to_label(fragment);
2413
2414 MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2415}
2416
2417void
2418mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2419{
2420 struct label *label;
2421
2422 label = mbuf_to_label(mbuf);
2423
2424 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2425 label);
2426}
2427
2428void
2429mac_create_mount(struct ucred *cred, struct mount *mp)
2430{
2431
2432 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2433 &mp->mnt_fslabel);
2434}
2435
2436void
2437mac_create_root_mount(struct ucred *cred, struct mount *mp)
2438{
2439
2440 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2441 &mp->mnt_fslabel);
2442}
2443
2444int
2445mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2446{
2447 int error;
2448
2449 if (!mac_enforce_network)
2450 return (0);
2451
2452 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2453 &ifnet->if_label);
2454
2455 return (error);
2456}
2457
2458static int
2459mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2460{
2461 int error;
2462
2463 MAC_CHECK(check_cred_relabel, cred, newlabel);
2464
2465 return (error);
2466}
2467
2468int
2469mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2470{
2471 int error;
2472
2473 if (!mac_enforce_process)
2474 return (0);
2475
2476 MAC_CHECK(check_cred_visible, u1, u2);
2477
2478 return (error);
2479}
2480
2481int
2482mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2483{
2484 struct label *label;
2485 int error;
2486
2487 M_ASSERTPKTHDR(mbuf);
2488
2489 if (!mac_enforce_network)
2490 return (0);
2491
2492 label = mbuf_to_label(mbuf);
2493
2494 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2495 label);
2496
2497 return (error);
2498}
2499
2500int
2501mac_check_kenv_dump(struct ucred *cred)
2502{
2503 int error;
2504
2505 if (!mac_enforce_system)
2506 return (0);
2507
2508 MAC_CHECK(check_kenv_dump, cred);
2509
2510 return (error);
2511}
2512
2513int
2514mac_check_kenv_get(struct ucred *cred, char *name)
2515{
2516 int error;
2517
2518 if (!mac_enforce_system)
2519 return (0);
2520
2521 MAC_CHECK(check_kenv_get, cred, name);
2522
2523 return (error);
2524}
2525
2526int
2527mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2528{
2529 int error;
2530
2531 if (!mac_enforce_system)
2532 return (0);
2533
2534 MAC_CHECK(check_kenv_set, cred, name, value);
2535
2536 return (error);
2537}
2538
2539int
2540mac_check_kenv_unset(struct ucred *cred, char *name)
2541{
2542 int error;
2543
2544 if (!mac_enforce_system)
2545 return (0);
2546
2547 MAC_CHECK(check_kenv_unset, cred, name);
2548
2549 return (error);
2550}
2551
2552int
2553mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2554{
2555 int error;
2556
2557 ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2558
2559 if (!mac_enforce_kld)
2560 return (0);
2561
2562 MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2563
2564 return (error);
2565}
2566
2567int
2568mac_check_kld_stat(struct ucred *cred)
2569{
2570 int error;
2571
2572 if (!mac_enforce_kld)
2573 return (0);
2574
2575 MAC_CHECK(check_kld_stat, cred);
2576
2577 return (error);
2578}
2579
2580int
2581mac_check_kld_unload(struct ucred *cred)
2582{
2583 int error;
2584
2585 if (!mac_enforce_kld)
2586 return (0);
2587
2588 MAC_CHECK(check_kld_unload, cred);
2589
2590 return (error);
2591}
2592
2593int
2594mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2595{
2596 int error;
2597
2598 if (!mac_enforce_fs)
2599 return (0);
2600
2601 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2602
2603 return (error);
2604}
2605
2606int
2607mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2608 void *data)
2609{
2610 int error;
2611
2612 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2613
2614 if (!mac_enforce_pipe)
2615 return (0);
2616
2617 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2618
2619 return (error);
2620}
2621
2622int
2623mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2624{
2625 int error;
2626
2627 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2628
2629 if (!mac_enforce_pipe)
2630 return (0);
2631
2632 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2633
2634 return (error);
2635}
2636
2637int
2638mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2639{
2640 int error;
2641
2642 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2643
2644 if (!mac_enforce_pipe)
2645 return (0);
2646
2647 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2648
2649 return (error);
2650}
2651
2652static int
2653mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2654 struct label *newlabel)
2655{
2656 int error;
2657
2658 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2659
2660 if (!mac_enforce_pipe)
2661 return (0);
2662
2663 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2664
2665 return (error);
2666}
2667
2668int
2669mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2670{
2671 int error;
2672
2673 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2674
2675 if (!mac_enforce_pipe)
2676 return (0);
2677
2678 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2679
2680 return (error);
2681}
2682
2683int
2684mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2685{
2686 int error;
2687
2688 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2689
2690 if (!mac_enforce_pipe)
2691 return (0);
2692
2693 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2694
2695 return (error);
2696}
2697
2698int
2699mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2700{
2701 int error;
2702
2703 PROC_LOCK_ASSERT(proc, MA_OWNED);
2704
2705 if (!mac_enforce_process)
2706 return (0);
2707
2708 MAC_CHECK(check_proc_debug, cred, proc);
2709
2710 return (error);
2711}
2712
2713int
2714mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2715{
2716 int error;
2717
2718 PROC_LOCK_ASSERT(proc, MA_OWNED);
2719
2720 if (!mac_enforce_process)
2721 return (0);
2722
2723 MAC_CHECK(check_proc_sched, cred, proc);
2724
2725 return (error);
2726}
2727
2728int
2729mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2730{
2731 int error;
2732
2733 PROC_LOCK_ASSERT(proc, MA_OWNED);
2734
2735 if (!mac_enforce_process)
2736 return (0);
2737
2738 MAC_CHECK(check_proc_signal, cred, proc, signum);
2739
2740 return (error);
2741}
2742
2743int
2744mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2745 struct sockaddr *sockaddr)
2746{
2747 int error;
2748
2749 if (!mac_enforce_socket)
2750 return (0);
2751
2752 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2753 sockaddr);
2754
2755 return (error);
2756}
2757
2758int
2759mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2760 struct sockaddr *sockaddr)
2761{
2762 int error;
2763
2764 if (!mac_enforce_socket)
2765 return (0);
2766
2767 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2768 sockaddr);
2769
2770 return (error);
2771}
2772
2773int
2774mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2775{
2776 struct label *label;
2777 int error;
2778
2779 if (!mac_enforce_socket)
2780 return (0);
2781
2782 label = mbuf_to_label(mbuf);
2783
2784 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2785 label);
2786
2787 return (error);
2788}
2789
2790int
2791mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2792{
2793 int error;
2794
2795 if (!mac_enforce_socket)
2796 return (0);
2797
2798 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2799 return (error);
2800}
2801
2802int
2803mac_check_socket_receive(struct ucred *cred, struct socket *so)
2804{
2805 int error;
2806
2807 if (!mac_enforce_socket)
2808 return (0);
2809
2810 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2811
2812 return (error);
2813}
2814
2815static int
2816mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2817 struct label *newlabel)
2818{
2819 int error;
2820
2821 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2822 newlabel);
2823
2824 return (error);
2825}
2826
2827int
2828mac_check_socket_send(struct ucred *cred, struct socket *so)
2829{
2830 int error;
2831
2832 if (!mac_enforce_socket)
2833 return (0);
2834
2835 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2836
2837 return (error);
2838}
2839
2840int
2841mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2842{
2843 int error;
2844
2845 if (!mac_enforce_socket)
2846 return (0);
2847
2848 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2849
2850 return (error);
2851}
2852
2853int
2854mac_check_sysarch_ioperm(struct ucred *cred)
2855{
2856 int error;
2857
2858 if (!mac_enforce_system)
2859 return (0);
2860
2861 MAC_CHECK(check_sysarch_ioperm, cred);
2862 return (error);
2863}
2864
2865int
2866mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2867{
2868 int error;
2869
2870 if (vp != NULL) {
2871 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2872 }
2873
2874 if (!mac_enforce_system)
2875 return (0);
2876
2877 MAC_CHECK(check_system_acct, cred, vp,
2878 vp != NULL ? &vp->v_label : NULL);
2879
2880 return (error);
2881}
2882
2883int
2884mac_check_system_nfsd(struct ucred *cred)
2885{
2886 int error;
2887
2888 if (!mac_enforce_system)
2889 return (0);
2890
2891 MAC_CHECK(check_system_nfsd, cred);
2892
2893 return (error);
2894}
2895
2896int
2897mac_check_system_reboot(struct ucred *cred, int howto)
2898{
2899 int error;
2900
2901 if (!mac_enforce_system)
2902 return (0);
2903
2904 MAC_CHECK(check_system_reboot, cred, howto);
2905
2906 return (error);
2907}
2908
2909int
2910mac_check_system_settime(struct ucred *cred)
2911{
2912 int error;
2913
2914 if (!mac_enforce_system)
2915 return (0);
2916
2917 MAC_CHECK(check_system_settime, cred);
2918
2919 return (error);
2920}
2921
2922int
2923mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2924{
2925 int error;
2926
2927 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2928
2929 if (!mac_enforce_system)
2930 return (0);
2931
2932 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2933 return (error);
2934}
2935
2936int
2937mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2938{
2939 int error;
2940
2941 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2942
2943 if (!mac_enforce_system)
2944 return (0);
2945
2946 MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2947 return (error);
2948}
2949
2950int
2951mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2952 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2953{
2954 int error;
2955
2956 /*
2957 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2958 * but since it's not exported from kern_sysctl.c, we can't.
2959 */
2960 if (!mac_enforce_system)
2961 return (0);
2962
2963 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2964 inkernel, new, newlen);
2965
2966 return (error);
2967}
2968
2969int
2970mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2971 struct ifnet *ifnet)
2972{
2973 char *elements, *buffer;
2974 struct mac mac;
2975 int error;
2976
2977 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2978 if (error)
2979 return (error);
2980
2981 error = mac_check_structmac_consistent(&mac);
2982 if (error)
2983 return (error);
2984
2985 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2986 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2987 if (error) {
2988 free(elements, M_MACTEMP);
2989 return (error);
2990 }
2991
2992 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2993 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2994 buffer, mac.m_buflen, M_WAITOK);
2995 if (error == 0)
2996 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2997
2998 free(buffer, M_MACTEMP);
2999 free(elements, M_MACTEMP);
3000
3001 return (error);
3002}
3003
3004int
3005mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
3006 struct ifnet *ifnet)
3007{
3008 struct label intlabel;
3009 struct mac mac;
3010 char *buffer;
3011 int error;
3012
3013 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
3014 if (error)
3015 return (error);
3016
3017 error = mac_check_structmac_consistent(&mac);
3018 if (error)
3019 return (error);
3020
3021 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3022 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3023 if (error) {
3024 free(buffer, M_MACTEMP);
3025 return (error);
3026 }
3027
3028 mac_init_ifnet_label(&intlabel);
3029 error = mac_internalize_ifnet_label(&intlabel, buffer);
3030 free(buffer, M_MACTEMP);
3031 if (error) {
3032 mac_destroy_ifnet_label(&intlabel);
3033 return (error);
3034 }
3035
3036 /*
3037 * XXX: Note that this is a redundant privilege check, since
3038 * policies impose this check themselves if required by the
3039 * policy. Eventually, this should go away.
3040 */
3041 error = suser_cred(cred, 0);
3042 if (error) {
3043 mac_destroy_ifnet_label(&intlabel);
3044 return (error);
3045 }
3046
3047 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3048 &intlabel);
3049 if (error) {
3050 mac_destroy_ifnet_label(&intlabel);
3051 return (error);
3052 }
3053
3054 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3055
3056 mac_destroy_ifnet_label(&intlabel);
3057 return (0);
3058}
3059
3060void
3061mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
3062{
3063
3064 MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3065}
3066
3067void
3068mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3069 struct devfs_dirent *dd, struct devfs_dirent *de)
3070{
3071
3072 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3073 &de->de_label);
3074}
3075
3076void
3077mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3078 struct devfs_dirent *de)
3079{
3080
3081 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3082 &de->de_label);
3083}
3084
3085int
3086mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3087 struct mac *mac)
3088{
3089 struct label intlabel;
3090 char *buffer;
3091 int error;
3092
3093 error = mac_check_structmac_consistent(mac);
3094 if (error)
3095 return (error);
3096
3097 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3098 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3099 if (error) {
3100 free(buffer, M_MACTEMP);
3101 return (error);
3102 }
3103
3104 mac_init_socket_label(&intlabel, M_WAITOK);
3105 error = mac_internalize_socket_label(&intlabel, buffer);
3106 free(buffer, M_MACTEMP);
3107 if (error) {
3108 mac_destroy_socket_label(&intlabel);
3109 return (error);
3110 }
3111
3112 mac_check_socket_relabel(cred, so, &intlabel);
3113 if (error) {
3114 mac_destroy_socket_label(&intlabel);
3115 return (error);
3116 }
3117
3118 mac_relabel_socket(cred, so, &intlabel);
3119
3120 mac_destroy_socket_label(&intlabel);
3121 return (0);
3122}
3123
3124int
3125mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3126{
3127 int error;
3128
3129 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3130
3131 error = mac_check_pipe_relabel(cred, pipe, label);
3132 if (error)
3133 return (error);
3134
3135 mac_relabel_pipe(cred, pipe, label);
3136
3137 return (0);
3138}
3139
3140int
3141mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3142 struct mac *mac)
3143{
3144 char *buffer, *elements;
3145 int error;
3146
3147 error = mac_check_structmac_consistent(mac);
3148 if (error)
3149 return (error);
3150
3151 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3152 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3153 if (error) {
3154 free(elements, M_MACTEMP);
3155 return (error);
3156 }
3157
3158 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3159 error = mac_externalize_socket_label(&so->so_label, elements,
3160 buffer, mac->m_buflen, M_WAITOK);
3161 if (error == 0)
3162 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3163
3164 free(buffer, M_MACTEMP);
3165 free(elements, M_MACTEMP);
3166
3167 return (error);
3168}
3169
3170int
3171mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3172 struct mac *mac)
3173{
3174 char *elements, *buffer;
3175 int error;
3176
3177 error = mac_check_structmac_consistent(mac);
3178 if (error)
3179 return (error);
3180
3181 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3182 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3183 if (error) {
3184 free(elements, M_MACTEMP);
3185 return (error);
3186 }
3187
3188 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3189 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3190 elements, buffer, mac->m_buflen, M_WAITOK);
3191 if (error == 0)
3192 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3193
3194 free(buffer, M_MACTEMP);
3195 free(elements, M_MACTEMP);
3196
3197 return (error);
3198}
3199
3200/*
3201 * Implementation of VOP_SETLABEL() that relies on extended attributes
3202 * to store label data. Can be referenced by filesystems supporting
3203 * extended attributes.
3204 */
3205int
3206vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3207{
3208 struct vnode *vp = ap->a_vp;
3209 struct label *intlabel = ap->a_label;
3210 int error;
3211
3212 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3213
3214 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3215 return (EOPNOTSUPP);
3216
3217 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3218 if (error)
3219 return (error);
3220
3221 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3222
3223 return (0);
3224}
3225
3226static int
3227vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3228{
3229 int error;
3230
3231 if (vp->v_mount == NULL) {
3232 /* printf("vn_setlabel: null v_mount\n"); */
3233 if (vp->v_type != VNON)
3234 printf("vn_setlabel: null v_mount with non-VNON\n");
3235 return (EBADF);
3236 }
3237
3238 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3239 return (EOPNOTSUPP);
3240
3241 /*
3242 * Multi-phase commit. First check the policies to confirm the
3243 * change is OK. Then commit via the filesystem. Finally,
3244 * update the actual vnode label. Question: maybe the filesystem
3245 * should update the vnode at the end as part of VOP_SETLABEL()?
3246 */
3247 error = mac_check_vnode_relabel(cred, vp, intlabel);
3248 if (error)
3249 return (error);
3250
3251 /*
3252 * VADMIN provides the opportunity for the filesystem to make
3253 * decisions about who is and is not able to modify labels
3254 * and protections on files. This might not be right. We can't
3255 * assume VOP_SETLABEL() will do it, because we might implement
3256 * that as part of vop_stdsetlabel_ea().
3257 */
3258 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3259 if (error)
3260 return (error);
3261
3262 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3263 if (error)
3264 return (error);
3265
3266 return (0);
3267}
3268
3269int
3270__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3271{
3272 char *elements, *buffer;
3273 struct mac mac;
3274 struct proc *tproc;
3275 struct ucred *tcred;
3276 int error;
3277
3278 error = copyin(uap->mac_p, &mac, sizeof(mac));
3279 if (error)
3280 return (error);
3281
3282 error = mac_check_structmac_consistent(&mac);
3283 if (error)
3284 return (error);
3285
3286 tproc = pfind(uap->pid);
3287 if (tproc == NULL)
3288 return (ESRCH);
3289
3290 tcred = NULL; /* Satisfy gcc. */
3291 error = p_cansee(td, tproc);
3292 if (error == 0)
3293 tcred = crhold(tproc->p_ucred);
3294 PROC_UNLOCK(tproc);
3295 if (error)
3296 return (error);
3297
3298 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3299 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3300 if (error) {
3301 free(elements, M_MACTEMP);
3302 crfree(tcred);
3303 return (error);
3304 }
3305
3306 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3307 error = mac_externalize_cred_label(&tcred->cr_label, elements,
3308 buffer, mac.m_buflen, M_WAITOK);
3309 if (error == 0)
3310 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3311
3312 free(buffer, M_MACTEMP);
3313 free(elements, M_MACTEMP);
3314 crfree(tcred);
3315 return (error);
3316}
3317
3318/*
3319 * MPSAFE
3320 */
3321int
3322__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3323{
3324 char *elements, *buffer;
3325 struct mac mac;
3326 int error;
3327
3328 error = copyin(uap->mac_p, &mac, sizeof(mac));
3329 if (error)
3330 return (error);
3331
3332 error = mac_check_structmac_consistent(&mac);
3333 if (error)
3334 return (error);
3335
3336 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3337 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3338 if (error) {
3339 free(elements, M_MACTEMP);
3340 return (error);
3341 }
3342
3343 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3344 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3345 elements, buffer, mac.m_buflen, M_WAITOK);
3346 if (error == 0)
3347 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3348
3349 free(buffer, M_MACTEMP);
3350 free(elements, M_MACTEMP);
3351 return (error);
3352}
3353
3354/*
3355 * MPSAFE
3356 */
3357int
3358__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3359{
3360 struct ucred *newcred, *oldcred;
3361 struct label intlabel;
3362 struct proc *p;
3363 struct mac mac;
3364 char *buffer;
3365 int error;
3366
3367 error = copyin(uap->mac_p, &mac, sizeof(mac));
3368 if (error)
3369 return (error);
3370
3371 error = mac_check_structmac_consistent(&mac);
3372 if (error)
3373 return (error);
3374
3375 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3376 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3377 if (error) {
3378 free(buffer, M_MACTEMP);
3379 return (error);
3380 }
3381
3382 mac_init_cred_label(&intlabel);
3383 error = mac_internalize_cred_label(&intlabel, buffer);
3384 free(buffer, M_MACTEMP);
3385 if (error) {
3386 mac_destroy_cred_label(&intlabel);
3387 return (error);
3388 }
3389
3390 newcred = crget();
3391
3392 p = td->td_proc;
3393 PROC_LOCK(p);
3394 oldcred = p->p_ucred;
3395
3396 error = mac_check_cred_relabel(oldcred, &intlabel);
3397 if (error) {
3398 PROC_UNLOCK(p);
3399 crfree(newcred);
3400 goto out;
3401 }
3402
3403 setsugid(p);
3404 crcopy(newcred, oldcred);
3405 mac_relabel_cred(newcred, &intlabel);
3406 p->p_ucred = newcred;
3407
3408 /*
3409 * Grab additional reference for use while revoking mmaps, prior
3410 * to releasing the proc lock and sharing the cred.
3411 */
3412 crhold(newcred);
3413 PROC_UNLOCK(p);
3414
3415 if (mac_enforce_vm) {
3416 mtx_lock(&Giant);
3417 mac_cred_mmapped_drop_perms(td, newcred);
3418 mtx_unlock(&Giant);
3419 }
3420
3421 crfree(newcred); /* Free revocation reference. */
3422 crfree(oldcred);
3423
3424out:
3425 mac_destroy_cred_label(&intlabel);
3426 return (error);
3427}
3428
3429/*
3430 * MPSAFE
3431 */
3432int
3433__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3434{
3435 char *elements, *buffer;
3436 struct label intlabel;
3437 struct file *fp;
3438 struct mac mac;
3439 struct vnode *vp;
3440 struct pipe *pipe;
3441 short label_type;
3442 int error;
3443
3444 error = copyin(uap->mac_p, &mac, sizeof(mac));
3445 if (error)
3446 return (error);
3447
3448 error = mac_check_structmac_consistent(&mac);
3449 if (error)
3450 return (error);
3451
3452 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3453 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3454 if (error) {
3455 free(elements, M_MACTEMP);
3456 return (error);
3457 }
3458
3459 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3460 mtx_lock(&Giant); /* VFS */
3461 error = fget(td, uap->fd, &fp);
3462 if (error)
3463 goto out;
3464
3465 label_type = fp->f_type;
3466 switch (fp->f_type) {
3467 case DTYPE_FIFO:
3468 case DTYPE_VNODE:
3469 vp = fp->f_vnode;
3470
3471 mac_init_vnode_label(&intlabel);
3472
3473 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3474 mac_copy_vnode_label(&vp->v_label, &intlabel);
3475 VOP_UNLOCK(vp, 0, td);
3476
3477 break;
3478 case DTYPE_PIPE:
3479 pipe = fp->f_data;
3480
3481 mac_init_pipe_label(&intlabel);
3482
3483 PIPE_LOCK(pipe);
3484 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3485 PIPE_UNLOCK(pipe);
3486 break;
3487 default:
3488 error = EINVAL;
3489 fdrop(fp, td);
3490 goto out;
3491 }
3492 fdrop(fp, td);
3493
3494 switch (label_type) {
3495 case DTYPE_FIFO:
3496 case DTYPE_VNODE:
3497 if (error == 0)
3498 error = mac_externalize_vnode_label(&intlabel,
3499 elements, buffer, mac.m_buflen, M_WAITOK);
3500 mac_destroy_vnode_label(&intlabel);
3501 break;
3502 case DTYPE_PIPE:
3503 error = mac_externalize_pipe_label(&intlabel, elements,
3504 buffer, mac.m_buflen, M_WAITOK);
3505 mac_destroy_pipe_label(&intlabel);
3506 break;
3507 default:
3508 panic("__mac_get_fd: corrupted label_type");
3509 }
3510
3511 if (error == 0)
3512 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3513
3514out:
3515 mtx_unlock(&Giant); /* VFS */
3516 free(buffer, M_MACTEMP);
3517 free(elements, M_MACTEMP);
3518
3519 return (error);
3520}
3521
3522/*
3523 * MPSAFE
3524 */
3525int
3526__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3527{
3528 char *elements, *buffer;
3529 struct nameidata nd;
3530 struct label intlabel;
3531 struct mac mac;
3532 int error;
3533
3534 error = copyin(uap->mac_p, &mac, sizeof(mac));
3535 if (error)
3536 return (error);
3537
3538 error = mac_check_structmac_consistent(&mac);
3539 if (error)
3540 return (error);
3541
3542 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3543 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3544 if (error) {
3545 free(elements, M_MACTEMP);
3546 return (error);
3547 }
3548
3549 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3550 mtx_lock(&Giant); /* VFS */
3551 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3552 td);
3553 error = namei(&nd);
3554 if (error)
3555 goto out;
3556
3557 mac_init_vnode_label(&intlabel);
3558 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3559 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3560 mac.m_buflen, M_WAITOK);
3561
3562 NDFREE(&nd, 0);
3563 mac_destroy_vnode_label(&intlabel);
3564
3565 if (error == 0)
3566 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3567
3568out:
3569 mtx_unlock(&Giant); /* VFS */
3570
3571 free(buffer, M_MACTEMP);
3572 free(elements, M_MACTEMP);
3573
3574 return (error);
3575}
3576
3577/*
3578 * MPSAFE
3579 */
3580int
3581__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3582{
3583 char *elements, *buffer;
3584 struct nameidata nd;
3585 struct label intlabel;
3586 struct mac mac;
3587 int error;
3588
3589 error = copyin(uap->mac_p, &mac, sizeof(mac));
3590 if (error)
3591 return (error);
3592
3593 error = mac_check_structmac_consistent(&mac);
3594 if (error)
3595 return (error);
3596
3597 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3598 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3599 if (error) {
3600 free(elements, M_MACTEMP);
3601 return (error);
3602 }
3603
3604 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3605 mtx_lock(&Giant); /* VFS */
3606 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3607 td);
3608 error = namei(&nd);
3609 if (error)
3610 goto out;
3611
3612 mac_init_vnode_label(&intlabel);
3613 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3614 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3615 mac.m_buflen, M_WAITOK);
3616 NDFREE(&nd, 0);
3617 mac_destroy_vnode_label(&intlabel);
3618
3619 if (error == 0)
3620 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3621
3622out:
3623 mtx_unlock(&Giant); /* VFS */
3624
3625 free(buffer, M_MACTEMP);
3626 free(elements, M_MACTEMP);
3627
3628 return (error);
3629}
3630
3631/*
3632 * MPSAFE
3633 */
3634int
3635__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3636{
3637 struct label intlabel;
3638 struct pipe *pipe;
3639 struct file *fp;
3640 struct mount *mp;
3641 struct vnode *vp;
3642 struct mac mac;
3643 char *buffer;
3644 int error;
3645
3646 error = copyin(uap->mac_p, &mac, sizeof(mac));
3647 if (error)
3648 return (error);
3649
3650 error = mac_check_structmac_consistent(&mac);
3651 if (error)
3652 return (error);
3653
3654 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3655 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3656 if (error) {
3657 free(buffer, M_MACTEMP);
3658 return (error);
3659 }
3660
3661 mtx_lock(&Giant); /* VFS */
3662
3663 error = fget(td, uap->fd, &fp);
3664 if (error)
3665 goto out;
3666
3667 switch (fp->f_type) {
3668 case DTYPE_FIFO:
3669 case DTYPE_VNODE:
3670 mac_init_vnode_label(&intlabel);
3671 error = mac_internalize_vnode_label(&intlabel, buffer);
3672 if (error) {
3673 mac_destroy_vnode_label(&intlabel);
3674 break;
3675 }
3676
3677 vp = fp->f_vnode;
3678 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3679 if (error != 0) {
3680 mac_destroy_vnode_label(&intlabel);
3681 break;
3682 }
3683
3684 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3685 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3686 VOP_UNLOCK(vp, 0, td);
3687 vn_finished_write(mp);
3688
3689 mac_destroy_vnode_label(&intlabel);
3690 break;
3691
3692 case DTYPE_PIPE:
3693 mac_init_pipe_label(&intlabel);
3694 error = mac_internalize_pipe_label(&intlabel, buffer);
3695 if (error == 0) {
3696 pipe = fp->f_data;
3697 PIPE_LOCK(pipe);
3698 error = mac_pipe_label_set(td->td_ucred, pipe,
3699 &intlabel);
3700 PIPE_UNLOCK(pipe);
3701 }
3702
3703 mac_destroy_pipe_label(&intlabel);
3704 break;
3705
3706 default:
3707 error = EINVAL;
3708 }
3709
3710 fdrop(fp, td);
3711out:
3712 mtx_unlock(&Giant); /* VFS */
3713
3714 free(buffer, M_MACTEMP);
3715
3716 return (error);
3717}
3718
3719/*
3720 * MPSAFE
3721 */
3722int
3723__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3724{
3725 struct label intlabel;
3726 struct nameidata nd;
3727 struct mount *mp;
3728 struct mac mac;
3729 char *buffer;
3730 int error;
3731
3732 error = copyin(uap->mac_p, &mac, sizeof(mac));
3733 if (error)
3734 return (error);
3735
3736 error = mac_check_structmac_consistent(&mac);
3737 if (error)
3738 return (error);
3739
3740 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3741 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3742 if (error) {
3743 free(buffer, M_MACTEMP);
3744 return (error);
3745 }
3746
3747 mac_init_vnode_label(&intlabel);
3748 error = mac_internalize_vnode_label(&intlabel, buffer);
3749 free(buffer, M_MACTEMP);
3750 if (error) {
3751 mac_destroy_vnode_label(&intlabel);
3752 return (error);
3753 }
3754
3755 mtx_lock(&Giant); /* VFS */
3756
3757 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3758 td);
3759 error = namei(&nd);
3760 if (error == 0) {
3761 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3762 if (error == 0)
3763 error = vn_setlabel(nd.ni_vp, &intlabel,
3764 td->td_ucred);
3765 vn_finished_write(mp);
3766 }
3767
3768 NDFREE(&nd, 0);
3769 mtx_unlock(&Giant); /* VFS */
3770 mac_destroy_vnode_label(&intlabel);
3771
3772 return (error);
3773}
3774
3775/*
3776 * MPSAFE
3777 */
3778int
3779__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3780{
3781 struct label intlabel;
3782 struct nameidata nd;
3783 struct mount *mp;
3784 struct mac mac;
3785 char *buffer;
3786 int error;
3787
3788 error = copyin(uap->mac_p, &mac, sizeof(mac));
3789 if (error)
3790 return (error);
3791
3792 error = mac_check_structmac_consistent(&mac);
3793 if (error)
3794 return (error);
3795
3796 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3797 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3798 if (error) {
3799 free(buffer, M_MACTEMP);
3800 return (error);
3801 }
3802
3803 mac_init_vnode_label(&intlabel);
3804 error = mac_internalize_vnode_label(&intlabel, buffer);
3805 free(buffer, M_MACTEMP);
3806 if (error) {
3807 mac_destroy_vnode_label(&intlabel);
3808 return (error);
3809 }
3810
3811 mtx_lock(&Giant); /* VFS */
3812
3813 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3814 td);
3815 error = namei(&nd);
3816 if (error == 0) {
3817 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3818 if (error == 0)
3819 error = vn_setlabel(nd.ni_vp, &intlabel,
3820 td->td_ucred);
3821 vn_finished_write(mp);
3822 }
3823
3824 NDFREE(&nd, 0);
3825 mtx_unlock(&Giant); /* VFS */
3826 mac_destroy_vnode_label(&intlabel);
3827
3828 return (error);
3829}
3830
3831/*
3832 * MPSAFE
3833 */
3834int
3835mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3836{
3837 struct mac_policy_conf *mpc;
3838 char target[MAC_MAX_POLICY_NAME];
3839 int entrycount, error;
3840
3841 error = copyinstr(uap->policy, target, sizeof(target), NULL);
3842 if (error)
3843 return (error);
3844
3845 error = ENOSYS;
3846 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3847 if (strcmp(mpc->mpc_name, target) == 0 &&
3848 mpc->mpc_ops->mpo_syscall != NULL) {
3849 error = mpc->mpc_ops->mpo_syscall(td,
3850 uap->call, uap->arg);
3851 goto out;
3852 }
3853 }
3854
3855 if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
3856 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3857 if (strcmp(mpc->mpc_name, target) == 0 &&
3858 mpc->mpc_ops->mpo_syscall != NULL) {
3859 error = mpc->mpc_ops->mpo_syscall(td,
3860 uap->call, uap->arg);
3861 break;
3862 }
3863 }
3864 mac_policy_list_unbusy();
3865 }
3866out:
3867 return (error);
3868}
3869
3870SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3871SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3872
3873#else /* !MAC */
3874
3875int
3876__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3877{
3878
3879 return (ENOSYS);
3880}
3881
3882int
3883__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3884{
3885
3886 return (ENOSYS);
3887}
3888
3889int
3890__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3891{
3892
3893 return (ENOSYS);
3894}
3895
3896int
3897__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3898{
3899
3900 return (ENOSYS);
3901}
3902
3903int
3904__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3905{
3906
3907 return (ENOSYS);
3908}
3909
3910int
3911__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3912{
3913
3914 return (ENOSYS);
3915}
3916
3917int
3918__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3919{
3920
3921 return (ENOSYS);
3922}
3923
3924int
3925__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3926{
3927
3928 return (ENOSYS);
3929}
3930
3931int
3932__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3933{
3934
3935 return (ENOSYS);
3936}
3937
3938int
3939mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3940{
3941
3942 return (ENOSYS);
3943}
3944
3945#endif
1137}
1138
1139void
1140mac_destroy_vnode(struct vnode *vp)
1141{
1142
1143 mac_destroy_vnode_label(&vp->v_label);
1144}
1145
1146void
1147mac_copy_mbuf_tag(struct m_tag *src, struct m_tag *dest)
1148{
1149 struct label *src_label, *dest_label;
1150
1151 src_label = (struct label *)(src+1);
1152 dest_label = (struct label *)(dest+1);
1153
1154 /*
1155 * mac_init_mbuf_tag() is called on the target tag in
1156 * m_tag_copy(), so we don't need to call it here.
1157 */
1158 MAC_PERFORM(copy_mbuf_label, src_label, dest_label);
1159}
1160
1161static void
1162mac_copy_pipe_label(struct label *src, struct label *dest)
1163{
1164
1165 MAC_PERFORM(copy_pipe_label, src, dest);
1166}
1167
1168void
1169mac_copy_vnode_label(struct label *src, struct label *dest)
1170{
1171
1172 MAC_PERFORM(copy_vnode_label, src, dest);
1173}
1174
1175static int
1176mac_check_structmac_consistent(struct mac *mac)
1177{
1178
1179 if (mac->m_buflen > MAC_MAX_LABEL_BUF_LEN)
1180 return (EINVAL);
1181
1182 return (0);
1183}
1184
1185static int
1186mac_externalize_cred_label(struct label *label, char *elements,
1187 char *outbuf, size_t outbuflen, int flags)
1188{
1189 int error;
1190
1191 MAC_EXTERNALIZE(cred_label, label, elements, outbuf, outbuflen);
1192
1193 return (error);
1194}
1195
1196static int
1197mac_externalize_ifnet_label(struct label *label, char *elements,
1198 char *outbuf, size_t outbuflen, int flags)
1199{
1200 int error;
1201
1202 MAC_EXTERNALIZE(ifnet_label, label, elements, outbuf, outbuflen);
1203
1204 return (error);
1205}
1206
1207static int
1208mac_externalize_pipe_label(struct label *label, char *elements,
1209 char *outbuf, size_t outbuflen, int flags)
1210{
1211 int error;
1212
1213 MAC_EXTERNALIZE(pipe_label, label, elements, outbuf, outbuflen);
1214
1215 return (error);
1216}
1217
1218static int
1219mac_externalize_socket_label(struct label *label, char *elements,
1220 char *outbuf, size_t outbuflen, int flags)
1221{
1222 int error;
1223
1224 MAC_EXTERNALIZE(socket_label, label, elements, outbuf, outbuflen);
1225
1226 return (error);
1227}
1228
1229static int
1230mac_externalize_socket_peer_label(struct label *label, char *elements,
1231 char *outbuf, size_t outbuflen, int flags)
1232{
1233 int error;
1234
1235 MAC_EXTERNALIZE(socket_peer_label, label, elements, outbuf, outbuflen);
1236
1237 return (error);
1238}
1239
1240static int
1241mac_externalize_vnode_label(struct label *label, char *elements,
1242 char *outbuf, size_t outbuflen, int flags)
1243{
1244 int error;
1245
1246 MAC_EXTERNALIZE(vnode_label, label, elements, outbuf, outbuflen);
1247
1248 return (error);
1249}
1250
1251static int
1252mac_internalize_cred_label(struct label *label, char *string)
1253{
1254 int error;
1255
1256 MAC_INTERNALIZE(cred_label, label, string);
1257
1258 return (error);
1259}
1260
1261static int
1262mac_internalize_ifnet_label(struct label *label, char *string)
1263{
1264 int error;
1265
1266 MAC_INTERNALIZE(ifnet_label, label, string);
1267
1268 return (error);
1269}
1270
1271static int
1272mac_internalize_pipe_label(struct label *label, char *string)
1273{
1274 int error;
1275
1276 MAC_INTERNALIZE(pipe_label, label, string);
1277
1278 return (error);
1279}
1280
1281static int
1282mac_internalize_socket_label(struct label *label, char *string)
1283{
1284 int error;
1285
1286 MAC_INTERNALIZE(socket_label, label, string);
1287
1288 return (error);
1289}
1290
1291static int
1292mac_internalize_vnode_label(struct label *label, char *string)
1293{
1294 int error;
1295
1296 MAC_INTERNALIZE(vnode_label, label, string);
1297
1298 return (error);
1299}
1300
1301/*
1302 * Initialize MAC label for the first kernel process, from which other
1303 * kernel processes and threads are spawned.
1304 */
1305void
1306mac_create_proc0(struct ucred *cred)
1307{
1308
1309 MAC_PERFORM(create_proc0, cred);
1310}
1311
1312/*
1313 * Initialize MAC label for the first userland process, from which other
1314 * userland processes and threads are spawned.
1315 */
1316void
1317mac_create_proc1(struct ucred *cred)
1318{
1319
1320 MAC_PERFORM(create_proc1, cred);
1321}
1322
1323void
1324mac_thread_userret(struct thread *td)
1325{
1326
1327 MAC_PERFORM(thread_userret, td);
1328}
1329
1330/*
1331 * When a new process is created, its label must be initialized. Generally,
1332 * this involves inheritence from the parent process, modulo possible
1333 * deltas. This function allows that processing to take place.
1334 */
1335void
1336mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1337{
1338
1339 MAC_PERFORM(create_cred, parent_cred, child_cred);
1340}
1341
1342void
1343mac_update_devfsdirent(struct mount *mp, struct devfs_dirent *de,
1344 struct vnode *vp)
1345{
1346
1347 MAC_PERFORM(update_devfsdirent, mp, de, &de->de_label, vp,
1348 &vp->v_label);
1349}
1350
1351void
1352mac_associate_vnode_devfs(struct mount *mp, struct devfs_dirent *de,
1353 struct vnode *vp)
1354{
1355
1356 MAC_PERFORM(associate_vnode_devfs, mp, &mp->mnt_fslabel, de,
1357 &de->de_label, vp, &vp->v_label);
1358}
1359
1360int
1361mac_associate_vnode_extattr(struct mount *mp, struct vnode *vp)
1362{
1363 int error;
1364
1365 ASSERT_VOP_LOCKED(vp, "mac_associate_vnode_extattr");
1366
1367 MAC_CHECK(associate_vnode_extattr, mp, &mp->mnt_fslabel, vp,
1368 &vp->v_label);
1369
1370 return (error);
1371}
1372
1373void
1374mac_associate_vnode_singlelabel(struct mount *mp, struct vnode *vp)
1375{
1376
1377 MAC_PERFORM(associate_vnode_singlelabel, mp, &mp->mnt_fslabel, vp,
1378 &vp->v_label);
1379}
1380
1381int
1382mac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1383 struct vnode *dvp, struct vnode *vp, struct componentname *cnp)
1384{
1385 int error;
1386
1387 ASSERT_VOP_LOCKED(dvp, "mac_create_vnode_extattr");
1388 ASSERT_VOP_LOCKED(vp, "mac_create_vnode_extattr");
1389
1390 error = VOP_OPENEXTATTR(vp, cred, curthread);
1391 if (error == EOPNOTSUPP) {
1392 /* XXX: Optionally abort if transactions not supported. */
1393 if (ea_warn_once == 0) {
1394 printf("Warning: transactions not supported "
1395 "in EA write.\n");
1396 ea_warn_once = 1;
1397 }
1398 } else if (error)
1399 return (error);
1400
1401 MAC_CHECK(create_vnode_extattr, cred, mp, &mp->mnt_fslabel,
1402 dvp, &dvp->v_label, vp, &vp->v_label, cnp);
1403
1404 if (error) {
1405 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1406 return (error);
1407 }
1408
1409 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1410
1411 if (error == EOPNOTSUPP)
1412 error = 0; /* XXX */
1413
1414 return (error);
1415}
1416
1417static int
1418mac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1419 struct label *intlabel)
1420{
1421 int error;
1422
1423 ASSERT_VOP_LOCKED(vp, "mac_setlabel_vnode_extattr");
1424
1425 error = VOP_OPENEXTATTR(vp, cred, curthread);
1426 if (error == EOPNOTSUPP) {
1427 /* XXX: Optionally abort if transactions not supported. */
1428 if (ea_warn_once == 0) {
1429 printf("Warning: transactions not supported "
1430 "in EA write.\n");
1431 ea_warn_once = 1;
1432 }
1433 } else if (error)
1434 return (error);
1435
1436 MAC_CHECK(setlabel_vnode_extattr, cred, vp, &vp->v_label, intlabel);
1437
1438 if (error) {
1439 VOP_CLOSEEXTATTR(vp, 0, NOCRED, curthread);
1440 return (error);
1441 }
1442
1443 error = VOP_CLOSEEXTATTR(vp, 1, NOCRED, curthread);
1444
1445 if (error == EOPNOTSUPP)
1446 error = 0; /* XXX */
1447
1448 return (error);
1449}
1450
1451int
1452mac_execve_enter(struct image_params *imgp, struct mac *mac_p,
1453 struct label *execlabelstorage)
1454{
1455 struct mac mac;
1456 char *buffer;
1457 int error;
1458
1459 if (mac_p == NULL)
1460 return (0);
1461
1462 error = copyin(mac_p, &mac, sizeof(mac));
1463 if (error)
1464 return (error);
1465
1466 error = mac_check_structmac_consistent(&mac);
1467 if (error)
1468 return (error);
1469
1470 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
1471 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
1472 if (error) {
1473 free(buffer, M_MACTEMP);
1474 return (error);
1475 }
1476
1477 mac_init_cred_label(execlabelstorage);
1478 error = mac_internalize_cred_label(execlabelstorage, buffer);
1479 free(buffer, M_MACTEMP);
1480 if (error) {
1481 mac_destroy_cred_label(execlabelstorage);
1482 return (error);
1483 }
1484 imgp->execlabel = execlabelstorage;
1485 return (0);
1486}
1487
1488void
1489mac_execve_exit(struct image_params *imgp)
1490{
1491 if (imgp->execlabel != NULL)
1492 mac_destroy_cred_label(imgp->execlabel);
1493}
1494
1495void
1496mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp,
1497 struct label *interpvnodelabel, struct image_params *imgp)
1498{
1499
1500 ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1501
1502 if (!mac_enforce_process && !mac_enforce_fs)
1503 return;
1504
1505 MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label,
1506 interpvnodelabel, imgp, imgp->execlabel);
1507}
1508
1509int
1510mac_execve_will_transition(struct ucred *old, struct vnode *vp,
1511 struct label *interpvnodelabel, struct image_params *imgp)
1512{
1513 int result;
1514
1515 ASSERT_VOP_LOCKED(vp, "mac_execve_will_transition");
1516
1517 if (!mac_enforce_process && !mac_enforce_fs)
1518 return (0);
1519
1520 result = 0;
1521 MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label,
1522 interpvnodelabel, imgp, imgp->execlabel);
1523
1524 return (result);
1525}
1526
1527int
1528mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int acc_mode)
1529{
1530 int error;
1531
1532 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1533
1534 if (!mac_enforce_fs)
1535 return (0);
1536
1537 MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, acc_mode);
1538 return (error);
1539}
1540
1541int
1542mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1543{
1544 int error;
1545
1546 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1547
1548 if (!mac_enforce_fs)
1549 return (0);
1550
1551 MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1552 return (error);
1553}
1554
1555int
1556mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1557{
1558 int error;
1559
1560 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1561
1562 if (!mac_enforce_fs)
1563 return (0);
1564
1565 MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1566 return (error);
1567}
1568
1569int
1570mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1571 struct componentname *cnp, struct vattr *vap)
1572{
1573 int error;
1574
1575 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1576
1577 if (!mac_enforce_fs)
1578 return (0);
1579
1580 MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1581 return (error);
1582}
1583
1584int
1585mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1586 struct componentname *cnp)
1587{
1588 int error;
1589
1590 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1591 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1592
1593 if (!mac_enforce_fs)
1594 return (0);
1595
1596 MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1597 &vp->v_label, cnp);
1598 return (error);
1599}
1600
1601int
1602mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1603 acl_type_t type)
1604{
1605 int error;
1606
1607 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1608
1609 if (!mac_enforce_fs)
1610 return (0);
1611
1612 MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1613 return (error);
1614}
1615
1616int
1617mac_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1618 struct image_params *imgp)
1619{
1620 int error;
1621
1622 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1623
1624 if (!mac_enforce_process && !mac_enforce_fs)
1625 return (0);
1626
1627 MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label, imgp,
1628 imgp->execlabel);
1629
1630 return (error);
1631}
1632
1633int
1634mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1635{
1636 int error;
1637
1638 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1639
1640 if (!mac_enforce_fs)
1641 return (0);
1642
1643 MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1644 return (error);
1645}
1646
1647int
1648mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1649 int attrnamespace, const char *name, struct uio *uio)
1650{
1651 int error;
1652
1653 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1654
1655 if (!mac_enforce_fs)
1656 return (0);
1657
1658 MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1659 attrnamespace, name, uio);
1660 return (error);
1661}
1662
1663int
1664mac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1665 struct vnode *vp, struct componentname *cnp)
1666{
1667 int error;
1668
1669 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_link");
1670 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_link");
1671
1672 if (!mac_enforce_fs)
1673 return (0);
1674
1675 MAC_CHECK(check_vnode_link, cred, dvp, &dvp->v_label, vp,
1676 &vp->v_label, cnp);
1677 return (error);
1678}
1679
1680int
1681mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1682 struct componentname *cnp)
1683{
1684 int error;
1685
1686 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1687
1688 if (!mac_enforce_fs)
1689 return (0);
1690
1691 MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1692 return (error);
1693}
1694
1695int
1696mac_check_vnode_mmap(struct ucred *cred, struct vnode *vp, int prot)
1697{
1698 int error;
1699
1700 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap");
1701
1702 if (!mac_enforce_fs || !mac_enforce_vm)
1703 return (0);
1704
1705 MAC_CHECK(check_vnode_mmap, cred, vp, &vp->v_label, prot);
1706 return (error);
1707}
1708
1709void
1710mac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp, int *prot)
1711{
1712 int result = *prot;
1713
1714 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_downgrade");
1715
1716 if (!mac_enforce_fs || !mac_enforce_vm)
1717 return;
1718
1719 MAC_PERFORM(check_vnode_mmap_downgrade, cred, vp, &vp->v_label,
1720 &result);
1721
1722 *prot = result;
1723}
1724
1725int
1726mac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp, int prot)
1727{
1728 int error;
1729
1730 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mprotect");
1731
1732 if (!mac_enforce_fs || !mac_enforce_vm)
1733 return (0);
1734
1735 MAC_CHECK(check_vnode_mprotect, cred, vp, &vp->v_label, prot);
1736 return (error);
1737}
1738
1739int
1740mac_check_vnode_open(struct ucred *cred, struct vnode *vp, int acc_mode)
1741{
1742 int error;
1743
1744 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1745
1746 if (!mac_enforce_fs)
1747 return (0);
1748
1749 MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1750 return (error);
1751}
1752
1753int
1754mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1755 struct vnode *vp)
1756{
1757 int error;
1758
1759 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1760
1761 if (!mac_enforce_fs)
1762 return (0);
1763
1764 MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1765 &vp->v_label);
1766
1767 return (error);
1768}
1769
1770int
1771mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1772 struct vnode *vp)
1773{
1774 int error;
1775
1776 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1777
1778 if (!mac_enforce_fs)
1779 return (0);
1780
1781 MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1782 &vp->v_label);
1783
1784 return (error);
1785}
1786
1787int
1788mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1789{
1790 int error;
1791
1792 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1793
1794 if (!mac_enforce_fs)
1795 return (0);
1796
1797 MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1798 return (error);
1799}
1800
1801int
1802mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1803{
1804 int error;
1805
1806 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1807
1808 if (!mac_enforce_fs)
1809 return (0);
1810
1811 MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1812 return (error);
1813}
1814
1815static int
1816mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1817 struct label *newlabel)
1818{
1819 int error;
1820
1821 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1822
1823 MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1824
1825 return (error);
1826}
1827
1828int
1829mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1830 struct vnode *vp, struct componentname *cnp)
1831{
1832 int error;
1833
1834 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1835 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1836
1837 if (!mac_enforce_fs)
1838 return (0);
1839
1840 MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1841 &vp->v_label, cnp);
1842 return (error);
1843}
1844
1845int
1846mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1847 struct vnode *vp, int samedir, struct componentname *cnp)
1848{
1849 int error;
1850
1851 ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1852 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1853
1854 if (!mac_enforce_fs)
1855 return (0);
1856
1857 MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1858 vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1859 return (error);
1860}
1861
1862int
1863mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1864{
1865 int error;
1866
1867 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1868
1869 if (!mac_enforce_fs)
1870 return (0);
1871
1872 MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1873 return (error);
1874}
1875
1876int
1877mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1878 struct acl *acl)
1879{
1880 int error;
1881
1882 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
1883
1884 if (!mac_enforce_fs)
1885 return (0);
1886
1887 MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
1888 return (error);
1889}
1890
1891int
1892mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
1893 int attrnamespace, const char *name, struct uio *uio)
1894{
1895 int error;
1896
1897 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
1898
1899 if (!mac_enforce_fs)
1900 return (0);
1901
1902 MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
1903 attrnamespace, name, uio);
1904 return (error);
1905}
1906
1907int
1908mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
1909{
1910 int error;
1911
1912 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
1913
1914 if (!mac_enforce_fs)
1915 return (0);
1916
1917 MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
1918 return (error);
1919}
1920
1921int
1922mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
1923{
1924 int error;
1925
1926 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
1927
1928 if (!mac_enforce_fs)
1929 return (0);
1930
1931 MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
1932 return (error);
1933}
1934
1935int
1936mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
1937 gid_t gid)
1938{
1939 int error;
1940
1941 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
1942
1943 if (!mac_enforce_fs)
1944 return (0);
1945
1946 MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
1947 return (error);
1948}
1949
1950int
1951mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
1952 struct timespec atime, struct timespec mtime)
1953{
1954 int error;
1955
1956 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
1957
1958 if (!mac_enforce_fs)
1959 return (0);
1960
1961 MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
1962 mtime);
1963 return (error);
1964}
1965
1966int
1967mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
1968 struct vnode *vp)
1969{
1970 int error;
1971
1972 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
1973
1974 if (!mac_enforce_fs)
1975 return (0);
1976
1977 MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
1978 &vp->v_label);
1979 return (error);
1980}
1981
1982int
1983mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
1984 struct vnode *vp)
1985{
1986 int error;
1987
1988 ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
1989
1990 if (!mac_enforce_fs)
1991 return (0);
1992
1993 MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
1994 &vp->v_label);
1995
1996 return (error);
1997}
1998
1999/*
2000 * When relabeling a process, call out to the policies for the maximum
2001 * permission allowed for each object type we know about in its
2002 * memory space, and revoke access (in the least surprising ways we
2003 * know) when necessary. The process lock is not held here.
2004 */
2005void
2006mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2007{
2008
2009 /* XXX freeze all other threads */
2010 mac_cred_mmapped_drop_perms_recurse(td, cred,
2011 &td->td_proc->p_vmspace->vm_map);
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 int result;
2045 vm_prot_t revokeperms;
2046 vm_object_t object;
2047 vm_ooffset_t offset;
2048 struct vnode *vp;
2049
2050 if (!mac_mmap_revocation)
2051 return;
2052
2053 vm_map_lock_read(map);
2054 for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2055 if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2056 mac_cred_mmapped_drop_perms_recurse(td, cred,
2057 vme->object.sub_map);
2058 continue;
2059 }
2060 /*
2061 * Skip over entries that obviously are not shared.
2062 */
2063 if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2064 !vme->max_protection)
2065 continue;
2066 /*
2067 * Drill down to the deepest backing object.
2068 */
2069 offset = vme->offset;
2070 object = vme->object.vm_object;
2071 if (object == NULL)
2072 continue;
2073 while (object->backing_object != NULL) {
2074 object = object->backing_object;
2075 offset += object->backing_object_offset;
2076 }
2077 /*
2078 * At the moment, vm_maps and objects aren't considered
2079 * by the MAC system, so only things with backing by a
2080 * normal object (read: vnodes) are checked.
2081 */
2082 if (object->type != OBJT_VNODE)
2083 continue;
2084 vp = (struct vnode *)object->handle;
2085 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2086 result = vme->max_protection;
2087 mac_check_vnode_mmap_downgrade(cred, vp, &result);
2088 VOP_UNLOCK(vp, 0, td);
2089 /*
2090 * Find out what maximum protection we may be allowing
2091 * now but a policy needs to get removed.
2092 */
2093 revokeperms = vme->max_protection & ~result;
2094 if (!revokeperms)
2095 continue;
2096 printf("pid %ld: revoking %s perms from %#lx:%ld "
2097 "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2098 prot2str(revokeperms), (u_long)vme->start,
2099 (long)(vme->end - vme->start),
2100 prot2str(vme->max_protection), prot2str(vme->protection));
2101 vm_map_lock_upgrade(map);
2102 /*
2103 * This is the really simple case: if a map has more
2104 * max_protection than is allowed, but it's not being
2105 * actually used (that is, the current protection is
2106 * still allowed), we can just wipe it out and do
2107 * nothing more.
2108 */
2109 if ((vme->protection & revokeperms) == 0) {
2110 vme->max_protection -= revokeperms;
2111 } else {
2112 if (revokeperms & VM_PROT_WRITE) {
2113 /*
2114 * In the more complicated case, flush out all
2115 * pending changes to the object then turn it
2116 * copy-on-write.
2117 */
2118 vm_object_reference(object);
2119 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2120 VM_OBJECT_LOCK(object);
2121 vm_object_page_clean(object,
2122 OFF_TO_IDX(offset),
2123 OFF_TO_IDX(offset + vme->end - vme->start +
2124 PAGE_MASK),
2125 OBJPC_SYNC);
2126 VM_OBJECT_UNLOCK(object);
2127 VOP_UNLOCK(vp, 0, td);
2128 vm_object_deallocate(object);
2129 /*
2130 * Why bother if there's no read permissions
2131 * anymore? For the rest, we need to leave
2132 * the write permissions on for COW, or
2133 * remove them entirely if configured to.
2134 */
2135 if (!mac_mmap_revocation_via_cow) {
2136 vme->max_protection &= ~VM_PROT_WRITE;
2137 vme->protection &= ~VM_PROT_WRITE;
2138 } if ((revokeperms & VM_PROT_READ) == 0)
2139 vme->eflags |= MAP_ENTRY_COW |
2140 MAP_ENTRY_NEEDS_COPY;
2141 }
2142 if (revokeperms & VM_PROT_EXECUTE) {
2143 vme->max_protection &= ~VM_PROT_EXECUTE;
2144 vme->protection &= ~VM_PROT_EXECUTE;
2145 }
2146 if (revokeperms & VM_PROT_READ) {
2147 vme->max_protection = 0;
2148 vme->protection = 0;
2149 }
2150 pmap_protect(map->pmap, vme->start, vme->end,
2151 vme->protection & ~revokeperms);
2152 vm_map_simplify_entry(map, vme);
2153 }
2154 vm_map_lock_downgrade(map);
2155 }
2156 vm_map_unlock_read(map);
2157}
2158
2159/*
2160 * When the subject's label changes, it may require revocation of privilege
2161 * to mapped objects. This can't be done on-the-fly later with a unified
2162 * buffer cache.
2163 */
2164static void
2165mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2166{
2167
2168 MAC_PERFORM(relabel_cred, cred, newlabel);
2169}
2170
2171void
2172mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2173{
2174
2175 MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2176}
2177
2178void
2179mac_create_ifnet(struct ifnet *ifnet)
2180{
2181
2182 MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2183}
2184
2185void
2186mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2187{
2188
2189 MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2190}
2191
2192void
2193mac_create_socket(struct ucred *cred, struct socket *socket)
2194{
2195
2196 MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2197}
2198
2199void
2200mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2201{
2202
2203 MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2204}
2205
2206void
2207mac_create_socket_from_socket(struct socket *oldsocket,
2208 struct socket *newsocket)
2209{
2210
2211 MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2212 newsocket, &newsocket->so_label);
2213}
2214
2215static void
2216mac_relabel_socket(struct ucred *cred, struct socket *socket,
2217 struct label *newlabel)
2218{
2219
2220 MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2221}
2222
2223static void
2224mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2225{
2226
2227 MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2228}
2229
2230void
2231mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2232{
2233 struct label *label;
2234
2235 label = mbuf_to_label(mbuf);
2236
2237 MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, label, socket,
2238 &socket->so_peerlabel);
2239}
2240
2241void
2242mac_set_socket_peer_from_socket(struct socket *oldsocket,
2243 struct socket *newsocket)
2244{
2245
2246 MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2247 &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2248}
2249
2250void
2251mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2252{
2253 struct label *label;
2254
2255 label = mbuf_to_label(datagram);
2256
2257 MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2258 datagram, label);
2259}
2260
2261void
2262mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2263{
2264 struct label *datagramlabel, *fragmentlabel;
2265
2266 datagramlabel = mbuf_to_label(datagram);
2267 fragmentlabel = mbuf_to_label(fragment);
2268
2269 MAC_PERFORM(create_fragment, datagram, datagramlabel, fragment,
2270 fragmentlabel);
2271}
2272
2273void
2274mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2275{
2276 struct label *label;
2277
2278 label = mbuf_to_label(fragment);
2279
2280 MAC_PERFORM(create_ipq, fragment, label, ipq, &ipq->ipq_label);
2281}
2282
2283void
2284mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2285{
2286 struct label *oldmbuflabel, *newmbuflabel;
2287
2288 oldmbuflabel = mbuf_to_label(oldmbuf);
2289 newmbuflabel = mbuf_to_label(newmbuf);
2290
2291 MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, oldmbuflabel, newmbuf,
2292 newmbuflabel);
2293}
2294
2295void
2296mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2297{
2298 struct label *label;
2299
2300 label = mbuf_to_label(mbuf);
2301
2302 MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2303 label);
2304}
2305
2306void
2307mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2308{
2309 struct label *label;
2310
2311 label = mbuf_to_label(mbuf);
2312
2313 MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2314 label);
2315}
2316
2317void
2318mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2319{
2320 struct label *label;
2321
2322 label = mbuf_to_label(mbuf);
2323
2324 MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2325 label);
2326}
2327
2328void
2329mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2330 struct mbuf *newmbuf)
2331{
2332 struct label *oldmbuflabel, *newmbuflabel;
2333
2334 oldmbuflabel = mbuf_to_label(oldmbuf);
2335 newmbuflabel = mbuf_to_label(newmbuf);
2336
2337 MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf, oldmbuflabel,
2338 ifnet, &ifnet->if_label, newmbuf, newmbuflabel);
2339}
2340
2341void
2342mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2343{
2344 struct label *oldmbuflabel, *newmbuflabel;
2345
2346 oldmbuflabel = mbuf_to_label(oldmbuf);
2347 newmbuflabel = mbuf_to_label(newmbuf);
2348
2349 MAC_PERFORM(create_mbuf_netlayer, oldmbuf, oldmbuflabel, newmbuf,
2350 newmbuflabel);
2351}
2352
2353int
2354mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2355{
2356 struct label *label;
2357 int result;
2358
2359 label = mbuf_to_label(fragment);
2360
2361 result = 1;
2362 MAC_BOOLEAN(fragment_match, &&, fragment, label, ipq,
2363 &ipq->ipq_label);
2364
2365 return (result);
2366}
2367
2368void
2369mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2370{
2371 struct label *label;
2372
2373 label = mbuf_to_label(fragment);
2374
2375 MAC_PERFORM(update_ipq, fragment, label, ipq, &ipq->ipq_label);
2376}
2377
2378void
2379mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2380{
2381 struct label *label;
2382
2383 label = mbuf_to_label(mbuf);
2384
2385 MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2386 label);
2387}
2388
2389void
2390mac_create_mount(struct ucred *cred, struct mount *mp)
2391{
2392
2393 MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2394 &mp->mnt_fslabel);
2395}
2396
2397void
2398mac_create_root_mount(struct ucred *cred, struct mount *mp)
2399{
2400
2401 MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2402 &mp->mnt_fslabel);
2403}
2404
2405int
2406mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2407{
2408 int error;
2409
2410 if (!mac_enforce_network)
2411 return (0);
2412
2413 MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2414 &ifnet->if_label);
2415
2416 return (error);
2417}
2418
2419static int
2420mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2421{
2422 int error;
2423
2424 MAC_CHECK(check_cred_relabel, cred, newlabel);
2425
2426 return (error);
2427}
2428
2429int
2430mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2431{
2432 int error;
2433
2434 if (!mac_enforce_process)
2435 return (0);
2436
2437 MAC_CHECK(check_cred_visible, u1, u2);
2438
2439 return (error);
2440}
2441
2442int
2443mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2444{
2445 struct label *label;
2446 int error;
2447
2448 M_ASSERTPKTHDR(mbuf);
2449
2450 if (!mac_enforce_network)
2451 return (0);
2452
2453 label = mbuf_to_label(mbuf);
2454
2455 MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2456 label);
2457
2458 return (error);
2459}
2460
2461int
2462mac_check_kenv_dump(struct ucred *cred)
2463{
2464 int error;
2465
2466 if (!mac_enforce_system)
2467 return (0);
2468
2469 MAC_CHECK(check_kenv_dump, cred);
2470
2471 return (error);
2472}
2473
2474int
2475mac_check_kenv_get(struct ucred *cred, char *name)
2476{
2477 int error;
2478
2479 if (!mac_enforce_system)
2480 return (0);
2481
2482 MAC_CHECK(check_kenv_get, cred, name);
2483
2484 return (error);
2485}
2486
2487int
2488mac_check_kenv_set(struct ucred *cred, char *name, char *value)
2489{
2490 int error;
2491
2492 if (!mac_enforce_system)
2493 return (0);
2494
2495 MAC_CHECK(check_kenv_set, cred, name, value);
2496
2497 return (error);
2498}
2499
2500int
2501mac_check_kenv_unset(struct ucred *cred, char *name)
2502{
2503 int error;
2504
2505 if (!mac_enforce_system)
2506 return (0);
2507
2508 MAC_CHECK(check_kenv_unset, cred, name);
2509
2510 return (error);
2511}
2512
2513int
2514mac_check_kld_load(struct ucred *cred, struct vnode *vp)
2515{
2516 int error;
2517
2518 ASSERT_VOP_LOCKED(vp, "mac_check_kld_load");
2519
2520 if (!mac_enforce_kld)
2521 return (0);
2522
2523 MAC_CHECK(check_kld_load, cred, vp, &vp->v_label);
2524
2525 return (error);
2526}
2527
2528int
2529mac_check_kld_stat(struct ucred *cred)
2530{
2531 int error;
2532
2533 if (!mac_enforce_kld)
2534 return (0);
2535
2536 MAC_CHECK(check_kld_stat, cred);
2537
2538 return (error);
2539}
2540
2541int
2542mac_check_kld_unload(struct ucred *cred)
2543{
2544 int error;
2545
2546 if (!mac_enforce_kld)
2547 return (0);
2548
2549 MAC_CHECK(check_kld_unload, cred);
2550
2551 return (error);
2552}
2553
2554int
2555mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2556{
2557 int error;
2558
2559 if (!mac_enforce_fs)
2560 return (0);
2561
2562 MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2563
2564 return (error);
2565}
2566
2567int
2568mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2569 void *data)
2570{
2571 int error;
2572
2573 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2574
2575 if (!mac_enforce_pipe)
2576 return (0);
2577
2578 MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2579
2580 return (error);
2581}
2582
2583int
2584mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2585{
2586 int error;
2587
2588 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2589
2590 if (!mac_enforce_pipe)
2591 return (0);
2592
2593 MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2594
2595 return (error);
2596}
2597
2598int
2599mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2600{
2601 int error;
2602
2603 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2604
2605 if (!mac_enforce_pipe)
2606 return (0);
2607
2608 MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2609
2610 return (error);
2611}
2612
2613static int
2614mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2615 struct label *newlabel)
2616{
2617 int error;
2618
2619 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2620
2621 if (!mac_enforce_pipe)
2622 return (0);
2623
2624 MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2625
2626 return (error);
2627}
2628
2629int
2630mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2631{
2632 int error;
2633
2634 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2635
2636 if (!mac_enforce_pipe)
2637 return (0);
2638
2639 MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2640
2641 return (error);
2642}
2643
2644int
2645mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2646{
2647 int error;
2648
2649 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2650
2651 if (!mac_enforce_pipe)
2652 return (0);
2653
2654 MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2655
2656 return (error);
2657}
2658
2659int
2660mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2661{
2662 int error;
2663
2664 PROC_LOCK_ASSERT(proc, MA_OWNED);
2665
2666 if (!mac_enforce_process)
2667 return (0);
2668
2669 MAC_CHECK(check_proc_debug, cred, proc);
2670
2671 return (error);
2672}
2673
2674int
2675mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2676{
2677 int error;
2678
2679 PROC_LOCK_ASSERT(proc, MA_OWNED);
2680
2681 if (!mac_enforce_process)
2682 return (0);
2683
2684 MAC_CHECK(check_proc_sched, cred, proc);
2685
2686 return (error);
2687}
2688
2689int
2690mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2691{
2692 int error;
2693
2694 PROC_LOCK_ASSERT(proc, MA_OWNED);
2695
2696 if (!mac_enforce_process)
2697 return (0);
2698
2699 MAC_CHECK(check_proc_signal, cred, proc, signum);
2700
2701 return (error);
2702}
2703
2704int
2705mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2706 struct sockaddr *sockaddr)
2707{
2708 int error;
2709
2710 if (!mac_enforce_socket)
2711 return (0);
2712
2713 MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2714 sockaddr);
2715
2716 return (error);
2717}
2718
2719int
2720mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2721 struct sockaddr *sockaddr)
2722{
2723 int error;
2724
2725 if (!mac_enforce_socket)
2726 return (0);
2727
2728 MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2729 sockaddr);
2730
2731 return (error);
2732}
2733
2734int
2735mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2736{
2737 struct label *label;
2738 int error;
2739
2740 if (!mac_enforce_socket)
2741 return (0);
2742
2743 label = mbuf_to_label(mbuf);
2744
2745 MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2746 label);
2747
2748 return (error);
2749}
2750
2751int
2752mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2753{
2754 int error;
2755
2756 if (!mac_enforce_socket)
2757 return (0);
2758
2759 MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2760 return (error);
2761}
2762
2763int
2764mac_check_socket_receive(struct ucred *cred, struct socket *so)
2765{
2766 int error;
2767
2768 if (!mac_enforce_socket)
2769 return (0);
2770
2771 MAC_CHECK(check_socket_receive, cred, so, &so->so_label);
2772
2773 return (error);
2774}
2775
2776static int
2777mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2778 struct label *newlabel)
2779{
2780 int error;
2781
2782 MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2783 newlabel);
2784
2785 return (error);
2786}
2787
2788int
2789mac_check_socket_send(struct ucred *cred, struct socket *so)
2790{
2791 int error;
2792
2793 if (!mac_enforce_socket)
2794 return (0);
2795
2796 MAC_CHECK(check_socket_send, cred, so, &so->so_label);
2797
2798 return (error);
2799}
2800
2801int
2802mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2803{
2804 int error;
2805
2806 if (!mac_enforce_socket)
2807 return (0);
2808
2809 MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2810
2811 return (error);
2812}
2813
2814int
2815mac_check_sysarch_ioperm(struct ucred *cred)
2816{
2817 int error;
2818
2819 if (!mac_enforce_system)
2820 return (0);
2821
2822 MAC_CHECK(check_sysarch_ioperm, cred);
2823 return (error);
2824}
2825
2826int
2827mac_check_system_acct(struct ucred *cred, struct vnode *vp)
2828{
2829 int error;
2830
2831 if (vp != NULL) {
2832 ASSERT_VOP_LOCKED(vp, "mac_check_system_acct");
2833 }
2834
2835 if (!mac_enforce_system)
2836 return (0);
2837
2838 MAC_CHECK(check_system_acct, cred, vp,
2839 vp != NULL ? &vp->v_label : NULL);
2840
2841 return (error);
2842}
2843
2844int
2845mac_check_system_nfsd(struct ucred *cred)
2846{
2847 int error;
2848
2849 if (!mac_enforce_system)
2850 return (0);
2851
2852 MAC_CHECK(check_system_nfsd, cred);
2853
2854 return (error);
2855}
2856
2857int
2858mac_check_system_reboot(struct ucred *cred, int howto)
2859{
2860 int error;
2861
2862 if (!mac_enforce_system)
2863 return (0);
2864
2865 MAC_CHECK(check_system_reboot, cred, howto);
2866
2867 return (error);
2868}
2869
2870int
2871mac_check_system_settime(struct ucred *cred)
2872{
2873 int error;
2874
2875 if (!mac_enforce_system)
2876 return (0);
2877
2878 MAC_CHECK(check_system_settime, cred);
2879
2880 return (error);
2881}
2882
2883int
2884mac_check_system_swapon(struct ucred *cred, struct vnode *vp)
2885{
2886 int error;
2887
2888 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapon");
2889
2890 if (!mac_enforce_system)
2891 return (0);
2892
2893 MAC_CHECK(check_system_swapon, cred, vp, &vp->v_label);
2894 return (error);
2895}
2896
2897int
2898mac_check_system_swapoff(struct ucred *cred, struct vnode *vp)
2899{
2900 int error;
2901
2902 ASSERT_VOP_LOCKED(vp, "mac_check_system_swapoff");
2903
2904 if (!mac_enforce_system)
2905 return (0);
2906
2907 MAC_CHECK(check_system_swapoff, cred, vp, &vp->v_label);
2908 return (error);
2909}
2910
2911int
2912mac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2913 void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2914{
2915 int error;
2916
2917 /*
2918 * XXXMAC: We're very much like to assert the SYSCTL_LOCK here,
2919 * but since it's not exported from kern_sysctl.c, we can't.
2920 */
2921 if (!mac_enforce_system)
2922 return (0);
2923
2924 MAC_CHECK(check_system_sysctl, cred, name, namelen, old, oldlenp,
2925 inkernel, new, newlen);
2926
2927 return (error);
2928}
2929
2930int
2931mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2932 struct ifnet *ifnet)
2933{
2934 char *elements, *buffer;
2935 struct mac mac;
2936 int error;
2937
2938 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2939 if (error)
2940 return (error);
2941
2942 error = mac_check_structmac_consistent(&mac);
2943 if (error)
2944 return (error);
2945
2946 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2947 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
2948 if (error) {
2949 free(elements, M_MACTEMP);
2950 return (error);
2951 }
2952
2953 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
2954 error = mac_externalize_ifnet_label(&ifnet->if_label, elements,
2955 buffer, mac.m_buflen, M_WAITOK);
2956 if (error == 0)
2957 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
2958
2959 free(buffer, M_MACTEMP);
2960 free(elements, M_MACTEMP);
2961
2962 return (error);
2963}
2964
2965int
2966mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2967 struct ifnet *ifnet)
2968{
2969 struct label intlabel;
2970 struct mac mac;
2971 char *buffer;
2972 int error;
2973
2974 error = copyin(ifr->ifr_ifru.ifru_data, &mac, sizeof(mac));
2975 if (error)
2976 return (error);
2977
2978 error = mac_check_structmac_consistent(&mac);
2979 if (error)
2980 return (error);
2981
2982 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
2983 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
2984 if (error) {
2985 free(buffer, M_MACTEMP);
2986 return (error);
2987 }
2988
2989 mac_init_ifnet_label(&intlabel);
2990 error = mac_internalize_ifnet_label(&intlabel, buffer);
2991 free(buffer, M_MACTEMP);
2992 if (error) {
2993 mac_destroy_ifnet_label(&intlabel);
2994 return (error);
2995 }
2996
2997 /*
2998 * XXX: Note that this is a redundant privilege check, since
2999 * policies impose this check themselves if required by the
3000 * policy. Eventually, this should go away.
3001 */
3002 error = suser_cred(cred, 0);
3003 if (error) {
3004 mac_destroy_ifnet_label(&intlabel);
3005 return (error);
3006 }
3007
3008 MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
3009 &intlabel);
3010 if (error) {
3011 mac_destroy_ifnet_label(&intlabel);
3012 return (error);
3013 }
3014
3015 MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
3016
3017 mac_destroy_ifnet_label(&intlabel);
3018 return (0);
3019}
3020
3021void
3022mac_create_devfs_device(struct mount *mp, dev_t dev, struct devfs_dirent *de)
3023{
3024
3025 MAC_PERFORM(create_devfs_device, mp, dev, de, &de->de_label);
3026}
3027
3028void
3029mac_create_devfs_symlink(struct ucred *cred, struct mount *mp,
3030 struct devfs_dirent *dd, struct devfs_dirent *de)
3031{
3032
3033 MAC_PERFORM(create_devfs_symlink, cred, mp, dd, &dd->de_label, de,
3034 &de->de_label);
3035}
3036
3037void
3038mac_create_devfs_directory(struct mount *mp, char *dirname, int dirnamelen,
3039 struct devfs_dirent *de)
3040{
3041
3042 MAC_PERFORM(create_devfs_directory, mp, dirname, dirnamelen, de,
3043 &de->de_label);
3044}
3045
3046int
3047mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
3048 struct mac *mac)
3049{
3050 struct label intlabel;
3051 char *buffer;
3052 int error;
3053
3054 error = mac_check_structmac_consistent(mac);
3055 if (error)
3056 return (error);
3057
3058 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3059 error = copyinstr(mac->m_string, buffer, mac->m_buflen, NULL);
3060 if (error) {
3061 free(buffer, M_MACTEMP);
3062 return (error);
3063 }
3064
3065 mac_init_socket_label(&intlabel, M_WAITOK);
3066 error = mac_internalize_socket_label(&intlabel, buffer);
3067 free(buffer, M_MACTEMP);
3068 if (error) {
3069 mac_destroy_socket_label(&intlabel);
3070 return (error);
3071 }
3072
3073 mac_check_socket_relabel(cred, so, &intlabel);
3074 if (error) {
3075 mac_destroy_socket_label(&intlabel);
3076 return (error);
3077 }
3078
3079 mac_relabel_socket(cred, so, &intlabel);
3080
3081 mac_destroy_socket_label(&intlabel);
3082 return (0);
3083}
3084
3085int
3086mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
3087{
3088 int error;
3089
3090 PIPE_LOCK_ASSERT(pipe, MA_OWNED);
3091
3092 error = mac_check_pipe_relabel(cred, pipe, label);
3093 if (error)
3094 return (error);
3095
3096 mac_relabel_pipe(cred, pipe, label);
3097
3098 return (0);
3099}
3100
3101int
3102mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
3103 struct mac *mac)
3104{
3105 char *buffer, *elements;
3106 int error;
3107
3108 error = mac_check_structmac_consistent(mac);
3109 if (error)
3110 return (error);
3111
3112 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3113 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3114 if (error) {
3115 free(elements, M_MACTEMP);
3116 return (error);
3117 }
3118
3119 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3120 error = mac_externalize_socket_label(&so->so_label, elements,
3121 buffer, mac->m_buflen, M_WAITOK);
3122 if (error == 0)
3123 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3124
3125 free(buffer, M_MACTEMP);
3126 free(elements, M_MACTEMP);
3127
3128 return (error);
3129}
3130
3131int
3132mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
3133 struct mac *mac)
3134{
3135 char *elements, *buffer;
3136 int error;
3137
3138 error = mac_check_structmac_consistent(mac);
3139 if (error)
3140 return (error);
3141
3142 elements = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK);
3143 error = copyinstr(mac->m_string, elements, mac->m_buflen, NULL);
3144 if (error) {
3145 free(elements, M_MACTEMP);
3146 return (error);
3147 }
3148
3149 buffer = malloc(mac->m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3150 error = mac_externalize_socket_peer_label(&so->so_peerlabel,
3151 elements, buffer, mac->m_buflen, M_WAITOK);
3152 if (error == 0)
3153 error = copyout(buffer, mac->m_string, strlen(buffer)+1);
3154
3155 free(buffer, M_MACTEMP);
3156 free(elements, M_MACTEMP);
3157
3158 return (error);
3159}
3160
3161/*
3162 * Implementation of VOP_SETLABEL() that relies on extended attributes
3163 * to store label data. Can be referenced by filesystems supporting
3164 * extended attributes.
3165 */
3166int
3167vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
3168{
3169 struct vnode *vp = ap->a_vp;
3170 struct label *intlabel = ap->a_label;
3171 int error;
3172
3173 ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
3174
3175 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3176 return (EOPNOTSUPP);
3177
3178 error = mac_setlabel_vnode_extattr(ap->a_cred, vp, intlabel);
3179 if (error)
3180 return (error);
3181
3182 mac_relabel_vnode(ap->a_cred, vp, intlabel);
3183
3184 return (0);
3185}
3186
3187static int
3188vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3189{
3190 int error;
3191
3192 if (vp->v_mount == NULL) {
3193 /* printf("vn_setlabel: null v_mount\n"); */
3194 if (vp->v_type != VNON)
3195 printf("vn_setlabel: null v_mount with non-VNON\n");
3196 return (EBADF);
3197 }
3198
3199 if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3200 return (EOPNOTSUPP);
3201
3202 /*
3203 * Multi-phase commit. First check the policies to confirm the
3204 * change is OK. Then commit via the filesystem. Finally,
3205 * update the actual vnode label. Question: maybe the filesystem
3206 * should update the vnode at the end as part of VOP_SETLABEL()?
3207 */
3208 error = mac_check_vnode_relabel(cred, vp, intlabel);
3209 if (error)
3210 return (error);
3211
3212 /*
3213 * VADMIN provides the opportunity for the filesystem to make
3214 * decisions about who is and is not able to modify labels
3215 * and protections on files. This might not be right. We can't
3216 * assume VOP_SETLABEL() will do it, because we might implement
3217 * that as part of vop_stdsetlabel_ea().
3218 */
3219 error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3220 if (error)
3221 return (error);
3222
3223 error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3224 if (error)
3225 return (error);
3226
3227 return (0);
3228}
3229
3230int
3231__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3232{
3233 char *elements, *buffer;
3234 struct mac mac;
3235 struct proc *tproc;
3236 struct ucred *tcred;
3237 int error;
3238
3239 error = copyin(uap->mac_p, &mac, sizeof(mac));
3240 if (error)
3241 return (error);
3242
3243 error = mac_check_structmac_consistent(&mac);
3244 if (error)
3245 return (error);
3246
3247 tproc = pfind(uap->pid);
3248 if (tproc == NULL)
3249 return (ESRCH);
3250
3251 tcred = NULL; /* Satisfy gcc. */
3252 error = p_cansee(td, tproc);
3253 if (error == 0)
3254 tcred = crhold(tproc->p_ucred);
3255 PROC_UNLOCK(tproc);
3256 if (error)
3257 return (error);
3258
3259 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3260 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3261 if (error) {
3262 free(elements, M_MACTEMP);
3263 crfree(tcred);
3264 return (error);
3265 }
3266
3267 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3268 error = mac_externalize_cred_label(&tcred->cr_label, elements,
3269 buffer, mac.m_buflen, M_WAITOK);
3270 if (error == 0)
3271 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3272
3273 free(buffer, M_MACTEMP);
3274 free(elements, M_MACTEMP);
3275 crfree(tcred);
3276 return (error);
3277}
3278
3279/*
3280 * MPSAFE
3281 */
3282int
3283__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3284{
3285 char *elements, *buffer;
3286 struct mac mac;
3287 int error;
3288
3289 error = copyin(uap->mac_p, &mac, sizeof(mac));
3290 if (error)
3291 return (error);
3292
3293 error = mac_check_structmac_consistent(&mac);
3294 if (error)
3295 return (error);
3296
3297 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3298 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3299 if (error) {
3300 free(elements, M_MACTEMP);
3301 return (error);
3302 }
3303
3304 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3305 error = mac_externalize_cred_label(&td->td_ucred->cr_label,
3306 elements, buffer, mac.m_buflen, M_WAITOK);
3307 if (error == 0)
3308 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3309
3310 free(buffer, M_MACTEMP);
3311 free(elements, M_MACTEMP);
3312 return (error);
3313}
3314
3315/*
3316 * MPSAFE
3317 */
3318int
3319__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3320{
3321 struct ucred *newcred, *oldcred;
3322 struct label intlabel;
3323 struct proc *p;
3324 struct mac mac;
3325 char *buffer;
3326 int error;
3327
3328 error = copyin(uap->mac_p, &mac, sizeof(mac));
3329 if (error)
3330 return (error);
3331
3332 error = mac_check_structmac_consistent(&mac);
3333 if (error)
3334 return (error);
3335
3336 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3337 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3338 if (error) {
3339 free(buffer, M_MACTEMP);
3340 return (error);
3341 }
3342
3343 mac_init_cred_label(&intlabel);
3344 error = mac_internalize_cred_label(&intlabel, buffer);
3345 free(buffer, M_MACTEMP);
3346 if (error) {
3347 mac_destroy_cred_label(&intlabel);
3348 return (error);
3349 }
3350
3351 newcred = crget();
3352
3353 p = td->td_proc;
3354 PROC_LOCK(p);
3355 oldcred = p->p_ucred;
3356
3357 error = mac_check_cred_relabel(oldcred, &intlabel);
3358 if (error) {
3359 PROC_UNLOCK(p);
3360 crfree(newcred);
3361 goto out;
3362 }
3363
3364 setsugid(p);
3365 crcopy(newcred, oldcred);
3366 mac_relabel_cred(newcred, &intlabel);
3367 p->p_ucred = newcred;
3368
3369 /*
3370 * Grab additional reference for use while revoking mmaps, prior
3371 * to releasing the proc lock and sharing the cred.
3372 */
3373 crhold(newcred);
3374 PROC_UNLOCK(p);
3375
3376 if (mac_enforce_vm) {
3377 mtx_lock(&Giant);
3378 mac_cred_mmapped_drop_perms(td, newcred);
3379 mtx_unlock(&Giant);
3380 }
3381
3382 crfree(newcred); /* Free revocation reference. */
3383 crfree(oldcred);
3384
3385out:
3386 mac_destroy_cred_label(&intlabel);
3387 return (error);
3388}
3389
3390/*
3391 * MPSAFE
3392 */
3393int
3394__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3395{
3396 char *elements, *buffer;
3397 struct label intlabel;
3398 struct file *fp;
3399 struct mac mac;
3400 struct vnode *vp;
3401 struct pipe *pipe;
3402 short label_type;
3403 int error;
3404
3405 error = copyin(uap->mac_p, &mac, sizeof(mac));
3406 if (error)
3407 return (error);
3408
3409 error = mac_check_structmac_consistent(&mac);
3410 if (error)
3411 return (error);
3412
3413 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3414 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3415 if (error) {
3416 free(elements, M_MACTEMP);
3417 return (error);
3418 }
3419
3420 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3421 mtx_lock(&Giant); /* VFS */
3422 error = fget(td, uap->fd, &fp);
3423 if (error)
3424 goto out;
3425
3426 label_type = fp->f_type;
3427 switch (fp->f_type) {
3428 case DTYPE_FIFO:
3429 case DTYPE_VNODE:
3430 vp = fp->f_vnode;
3431
3432 mac_init_vnode_label(&intlabel);
3433
3434 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3435 mac_copy_vnode_label(&vp->v_label, &intlabel);
3436 VOP_UNLOCK(vp, 0, td);
3437
3438 break;
3439 case DTYPE_PIPE:
3440 pipe = fp->f_data;
3441
3442 mac_init_pipe_label(&intlabel);
3443
3444 PIPE_LOCK(pipe);
3445 mac_copy_pipe_label(pipe->pipe_label, &intlabel);
3446 PIPE_UNLOCK(pipe);
3447 break;
3448 default:
3449 error = EINVAL;
3450 fdrop(fp, td);
3451 goto out;
3452 }
3453 fdrop(fp, td);
3454
3455 switch (label_type) {
3456 case DTYPE_FIFO:
3457 case DTYPE_VNODE:
3458 if (error == 0)
3459 error = mac_externalize_vnode_label(&intlabel,
3460 elements, buffer, mac.m_buflen, M_WAITOK);
3461 mac_destroy_vnode_label(&intlabel);
3462 break;
3463 case DTYPE_PIPE:
3464 error = mac_externalize_pipe_label(&intlabel, elements,
3465 buffer, mac.m_buflen, M_WAITOK);
3466 mac_destroy_pipe_label(&intlabel);
3467 break;
3468 default:
3469 panic("__mac_get_fd: corrupted label_type");
3470 }
3471
3472 if (error == 0)
3473 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3474
3475out:
3476 mtx_unlock(&Giant); /* VFS */
3477 free(buffer, M_MACTEMP);
3478 free(elements, M_MACTEMP);
3479
3480 return (error);
3481}
3482
3483/*
3484 * MPSAFE
3485 */
3486int
3487__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3488{
3489 char *elements, *buffer;
3490 struct nameidata nd;
3491 struct label intlabel;
3492 struct mac mac;
3493 int error;
3494
3495 error = copyin(uap->mac_p, &mac, sizeof(mac));
3496 if (error)
3497 return (error);
3498
3499 error = mac_check_structmac_consistent(&mac);
3500 if (error)
3501 return (error);
3502
3503 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3504 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3505 if (error) {
3506 free(elements, M_MACTEMP);
3507 return (error);
3508 }
3509
3510 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3511 mtx_lock(&Giant); /* VFS */
3512 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3513 td);
3514 error = namei(&nd);
3515 if (error)
3516 goto out;
3517
3518 mac_init_vnode_label(&intlabel);
3519 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3520 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3521 mac.m_buflen, M_WAITOK);
3522
3523 NDFREE(&nd, 0);
3524 mac_destroy_vnode_label(&intlabel);
3525
3526 if (error == 0)
3527 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3528
3529out:
3530 mtx_unlock(&Giant); /* VFS */
3531
3532 free(buffer, M_MACTEMP);
3533 free(elements, M_MACTEMP);
3534
3535 return (error);
3536}
3537
3538/*
3539 * MPSAFE
3540 */
3541int
3542__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3543{
3544 char *elements, *buffer;
3545 struct nameidata nd;
3546 struct label intlabel;
3547 struct mac mac;
3548 int error;
3549
3550 error = copyin(uap->mac_p, &mac, sizeof(mac));
3551 if (error)
3552 return (error);
3553
3554 error = mac_check_structmac_consistent(&mac);
3555 if (error)
3556 return (error);
3557
3558 elements = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3559 error = copyinstr(mac.m_string, elements, mac.m_buflen, NULL);
3560 if (error) {
3561 free(elements, M_MACTEMP);
3562 return (error);
3563 }
3564
3565 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK | M_ZERO);
3566 mtx_lock(&Giant); /* VFS */
3567 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3568 td);
3569 error = namei(&nd);
3570 if (error)
3571 goto out;
3572
3573 mac_init_vnode_label(&intlabel);
3574 mac_copy_vnode_label(&nd.ni_vp->v_label, &intlabel);
3575 error = mac_externalize_vnode_label(&intlabel, elements, buffer,
3576 mac.m_buflen, M_WAITOK);
3577 NDFREE(&nd, 0);
3578 mac_destroy_vnode_label(&intlabel);
3579
3580 if (error == 0)
3581 error = copyout(buffer, mac.m_string, strlen(buffer)+1);
3582
3583out:
3584 mtx_unlock(&Giant); /* VFS */
3585
3586 free(buffer, M_MACTEMP);
3587 free(elements, M_MACTEMP);
3588
3589 return (error);
3590}
3591
3592/*
3593 * MPSAFE
3594 */
3595int
3596__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3597{
3598 struct label intlabel;
3599 struct pipe *pipe;
3600 struct file *fp;
3601 struct mount *mp;
3602 struct vnode *vp;
3603 struct mac mac;
3604 char *buffer;
3605 int error;
3606
3607 error = copyin(uap->mac_p, &mac, sizeof(mac));
3608 if (error)
3609 return (error);
3610
3611 error = mac_check_structmac_consistent(&mac);
3612 if (error)
3613 return (error);
3614
3615 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3616 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3617 if (error) {
3618 free(buffer, M_MACTEMP);
3619 return (error);
3620 }
3621
3622 mtx_lock(&Giant); /* VFS */
3623
3624 error = fget(td, uap->fd, &fp);
3625 if (error)
3626 goto out;
3627
3628 switch (fp->f_type) {
3629 case DTYPE_FIFO:
3630 case DTYPE_VNODE:
3631 mac_init_vnode_label(&intlabel);
3632 error = mac_internalize_vnode_label(&intlabel, buffer);
3633 if (error) {
3634 mac_destroy_vnode_label(&intlabel);
3635 break;
3636 }
3637
3638 vp = fp->f_vnode;
3639 error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3640 if (error != 0) {
3641 mac_destroy_vnode_label(&intlabel);
3642 break;
3643 }
3644
3645 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3646 error = vn_setlabel(vp, &intlabel, td->td_ucred);
3647 VOP_UNLOCK(vp, 0, td);
3648 vn_finished_write(mp);
3649
3650 mac_destroy_vnode_label(&intlabel);
3651 break;
3652
3653 case DTYPE_PIPE:
3654 mac_init_pipe_label(&intlabel);
3655 error = mac_internalize_pipe_label(&intlabel, buffer);
3656 if (error == 0) {
3657 pipe = fp->f_data;
3658 PIPE_LOCK(pipe);
3659 error = mac_pipe_label_set(td->td_ucred, pipe,
3660 &intlabel);
3661 PIPE_UNLOCK(pipe);
3662 }
3663
3664 mac_destroy_pipe_label(&intlabel);
3665 break;
3666
3667 default:
3668 error = EINVAL;
3669 }
3670
3671 fdrop(fp, td);
3672out:
3673 mtx_unlock(&Giant); /* VFS */
3674
3675 free(buffer, M_MACTEMP);
3676
3677 return (error);
3678}
3679
3680/*
3681 * MPSAFE
3682 */
3683int
3684__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3685{
3686 struct label intlabel;
3687 struct nameidata nd;
3688 struct mount *mp;
3689 struct mac mac;
3690 char *buffer;
3691 int error;
3692
3693 error = copyin(uap->mac_p, &mac, sizeof(mac));
3694 if (error)
3695 return (error);
3696
3697 error = mac_check_structmac_consistent(&mac);
3698 if (error)
3699 return (error);
3700
3701 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3702 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3703 if (error) {
3704 free(buffer, M_MACTEMP);
3705 return (error);
3706 }
3707
3708 mac_init_vnode_label(&intlabel);
3709 error = mac_internalize_vnode_label(&intlabel, buffer);
3710 free(buffer, M_MACTEMP);
3711 if (error) {
3712 mac_destroy_vnode_label(&intlabel);
3713 return (error);
3714 }
3715
3716 mtx_lock(&Giant); /* VFS */
3717
3718 NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE, uap->path_p,
3719 td);
3720 error = namei(&nd);
3721 if (error == 0) {
3722 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3723 if (error == 0)
3724 error = vn_setlabel(nd.ni_vp, &intlabel,
3725 td->td_ucred);
3726 vn_finished_write(mp);
3727 }
3728
3729 NDFREE(&nd, 0);
3730 mtx_unlock(&Giant); /* VFS */
3731 mac_destroy_vnode_label(&intlabel);
3732
3733 return (error);
3734}
3735
3736/*
3737 * MPSAFE
3738 */
3739int
3740__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3741{
3742 struct label intlabel;
3743 struct nameidata nd;
3744 struct mount *mp;
3745 struct mac mac;
3746 char *buffer;
3747 int error;
3748
3749 error = copyin(uap->mac_p, &mac, sizeof(mac));
3750 if (error)
3751 return (error);
3752
3753 error = mac_check_structmac_consistent(&mac);
3754 if (error)
3755 return (error);
3756
3757 buffer = malloc(mac.m_buflen, M_MACTEMP, M_WAITOK);
3758 error = copyinstr(mac.m_string, buffer, mac.m_buflen, NULL);
3759 if (error) {
3760 free(buffer, M_MACTEMP);
3761 return (error);
3762 }
3763
3764 mac_init_vnode_label(&intlabel);
3765 error = mac_internalize_vnode_label(&intlabel, buffer);
3766 free(buffer, M_MACTEMP);
3767 if (error) {
3768 mac_destroy_vnode_label(&intlabel);
3769 return (error);
3770 }
3771
3772 mtx_lock(&Giant); /* VFS */
3773
3774 NDINIT(&nd, LOOKUP, LOCKLEAF | NOFOLLOW, UIO_USERSPACE, uap->path_p,
3775 td);
3776 error = namei(&nd);
3777 if (error == 0) {
3778 error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3779 if (error == 0)
3780 error = vn_setlabel(nd.ni_vp, &intlabel,
3781 td->td_ucred);
3782 vn_finished_write(mp);
3783 }
3784
3785 NDFREE(&nd, 0);
3786 mtx_unlock(&Giant); /* VFS */
3787 mac_destroy_vnode_label(&intlabel);
3788
3789 return (error);
3790}
3791
3792/*
3793 * MPSAFE
3794 */
3795int
3796mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3797{
3798 struct mac_policy_conf *mpc;
3799 char target[MAC_MAX_POLICY_NAME];
3800 int entrycount, error;
3801
3802 error = copyinstr(uap->policy, target, sizeof(target), NULL);
3803 if (error)
3804 return (error);
3805
3806 error = ENOSYS;
3807 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3808 if (strcmp(mpc->mpc_name, target) == 0 &&
3809 mpc->mpc_ops->mpo_syscall != NULL) {
3810 error = mpc->mpc_ops->mpo_syscall(td,
3811 uap->call, uap->arg);
3812 goto out;
3813 }
3814 }
3815
3816 if ((entrycount = mac_policy_list_conditional_busy()) != 0) {
3817 LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3818 if (strcmp(mpc->mpc_name, target) == 0 &&
3819 mpc->mpc_ops->mpo_syscall != NULL) {
3820 error = mpc->mpc_ops->mpo_syscall(td,
3821 uap->call, uap->arg);
3822 break;
3823 }
3824 }
3825 mac_policy_list_unbusy();
3826 }
3827out:
3828 return (error);
3829}
3830
3831SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3832SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3833
3834#else /* !MAC */
3835
3836int
3837__mac_get_pid(struct thread *td, struct __mac_get_pid_args *uap)
3838{
3839
3840 return (ENOSYS);
3841}
3842
3843int
3844__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3845{
3846
3847 return (ENOSYS);
3848}
3849
3850int
3851__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3852{
3853
3854 return (ENOSYS);
3855}
3856
3857int
3858__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3859{
3860
3861 return (ENOSYS);
3862}
3863
3864int
3865__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3866{
3867
3868 return (ENOSYS);
3869}
3870
3871int
3872__mac_get_link(struct thread *td, struct __mac_get_link_args *uap)
3873{
3874
3875 return (ENOSYS);
3876}
3877
3878int
3879__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3880{
3881
3882 return (ENOSYS);
3883}
3884
3885int
3886__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3887{
3888
3889 return (ENOSYS);
3890}
3891
3892int
3893__mac_set_link(struct thread *td, struct __mac_set_link_args *uap)
3894{
3895
3896 return (ENOSYS);
3897}
3898
3899int
3900mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3901{
3902
3903 return (ENOSYS);
3904}
3905
3906#endif