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