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