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