xref: /freebsd/sys/security/mac/mac_vfs.c (revision c031391bd5dec6d2e0cd9918295a4d08e86d04e4)
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$
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  */
94 MODULE_VERSION(kernel_mac_support, 1);
95 
96 SYSCTL_DECL(_security);
97 
98 SYSCTL_NODE(_security, OID_AUTO, mac, CTLFLAG_RW, 0,
99     "TrustedBSD MAC policy controls");
100 SYSCTL_NODE(_security_mac, OID_AUTO, debug, CTLFLAG_RW, 0,
101     "TrustedBSD MAC debug info");
102 
103 static int	mac_debug_label_fallback = 0;
104 SYSCTL_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.");
107 TUNABLE_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
116 static unsigned int mac_max_policies = MAC_MAX_POLICIES;
117 static unsigned int mac_policy_offsets_free = (1 << MAC_MAX_POLICIES) - 1;
118 SYSCTL_UINT(_security_mac, OID_AUTO, max_policies, CTLFLAG_RD,
119     &mac_max_policies, 0, "");
120 
121 static int	mac_late = 0;
122 
123 static int	mac_enforce_fs = 1;
124 SYSCTL_INT(_security_mac, OID_AUTO, enforce_fs, CTLFLAG_RW,
125     &mac_enforce_fs, 0, "Enforce MAC policy on file system objects");
126 TUNABLE_INT("security.mac.enforce_fs", &mac_enforce_fs);
127 
128 static int	mac_enforce_network = 1;
129 SYSCTL_INT(_security_mac, OID_AUTO, enforce_network, CTLFLAG_RW,
130     &mac_enforce_network, 0, "Enforce MAC policy on network packets");
131 TUNABLE_INT("security.mac.enforce_network", &mac_enforce_network);
132 
133 static int	mac_enforce_pipe = 1;
134 SYSCTL_INT(_security_mac, OID_AUTO, enforce_pipe, CTLFLAG_RW,
135     &mac_enforce_pipe, 0, "Enforce MAC policy on pipe operations");
136 TUNABLE_INT("security.mac.enforce_pipe", &mac_enforce_pipe);
137 
138 static int	mac_enforce_process = 1;
139 SYSCTL_INT(_security_mac, OID_AUTO, enforce_process, CTLFLAG_RW,
140     &mac_enforce_process, 0, "Enforce MAC policy on inter-process operations");
141 TUNABLE_INT("security.mac.enforce_process", &mac_enforce_process);
142 
143 static int	mac_enforce_socket = 1;
144 SYSCTL_INT(_security_mac, OID_AUTO, enforce_socket, CTLFLAG_RW,
145     &mac_enforce_socket, 0, "Enforce MAC policy on socket operations");
146 TUNABLE_INT("security.mac.enforce_socket", &mac_enforce_socket);
147 
148 static int     mac_enforce_vm = 1;
149 SYSCTL_INT(_security_mac, OID_AUTO, enforce_vm, CTLFLAG_RW,
150     &mac_enforce_vm, 0, "Enforce MAC policy on vm operations");
151 TUNABLE_INT("security.mac.enforce_vm", &mac_enforce_vm);
152 
153 static int	mac_label_size = sizeof(struct mac);
154 SYSCTL_INT(_security_mac, OID_AUTO, label_size, CTLFLAG_RD,
155     &mac_label_size, 0, "Pre-compiled MAC label size");
156 
157 static int	mac_cache_fslabel_in_vnode = 1;
158 SYSCTL_INT(_security_mac, OID_AUTO, cache_fslabel_in_vnode, CTLFLAG_RW,
159     &mac_cache_fslabel_in_vnode, 0, "Cache mount fslabel in vnode");
160 TUNABLE_INT("security.mac.cache_fslabel_in_vnode",
161     &mac_cache_fslabel_in_vnode);
162 
163 static int	mac_vnode_label_cache_hits = 0;
164 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_hits, CTLFLAG_RD,
165     &mac_vnode_label_cache_hits, 0, "Cache hits on vnode labels");
166 static int	mac_vnode_label_cache_misses = 0;
167 SYSCTL_INT(_security_mac, OID_AUTO, vnode_label_cache_misses, CTLFLAG_RD,
168     &mac_vnode_label_cache_misses, 0, "Cache misses on vnode labels");
169 
170 static int	mac_mmap_revocation = 1;
171 SYSCTL_INT(_security_mac, OID_AUTO, mmap_revocation, CTLFLAG_RW,
172     &mac_mmap_revocation, 0, "Revoke mmap access to files on subject "
173     "relabel");
174 static int	mac_mmap_revocation_via_cow = 0;
175 SYSCTL_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
180 static unsigned int nmacmbufs, nmaccreds, nmacifnets, nmacbpfdescs,
181     nmacsockets, nmacmounts, nmactemp, nmacvnodes, nmacdevfsdirents,
182     nmacipqs, nmacpipes;
183 SYSCTL_UINT(_security_mac_debug, OID_AUTO, mbufs, CTLFLAG_RD,
184     &nmacmbufs, 0, "number of mbufs in use");
185 SYSCTL_UINT(_security_mac_debug, OID_AUTO, creds, CTLFLAG_RD,
186     &nmaccreds, 0, "number of ucreds in use");
187 SYSCTL_UINT(_security_mac_debug, OID_AUTO, ifnets, CTLFLAG_RD,
188     &nmacifnets, 0, "number of ifnets in use");
189 SYSCTL_UINT(_security_mac_debug, OID_AUTO, ipqs, CTLFLAG_RD,
190     &nmacipqs, 0, "number of ipqs in use");
191 SYSCTL_UINT(_security_mac_debug, OID_AUTO, bpfdescs, CTLFLAG_RD,
192     &nmacbpfdescs, 0, "number of bpfdescs in use");
193 SYSCTL_UINT(_security_mac_debug, OID_AUTO, sockets, CTLFLAG_RD,
194     &nmacsockets, 0, "number of sockets in use");
195 SYSCTL_UINT(_security_mac_debug, OID_AUTO, pipes, CTLFLAG_RD,
196     &nmacpipes, 0, "number of pipes in use");
197 SYSCTL_UINT(_security_mac_debug, OID_AUTO, mounts, CTLFLAG_RD,
198     &nmacmounts, 0, "number of mounts in use");
199 SYSCTL_UINT(_security_mac_debug, OID_AUTO, temp, CTLFLAG_RD,
200     &nmactemp, 0, "number of temporary labels in use");
201 SYSCTL_UINT(_security_mac_debug, OID_AUTO, vnodes, CTLFLAG_RD,
202     &nmacvnodes, 0, "number of vnodes in use");
203 SYSCTL_UINT(_security_mac_debug, OID_AUTO, devfsdirents, CTLFLAG_RD,
204     &nmacdevfsdirents, 0, "number of devfs dirents inuse");
205 #endif
206 
207 static int	error_select(int error1, int error2);
208 static int	mac_externalize(struct label *label, struct mac *mac);
209 static int	mac_policy_register(struct mac_policy_conf *mpc);
210 static int	mac_policy_unregister(struct mac_policy_conf *mpc);
211 
212 static int	mac_stdcreatevnode_ea(struct vnode *vp);
213 static void	mac_cred_mmapped_drop_perms(struct thread *td,
214 		    struct ucred *cred);
215 static void	mac_cred_mmapped_drop_perms_recurse(struct thread *td,
216 		    struct ucred *cred, struct vm_map *map);
217 
218 MALLOC_DEFINE(M_MACOPVEC, "macopvec", "MAC policy operation vector");
219 MALLOC_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  */
229 static struct mtx mac_policy_list_lock;
230 static LIST_HEAD(, mac_policy_conf) mac_policy_list;
231 static 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  */
309 static void
310 mac_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  */
322 static void
323 mac_late_init(void)
324 {
325 
326 	mac_late = 1;
327 }
328 
329 /*
330  * Allow MAC policy modules to register during boot, etc.
331  */
332 int
333 mac_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 
367 static int
368 mac_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 
899 static int
900 mac_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  */
936 static int
937 error_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 
969 void
970 mac_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 
976 void
977 mac_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  */
987 static int
988 mac_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  */
1002 static int
1003 mac_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  */
1016 void
1017 mac_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  */
1033 int
1034 vop_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  */
1107 static int
1108 vn_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  */
1164 int
1165 vop_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 
1218 void
1219 mac_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 
1235 int
1236 mac_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 
1250 static void
1251 mac_init_label(struct label *label)
1252 {
1253 
1254 	bzero(label, sizeof(*label));
1255 	label->l_flags = MAC_FLAG_INITIALIZED;
1256 }
1257 
1258 static void
1259 mac_init_structmac(struct mac *mac)
1260 {
1261 
1262 	bzero(mac, sizeof(*mac));
1263 	mac->m_macflags = MAC_FLAG_INITIALIZED;
1264 }
1265 
1266 static void
1267 mac_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 
1277 int
1278 mac_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 
1291 void
1292 mac_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 
1302 void
1303 mac_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 
1313 void
1314 mac_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 
1324 void
1325 mac_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 
1335 void
1336 mac_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 
1346 void
1347 mac_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 
1357 void
1358 mac_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 
1368 void
1369 mac_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 
1381 void
1382 mac_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 
1394 void
1395 mac_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 
1409 void
1410 mac_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 
1421 void
1422 mac_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 
1432 void
1433 mac_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 
1443 void
1444 mac_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 
1455 void
1456 mac_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 
1467 static void
1468 mac_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 
1478 static void
1479 mac_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 
1489 void
1490 mac_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 
1500 void
1501 mac_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 
1511 void
1512 mac_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 
1522 void
1523 mac_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 
1533 static int
1534 mac_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 
1544 static int
1545 mac_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  */
1561 void
1562 mac_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  */
1572 void
1573 mac_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  */
1584 void
1585 mac_create_cred(struct ucred *parent_cred, struct ucred *child_cred)
1586 {
1587 
1588 	MAC_PERFORM(create_cred, parent_cred, child_cred);
1589 }
1590 
1591 int
1592 mac_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 
1609 int
1610 mac_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 
1627 int
1628 mac_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 
1645 int
1646 mac_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 
1664 int
1665 mac_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 
1688 int
1689 mac_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 
1707 int
1708 mac_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 
1725 int
1726 mac_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 
1743 int
1744 mac_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 
1763 int
1764 mac_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 
1782 vm_prot_t
1783 mac_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 
1799 int
1800 mac_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 
1817 int
1818 mac_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 
1838 int
1839 mac_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 
1859 int
1860 mac_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 
1877 int
1878 mac_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 
1895 static int
1896 mac_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 
1912 int
1913 mac_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 
1936 int
1937 mac_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 
1961 int
1962 mac_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 
1979 int
1980 mac_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 
1998 int
1999 mac_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 
2018 int
2019 mac_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 
2036 int
2037 mac_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 
2054 int
2055 mac_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 
2073 int
2074 mac_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 
2093 int
2094 mac_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 
2113 int
2114 mac_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  */
2140 static void
2141 mac_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 
2150 static __inline const char *
2151 prot2str(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 
2174 static void
2175 mac_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  */
2295 static void
2296 mac_relabel_cred(struct ucred *cred, struct label *newlabel)
2297 {
2298 
2299 	MAC_PERFORM(relabel_cred, cred, newlabel);
2300 }
2301 
2302 void
2303 mac_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 
2309 void
2310 mac_create_ifnet(struct ifnet *ifnet)
2311 {
2312 
2313 	MAC_PERFORM(create_ifnet, ifnet, &ifnet->if_label);
2314 }
2315 
2316 void
2317 mac_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 
2323 void
2324 mac_create_socket(struct ucred *cred, struct socket *socket)
2325 {
2326 
2327 	MAC_PERFORM(create_socket, cred, socket, &socket->so_label);
2328 }
2329 
2330 void
2331 mac_create_pipe(struct ucred *cred, struct pipe *pipe)
2332 {
2333 
2334 	MAC_PERFORM(create_pipe, cred, pipe, pipe->pipe_label);
2335 }
2336 
2337 void
2338 mac_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 
2346 static void
2347 mac_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 
2354 static void
2355 mac_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 
2361 void
2362 mac_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 
2369 void
2370 mac_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 
2378 void
2379 mac_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 
2386 void
2387 mac_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 
2394 void
2395 mac_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 
2402 void
2403 mac_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 
2410 void
2411 mac_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 
2418 void
2419 mac_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 
2426 void
2427 mac_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 
2434 void
2435 mac_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 
2444 void
2445 mac_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 
2452 int
2453 mac_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 
2464 void
2465 mac_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 
2472 void
2473 mac_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 
2480 void
2481 mac_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 
2488 void
2489 mac_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 
2496 int
2497 mac_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 
2510 static int
2511 mac_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 
2520 int
2521 mac_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 
2533 int
2534 mac_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 
2552 int
2553 mac_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 
2565 int
2566 mac_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 
2576 int
2577 mac_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 
2586 int
2587 mac_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 
2596 static int
2597 mac_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 
2607 int
2608 mac_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 
2617 int
2618 mac_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 
2627 int
2628 mac_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 
2642 int
2643 mac_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 
2657 int
2658 mac_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 
2672 int
2673 mac_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 
2687 int
2688 mac_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 
2702 int
2703 mac_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 
2716 int
2717 mac_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 
2728 static int
2729 mac_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 
2740 int
2741 mac_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 
2753 int
2754 mac_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 
2767 int
2768 mac_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 
2799 out:
2800 	mac_destroy_temp(&intlabel);
2801 	return (error);
2802 }
2803 
2804 void
2805 mac_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 
2811 void
2812 mac_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 
2818 static int
2819 mac_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 
2828 void
2829 mac_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  */
2840 void
2841 mac_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 
2860 int
2861 mac_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 
2883 int
2884 mac_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 
2897 int
2898 mac_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 
2905 int
2906 mac_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  */
2918 int
2919 vop_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 
2955 static int
2956 vn_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  */
3001 int
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  */
3017 int
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  */
3073 int
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 
3112 out:
3113 	mtx_unlock(&Giant);
3114 	return (error);
3115 }
3116 
3117 /*
3118  * MPSAFE
3119  */
3120 int
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 
3143 out:
3144 	mtx_unlock(&Giant);
3145 	return (error);
3146 }
3147 
3148 /*
3149  * MPSAFE
3150  */
3151 int
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 
3197 out2:
3198 	fdrop(fp, td);
3199 out1:
3200 	mtx_unlock(&Giant);
3201 	return (error);
3202 }
3203 
3204 /*
3205  * MPSAFE
3206  */
3207 int
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);
3238 out2:
3239 	mac_destroy_temp(&intlabel);
3240 	NDFREE(&nd, 0);
3241 out:
3242 	mtx_unlock(&Giant);
3243 	return (error);
3244 }
3245 
3246 int
3247 mac_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 
3268 out:
3269 	MAC_POLICY_LIST_UNBUSY();
3270 	return (error);
3271 }
3272 
3273 SYSINIT(mac, SI_SUB_MAC, SI_ORDER_FIRST, mac_init, NULL);
3274 SYSINIT(mac_late, SI_SUB_MAC_LATE, SI_ORDER_FIRST, mac_late_init, NULL);
3275 
3276 #else /* !MAC */
3277 
3278 int
3279 __mac_get_proc(struct thread *td, struct __mac_get_proc_args *uap)
3280 {
3281 
3282 	return (ENOSYS);
3283 }
3284 
3285 int
3286 __mac_set_proc(struct thread *td, struct __mac_set_proc_args *uap)
3287 {
3288 
3289 	return (ENOSYS);
3290 }
3291 
3292 int
3293 __mac_get_fd(struct thread *td, struct __mac_get_fd_args *uap)
3294 {
3295 
3296 	return (ENOSYS);
3297 }
3298 
3299 int
3300 __mac_get_file(struct thread *td, struct __mac_get_file_args *uap)
3301 {
3302 
3303 	return (ENOSYS);
3304 }
3305 
3306 int
3307 __mac_set_fd(struct thread *td, struct __mac_set_fd_args *uap)
3308 {
3309 
3310 	return (ENOSYS);
3311 }
3312 
3313 int
3314 __mac_set_file(struct thread *td, struct __mac_set_file_args *uap)
3315 {
3316 
3317 	return (ENOSYS);
3318 }
3319 
3320 int
3321 mac_syscall(struct thread *td, struct mac_syscall_args *uap)
3322 {
3323 
3324 	return (ENOSYS);
3325 }
3326 
3327 #endif /* !MAC */
3328