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