xref: /freebsd/sys/security/mac_mls/mac_mls.c (revision 263d6a7ece4f357d01b3152c39e5d36043f877bb)
1 /*-
2  * Copyright (c) 1999-2002 Robert N. M. Watson
3  * Copyright (c) 2001-2005 McAfee, Inc.
4  * All rights reserved.
5  *
6  * This software was developed by Robert Watson for the TrustedBSD Project.
7  *
8  * This software was developed for the FreeBSD Project in part by McAfee
9  * Research, the Security Research Division of McAfee, Inc. under
10  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11  * CHATS research program.
12  *
13  * Redistribution and use in source and binary forms, with or without
14  * modification, are permitted provided that the following conditions
15  * are met:
16  * 1. Redistributions of source code must retain the above copyright
17  *    notice, this list of conditions and the following disclaimer.
18  * 2. Redistributions in binary form must reproduce the above copyright
19  *    notice, this list of conditions and the following disclaimer in the
20  *    documentation and/or other materials provided with the distribution.
21  *
22  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32  * SUCH DAMAGE.
33  *
34  * $FreeBSD$
35  */
36 
37 /*
38  * Developed by the TrustedBSD Project.
39  * MLS fixed label mandatory confidentiality policy.
40  */
41 
42 #include <sys/types.h>
43 #include <sys/param.h>
44 #include <sys/acl.h>
45 #include <sys/conf.h>
46 #include <sys/extattr.h>
47 #include <sys/kernel.h>
48 #include <sys/mac.h>
49 #include <sys/mman.h>
50 #include <sys/malloc.h>
51 #include <sys/mount.h>
52 #include <sys/proc.h>
53 #include <sys/sbuf.h>
54 #include <sys/systm.h>
55 #include <sys/sysproto.h>
56 #include <sys/sysent.h>
57 #include <sys/systm.h>
58 #include <sys/vnode.h>
59 #include <sys/file.h>
60 #include <sys/socket.h>
61 #include <sys/socketvar.h>
62 #include <sys/pipe.h>
63 #include <sys/sysctl.h>
64 #include <sys/msg.h>
65 #include <sys/sem.h>
66 #include <sys/shm.h>
67 
68 #include <fs/devfs/devfs.h>
69 
70 #include <net/bpfdesc.h>
71 #include <net/if.h>
72 #include <net/if_types.h>
73 #include <net/if_var.h>
74 
75 #include <netinet/in.h>
76 #include <netinet/in_pcb.h>
77 #include <netinet/ip_var.h>
78 
79 #include <vm/uma.h>
80 #include <vm/vm.h>
81 
82 #include <sys/mac_policy.h>
83 
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 *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
120 #define	SLOT_SET(l, val) (LABEL_TO_SLOT((l), mac_mls_slot).l_ptr = (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 mount *mp, struct cdev *dev,
748     struct devfs_dirent *devfs_dirent, struct label *label)
749 {
750 	struct mac_mls *mac_mls;
751 	int mls_type;
752 
753 	mac_mls = SLOT(label);
754 	if (strcmp(dev->si_name, "null") == 0 ||
755 	    strcmp(dev->si_name, "zero") == 0 ||
756 	    strcmp(dev->si_name, "random") == 0 ||
757 	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
758 		mls_type = MAC_MLS_TYPE_EQUAL;
759 	else if (strcmp(dev->si_name, "kmem") == 0 ||
760 	    strcmp(dev->si_name, "mem") == 0)
761 		mls_type = MAC_MLS_TYPE_HIGH;
762 	else if (ptys_equal &&
763 	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
764 	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
765 		mls_type = MAC_MLS_TYPE_EQUAL;
766 	else
767 		mls_type = MAC_MLS_TYPE_LOW;
768 	mac_mls_set_effective(mac_mls, mls_type, 0, NULL);
769 }
770 
771 static void
772 mac_mls_create_devfs_directory(struct mount *mp, char *dirname,
773     int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
774 {
775 	struct mac_mls *mac_mls;
776 
777 	mac_mls = SLOT(label);
778 	mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
779 }
780 
781 static void
782 mac_mls_create_devfs_symlink(struct ucred *cred, struct mount *mp,
783     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
784     struct label *delabel)
785 {
786 	struct mac_mls *source, *dest;
787 
788 	source = SLOT(cred->cr_label);
789 	dest = SLOT(delabel);
790 
791 	mac_mls_copy_effective(source, dest);
792 }
793 
794 static void
795 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
796     struct label *mntlabel, struct label *fslabel)
797 {
798 	struct mac_mls *source, *dest;
799 
800 	source = SLOT(cred->cr_label);
801 	dest = SLOT(mntlabel);
802 	mac_mls_copy_effective(source, dest);
803 	dest = SLOT(fslabel);
804 	mac_mls_copy_effective(source, dest);
805 }
806 
807 static void
808 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
809     struct label *mntlabel, struct label *fslabel)
810 {
811 	struct mac_mls *mac_mls;
812 
813 	/* Always mount root as high integrity. */
814 	mac_mls = SLOT(fslabel);
815 	mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
816 	mac_mls = SLOT(mntlabel);
817 	mac_mls_set_effective(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
818 }
819 
820 static void
821 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
822     struct label *vnodelabel, struct label *label)
823 {
824 	struct mac_mls *source, *dest;
825 
826 	source = SLOT(label);
827 	dest = SLOT(vnodelabel);
828 
829 	mac_mls_copy(source, dest);
830 }
831 
832 static void
833 mac_mls_update_devfsdirent(struct mount *mp,
834     struct devfs_dirent *devfs_dirent, struct label *direntlabel,
835     struct vnode *vp, struct label *vnodelabel)
836 {
837 	struct mac_mls *source, *dest;
838 
839 	source = SLOT(vnodelabel);
840 	dest = SLOT(direntlabel);
841 
842 	mac_mls_copy_effective(source, dest);
843 }
844 
845 static void
846 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
847     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
848     struct label *vlabel)
849 {
850 	struct mac_mls *source, *dest;
851 
852 	source = SLOT(delabel);
853 	dest = SLOT(vlabel);
854 
855 	mac_mls_copy_effective(source, dest);
856 }
857 
858 static int
859 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
860     struct vnode *vp, struct label *vlabel)
861 {
862 	struct mac_mls temp, *source, *dest;
863 	int buflen, error;
864 
865 	source = SLOT(fslabel);
866 	dest = SLOT(vlabel);
867 
868 	buflen = sizeof(temp);
869 	bzero(&temp, buflen);
870 
871 	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
872 	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
873 	if (error == ENOATTR || error == EOPNOTSUPP) {
874 		/* Fall back to the fslabel. */
875 		mac_mls_copy_effective(source, dest);
876 		return (0);
877 	} else if (error)
878 		return (error);
879 
880 	if (buflen != sizeof(temp)) {
881 		printf("mac_mls_associate_vnode_extattr: bad size %d\n",
882 		    buflen);
883 		return (EPERM);
884 	}
885 	if (mac_mls_valid(&temp) != 0) {
886 		printf("mac_mls_associate_vnode_extattr: invalid\n");
887 		return (EPERM);
888 	}
889 	if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_EFFECTIVE) {
890 		printf("mac_mls_associated_vnode_extattr: not effective\n");
891 		return (EPERM);
892 	}
893 
894 	mac_mls_copy_effective(&temp, dest);
895 	return (0);
896 }
897 
898 static void
899 mac_mls_associate_vnode_singlelabel(struct mount *mp,
900     struct label *fslabel, struct vnode *vp, struct label *vlabel)
901 {
902 	struct mac_mls *source, *dest;
903 
904 	source = SLOT(fslabel);
905 	dest = SLOT(vlabel);
906 
907 	mac_mls_copy_effective(source, dest);
908 }
909 
910 static int
911 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
912     struct label *fslabel, struct vnode *dvp, struct label *dlabel,
913     struct vnode *vp, struct label *vlabel, struct componentname *cnp)
914 {
915 	struct mac_mls *source, *dest, temp;
916 	size_t buflen;
917 	int error;
918 
919 	buflen = sizeof(temp);
920 	bzero(&temp, buflen);
921 
922 	source = SLOT(cred->cr_label);
923 	dest = SLOT(vlabel);
924 	mac_mls_copy_effective(source, &temp);
925 
926 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
927 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
928 	if (error == 0)
929 		mac_mls_copy_effective(source, dest);
930 	return (error);
931 }
932 
933 static int
934 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
935     struct label *vlabel, struct label *intlabel)
936 {
937 	struct mac_mls *source, temp;
938 	size_t buflen;
939 	int error;
940 
941 	buflen = sizeof(temp);
942 	bzero(&temp, buflen);
943 
944 	source = SLOT(intlabel);
945 	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
946 		return (0);
947 
948 	mac_mls_copy_effective(source, &temp);
949 
950 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
951 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
952 	return (error);
953 }
954 
955 /*
956  * Labeling event operations: IPC object.
957  */
958 static void
959 mac_mls_create_inpcb_from_socket(struct socket *so, struct label *solabel,
960     struct inpcb *inp, struct label *inplabel)
961 {
962 	struct mac_mls *source, *dest;
963 
964 	source = SLOT(solabel);
965 	dest = SLOT(inplabel);
966 
967 	mac_mls_copy_effective(source, dest);
968 }
969 
970 static void
971 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
972     struct mbuf *m, struct label *mbuflabel)
973 {
974 	struct mac_mls *source, *dest;
975 
976 	source = SLOT(socketlabel);
977 	dest = SLOT(mbuflabel);
978 
979 	mac_mls_copy_effective(source, dest);
980 }
981 
982 static void
983 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
984     struct label *socketlabel)
985 {
986 	struct mac_mls *source, *dest;
987 
988 	source = SLOT(cred->cr_label);
989 	dest = SLOT(socketlabel);
990 
991 	mac_mls_copy_effective(source, dest);
992 }
993 
994 static void
995 mac_mls_create_pipe(struct ucred *cred, struct pipepair *pp,
996     struct label *pipelabel)
997 {
998 	struct mac_mls *source, *dest;
999 
1000 	source = SLOT(cred->cr_label);
1001 	dest = SLOT(pipelabel);
1002 
1003 	mac_mls_copy_effective(source, dest);
1004 }
1005 
1006 static void
1007 mac_mls_create_socket_from_socket(struct socket *oldsocket,
1008     struct label *oldsocketlabel, struct socket *newsocket,
1009     struct label *newsocketlabel)
1010 {
1011 	struct mac_mls *source, *dest;
1012 
1013 	source = SLOT(oldsocketlabel);
1014 	dest = SLOT(newsocketlabel);
1015 
1016 	mac_mls_copy_effective(source, dest);
1017 }
1018 
1019 static void
1020 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
1021     struct label *socketlabel, struct label *newlabel)
1022 {
1023 	struct mac_mls *source, *dest;
1024 
1025 	source = SLOT(newlabel);
1026 	dest = SLOT(socketlabel);
1027 
1028 	mac_mls_copy(source, dest);
1029 }
1030 
1031 static void
1032 mac_mls_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1033     struct label *pipelabel, struct label *newlabel)
1034 {
1035 	struct mac_mls *source, *dest;
1036 
1037 	source = SLOT(newlabel);
1038 	dest = SLOT(pipelabel);
1039 
1040 	mac_mls_copy(source, dest);
1041 }
1042 
1043 static void
1044 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1045     struct socket *socket, struct label *socketpeerlabel)
1046 {
1047 	struct mac_mls *source, *dest;
1048 
1049 	source = SLOT(mbuflabel);
1050 	dest = SLOT(socketpeerlabel);
1051 
1052 	mac_mls_copy_effective(source, dest);
1053 }
1054 
1055 /*
1056  * Labeling event operations: System V IPC objects.
1057  */
1058 
1059 static void
1060 mac_mls_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr,
1061     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1062 {
1063 	struct mac_mls *source, *dest;
1064 
1065 	/* Ignore the msgq label */
1066 	source = SLOT(cred->cr_label);
1067 	dest = SLOT(msglabel);
1068 
1069 	mac_mls_copy_effective(source, dest);
1070 }
1071 
1072 static void
1073 mac_mls_create_sysv_msgqueue(struct ucred *cred, struct msqid_kernel *msqkptr,
1074     struct label *msqlabel)
1075 {
1076 	struct mac_mls *source, *dest;
1077 
1078 	source = SLOT(cred->cr_label);
1079 	dest = SLOT(msqlabel);
1080 
1081 	mac_mls_copy_effective(source, dest);
1082 }
1083 
1084 static void
1085 mac_mls_create_sysv_sema(struct ucred *cred, struct semid_kernel *semakptr,
1086     struct label *semalabel)
1087 {
1088 	struct mac_mls *source, *dest;
1089 
1090 	source = SLOT(cred->cr_label);
1091 	dest = SLOT(semalabel);
1092 
1093 	mac_mls_copy_effective(source, dest);
1094 }
1095 
1096 static void
1097 mac_mls_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr,
1098     struct label *shmlabel)
1099 {
1100 	struct mac_mls *source, *dest;
1101 
1102 	source = SLOT(cred->cr_label);
1103 	dest = SLOT(shmlabel);
1104 
1105 	mac_mls_copy_effective(source, dest);
1106 }
1107 
1108 /*
1109  * Labeling event operations: network objects.
1110  */
1111 static void
1112 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
1113     struct label *oldsocketlabel, struct socket *newsocket,
1114     struct label *newsocketpeerlabel)
1115 {
1116 	struct mac_mls *source, *dest;
1117 
1118 	source = SLOT(oldsocketlabel);
1119 	dest = SLOT(newsocketpeerlabel);
1120 
1121 	mac_mls_copy_effective(source, dest);
1122 }
1123 
1124 static void
1125 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1126     struct label *bpflabel)
1127 {
1128 	struct mac_mls *source, *dest;
1129 
1130 	source = SLOT(cred->cr_label);
1131 	dest = SLOT(bpflabel);
1132 
1133 	mac_mls_copy_effective(source, dest);
1134 }
1135 
1136 static void
1137 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1138 {
1139 	struct mac_mls *dest;
1140 	int type;
1141 
1142 	dest = SLOT(ifnetlabel);
1143 
1144 	if (ifnet->if_type == IFT_LOOP)
1145 		type = MAC_MLS_TYPE_EQUAL;
1146 	else
1147 		type = MAC_MLS_TYPE_LOW;
1148 
1149 	mac_mls_set_effective(dest, type, 0, NULL);
1150 	mac_mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1151 }
1152 
1153 static void
1154 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1155     struct ipq *ipq, struct label *ipqlabel)
1156 {
1157 	struct mac_mls *source, *dest;
1158 
1159 	source = SLOT(fragmentlabel);
1160 	dest = SLOT(ipqlabel);
1161 
1162 	mac_mls_copy_effective(source, dest);
1163 }
1164 
1165 static void
1166 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1167     struct mbuf *datagram, struct label *datagramlabel)
1168 {
1169 	struct mac_mls *source, *dest;
1170 
1171 	source = SLOT(ipqlabel);
1172 	dest = SLOT(datagramlabel);
1173 
1174 	/* Just use the head, since we require them all to match. */
1175 	mac_mls_copy_effective(source, dest);
1176 }
1177 
1178 static void
1179 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1180     struct mbuf *fragment, struct label *fragmentlabel)
1181 {
1182 	struct mac_mls *source, *dest;
1183 
1184 	source = SLOT(datagramlabel);
1185 	dest = SLOT(fragmentlabel);
1186 
1187 	mac_mls_copy_effective(source, dest);
1188 }
1189 
1190 static void
1191 mac_mls_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1192     struct mbuf *m, struct label *mlabel)
1193 {
1194 	struct mac_mls *source, *dest;
1195 
1196 	source = SLOT(inplabel);
1197 	dest = SLOT(mlabel);
1198 
1199 	mac_mls_copy_effective(source, dest);
1200 }
1201 
1202 static void
1203 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1204     struct label *oldmbuflabel, struct mbuf *newmbuf,
1205     struct label *newmbuflabel)
1206 {
1207 	struct mac_mls *source, *dest;
1208 
1209 	source = SLOT(oldmbuflabel);
1210 	dest = SLOT(newmbuflabel);
1211 
1212 	/*
1213 	 * Because the source mbuf may not yet have been "created",
1214 	 * just initialized, we do a conditional copy.  Since we don't
1215 	 * allow mbufs to have ranges, do a KASSERT to make sure that
1216 	 * doesn't happen.
1217 	 */
1218 	KASSERT((source->mm_flags & MAC_MLS_FLAG_RANGE) == 0,
1219 	    ("mac_mls_create_mbuf_from_mbuf: source mbuf has range"));
1220 	mac_mls_copy(source, dest);
1221 }
1222 
1223 static void
1224 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1225     struct mbuf *mbuf, struct label *mbuflabel)
1226 {
1227 	struct mac_mls *dest;
1228 
1229 	dest = SLOT(mbuflabel);
1230 
1231 	mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1232 }
1233 
1234 static void
1235 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1236     struct mbuf *mbuf, struct label *mbuflabel)
1237 {
1238 	struct mac_mls *source, *dest;
1239 
1240 	source = SLOT(bpflabel);
1241 	dest = SLOT(mbuflabel);
1242 
1243 	mac_mls_copy_effective(source, dest);
1244 }
1245 
1246 static void
1247 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1248     struct mbuf *m, struct label *mbuflabel)
1249 {
1250 	struct mac_mls *source, *dest;
1251 
1252 	source = SLOT(ifnetlabel);
1253 	dest = SLOT(mbuflabel);
1254 
1255 	mac_mls_copy_effective(source, dest);
1256 }
1257 
1258 static void
1259 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1260     struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1261     struct mbuf *newmbuf, struct label *newmbuflabel)
1262 {
1263 	struct mac_mls *source, *dest;
1264 
1265 	source = SLOT(oldmbuflabel);
1266 	dest = SLOT(newmbuflabel);
1267 
1268 	mac_mls_copy_effective(source, dest);
1269 }
1270 
1271 static void
1272 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1273     struct mbuf *newmbuf, struct label *newmbuflabel)
1274 {
1275 	struct mac_mls *source, *dest;
1276 
1277 	source = SLOT(oldmbuflabel);
1278 	dest = SLOT(newmbuflabel);
1279 
1280 	mac_mls_copy_effective(source, dest);
1281 }
1282 
1283 static int
1284 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1285     struct ipq *ipq, struct label *ipqlabel)
1286 {
1287 	struct mac_mls *a, *b;
1288 
1289 	a = SLOT(ipqlabel);
1290 	b = SLOT(fragmentlabel);
1291 
1292 	return (mac_mls_equal_effective(a, b));
1293 }
1294 
1295 static void
1296 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1297     struct label *ifnetlabel, struct label *newlabel)
1298 {
1299 	struct mac_mls *source, *dest;
1300 
1301 	source = SLOT(newlabel);
1302 	dest = SLOT(ifnetlabel);
1303 
1304 	mac_mls_copy(source, dest);
1305 }
1306 
1307 static void
1308 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1309     struct ipq *ipq, struct label *ipqlabel)
1310 {
1311 
1312 	/* NOOP: we only accept matching labels, so no need to update */
1313 }
1314 
1315 static void
1316 mac_mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1317     struct inpcb *inp, struct label *inplabel)
1318 {
1319 	struct mac_mls *source, *dest;
1320 
1321 	source = SLOT(solabel);
1322 	dest = SLOT(inplabel);
1323 
1324 	mac_mls_copy(source, dest);
1325 }
1326 
1327 /*
1328  * Labeling event operations: processes.
1329  */
1330 static void
1331 mac_mls_create_proc0(struct ucred *cred)
1332 {
1333 	struct mac_mls *dest;
1334 
1335 	dest = SLOT(cred->cr_label);
1336 
1337 	mac_mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1338 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1339 	    0, NULL);
1340 }
1341 
1342 static void
1343 mac_mls_create_proc1(struct ucred *cred)
1344 {
1345 	struct mac_mls *dest;
1346 
1347 	dest = SLOT(cred->cr_label);
1348 
1349 	mac_mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1350 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1351 	    0, NULL);
1352 }
1353 
1354 static void
1355 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1356 {
1357 	struct mac_mls *source, *dest;
1358 
1359 	source = SLOT(newlabel);
1360 	dest = SLOT(cred->cr_label);
1361 
1362 	mac_mls_copy(source, dest);
1363 }
1364 
1365 /*
1366  * Label cleanup/flush operations.
1367  */
1368 static void
1369 mac_mls_cleanup_sysv_msgmsg(struct label *msglabel)
1370 {
1371 
1372 	bzero(SLOT(msglabel), sizeof(struct mac_mls));
1373 }
1374 
1375 static void
1376 mac_mls_cleanup_sysv_msgqueue(struct label *msqlabel)
1377 {
1378 
1379 	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
1380 }
1381 
1382 static void
1383 mac_mls_cleanup_sysv_sema(struct label *semalabel)
1384 {
1385 
1386 	bzero(SLOT(semalabel), sizeof(struct mac_mls));
1387 }
1388 
1389 static void
1390 mac_mls_cleanup_sysv_shm(struct label *shmlabel)
1391 {
1392 
1393 	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
1394 }
1395 
1396 /*
1397  * Access control checks.
1398  */
1399 static int
1400 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1401      struct ifnet *ifnet, struct label *ifnetlabel)
1402 {
1403 	struct mac_mls *a, *b;
1404 
1405 	if (!mac_mls_enabled)
1406 		return (0);
1407 
1408 	a = SLOT(bpflabel);
1409 	b = SLOT(ifnetlabel);
1410 
1411 	if (mac_mls_equal_effective(a, b))
1412 		return (0);
1413 	return (EACCES);
1414 }
1415 
1416 static int
1417 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1418 {
1419 	struct mac_mls *subj, *new;
1420 	int error;
1421 
1422 	subj = SLOT(cred->cr_label);
1423 	new = SLOT(newlabel);
1424 
1425 	/*
1426 	 * If there is an MLS label update for the credential, it may be
1427 	 * an update of effective, range, or both.
1428 	 */
1429 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1430 	if (error)
1431 		return (error);
1432 
1433 	/*
1434 	 * If the MLS label is to be changed, authorize as appropriate.
1435 	 */
1436 	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1437 		/*
1438 		 * If the change request modifies both the MLS label effective
1439 		 * and range, check that the new effective will be in the
1440 		 * new range.
1441 		 */
1442 		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
1443 		    MAC_MLS_FLAGS_BOTH &&
1444 		    !mac_mls_effective_in_range(new, new))
1445 			return (EINVAL);
1446 
1447 		/*
1448 		 * To change the MLS effective label on a credential, the
1449 		 * new effective label must be in the current range.
1450 		 */
1451 		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
1452 		    !mac_mls_effective_in_range(new, subj))
1453 			return (EPERM);
1454 
1455 		/*
1456 		 * To change the MLS range label on a credential, the
1457 		 * new range must be in the current range.
1458 		 */
1459 		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
1460 		    !mac_mls_range_in_range(new, subj))
1461 			return (EPERM);
1462 
1463 		/*
1464 		 * To have EQUAL in any component of the new credential
1465 		 * MLS label, the subject must already have EQUAL in
1466 		 * their label.
1467 		 */
1468 		if (mac_mls_contains_equal(new)) {
1469 			error = mac_mls_subject_privileged(subj);
1470 			if (error)
1471 				return (error);
1472 		}
1473 	}
1474 
1475 	return (0);
1476 }
1477 
1478 static int
1479 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1480 {
1481 	struct mac_mls *subj, *obj;
1482 
1483 	if (!mac_mls_enabled)
1484 		return (0);
1485 
1486 	subj = SLOT(u1->cr_label);
1487 	obj = SLOT(u2->cr_label);
1488 
1489 	/* XXX: range */
1490 	if (!mac_mls_dominate_effective(subj, obj))
1491 		return (ESRCH);
1492 
1493 	return (0);
1494 }
1495 
1496 static int
1497 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1498     struct label *ifnetlabel, struct label *newlabel)
1499 {
1500 	struct mac_mls *subj, *new;
1501 	int error;
1502 
1503 	subj = SLOT(cred->cr_label);
1504 	new = SLOT(newlabel);
1505 
1506 	/*
1507 	 * If there is an MLS label update for the interface, it may
1508 	 * be an update of effective, range, or both.
1509 	 */
1510 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1511 	if (error)
1512 		return (error);
1513 
1514 	/*
1515 	 * Relabeling network interfaces requires MLS privilege.
1516 	 */
1517 	error = mac_mls_subject_privileged(subj);
1518 
1519 	return (0);
1520 }
1521 
1522 static int
1523 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1524     struct mbuf *m, struct label *mbuflabel)
1525 {
1526 	struct mac_mls *p, *i;
1527 
1528 	if (!mac_mls_enabled)
1529 		return (0);
1530 
1531 	p = SLOT(mbuflabel);
1532 	i = SLOT(ifnetlabel);
1533 
1534 	return (mac_mls_effective_in_range(p, i) ? 0 : EACCES);
1535 }
1536 
1537 static int
1538 mac_mls_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1539     struct mbuf *m, struct label *mlabel)
1540 {
1541 	struct mac_mls *p, *i;
1542 
1543 	if (!mac_mls_enabled)
1544 		return (0);
1545 
1546 	p = SLOT(mlabel);
1547 	i = SLOT(inplabel);
1548 
1549 	return (mac_mls_equal_effective(p, i) ? 0 : EACCES);
1550 }
1551 
1552 static int
1553 mac_mls_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr,
1554     struct label *msglabel)
1555 {
1556 	struct mac_mls *subj, *obj;
1557 
1558 	if (!mac_mls_enabled)
1559 		return (0);
1560 
1561 	subj = SLOT(cred->cr_label);
1562 	obj = SLOT(msglabel);
1563 
1564 	if (!mac_mls_dominate_effective(subj, obj))
1565 		return (EACCES);
1566 
1567 	return (0);
1568 }
1569 
1570 static int
1571 mac_mls_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr,
1572     struct label *msglabel)
1573 {
1574 	struct mac_mls *subj, *obj;
1575 
1576 	if (!mac_mls_enabled)
1577 		return (0);
1578 
1579 	subj = SLOT(cred->cr_label);
1580 	obj = SLOT(msglabel);
1581 
1582 	if (!mac_mls_dominate_effective(obj, subj))
1583 		return (EACCES);
1584 
1585 	return (0);
1586 }
1587 
1588 static int
1589 mac_mls_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1590     struct label *msqklabel)
1591 {
1592 	struct mac_mls *subj, *obj;
1593 
1594 	if (!mac_mls_enabled)
1595 		return (0);
1596 
1597 	subj = SLOT(cred->cr_label);
1598 	obj = SLOT(msqklabel);
1599 
1600 	if (!mac_mls_dominate_effective(subj, obj))
1601 		return (EACCES);
1602 
1603 	return (0);
1604 }
1605 
1606 static int
1607 mac_mls_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1608     struct label *msqklabel)
1609 {
1610 	struct mac_mls *subj, *obj;
1611 
1612 	if (!mac_mls_enabled)
1613 		return (0);
1614 
1615 	subj = SLOT(cred->cr_label);
1616 	obj = SLOT(msqklabel);
1617 
1618 	if (!mac_mls_dominate_effective(obj, subj))
1619 		return (EACCES);
1620 
1621 	return (0);
1622 }
1623 
1624 static int
1625 mac_mls_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1626     struct label *msqklabel)
1627 {
1628 	struct mac_mls *subj, *obj;
1629 
1630 	if (!mac_mls_enabled)
1631 		return (0);
1632 
1633 	subj = SLOT(cred->cr_label);
1634 	obj = SLOT(msqklabel);
1635 
1636 	if (!mac_mls_dominate_effective(subj, obj))
1637 		return (EACCES);
1638 
1639 	return (0);
1640 }
1641 
1642 static int
1643 mac_mls_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1644     struct label *msqklabel, int cmd)
1645 {
1646 	struct mac_mls *subj, *obj;
1647 
1648 	if (!mac_mls_enabled)
1649 		return (0);
1650 
1651 	subj = SLOT(cred->cr_label);
1652 	obj = SLOT(msqklabel);
1653 
1654 	switch(cmd) {
1655 	case IPC_RMID:
1656 	case IPC_SET:
1657 		if (!mac_mls_dominate_effective(obj, subj))
1658 			return (EACCES);
1659 		break;
1660 
1661 	case IPC_STAT:
1662 		if (!mac_mls_dominate_effective(subj, obj))
1663 			return (EACCES);
1664 		break;
1665 
1666 	default:
1667 		return (EACCES);
1668 	}
1669 
1670 	return (0);
1671 }
1672 
1673 static int
1674 mac_mls_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr,
1675     struct label *semaklabel, int cmd)
1676 {
1677 	struct mac_mls *subj, *obj;
1678 
1679 	if (!mac_mls_enabled)
1680 		return (0);
1681 
1682 	subj = SLOT(cred->cr_label);
1683 	obj = SLOT(semaklabel);
1684 
1685 	switch(cmd) {
1686 	case IPC_RMID:
1687 	case IPC_SET:
1688 	case SETVAL:
1689 	case SETALL:
1690 		if (!mac_mls_dominate_effective(obj, subj))
1691 			return (EACCES);
1692 		break;
1693 
1694 	case IPC_STAT:
1695 	case GETVAL:
1696 	case GETPID:
1697 	case GETNCNT:
1698 	case GETZCNT:
1699 	case GETALL:
1700 		if (!mac_mls_dominate_effective(subj, obj))
1701 			return (EACCES);
1702 		break;
1703 
1704 	default:
1705 		return (EACCES);
1706 	}
1707 
1708 	return (0);
1709 }
1710 
1711 static int
1712 mac_mls_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr,
1713     struct label *semaklabel)
1714 {
1715 	struct mac_mls *subj, *obj;
1716 
1717 	if (!mac_mls_enabled)
1718 		return (0);
1719 
1720 	subj = SLOT(cred->cr_label);
1721 	obj = SLOT(semaklabel);
1722 
1723 	if (!mac_mls_dominate_effective(subj, obj))
1724 		return (EACCES);
1725 
1726 	return (0);
1727 }
1728 
1729 static int
1730 mac_mls_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr,
1731     struct label *semaklabel, size_t accesstype)
1732 {
1733 	struct mac_mls *subj, *obj;
1734 
1735 	if (!mac_mls_enabled)
1736 		return (0);
1737 
1738 	subj = SLOT(cred->cr_label);
1739 	obj = SLOT(semaklabel);
1740 
1741 	if( accesstype & SEM_R )
1742 		if (!mac_mls_dominate_effective(subj, obj))
1743 			return (EACCES);
1744 
1745 	if( accesstype & SEM_A )
1746 		if (!mac_mls_dominate_effective(obj, subj))
1747 			return (EACCES);
1748 
1749 	return (0);
1750 }
1751 
1752 static int
1753 mac_mls_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
1754     struct label *shmseglabel, int shmflg)
1755 {
1756 	struct mac_mls *subj, *obj;
1757 
1758 	if (!mac_mls_enabled)
1759 		return (0);
1760 
1761 	subj = SLOT(cred->cr_label);
1762 	obj = SLOT(shmseglabel);
1763 
1764 	if (!mac_mls_dominate_effective(subj, obj))
1765 			return (EACCES);
1766 	if ((shmflg & SHM_RDONLY) == 0)
1767 		if (!mac_mls_dominate_effective(obj, subj))
1768 			return (EACCES);
1769 
1770 	return (0);
1771 }
1772 
1773 static int
1774 mac_mls_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
1775     struct label *shmseglabel, int cmd)
1776 {
1777 	struct mac_mls *subj, *obj;
1778 
1779 	if (!mac_mls_enabled)
1780 		return (0);
1781 
1782 	subj = SLOT(cred->cr_label);
1783 	obj = SLOT(shmseglabel);
1784 
1785 	switch(cmd) {
1786 	case IPC_RMID:
1787 	case IPC_SET:
1788 		if (!mac_mls_dominate_effective(obj, subj))
1789 			return (EACCES);
1790 		break;
1791 
1792 	case IPC_STAT:
1793 	case SHM_STAT:
1794 		if (!mac_mls_dominate_effective(subj, obj))
1795 			return (EACCES);
1796 		break;
1797 
1798 	default:
1799 		return (EACCES);
1800 	}
1801 
1802 	return (0);
1803 }
1804 
1805 static int
1806 mac_mls_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
1807     struct label *shmseglabel, int shmflg)
1808 {
1809 	struct mac_mls *subj, *obj;
1810 
1811 	if (!mac_mls_enabled)
1812 		return (0);
1813 
1814 	subj = SLOT(cred->cr_label);
1815 	obj = SLOT(shmseglabel);
1816 
1817 	if (!mac_mls_dominate_effective(obj, subj))
1818 		return (EACCES);
1819 
1820 	return (0);
1821 }
1822 
1823 static int
1824 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1825     struct label *mntlabel)
1826 {
1827 	struct mac_mls *subj, *obj;
1828 
1829 	if (!mac_mls_enabled)
1830 		return (0);
1831 
1832 	subj = SLOT(cred->cr_label);
1833 	obj = SLOT(mntlabel);
1834 
1835 	if (!mac_mls_dominate_effective(subj, obj))
1836 		return (EACCES);
1837 
1838 	return (0);
1839 }
1840 
1841 static int
1842 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1843     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1844 {
1845 
1846 	if(!mac_mls_enabled)
1847 		return (0);
1848 
1849 	/* XXX: This will be implemented soon... */
1850 
1851 	return (0);
1852 }
1853 
1854 static int
1855 mac_mls_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1856     struct label *pipelabel)
1857 {
1858 	struct mac_mls *subj, *obj;
1859 
1860 	if (!mac_mls_enabled)
1861 		return (0);
1862 
1863 	subj = SLOT(cred->cr_label);
1864 	obj = SLOT((pipelabel));
1865 
1866 	if (!mac_mls_dominate_effective(subj, obj))
1867 		return (EACCES);
1868 
1869 	return (0);
1870 }
1871 
1872 static int
1873 mac_mls_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1874     struct label *pipelabel)
1875 {
1876 	struct mac_mls *subj, *obj;
1877 
1878 	if (!mac_mls_enabled)
1879 		return (0);
1880 
1881 	subj = SLOT(cred->cr_label);
1882 	obj = SLOT((pipelabel));
1883 
1884 	if (!mac_mls_dominate_effective(subj, obj))
1885 		return (EACCES);
1886 
1887 	return (0);
1888 }
1889 
1890 static int
1891 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1892     struct label *pipelabel, struct label *newlabel)
1893 {
1894 	struct mac_mls *subj, *obj, *new;
1895 	int error;
1896 
1897 	new = SLOT(newlabel);
1898 	subj = SLOT(cred->cr_label);
1899 	obj = SLOT(pipelabel);
1900 
1901 	/*
1902 	 * If there is an MLS label update for a pipe, it must be a
1903 	 * effective update.
1904 	 */
1905 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1906 	if (error)
1907 		return (error);
1908 
1909 	/*
1910 	 * To perform a relabel of a pipe (MLS label or not), MLS must
1911 	 * authorize the relabel.
1912 	 */
1913 	if (!mac_mls_effective_in_range(obj, subj))
1914 		return (EPERM);
1915 
1916 	/*
1917 	 * If the MLS label is to be changed, authorize as appropriate.
1918 	 */
1919 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1920 		/*
1921 		 * To change the MLS label on a pipe, the new pipe label
1922 		 * must be in the subject range.
1923 		 */
1924 		if (!mac_mls_effective_in_range(new, subj))
1925 			return (EPERM);
1926 
1927 		/*
1928 		 * To change the MLS label on a pipe to be EQUAL, the
1929 		 * subject must have appropriate privilege.
1930 		 */
1931 		if (mac_mls_contains_equal(new)) {
1932 			error = mac_mls_subject_privileged(subj);
1933 			if (error)
1934 				return (error);
1935 		}
1936 	}
1937 
1938 	return (0);
1939 }
1940 
1941 static int
1942 mac_mls_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
1943     struct label *pipelabel)
1944 {
1945 	struct mac_mls *subj, *obj;
1946 
1947 	if (!mac_mls_enabled)
1948 		return (0);
1949 
1950 	subj = SLOT(cred->cr_label);
1951 	obj = SLOT((pipelabel));
1952 
1953 	if (!mac_mls_dominate_effective(subj, obj))
1954 		return (EACCES);
1955 
1956 	return (0);
1957 }
1958 
1959 static int
1960 mac_mls_check_pipe_write(struct ucred *cred, struct pipepair *pp,
1961     struct label *pipelabel)
1962 {
1963 	struct mac_mls *subj, *obj;
1964 
1965 	if (!mac_mls_enabled)
1966 		return (0);
1967 
1968 	subj = SLOT(cred->cr_label);
1969 	obj = SLOT((pipelabel));
1970 
1971 	if (!mac_mls_dominate_effective(obj, subj))
1972 		return (EACCES);
1973 
1974 	return (0);
1975 }
1976 
1977 static int
1978 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1979 {
1980 	struct mac_mls *subj, *obj;
1981 
1982 	if (!mac_mls_enabled)
1983 		return (0);
1984 
1985 	subj = SLOT(cred->cr_label);
1986 	obj = SLOT(proc->p_ucred->cr_label);
1987 
1988 	/* XXX: range checks */
1989 	if (!mac_mls_dominate_effective(subj, obj))
1990 		return (ESRCH);
1991 	if (!mac_mls_dominate_effective(obj, subj))
1992 		return (EACCES);
1993 
1994 	return (0);
1995 }
1996 
1997 static int
1998 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1999 {
2000 	struct mac_mls *subj, *obj;
2001 
2002 	if (!mac_mls_enabled)
2003 		return (0);
2004 
2005 	subj = SLOT(cred->cr_label);
2006 	obj = SLOT(proc->p_ucred->cr_label);
2007 
2008 	/* XXX: range checks */
2009 	if (!mac_mls_dominate_effective(subj, obj))
2010 		return (ESRCH);
2011 	if (!mac_mls_dominate_effective(obj, subj))
2012 		return (EACCES);
2013 
2014 	return (0);
2015 }
2016 
2017 static int
2018 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2019 {
2020 	struct mac_mls *subj, *obj;
2021 
2022 	if (!mac_mls_enabled)
2023 		return (0);
2024 
2025 	subj = SLOT(cred->cr_label);
2026 	obj = SLOT(proc->p_ucred->cr_label);
2027 
2028 	/* XXX: range checks */
2029 	if (!mac_mls_dominate_effective(subj, obj))
2030 		return (ESRCH);
2031 	if (!mac_mls_dominate_effective(obj, subj))
2032 		return (EACCES);
2033 
2034 	return (0);
2035 }
2036 
2037 static int
2038 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
2039     struct mbuf *m, struct label *mbuflabel)
2040 {
2041 	struct mac_mls *p, *s;
2042 
2043 	if (!mac_mls_enabled)
2044 		return (0);
2045 
2046 	p = SLOT(mbuflabel);
2047 	s = SLOT(socketlabel);
2048 
2049 	return (mac_mls_equal_effective(p, s) ? 0 : EACCES);
2050 }
2051 
2052 static int
2053 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
2054     struct label *socketlabel, struct label *newlabel)
2055 {
2056 	struct mac_mls *subj, *obj, *new;
2057 	int error;
2058 
2059 	new = SLOT(newlabel);
2060 	subj = SLOT(cred->cr_label);
2061 	obj = SLOT(socketlabel);
2062 
2063 	/*
2064 	 * If there is an MLS label update for the socket, it may be
2065 	 * an update of effective.
2066 	 */
2067 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2068 	if (error)
2069 		return (error);
2070 
2071 	/*
2072 	 * To relabel a socket, the old socket effective must be in the subject
2073 	 * range.
2074 	 */
2075 	if (!mac_mls_effective_in_range(obj, subj))
2076 		return (EPERM);
2077 
2078 	/*
2079 	 * If the MLS label is to be changed, authorize as appropriate.
2080 	 */
2081 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2082 		/*
2083 		 * To relabel a socket, the new socket effective must be in
2084 		 * the subject range.
2085 		 */
2086 		if (!mac_mls_effective_in_range(new, subj))
2087 			return (EPERM);
2088 
2089 		/*
2090 		 * To change the MLS label on the socket to contain EQUAL,
2091 		 * the subject must have appropriate privilege.
2092 		 */
2093 		if (mac_mls_contains_equal(new)) {
2094 			error = mac_mls_subject_privileged(subj);
2095 			if (error)
2096 				return (error);
2097 		}
2098 	}
2099 
2100 	return (0);
2101 }
2102 
2103 static int
2104 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
2105     struct label *socketlabel)
2106 {
2107 	struct mac_mls *subj, *obj;
2108 
2109 	if (!mac_mls_enabled)
2110 		return (0);
2111 
2112 	subj = SLOT(cred->cr_label);
2113 	obj = SLOT(socketlabel);
2114 
2115 	if (!mac_mls_dominate_effective(subj, obj))
2116 		return (ENOENT);
2117 
2118 	return (0);
2119 }
2120 
2121 static int
2122 mac_mls_check_system_swapon(struct ucred *cred, struct vnode *vp,
2123     struct label *label)
2124 {
2125 	struct mac_mls *subj, *obj;
2126 
2127 	if (!mac_mls_enabled)
2128 		return (0);
2129 
2130 	subj = SLOT(cred->cr_label);
2131 	obj = SLOT(label);
2132 
2133 	if (!mac_mls_dominate_effective(obj, subj) ||
2134 	    !mac_mls_dominate_effective(subj, obj))
2135 		return (EACCES);
2136 
2137 	return (0);
2138 }
2139 
2140 static int
2141 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2142     struct label *dlabel)
2143 {
2144 	struct mac_mls *subj, *obj;
2145 
2146 	if (!mac_mls_enabled)
2147 		return (0);
2148 
2149 	subj = SLOT(cred->cr_label);
2150 	obj = SLOT(dlabel);
2151 
2152 	if (!mac_mls_dominate_effective(subj, obj))
2153 		return (EACCES);
2154 
2155 	return (0);
2156 }
2157 
2158 static int
2159 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2160     struct label *dlabel)
2161 {
2162 	struct mac_mls *subj, *obj;
2163 
2164 	if (!mac_mls_enabled)
2165 		return (0);
2166 
2167 	subj = SLOT(cred->cr_label);
2168 	obj = SLOT(dlabel);
2169 
2170 	if (!mac_mls_dominate_effective(subj, obj))
2171 		return (EACCES);
2172 
2173 	return (0);
2174 }
2175 
2176 static int
2177 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2178     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2179 {
2180 	struct mac_mls *subj, *obj;
2181 
2182 	if (!mac_mls_enabled)
2183 		return (0);
2184 
2185 	subj = SLOT(cred->cr_label);
2186 	obj = SLOT(dlabel);
2187 
2188 	if (!mac_mls_dominate_effective(obj, subj))
2189 		return (EACCES);
2190 
2191 	return (0);
2192 }
2193 
2194 static int
2195 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2196     struct label *dlabel, struct vnode *vp, struct label *label,
2197     struct componentname *cnp)
2198 {
2199 	struct mac_mls *subj, *obj;
2200 
2201 	if (!mac_mls_enabled)
2202 		return (0);
2203 
2204 	subj = SLOT(cred->cr_label);
2205 	obj = SLOT(dlabel);
2206 
2207 	if (!mac_mls_dominate_effective(obj, subj))
2208 		return (EACCES);
2209 
2210 	obj = SLOT(label);
2211 
2212 	if (!mac_mls_dominate_effective(obj, subj))
2213 		return (EACCES);
2214 
2215 	return (0);
2216 }
2217 
2218 static int
2219 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2220     struct label *label, acl_type_t type)
2221 {
2222 	struct mac_mls *subj, *obj;
2223 
2224 	if (!mac_mls_enabled)
2225 		return (0);
2226 
2227 	subj = SLOT(cred->cr_label);
2228 	obj = SLOT(label);
2229 
2230 	if (!mac_mls_dominate_effective(obj, subj))
2231 		return (EACCES);
2232 
2233 	return (0);
2234 }
2235 
2236 static int
2237 mac_mls_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2238     struct label *label, int attrnamespace, const char *name)
2239 {
2240 	struct mac_mls *subj, *obj;
2241 
2242 	if (!mac_mls_enabled)
2243 		return (0);
2244 
2245 	subj = SLOT(cred->cr_label);
2246 	obj = SLOT(label);
2247 
2248 	if (!mac_mls_dominate_effective(obj, subj))
2249 		return (EACCES);
2250 
2251 	return (0);
2252 }
2253 
2254 static int
2255 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2256     struct label *label, struct image_params *imgp,
2257     struct label *execlabel)
2258 {
2259 	struct mac_mls *subj, *obj, *exec;
2260 	int error;
2261 
2262 	if (execlabel != NULL) {
2263 		/*
2264 		 * We currently don't permit labels to be changed at
2265 		 * exec-time as part of MLS, so disallow non-NULL
2266 		 * MLS label elements in the execlabel.
2267 		 */
2268 		exec = SLOT(execlabel);
2269 		error = mls_atmostflags(exec, 0);
2270 		if (error)
2271 			return (error);
2272 	}
2273 
2274 	if (!mac_mls_enabled)
2275 		return (0);
2276 
2277 	subj = SLOT(cred->cr_label);
2278 	obj = SLOT(label);
2279 
2280 	if (!mac_mls_dominate_effective(subj, obj))
2281 		return (EACCES);
2282 
2283 	return (0);
2284 }
2285 
2286 static int
2287 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2288     struct label *label, acl_type_t type)
2289 {
2290 	struct mac_mls *subj, *obj;
2291 
2292 	if (!mac_mls_enabled)
2293 		return (0);
2294 
2295 	subj = SLOT(cred->cr_label);
2296 	obj = SLOT(label);
2297 
2298 	if (!mac_mls_dominate_effective(subj, obj))
2299 		return (EACCES);
2300 
2301 	return (0);
2302 }
2303 
2304 static int
2305 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2306     struct label *label, int attrnamespace, const char *name, struct uio *uio)
2307 {
2308 	struct mac_mls *subj, *obj;
2309 
2310 	if (!mac_mls_enabled)
2311 		return (0);
2312 
2313 	subj = SLOT(cred->cr_label);
2314 	obj = SLOT(label);
2315 
2316 	if (!mac_mls_dominate_effective(subj, obj))
2317 		return (EACCES);
2318 
2319 	return (0);
2320 }
2321 
2322 static int
2323 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2324     struct label *dlabel, struct vnode *vp, struct label *label,
2325     struct componentname *cnp)
2326 {
2327 	struct mac_mls *subj, *obj;
2328 
2329 	if (!mac_mls_enabled)
2330 		return (0);
2331 
2332 	subj = SLOT(cred->cr_label);
2333 	obj = SLOT(dlabel);
2334 
2335 	if (!mac_mls_dominate_effective(obj, subj))
2336 		return (EACCES);
2337 
2338 	obj = SLOT(dlabel);
2339 	if (!mac_mls_dominate_effective(obj, subj))
2340 		return (EACCES);
2341 
2342 	return (0);
2343 }
2344 
2345 static int
2346 mac_mls_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2347     struct label *label, int attrnamespace)
2348 {
2349 
2350 	struct mac_mls *subj, *obj;
2351 
2352 	if (!mac_mls_enabled)
2353 		return (0);
2354 
2355 	subj = SLOT(cred->cr_label);
2356 	obj = SLOT(label);
2357 
2358 	if (!mac_mls_dominate_effective(subj, obj))
2359 		return (EACCES);
2360 
2361 	return (0);
2362 }
2363 
2364 static int
2365 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2366     struct label *dlabel, struct componentname *cnp)
2367 {
2368 	struct mac_mls *subj, *obj;
2369 
2370 	if (!mac_mls_enabled)
2371 		return (0);
2372 
2373 	subj = SLOT(cred->cr_label);
2374 	obj = SLOT(dlabel);
2375 
2376 	if (!mac_mls_dominate_effective(subj, obj))
2377 		return (EACCES);
2378 
2379 	return (0);
2380 }
2381 
2382 static int
2383 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2384     struct label *label, int prot, int flags)
2385 {
2386 	struct mac_mls *subj, *obj;
2387 
2388 	/*
2389 	 * Rely on the use of open()-time protections to handle
2390 	 * non-revocation cases.
2391 	 */
2392 	if (!mac_mls_enabled || !revocation_enabled)
2393 		return (0);
2394 
2395 	subj = SLOT(cred->cr_label);
2396 	obj = SLOT(label);
2397 
2398 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2399 		if (!mac_mls_dominate_effective(subj, obj))
2400 			return (EACCES);
2401 	}
2402 	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2403 		if (!mac_mls_dominate_effective(obj, subj))
2404 			return (EACCES);
2405 	}
2406 
2407 	return (0);
2408 }
2409 
2410 static int
2411 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2412     struct label *vnodelabel, int acc_mode)
2413 {
2414 	struct mac_mls *subj, *obj;
2415 
2416 	if (!mac_mls_enabled)
2417 		return (0);
2418 
2419 	subj = SLOT(cred->cr_label);
2420 	obj = SLOT(vnodelabel);
2421 
2422 	/* XXX privilege override for admin? */
2423 	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2424 		if (!mac_mls_dominate_effective(subj, obj))
2425 			return (EACCES);
2426 	}
2427 	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2428 		if (!mac_mls_dominate_effective(obj, subj))
2429 			return (EACCES);
2430 	}
2431 
2432 	return (0);
2433 }
2434 
2435 static int
2436 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2437     struct vnode *vp, struct label *label)
2438 {
2439 	struct mac_mls *subj, *obj;
2440 
2441 	if (!mac_mls_enabled || !revocation_enabled)
2442 		return (0);
2443 
2444 	subj = SLOT(active_cred->cr_label);
2445 	obj = SLOT(label);
2446 
2447 	if (!mac_mls_dominate_effective(subj, obj))
2448 		return (EACCES);
2449 
2450 	return (0);
2451 }
2452 
2453 static int
2454 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2455     struct vnode *vp, struct label *label)
2456 {
2457 	struct mac_mls *subj, *obj;
2458 
2459 	if (!mac_mls_enabled || !revocation_enabled)
2460 		return (0);
2461 
2462 	subj = SLOT(active_cred->cr_label);
2463 	obj = SLOT(label);
2464 
2465 	if (!mac_mls_dominate_effective(subj, obj))
2466 		return (EACCES);
2467 
2468 	return (0);
2469 }
2470 
2471 static int
2472 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2473     struct label *dlabel)
2474 {
2475 	struct mac_mls *subj, *obj;
2476 
2477 	if (!mac_mls_enabled)
2478 		return (0);
2479 
2480 	subj = SLOT(cred->cr_label);
2481 	obj = SLOT(dlabel);
2482 
2483 	if (!mac_mls_dominate_effective(subj, obj))
2484 		return (EACCES);
2485 
2486 	return (0);
2487 }
2488 
2489 static int
2490 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2491     struct label *vnodelabel)
2492 {
2493 	struct mac_mls *subj, *obj;
2494 
2495 	if (!mac_mls_enabled)
2496 		return (0);
2497 
2498 	subj = SLOT(cred->cr_label);
2499 	obj = SLOT(vnodelabel);
2500 
2501 	if (!mac_mls_dominate_effective(subj, obj))
2502 		return (EACCES);
2503 
2504 	return (0);
2505 }
2506 
2507 static int
2508 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2509     struct label *vnodelabel, struct label *newlabel)
2510 {
2511 	struct mac_mls *old, *new, *subj;
2512 	int error;
2513 
2514 	old = SLOT(vnodelabel);
2515 	new = SLOT(newlabel);
2516 	subj = SLOT(cred->cr_label);
2517 
2518 	/*
2519 	 * If there is an MLS label update for the vnode, it must be a
2520 	 * effective label.
2521 	 */
2522 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2523 	if (error)
2524 		return (error);
2525 
2526 	/*
2527 	 * To perform a relabel of the vnode (MLS label or not), MLS must
2528 	 * authorize the relabel.
2529 	 */
2530 	if (!mac_mls_effective_in_range(old, subj))
2531 		return (EPERM);
2532 
2533 	/*
2534 	 * If the MLS label is to be changed, authorize as appropriate.
2535 	 */
2536 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2537 		/*
2538 		 * To change the MLS label on a vnode, the new vnode label
2539 		 * must be in the subject range.
2540 		 */
2541 		if (!mac_mls_effective_in_range(new, subj))
2542 			return (EPERM);
2543 
2544 		/*
2545 		 * To change the MLS label on the vnode to be EQUAL,
2546 		 * the subject must have appropriate privilege.
2547 		 */
2548 		if (mac_mls_contains_equal(new)) {
2549 			error = mac_mls_subject_privileged(subj);
2550 			if (error)
2551 				return (error);
2552 		}
2553 	}
2554 
2555 	return (0);
2556 }
2557 
2558 
2559 static int
2560 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2561     struct label *dlabel, struct vnode *vp, struct label *label,
2562     struct componentname *cnp)
2563 {
2564 	struct mac_mls *subj, *obj;
2565 
2566 	if (!mac_mls_enabled)
2567 		return (0);
2568 
2569 	subj = SLOT(cred->cr_label);
2570 	obj = SLOT(dlabel);
2571 
2572 	if (!mac_mls_dominate_effective(obj, subj))
2573 		return (EACCES);
2574 
2575 	obj = SLOT(label);
2576 
2577 	if (!mac_mls_dominate_effective(obj, subj))
2578 		return (EACCES);
2579 
2580 	return (0);
2581 }
2582 
2583 static int
2584 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2585     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2586     struct componentname *cnp)
2587 {
2588 	struct mac_mls *subj, *obj;
2589 
2590 	if (!mac_mls_enabled)
2591 		return (0);
2592 
2593 	subj = SLOT(cred->cr_label);
2594 	obj = SLOT(dlabel);
2595 
2596 	if (!mac_mls_dominate_effective(obj, subj))
2597 		return (EACCES);
2598 
2599 	if (vp != NULL) {
2600 		obj = SLOT(label);
2601 
2602 		if (!mac_mls_dominate_effective(obj, subj))
2603 			return (EACCES);
2604 	}
2605 
2606 	return (0);
2607 }
2608 
2609 static int
2610 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2611     struct label *label)
2612 {
2613 	struct mac_mls *subj, *obj;
2614 
2615 	if (!mac_mls_enabled)
2616 		return (0);
2617 
2618 	subj = SLOT(cred->cr_label);
2619 	obj = SLOT(label);
2620 
2621 	if (!mac_mls_dominate_effective(obj, subj))
2622 		return (EACCES);
2623 
2624 	return (0);
2625 }
2626 
2627 static int
2628 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2629     struct label *label, acl_type_t type, struct acl *acl)
2630 {
2631 	struct mac_mls *subj, *obj;
2632 
2633 	if (!mac_mls_enabled)
2634 		return (0);
2635 
2636 	subj = SLOT(cred->cr_label);
2637 	obj = SLOT(label);
2638 
2639 	if (!mac_mls_dominate_effective(obj, subj))
2640 		return (EACCES);
2641 
2642 	return (0);
2643 }
2644 
2645 static int
2646 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2647     struct label *vnodelabel, int attrnamespace, const char *name,
2648     struct uio *uio)
2649 {
2650 	struct mac_mls *subj, *obj;
2651 
2652 	if (!mac_mls_enabled)
2653 		return (0);
2654 
2655 	subj = SLOT(cred->cr_label);
2656 	obj = SLOT(vnodelabel);
2657 
2658 	if (!mac_mls_dominate_effective(obj, subj))
2659 		return (EACCES);
2660 
2661 	/* XXX: protect the MAC EA in a special way? */
2662 
2663 	return (0);
2664 }
2665 
2666 static int
2667 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2668     struct label *vnodelabel, u_long flags)
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(vnodelabel);
2677 
2678 	if (!mac_mls_dominate_effective(obj, subj))
2679 		return (EACCES);
2680 
2681 	return (0);
2682 }
2683 
2684 static int
2685 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2686     struct label *vnodelabel, mode_t mode)
2687 {
2688 	struct mac_mls *subj, *obj;
2689 
2690 	if (!mac_mls_enabled)
2691 		return (0);
2692 
2693 	subj = SLOT(cred->cr_label);
2694 	obj = SLOT(vnodelabel);
2695 
2696 	if (!mac_mls_dominate_effective(obj, subj))
2697 		return (EACCES);
2698 
2699 	return (0);
2700 }
2701 
2702 static int
2703 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2704     struct label *vnodelabel, uid_t uid, gid_t gid)
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(vnodelabel);
2713 
2714 	if (!mac_mls_dominate_effective(obj, subj))
2715 		return (EACCES);
2716 
2717 	return (0);
2718 }
2719 
2720 static int
2721 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2722     struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2723 {
2724 	struct mac_mls *subj, *obj;
2725 
2726 	if (!mac_mls_enabled)
2727 		return (0);
2728 
2729 	subj = SLOT(cred->cr_label);
2730 	obj = SLOT(vnodelabel);
2731 
2732 	if (!mac_mls_dominate_effective(obj, subj))
2733 		return (EACCES);
2734 
2735 	return (0);
2736 }
2737 
2738 static int
2739 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2740     struct vnode *vp, struct label *vnodelabel)
2741 {
2742 	struct mac_mls *subj, *obj;
2743 
2744 	if (!mac_mls_enabled)
2745 		return (0);
2746 
2747 	subj = SLOT(active_cred->cr_label);
2748 	obj = SLOT(vnodelabel);
2749 
2750 	if (!mac_mls_dominate_effective(subj, obj))
2751 		return (EACCES);
2752 
2753 	return (0);
2754 }
2755 
2756 static int
2757 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2758     struct vnode *vp, struct label *label)
2759 {
2760 	struct mac_mls *subj, *obj;
2761 
2762 	if (!mac_mls_enabled || !revocation_enabled)
2763 		return (0);
2764 
2765 	subj = SLOT(active_cred->cr_label);
2766 	obj = SLOT(label);
2767 
2768 	if (!mac_mls_dominate_effective(obj, subj))
2769 		return (EACCES);
2770 
2771 	return (0);
2772 }
2773 
2774 static struct mac_policy_ops mac_mls_ops =
2775 {
2776 	.mpo_init = mac_mls_init,
2777 	.mpo_init_bpfdesc_label = mac_mls_init_label,
2778 	.mpo_init_cred_label = mac_mls_init_label,
2779 	.mpo_init_devfsdirent_label = mac_mls_init_label,
2780 	.mpo_init_ifnet_label = mac_mls_init_label,
2781 	.mpo_init_inpcb_label = mac_mls_init_label_waitcheck,
2782 	.mpo_init_sysv_msgmsg_label = mac_mls_init_label,
2783 	.mpo_init_sysv_msgqueue_label = mac_mls_init_label,
2784 	.mpo_init_sysv_sema_label = mac_mls_init_label,
2785 	.mpo_init_sysv_shm_label = mac_mls_init_label,
2786 	.mpo_init_ipq_label = mac_mls_init_label_waitcheck,
2787 	.mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
2788 	.mpo_init_mount_label = mac_mls_init_label,
2789 	.mpo_init_mount_fs_label = mac_mls_init_label,
2790 	.mpo_init_pipe_label = mac_mls_init_label,
2791 	.mpo_init_socket_label = mac_mls_init_label_waitcheck,
2792 	.mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
2793 	.mpo_init_vnode_label = mac_mls_init_label,
2794 	.mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
2795 	.mpo_destroy_cred_label = mac_mls_destroy_label,
2796 	.mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
2797 	.mpo_destroy_ifnet_label = mac_mls_destroy_label,
2798 	.mpo_destroy_inpcb_label = mac_mls_destroy_label,
2799 	.mpo_destroy_sysv_msgmsg_label = mac_mls_destroy_label,
2800 	.mpo_destroy_sysv_msgqueue_label = mac_mls_destroy_label,
2801 	.mpo_destroy_sysv_sema_label = mac_mls_destroy_label,
2802 	.mpo_destroy_sysv_shm_label = mac_mls_destroy_label,
2803 	.mpo_destroy_ipq_label = mac_mls_destroy_label,
2804 	.mpo_destroy_mbuf_label = mac_mls_destroy_label,
2805 	.mpo_destroy_mount_label = mac_mls_destroy_label,
2806 	.mpo_destroy_mount_fs_label = mac_mls_destroy_label,
2807 	.mpo_destroy_pipe_label = mac_mls_destroy_label,
2808 	.mpo_destroy_socket_label = mac_mls_destroy_label,
2809 	.mpo_destroy_socket_peer_label = mac_mls_destroy_label,
2810 	.mpo_destroy_vnode_label = mac_mls_destroy_label,
2811 	.mpo_copy_cred_label = mac_mls_copy_label,
2812 	.mpo_copy_ifnet_label = mac_mls_copy_label,
2813 	.mpo_copy_mbuf_label = mac_mls_copy_label,
2814 	.mpo_copy_pipe_label = mac_mls_copy_label,
2815 	.mpo_copy_socket_label = mac_mls_copy_label,
2816 	.mpo_copy_vnode_label = mac_mls_copy_label,
2817 	.mpo_externalize_cred_label = mac_mls_externalize_label,
2818 	.mpo_externalize_ifnet_label = mac_mls_externalize_label,
2819 	.mpo_externalize_pipe_label = mac_mls_externalize_label,
2820 	.mpo_externalize_socket_label = mac_mls_externalize_label,
2821 	.mpo_externalize_socket_peer_label = mac_mls_externalize_label,
2822 	.mpo_externalize_vnode_label = mac_mls_externalize_label,
2823 	.mpo_internalize_cred_label = mac_mls_internalize_label,
2824 	.mpo_internalize_ifnet_label = mac_mls_internalize_label,
2825 	.mpo_internalize_pipe_label = mac_mls_internalize_label,
2826 	.mpo_internalize_socket_label = mac_mls_internalize_label,
2827 	.mpo_internalize_vnode_label = mac_mls_internalize_label,
2828 	.mpo_create_devfs_device = mac_mls_create_devfs_device,
2829 	.mpo_create_devfs_directory = mac_mls_create_devfs_directory,
2830 	.mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
2831 	.mpo_create_mount = mac_mls_create_mount,
2832 	.mpo_create_root_mount = mac_mls_create_root_mount,
2833 	.mpo_relabel_vnode = mac_mls_relabel_vnode,
2834 	.mpo_update_devfsdirent = mac_mls_update_devfsdirent,
2835 	.mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
2836 	.mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
2837 	.mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
2838 	.mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
2839 	.mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
2840 	.mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
2841 	.mpo_create_pipe = mac_mls_create_pipe,
2842 	.mpo_create_socket = mac_mls_create_socket,
2843 	.mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
2844 	.mpo_relabel_pipe = mac_mls_relabel_pipe,
2845 	.mpo_relabel_socket = mac_mls_relabel_socket,
2846 	.mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
2847 	.mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
2848 	.mpo_create_bpfdesc = mac_mls_create_bpfdesc,
2849 	.mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
2850 	.mpo_create_fragment = mac_mls_create_fragment,
2851 	.mpo_create_ifnet = mac_mls_create_ifnet,
2852 	.mpo_create_inpcb_from_socket = mac_mls_create_inpcb_from_socket,
2853 	.mpo_create_ipq = mac_mls_create_ipq,
2854 	.mpo_create_sysv_msgmsg = mac_mls_create_sysv_msgmsg,
2855 	.mpo_create_sysv_msgqueue = mac_mls_create_sysv_msgqueue,
2856 	.mpo_create_sysv_sema = mac_mls_create_sysv_sema,
2857 	.mpo_create_sysv_shm = mac_mls_create_sysv_shm,
2858 	.mpo_create_mbuf_from_inpcb = mac_mls_create_mbuf_from_inpcb,
2859 	.mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf,
2860 	.mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
2861 	.mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
2862 	.mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
2863 	.mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
2864 	.mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
2865 	.mpo_fragment_match = mac_mls_fragment_match,
2866 	.mpo_relabel_ifnet = mac_mls_relabel_ifnet,
2867 	.mpo_update_ipq = mac_mls_update_ipq,
2868 	.mpo_inpcb_sosetlabel = mac_mls_inpcb_sosetlabel,
2869 	.mpo_create_proc0 = mac_mls_create_proc0,
2870 	.mpo_create_proc1 = mac_mls_create_proc1,
2871 	.mpo_relabel_cred = mac_mls_relabel_cred,
2872 	.mpo_cleanup_sysv_msgmsg = mac_mls_cleanup_sysv_msgmsg,
2873 	.mpo_cleanup_sysv_msgqueue = mac_mls_cleanup_sysv_msgqueue,
2874 	.mpo_cleanup_sysv_sema = mac_mls_cleanup_sysv_sema,
2875 	.mpo_cleanup_sysv_shm = mac_mls_cleanup_sysv_shm,
2876 	.mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
2877 	.mpo_check_cred_relabel = mac_mls_check_cred_relabel,
2878 	.mpo_check_cred_visible = mac_mls_check_cred_visible,
2879 	.mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
2880 	.mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
2881 	.mpo_check_inpcb_deliver = mac_mls_check_inpcb_deliver,
2882 	.mpo_check_sysv_msgrcv = mac_mls_check_sysv_msgrcv,
2883 	.mpo_check_sysv_msgrmid = mac_mls_check_sysv_msgrmid,
2884 	.mpo_check_sysv_msqget = mac_mls_check_sysv_msqget,
2885 	.mpo_check_sysv_msqsnd = mac_mls_check_sysv_msqsnd,
2886 	.mpo_check_sysv_msqrcv = mac_mls_check_sysv_msqrcv,
2887 	.mpo_check_sysv_msqctl = mac_mls_check_sysv_msqctl,
2888 	.mpo_check_sysv_semctl = mac_mls_check_sysv_semctl,
2889 	.mpo_check_sysv_semget = mac_mls_check_sysv_semget,
2890 	.mpo_check_sysv_semop = mac_mls_check_sysv_semop,
2891 	.mpo_check_sysv_shmat = mac_mls_check_sysv_shmat,
2892 	.mpo_check_sysv_shmctl = mac_mls_check_sysv_shmctl,
2893 	.mpo_check_sysv_shmget = mac_mls_check_sysv_shmget,
2894 	.mpo_check_mount_stat = mac_mls_check_mount_stat,
2895 	.mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
2896 	.mpo_check_pipe_poll = mac_mls_check_pipe_poll,
2897 	.mpo_check_pipe_read = mac_mls_check_pipe_read,
2898 	.mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
2899 	.mpo_check_pipe_stat = mac_mls_check_pipe_stat,
2900 	.mpo_check_pipe_write = mac_mls_check_pipe_write,
2901 	.mpo_check_proc_debug = mac_mls_check_proc_debug,
2902 	.mpo_check_proc_sched = mac_mls_check_proc_sched,
2903 	.mpo_check_proc_signal = mac_mls_check_proc_signal,
2904 	.mpo_check_socket_deliver = mac_mls_check_socket_deliver,
2905 	.mpo_check_socket_relabel = mac_mls_check_socket_relabel,
2906 	.mpo_check_socket_visible = mac_mls_check_socket_visible,
2907 	.mpo_check_system_swapon = mac_mls_check_system_swapon,
2908 	.mpo_check_vnode_access = mac_mls_check_vnode_open,
2909 	.mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
2910 	.mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
2911 	.mpo_check_vnode_create = mac_mls_check_vnode_create,
2912 	.mpo_check_vnode_delete = mac_mls_check_vnode_delete,
2913 	.mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
2914 	.mpo_check_vnode_deleteextattr = mac_mls_check_vnode_deleteextattr,
2915 	.mpo_check_vnode_exec = mac_mls_check_vnode_exec,
2916 	.mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
2917 	.mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
2918 	.mpo_check_vnode_link = mac_mls_check_vnode_link,
2919 	.mpo_check_vnode_listextattr = mac_mls_check_vnode_listextattr,
2920 	.mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
2921 	.mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
2922 	.mpo_check_vnode_open = mac_mls_check_vnode_open,
2923 	.mpo_check_vnode_poll = mac_mls_check_vnode_poll,
2924 	.mpo_check_vnode_read = mac_mls_check_vnode_read,
2925 	.mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
2926 	.mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
2927 	.mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
2928 	.mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
2929 	.mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
2930 	.mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
2931 	.mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
2932 	.mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
2933 	.mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
2934 	.mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
2935 	.mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
2936 	.mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
2937 	.mpo_check_vnode_stat = mac_mls_check_vnode_stat,
2938 	.mpo_check_vnode_write = mac_mls_check_vnode_write,
2939 };
2940 
2941 MAC_POLICY_SET(&mac_mls_ops, mac_mls, "TrustedBSD MAC/MLS",
2942     MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_mls_slot);
2943