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