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