xref: /freebsd/sys/security/mac_mls/mac_mls.c (revision 2b743a9e9ddc6736208dc8ca1ce06ce64ad20a19)
1 /*-
2  * Copyright (c) 1999-2002 Robert N. M. Watson
3  * Copyright (c) 2001-2005 McAfee, Inc.
4  * All rights reserved.
5  *
6  * This software was developed by Robert Watson for the TrustedBSD Project.
7  *
8  * This software was developed for the FreeBSD Project in part by McAfee
9  * Research, the Security Research Division of McAfee, Inc. under
10  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11  * CHATS research program.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $FreeBSD$
35  */
36 
37 /*
38  * Developed by the TrustedBSD Project.
39  * MLS fixed label mandatory confidentiality policy.
40  */
41 
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/acl.h>
45 #include <sys/conf.h>
46 #include <sys/extattr.h>
47 #include <sys/kernel.h>
48 #include <sys/ksem.h>
49 #include <sys/mman.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/proc.h>
53 #include <sys/sbuf.h>
54 #include <sys/systm.h>
55 #include <sys/sysproto.h>
56 #include <sys/sysent.h>
57 #include <sys/systm.h>
58 #include <sys/vnode.h>
59 #include <sys/file.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/pipe.h>
63 #include <sys/sx.h>
64 #include <sys/sysctl.h>
65 #include <sys/msg.h>
66 #include <sys/sem.h>
67 #include <sys/shm.h>
68 
69 #include <fs/devfs/devfs.h>
70 
71 #include <net/bpfdesc.h>
72 #include <net/if.h>
73 #include <net/if_types.h>
74 #include <net/if_var.h>
75 
76 #include <netinet/in.h>
77 #include <netinet/in_pcb.h>
78 #include <netinet/ip_var.h>
79 
80 #include <vm/uma.h>
81 #include <vm/vm.h>
82 
83 #include <security/mac/mac_policy.h>
84 #include <security/mac_mls/mac_mls.h>
85 
86 SYSCTL_DECL(_security_mac);
87 
88 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
89     "TrustedBSD mac_mls policy controls");
90 
91 static int	mac_mls_label_size = sizeof(struct mac_mls);
92 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
93     &mac_mls_label_size, 0, "Size of struct mac_mls");
94 
95 static int	mac_mls_enabled = 1;
96 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
97     &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
98 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
99 
100 static int	destroyed_not_inited;
101 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
102     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
103 
104 static int	ptys_equal = 0;
105 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
106     &ptys_equal, 0, "Label pty devices as mls/equal on create");
107 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
108 
109 static int	revocation_enabled = 0;
110 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
111     &revocation_enabled, 0, "Revoke access to objects on relabel");
112 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
113 
114 static int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
115 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
116     &max_compartments, 0, "Maximum compartments the policy supports");
117 
118 static int	mac_mls_slot;
119 #define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mac_mls_slot))
120 #define	SLOT_SET(l, val) mac_label_set((l), mac_mls_slot, (uintptr_t)(val))
121 
122 static uma_zone_t	zone_mls;
123 
124 static __inline int
125 mls_bit_set_empty(u_char *set) {
126 	int i;
127 
128 	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
129 		if (set[i] != 0)
130 			return (0);
131 	return (1);
132 }
133 
134 static struct mac_mls *
135 mls_alloc(int flag)
136 {
137 
138 	return (uma_zalloc(zone_mls, flag | M_ZERO));
139 }
140 
141 static void
142 mls_free(struct mac_mls *mac_mls)
143 {
144 
145 	if (mac_mls != NULL)
146 		uma_zfree(zone_mls, mac_mls);
147 	else
148 		atomic_add_int(&destroyed_not_inited, 1);
149 }
150 
151 static int
152 mls_atmostflags(struct mac_mls *mac_mls, int flags)
153 {
154 
155 	if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
156 		return (EINVAL);
157 	return (0);
158 }
159 
160 static int
161 mac_mls_dominate_element(struct mac_mls_element *a,
162     struct mac_mls_element *b)
163 {
164 	int bit;
165 
166 	switch (a->mme_type) {
167 	case MAC_MLS_TYPE_EQUAL:
168 	case MAC_MLS_TYPE_HIGH:
169 		return (1);
170 
171 	case MAC_MLS_TYPE_LOW:
172 		switch (b->mme_type) {
173 		case MAC_MLS_TYPE_LEVEL:
174 		case MAC_MLS_TYPE_HIGH:
175 			return (0);
176 
177 		case MAC_MLS_TYPE_EQUAL:
178 		case MAC_MLS_TYPE_LOW:
179 			return (1);
180 
181 		default:
182 			panic("mac_mls_dominate_element: b->mme_type invalid");
183 		}
184 
185 	case MAC_MLS_TYPE_LEVEL:
186 		switch (b->mme_type) {
187 		case MAC_MLS_TYPE_EQUAL:
188 		case MAC_MLS_TYPE_LOW:
189 			return (1);
190 
191 		case MAC_MLS_TYPE_HIGH:
192 			return (0);
193 
194 		case MAC_MLS_TYPE_LEVEL:
195 			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
196 				if (!MAC_MLS_BIT_TEST(bit,
197 				    a->mme_compartments) &&
198 				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
199 					return (0);
200 			return (a->mme_level >= b->mme_level);
201 
202 		default:
203 			panic("mac_mls_dominate_element: b->mme_type invalid");
204 		}
205 
206 	default:
207 		panic("mac_mls_dominate_element: a->mme_type invalid");
208 	}
209 
210 	return (0);
211 }
212 
213 static int
214 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
215 {
216 
217 	return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
218 	    &rangea->mm_rangehigh) &&
219 	    mac_mls_dominate_element(&rangea->mm_rangelow,
220 	    &rangeb->mm_rangelow));
221 }
222 
223 static int
224 mac_mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
225 {
226 
227 	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
228 	    ("mac_mls_effective_in_range: a not effective"));
229 	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
230 	    ("mac_mls_effective_in_range: b not range"));
231 
232 	return (mac_mls_dominate_element(&range->mm_rangehigh,
233 	    &effective->mm_effective) &&
234 	    mac_mls_dominate_element(&effective->mm_effective,
235 	    &range->mm_rangelow));
236 
237 	return (1);
238 }
239 
240 static int
241 mac_mls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
242 {
243 	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
244 	    ("mac_mls_dominate_effective: a not effective"));
245 	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
246 	    ("mac_mls_dominate_effective: b not effective"));
247 
248 	return (mac_mls_dominate_element(&a->mm_effective, &b->mm_effective));
249 }
250 
251 static int
252 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
253 {
254 
255 	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
256 	    b->mme_type == MAC_MLS_TYPE_EQUAL)
257 		return (1);
258 
259 	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
260 }
261 
262 static int
263 mac_mls_equal_effective(struct mac_mls *a, struct mac_mls *b)
264 {
265 
266 	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
267 	    ("mac_mls_equal_effective: a not effective"));
268 	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
269 	    ("mac_mls_equal_effective: b not effective"));
270 
271 	return (mac_mls_equal_element(&a->mm_effective, &b->mm_effective));
272 }
273 
274 static int
275 mac_mls_contains_equal(struct mac_mls *mac_mls)
276 {
277 
278 	if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
279 		if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
280 			return (1);
281 
282 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
283 		if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
284 			return (1);
285 		if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
286 			return (1);
287 	}
288 
289 	return (0);
290 }
291 
292 static int
293 mac_mls_subject_privileged(struct mac_mls *mac_mls)
294 {
295 
296 	KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) ==
297 	    MAC_MLS_FLAGS_BOTH,
298 	    ("mac_mls_subject_privileged: subject doesn't have both labels"));
299 
300 	/* If the effective is EQUAL, it's ok. */
301 	if (mac_mls->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
302 		return (0);
303 
304 	/* If either range endpoint is EQUAL, it's ok. */
305 	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
306 	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
307 		return (0);
308 
309 	/* If the range is low-high, it's ok. */
310 	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
311 	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
312 		return (0);
313 
314 	/* It's not ok. */
315 	return (EPERM);
316 }
317 
318 static int
319 mac_mls_valid(struct mac_mls *mac_mls)
320 {
321 
322 	if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
323 		switch (mac_mls->mm_effective.mme_type) {
324 		case MAC_MLS_TYPE_LEVEL:
325 			break;
326 
327 		case MAC_MLS_TYPE_EQUAL:
328 		case MAC_MLS_TYPE_HIGH:
329 		case MAC_MLS_TYPE_LOW:
330 			if (mac_mls->mm_effective.mme_level != 0 ||
331 			    !MAC_MLS_BIT_SET_EMPTY(
332 			    mac_mls->mm_effective.mme_compartments))
333 				return (EINVAL);
334 			break;
335 
336 		default:
337 			return (EINVAL);
338 		}
339 	} else {
340 		if (mac_mls->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
341 			return (EINVAL);
342 	}
343 
344 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
345 		switch (mac_mls->mm_rangelow.mme_type) {
346 		case MAC_MLS_TYPE_LEVEL:
347 			break;
348 
349 		case MAC_MLS_TYPE_EQUAL:
350 		case MAC_MLS_TYPE_HIGH:
351 		case MAC_MLS_TYPE_LOW:
352 			if (mac_mls->mm_rangelow.mme_level != 0 ||
353 			    !MAC_MLS_BIT_SET_EMPTY(
354 			    mac_mls->mm_rangelow.mme_compartments))
355 				return (EINVAL);
356 			break;
357 
358 		default:
359 			return (EINVAL);
360 		}
361 
362 		switch (mac_mls->mm_rangehigh.mme_type) {
363 		case MAC_MLS_TYPE_LEVEL:
364 			break;
365 
366 		case MAC_MLS_TYPE_EQUAL:
367 		case MAC_MLS_TYPE_HIGH:
368 		case MAC_MLS_TYPE_LOW:
369 			if (mac_mls->mm_rangehigh.mme_level != 0 ||
370 			    !MAC_MLS_BIT_SET_EMPTY(
371 			    mac_mls->mm_rangehigh.mme_compartments))
372 				return (EINVAL);
373 			break;
374 
375 		default:
376 			return (EINVAL);
377 		}
378 		if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
379 		    &mac_mls->mm_rangelow))
380 			return (EINVAL);
381 	} else {
382 		if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
383 		    mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
384 			return (EINVAL);
385 	}
386 
387 	return (0);
388 }
389 
390 static void
391 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
392     u_short levellow, u_char *compartmentslow, u_short typehigh,
393     u_short levelhigh, u_char *compartmentshigh)
394 {
395 
396 	mac_mls->mm_rangelow.mme_type = typelow;
397 	mac_mls->mm_rangelow.mme_level = levellow;
398 	if (compartmentslow != NULL)
399 		memcpy(mac_mls->mm_rangelow.mme_compartments,
400 		    compartmentslow,
401 		    sizeof(mac_mls->mm_rangelow.mme_compartments));
402 	mac_mls->mm_rangehigh.mme_type = typehigh;
403 	mac_mls->mm_rangehigh.mme_level = levelhigh;
404 	if (compartmentshigh != NULL)
405 		memcpy(mac_mls->mm_rangehigh.mme_compartments,
406 		    compartmentshigh,
407 		    sizeof(mac_mls->mm_rangehigh.mme_compartments));
408 	mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
409 }
410 
411 static void
412 mac_mls_set_effective(struct mac_mls *mac_mls, u_short type, u_short level,
413     u_char *compartments)
414 {
415 
416 	mac_mls->mm_effective.mme_type = type;
417 	mac_mls->mm_effective.mme_level = level;
418 	if (compartments != NULL)
419 		memcpy(mac_mls->mm_effective.mme_compartments, compartments,
420 		    sizeof(mac_mls->mm_effective.mme_compartments));
421 	mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
422 }
423 
424 static void
425 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
426 {
427 
428 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
429 	    ("mac_mls_copy_range: labelfrom not range"));
430 
431 	labelto->mm_rangelow = labelfrom->mm_rangelow;
432 	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
433 	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
434 }
435 
436 static void
437 mac_mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
438 {
439 
440 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
441 	    ("mac_mls_copy_effective: labelfrom not effective"));
442 
443 	labelto->mm_effective = labelfrom->mm_effective;
444 	labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
445 }
446 
447 static void
448 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
449 {
450 
451 	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
452 		mac_mls_copy_effective(source, dest);
453 	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
454 		mac_mls_copy_range(source, dest);
455 }
456 
457 /*
458  * Policy module operations.
459  */
460 static void
461 mac_mls_init(struct mac_policy_conf *conf)
462 {
463 
464 	zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
465 	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
466 }
467 
468 /*
469  * Label operations.
470  */
471 static void
472 mac_mls_init_label(struct label *label)
473 {
474 
475 	SLOT_SET(label, mls_alloc(M_WAITOK));
476 }
477 
478 static int
479 mac_mls_init_label_waitcheck(struct label *label, int flag)
480 {
481 
482 	SLOT_SET(label, mls_alloc(flag));
483 	if (SLOT(label) == NULL)
484 		return (ENOMEM);
485 
486 	return (0);
487 }
488 
489 static void
490 mac_mls_destroy_label(struct label *label)
491 {
492 
493 	mls_free(SLOT(label));
494 	SLOT_SET(label, NULL);
495 }
496 
497 /*
498  * mac_mls_element_to_string() accepts an sbuf and MLS element.  It
499  * converts the MLS element to a string and stores the result in the
500  * sbuf; if there isn't space in the sbuf, -1 is returned.
501  */
502 static int
503 mac_mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
504 {
505 	int i, first;
506 
507 	switch (element->mme_type) {
508 	case MAC_MLS_TYPE_HIGH:
509 		return (sbuf_printf(sb, "high"));
510 
511 	case MAC_MLS_TYPE_LOW:
512 		return (sbuf_printf(sb, "low"));
513 
514 	case MAC_MLS_TYPE_EQUAL:
515 		return (sbuf_printf(sb, "equal"));
516 
517 	case MAC_MLS_TYPE_LEVEL:
518 		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
519 			return (-1);
520 
521 		first = 1;
522 		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
523 			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
524 				if (first) {
525 					if (sbuf_putc(sb, ':') == -1)
526 						return (-1);
527 					if (sbuf_printf(sb, "%d", i) == -1)
528 						return (-1);
529 					first = 0;
530 				} else {
531 					if (sbuf_printf(sb, "+%d", i) == -1)
532 						return (-1);
533 				}
534 			}
535 		}
536 		return (0);
537 
538 	default:
539 		panic("mac_mls_element_to_string: invalid type (%d)",
540 		    element->mme_type);
541 	}
542 }
543 
544 /*
545  * mac_mls_to_string() converts an MLS label to a string, and places
546  * the results in the passed sbuf.  It returns 0 on success, or EINVAL
547  * if there isn't room in the sbuf.  Note: the sbuf will be modified
548  * even in a failure case, so the caller may need to revert the sbuf
549  * by restoring the offset if that's undesired.
550  */
551 static int
552 mac_mls_to_string(struct sbuf *sb, struct mac_mls *mac_mls)
553 {
554 
555 	if (mac_mls->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
556 		if (mac_mls_element_to_string(sb, &mac_mls->mm_effective)
557 		    == -1)
558 			return (EINVAL);
559 	}
560 
561 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
562 		if (sbuf_putc(sb, '(') == -1)
563 			return (EINVAL);
564 
565 		if (mac_mls_element_to_string(sb, &mac_mls->mm_rangelow)
566 		    == -1)
567 			return (EINVAL);
568 
569 		if (sbuf_putc(sb, '-') == -1)
570 			return (EINVAL);
571 
572 		if (mac_mls_element_to_string(sb, &mac_mls->mm_rangehigh)
573 		    == -1)
574 			return (EINVAL);
575 
576 		if (sbuf_putc(sb, ')') == -1)
577 			return (EINVAL);
578 	}
579 
580 	return (0);
581 }
582 
583 static int
584 mac_mls_externalize_label(struct label *label, char *element_name,
585     struct sbuf *sb, int *claimed)
586 {
587 	struct mac_mls *mac_mls;
588 
589 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
590 		return (0);
591 
592 	(*claimed)++;
593 
594 	mac_mls = SLOT(label);
595 
596 	return (mac_mls_to_string(sb, mac_mls));
597 }
598 
599 static int
600 mac_mls_parse_element(struct mac_mls_element *element, char *string)
601 {
602 	char *compartment, *end, *level;
603 	int value;
604 
605 	if (strcmp(string, "high") == 0 ||
606 	    strcmp(string, "hi") == 0) {
607 		element->mme_type = MAC_MLS_TYPE_HIGH;
608 		element->mme_level = MAC_MLS_TYPE_UNDEF;
609 	} else if (strcmp(string, "low") == 0 ||
610 	    strcmp(string, "lo") == 0) {
611 		element->mme_type = MAC_MLS_TYPE_LOW;
612 		element->mme_level = MAC_MLS_TYPE_UNDEF;
613 	} else if (strcmp(string, "equal") == 0 ||
614 	    strcmp(string, "eq") == 0) {
615 		element->mme_type = MAC_MLS_TYPE_EQUAL;
616 		element->mme_level = MAC_MLS_TYPE_UNDEF;
617 	} else {
618 		element->mme_type = MAC_MLS_TYPE_LEVEL;
619 
620 		/*
621 		 * Numeric level piece of the element.
622 		 */
623 		level = strsep(&string, ":");
624 		value = strtol(level, &end, 10);
625 		if (end == level || *end != '\0')
626 			return (EINVAL);
627 		if (value < 0 || value > 65535)
628 			return (EINVAL);
629 		element->mme_level = value;
630 
631 		/*
632 		 * Optional compartment piece of the element.  If none
633 		 * are included, we assume that the label has no
634 		 * compartments.
635 		 */
636 		if (string == NULL)
637 			return (0);
638 		if (*string == '\0')
639 			return (0);
640 
641 		while ((compartment = strsep(&string, "+")) != NULL) {
642 			value = strtol(compartment, &end, 10);
643 			if (compartment == end || *end != '\0')
644 				return (EINVAL);
645 			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
646 				return (EINVAL);
647 			MAC_MLS_BIT_SET(value, element->mme_compartments);
648 		}
649 	}
650 
651 	return (0);
652 }
653 
654 /*
655  * Note: destructively consumes the string, make a local copy before
656  * calling if that's a problem.
657  */
658 static int
659 mac_mls_parse(struct mac_mls *mac_mls, char *string)
660 {
661 	char *rangehigh, *rangelow, *effective;
662 	int error;
663 
664 	effective = strsep(&string, "(");
665 	if (*effective == '\0')
666 		effective = NULL;
667 
668 	if (string != NULL) {
669 		rangelow = strsep(&string, "-");
670 		if (string == NULL)
671 			return (EINVAL);
672 		rangehigh = strsep(&string, ")");
673 		if (string == NULL)
674 			return (EINVAL);
675 		if (*string != '\0')
676 			return (EINVAL);
677 	} else {
678 		rangelow = NULL;
679 		rangehigh = NULL;
680 	}
681 
682 	KASSERT((rangelow != NULL && rangehigh != NULL) ||
683 	    (rangelow == NULL && rangehigh == NULL),
684 	    ("mac_mls_parse: range mismatch"));
685 
686 	bzero(mac_mls, sizeof(*mac_mls));
687 	if (effective != NULL) {
688 		error = mac_mls_parse_element(&mac_mls->mm_effective, effective);
689 		if (error)
690 			return (error);
691 		mac_mls->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
692 	}
693 
694 	if (rangelow != NULL) {
695 		error = mac_mls_parse_element(&mac_mls->mm_rangelow,
696 		    rangelow);
697 		if (error)
698 			return (error);
699 		error = mac_mls_parse_element(&mac_mls->mm_rangehigh,
700 		    rangehigh);
701 		if (error)
702 			return (error);
703 		mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
704 	}
705 
706 	error = mac_mls_valid(mac_mls);
707 	if (error)
708 		return (error);
709 
710 	return (0);
711 }
712 
713 static int
714 mac_mls_internalize_label(struct label *label, char *element_name,
715     char *element_data, int *claimed)
716 {
717 	struct mac_mls *mac_mls, mac_mls_temp;
718 	int error;
719 
720 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
721 		return (0);
722 
723 	(*claimed)++;
724 
725 	error = mac_mls_parse(&mac_mls_temp, element_data);
726 	if (error)
727 		return (error);
728 
729 	mac_mls = SLOT(label);
730 	*mac_mls = mac_mls_temp;
731 
732 	return (0);
733 }
734 
735 static void
736 mac_mls_copy_label(struct label *src, struct label *dest)
737 {
738 
739 	*SLOT(dest) = *SLOT(src);
740 }
741 
742 /*
743  * Labeling event operations: file system objects, and things that look
744  * a lot like file system objects.
745  */
746 static void
747 mac_mls_create_devfs_device(struct ucred *cred, struct mount *mp,
748     struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label)
749 {
750 	struct mac_mls *mac_mls;
751 	int mls_type;
752 
753 	mac_mls = SLOT(label);
754 	if (strcmp(dev->si_name, "null") == 0 ||
755 	    strcmp(dev->si_name, "zero") == 0 ||
756 	    strcmp(dev->si_name, "random") == 0 ||
757 	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
758 		mls_type = MAC_MLS_TYPE_EQUAL;
759 	else if (strcmp(dev->si_name, "kmem") == 0 ||
760 	    strcmp(dev->si_name, "mem") == 0)
761 		mls_type = MAC_MLS_TYPE_HIGH;
762 	else if (ptys_equal &&
763 	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
764 	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
765 		mls_type = MAC_MLS_TYPE_EQUAL;
766 	else
767 		mls_type = MAC_MLS_TYPE_LOW;
768 	mac_mls_set_effective(mac_mls, mls_type, 0, NULL);
769 }
770 
771 static void
772 mac_mls_create_devfs_directory(struct mount *mp, char *dirname,
773     int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
774 {
775 	struct mac_mls *mac_mls;
776 
777 	mac_mls = SLOT(label);
778 	mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
779 }
780 
781 static void
782 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp,
783     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
784     struct label *delabel)
785 {
786 	struct mac_mls *source, *dest;
787 
788 	source = SLOT(cred->cr_label);
789 	dest = SLOT(delabel);
790 
791 	mac_mls_copy_effective(source, dest);
792 }
793 
794 static void
795 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
796     struct label *mntlabel, struct label *fslabel)
797 {
798 	struct mac_mls *source, *dest;
799 
800 	source = SLOT(cred->cr_label);
801 	dest = SLOT(mntlabel);
802 	mac_mls_copy_effective(source, dest);
803 	dest = SLOT(fslabel);
804 	mac_mls_copy_effective(source, dest);
805 }
806 
807 static void
808 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
809     struct label *vnodelabel, struct label *label)
810 {
811 	struct mac_mls *source, *dest;
812 
813 	source = SLOT(label);
814 	dest = SLOT(vnodelabel);
815 
816 	mac_mls_copy(source, dest);
817 }
818 
819 static void
820 mac_mls_update_devfsdirent(struct mount *mp,
821     struct devfs_dirent *devfs_dirent, struct label *direntlabel,
822     struct vnode *vp, struct label *vnodelabel)
823 {
824 	struct mac_mls *source, *dest;
825 
826 	source = SLOT(vnodelabel);
827 	dest = SLOT(direntlabel);
828 
829 	mac_mls_copy_effective(source, dest);
830 }
831 
832 static void
833 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
834     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
835     struct label *vlabel)
836 {
837 	struct mac_mls *source, *dest;
838 
839 	source = SLOT(delabel);
840 	dest = SLOT(vlabel);
841 
842 	mac_mls_copy_effective(source, dest);
843 }
844 
845 static int
846 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
847     struct vnode *vp, struct label *vlabel)
848 {
849 	struct mac_mls temp, *source, *dest;
850 	int buflen, error;
851 
852 	source = SLOT(fslabel);
853 	dest = SLOT(vlabel);
854 
855 	buflen = sizeof(temp);
856 	bzero(&temp, buflen);
857 
858 	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
859 	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
860 	if (error == ENOATTR || error == EOPNOTSUPP) {
861 		/* Fall back to the fslabel. */
862 		mac_mls_copy_effective(source, dest);
863 		return (0);
864 	} else if (error)
865 		return (error);
866 
867 	if (buflen != sizeof(temp)) {
868 		printf("mac_mls_associate_vnode_extattr: bad size %d\n",
869 		    buflen);
870 		return (EPERM);
871 	}
872 	if (mac_mls_valid(&temp) != 0) {
873 		printf("mac_mls_associate_vnode_extattr: invalid\n");
874 		return (EPERM);
875 	}
876 	if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_EFFECTIVE) {
877 		printf("mac_mls_associated_vnode_extattr: not effective\n");
878 		return (EPERM);
879 	}
880 
881 	mac_mls_copy_effective(&temp, dest);
882 	return (0);
883 }
884 
885 static void
886 mac_mls_associate_vnode_singlelabel(struct mount *mp,
887     struct label *fslabel, struct vnode *vp, struct label *vlabel)
888 {
889 	struct mac_mls *source, *dest;
890 
891 	source = SLOT(fslabel);
892 	dest = SLOT(vlabel);
893 
894 	mac_mls_copy_effective(source, dest);
895 }
896 
897 static int
898 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
899     struct label *fslabel, struct vnode *dvp, struct label *dlabel,
900     struct vnode *vp, struct label *vlabel, struct componentname *cnp)
901 {
902 	struct mac_mls *source, *dest, temp;
903 	size_t buflen;
904 	int error;
905 
906 	buflen = sizeof(temp);
907 	bzero(&temp, buflen);
908 
909 	source = SLOT(cred->cr_label);
910 	dest = SLOT(vlabel);
911 	mac_mls_copy_effective(source, &temp);
912 
913 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
914 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
915 	if (error == 0)
916 		mac_mls_copy_effective(source, dest);
917 	return (error);
918 }
919 
920 static int
921 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
922     struct label *vlabel, struct label *intlabel)
923 {
924 	struct mac_mls *source, temp;
925 	size_t buflen;
926 	int error;
927 
928 	buflen = sizeof(temp);
929 	bzero(&temp, buflen);
930 
931 	source = SLOT(intlabel);
932 	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
933 		return (0);
934 
935 	mac_mls_copy_effective(source, &temp);
936 
937 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
938 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
939 	return (error);
940 }
941 
942 /*
943  * Labeling event operations: IPC object.
944  */
945 static void
946 mac_mls_create_inpcb_from_socket(struct socket *so, struct label *solabel,
947     struct inpcb *inp, struct label *inplabel)
948 {
949 	struct mac_mls *source, *dest;
950 
951 	source = SLOT(solabel);
952 	dest = SLOT(inplabel);
953 
954 	mac_mls_copy_effective(source, dest);
955 }
956 
957 static void
958 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
959     struct mbuf *m, struct label *mbuflabel)
960 {
961 	struct mac_mls *source, *dest;
962 
963 	source = SLOT(socketlabel);
964 	dest = SLOT(mbuflabel);
965 
966 	mac_mls_copy_effective(source, dest);
967 }
968 
969 static void
970 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
971     struct label *socketlabel)
972 {
973 	struct mac_mls *source, *dest;
974 
975 	source = SLOT(cred->cr_label);
976 	dest = SLOT(socketlabel);
977 
978 	mac_mls_copy_effective(source, dest);
979 }
980 
981 static void
982 mac_mls_create_pipe(struct ucred *cred, struct pipepair *pp,
983     struct label *pipelabel)
984 {
985 	struct mac_mls *source, *dest;
986 
987 	source = SLOT(cred->cr_label);
988 	dest = SLOT(pipelabel);
989 
990 	mac_mls_copy_effective(source, dest);
991 }
992 
993 static void
994 mac_mls_create_posix_sem(struct ucred *cred, struct ksem *ksemptr,
995     struct label *ks_label)
996 {
997 	struct mac_mls *source, *dest;
998 
999 	source = SLOT(cred->cr_label);
1000 	dest = SLOT(ks_label);
1001 
1002 	mac_mls_copy_effective(source, dest);
1003 }
1004 
1005 static void
1006 mac_mls_create_socket_from_socket(struct socket *oldsocket,
1007     struct label *oldsocketlabel, struct socket *newsocket,
1008     struct label *newsocketlabel)
1009 {
1010 	struct mac_mls *source, *dest;
1011 
1012 	source = SLOT(oldsocketlabel);
1013 	dest = SLOT(newsocketlabel);
1014 
1015 	mac_mls_copy_effective(source, dest);
1016 }
1017 
1018 static void
1019 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
1020     struct label *socketlabel, struct label *newlabel)
1021 {
1022 	struct mac_mls *source, *dest;
1023 
1024 	source = SLOT(newlabel);
1025 	dest = SLOT(socketlabel);
1026 
1027 	mac_mls_copy(source, dest);
1028 }
1029 
1030 static void
1031 mac_mls_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1032     struct label *pipelabel, struct label *newlabel)
1033 {
1034 	struct mac_mls *source, *dest;
1035 
1036 	source = SLOT(newlabel);
1037 	dest = SLOT(pipelabel);
1038 
1039 	mac_mls_copy(source, dest);
1040 }
1041 
1042 static void
1043 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1044     struct socket *socket, struct label *socketpeerlabel)
1045 {
1046 	struct mac_mls *source, *dest;
1047 
1048 	source = SLOT(mbuflabel);
1049 	dest = SLOT(socketpeerlabel);
1050 
1051 	mac_mls_copy_effective(source, dest);
1052 }
1053 
1054 /*
1055  * Labeling event operations: System V IPC objects.
1056  */
1057 
1058 static void
1059 mac_mls_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr,
1060     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1061 {
1062 	struct mac_mls *source, *dest;
1063 
1064 	/* Ignore the msgq label */
1065 	source = SLOT(cred->cr_label);
1066 	dest = SLOT(msglabel);
1067 
1068 	mac_mls_copy_effective(source, dest);
1069 }
1070 
1071 static void
1072 mac_mls_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr,
1073     struct label *msqlabel)
1074 {
1075 	struct mac_mls *source, *dest;
1076 
1077 	source = SLOT(cred->cr_label);
1078 	dest = SLOT(msqlabel);
1079 
1080 	mac_mls_copy_effective(source, dest);
1081 }
1082 
1083 static void
1084 mac_mls_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr,
1085     struct label *semalabel)
1086 {
1087 	struct mac_mls *source, *dest;
1088 
1089 	source = SLOT(cred->cr_label);
1090 	dest = SLOT(semalabel);
1091 
1092 	mac_mls_copy_effective(source, dest);
1093 }
1094 
1095 static void
1096 mac_mls_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr,
1097     struct label *shmlabel)
1098 {
1099 	struct mac_mls *source, *dest;
1100 
1101 	source = SLOT(cred->cr_label);
1102 	dest = SLOT(shmlabel);
1103 
1104 	mac_mls_copy_effective(source, dest);
1105 }
1106 
1107 /*
1108  * Labeling event operations: network objects.
1109  */
1110 static void
1111 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
1112     struct label *oldsocketlabel, struct socket *newsocket,
1113     struct label *newsocketpeerlabel)
1114 {
1115 	struct mac_mls *source, *dest;
1116 
1117 	source = SLOT(oldsocketlabel);
1118 	dest = SLOT(newsocketpeerlabel);
1119 
1120 	mac_mls_copy_effective(source, dest);
1121 }
1122 
1123 static void
1124 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1125     struct label *bpflabel)
1126 {
1127 	struct mac_mls *source, *dest;
1128 
1129 	source = SLOT(cred->cr_label);
1130 	dest = SLOT(bpflabel);
1131 
1132 	mac_mls_copy_effective(source, dest);
1133 }
1134 
1135 static void
1136 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1137 {
1138 	struct mac_mls *dest;
1139 	int type;
1140 
1141 	dest = SLOT(ifnetlabel);
1142 
1143 	if (ifnet->if_type == IFT_LOOP)
1144 		type = MAC_MLS_TYPE_EQUAL;
1145 	else
1146 		type = MAC_MLS_TYPE_LOW;
1147 
1148 	mac_mls_set_effective(dest, type, 0, NULL);
1149 	mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1150 }
1151 
1152 static void
1153 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1154     struct ipq *ipq, struct label *ipqlabel)
1155 {
1156 	struct mac_mls *source, *dest;
1157 
1158 	source = SLOT(fragmentlabel);
1159 	dest = SLOT(ipqlabel);
1160 
1161 	mac_mls_copy_effective(source, dest);
1162 }
1163 
1164 static void
1165 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1166     struct mbuf *datagram, struct label *datagramlabel)
1167 {
1168 	struct mac_mls *source, *dest;
1169 
1170 	source = SLOT(ipqlabel);
1171 	dest = SLOT(datagramlabel);
1172 
1173 	/* Just use the head, since we require them all to match. */
1174 	mac_mls_copy_effective(source, dest);
1175 }
1176 
1177 static void
1178 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1179     struct mbuf *fragment, struct label *fragmentlabel)
1180 {
1181 	struct mac_mls *source, *dest;
1182 
1183 	source = SLOT(datagramlabel);
1184 	dest = SLOT(fragmentlabel);
1185 
1186 	mac_mls_copy_effective(source, dest);
1187 }
1188 
1189 static void
1190 mac_mls_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1191     struct mbuf *m, struct label *mlabel)
1192 {
1193 	struct mac_mls *source, *dest;
1194 
1195 	source = SLOT(inplabel);
1196 	dest = SLOT(mlabel);
1197 
1198 	mac_mls_copy_effective(source, dest);
1199 }
1200 
1201 static void
1202 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1203     struct mbuf *mbuf, struct label *mbuflabel)
1204 {
1205 	struct mac_mls *dest;
1206 
1207 	dest = SLOT(mbuflabel);
1208 
1209 	mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1210 }
1211 
1212 static void
1213 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1214     struct mbuf *mbuf, struct label *mbuflabel)
1215 {
1216 	struct mac_mls *source, *dest;
1217 
1218 	source = SLOT(bpflabel);
1219 	dest = SLOT(mbuflabel);
1220 
1221 	mac_mls_copy_effective(source, dest);
1222 }
1223 
1224 static void
1225 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1226     struct mbuf *m, struct label *mbuflabel)
1227 {
1228 	struct mac_mls *source, *dest;
1229 
1230 	source = SLOT(ifnetlabel);
1231 	dest = SLOT(mbuflabel);
1232 
1233 	mac_mls_copy_effective(source, dest);
1234 }
1235 
1236 static void
1237 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1238     struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1239     struct mbuf *newmbuf, struct label *newmbuflabel)
1240 {
1241 	struct mac_mls *source, *dest;
1242 
1243 	source = SLOT(oldmbuflabel);
1244 	dest = SLOT(newmbuflabel);
1245 
1246 	mac_mls_copy_effective(source, dest);
1247 }
1248 
1249 static void
1250 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1251     struct mbuf *newmbuf, struct label *newmbuflabel)
1252 {
1253 	struct mac_mls *source, *dest;
1254 
1255 	source = SLOT(oldmbuflabel);
1256 	dest = SLOT(newmbuflabel);
1257 
1258 	mac_mls_copy_effective(source, dest);
1259 }
1260 
1261 static int
1262 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1263     struct ipq *ipq, struct label *ipqlabel)
1264 {
1265 	struct mac_mls *a, *b;
1266 
1267 	a = SLOT(ipqlabel);
1268 	b = SLOT(fragmentlabel);
1269 
1270 	return (mac_mls_equal_effective(a, b));
1271 }
1272 
1273 static void
1274 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1275     struct label *ifnetlabel, struct label *newlabel)
1276 {
1277 	struct mac_mls *source, *dest;
1278 
1279 	source = SLOT(newlabel);
1280 	dest = SLOT(ifnetlabel);
1281 
1282 	mac_mls_copy(source, dest);
1283 }
1284 
1285 static void
1286 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1287     struct ipq *ipq, struct label *ipqlabel)
1288 {
1289 
1290 	/* NOOP: we only accept matching labels, so no need to update */
1291 }
1292 
1293 static void
1294 mac_mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1295     struct inpcb *inp, struct label *inplabel)
1296 {
1297 	struct mac_mls *source, *dest;
1298 
1299 	source = SLOT(solabel);
1300 	dest = SLOT(inplabel);
1301 
1302 	mac_mls_copy(source, dest);
1303 }
1304 
1305 static void
1306 mac_mls_create_mbuf_from_firewall(struct mbuf *m, struct label *mbuflabel)
1307 {
1308 	struct mac_mls *dest;
1309 
1310 	dest = SLOT(mbuflabel);
1311 
1312 	/* XXX: where is the label for the firewall really comming from? */
1313 	mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1314 }
1315 
1316 static void
1317 mac_mls_init_syncache_from_inpcb(struct label *label, struct inpcb *inp)
1318 {
1319 	struct mac_mls *source, *dest;
1320 
1321 	source = SLOT(inp->inp_label);
1322 	dest = SLOT(label);
1323 	mac_mls_copy_effective(source, dest);
1324 }
1325 
1326 static void
1327 mac_mls_create_mbuf_from_syncache(struct label *sc_label, struct mbuf *m,
1328     struct label *mbuf_label)
1329 {
1330 	struct mac_mls *source, *dest;
1331 
1332 	source = SLOT(sc_label);
1333 	dest = SLOT(mbuf_label);
1334 	mac_mls_copy_effective(source, dest);
1335 }
1336 
1337 /*
1338  * Labeling event operations: processes.
1339  */
1340 static void
1341 mac_mls_create_proc0(struct ucred *cred)
1342 {
1343 	struct mac_mls *dest;
1344 
1345 	dest = SLOT(cred->cr_label);
1346 
1347 	mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1348 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1349 	    0, NULL);
1350 }
1351 
1352 static void
1353 mac_mls_create_proc1(struct ucred *cred)
1354 {
1355 	struct mac_mls *dest;
1356 
1357 	dest = SLOT(cred->cr_label);
1358 
1359 	mac_mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1360 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1361 	    0, NULL);
1362 }
1363 
1364 static void
1365 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1366 {
1367 	struct mac_mls *source, *dest;
1368 
1369 	source = SLOT(newlabel);
1370 	dest = SLOT(cred->cr_label);
1371 
1372 	mac_mls_copy(source, dest);
1373 }
1374 
1375 /*
1376  * Label cleanup/flush operations.
1377  */
1378 static void
1379 mac_mls_cleanup_sysv_msgmsg(struct label *msglabel)
1380 {
1381 
1382 	bzero(SLOT(msglabel), sizeof(struct mac_mls));
1383 }
1384 
1385 static void
1386 mac_mls_cleanup_sysv_msgqueue(struct label *msqlabel)
1387 {
1388 
1389 	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
1390 }
1391 
1392 static void
1393 mac_mls_cleanup_sysv_sem(struct label *semalabel)
1394 {
1395 
1396 	bzero(SLOT(semalabel), sizeof(struct mac_mls));
1397 }
1398 
1399 static void
1400 mac_mls_cleanup_sysv_shm(struct label *shmlabel)
1401 {
1402 
1403 	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
1404 }
1405 
1406 /*
1407  * Access control checks.
1408  */
1409 static int
1410 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1411      struct ifnet *ifnet, struct label *ifnetlabel)
1412 {
1413 	struct mac_mls *a, *b;
1414 
1415 	if (!mac_mls_enabled)
1416 		return (0);
1417 
1418 	a = SLOT(bpflabel);
1419 	b = SLOT(ifnetlabel);
1420 
1421 	if (mac_mls_equal_effective(a, b))
1422 		return (0);
1423 	return (EACCES);
1424 }
1425 
1426 static int
1427 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1428 {
1429 	struct mac_mls *subj, *new;
1430 	int error;
1431 
1432 	subj = SLOT(cred->cr_label);
1433 	new = SLOT(newlabel);
1434 
1435 	/*
1436 	 * If there is an MLS label update for the credential, it may be
1437 	 * an update of effective, range, or both.
1438 	 */
1439 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1440 	if (error)
1441 		return (error);
1442 
1443 	/*
1444 	 * If the MLS label is to be changed, authorize as appropriate.
1445 	 */
1446 	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1447 		/*
1448 		 * If the change request modifies both the MLS label effective
1449 		 * and range, check that the new effective will be in the
1450 		 * new range.
1451 		 */
1452 		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
1453 		    MAC_MLS_FLAGS_BOTH &&
1454 		    !mac_mls_effective_in_range(new, new))
1455 			return (EINVAL);
1456 
1457 		/*
1458 		 * To change the MLS effective label on a credential, the
1459 		 * new effective label must be in the current range.
1460 		 */
1461 		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
1462 		    !mac_mls_effective_in_range(new, subj))
1463 			return (EPERM);
1464 
1465 		/*
1466 		 * To change the MLS range label on a credential, the
1467 		 * new range must be in the current range.
1468 		 */
1469 		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
1470 		    !mac_mls_range_in_range(new, subj))
1471 			return (EPERM);
1472 
1473 		/*
1474 		 * To have EQUAL in any component of the new credential
1475 		 * MLS label, the subject must already have EQUAL in
1476 		 * their label.
1477 		 */
1478 		if (mac_mls_contains_equal(new)) {
1479 			error = mac_mls_subject_privileged(subj);
1480 			if (error)
1481 				return (error);
1482 		}
1483 	}
1484 
1485 	return (0);
1486 }
1487 
1488 static int
1489 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1490 {
1491 	struct mac_mls *subj, *obj;
1492 
1493 	if (!mac_mls_enabled)
1494 		return (0);
1495 
1496 	subj = SLOT(u1->cr_label);
1497 	obj = SLOT(u2->cr_label);
1498 
1499 	/* XXX: range */
1500 	if (!mac_mls_dominate_effective(subj, obj))
1501 		return (ESRCH);
1502 
1503 	return (0);
1504 }
1505 
1506 static int
1507 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1508     struct label *ifnetlabel, struct label *newlabel)
1509 {
1510 	struct mac_mls *subj, *new;
1511 	int error;
1512 
1513 	subj = SLOT(cred->cr_label);
1514 	new = SLOT(newlabel);
1515 
1516 	/*
1517 	 * If there is an MLS label update for the interface, it may
1518 	 * be an update of effective, range, or both.
1519 	 */
1520 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1521 	if (error)
1522 		return (error);
1523 
1524 	/*
1525 	 * Relabeling network interfaces requires MLS privilege.
1526 	 */
1527 	error = mac_mls_subject_privileged(subj);
1528 
1529 	return (0);
1530 }
1531 
1532 static int
1533 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1534     struct mbuf *m, struct label *mbuflabel)
1535 {
1536 	struct mac_mls *p, *i;
1537 
1538 	if (!mac_mls_enabled)
1539 		return (0);
1540 
1541 	p = SLOT(mbuflabel);
1542 	i = SLOT(ifnetlabel);
1543 
1544 	return (mac_mls_effective_in_range(p, i) ? 0 : EACCES);
1545 }
1546 
1547 static int
1548 mac_mls_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1549     struct mbuf *m, struct label *mlabel)
1550 {
1551 	struct mac_mls *p, *i;
1552 
1553 	if (!mac_mls_enabled)
1554 		return (0);
1555 
1556 	p = SLOT(mlabel);
1557 	i = SLOT(inplabel);
1558 
1559 	return (mac_mls_equal_effective(p, i) ? 0 : EACCES);
1560 }
1561 
1562 static int
1563 mac_mls_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr,
1564     struct label *msglabel)
1565 {
1566 	struct mac_mls *subj, *obj;
1567 
1568 	if (!mac_mls_enabled)
1569 		return (0);
1570 
1571 	subj = SLOT(cred->cr_label);
1572 	obj = SLOT(msglabel);
1573 
1574 	if (!mac_mls_dominate_effective(subj, obj))
1575 		return (EACCES);
1576 
1577 	return (0);
1578 }
1579 
1580 static int
1581 mac_mls_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr,
1582     struct label *msglabel)
1583 {
1584 	struct mac_mls *subj, *obj;
1585 
1586 	if (!mac_mls_enabled)
1587 		return (0);
1588 
1589 	subj = SLOT(cred->cr_label);
1590 	obj = SLOT(msglabel);
1591 
1592 	if (!mac_mls_dominate_effective(obj, subj))
1593 		return (EACCES);
1594 
1595 	return (0);
1596 }
1597 
1598 static int
1599 mac_mls_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1600     struct label *msqklabel)
1601 {
1602 	struct mac_mls *subj, *obj;
1603 
1604 	if (!mac_mls_enabled)
1605 		return (0);
1606 
1607 	subj = SLOT(cred->cr_label);
1608 	obj = SLOT(msqklabel);
1609 
1610 	if (!mac_mls_dominate_effective(subj, obj))
1611 		return (EACCES);
1612 
1613 	return (0);
1614 }
1615 
1616 static int
1617 mac_mls_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1618     struct label *msqklabel)
1619 {
1620 	struct mac_mls *subj, *obj;
1621 
1622 	if (!mac_mls_enabled)
1623 		return (0);
1624 
1625 	subj = SLOT(cred->cr_label);
1626 	obj = SLOT(msqklabel);
1627 
1628 	if (!mac_mls_dominate_effective(obj, subj))
1629 		return (EACCES);
1630 
1631 	return (0);
1632 }
1633 
1634 static int
1635 mac_mls_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1636     struct label *msqklabel)
1637 {
1638 	struct mac_mls *subj, *obj;
1639 
1640 	if (!mac_mls_enabled)
1641 		return (0);
1642 
1643 	subj = SLOT(cred->cr_label);
1644 	obj = SLOT(msqklabel);
1645 
1646 	if (!mac_mls_dominate_effective(subj, obj))
1647 		return (EACCES);
1648 
1649 	return (0);
1650 }
1651 
1652 static int
1653 mac_mls_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1654     struct label *msqklabel, int cmd)
1655 {
1656 	struct mac_mls *subj, *obj;
1657 
1658 	if (!mac_mls_enabled)
1659 		return (0);
1660 
1661 	subj = SLOT(cred->cr_label);
1662 	obj = SLOT(msqklabel);
1663 
1664 	switch(cmd) {
1665 	case IPC_RMID:
1666 	case IPC_SET:
1667 		if (!mac_mls_dominate_effective(obj, subj))
1668 			return (EACCES);
1669 		break;
1670 
1671 	case IPC_STAT:
1672 		if (!mac_mls_dominate_effective(subj, obj))
1673 			return (EACCES);
1674 		break;
1675 
1676 	default:
1677 		return (EACCES);
1678 	}
1679 
1680 	return (0);
1681 }
1682 
1683 static int
1684 mac_mls_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr,
1685     struct label *semaklabel, int cmd)
1686 {
1687 	struct mac_mls *subj, *obj;
1688 
1689 	if (!mac_mls_enabled)
1690 		return (0);
1691 
1692 	subj = SLOT(cred->cr_label);
1693 	obj = SLOT(semaklabel);
1694 
1695 	switch(cmd) {
1696 	case IPC_RMID:
1697 	case IPC_SET:
1698 	case SETVAL:
1699 	case SETALL:
1700 		if (!mac_mls_dominate_effective(obj, subj))
1701 			return (EACCES);
1702 		break;
1703 
1704 	case IPC_STAT:
1705 	case GETVAL:
1706 	case GETPID:
1707 	case GETNCNT:
1708 	case GETZCNT:
1709 	case GETALL:
1710 		if (!mac_mls_dominate_effective(subj, obj))
1711 			return (EACCES);
1712 		break;
1713 
1714 	default:
1715 		return (EACCES);
1716 	}
1717 
1718 	return (0);
1719 }
1720 
1721 static int
1722 mac_mls_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr,
1723     struct label *semaklabel)
1724 {
1725 	struct mac_mls *subj, *obj;
1726 
1727 	if (!mac_mls_enabled)
1728 		return (0);
1729 
1730 	subj = SLOT(cred->cr_label);
1731 	obj = SLOT(semaklabel);
1732 
1733 	if (!mac_mls_dominate_effective(subj, obj))
1734 		return (EACCES);
1735 
1736 	return (0);
1737 }
1738 
1739 static int
1740 mac_mls_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr,
1741     struct label *semaklabel, size_t accesstype)
1742 {
1743 	struct mac_mls *subj, *obj;
1744 
1745 	if (!mac_mls_enabled)
1746 		return (0);
1747 
1748 	subj = SLOT(cred->cr_label);
1749 	obj = SLOT(semaklabel);
1750 
1751 	if( accesstype & SEM_R )
1752 		if (!mac_mls_dominate_effective(subj, obj))
1753 			return (EACCES);
1754 
1755 	if( accesstype & SEM_A )
1756 		if (!mac_mls_dominate_effective(obj, subj))
1757 			return (EACCES);
1758 
1759 	return (0);
1760 }
1761 
1762 static int
1763 mac_mls_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
1764     struct label *shmseglabel, int shmflg)
1765 {
1766 	struct mac_mls *subj, *obj;
1767 
1768 	if (!mac_mls_enabled)
1769 		return (0);
1770 
1771 	subj = SLOT(cred->cr_label);
1772 	obj = SLOT(shmseglabel);
1773 
1774 	if (!mac_mls_dominate_effective(subj, obj))
1775 			return (EACCES);
1776 	if ((shmflg & SHM_RDONLY) == 0)
1777 		if (!mac_mls_dominate_effective(obj, subj))
1778 			return (EACCES);
1779 
1780 	return (0);
1781 }
1782 
1783 static int
1784 mac_mls_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
1785     struct label *shmseglabel, int cmd)
1786 {
1787 	struct mac_mls *subj, *obj;
1788 
1789 	if (!mac_mls_enabled)
1790 		return (0);
1791 
1792 	subj = SLOT(cred->cr_label);
1793 	obj = SLOT(shmseglabel);
1794 
1795 	switch(cmd) {
1796 	case IPC_RMID:
1797 	case IPC_SET:
1798 		if (!mac_mls_dominate_effective(obj, subj))
1799 			return (EACCES);
1800 		break;
1801 
1802 	case IPC_STAT:
1803 	case SHM_STAT:
1804 		if (!mac_mls_dominate_effective(subj, obj))
1805 			return (EACCES);
1806 		break;
1807 
1808 	default:
1809 		return (EACCES);
1810 	}
1811 
1812 	return (0);
1813 }
1814 
1815 static int
1816 mac_mls_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
1817     struct label *shmseglabel, int shmflg)
1818 {
1819 	struct mac_mls *subj, *obj;
1820 
1821 	if (!mac_mls_enabled)
1822 		return (0);
1823 
1824 	subj = SLOT(cred->cr_label);
1825 	obj = SLOT(shmseglabel);
1826 
1827 	if (!mac_mls_dominate_effective(obj, subj))
1828 		return (EACCES);
1829 
1830 	return (0);
1831 }
1832 
1833 static int
1834 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1835     struct label *mntlabel)
1836 {
1837 	struct mac_mls *subj, *obj;
1838 
1839 	if (!mac_mls_enabled)
1840 		return (0);
1841 
1842 	subj = SLOT(cred->cr_label);
1843 	obj = SLOT(mntlabel);
1844 
1845 	if (!mac_mls_dominate_effective(subj, obj))
1846 		return (EACCES);
1847 
1848 	return (0);
1849 }
1850 
1851 static int
1852 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1853     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1854 {
1855 
1856 	if(!mac_mls_enabled)
1857 		return (0);
1858 
1859 	/* XXX: This will be implemented soon... */
1860 
1861 	return (0);
1862 }
1863 
1864 static int
1865 mac_mls_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1866     struct label *pipelabel)
1867 {
1868 	struct mac_mls *subj, *obj;
1869 
1870 	if (!mac_mls_enabled)
1871 		return (0);
1872 
1873 	subj = SLOT(cred->cr_label);
1874 	obj = SLOT((pipelabel));
1875 
1876 	if (!mac_mls_dominate_effective(subj, obj))
1877 		return (EACCES);
1878 
1879 	return (0);
1880 }
1881 
1882 static int
1883 mac_mls_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1884     struct label *pipelabel)
1885 {
1886 	struct mac_mls *subj, *obj;
1887 
1888 	if (!mac_mls_enabled)
1889 		return (0);
1890 
1891 	subj = SLOT(cred->cr_label);
1892 	obj = SLOT((pipelabel));
1893 
1894 	if (!mac_mls_dominate_effective(subj, obj))
1895 		return (EACCES);
1896 
1897 	return (0);
1898 }
1899 
1900 static int
1901 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1902     struct label *pipelabel, struct label *newlabel)
1903 {
1904 	struct mac_mls *subj, *obj, *new;
1905 	int error;
1906 
1907 	new = SLOT(newlabel);
1908 	subj = SLOT(cred->cr_label);
1909 	obj = SLOT(pipelabel);
1910 
1911 	/*
1912 	 * If there is an MLS label update for a pipe, it must be a
1913 	 * effective update.
1914 	 */
1915 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1916 	if (error)
1917 		return (error);
1918 
1919 	/*
1920 	 * To perform a relabel of a pipe (MLS label or not), MLS must
1921 	 * authorize the relabel.
1922 	 */
1923 	if (!mac_mls_effective_in_range(obj, subj))
1924 		return (EPERM);
1925 
1926 	/*
1927 	 * If the MLS label is to be changed, authorize as appropriate.
1928 	 */
1929 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1930 		/*
1931 		 * To change the MLS label on a pipe, the new pipe label
1932 		 * must be in the subject range.
1933 		 */
1934 		if (!mac_mls_effective_in_range(new, subj))
1935 			return (EPERM);
1936 
1937 		/*
1938 		 * To change the MLS label on a pipe to be EQUAL, the
1939 		 * subject must have appropriate privilege.
1940 		 */
1941 		if (mac_mls_contains_equal(new)) {
1942 			error = mac_mls_subject_privileged(subj);
1943 			if (error)
1944 				return (error);
1945 		}
1946 	}
1947 
1948 	return (0);
1949 }
1950 
1951 static int
1952 mac_mls_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
1953     struct label *pipelabel)
1954 {
1955 	struct mac_mls *subj, *obj;
1956 
1957 	if (!mac_mls_enabled)
1958 		return (0);
1959 
1960 	subj = SLOT(cred->cr_label);
1961 	obj = SLOT((pipelabel));
1962 
1963 	if (!mac_mls_dominate_effective(subj, obj))
1964 		return (EACCES);
1965 
1966 	return (0);
1967 }
1968 
1969 static int
1970 mac_mls_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1971     struct label *pipelabel)
1972 {
1973 	struct mac_mls *subj, *obj;
1974 
1975 	if (!mac_mls_enabled)
1976 		return (0);
1977 
1978 	subj = SLOT(cred->cr_label);
1979 	obj = SLOT((pipelabel));
1980 
1981 	if (!mac_mls_dominate_effective(obj, subj))
1982 		return (EACCES);
1983 
1984 	return (0);
1985 }
1986 
1987 static int
1988 mac_mls_check_posix_sem_write(struct ucred *cred, struct ksem *ksemptr,
1989     struct label *ks_label)
1990 {
1991 	struct mac_mls *subj, *obj;
1992 
1993 	if (!mac_mls_enabled)
1994 		return (0);
1995 
1996 	subj = SLOT(cred->cr_label);
1997 	obj = SLOT(ks_label);
1998 
1999 	if (!mac_mls_dominate_effective(obj, subj))
2000 		return (EACCES);
2001 
2002 	return (0);
2003 }
2004 
2005 static int
2006 mac_mls_check_posix_sem_rdonly(struct ucred *cred, struct ksem *ksemptr,
2007     struct label *ks_label)
2008 {
2009 	struct mac_mls *subj, *obj;
2010 
2011 	if (!mac_mls_enabled)
2012 		return (0);
2013 
2014 	subj = SLOT(cred->cr_label);
2015 	obj = SLOT(ks_label);
2016 
2017 	if (!mac_mls_dominate_effective(subj, obj))
2018 		return (EACCES);
2019 
2020 	return (0);
2021 }
2022 
2023 static int
2024 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
2025 {
2026 	struct mac_mls *subj, *obj;
2027 
2028 	if (!mac_mls_enabled)
2029 		return (0);
2030 
2031 	subj = SLOT(cred->cr_label);
2032 	obj = SLOT(proc->p_ucred->cr_label);
2033 
2034 	/* XXX: range checks */
2035 	if (!mac_mls_dominate_effective(subj, obj))
2036 		return (ESRCH);
2037 	if (!mac_mls_dominate_effective(obj, subj))
2038 		return (EACCES);
2039 
2040 	return (0);
2041 }
2042 
2043 static int
2044 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
2045 {
2046 	struct mac_mls *subj, *obj;
2047 
2048 	if (!mac_mls_enabled)
2049 		return (0);
2050 
2051 	subj = SLOT(cred->cr_label);
2052 	obj = SLOT(proc->p_ucred->cr_label);
2053 
2054 	/* XXX: range checks */
2055 	if (!mac_mls_dominate_effective(subj, obj))
2056 		return (ESRCH);
2057 	if (!mac_mls_dominate_effective(obj, subj))
2058 		return (EACCES);
2059 
2060 	return (0);
2061 }
2062 
2063 static int
2064 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2065 {
2066 	struct mac_mls *subj, *obj;
2067 
2068 	if (!mac_mls_enabled)
2069 		return (0);
2070 
2071 	subj = SLOT(cred->cr_label);
2072 	obj = SLOT(proc->p_ucred->cr_label);
2073 
2074 	/* XXX: range checks */
2075 	if (!mac_mls_dominate_effective(subj, obj))
2076 		return (ESRCH);
2077 	if (!mac_mls_dominate_effective(obj, subj))
2078 		return (EACCES);
2079 
2080 	return (0);
2081 }
2082 
2083 static int
2084 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
2085     struct mbuf *m, struct label *mbuflabel)
2086 {
2087 	struct mac_mls *p, *s;
2088 
2089 	if (!mac_mls_enabled)
2090 		return (0);
2091 
2092 	p = SLOT(mbuflabel);
2093 	s = SLOT(socketlabel);
2094 
2095 	return (mac_mls_equal_effective(p, s) ? 0 : EACCES);
2096 }
2097 
2098 static int
2099 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
2100     struct label *socketlabel, struct label *newlabel)
2101 {
2102 	struct mac_mls *subj, *obj, *new;
2103 	int error;
2104 
2105 	new = SLOT(newlabel);
2106 	subj = SLOT(cred->cr_label);
2107 	obj = SLOT(socketlabel);
2108 
2109 	/*
2110 	 * If there is an MLS label update for the socket, it may be
2111 	 * an update of effective.
2112 	 */
2113 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2114 	if (error)
2115 		return (error);
2116 
2117 	/*
2118 	 * To relabel a socket, the old socket effective must be in the subject
2119 	 * range.
2120 	 */
2121 	if (!mac_mls_effective_in_range(obj, subj))
2122 		return (EPERM);
2123 
2124 	/*
2125 	 * If the MLS label is to be changed, authorize as appropriate.
2126 	 */
2127 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2128 		/*
2129 		 * To relabel a socket, the new socket effective must be in
2130 		 * the subject range.
2131 		 */
2132 		if (!mac_mls_effective_in_range(new, subj))
2133 			return (EPERM);
2134 
2135 		/*
2136 		 * To change the MLS label on the socket to contain EQUAL,
2137 		 * the subject must have appropriate privilege.
2138 		 */
2139 		if (mac_mls_contains_equal(new)) {
2140 			error = mac_mls_subject_privileged(subj);
2141 			if (error)
2142 				return (error);
2143 		}
2144 	}
2145 
2146 	return (0);
2147 }
2148 
2149 static int
2150 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
2151     struct label *socketlabel)
2152 {
2153 	struct mac_mls *subj, *obj;
2154 
2155 	if (!mac_mls_enabled)
2156 		return (0);
2157 
2158 	subj = SLOT(cred->cr_label);
2159 	obj = SLOT(socketlabel);
2160 
2161 	if (!mac_mls_dominate_effective(subj, obj))
2162 		return (ENOENT);
2163 
2164 	return (0);
2165 }
2166 
2167 static int
2168 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp,
2169     struct label *label)
2170 {
2171 	struct mac_mls *subj, *obj;
2172 
2173 	if (!mac_mls_enabled)
2174 		return (0);
2175 
2176 	subj = SLOT(cred->cr_label);
2177 	obj = SLOT(label);
2178 
2179 	if (!mac_mls_dominate_effective(obj, subj) ||
2180 	    !mac_mls_dominate_effective(subj, obj))
2181 		return (EACCES);
2182 
2183 	return (0);
2184 }
2185 
2186 static int
2187 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2188     struct label *dlabel)
2189 {
2190 	struct mac_mls *subj, *obj;
2191 
2192 	if (!mac_mls_enabled)
2193 		return (0);
2194 
2195 	subj = SLOT(cred->cr_label);
2196 	obj = SLOT(dlabel);
2197 
2198 	if (!mac_mls_dominate_effective(subj, obj))
2199 		return (EACCES);
2200 
2201 	return (0);
2202 }
2203 
2204 static int
2205 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2206     struct label *dlabel)
2207 {
2208 	struct mac_mls *subj, *obj;
2209 
2210 	if (!mac_mls_enabled)
2211 		return (0);
2212 
2213 	subj = SLOT(cred->cr_label);
2214 	obj = SLOT(dlabel);
2215 
2216 	if (!mac_mls_dominate_effective(subj, obj))
2217 		return (EACCES);
2218 
2219 	return (0);
2220 }
2221 
2222 static int
2223 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2224     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2225 {
2226 	struct mac_mls *subj, *obj;
2227 
2228 	if (!mac_mls_enabled)
2229 		return (0);
2230 
2231 	subj = SLOT(cred->cr_label);
2232 	obj = SLOT(dlabel);
2233 
2234 	if (!mac_mls_dominate_effective(obj, subj))
2235 		return (EACCES);
2236 
2237 	return (0);
2238 }
2239 
2240 static int
2241 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2242     struct label *dlabel, struct vnode *vp, struct label *label,
2243     struct componentname *cnp)
2244 {
2245 	struct mac_mls *subj, *obj;
2246 
2247 	if (!mac_mls_enabled)
2248 		return (0);
2249 
2250 	subj = SLOT(cred->cr_label);
2251 	obj = SLOT(dlabel);
2252 
2253 	if (!mac_mls_dominate_effective(obj, subj))
2254 		return (EACCES);
2255 
2256 	obj = SLOT(label);
2257 
2258 	if (!mac_mls_dominate_effective(obj, subj))
2259 		return (EACCES);
2260 
2261 	return (0);
2262 }
2263 
2264 static int
2265 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2266     struct label *label, acl_type_t type)
2267 {
2268 	struct mac_mls *subj, *obj;
2269 
2270 	if (!mac_mls_enabled)
2271 		return (0);
2272 
2273 	subj = SLOT(cred->cr_label);
2274 	obj = SLOT(label);
2275 
2276 	if (!mac_mls_dominate_effective(obj, subj))
2277 		return (EACCES);
2278 
2279 	return (0);
2280 }
2281 
2282 static int
2283 mac_mls_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2284     struct label *label, int attrnamespace, const char *name)
2285 {
2286 	struct mac_mls *subj, *obj;
2287 
2288 	if (!mac_mls_enabled)
2289 		return (0);
2290 
2291 	subj = SLOT(cred->cr_label);
2292 	obj = SLOT(label);
2293 
2294 	if (!mac_mls_dominate_effective(obj, subj))
2295 		return (EACCES);
2296 
2297 	return (0);
2298 }
2299 
2300 static int
2301 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2302     struct label *label, struct image_params *imgp,
2303     struct label *execlabel)
2304 {
2305 	struct mac_mls *subj, *obj, *exec;
2306 	int error;
2307 
2308 	if (execlabel != NULL) {
2309 		/*
2310 		 * We currently don't permit labels to be changed at
2311 		 * exec-time as part of MLS, so disallow non-NULL
2312 		 * MLS label elements in the execlabel.
2313 		 */
2314 		exec = SLOT(execlabel);
2315 		error = mls_atmostflags(exec, 0);
2316 		if (error)
2317 			return (error);
2318 	}
2319 
2320 	if (!mac_mls_enabled)
2321 		return (0);
2322 
2323 	subj = SLOT(cred->cr_label);
2324 	obj = SLOT(label);
2325 
2326 	if (!mac_mls_dominate_effective(subj, obj))
2327 		return (EACCES);
2328 
2329 	return (0);
2330 }
2331 
2332 static int
2333 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2334     struct label *label, acl_type_t type)
2335 {
2336 	struct mac_mls *subj, *obj;
2337 
2338 	if (!mac_mls_enabled)
2339 		return (0);
2340 
2341 	subj = SLOT(cred->cr_label);
2342 	obj = SLOT(label);
2343 
2344 	if (!mac_mls_dominate_effective(subj, obj))
2345 		return (EACCES);
2346 
2347 	return (0);
2348 }
2349 
2350 static int
2351 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2352     struct label *label, int attrnamespace, const char *name, struct uio *uio)
2353 {
2354 	struct mac_mls *subj, *obj;
2355 
2356 	if (!mac_mls_enabled)
2357 		return (0);
2358 
2359 	subj = SLOT(cred->cr_label);
2360 	obj = SLOT(label);
2361 
2362 	if (!mac_mls_dominate_effective(subj, obj))
2363 		return (EACCES);
2364 
2365 	return (0);
2366 }
2367 
2368 static int
2369 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2370     struct label *dlabel, struct vnode *vp, struct label *label,
2371     struct componentname *cnp)
2372 {
2373 	struct mac_mls *subj, *obj;
2374 
2375 	if (!mac_mls_enabled)
2376 		return (0);
2377 
2378 	subj = SLOT(cred->cr_label);
2379 	obj = SLOT(dlabel);
2380 
2381 	if (!mac_mls_dominate_effective(obj, subj))
2382 		return (EACCES);
2383 
2384 	obj = SLOT(dlabel);
2385 	if (!mac_mls_dominate_effective(obj, subj))
2386 		return (EACCES);
2387 
2388 	return (0);
2389 }
2390 
2391 static int
2392 mac_mls_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2393     struct label *label, int attrnamespace)
2394 {
2395 
2396 	struct mac_mls *subj, *obj;
2397 
2398 	if (!mac_mls_enabled)
2399 		return (0);
2400 
2401 	subj = SLOT(cred->cr_label);
2402 	obj = SLOT(label);
2403 
2404 	if (!mac_mls_dominate_effective(subj, obj))
2405 		return (EACCES);
2406 
2407 	return (0);
2408 }
2409 
2410 static int
2411 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2412     struct label *dlabel, struct componentname *cnp)
2413 {
2414 	struct mac_mls *subj, *obj;
2415 
2416 	if (!mac_mls_enabled)
2417 		return (0);
2418 
2419 	subj = SLOT(cred->cr_label);
2420 	obj = SLOT(dlabel);
2421 
2422 	if (!mac_mls_dominate_effective(subj, obj))
2423 		return (EACCES);
2424 
2425 	return (0);
2426 }
2427 
2428 static int
2429 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2430     struct label *label, int prot, int flags)
2431 {
2432 	struct mac_mls *subj, *obj;
2433 
2434 	/*
2435 	 * Rely on the use of open()-time protections to handle
2436 	 * non-revocation cases.
2437 	 */
2438 	if (!mac_mls_enabled || !revocation_enabled)
2439 		return (0);
2440 
2441 	subj = SLOT(cred->cr_label);
2442 	obj = SLOT(label);
2443 
2444 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2445 		if (!mac_mls_dominate_effective(subj, obj))
2446 			return (EACCES);
2447 	}
2448 	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2449 		if (!mac_mls_dominate_effective(obj, subj))
2450 			return (EACCES);
2451 	}
2452 
2453 	return (0);
2454 }
2455 
2456 static int
2457 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2458     struct label *vnodelabel, int acc_mode)
2459 {
2460 	struct mac_mls *subj, *obj;
2461 
2462 	if (!mac_mls_enabled)
2463 		return (0);
2464 
2465 	subj = SLOT(cred->cr_label);
2466 	obj = SLOT(vnodelabel);
2467 
2468 	/* XXX privilege override for admin? */
2469 	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2470 		if (!mac_mls_dominate_effective(subj, obj))
2471 			return (EACCES);
2472 	}
2473 	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2474 		if (!mac_mls_dominate_effective(obj, subj))
2475 			return (EACCES);
2476 	}
2477 
2478 	return (0);
2479 }
2480 
2481 static int
2482 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2483     struct vnode *vp, struct label *label)
2484 {
2485 	struct mac_mls *subj, *obj;
2486 
2487 	if (!mac_mls_enabled || !revocation_enabled)
2488 		return (0);
2489 
2490 	subj = SLOT(active_cred->cr_label);
2491 	obj = SLOT(label);
2492 
2493 	if (!mac_mls_dominate_effective(subj, obj))
2494 		return (EACCES);
2495 
2496 	return (0);
2497 }
2498 
2499 static int
2500 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2501     struct vnode *vp, struct label *label)
2502 {
2503 	struct mac_mls *subj, *obj;
2504 
2505 	if (!mac_mls_enabled || !revocation_enabled)
2506 		return (0);
2507 
2508 	subj = SLOT(active_cred->cr_label);
2509 	obj = SLOT(label);
2510 
2511 	if (!mac_mls_dominate_effective(subj, obj))
2512 		return (EACCES);
2513 
2514 	return (0);
2515 }
2516 
2517 static int
2518 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2519     struct label *dlabel)
2520 {
2521 	struct mac_mls *subj, *obj;
2522 
2523 	if (!mac_mls_enabled)
2524 		return (0);
2525 
2526 	subj = SLOT(cred->cr_label);
2527 	obj = SLOT(dlabel);
2528 
2529 	if (!mac_mls_dominate_effective(subj, obj))
2530 		return (EACCES);
2531 
2532 	return (0);
2533 }
2534 
2535 static int
2536 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2537     struct label *vnodelabel)
2538 {
2539 	struct mac_mls *subj, *obj;
2540 
2541 	if (!mac_mls_enabled)
2542 		return (0);
2543 
2544 	subj = SLOT(cred->cr_label);
2545 	obj = SLOT(vnodelabel);
2546 
2547 	if (!mac_mls_dominate_effective(subj, obj))
2548 		return (EACCES);
2549 
2550 	return (0);
2551 }
2552 
2553 static int
2554 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2555     struct label *vnodelabel, struct label *newlabel)
2556 {
2557 	struct mac_mls *old, *new, *subj;
2558 	int error;
2559 
2560 	old = SLOT(vnodelabel);
2561 	new = SLOT(newlabel);
2562 	subj = SLOT(cred->cr_label);
2563 
2564 	/*
2565 	 * If there is an MLS label update for the vnode, it must be a
2566 	 * effective label.
2567 	 */
2568 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2569 	if (error)
2570 		return (error);
2571 
2572 	/*
2573 	 * To perform a relabel of the vnode (MLS label or not), MLS must
2574 	 * authorize the relabel.
2575 	 */
2576 	if (!mac_mls_effective_in_range(old, subj))
2577 		return (EPERM);
2578 
2579 	/*
2580 	 * If the MLS label is to be changed, authorize as appropriate.
2581 	 */
2582 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2583 		/*
2584 		 * To change the MLS label on a vnode, the new vnode label
2585 		 * must be in the subject range.
2586 		 */
2587 		if (!mac_mls_effective_in_range(new, subj))
2588 			return (EPERM);
2589 
2590 		/*
2591 		 * To change the MLS label on the vnode to be EQUAL,
2592 		 * the subject must have appropriate privilege.
2593 		 */
2594 		if (mac_mls_contains_equal(new)) {
2595 			error = mac_mls_subject_privileged(subj);
2596 			if (error)
2597 				return (error);
2598 		}
2599 	}
2600 
2601 	return (0);
2602 }
2603 
2604 
2605 static int
2606 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2607     struct label *dlabel, struct vnode *vp, struct label *label,
2608     struct componentname *cnp)
2609 {
2610 	struct mac_mls *subj, *obj;
2611 
2612 	if (!mac_mls_enabled)
2613 		return (0);
2614 
2615 	subj = SLOT(cred->cr_label);
2616 	obj = SLOT(dlabel);
2617 
2618 	if (!mac_mls_dominate_effective(obj, subj))
2619 		return (EACCES);
2620 
2621 	obj = SLOT(label);
2622 
2623 	if (!mac_mls_dominate_effective(obj, subj))
2624 		return (EACCES);
2625 
2626 	return (0);
2627 }
2628 
2629 static int
2630 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2631     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2632     struct componentname *cnp)
2633 {
2634 	struct mac_mls *subj, *obj;
2635 
2636 	if (!mac_mls_enabled)
2637 		return (0);
2638 
2639 	subj = SLOT(cred->cr_label);
2640 	obj = SLOT(dlabel);
2641 
2642 	if (!mac_mls_dominate_effective(obj, subj))
2643 		return (EACCES);
2644 
2645 	if (vp != NULL) {
2646 		obj = SLOT(label);
2647 
2648 		if (!mac_mls_dominate_effective(obj, subj))
2649 			return (EACCES);
2650 	}
2651 
2652 	return (0);
2653 }
2654 
2655 static int
2656 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2657     struct label *label)
2658 {
2659 	struct mac_mls *subj, *obj;
2660 
2661 	if (!mac_mls_enabled)
2662 		return (0);
2663 
2664 	subj = SLOT(cred->cr_label);
2665 	obj = SLOT(label);
2666 
2667 	if (!mac_mls_dominate_effective(obj, subj))
2668 		return (EACCES);
2669 
2670 	return (0);
2671 }
2672 
2673 static int
2674 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2675     struct label *label, acl_type_t type, struct acl *acl)
2676 {
2677 	struct mac_mls *subj, *obj;
2678 
2679 	if (!mac_mls_enabled)
2680 		return (0);
2681 
2682 	subj = SLOT(cred->cr_label);
2683 	obj = SLOT(label);
2684 
2685 	if (!mac_mls_dominate_effective(obj, subj))
2686 		return (EACCES);
2687 
2688 	return (0);
2689 }
2690 
2691 static int
2692 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2693     struct label *vnodelabel, int attrnamespace, const char *name,
2694     struct uio *uio)
2695 {
2696 	struct mac_mls *subj, *obj;
2697 
2698 	if (!mac_mls_enabled)
2699 		return (0);
2700 
2701 	subj = SLOT(cred->cr_label);
2702 	obj = SLOT(vnodelabel);
2703 
2704 	if (!mac_mls_dominate_effective(obj, subj))
2705 		return (EACCES);
2706 
2707 	/* XXX: protect the MAC EA in a special way? */
2708 
2709 	return (0);
2710 }
2711 
2712 static int
2713 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2714     struct label *vnodelabel, u_long flags)
2715 {
2716 	struct mac_mls *subj, *obj;
2717 
2718 	if (!mac_mls_enabled)
2719 		return (0);
2720 
2721 	subj = SLOT(cred->cr_label);
2722 	obj = SLOT(vnodelabel);
2723 
2724 	if (!mac_mls_dominate_effective(obj, subj))
2725 		return (EACCES);
2726 
2727 	return (0);
2728 }
2729 
2730 static int
2731 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2732     struct label *vnodelabel, mode_t mode)
2733 {
2734 	struct mac_mls *subj, *obj;
2735 
2736 	if (!mac_mls_enabled)
2737 		return (0);
2738 
2739 	subj = SLOT(cred->cr_label);
2740 	obj = SLOT(vnodelabel);
2741 
2742 	if (!mac_mls_dominate_effective(obj, subj))
2743 		return (EACCES);
2744 
2745 	return (0);
2746 }
2747 
2748 static int
2749 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2750     struct label *vnodelabel, uid_t uid, gid_t gid)
2751 {
2752 	struct mac_mls *subj, *obj;
2753 
2754 	if (!mac_mls_enabled)
2755 		return (0);
2756 
2757 	subj = SLOT(cred->cr_label);
2758 	obj = SLOT(vnodelabel);
2759 
2760 	if (!mac_mls_dominate_effective(obj, subj))
2761 		return (EACCES);
2762 
2763 	return (0);
2764 }
2765 
2766 static int
2767 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2768     struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2769 {
2770 	struct mac_mls *subj, *obj;
2771 
2772 	if (!mac_mls_enabled)
2773 		return (0);
2774 
2775 	subj = SLOT(cred->cr_label);
2776 	obj = SLOT(vnodelabel);
2777 
2778 	if (!mac_mls_dominate_effective(obj, subj))
2779 		return (EACCES);
2780 
2781 	return (0);
2782 }
2783 
2784 static int
2785 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2786     struct vnode *vp, struct label *vnodelabel)
2787 {
2788 	struct mac_mls *subj, *obj;
2789 
2790 	if (!mac_mls_enabled)
2791 		return (0);
2792 
2793 	subj = SLOT(active_cred->cr_label);
2794 	obj = SLOT(vnodelabel);
2795 
2796 	if (!mac_mls_dominate_effective(subj, obj))
2797 		return (EACCES);
2798 
2799 	return (0);
2800 }
2801 
2802 static int
2803 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2804     struct vnode *vp, struct label *label)
2805 {
2806 	struct mac_mls *subj, *obj;
2807 
2808 	if (!mac_mls_enabled || !revocation_enabled)
2809 		return (0);
2810 
2811 	subj = SLOT(active_cred->cr_label);
2812 	obj = SLOT(label);
2813 
2814 	if (!mac_mls_dominate_effective(obj, subj))
2815 		return (EACCES);
2816 
2817 	return (0);
2818 }
2819 
2820 static void
2821 mac_mls_associate_nfsd_label(struct ucred *cred)
2822 {
2823 	struct mac_mls *label;
2824 
2825 	label = SLOT(cred->cr_label);
2826 	mac_mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
2827 	mac_mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL,
2828 	    MAC_MLS_TYPE_HIGH, 0, NULL);
2829 }
2830 
2831 static struct mac_policy_ops mac_mls_ops =
2832 {
2833 	.mpo_init = mac_mls_init,
2834 	.mpo_init_bpfdesc_label = mac_mls_init_label,
2835 	.mpo_init_cred_label = mac_mls_init_label,
2836 	.mpo_init_devfsdirent_label = mac_mls_init_label,
2837 	.mpo_init_ifnet_label = mac_mls_init_label,
2838 	.mpo_init_inpcb_label = mac_mls_init_label_waitcheck,
2839 	.mpo_init_syncache_label = mac_mls_init_label_waitcheck,
2840 	.mpo_init_sysv_msgmsg_label = mac_mls_init_label,
2841 	.mpo_init_sysv_msgqueue_label = mac_mls_init_label,
2842 	.mpo_init_sysv_sem_label = mac_mls_init_label,
2843 	.mpo_init_sysv_shm_label = mac_mls_init_label,
2844 	.mpo_init_ipq_label = mac_mls_init_label_waitcheck,
2845 	.mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
2846 	.mpo_init_mount_label = mac_mls_init_label,
2847 	.mpo_init_mount_fs_label = mac_mls_init_label,
2848 	.mpo_init_pipe_label = mac_mls_init_label,
2849 	.mpo_init_posix_sem_label = mac_mls_init_label,
2850 	.mpo_init_socket_label = mac_mls_init_label_waitcheck,
2851 	.mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
2852 	.mpo_init_vnode_label = mac_mls_init_label,
2853 	.mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
2854 	.mpo_destroy_cred_label = mac_mls_destroy_label,
2855 	.mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
2856 	.mpo_destroy_ifnet_label = mac_mls_destroy_label,
2857 	.mpo_destroy_inpcb_label = mac_mls_destroy_label,
2858 	.mpo_destroy_syncache_label = mac_mls_destroy_label,
2859 	.mpo_destroy_sysv_msgmsg_label = mac_mls_destroy_label,
2860 	.mpo_destroy_sysv_msgqueue_label = mac_mls_destroy_label,
2861 	.mpo_destroy_sysv_sem_label = mac_mls_destroy_label,
2862 	.mpo_destroy_sysv_shm_label = mac_mls_destroy_label,
2863 	.mpo_destroy_ipq_label = mac_mls_destroy_label,
2864 	.mpo_destroy_mbuf_label = mac_mls_destroy_label,
2865 	.mpo_destroy_mount_label = mac_mls_destroy_label,
2866 	.mpo_destroy_mount_fs_label = mac_mls_destroy_label,
2867 	.mpo_destroy_pipe_label = mac_mls_destroy_label,
2868 	.mpo_destroy_posix_sem_label = mac_mls_destroy_label,
2869 	.mpo_destroy_socket_label = mac_mls_destroy_label,
2870 	.mpo_destroy_socket_peer_label = mac_mls_destroy_label,
2871 	.mpo_destroy_vnode_label = mac_mls_destroy_label,
2872 	.mpo_copy_cred_label = mac_mls_copy_label,
2873 	.mpo_copy_ifnet_label = mac_mls_copy_label,
2874 	.mpo_copy_mbuf_label = mac_mls_copy_label,
2875 	.mpo_copy_pipe_label = mac_mls_copy_label,
2876 	.mpo_copy_socket_label = mac_mls_copy_label,
2877 	.mpo_copy_vnode_label = mac_mls_copy_label,
2878 	.mpo_externalize_cred_label = mac_mls_externalize_label,
2879 	.mpo_externalize_ifnet_label = mac_mls_externalize_label,
2880 	.mpo_externalize_pipe_label = mac_mls_externalize_label,
2881 	.mpo_externalize_socket_label = mac_mls_externalize_label,
2882 	.mpo_externalize_socket_peer_label = mac_mls_externalize_label,
2883 	.mpo_externalize_vnode_label = mac_mls_externalize_label,
2884 	.mpo_internalize_cred_label = mac_mls_internalize_label,
2885 	.mpo_internalize_ifnet_label = mac_mls_internalize_label,
2886 	.mpo_internalize_pipe_label = mac_mls_internalize_label,
2887 	.mpo_internalize_socket_label = mac_mls_internalize_label,
2888 	.mpo_internalize_vnode_label = mac_mls_internalize_label,
2889 	.mpo_create_devfs_device = mac_mls_create_devfs_device,
2890 	.mpo_create_devfs_directory = mac_mls_create_devfs_directory,
2891 	.mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
2892 	.mpo_create_mount = mac_mls_create_mount,
2893 	.mpo_relabel_vnode = mac_mls_relabel_vnode,
2894 	.mpo_update_devfsdirent = mac_mls_update_devfsdirent,
2895 	.mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
2896 	.mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
2897 	.mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
2898 	.mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
2899 	.mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
2900 	.mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
2901 	.mpo_create_mbuf_from_syncache = mac_mls_create_mbuf_from_syncache,
2902 	.mpo_create_pipe = mac_mls_create_pipe,
2903 	.mpo_create_posix_sem = mac_mls_create_posix_sem,
2904 	.mpo_create_socket = mac_mls_create_socket,
2905 	.mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
2906 	.mpo_relabel_pipe = mac_mls_relabel_pipe,
2907 	.mpo_relabel_socket = mac_mls_relabel_socket,
2908 	.mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
2909 	.mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
2910 	.mpo_create_bpfdesc = mac_mls_create_bpfdesc,
2911 	.mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
2912 	.mpo_create_fragment = mac_mls_create_fragment,
2913 	.mpo_create_ifnet = mac_mls_create_ifnet,
2914 	.mpo_create_inpcb_from_socket = mac_mls_create_inpcb_from_socket,
2915 	.mpo_init_syncache_from_inpcb = mac_mls_init_syncache_from_inpcb,
2916 	.mpo_create_ipq = mac_mls_create_ipq,
2917 	.mpo_create_sysv_msgmsg = mac_mls_create_sysv_msgmsg,
2918 	.mpo_create_sysv_msgqueue = mac_mls_create_sysv_msgqueue,
2919 	.mpo_create_sysv_sem = mac_mls_create_sysv_sem,
2920 	.mpo_create_sysv_shm = mac_mls_create_sysv_shm,
2921 	.mpo_create_mbuf_from_inpcb = mac_mls_create_mbuf_from_inpcb,
2922 	.mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
2923 	.mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
2924 	.mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
2925 	.mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
2926 	.mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
2927 	.mpo_fragment_match = mac_mls_fragment_match,
2928 	.mpo_relabel_ifnet = mac_mls_relabel_ifnet,
2929 	.mpo_update_ipq = mac_mls_update_ipq,
2930 	.mpo_inpcb_sosetlabel = mac_mls_inpcb_sosetlabel,
2931 	.mpo_create_proc0 = mac_mls_create_proc0,
2932 	.mpo_create_proc1 = mac_mls_create_proc1,
2933 	.mpo_relabel_cred = mac_mls_relabel_cred,
2934 	.mpo_cleanup_sysv_msgmsg = mac_mls_cleanup_sysv_msgmsg,
2935 	.mpo_cleanup_sysv_msgqueue = mac_mls_cleanup_sysv_msgqueue,
2936 	.mpo_cleanup_sysv_sem = mac_mls_cleanup_sysv_sem,
2937 	.mpo_cleanup_sysv_shm = mac_mls_cleanup_sysv_shm,
2938 	.mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
2939 	.mpo_check_cred_relabel = mac_mls_check_cred_relabel,
2940 	.mpo_check_cred_visible = mac_mls_check_cred_visible,
2941 	.mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
2942 	.mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
2943 	.mpo_check_inpcb_deliver = mac_mls_check_inpcb_deliver,
2944 	.mpo_check_sysv_msgrcv = mac_mls_check_sysv_msgrcv,
2945 	.mpo_check_sysv_msgrmid = mac_mls_check_sysv_msgrmid,
2946 	.mpo_check_sysv_msqget = mac_mls_check_sysv_msqget,
2947 	.mpo_check_sysv_msqsnd = mac_mls_check_sysv_msqsnd,
2948 	.mpo_check_sysv_msqrcv = mac_mls_check_sysv_msqrcv,
2949 	.mpo_check_sysv_msqctl = mac_mls_check_sysv_msqctl,
2950 	.mpo_check_sysv_semctl = mac_mls_check_sysv_semctl,
2951 	.mpo_check_sysv_semget = mac_mls_check_sysv_semget,
2952 	.mpo_check_sysv_semop = mac_mls_check_sysv_semop,
2953 	.mpo_check_sysv_shmat = mac_mls_check_sysv_shmat,
2954 	.mpo_check_sysv_shmctl = mac_mls_check_sysv_shmctl,
2955 	.mpo_check_sysv_shmget = mac_mls_check_sysv_shmget,
2956 	.mpo_check_mount_stat = mac_mls_check_mount_stat,
2957 	.mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
2958 	.mpo_check_pipe_poll = mac_mls_check_pipe_poll,
2959 	.mpo_check_pipe_read = mac_mls_check_pipe_read,
2960 	.mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
2961 	.mpo_check_pipe_stat = mac_mls_check_pipe_stat,
2962 	.mpo_check_pipe_write = mac_mls_check_pipe_write,
2963 	.mpo_check_posix_sem_destroy = mac_mls_check_posix_sem_write,
2964 	.mpo_check_posix_sem_getvalue = mac_mls_check_posix_sem_rdonly,
2965 	.mpo_check_posix_sem_open = mac_mls_check_posix_sem_write,
2966 	.mpo_check_posix_sem_post = mac_mls_check_posix_sem_write,
2967 	.mpo_check_posix_sem_unlink = mac_mls_check_posix_sem_write,
2968 	.mpo_check_posix_sem_wait = mac_mls_check_posix_sem_write,
2969 	.mpo_check_proc_debug = mac_mls_check_proc_debug,
2970 	.mpo_check_proc_sched = mac_mls_check_proc_sched,
2971 	.mpo_check_proc_signal = mac_mls_check_proc_signal,
2972 	.mpo_check_socket_deliver = mac_mls_check_socket_deliver,
2973 	.mpo_check_socket_relabel = mac_mls_check_socket_relabel,
2974 	.mpo_check_socket_visible = mac_mls_check_socket_visible,
2975 	.mpo_check_system_swapon = mac_mls_check_system_swapon,
2976 	.mpo_check_vnode_access = mac_mls_check_vnode_open,
2977 	.mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
2978 	.mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
2979 	.mpo_check_vnode_create = mac_mls_check_vnode_create,
2980 	.mpo_check_vnode_delete = mac_mls_check_vnode_delete,
2981 	.mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
2982 	.mpo_check_vnode_deleteextattr = mac_mls_check_vnode_deleteextattr,
2983 	.mpo_check_vnode_exec = mac_mls_check_vnode_exec,
2984 	.mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
2985 	.mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
2986 	.mpo_check_vnode_link = mac_mls_check_vnode_link,
2987 	.mpo_check_vnode_listextattr = mac_mls_check_vnode_listextattr,
2988 	.mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
2989 	.mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
2990 	.mpo_check_vnode_open = mac_mls_check_vnode_open,
2991 	.mpo_check_vnode_poll = mac_mls_check_vnode_poll,
2992 	.mpo_check_vnode_read = mac_mls_check_vnode_read,
2993 	.mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
2994 	.mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
2995 	.mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
2996 	.mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
2997 	.mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
2998 	.mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
2999 	.mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
3000 	.mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
3001 	.mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
3002 	.mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
3003 	.mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
3004 	.mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
3005 	.mpo_check_vnode_stat = mac_mls_check_vnode_stat,
3006 	.mpo_check_vnode_write = mac_mls_check_vnode_write,
3007 	.mpo_associate_nfsd_label = mac_mls_associate_nfsd_label,
3008 	.mpo_create_mbuf_from_firewall = mac_mls_create_mbuf_from_firewall,
3009 };
3010 
3011 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3012     MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);
3013