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