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