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