mac_cred.c revision 104338
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 104338 2002-10-02 02:42:38Z rwatson $
40 */
41/*
42 * Developed by the TrustedBSD Project.
43 *
44 * Framework for extensible kernel access control.  Kernel and userland
45 * interface to the framework, policy registration and composition.
46 */
47
48#include "opt_mac.h"
49#include "opt_devfs.h"
50
51#include <sys/param.h>
52#include <sys/extattr.h>
53#include <sys/kernel.h>
54#include <sys/lock.h>
55#include <sys/malloc.h>
56#include <sys/mutex.h>
57#include <sys/mac.h>
58#include <sys/module.h>
59#include <sys/proc.h>
60#include <sys/systm.h>
61#include <sys/sysproto.h>
62#include <sys/sysent.h>
63#include <sys/vnode.h>
64#include <sys/mount.h>
65#include <sys/file.h>
66#include <sys/namei.h>
67#include <sys/socket.h>
68#include <sys/pipe.h>
69#include <sys/socketvar.h>
70#include <sys/sysctl.h>
71
72#include <vm/vm.h>
73#include <vm/pmap.h>
74#include <vm/vm_map.h>
75#include <vm/vm_object.h>
76
77#include <sys/mac_policy.h>
78
79#include <fs/devfs/devfs.h>
80
81#include <net/bpfdesc.h>
82#include <net/if.h>
83#include <net/if_var.h>
84
85#include <netinet/in.h>
86#include <netinet/ip_var.h>
87
88#ifdef MAC
89
90/*
91 * Declare that the kernel provides MAC support, version 1.  This permits
92 * modules to refuse to be loaded if the necessary support isn't present,
93 * even if it's pre-boot.
94 */
95MODULE_VERSION(kernel_mac_support, 1);
96
97SYSCTL_DECL(_security);
98
99SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
100    "TrustedBSD MAC policy controls");
101#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_THREAD_USERRET:
656			mpc->mpc_ops->mpo_thread_userret =
657			    mpe->mpe_function;
658			break;
659		case MAC_CHECK_BPFDESC_RECEIVE:
660			mpc->mpc_ops->mpo_check_bpfdesc_receive =
661			    mpe->mpe_function;
662			break;
663		case MAC_CHECK_CRED_RELABEL:
664			mpc->mpc_ops->mpo_check_cred_relabel =
665			    mpe->mpe_function;
666			break;
667		case MAC_CHECK_CRED_VISIBLE:
668			mpc->mpc_ops->mpo_check_cred_visible =
669			    mpe->mpe_function;
670			break;
671		case MAC_CHECK_IFNET_RELABEL:
672			mpc->mpc_ops->mpo_check_ifnet_relabel =
673			    mpe->mpe_function;
674			break;
675		case MAC_CHECK_IFNET_TRANSMIT:
676			mpc->mpc_ops->mpo_check_ifnet_transmit =
677			    mpe->mpe_function;
678			break;
679		case MAC_CHECK_MOUNT_STAT:
680			mpc->mpc_ops->mpo_check_mount_stat =
681			    mpe->mpe_function;
682			break;
683		case MAC_CHECK_PIPE_IOCTL:
684			mpc->mpc_ops->mpo_check_pipe_ioctl =
685			    mpe->mpe_function;
686			break;
687		case MAC_CHECK_PIPE_POLL:
688			mpc->mpc_ops->mpo_check_pipe_poll =
689			    mpe->mpe_function;
690			break;
691		case MAC_CHECK_PIPE_READ:
692			mpc->mpc_ops->mpo_check_pipe_read =
693			    mpe->mpe_function;
694			break;
695		case MAC_CHECK_PIPE_RELABEL:
696			mpc->mpc_ops->mpo_check_pipe_relabel =
697			    mpe->mpe_function;
698			break;
699		case MAC_CHECK_PIPE_STAT:
700			mpc->mpc_ops->mpo_check_pipe_stat =
701			    mpe->mpe_function;
702			break;
703		case MAC_CHECK_PIPE_WRITE:
704			mpc->mpc_ops->mpo_check_pipe_write =
705			    mpe->mpe_function;
706			break;
707		case MAC_CHECK_PROC_DEBUG:
708			mpc->mpc_ops->mpo_check_proc_debug =
709			    mpe->mpe_function;
710			break;
711		case MAC_CHECK_PROC_SCHED:
712			mpc->mpc_ops->mpo_check_proc_sched =
713			    mpe->mpe_function;
714			break;
715		case MAC_CHECK_PROC_SIGNAL:
716			mpc->mpc_ops->mpo_check_proc_signal =
717			    mpe->mpe_function;
718			break;
719		case MAC_CHECK_SOCKET_BIND:
720			mpc->mpc_ops->mpo_check_socket_bind =
721			    mpe->mpe_function;
722			break;
723		case MAC_CHECK_SOCKET_CONNECT:
724			mpc->mpc_ops->mpo_check_socket_connect =
725			    mpe->mpe_function;
726			break;
727		case MAC_CHECK_SOCKET_DELIVER:
728			mpc->mpc_ops->mpo_check_socket_deliver =
729			    mpe->mpe_function;
730			break;
731		case MAC_CHECK_SOCKET_LISTEN:
732			mpc->mpc_ops->mpo_check_socket_listen =
733			    mpe->mpe_function;
734			break;
735		case MAC_CHECK_SOCKET_RELABEL:
736			mpc->mpc_ops->mpo_check_socket_relabel =
737			    mpe->mpe_function;
738			break;
739		case MAC_CHECK_SOCKET_VISIBLE:
740			mpc->mpc_ops->mpo_check_socket_visible =
741			    mpe->mpe_function;
742			break;
743		case MAC_CHECK_VNODE_ACCESS:
744			mpc->mpc_ops->mpo_check_vnode_access =
745			    mpe->mpe_function;
746			break;
747		case MAC_CHECK_VNODE_CHDIR:
748			mpc->mpc_ops->mpo_check_vnode_chdir =
749			    mpe->mpe_function;
750			break;
751		case MAC_CHECK_VNODE_CHROOT:
752			mpc->mpc_ops->mpo_check_vnode_chroot =
753			    mpe->mpe_function;
754			break;
755		case MAC_CHECK_VNODE_CREATE:
756			mpc->mpc_ops->mpo_check_vnode_create =
757			    mpe->mpe_function;
758			break;
759		case MAC_CHECK_VNODE_DELETE:
760			mpc->mpc_ops->mpo_check_vnode_delete =
761			    mpe->mpe_function;
762			break;
763		case MAC_CHECK_VNODE_DELETEACL:
764			mpc->mpc_ops->mpo_check_vnode_deleteacl =
765			    mpe->mpe_function;
766			break;
767		case MAC_CHECK_VNODE_EXEC:
768			mpc->mpc_ops->mpo_check_vnode_exec =
769			    mpe->mpe_function;
770			break;
771		case MAC_CHECK_VNODE_GETACL:
772			mpc->mpc_ops->mpo_check_vnode_getacl =
773			    mpe->mpe_function;
774			break;
775		case MAC_CHECK_VNODE_GETEXTATTR:
776			mpc->mpc_ops->mpo_check_vnode_getextattr =
777			    mpe->mpe_function;
778			break;
779		case MAC_CHECK_VNODE_LOOKUP:
780			mpc->mpc_ops->mpo_check_vnode_lookup =
781			    mpe->mpe_function;
782			break;
783		case MAC_CHECK_VNODE_MMAP_PERMS:
784			mpc->mpc_ops->mpo_check_vnode_mmap_perms =
785			    mpe->mpe_function;
786			break;
787		case MAC_CHECK_VNODE_OPEN:
788			mpc->mpc_ops->mpo_check_vnode_open =
789			    mpe->mpe_function;
790			break;
791		case MAC_CHECK_VNODE_POLL:
792			mpc->mpc_ops->mpo_check_vnode_poll =
793			    mpe->mpe_function;
794			break;
795		case MAC_CHECK_VNODE_READ:
796			mpc->mpc_ops->mpo_check_vnode_read =
797			    mpe->mpe_function;
798			break;
799		case MAC_CHECK_VNODE_READDIR:
800			mpc->mpc_ops->mpo_check_vnode_readdir =
801			    mpe->mpe_function;
802			break;
803		case MAC_CHECK_VNODE_READLINK:
804			mpc->mpc_ops->mpo_check_vnode_readlink =
805			    mpe->mpe_function;
806			break;
807		case MAC_CHECK_VNODE_RELABEL:
808			mpc->mpc_ops->mpo_check_vnode_relabel =
809			    mpe->mpe_function;
810			break;
811		case MAC_CHECK_VNODE_RENAME_FROM:
812			mpc->mpc_ops->mpo_check_vnode_rename_from =
813			    mpe->mpe_function;
814			break;
815		case MAC_CHECK_VNODE_RENAME_TO:
816			mpc->mpc_ops->mpo_check_vnode_rename_to =
817			    mpe->mpe_function;
818			break;
819		case MAC_CHECK_VNODE_REVOKE:
820			mpc->mpc_ops->mpo_check_vnode_revoke =
821			    mpe->mpe_function;
822			break;
823		case MAC_CHECK_VNODE_SETACL:
824			mpc->mpc_ops->mpo_check_vnode_setacl =
825			    mpe->mpe_function;
826			break;
827		case MAC_CHECK_VNODE_SETEXTATTR:
828			mpc->mpc_ops->mpo_check_vnode_setextattr =
829			    mpe->mpe_function;
830			break;
831		case MAC_CHECK_VNODE_SETFLAGS:
832			mpc->mpc_ops->mpo_check_vnode_setflags =
833			    mpe->mpe_function;
834			break;
835		case MAC_CHECK_VNODE_SETMODE:
836			mpc->mpc_ops->mpo_check_vnode_setmode =
837			    mpe->mpe_function;
838			break;
839		case MAC_CHECK_VNODE_SETOWNER:
840			mpc->mpc_ops->mpo_check_vnode_setowner =
841			    mpe->mpe_function;
842			break;
843		case MAC_CHECK_VNODE_SETUTIMES:
844			mpc->mpc_ops->mpo_check_vnode_setutimes =
845			    mpe->mpe_function;
846			break;
847		case MAC_CHECK_VNODE_STAT:
848			mpc->mpc_ops->mpo_check_vnode_stat =
849			    mpe->mpe_function;
850			break;
851		case MAC_CHECK_VNODE_WRITE:
852			mpc->mpc_ops->mpo_check_vnode_write =
853			    mpe->mpe_function;
854			break;
855/*
856		default:
857			printf("MAC policy `%s': unknown operation %d\n",
858			    mpc->mpc_name, mpe->mpe_constant);
859			return (EINVAL);
860*/
861		}
862	}
863	MAC_POLICY_LIST_LOCK();
864	if (mac_policy_list_busy > 0) {
865		MAC_POLICY_LIST_UNLOCK();
866		FREE(mpc->mpc_ops, M_MACOPVEC);
867		mpc->mpc_ops = NULL;
868		return (EBUSY);
869	}
870	LIST_FOREACH(tmpc, &mac_policy_list, mpc_list) {
871		if (strcmp(tmpc->mpc_name, mpc->mpc_name) == 0) {
872			MAC_POLICY_LIST_UNLOCK();
873			FREE(mpc->mpc_ops, M_MACOPVEC);
874			mpc->mpc_ops = NULL;
875			return (EEXIST);
876		}
877	}
878	if (mpc->mpc_field_off != NULL) {
879		slot = ffs(mac_policy_offsets_free);
880		if (slot == 0) {
881			MAC_POLICY_LIST_UNLOCK();
882			FREE(mpc->mpc_ops, M_MACOPVEC);
883			mpc->mpc_ops = NULL;
884			return (ENOMEM);
885		}
886		slot--;
887		mac_policy_offsets_free &= ~(1 << slot);
888		*mpc->mpc_field_off = slot;
889	}
890	mpc->mpc_runtime_flags |= MPC_RUNTIME_FLAG_REGISTERED;
891	LIST_INSERT_HEAD(&mac_policy_list, mpc, mpc_list);
892
893	/* Per-policy initialization. */
894	if (mpc->mpc_ops->mpo_init != NULL)
895		(*(mpc->mpc_ops->mpo_init))(mpc);
896	MAC_POLICY_LIST_UNLOCK();
897
898	printf("Security policy loaded: %s (%s)\n", mpc->mpc_fullname,
899	    mpc->mpc_name);
900
901	return (0);
902}
903
904static int
905mac_policy_unregister(struct mac_policy_conf *mpc)
906{
907
908#if 0
909	/*
910	 * Don't allow unloading modules with private data.
911	 */
912	if (mpc->mpc_field_off != NULL)
913		return (EBUSY);
914#endif
915	if ((mpc->mpc_loadtime_flags & MPC_LOADTIME_FLAG_UNLOADOK) == 0)
916		return (EBUSY);
917	MAC_POLICY_LIST_LOCK();
918	if (mac_policy_list_busy > 0) {
919		MAC_POLICY_LIST_UNLOCK();
920		return (EBUSY);
921	}
922	if (mpc->mpc_ops->mpo_destroy != NULL)
923		(*(mpc->mpc_ops->mpo_destroy))(mpc);
924
925	LIST_REMOVE(mpc, mpc_list);
926	MAC_POLICY_LIST_UNLOCK();
927
928	FREE(mpc->mpc_ops, M_MACOPVEC);
929	mpc->mpc_ops = NULL;
930
931	printf("Security policy unload: %s (%s)\n", mpc->mpc_fullname,
932	    mpc->mpc_name);
933
934	return (0);
935}
936
937/*
938 * Define an error value precedence, and given two arguments, selects the
939 * value with the higher precedence.
940 */
941static int
942error_select(int error1, int error2)
943{
944
945	/* Certain decision-making errors take top priority. */
946	if (error1 == EDEADLK || error2 == EDEADLK)
947		return (EDEADLK);
948
949	/* Invalid arguments should be reported where possible. */
950	if (error1 == EINVAL || error2 == EINVAL)
951		return (EINVAL);
952
953	/* Precedence goes to "visibility", with both process and file. */
954	if (error1 == ESRCH || error2 == ESRCH)
955		return (ESRCH);
956
957	if (error1 == ENOENT || error2 == ENOENT)
958		return (ENOENT);
959
960	/* Precedence goes to DAC/MAC protections. */
961	if (error1 == EACCES || error2 == EACCES)
962		return (EACCES);
963
964	/* Precedence goes to privilege. */
965	if (error1 == EPERM || error2 == EPERM)
966		return (EPERM);
967
968	/* Precedence goes to error over success; otherwise, arbitrary. */
969	if (error1 != 0)
970		return (error1);
971	return (error2);
972}
973
974void
975mac_update_devfsdirent(struct devfs_dirent *de, struct vnode *vp)
976{
977
978	MAC_PERFORM(update_devfsdirent, de, &de->de_label, vp, &vp->v_label);
979}
980
981void
982mac_update_procfsvnode(struct vnode *vp, struct ucred *cred)
983{
984
985	MAC_PERFORM(update_procfsvnode, vp, &vp->v_label, cred);
986}
987
988/*
989 * Support callout for policies that manage their own externalization
990 * using extended attributes.
991 */
992static int
993mac_update_vnode_from_extattr(struct vnode *vp, struct mount *mp)
994{
995	int error;
996
997	MAC_CHECK(update_vnode_from_extattr, vp, &vp->v_label, mp,
998	    &mp->mnt_fslabel);
999
1000	return (error);
1001}
1002
1003/*
1004 * Given an externalized mac label, internalize it and stamp it on a
1005 * vnode.
1006 */
1007static int
1008mac_update_vnode_from_externalized(struct vnode *vp, struct mac *extmac)
1009{
1010	int error;
1011
1012	MAC_CHECK(update_vnode_from_externalized, vp, &vp->v_label, extmac);
1013
1014	return (error);
1015}
1016
1017/*
1018 * Call out to individual policies to update the label in a vnode from
1019 * the mountpoint.
1020 */
1021void
1022mac_update_vnode_from_mount(struct vnode *vp, struct mount *mp)
1023{
1024
1025	MAC_PERFORM(update_vnode_from_mount, vp, &vp->v_label, mp,
1026	    &mp->mnt_fslabel);
1027
1028	ASSERT_VOP_LOCKED(vp, "mac_update_vnode_from_mount");
1029	if (mac_cache_fslabel_in_vnode)
1030		vp->v_vflag |= VV_CACHEDLABEL;
1031}
1032
1033/*
1034 * Implementation of VOP_REFRESHLABEL() that relies on extended attributes
1035 * to store label data.  Can be referenced by filesystems supporting
1036 * extended attributes.
1037 */
1038int
1039vop_stdrefreshlabel_ea(struct vop_refreshlabel_args *ap)
1040{
1041	struct vnode *vp = ap->a_vp;
1042	struct mac extmac;
1043	int buflen, error;
1044
1045	ASSERT_VOP_LOCKED(vp, "vop_stdrefreshlabel_ea");
1046
1047	/*
1048	 * Call out to external policies first.  Order doesn't really
1049	 * matter, as long as failure of one assures failure of all.
1050	 */
1051	error = mac_update_vnode_from_extattr(vp, vp->v_mount);
1052	if (error)
1053		return (error);
1054
1055	buflen = sizeof(extmac);
1056	error = vn_extattr_get(vp, IO_NODELOCKED,
1057	    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME, &buflen,
1058	    (char *)&extmac, curthread);
1059	switch (error) {
1060	case 0:
1061		/* Got it */
1062		break;
1063
1064	case ENOATTR:
1065		/*
1066		 * Use the label from the mount point.
1067		 */
1068		mac_update_vnode_from_mount(vp, vp->v_mount);
1069		return (0);
1070
1071	case EOPNOTSUPP:
1072	default:
1073		/* Fail horribly. */
1074		return (error);
1075	}
1076
1077	if (buflen != sizeof(extmac))
1078		error = EPERM;		/* Fail very closed. */
1079	if (error == 0)
1080		error = mac_update_vnode_from_externalized(vp, &extmac);
1081	if (error == 0)
1082		vp->v_vflag |= VV_CACHEDLABEL;
1083	else {
1084		struct vattr va;
1085
1086		printf("Corrupted label on %s",
1087		    vp->v_mount->mnt_stat.f_mntonname);
1088		if (VOP_GETATTR(vp, &va, curthread->td_ucred, curthread) == 0)
1089			printf(" inum %ld", va.va_fileid);
1090#ifdef MAC_DEBUG
1091		if (mac_debug_label_fallback) {
1092			printf(", falling back.\n");
1093			mac_update_vnode_from_mount(vp, vp->v_mount);
1094			error = 0;
1095		} else {
1096#endif
1097			printf(".\n");
1098			error = EPERM;
1099#ifdef MAC_DEBUG
1100		}
1101#endif
1102	}
1103
1104	return (error);
1105}
1106
1107/*
1108 * Make sure the vnode label is up-to-date.  If EOPNOTSUPP, then we handle
1109 * the labeling activity outselves.  Filesystems should be careful not
1110 * to change their minds regarding whether they support vop_refreshlabel()
1111 * for a vnode or not.  Don't cache the vnode here, allow the file
1112 * system code to determine if it's safe to cache.  If we update from
1113 * the mount, don't cache since a change to the mount label should affect
1114 * all vnodes.
1115 */
1116static int
1117vn_refreshlabel(struct vnode *vp, struct ucred *cred)
1118{
1119	int error;
1120
1121	ASSERT_VOP_LOCKED(vp, "vn_refreshlabel");
1122
1123	if (vp->v_mount == NULL) {
1124/*
1125		Eventually, we probably want to special-case refreshing
1126		of deadfs vnodes, and if there's a lock-free race somewhere,
1127		that case might be handled here.
1128
1129		mac_update_vnode_deadfs(vp);
1130		return (0);
1131 */
1132		/* printf("vn_refreshlabel: null v_mount\n"); */
1133		if (vp->v_type != VNON)
1134			printf(
1135			    "vn_refreshlabel: null v_mount with non-VNON\n");
1136		return (EBADF);
1137	}
1138
1139	if (vp->v_vflag & VV_CACHEDLABEL) {
1140		mac_vnode_label_cache_hits++;
1141		return (0);
1142	} else
1143		mac_vnode_label_cache_misses++;
1144
1145	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1146		mac_update_vnode_from_mount(vp, vp->v_mount);
1147		return (0);
1148	}
1149
1150	error = VOP_REFRESHLABEL(vp, cred, curthread);
1151	switch (error) {
1152	case EOPNOTSUPP:
1153		/*
1154		 * If labels are not supported on this vnode, fall back to
1155		 * the label in the mount and propagate it to the vnode.
1156		 * There should probably be some sort of policy/flag/decision
1157		 * about doing this.
1158		 */
1159		mac_update_vnode_from_mount(vp, vp->v_mount);
1160		error = 0;
1161	default:
1162		return (error);
1163	}
1164}
1165
1166/*
1167 * Helper function for file systems using the vop_std*_ea() calls.  This
1168 * function must be called after EA service is available for the vnode,
1169 * but before it's hooked up to the namespace so that the node persists
1170 * if there's a crash, or before it can be accessed.  On successful
1171 * commit of the label to disk (etc), do cache the label.
1172 */
1173int
1174vop_stdcreatevnode_ea(struct vnode *dvp, struct vnode *tvp, struct ucred *cred)
1175{
1176	struct mac extmac;
1177	int error;
1178
1179	ASSERT_VOP_LOCKED(tvp, "vop_stdcreatevnode_ea");
1180	if ((dvp->v_mount->mnt_flag & MNT_MULTILABEL) == 0) {
1181		mac_update_vnode_from_mount(tvp, tvp->v_mount);
1182	} else {
1183		error = vn_refreshlabel(dvp, cred);
1184		if (error)
1185			return (error);
1186
1187		/*
1188		 * Stick the label in the vnode.  Then try to write to
1189		 * disk.  If we fail, return a failure to abort the
1190		 * create operation.  Really, this failure shouldn't
1191		 * happen except in fairly unusual circumstances (out
1192		 * of disk, etc).
1193		 */
1194		mac_create_vnode(cred, dvp, tvp);
1195
1196		error = mac_stdcreatevnode_ea(tvp);
1197		if (error)
1198			return (error);
1199
1200		/*
1201		 * XXX: Eventually this will go away and all policies will
1202		 * directly manage their extended attributes.
1203		 */
1204		error = mac_externalize(&tvp->v_label, &extmac);
1205		if (error)
1206			return (error);
1207
1208		error = vn_extattr_set(tvp, IO_NODELOCKED,
1209		    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
1210		    sizeof(extmac), (char *)&extmac, curthread);
1211		if (error == 0)
1212			tvp->v_vflag |= VV_CACHEDLABEL;
1213		else {
1214#if 0
1215			/*
1216			 * In theory, we could have fall-back behavior here.
1217			 * It would probably be incorrect.
1218			 */
1219#endif
1220			return (error);
1221		}
1222	}
1223
1224	return (0);
1225}
1226
1227void
1228mac_execve_transition(struct ucred *old, struct ucred *new, struct vnode *vp)
1229{
1230	int error;
1231
1232	ASSERT_VOP_LOCKED(vp, "mac_execve_transition");
1233
1234	error = vn_refreshlabel(vp, old);
1235	if (error) {
1236		printf("mac_execve_transition: vn_refreshlabel returned %d\n",
1237		    error);
1238		printf("mac_execve_transition: using old vnode label\n");
1239	}
1240
1241	MAC_PERFORM(execve_transition, old, new, vp, &vp->v_label);
1242}
1243
1244int
1245mac_execve_will_transition(struct ucred *old, struct vnode *vp)
1246{
1247	int error, result;
1248
1249	error = vn_refreshlabel(vp, old);
1250	if (error)
1251		return (error);
1252
1253	result = 0;
1254	MAC_BOOLEAN(execve_will_transition, ||, old, vp, &vp->v_label);
1255
1256	return (result);
1257}
1258
1259static void
1260mac_init_label(struct label *label)
1261{
1262
1263	bzero(label, sizeof(*label));
1264	label->l_flags = MAC_FLAG_INITIALIZED;
1265}
1266
1267static void
1268mac_init_structmac(struct mac *mac)
1269{
1270
1271	bzero(mac, sizeof(*mac));
1272	mac->m_macflags = MAC_FLAG_INITIALIZED;
1273}
1274
1275static void
1276mac_destroy_label(struct label *label)
1277{
1278
1279	KASSERT(label->l_flags & MAC_FLAG_INITIALIZED,
1280	    ("destroying uninitialized label"));
1281
1282	bzero(label, sizeof(*label));
1283	/* implicit: label->l_flags &= ~MAC_FLAG_INITIALIZED; */
1284}
1285
1286int
1287mac_init_mbuf(struct mbuf *m, int how)
1288{
1289	KASSERT(m->m_flags & M_PKTHDR, ("mac_init_mbuf on non-header mbuf"));
1290
1291	/* "how" is one of M_(TRY|DONT)WAIT */
1292	mac_init_label(&m->m_pkthdr.label);
1293	MAC_PERFORM(init_mbuf, m, how, &m->m_pkthdr.label);
1294#ifdef MAC_DEBUG
1295	atomic_add_int(&nmacmbufs, 1);
1296#endif
1297	return (0);
1298}
1299
1300void
1301mac_destroy_mbuf(struct mbuf *m)
1302{
1303
1304	MAC_PERFORM(destroy_mbuf, m, &m->m_pkthdr.label);
1305	mac_destroy_label(&m->m_pkthdr.label);
1306#ifdef MAC_DEBUG
1307	atomic_subtract_int(&nmacmbufs, 1);
1308#endif
1309}
1310
1311void
1312mac_init_cred(struct ucred *cr)
1313{
1314
1315	mac_init_label(&cr->cr_label);
1316	MAC_PERFORM(init_cred, cr, &cr->cr_label);
1317#ifdef MAC_DEBUG
1318	atomic_add_int(&nmaccreds, 1);
1319#endif
1320}
1321
1322void
1323mac_destroy_cred(struct ucred *cr)
1324{
1325
1326	MAC_PERFORM(destroy_cred, cr, &cr->cr_label);
1327	mac_destroy_label(&cr->cr_label);
1328#ifdef MAC_DEBUG
1329	atomic_subtract_int(&nmaccreds, 1);
1330#endif
1331}
1332
1333void
1334mac_init_ifnet(struct ifnet *ifp)
1335{
1336
1337	mac_init_label(&ifp->if_label);
1338	MAC_PERFORM(init_ifnet, ifp, &ifp->if_label);
1339#ifdef MAC_DEBUG
1340	atomic_add_int(&nmacifnets, 1);
1341#endif
1342}
1343
1344void
1345mac_destroy_ifnet(struct ifnet *ifp)
1346{
1347
1348	MAC_PERFORM(destroy_ifnet, ifp, &ifp->if_label);
1349	mac_destroy_label(&ifp->if_label);
1350#ifdef MAC_DEBUG
1351	atomic_subtract_int(&nmacifnets, 1);
1352#endif
1353}
1354
1355void
1356mac_init_ipq(struct ipq *ipq)
1357{
1358
1359	mac_init_label(&ipq->ipq_label);
1360	MAC_PERFORM(init_ipq, ipq, &ipq->ipq_label);
1361#ifdef MAC_DEBUG
1362	atomic_add_int(&nmacipqs, 1);
1363#endif
1364}
1365
1366void
1367mac_destroy_ipq(struct ipq *ipq)
1368{
1369
1370	MAC_PERFORM(destroy_ipq, ipq, &ipq->ipq_label);
1371	mac_destroy_label(&ipq->ipq_label);
1372#ifdef MAC_DEBUG
1373	atomic_subtract_int(&nmacipqs, 1);
1374#endif
1375}
1376
1377void
1378mac_init_socket(struct socket *socket)
1379{
1380
1381	mac_init_label(&socket->so_label);
1382	mac_init_label(&socket->so_peerlabel);
1383	MAC_PERFORM(init_socket, socket, &socket->so_label,
1384	    &socket->so_peerlabel);
1385#ifdef MAC_DEBUG
1386	atomic_add_int(&nmacsockets, 1);
1387#endif
1388}
1389
1390void
1391mac_destroy_socket(struct socket *socket)
1392{
1393
1394	MAC_PERFORM(destroy_socket, socket, &socket->so_label,
1395	    &socket->so_peerlabel);
1396	mac_destroy_label(&socket->so_label);
1397	mac_destroy_label(&socket->so_peerlabel);
1398#ifdef MAC_DEBUG
1399	atomic_subtract_int(&nmacsockets, 1);
1400#endif
1401}
1402
1403void
1404mac_init_pipe(struct pipe *pipe)
1405{
1406	struct label *label;
1407
1408	label = malloc(sizeof(struct label), M_MACPIPELABEL, M_ZERO|M_WAITOK);
1409	mac_init_label(label);
1410	pipe->pipe_label = label;
1411	pipe->pipe_peer->pipe_label = label;
1412	MAC_PERFORM(init_pipe, pipe, pipe->pipe_label);
1413#ifdef MAC_DEBUG
1414	atomic_add_int(&nmacpipes, 1);
1415#endif
1416}
1417
1418void
1419mac_destroy_pipe(struct pipe *pipe)
1420{
1421
1422	MAC_PERFORM(destroy_pipe, pipe, pipe->pipe_label);
1423	mac_destroy_label(pipe->pipe_label);
1424	free(pipe->pipe_label, M_MACPIPELABEL);
1425#ifdef MAC_DEBUG
1426	atomic_subtract_int(&nmacpipes, 1);
1427#endif
1428}
1429
1430void
1431mac_init_bpfdesc(struct bpf_d *bpf_d)
1432{
1433
1434	mac_init_label(&bpf_d->bd_label);
1435	MAC_PERFORM(init_bpfdesc, bpf_d, &bpf_d->bd_label);
1436#ifdef MAC_DEBUG
1437	atomic_add_int(&nmacbpfdescs, 1);
1438#endif
1439}
1440
1441void
1442mac_destroy_bpfdesc(struct bpf_d *bpf_d)
1443{
1444
1445	MAC_PERFORM(destroy_bpfdesc, bpf_d, &bpf_d->bd_label);
1446	mac_destroy_label(&bpf_d->bd_label);
1447#ifdef MAC_DEBUG
1448	atomic_subtract_int(&nmacbpfdescs, 1);
1449#endif
1450}
1451
1452void
1453mac_init_mount(struct mount *mp)
1454{
1455
1456	mac_init_label(&mp->mnt_mntlabel);
1457	mac_init_label(&mp->mnt_fslabel);
1458	MAC_PERFORM(init_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel);
1459#ifdef MAC_DEBUG
1460	atomic_add_int(&nmacmounts, 1);
1461#endif
1462}
1463
1464void
1465mac_destroy_mount(struct mount *mp)
1466{
1467
1468	MAC_PERFORM(destroy_mount, mp, &mp->mnt_mntlabel, &mp->mnt_fslabel);
1469	mac_destroy_label(&mp->mnt_fslabel);
1470	mac_destroy_label(&mp->mnt_mntlabel);
1471#ifdef MAC_DEBUG
1472	atomic_subtract_int(&nmacmounts, 1);
1473#endif
1474}
1475
1476static void
1477mac_init_temp(struct label *label)
1478{
1479
1480	mac_init_label(label);
1481	MAC_PERFORM(init_temp, label);
1482#ifdef MAC_DEBUG
1483	atomic_add_int(&nmactemp, 1);
1484#endif
1485}
1486
1487static void
1488mac_destroy_temp(struct label *label)
1489{
1490
1491	MAC_PERFORM(destroy_temp, label);
1492	mac_destroy_label(label);
1493#ifdef MAC_DEBUG
1494	atomic_subtract_int(&nmactemp, 1);
1495#endif
1496}
1497
1498void
1499mac_init_vnode(struct vnode *vp)
1500{
1501
1502	mac_init_label(&vp->v_label);
1503	MAC_PERFORM(init_vnode, vp, &vp->v_label);
1504#ifdef MAC_DEBUG
1505	atomic_add_int(&nmacvnodes, 1);
1506#endif
1507}
1508
1509void
1510mac_destroy_vnode(struct vnode *vp)
1511{
1512
1513	MAC_PERFORM(destroy_vnode, vp, &vp->v_label);
1514	mac_destroy_label(&vp->v_label);
1515#ifdef MAC_DEBUG
1516	atomic_subtract_int(&nmacvnodes, 1);
1517#endif
1518}
1519
1520void
1521mac_init_devfsdirent(struct devfs_dirent *de)
1522{
1523
1524	mac_init_label(&de->de_label);
1525	MAC_PERFORM(init_devfsdirent, de, &de->de_label);
1526#ifdef MAC_DEBUG
1527	atomic_add_int(&nmacdevfsdirents, 1);
1528#endif
1529}
1530
1531void
1532mac_destroy_devfsdirent(struct devfs_dirent *de)
1533{
1534
1535	MAC_PERFORM(destroy_devfsdirent, de, &de->de_label);
1536	mac_destroy_label(&de->de_label);
1537#ifdef MAC_DEBUG
1538	atomic_subtract_int(&nmacdevfsdirents, 1);
1539#endif
1540}
1541
1542static int
1543mac_externalize(struct label *label, struct mac *mac)
1544{
1545	int error;
1546
1547	mac_init_structmac(mac);
1548	MAC_CHECK(externalize, label, mac);
1549
1550	return (error);
1551}
1552
1553static int
1554mac_internalize(struct label *label, struct mac *mac)
1555{
1556	int error;
1557
1558	mac_init_temp(label);
1559	MAC_CHECK(internalize, label, mac);
1560	if (error)
1561		mac_destroy_temp(label);
1562
1563	return (error);
1564}
1565
1566/*
1567 * Initialize MAC label for the first kernel process, from which other
1568 * kernel processes and threads are spawned.
1569 */
1570void
1571mac_create_proc0(struct ucred *cred)
1572{
1573
1574	MAC_PERFORM(create_proc0, cred);
1575}
1576
1577/*
1578 * Initialize MAC label for the first userland process, from which other
1579 * userland processes and threads are spawned.
1580 */
1581void
1582mac_create_proc1(struct ucred *cred)
1583{
1584
1585	MAC_PERFORM(create_proc1, cred);
1586}
1587
1588void
1589mac_thread_userret(struct thread *td)
1590{
1591
1592	MAC_PERFORM(thread_userret, td);
1593}
1594
1595/*
1596 * When a new process is created, its label must be initialized.  Generally,
1597 * this involves inheritence from the parent process, modulo possible
1598 * deltas.  This function allows that processing to take place.
1599 */
1600void
1601mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1602{
1603
1604	MAC_PERFORM(create_cred, parent_cred, child_cred);
1605}
1606
1607int
1608mac_check_vnode_access(struct ucred *cred, struct vnode *vp, int flags)
1609{
1610	int error;
1611
1612	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_access");
1613
1614	if (!mac_enforce_fs)
1615		return (0);
1616
1617	error = vn_refreshlabel(vp, cred);
1618	if (error)
1619		return (error);
1620
1621	MAC_CHECK(check_vnode_access, cred, vp, &vp->v_label, flags);
1622	return (error);
1623}
1624
1625int
1626mac_check_vnode_chdir(struct ucred *cred, struct vnode *dvp)
1627{
1628	int error;
1629
1630	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chdir");
1631
1632	if (!mac_enforce_fs)
1633		return (0);
1634
1635	error = vn_refreshlabel(dvp, cred);
1636	if (error)
1637		return (error);
1638
1639	MAC_CHECK(check_vnode_chdir, cred, dvp, &dvp->v_label);
1640	return (error);
1641}
1642
1643int
1644mac_check_vnode_chroot(struct ucred *cred, struct vnode *dvp)
1645{
1646	int error;
1647
1648	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_chroot");
1649
1650	if (!mac_enforce_fs)
1651		return (0);
1652
1653	error = vn_refreshlabel(dvp, cred);
1654	if (error)
1655		return (error);
1656
1657	MAC_CHECK(check_vnode_chroot, cred, dvp, &dvp->v_label);
1658	return (error);
1659}
1660
1661int
1662mac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1663    struct componentname *cnp, struct vattr *vap)
1664{
1665	int error;
1666
1667	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_create");
1668
1669	if (!mac_enforce_fs)
1670		return (0);
1671
1672	error = vn_refreshlabel(dvp, cred);
1673	if (error)
1674		return (error);
1675
1676	MAC_CHECK(check_vnode_create, cred, dvp, &dvp->v_label, cnp, vap);
1677	return (error);
1678}
1679
1680int
1681mac_check_vnode_delete(struct ucred *cred, struct vnode *dvp, struct vnode *vp,
1682    struct componentname *cnp)
1683{
1684	int error;
1685
1686	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_delete");
1687	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_delete");
1688
1689	if (!mac_enforce_fs)
1690		return (0);
1691
1692	error = vn_refreshlabel(dvp, cred);
1693	if (error)
1694		return (error);
1695	error = vn_refreshlabel(vp, cred);
1696	if (error)
1697		return (error);
1698
1699	MAC_CHECK(check_vnode_delete, cred, dvp, &dvp->v_label, vp,
1700	    &vp->v_label, cnp);
1701	return (error);
1702}
1703
1704int
1705mac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1706    acl_type_t type)
1707{
1708	int error;
1709
1710	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_deleteacl");
1711
1712	if (!mac_enforce_fs)
1713		return (0);
1714
1715	error = vn_refreshlabel(vp, cred);
1716	if (error)
1717		return (error);
1718
1719	MAC_CHECK(check_vnode_deleteacl, cred, vp, &vp->v_label, type);
1720	return (error);
1721}
1722
1723int
1724mac_check_vnode_exec(struct ucred *cred, struct vnode *vp)
1725{
1726	int error;
1727
1728	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_exec");
1729
1730	if (!mac_enforce_process && !mac_enforce_fs)
1731		return (0);
1732
1733	error = vn_refreshlabel(vp, cred);
1734	if (error)
1735		return (error);
1736	MAC_CHECK(check_vnode_exec, cred, vp, &vp->v_label);
1737
1738	return (error);
1739}
1740
1741int
1742mac_check_vnode_getacl(struct ucred *cred, struct vnode *vp, acl_type_t type)
1743{
1744	int error;
1745
1746	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getacl");
1747
1748	if (!mac_enforce_fs)
1749		return (0);
1750
1751	error = vn_refreshlabel(vp, cred);
1752	if (error)
1753		return (error);
1754
1755	MAC_CHECK(check_vnode_getacl, cred, vp, &vp->v_label, type);
1756	return (error);
1757}
1758
1759int
1760mac_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1761    int attrnamespace, const char *name, struct uio *uio)
1762{
1763	int error;
1764
1765	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_getextattr");
1766
1767	if (!mac_enforce_fs)
1768		return (0);
1769
1770	error = vn_refreshlabel(vp, cred);
1771	if (error)
1772		return (error);
1773
1774	MAC_CHECK(check_vnode_getextattr, cred, vp, &vp->v_label,
1775	    attrnamespace, name, uio);
1776	return (error);
1777}
1778
1779int
1780mac_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1781    struct componentname *cnp)
1782{
1783	int error;
1784
1785	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_lookup");
1786
1787	if (!mac_enforce_fs)
1788		return (0);
1789
1790	error = vn_refreshlabel(dvp, cred);
1791	if (error)
1792		return (error);
1793
1794	MAC_CHECK(check_vnode_lookup, cred, dvp, &dvp->v_label, cnp);
1795	return (error);
1796}
1797
1798vm_prot_t
1799mac_check_vnode_mmap_prot(struct ucred *cred, struct vnode *vp, int newmapping)
1800{
1801	vm_prot_t result = VM_PROT_ALL;
1802
1803	if (!mac_enforce_vm)
1804		return (result);
1805
1806	/*
1807	 * This should be some sort of MAC_BITWISE, maybe :)
1808	 */
1809	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_mmap_perms");
1810	MAC_BOOLEAN(check_vnode_mmap_perms, &, cred, vp, &vp->v_label,
1811	    newmapping);
1812	return (result);
1813}
1814
1815int
1816mac_check_vnode_open(struct ucred *cred, struct vnode *vp, mode_t acc_mode)
1817{
1818	int error;
1819
1820	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_open");
1821
1822	if (!mac_enforce_fs)
1823		return (0);
1824
1825	error = vn_refreshlabel(vp, cred);
1826	if (error)
1827		return (error);
1828
1829	MAC_CHECK(check_vnode_open, cred, vp, &vp->v_label, acc_mode);
1830	return (error);
1831}
1832
1833int
1834mac_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
1835    struct vnode *vp)
1836{
1837	int error;
1838
1839	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_poll");
1840
1841	if (!mac_enforce_fs)
1842		return (0);
1843
1844	error = vn_refreshlabel(vp, active_cred);
1845	if (error)
1846		return (error);
1847
1848	MAC_CHECK(check_vnode_poll, active_cred, file_cred, vp,
1849	    &vp->v_label);
1850
1851	return (error);
1852}
1853
1854int
1855mac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
1856    struct vnode *vp)
1857{
1858	int error;
1859
1860	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_read");
1861
1862	if (!mac_enforce_fs)
1863		return (0);
1864
1865	error = vn_refreshlabel(vp, active_cred);
1866	if (error)
1867		return (error);
1868
1869	MAC_CHECK(check_vnode_read, active_cred, file_cred, vp,
1870	    &vp->v_label);
1871
1872	return (error);
1873}
1874
1875int
1876mac_check_vnode_readdir(struct ucred *cred, struct vnode *dvp)
1877{
1878	int error;
1879
1880	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_readdir");
1881
1882	if (!mac_enforce_fs)
1883		return (0);
1884
1885	error = vn_refreshlabel(dvp, cred);
1886	if (error)
1887		return (error);
1888
1889	MAC_CHECK(check_vnode_readdir, cred, dvp, &dvp->v_label);
1890	return (error);
1891}
1892
1893int
1894mac_check_vnode_readlink(struct ucred *cred, struct vnode *vp)
1895{
1896	int error;
1897
1898	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_readlink");
1899
1900	if (!mac_enforce_fs)
1901		return (0);
1902
1903	error = vn_refreshlabel(vp, cred);
1904	if (error)
1905		return (error);
1906
1907	MAC_CHECK(check_vnode_readlink, cred, vp, &vp->v_label);
1908	return (error);
1909}
1910
1911static int
1912mac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
1913    struct label *newlabel)
1914{
1915	int error;
1916
1917	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_relabel");
1918
1919	error = vn_refreshlabel(vp, cred);
1920	if (error)
1921		return (error);
1922
1923	MAC_CHECK(check_vnode_relabel, cred, vp, &vp->v_label, newlabel);
1924
1925	return (error);
1926}
1927
1928int
1929mac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
1930    struct vnode *vp, struct componentname *cnp)
1931{
1932	int error;
1933
1934	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_from");
1935	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_from");
1936
1937	if (!mac_enforce_fs)
1938		return (0);
1939
1940	error = vn_refreshlabel(dvp, cred);
1941	if (error)
1942		return (error);
1943	error = vn_refreshlabel(vp, cred);
1944	if (error)
1945		return (error);
1946
1947	MAC_CHECK(check_vnode_rename_from, cred, dvp, &dvp->v_label, vp,
1948	    &vp->v_label, cnp);
1949	return (error);
1950}
1951
1952int
1953mac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
1954    struct vnode *vp, int samedir, struct componentname *cnp)
1955{
1956	int error;
1957
1958	ASSERT_VOP_LOCKED(dvp, "mac_check_vnode_rename_to");
1959	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_rename_to");
1960
1961	if (!mac_enforce_fs)
1962		return (0);
1963
1964	error = vn_refreshlabel(dvp, cred);
1965	if (error)
1966		return (error);
1967	if (vp != NULL) {
1968		error = vn_refreshlabel(vp, cred);
1969		if (error)
1970			return (error);
1971	}
1972	MAC_CHECK(check_vnode_rename_to, cred, dvp, &dvp->v_label, vp,
1973	    vp != NULL ? &vp->v_label : NULL, samedir, cnp);
1974	return (error);
1975}
1976
1977int
1978mac_check_vnode_revoke(struct ucred *cred, struct vnode *vp)
1979{
1980	int error;
1981
1982	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_revoke");
1983
1984	if (!mac_enforce_fs)
1985		return (0);
1986
1987	error = vn_refreshlabel(vp, cred);
1988	if (error)
1989		return (error);
1990
1991	MAC_CHECK(check_vnode_revoke, cred, vp, &vp->v_label);
1992	return (error);
1993}
1994
1995int
1996mac_check_vnode_setacl(struct ucred *cred, struct vnode *vp, acl_type_t type,
1997    struct acl *acl)
1998{
1999	int error;
2000
2001	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setacl");
2002
2003	if (!mac_enforce_fs)
2004		return (0);
2005
2006	error = vn_refreshlabel(vp, cred);
2007	if (error)
2008		return (error);
2009
2010	MAC_CHECK(check_vnode_setacl, cred, vp, &vp->v_label, type, acl);
2011	return (error);
2012}
2013
2014int
2015mac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2016    int attrnamespace, const char *name, struct uio *uio)
2017{
2018	int error;
2019
2020	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setextattr");
2021
2022	if (!mac_enforce_fs)
2023		return (0);
2024
2025	error = vn_refreshlabel(vp, cred);
2026	if (error)
2027		return (error);
2028
2029	MAC_CHECK(check_vnode_setextattr, cred, vp, &vp->v_label,
2030	    attrnamespace, name, uio);
2031	return (error);
2032}
2033
2034int
2035mac_check_vnode_setflags(struct ucred *cred, struct vnode *vp, u_long flags)
2036{
2037	int error;
2038
2039	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setflags");
2040
2041	if (!mac_enforce_fs)
2042		return (0);
2043
2044	error = vn_refreshlabel(vp, cred);
2045	if (error)
2046		return (error);
2047
2048	MAC_CHECK(check_vnode_setflags, cred, vp, &vp->v_label, flags);
2049	return (error);
2050}
2051
2052int
2053mac_check_vnode_setmode(struct ucred *cred, struct vnode *vp, mode_t mode)
2054{
2055	int error;
2056
2057	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setmode");
2058
2059	if (!mac_enforce_fs)
2060		return (0);
2061
2062	error = vn_refreshlabel(vp, cred);
2063	if (error)
2064		return (error);
2065
2066	MAC_CHECK(check_vnode_setmode, cred, vp, &vp->v_label, mode);
2067	return (error);
2068}
2069
2070int
2071mac_check_vnode_setowner(struct ucred *cred, struct vnode *vp, uid_t uid,
2072    gid_t gid)
2073{
2074	int error;
2075
2076	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setowner");
2077
2078	if (!mac_enforce_fs)
2079		return (0);
2080
2081	error = vn_refreshlabel(vp, cred);
2082	if (error)
2083		return (error);
2084
2085	MAC_CHECK(check_vnode_setowner, cred, vp, &vp->v_label, uid, gid);
2086	return (error);
2087}
2088
2089int
2090mac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2091    struct timespec atime, struct timespec mtime)
2092{
2093	int error;
2094
2095	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_setutimes");
2096
2097	if (!mac_enforce_fs)
2098		return (0);
2099
2100	error = vn_refreshlabel(vp, cred);
2101	if (error)
2102		return (error);
2103
2104	MAC_CHECK(check_vnode_setutimes, cred, vp, &vp->v_label, atime,
2105	    mtime);
2106	return (error);
2107}
2108
2109int
2110mac_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2111    struct vnode *vp)
2112{
2113	int error;
2114
2115	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_stat");
2116
2117	if (!mac_enforce_fs)
2118		return (0);
2119
2120	error = vn_refreshlabel(vp, active_cred);
2121	if (error)
2122		return (error);
2123
2124	MAC_CHECK(check_vnode_stat, active_cred, file_cred, vp,
2125	    &vp->v_label);
2126	return (error);
2127}
2128
2129int
2130mac_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2131    struct vnode *vp)
2132{
2133	int error;
2134
2135	ASSERT_VOP_LOCKED(vp, "mac_check_vnode_write");
2136
2137	if (!mac_enforce_fs)
2138		return (0);
2139
2140	error = vn_refreshlabel(vp, active_cred);
2141	if (error)
2142		return (error);
2143
2144	MAC_CHECK(check_vnode_write, active_cred, file_cred, vp,
2145	    &vp->v_label);
2146
2147	return (error);
2148}
2149
2150/*
2151 * When relabeling a process, call out to the policies for the maximum
2152 * permission allowed for each object type we know about in its
2153 * memory space, and revoke access (in the least surprising ways we
2154 * know) when necessary.  The process lock is not held here.
2155 */
2156static void
2157mac_cred_mmapped_drop_perms(struct thread *td, struct ucred *cred)
2158{
2159
2160	/* XXX freeze all other threads */
2161	mac_cred_mmapped_drop_perms_recurse(td, cred,
2162	    &td->td_proc->p_vmspace->vm_map);
2163	/* XXX allow other threads to continue */
2164}
2165
2166static __inline const char *
2167prot2str(vm_prot_t prot)
2168{
2169
2170	switch (prot & VM_PROT_ALL) {
2171	case VM_PROT_READ:
2172		return ("r--");
2173	case VM_PROT_READ | VM_PROT_WRITE:
2174		return ("rw-");
2175	case VM_PROT_READ | VM_PROT_EXECUTE:
2176		return ("r-x");
2177	case VM_PROT_READ | VM_PROT_WRITE | VM_PROT_EXECUTE:
2178		return ("rwx");
2179	case VM_PROT_WRITE:
2180		return ("-w-");
2181	case VM_PROT_EXECUTE:
2182		return ("--x");
2183	case VM_PROT_WRITE | VM_PROT_EXECUTE:
2184		return ("-wx");
2185	default:
2186		return ("---");
2187	}
2188}
2189
2190static void
2191mac_cred_mmapped_drop_perms_recurse(struct thread *td, struct ucred *cred,
2192    struct vm_map *map)
2193{
2194	struct vm_map_entry *vme;
2195	vm_prot_t result, revokeperms;
2196	vm_object_t object;
2197	vm_ooffset_t offset;
2198	struct vnode *vp;
2199
2200	if (!mac_mmap_revocation)
2201		return;
2202
2203	vm_map_lock_read(map);
2204	for (vme = map->header.next; vme != &map->header; vme = vme->next) {
2205		if (vme->eflags & MAP_ENTRY_IS_SUB_MAP) {
2206			mac_cred_mmapped_drop_perms_recurse(td, cred,
2207			    vme->object.sub_map);
2208			continue;
2209		}
2210		/*
2211		 * Skip over entries that obviously are not shared.
2212		 */
2213		if (vme->eflags & (MAP_ENTRY_COW | MAP_ENTRY_NOSYNC) ||
2214		    !vme->max_protection)
2215			continue;
2216		/*
2217		 * Drill down to the deepest backing object.
2218		 */
2219		offset = vme->offset;
2220		object = vme->object.vm_object;
2221		if (object == NULL)
2222			continue;
2223		while (object->backing_object != NULL) {
2224			object = object->backing_object;
2225			offset += object->backing_object_offset;
2226		}
2227		/*
2228		 * At the moment, vm_maps and objects aren't considered
2229		 * by the MAC system, so only things with backing by a
2230		 * normal object (read: vnodes) are checked.
2231		 */
2232		if (object->type != OBJT_VNODE)
2233			continue;
2234		vp = (struct vnode *)object->handle;
2235		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2236		result = mac_check_vnode_mmap_prot(cred, vp, 0);
2237		VOP_UNLOCK(vp, 0, td);
2238		/*
2239		 * Find out what maximum protection we may be allowing
2240		 * now but a policy needs to get removed.
2241		 */
2242		revokeperms = vme->max_protection & ~result;
2243		if (!revokeperms)
2244			continue;
2245		printf("pid %ld: revoking %s perms from %#lx:%ld "
2246		    "(max %s/cur %s)\n", (long)td->td_proc->p_pid,
2247		    prot2str(revokeperms), (u_long)vme->start,
2248		    (long)(vme->end - vme->start),
2249		    prot2str(vme->max_protection), prot2str(vme->protection));
2250		vm_map_lock_upgrade(map);
2251		/*
2252		 * This is the really simple case: if a map has more
2253		 * max_protection than is allowed, but it's not being
2254		 * actually used (that is, the current protection is
2255		 * still allowed), we can just wipe it out and do
2256		 * nothing more.
2257		 */
2258		if ((vme->protection & revokeperms) == 0) {
2259			vme->max_protection -= revokeperms;
2260		} else {
2261			if (revokeperms & VM_PROT_WRITE) {
2262				/*
2263				 * In the more complicated case, flush out all
2264				 * pending changes to the object then turn it
2265				 * copy-on-write.
2266				 */
2267				vm_object_reference(object);
2268				vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
2269				vm_object_page_clean(object,
2270				    OFF_TO_IDX(offset),
2271				    OFF_TO_IDX(offset + vme->end - vme->start +
2272					PAGE_MASK),
2273				    OBJPC_SYNC);
2274				VOP_UNLOCK(vp, 0, td);
2275				vm_object_deallocate(object);
2276				/*
2277				 * Why bother if there's no read permissions
2278				 * anymore?  For the rest, we need to leave
2279				 * the write permissions on for COW, or
2280				 * remove them entirely if configured to.
2281				 */
2282				if (!mac_mmap_revocation_via_cow) {
2283					vme->max_protection &= ~VM_PROT_WRITE;
2284					vme->protection &= ~VM_PROT_WRITE;
2285				} if ((revokeperms & VM_PROT_READ) == 0)
2286					vme->eflags |= MAP_ENTRY_COW |
2287					    MAP_ENTRY_NEEDS_COPY;
2288			}
2289			if (revokeperms & VM_PROT_EXECUTE) {
2290				vme->max_protection &= ~VM_PROT_EXECUTE;
2291				vme->protection &= ~VM_PROT_EXECUTE;
2292			}
2293			if (revokeperms & VM_PROT_READ) {
2294				vme->max_protection = 0;
2295				vme->protection = 0;
2296			}
2297			pmap_protect(map->pmap, vme->start, vme->end,
2298			    vme->protection & ~revokeperms);
2299			vm_map_simplify_entry(map, vme);
2300		}
2301		vm_map_lock_downgrade(map);
2302	}
2303	vm_map_unlock_read(map);
2304}
2305
2306/*
2307 * When the subject's label changes, it may require revocation of privilege
2308 * to mapped objects.  This can't be done on-the-fly later with a unified
2309 * buffer cache.
2310 */
2311static void
2312mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2313{
2314
2315	MAC_PERFORM(relabel_cred, cred, newlabel);
2316}
2317
2318void
2319mac_relabel_vnode(struct ucred *cred, struct vnode *vp, struct label *newlabel)
2320{
2321
2322	MAC_PERFORM(relabel_vnode, cred, vp, &vp->v_label, newlabel);
2323}
2324
2325void
2326mac_create_ifnet(struct ifnet *ifnet)
2327{
2328
2329	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2330}
2331
2332void
2333mac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d)
2334{
2335
2336	MAC_PERFORM(create_bpfdesc, cred, bpf_d, &bpf_d->bd_label);
2337}
2338
2339void
2340mac_create_socket(struct ucred *cred, struct socket *socket)
2341{
2342
2343	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2344}
2345
2346void
2347mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2348{
2349
2350	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2351}
2352
2353void
2354mac_create_socket_from_socket(struct socket *oldsocket,
2355    struct socket *newsocket)
2356{
2357
2358	MAC_PERFORM(create_socket_from_socket, oldsocket, &oldsocket->so_label,
2359	    newsocket, &newsocket->so_label);
2360}
2361
2362static void
2363mac_relabel_socket(struct ucred *cred, struct socket *socket,
2364    struct label *newlabel)
2365{
2366
2367	MAC_PERFORM(relabel_socket, cred, socket, &socket->so_label, newlabel);
2368}
2369
2370static void
2371mac_relabel_pipe(struct ucred *cred, struct pipe *pipe, struct label *newlabel)
2372{
2373
2374	MAC_PERFORM(relabel_pipe, cred, pipe, pipe->pipe_label, newlabel);
2375}
2376
2377void
2378mac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct socket *socket)
2379{
2380
2381	MAC_PERFORM(set_socket_peer_from_mbuf, mbuf, &mbuf->m_pkthdr.label,
2382	    socket, &socket->so_peerlabel);
2383}
2384
2385void
2386mac_set_socket_peer_from_socket(struct socket *oldsocket,
2387    struct socket *newsocket)
2388{
2389
2390	MAC_PERFORM(set_socket_peer_from_socket, oldsocket,
2391	    &oldsocket->so_label, newsocket, &newsocket->so_peerlabel);
2392}
2393
2394void
2395mac_create_datagram_from_ipq(struct ipq *ipq, struct mbuf *datagram)
2396{
2397
2398	MAC_PERFORM(create_datagram_from_ipq, ipq, &ipq->ipq_label,
2399	    datagram, &datagram->m_pkthdr.label);
2400}
2401
2402void
2403mac_create_fragment(struct mbuf *datagram, struct mbuf *fragment)
2404{
2405
2406	MAC_PERFORM(create_fragment, datagram, &datagram->m_pkthdr.label,
2407	    fragment, &fragment->m_pkthdr.label);
2408}
2409
2410void
2411mac_create_ipq(struct mbuf *fragment, struct ipq *ipq)
2412{
2413
2414	MAC_PERFORM(create_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2415	    &ipq->ipq_label);
2416}
2417
2418void
2419mac_create_mbuf_from_mbuf(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2420{
2421
2422	MAC_PERFORM(create_mbuf_from_mbuf, oldmbuf, &oldmbuf->m_pkthdr.label,
2423	    newmbuf, &newmbuf->m_pkthdr.label);
2424}
2425
2426void
2427mac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct mbuf *mbuf)
2428{
2429
2430	MAC_PERFORM(create_mbuf_from_bpfdesc, bpf_d, &bpf_d->bd_label, mbuf,
2431	    &mbuf->m_pkthdr.label);
2432}
2433
2434void
2435mac_create_mbuf_linklayer(struct ifnet *ifnet, struct mbuf *mbuf)
2436{
2437
2438	MAC_PERFORM(create_mbuf_linklayer, ifnet, &ifnet->if_label, mbuf,
2439	    &mbuf->m_pkthdr.label);
2440}
2441
2442void
2443mac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct mbuf *mbuf)
2444{
2445
2446	MAC_PERFORM(create_mbuf_from_ifnet, ifnet, &ifnet->if_label, mbuf,
2447	    &mbuf->m_pkthdr.label);
2448}
2449
2450void
2451mac_create_mbuf_multicast_encap(struct mbuf *oldmbuf, struct ifnet *ifnet,
2452    struct mbuf *newmbuf)
2453{
2454
2455	MAC_PERFORM(create_mbuf_multicast_encap, oldmbuf,
2456	    &oldmbuf->m_pkthdr.label, ifnet, &ifnet->if_label, newmbuf,
2457	    &newmbuf->m_pkthdr.label);
2458}
2459
2460void
2461mac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct mbuf *newmbuf)
2462{
2463
2464	MAC_PERFORM(create_mbuf_netlayer, oldmbuf, &oldmbuf->m_pkthdr.label,
2465	    newmbuf, &newmbuf->m_pkthdr.label);
2466}
2467
2468int
2469mac_fragment_match(struct mbuf *fragment, struct ipq *ipq)
2470{
2471	int result;
2472
2473	result = 1;
2474	MAC_BOOLEAN(fragment_match, &&, fragment, &fragment->m_pkthdr.label,
2475	    ipq, &ipq->ipq_label);
2476
2477	return (result);
2478}
2479
2480void
2481mac_update_ipq(struct mbuf *fragment, struct ipq *ipq)
2482{
2483
2484	MAC_PERFORM(update_ipq, fragment, &fragment->m_pkthdr.label, ipq,
2485	    &ipq->ipq_label);
2486}
2487
2488void
2489mac_create_mbuf_from_socket(struct socket *socket, struct mbuf *mbuf)
2490{
2491
2492	MAC_PERFORM(create_mbuf_from_socket, socket, &socket->so_label, mbuf,
2493	    &mbuf->m_pkthdr.label);
2494}
2495
2496void
2497mac_create_mount(struct ucred *cred, struct mount *mp)
2498{
2499
2500	MAC_PERFORM(create_mount, cred, mp, &mp->mnt_mntlabel,
2501	    &mp->mnt_fslabel);
2502}
2503
2504void
2505mac_create_root_mount(struct ucred *cred, struct mount *mp)
2506{
2507
2508	MAC_PERFORM(create_root_mount, cred, mp, &mp->mnt_mntlabel,
2509	    &mp->mnt_fslabel);
2510}
2511
2512int
2513mac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct ifnet *ifnet)
2514{
2515	int error;
2516
2517	if (!mac_enforce_network)
2518		return (0);
2519
2520	MAC_CHECK(check_bpfdesc_receive, bpf_d, &bpf_d->bd_label, ifnet,
2521	    &ifnet->if_label);
2522
2523	return (error);
2524}
2525
2526static int
2527mac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
2528{
2529	int error;
2530
2531	MAC_CHECK(check_cred_relabel, cred, newlabel);
2532
2533	return (error);
2534}
2535
2536int
2537mac_check_cred_visible(struct ucred *u1, struct ucred *u2)
2538{
2539	int error;
2540
2541	if (!mac_enforce_process)
2542		return (0);
2543
2544	MAC_CHECK(check_cred_visible, u1, u2);
2545
2546	return (error);
2547}
2548
2549int
2550mac_check_ifnet_transmit(struct ifnet *ifnet, struct mbuf *mbuf)
2551{
2552	int error;
2553
2554	if (!mac_enforce_network)
2555		return (0);
2556
2557	KASSERT(mbuf->m_flags & M_PKTHDR, ("packet has no pkthdr"));
2558	if (!(mbuf->m_pkthdr.label.l_flags & MAC_FLAG_INITIALIZED))
2559		printf("%s%d: not initialized\n", ifnet->if_name,
2560		    ifnet->if_unit);
2561
2562	MAC_CHECK(check_ifnet_transmit, ifnet, &ifnet->if_label, mbuf,
2563	    &mbuf->m_pkthdr.label);
2564
2565	return (error);
2566}
2567
2568int
2569mac_check_mount_stat(struct ucred *cred, struct mount *mount)
2570{
2571	int error;
2572
2573	if (!mac_enforce_fs)
2574		return (0);
2575
2576	MAC_CHECK(check_mount_stat, cred, mount, &mount->mnt_mntlabel);
2577
2578	return (error);
2579}
2580
2581int
2582mac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe, unsigned long cmd,
2583    void *data)
2584{
2585	int error;
2586
2587	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2588
2589	if (!mac_enforce_pipe)
2590		return (0);
2591
2592	MAC_CHECK(check_pipe_ioctl, cred, pipe, pipe->pipe_label, cmd, data);
2593
2594	return (error);
2595}
2596
2597int
2598mac_check_pipe_poll(struct ucred *cred, struct pipe *pipe)
2599{
2600	int error;
2601
2602	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2603
2604	if (!mac_enforce_pipe)
2605		return (0);
2606
2607	MAC_CHECK(check_pipe_poll, cred, pipe, pipe->pipe_label);
2608
2609	return (error);
2610}
2611
2612int
2613mac_check_pipe_read(struct ucred *cred, struct pipe *pipe)
2614{
2615	int error;
2616
2617	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2618
2619	if (!mac_enforce_pipe)
2620		return (0);
2621
2622	MAC_CHECK(check_pipe_read, cred, pipe, pipe->pipe_label);
2623
2624	return (error);
2625}
2626
2627static int
2628mac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
2629    struct label *newlabel)
2630{
2631	int error;
2632
2633	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2634
2635	if (!mac_enforce_pipe)
2636		return (0);
2637
2638	MAC_CHECK(check_pipe_relabel, cred, pipe, pipe->pipe_label, newlabel);
2639
2640	return (error);
2641}
2642
2643int
2644mac_check_pipe_stat(struct ucred *cred, struct pipe *pipe)
2645{
2646	int error;
2647
2648	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2649
2650	if (!mac_enforce_pipe)
2651		return (0);
2652
2653	MAC_CHECK(check_pipe_stat, cred, pipe, pipe->pipe_label);
2654
2655	return (error);
2656}
2657
2658int
2659mac_check_pipe_write(struct ucred *cred, struct pipe *pipe)
2660{
2661	int error;
2662
2663	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2664
2665	if (!mac_enforce_pipe)
2666		return (0);
2667
2668	MAC_CHECK(check_pipe_write, cred, pipe, pipe->pipe_label);
2669
2670	return (error);
2671}
2672
2673int
2674mac_check_proc_debug(struct ucred *cred, struct proc *proc)
2675{
2676	int error;
2677
2678	PROC_LOCK_ASSERT(proc, MA_OWNED);
2679
2680	if (!mac_enforce_process)
2681		return (0);
2682
2683	MAC_CHECK(check_proc_debug, cred, proc);
2684
2685	return (error);
2686}
2687
2688int
2689mac_check_proc_sched(struct ucred *cred, struct proc *proc)
2690{
2691	int error;
2692
2693	PROC_LOCK_ASSERT(proc, MA_OWNED);
2694
2695	if (!mac_enforce_process)
2696		return (0);
2697
2698	MAC_CHECK(check_proc_sched, cred, proc);
2699
2700	return (error);
2701}
2702
2703int
2704mac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2705{
2706	int error;
2707
2708	PROC_LOCK_ASSERT(proc, MA_OWNED);
2709
2710	if (!mac_enforce_process)
2711		return (0);
2712
2713	MAC_CHECK(check_proc_signal, cred, proc, signum);
2714
2715	return (error);
2716}
2717
2718int
2719mac_check_socket_bind(struct ucred *ucred, struct socket *socket,
2720    struct sockaddr *sockaddr)
2721{
2722	int error;
2723
2724	if (!mac_enforce_socket)
2725		return (0);
2726
2727	MAC_CHECK(check_socket_bind, ucred, socket, &socket->so_label,
2728	    sockaddr);
2729
2730	return (error);
2731}
2732
2733int
2734mac_check_socket_connect(struct ucred *cred, struct socket *socket,
2735    struct sockaddr *sockaddr)
2736{
2737	int error;
2738
2739	if (!mac_enforce_socket)
2740		return (0);
2741
2742	MAC_CHECK(check_socket_connect, cred, socket, &socket->so_label,
2743	    sockaddr);
2744
2745	return (error);
2746}
2747
2748int
2749mac_check_socket_deliver(struct socket *socket, struct mbuf *mbuf)
2750{
2751	int error;
2752
2753	if (!mac_enforce_socket)
2754		return (0);
2755
2756	MAC_CHECK(check_socket_deliver, socket, &socket->so_label, mbuf,
2757	    &mbuf->m_pkthdr.label);
2758
2759	return (error);
2760}
2761
2762int
2763mac_check_socket_listen(struct ucred *cred, struct socket *socket)
2764{
2765	int error;
2766
2767	if (!mac_enforce_socket)
2768		return (0);
2769
2770	MAC_CHECK(check_socket_listen, cred, socket, &socket->so_label);
2771	return (error);
2772}
2773
2774static int
2775mac_check_socket_relabel(struct ucred *cred, struct socket *socket,
2776    struct label *newlabel)
2777{
2778	int error;
2779
2780	MAC_CHECK(check_socket_relabel, cred, socket, &socket->so_label,
2781	    newlabel);
2782
2783	return (error);
2784}
2785
2786int
2787mac_check_socket_visible(struct ucred *cred, struct socket *socket)
2788{
2789	int error;
2790
2791	if (!mac_enforce_socket)
2792		return (0);
2793
2794	MAC_CHECK(check_socket_visible, cred, socket, &socket->so_label);
2795
2796	return (error);
2797}
2798
2799int
2800mac_ioctl_ifnet_get(struct ucred *cred, struct ifreq *ifr,
2801    struct ifnet *ifnet)
2802{
2803	struct mac label;
2804	int error;
2805
2806	error = mac_externalize(&ifnet->if_label, &label);
2807	if (error)
2808		return (error);
2809
2810	return (copyout(&label, ifr->ifr_ifru.ifru_data, sizeof(label)));
2811}
2812
2813int
2814mac_ioctl_ifnet_set(struct ucred *cred, struct ifreq *ifr,
2815    struct ifnet *ifnet)
2816{
2817	struct mac newlabel;
2818	struct label intlabel;
2819	int error;
2820
2821	error = copyin(ifr->ifr_ifru.ifru_data, &newlabel, sizeof(newlabel));
2822	if (error)
2823		return (error);
2824
2825	error = mac_internalize(&intlabel, &newlabel);
2826	if (error)
2827		return (error);
2828
2829	/*
2830	 * XXX: Note that this is a redundant privilege check, since
2831	 * policies impose this check themselves if required by the
2832	 * policy.  Eventually, this should go away.
2833	 */
2834	error = suser_cred(cred, 0);
2835	if (error)
2836		goto out;
2837
2838	MAC_CHECK(check_ifnet_relabel, cred, ifnet, &ifnet->if_label,
2839	    &intlabel);
2840	if (error)
2841		goto out;
2842
2843	MAC_PERFORM(relabel_ifnet, cred, ifnet, &ifnet->if_label, &intlabel);
2844
2845out:
2846	mac_destroy_temp(&intlabel);
2847	return (error);
2848}
2849
2850void
2851mac_create_devfs_vnode(struct devfs_dirent *de, struct vnode *vp)
2852{
2853
2854	MAC_PERFORM(create_devfs_vnode, de, &de->de_label, vp, &vp->v_label);
2855}
2856
2857void
2858mac_create_devfs_device(dev_t dev, struct devfs_dirent *de)
2859{
2860
2861	MAC_PERFORM(create_devfs_device, dev, de, &de->de_label);
2862}
2863
2864static int
2865mac_stdcreatevnode_ea(struct vnode *vp)
2866{
2867	int error;
2868
2869	MAC_CHECK(stdcreatevnode_ea, vp, &vp->v_label);
2870
2871	return (error);
2872}
2873
2874void
2875mac_create_devfs_directory(char *dirname, int dirnamelen,
2876    struct devfs_dirent *de)
2877{
2878
2879	MAC_PERFORM(create_devfs_directory, dirname, dirnamelen, de,
2880	    &de->de_label);
2881}
2882
2883/*
2884 * When a new vnode is created, this call will initialize its label.
2885 */
2886void
2887mac_create_vnode(struct ucred *cred, struct vnode *parent,
2888    struct vnode *child)
2889{
2890	int error;
2891
2892	ASSERT_VOP_LOCKED(parent, "mac_create_vnode");
2893	ASSERT_VOP_LOCKED(child, "mac_create_vnode");
2894
2895	error = vn_refreshlabel(parent, cred);
2896	if (error) {
2897		printf("mac_create_vnode: vn_refreshlabel returned %d\n",
2898		    error);
2899		printf("mac_create_vnode: using old vnode label\n");
2900	}
2901
2902	MAC_PERFORM(create_vnode, cred, parent, &parent->v_label, child,
2903	    &child->v_label);
2904}
2905
2906int
2907mac_setsockopt_label_set(struct ucred *cred, struct socket *so,
2908    struct mac *extmac)
2909{
2910	struct label intlabel;
2911	int error;
2912
2913	error = mac_internalize(&intlabel, extmac);
2914	if (error)
2915		return (error);
2916
2917	mac_check_socket_relabel(cred, so, &intlabel);
2918	if (error) {
2919		mac_destroy_temp(&intlabel);
2920		return (error);
2921	}
2922
2923	mac_relabel_socket(cred, so, &intlabel);
2924
2925	mac_destroy_temp(&intlabel);
2926	return (0);
2927}
2928
2929int
2930mac_pipe_label_set(struct ucred *cred, struct pipe *pipe, struct label *label)
2931{
2932	int error;
2933
2934	PIPE_LOCK_ASSERT(pipe, MA_OWNED);
2935
2936	error = mac_check_pipe_relabel(cred, pipe, label);
2937	if (error)
2938		return (error);
2939
2940	mac_relabel_pipe(cred, pipe, label);
2941
2942	return (0);
2943}
2944
2945int
2946mac_getsockopt_label_get(struct ucred *cred, struct socket *so,
2947    struct mac *extmac)
2948{
2949
2950	return (mac_externalize(&so->so_label, extmac));
2951}
2952
2953int
2954mac_getsockopt_peerlabel_get(struct ucred *cred, struct socket *so,
2955    struct mac *extmac)
2956{
2957
2958	return (mac_externalize(&so->so_peerlabel, extmac));
2959}
2960
2961/*
2962 * Implementation of VOP_SETLABEL() that relies on extended attributes
2963 * to store label data.  Can be referenced by filesystems supporting
2964 * extended attributes.
2965 */
2966int
2967vop_stdsetlabel_ea(struct vop_setlabel_args *ap)
2968{
2969	struct vnode *vp = ap->a_vp;
2970	struct label *intlabel = ap->a_label;
2971	struct mac extmac;
2972	int error;
2973
2974	ASSERT_VOP_LOCKED(vp, "vop_stdsetlabel_ea");
2975
2976	/*
2977	 * XXX: Eventually call out to EA check/set calls here.
2978	 * Be particularly careful to avoid race conditions,
2979	 * consistency problems, and stability problems when
2980	 * dealing with multiple EAs.  In particular, we require
2981	 * the ability to write multiple EAs on the same file in
2982	 * a single transaction, which the current EA interface
2983	 * does not provide.
2984	 */
2985
2986	error = mac_externalize(intlabel, &extmac);
2987	if (error)
2988		return (error);
2989
2990	error = vn_extattr_set(vp, IO_NODELOCKED,
2991	    FREEBSD_MAC_EXTATTR_NAMESPACE, FREEBSD_MAC_EXTATTR_NAME,
2992	    sizeof(extmac), (char *)&extmac, curthread);
2993	if (error)
2994		return (error);
2995
2996	mac_relabel_vnode(ap->a_cred, vp, intlabel);
2997
2998	vp->v_vflag |= VV_CACHEDLABEL;
2999
3000	return (0);
3001}
3002
3003static int
3004vn_setlabel(struct vnode *vp, struct label *intlabel, struct ucred *cred)
3005{
3006	int error;
3007
3008	if (vp->v_mount == NULL) {
3009		/* printf("vn_setlabel: null v_mount\n"); */
3010		if (vp->v_type != VNON)
3011			printf("vn_setlabel: null v_mount with non-VNON\n");
3012		return (EBADF);
3013	}
3014
3015	if ((vp->v_mount->mnt_flag & MNT_MULTILABEL) == 0)
3016		return (EOPNOTSUPP);
3017
3018	/*
3019	 * Multi-phase commit.  First check the policies to confirm the
3020	 * change is OK.  Then commit via the filesystem.  Finally,
3021	 * update the actual vnode label.  Question: maybe the filesystem
3022	 * should update the vnode at the end as part of VOP_SETLABEL()?
3023	 */
3024	error = mac_check_vnode_relabel(cred, vp, intlabel);
3025	if (error)
3026		return (error);
3027
3028	/*
3029	 * VADMIN provides the opportunity for the filesystem to make
3030	 * decisions about who is and is not able to modify labels
3031	 * and protections on files.  This might not be right.  We can't
3032	 * assume VOP_SETLABEL() will do it, because we might implement
3033	 * that as part of vop_stdsetlabel_ea().
3034	 */
3035	error = VOP_ACCESS(vp, VADMIN, cred, curthread);
3036	if (error)
3037		return (error);
3038
3039	error = VOP_SETLABEL(vp, intlabel, cred, curthread);
3040	if (error)
3041		return (error);
3042
3043	return (0);
3044}
3045
3046/*
3047 * MPSAFE
3048 */
3049int
3050__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3051{
3052	struct mac extmac;
3053	int error;
3054
3055	error = mac_externalize(&td->td_ucred->cr_label, &extmac);
3056	if (error == 0)
3057		error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3058
3059	return (error);
3060}
3061
3062/*
3063 * MPSAFE
3064 */
3065int
3066__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3067{
3068	struct ucred *newcred, *oldcred;
3069	struct proc *p;
3070	struct mac extmac;
3071	struct label intlabel;
3072	int error;
3073
3074	error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3075	if (error)
3076		return (error);
3077
3078	error = mac_internalize(&intlabel, &extmac);
3079	if (error)
3080		return (error);
3081
3082	newcred = crget();
3083
3084	p = td->td_proc;
3085	PROC_LOCK(p);
3086	oldcred = p->p_ucred;
3087
3088	error = mac_check_cred_relabel(oldcred, &intlabel);
3089	if (error) {
3090		PROC_UNLOCK(p);
3091		mac_destroy_temp(&intlabel);
3092		crfree(newcred);
3093		return (error);
3094	}
3095
3096	setsugid(p);
3097	crcopy(newcred, oldcred);
3098	mac_relabel_cred(newcred, &intlabel);
3099	p->p_ucred = newcred;
3100
3101	/*
3102	 * Grab additional reference for use while revoking mmaps, prior
3103	 * to releasing the proc lock and sharing the cred.
3104	 */
3105	crhold(newcred);
3106	PROC_UNLOCK(p);
3107
3108	mtx_lock(&Giant);
3109	mac_cred_mmapped_drop_perms(td, newcred);
3110	mtx_unlock(&Giant);
3111
3112	crfree(newcred);	/* Free revocation reference. */
3113	crfree(oldcred);
3114	mac_destroy_temp(&intlabel);
3115	return (0);
3116}
3117
3118/*
3119 * MPSAFE
3120 */
3121int
3122__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3123{
3124	struct file *fp;
3125	struct mac extmac;
3126	struct vnode *vp;
3127	struct pipe *pipe;
3128	int error;
3129
3130	mtx_lock(&Giant);
3131
3132	error = fget(td, SCARG(uap, fd), &fp);
3133	if (error)
3134		goto out;
3135
3136	switch (fp->f_type) {
3137	case DTYPE_FIFO:
3138	case DTYPE_VNODE:
3139		vp = (struct vnode *)fp->f_data;
3140
3141		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3142		error = vn_refreshlabel(vp, td->td_ucred);
3143		if (error == 0)
3144			error = mac_externalize(&vp->v_label, &extmac);
3145		VOP_UNLOCK(vp, 0, td);
3146		break;
3147	case DTYPE_PIPE:
3148		pipe = (struct pipe *)fp->f_data;
3149		error = mac_externalize(pipe->pipe_label, &extmac);
3150		break;
3151	default:
3152		error = EINVAL;
3153	}
3154
3155	if (error == 0)
3156		error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3157
3158	fdrop(fp, td);
3159
3160out:
3161	mtx_unlock(&Giant);
3162	return (error);
3163}
3164
3165/*
3166 * MPSAFE
3167 */
3168int
3169__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3170{
3171	struct nameidata nd;
3172	struct mac extmac;
3173	int error;
3174
3175	mtx_lock(&Giant);
3176	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3177	    SCARG(uap, path_p), td);
3178	error = namei(&nd);
3179	if (error)
3180		goto out;
3181
3182	error = vn_refreshlabel(nd.ni_vp, td->td_ucred);
3183	if (error == 0)
3184		error = mac_externalize(&nd.ni_vp->v_label, &extmac);
3185	NDFREE(&nd, 0);
3186	if (error)
3187		goto out;
3188
3189	error = copyout(&extmac, SCARG(uap, mac_p), sizeof(extmac));
3190
3191out:
3192	mtx_unlock(&Giant);
3193	return (error);
3194}
3195
3196/*
3197 * MPSAFE
3198 */
3199int
3200__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3201{
3202	struct file *fp;
3203	struct mac extmac;
3204	struct label intlabel;
3205	struct mount *mp;
3206	struct vnode *vp;
3207	struct pipe *pipe;
3208	int error;
3209
3210	mtx_lock(&Giant);
3211	error = fget(td, SCARG(uap, fd), &fp);
3212	if (error)
3213		goto out1;
3214
3215	error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3216	if (error)
3217		goto out2;
3218
3219	error = mac_internalize(&intlabel, &extmac);
3220	if (error)
3221		goto out2;
3222
3223	switch (fp->f_type) {
3224	case DTYPE_FIFO:
3225	case DTYPE_VNODE:
3226		vp = (struct vnode *)fp->f_data;
3227		error = vn_start_write(vp, &mp, V_WAIT | PCATCH);
3228		if (error != 0)
3229			break;
3230
3231		vn_lock(vp, LK_EXCLUSIVE | LK_RETRY, td);
3232		error = vn_setlabel(vp, &intlabel, td->td_ucred);
3233		VOP_UNLOCK(vp, 0, td);
3234		vn_finished_write(mp);
3235		mac_destroy_temp(&intlabel);
3236		break;
3237	case DTYPE_PIPE:
3238		pipe = (struct pipe *)fp->f_data;
3239		PIPE_LOCK(pipe);
3240		error = mac_pipe_label_set(td->td_ucred, pipe, &intlabel);
3241		PIPE_UNLOCK(pipe);
3242		break;
3243	default:
3244		error = EINVAL;
3245	}
3246
3247out2:
3248	fdrop(fp, td);
3249out1:
3250	mtx_unlock(&Giant);
3251	return (error);
3252}
3253
3254/*
3255 * MPSAFE
3256 */
3257int
3258__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3259{
3260	struct nameidata nd;
3261	struct mac extmac;
3262	struct label intlabel;
3263	struct mount *mp;
3264	int error;
3265
3266	mtx_lock(&Giant);
3267
3268	error = copyin(SCARG(uap, mac_p), &extmac, sizeof(extmac));
3269	if (error)
3270		goto out;
3271
3272	error = mac_internalize(&intlabel, &extmac);
3273	if (error)
3274		goto out;
3275
3276	NDINIT(&nd, LOOKUP, LOCKLEAF | FOLLOW, UIO_USERSPACE,
3277	    SCARG(uap, path_p), td);
3278	error = namei(&nd);
3279	if (error)
3280		goto out2;
3281	error = vn_start_write(nd.ni_vp, &mp, V_WAIT | PCATCH);
3282	if (error)
3283		goto out2;
3284
3285	error = vn_setlabel(nd.ni_vp, &intlabel, td->td_ucred);
3286
3287	vn_finished_write(mp);
3288out2:
3289	mac_destroy_temp(&intlabel);
3290	NDFREE(&nd, 0);
3291out:
3292	mtx_unlock(&Giant);
3293	return (error);
3294}
3295
3296int
3297mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3298{
3299	struct mac_policy_conf *mpc;
3300	char target[MAC_MAX_POLICY_NAME];
3301	int error;
3302
3303	error = copyinstr(SCARG(uap, policy), target, sizeof(target), NULL);
3304	if (error)
3305		return (error);
3306
3307	error = ENOSYS;
3308	MAC_POLICY_LIST_BUSY();
3309	LIST_FOREACH(mpc, &mac_policy_list, mpc_list) {
3310		if (strcmp(mpc->mpc_name, target) == 0 &&
3311		    mpc->mpc_ops->mpo_syscall != NULL) {
3312			error = mpc->mpc_ops->mpo_syscall(td,
3313			    SCARG(uap, call), SCARG(uap, arg));
3314			goto out;
3315		}
3316	}
3317
3318out:
3319	MAC_POLICY_LIST_UNBUSY();
3320	return (error);
3321}
3322
3323SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3324SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3325
3326#else /* !MAC */
3327
3328int
3329__mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3330{
3331
3332	return (ENOSYS);
3333}
3334
3335int
3336__mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3337{
3338
3339	return (ENOSYS);
3340}
3341
3342int
3343__mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3344{
3345
3346	return (ENOSYS);
3347}
3348
3349int
3350__mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3351{
3352
3353	return (ENOSYS);
3354}
3355
3356int
3357__mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3358{
3359
3360	return (ENOSYS);
3361}
3362
3363int
3364__mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3365{
3366
3367	return (ENOSYS);
3368}
3369
3370int
3371mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3372{
3373
3374	return (ENOSYS);
3375}
3376
3377#endif /* !MAC */
3378