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