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