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