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