xref: /freebsd/sys/security/mac_mls/mac_mls.c (revision 71fe318b852b8dfb3e799cb12ef184750f7f8eac)
1 /*-
2  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3  * Copyright (c) 2001, 2002 Networks Associates Technology, 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 NAI Labs,
9  * the Security Research Division of Network Associates, 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  * 3. The names of the authors may not be used to endorse or promote
22  *    products derived from this software without specific prior written
23  *    permission.
24  *
25  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35  * SUCH DAMAGE.
36  *
37  * $FreeBSD$
38  */
39 
40 /*
41  * Developed by the TrustedBSD Project.
42  * MLS fixed label mandatory confidentiality policy.
43  */
44 
45 #include <sys/types.h>
46 #include <sys/param.h>
47 #include <sys/acl.h>
48 #include <sys/conf.h>
49 #include <sys/extattr.h>
50 #include <sys/kernel.h>
51 #include <sys/mac.h>
52 #include <sys/malloc.h>
53 #include <sys/mount.h>
54 #include <sys/proc.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/sysctl.h>
65 
66 #include <fs/devfs/devfs.h>
67 
68 #include <net/bpfdesc.h>
69 #include <net/if.h>
70 #include <net/if_types.h>
71 #include <net/if_var.h>
72 
73 #include <netinet/in.h>
74 #include <netinet/ip_var.h>
75 
76 #include <vm/vm.h>
77 
78 #include <sys/mac_policy.h>
79 
80 #include <security/mac_mls/mac_mls.h>
81 
82 SYSCTL_DECL(_security_mac);
83 
84 SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
85     "TrustedBSD mac_mls policy controls");
86 
87 static int	mac_mls_label_size = sizeof(struct mac_mls);
88 SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
89     &mac_mls_label_size, 0, "Size of struct mac_mls");
90 
91 static int	mac_mls_enabled = 0;
92 SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
93     &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
94 TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
95 
96 static int	destroyed_not_inited;
97 SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99 
100 static int	ptys_equal = 0;
101 SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
102     &ptys_equal, 0, "Label pty devices as mls/equal on create");
103 TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
104 
105 static int	revocation_enabled = 0;
106 SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
107     &revocation_enabled, 0, "Revoke access to objects on relabel");
108 TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
109 
110 static int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
111 SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
112     &max_compartments, 0, "Maximum compartments the policy supports");
113 
114 static int	mac_mls_slot;
115 #define	SLOT(l)	((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
116 
117 MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
118 
119 static __inline int
120 mls_bit_set_empty(u_char *set) {
121 	int i;
122 
123 	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
124 		if (set[i] != 0)
125 			return (0);
126 	return (1);
127 }
128 
129 static struct mac_mls *
130 mls_alloc(int flag)
131 {
132 	struct mac_mls *mac_mls;
133 
134 	mac_mls = malloc(sizeof(struct mac_mls), M_MACMLS, M_ZERO | flag);
135 
136 	return (mac_mls);
137 }
138 
139 static void
140 mls_free(struct mac_mls *mac_mls)
141 {
142 
143 	if (mac_mls != NULL)
144 		free(mac_mls, M_MACMLS);
145 	else
146 		atomic_add_int(&destroyed_not_inited, 1);
147 }
148 
149 static int
150 mls_atmostflags(struct mac_mls *mac_mls, int flags)
151 {
152 
153 	if ((mac_mls->mm_flags & flags) != mac_mls->mm_flags)
154 		return (EINVAL);
155 	return (0);
156 }
157 
158 static int
159 mac_mls_dominate_element(struct mac_mls_element *a,
160     struct mac_mls_element *b)
161 {
162 	int bit;
163 
164 	switch (a->mme_type) {
165 	case MAC_MLS_TYPE_EQUAL:
166 	case MAC_MLS_TYPE_HIGH:
167 		return (1);
168 
169 	case MAC_MLS_TYPE_LOW:
170 		switch (b->mme_type) {
171 		case MAC_MLS_TYPE_LEVEL:
172 		case MAC_MLS_TYPE_HIGH:
173 			return (0);
174 
175 		case MAC_MLS_TYPE_EQUAL:
176 		case MAC_MLS_TYPE_LOW:
177 			return (1);
178 
179 		default:
180 			panic("mac_mls_dominate_element: b->mme_type invalid");
181 		}
182 
183 	case MAC_MLS_TYPE_LEVEL:
184 		switch (b->mme_type) {
185 		case MAC_MLS_TYPE_EQUAL:
186 		case MAC_MLS_TYPE_LOW:
187 			return (1);
188 
189 		case MAC_MLS_TYPE_HIGH:
190 			return (0);
191 
192 		case MAC_MLS_TYPE_LEVEL:
193 			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
194 				if (!MAC_MLS_BIT_TEST(bit,
195 				    a->mme_compartments) &&
196 				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
197 					return (0);
198 			return (a->mme_level >= b->mme_level);
199 
200 		default:
201 			panic("mac_mls_dominate_element: b->mme_type invalid");
202 		}
203 
204 	default:
205 		panic("mac_mls_dominate_element: a->mme_type invalid");
206 	}
207 
208 	return (0);
209 }
210 
211 static int
212 mac_mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
213 {
214 
215 	return (mac_mls_dominate_element(&rangeb->mm_rangehigh,
216 	    &rangea->mm_rangehigh) &&
217 	    mac_mls_dominate_element(&rangea->mm_rangelow,
218 	    &rangeb->mm_rangelow));
219 }
220 
221 static int
222 mac_mls_single_in_range(struct mac_mls *single, struct mac_mls *range)
223 {
224 
225 	KASSERT((single->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
226 	    ("mac_mls_single_in_range: a not single"));
227 	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
228 	    ("mac_mls_single_in_range: b not range"));
229 
230 	return (mac_mls_dominate_element(&range->mm_rangehigh,
231 	    &single->mm_single) &&
232 	    mac_mls_dominate_element(&single->mm_single,
233 	    &range->mm_rangelow));
234 
235 	return (1);
236 }
237 
238 static int
239 mac_mls_dominate_single(struct mac_mls *a, struct mac_mls *b)
240 {
241 	KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
242 	    ("mac_mls_dominate_single: a not single"));
243 	KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
244 	    ("mac_mls_dominate_single: b not single"));
245 
246 	return (mac_mls_dominate_element(&a->mm_single, &b->mm_single));
247 }
248 
249 static int
250 mac_mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
251 {
252 
253 	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
254 	    b->mme_type == MAC_MLS_TYPE_EQUAL)
255 		return (1);
256 
257 	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
258 }
259 
260 static int
261 mac_mls_equal_single(struct mac_mls *a, struct mac_mls *b)
262 {
263 
264 	KASSERT((a->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
265 	    ("mac_mls_equal_single: a not single"));
266 	KASSERT((b->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
267 	    ("mac_mls_equal_single: b not single"));
268 
269 	return (mac_mls_equal_element(&a->mm_single, &b->mm_single));
270 }
271 
272 static int
273 mac_mls_contains_equal(struct mac_mls *mac_mls)
274 {
275 
276 	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE)
277 		if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
278 			return (1);
279 
280 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
281 		if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
282 			return (1);
283 		if (mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
284 			return (1);
285 	}
286 
287 	return (0);
288 }
289 
290 static int
291 mac_mls_subject_equal_ok(struct mac_mls *mac_mls)
292 {
293 
294 	KASSERT((mac_mls->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
295 	    ("mac_mls_subject_equal_ok: subject doesn't have both labels"));
296 
297 	/* If the single is EQUAL, it's ok. */
298 	if (mac_mls->mm_single.mme_type == MAC_MLS_TYPE_EQUAL)
299 		return (0);
300 
301 	/* If either range endpoint is EQUAL, it's ok. */
302 	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
303 	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
304 		return (0);
305 
306 	/* If the range is low-high, it's ok. */
307 	if (mac_mls->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
308 	    mac_mls->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
309 		return (0);
310 
311 	/* It's not ok. */
312 	return (EPERM);
313 }
314 
315 static int
316 mac_mls_valid(struct mac_mls *mac_mls)
317 {
318 
319 	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
320 		switch (mac_mls->mm_single.mme_type) {
321 		case MAC_MLS_TYPE_LEVEL:
322 			break;
323 
324 		case MAC_MLS_TYPE_EQUAL:
325 		case MAC_MLS_TYPE_HIGH:
326 		case MAC_MLS_TYPE_LOW:
327 			if (mac_mls->mm_single.mme_level != 0 ||
328 			    !MAC_MLS_BIT_SET_EMPTY(
329 			    mac_mls->mm_single.mme_compartments))
330 				return (EINVAL);
331 			break;
332 
333 		default:
334 			return (EINVAL);
335 		}
336 	} else {
337 		if (mac_mls->mm_single.mme_type != MAC_MLS_TYPE_UNDEF)
338 			return (EINVAL);
339 	}
340 
341 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
342 		switch (mac_mls->mm_rangelow.mme_type) {
343 		case MAC_MLS_TYPE_LEVEL:
344 			break;
345 
346 		case MAC_MLS_TYPE_EQUAL:
347 		case MAC_MLS_TYPE_HIGH:
348 		case MAC_MLS_TYPE_LOW:
349 			if (mac_mls->mm_rangelow.mme_level != 0 ||
350 			    !MAC_MLS_BIT_SET_EMPTY(
351 			    mac_mls->mm_rangelow.mme_compartments))
352 				return (EINVAL);
353 			break;
354 
355 		default:
356 			return (EINVAL);
357 		}
358 
359 		switch (mac_mls->mm_rangehigh.mme_type) {
360 		case MAC_MLS_TYPE_LEVEL:
361 			break;
362 
363 		case MAC_MLS_TYPE_EQUAL:
364 		case MAC_MLS_TYPE_HIGH:
365 		case MAC_MLS_TYPE_LOW:
366 			if (mac_mls->mm_rangehigh.mme_level != 0 ||
367 			    !MAC_MLS_BIT_SET_EMPTY(
368 			    mac_mls->mm_rangehigh.mme_compartments))
369 				return (EINVAL);
370 			break;
371 
372 		default:
373 			return (EINVAL);
374 		}
375 		if (!mac_mls_dominate_element(&mac_mls->mm_rangehigh,
376 		    &mac_mls->mm_rangelow))
377 			return (EINVAL);
378 	} else {
379 		if (mac_mls->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
380 		    mac_mls->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
381 			return (EINVAL);
382 	}
383 
384 	return (0);
385 }
386 
387 static void
388 mac_mls_set_range(struct mac_mls *mac_mls, u_short typelow,
389     u_short levellow, u_char *compartmentslow, u_short typehigh,
390     u_short levelhigh, u_char *compartmentshigh)
391 {
392 
393 	mac_mls->mm_rangelow.mme_type = typelow;
394 	mac_mls->mm_rangelow.mme_level = levellow;
395 	if (compartmentslow != NULL)
396 		memcpy(mac_mls->mm_rangelow.mme_compartments,
397 		    compartmentslow,
398 		    sizeof(mac_mls->mm_rangelow.mme_compartments));
399 	mac_mls->mm_rangehigh.mme_type = typehigh;
400 	mac_mls->mm_rangehigh.mme_level = levelhigh;
401 	if (compartmentshigh != NULL)
402 		memcpy(mac_mls->mm_rangehigh.mme_compartments,
403 		    compartmentshigh,
404 		    sizeof(mac_mls->mm_rangehigh.mme_compartments));
405 	mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
406 }
407 
408 static void
409 mac_mls_set_single(struct mac_mls *mac_mls, u_short type, u_short level,
410     u_char *compartments)
411 {
412 
413 	mac_mls->mm_single.mme_type = type;
414 	mac_mls->mm_single.mme_level = level;
415 	if (compartments != NULL)
416 		memcpy(mac_mls->mm_single.mme_compartments, compartments,
417 		    sizeof(mac_mls->mm_single.mme_compartments));
418 	mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
419 }
420 
421 static void
422 mac_mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
423 {
424 
425 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
426 	    ("mac_mls_copy_range: labelfrom not range"));
427 
428 	labelto->mm_rangelow = labelfrom->mm_rangelow;
429 	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
430 	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
431 }
432 
433 static void
434 mac_mls_copy_single(struct mac_mls *labelfrom, struct mac_mls *labelto)
435 {
436 
437 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_SINGLE) != 0,
438 	    ("mac_mls_copy_single: labelfrom not single"));
439 
440 	labelto->mm_single = labelfrom->mm_single;
441 	labelto->mm_flags |= MAC_MLS_FLAG_SINGLE;
442 }
443 
444 static void
445 mac_mls_copy(struct mac_mls *source, struct mac_mls *dest)
446 {
447 
448 	if (source->mm_flags & MAC_MLS_FLAG_SINGLE)
449 		mac_mls_copy_single(source, dest);
450 	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
451 		mac_mls_copy_range(source, dest);
452 }
453 
454 /*
455  * Policy module operations.
456  */
457 static void
458 mac_mls_destroy(struct mac_policy_conf *conf)
459 {
460 
461 }
462 
463 static void
464 mac_mls_init(struct mac_policy_conf *conf)
465 {
466 
467 }
468 
469 /*
470  * Label operations.
471  */
472 static void
473 mac_mls_init_label(struct label *label)
474 {
475 
476 	SLOT(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(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(label) = NULL;
496 }
497 
498 /*
499  * mac_mls_element_to_string() is basically an snprintf wrapper with
500  * the same properties as snprintf().  It returns the length it would
501  * have added to the string in the event the string is too short.
502  */
503 static size_t
504 mac_mls_element_to_string(char *string, size_t size,
505     struct mac_mls_element *element)
506 {
507 	int pos, bit = 1;
508 
509 	switch (element->mme_type) {
510 	case MAC_MLS_TYPE_HIGH:
511 		return (snprintf(string, size, "high"));
512 
513 	case MAC_MLS_TYPE_LOW:
514 		return (snprintf(string, size, "low"));
515 
516 	case MAC_MLS_TYPE_EQUAL:
517 		return (snprintf(string, size, "equal"));
518 
519 	case MAC_MLS_TYPE_LEVEL:
520 		pos = snprintf(string, size, "%d:", element->mme_level);
521 		for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++) {
522 			if (MAC_MLS_BIT_TEST(bit, element->mme_compartments))
523 				pos += snprintf(string + pos, size - pos,
524 				    "%d+", bit);
525 		}
526 		if (string[pos - 1] == '+' || string[pos - 1] == ':')
527 			string[--pos] = NULL;
528 		return (pos);
529 
530 	default:
531 		panic("mac_mls_element_to_string: invalid type (%d)",
532 		    element->mme_type);
533 	}
534 }
535 
536 static size_t
537 mac_mls_to_string(char *string, size_t size, size_t *caller_len,
538     struct mac_mls *mac_mls)
539 {
540 	size_t left, len;
541 	char *curptr;
542 
543 	bzero(string, size);
544 	curptr = string;
545 	left = size;
546 
547 	if (mac_mls->mm_flags & MAC_MLS_FLAG_SINGLE) {
548 		len = mac_mls_element_to_string(curptr, left,
549 		    &mac_mls->mm_single);
550 		if (len >= left)
551 			return (EINVAL);
552 		left -= len;
553 		curptr += len;
554 	}
555 
556 	if (mac_mls->mm_flags & MAC_MLS_FLAG_RANGE) {
557 		len = snprintf(curptr, left, "(");
558 		if (len >= left)
559 			return (EINVAL);
560 		left -= len;
561 		curptr += len;
562 
563 		len = mac_mls_element_to_string(curptr, left,
564 		    &mac_mls->mm_rangelow);
565 		if (len >= left)
566 			return (EINVAL);
567 		left -= len;
568 		curptr += len;
569 
570 		len = snprintf(curptr, left, "-");
571 		if (len >= left)
572 			return (EINVAL);
573 		left -= len;
574 		curptr += len;
575 
576 		len = mac_mls_element_to_string(curptr, left,
577 		    &mac_mls->mm_rangehigh);
578 		if (len >= left)
579 			return (EINVAL);
580 		left -= len;
581 		curptr += len;
582 
583 		len = snprintf(curptr, left, ")");
584 		if (len >= left)
585 			return (EINVAL);
586 		left -= len;
587 		curptr += len;
588 	}
589 
590 	*caller_len = strlen(string);
591 	return (0);
592 }
593 
594 static int
595 mac_mls_externalize_label(struct label *label, char *element_name,
596     char *element_data, size_t size, size_t *len, int *claimed)
597 {
598 	struct mac_mls *mac_mls;
599 	int error;
600 
601 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
602 		return (0);
603 
604 	(*claimed)++;
605 
606 	mac_mls = SLOT(label);
607 
608 	error = mac_mls_to_string(element_data, size, len, mac_mls);
609 	if (error)
610 		return (error);
611 
612 	*len = strlen(element_data);
613 	return (0);
614 }
615 
616 static int
617 mac_mls_parse_element(struct mac_mls_element *element, char *string)
618 {
619 
620 	if (strcmp(string, "high") == 0 ||
621 	    strcmp(string, "hi") == 0) {
622 		element->mme_type = MAC_MLS_TYPE_HIGH;
623 		element->mme_level = MAC_MLS_TYPE_UNDEF;
624 	} else if (strcmp(string, "low") == 0 ||
625 	    strcmp(string, "lo") == 0) {
626 		element->mme_type = MAC_MLS_TYPE_LOW;
627 		element->mme_level = MAC_MLS_TYPE_UNDEF;
628 	} else if (strcmp(string, "equal") == 0 ||
629 	    strcmp(string, "eq") == 0) {
630 		element->mme_type = MAC_MLS_TYPE_EQUAL;
631 		element->mme_level = MAC_MLS_TYPE_UNDEF;
632 	} else {
633 		char *p0, *p1;
634 		int d;
635 
636 		p0 = string;
637 		d = strtol(p0, &p1, 10);
638 
639 		if (d < 0 || d > 65535)
640 			return (EINVAL);
641 		element->mme_type = MAC_MLS_TYPE_LEVEL;
642 		element->mme_level = d;
643 
644 		if (*p1 != ':')  {
645 			if (p1 == p0 || *p1 != '\0')
646 				return (EINVAL);
647 			else
648 				return (0);
649 		}
650 		else
651 			if (*(p1 + 1) == '\0')
652 				return (0);
653 
654 		while ((p0 = ++p1)) {
655 			d = strtol(p0, &p1, 10);
656 			if (d < 1 || d > MAC_MLS_MAX_COMPARTMENTS)
657 				return (EINVAL);
658 
659 			MAC_MLS_BIT_SET(d, element->mme_compartments);
660 
661 			if (*p1 == '\0')
662 				break;
663 			if (p1 == p0 || *p1 != '+')
664 				return (EINVAL);
665 		}
666 	}
667 
668 	return (0);
669 }
670 
671 /*
672  * Note: destructively consumes the string, make a local copy before
673  * calling if that's a problem.
674  */
675 static int
676 mac_mls_parse(struct mac_mls *mac_mls, char *string)
677 {
678 	char *range, *rangeend, *rangehigh, *rangelow, *single;
679 	int error;
680 
681 	/* Do we have a range? */
682 	single = string;
683 	range = index(string, '(');
684 	if (range == single)
685 		single = NULL;
686 	rangelow = rangehigh = NULL;
687 	if (range != NULL) {
688 		/* Nul terminate the end of the single string. */
689 		*range = '\0';
690 		range++;
691 		rangelow = range;
692 		rangehigh = index(rangelow, '-');
693 		if (rangehigh == NULL)
694 			return (EINVAL);
695 		rangehigh++;
696 		if (*rangelow == '\0' || *rangehigh == '\0')
697 			return (EINVAL);
698 		rangeend = index(rangehigh, ')');
699 		if (rangeend == NULL)
700 			return (EINVAL);
701 		if (*(rangeend + 1) != '\0')
702 			return (EINVAL);
703 		/* Nul terminate the ends of the ranges. */
704 		*(rangehigh - 1) = '\0';
705 		*rangeend = '\0';
706 	}
707 	KASSERT((rangelow != NULL && rangehigh != NULL) ||
708 	    (rangelow == NULL && rangehigh == NULL),
709 	    ("mac_mls_internalize_label: range mismatch"));
710 
711 	bzero(mac_mls, sizeof(*mac_mls));
712 	if (single != NULL) {
713 		error = mac_mls_parse_element(&mac_mls->mm_single, single);
714 		if (error)
715 			return (error);
716 		mac_mls->mm_flags |= MAC_MLS_FLAG_SINGLE;
717 	}
718 
719 	if (rangelow != NULL) {
720 		error = mac_mls_parse_element(&mac_mls->mm_rangelow,
721 		    rangelow);
722 		if (error)
723 			return (error);
724 		error = mac_mls_parse_element(&mac_mls->mm_rangehigh,
725 		    rangehigh);
726 		if (error)
727 			return (error);
728 		mac_mls->mm_flags |= MAC_MLS_FLAG_RANGE;
729 	}
730 
731 	error = mac_mls_valid(mac_mls);
732 	if (error)
733 		return (error);
734 
735 	return (0);
736 }
737 
738 static int
739 mac_mls_internalize_label(struct label *label, char *element_name,
740     char *element_data, int *claimed)
741 {
742 	struct mac_mls *mac_mls, mac_mls_temp;
743 	int error;
744 
745 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
746 		return (0);
747 
748 	(*claimed)++;
749 
750 	error = mac_mls_parse(&mac_mls_temp, element_data);
751 	if (error)
752 		return (error);
753 
754 	mac_mls = SLOT(label);
755 	*mac_mls = mac_mls_temp;
756 
757 	return (0);
758 }
759 
760 static void
761 mac_mls_copy_label(struct label *src, struct label *dest)
762 {
763 
764 	*SLOT(dest) = *SLOT(src);
765 }
766 
767 /*
768  * Labeling event operations: file system objects, and things that look
769  * a lot like file system objects.
770  */
771 static void
772 mac_mls_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
773     struct label *label)
774 {
775 	struct mac_mls *mac_mls;
776 	int mls_type;
777 
778 	mac_mls = SLOT(label);
779 	if (strcmp(dev->si_name, "null") == 0 ||
780 	    strcmp(dev->si_name, "zero") == 0 ||
781 	    strcmp(dev->si_name, "random") == 0 ||
782 	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
783 		mls_type = MAC_MLS_TYPE_EQUAL;
784 	else if (strcmp(dev->si_name, "kmem") == 0 ||
785 	    strcmp(dev->si_name, "mem") == 0)
786 		mls_type = MAC_MLS_TYPE_HIGH;
787 	else if (ptys_equal &&
788 	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
789 	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
790 		mls_type = MAC_MLS_TYPE_EQUAL;
791 	else
792 		mls_type = MAC_MLS_TYPE_LOW;
793 	mac_mls_set_single(mac_mls, mls_type, 0, NULL);
794 }
795 
796 static void
797 mac_mls_create_devfs_directory(char *dirname, int dirnamelen,
798     struct devfs_dirent *devfs_dirent, struct label *label)
799 {
800 	struct mac_mls *mac_mls;
801 
802 	mac_mls = SLOT(label);
803 	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
804 }
805 
806 static void
807 mac_mls_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
808     struct label *ddlabel, struct devfs_dirent *de, struct label *delabel)
809 {
810 	struct mac_mls *source, *dest;
811 
812 	source = SLOT(&cred->cr_label);
813 	dest = SLOT(delabel);
814 
815 	mac_mls_copy_single(source, dest);
816 }
817 
818 static void
819 mac_mls_create_devfs_vnode(struct devfs_dirent *devfs_dirent,
820     struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
821 {
822 	struct mac_mls *source, *dest;
823 
824 	source = SLOT(direntlabel);
825 	dest = SLOT(vnodelabel);
826 	mac_mls_copy_single(source, dest);
827 }
828 
829 static void
830 mac_mls_create_mount(struct ucred *cred, struct mount *mp,
831     struct label *mntlabel, struct label *fslabel)
832 {
833 	struct mac_mls *source, *dest;
834 
835 	source = SLOT(&cred->cr_label);
836 	dest = SLOT(mntlabel);
837 	mac_mls_copy_single(source, dest);
838 	dest = SLOT(fslabel);
839 	mac_mls_copy_single(source, dest);
840 }
841 
842 static void
843 mac_mls_create_root_mount(struct ucred *cred, struct mount *mp,
844     struct label *mntlabel, struct label *fslabel)
845 {
846 	struct mac_mls *mac_mls;
847 
848 	/* Always mount root as high integrity. */
849 	mac_mls = SLOT(fslabel);
850 	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
851 	mac_mls = SLOT(mntlabel);
852 	mac_mls_set_single(mac_mls, MAC_MLS_TYPE_LOW, 0, NULL);
853 }
854 
855 static void
856 mac_mls_relabel_vnode(struct ucred *cred, struct vnode *vp,
857     struct label *vnodelabel, struct label *label)
858 {
859 	struct mac_mls *source, *dest;
860 
861 	source = SLOT(label);
862 	dest = SLOT(vnodelabel);
863 
864 	mac_mls_copy(source, dest);
865 }
866 
867 static void
868 mac_mls_update_devfsdirent(struct devfs_dirent *devfs_dirent,
869     struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
870 {
871 	struct mac_mls *source, *dest;
872 
873 	source = SLOT(vnodelabel);
874 	dest = SLOT(direntlabel);
875 
876 	mac_mls_copy_single(source, dest);
877 }
878 
879 static void
880 mac_mls_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
881     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
882     struct label *vlabel)
883 {
884 	struct mac_mls *source, *dest;
885 
886 	source = SLOT(delabel);
887 	dest = SLOT(vlabel);
888 
889 	mac_mls_copy_single(source, dest);
890 }
891 
892 static int
893 mac_mls_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
894     struct vnode *vp, struct label *vlabel)
895 {
896 	struct mac_mls temp, *source, *dest;
897 	size_t buflen;
898 	int error;
899 
900 	source = SLOT(fslabel);
901 	dest = SLOT(vlabel);
902 
903 	buflen = sizeof(temp);
904 	bzero(&temp, buflen);
905 
906 	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
907 	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
908 	if (error == ENOATTR || error == EOPNOTSUPP) {
909 		/* Fall back to the fslabel. */
910 		mac_mls_copy_single(source, dest);
911 		return (0);
912 	} else if (error)
913 		return (error);
914 
915 	if (buflen != sizeof(temp)) {
916 		printf("mac_mls_associate_vnode_extattr: bad size %d\n",
917 		    buflen);
918 		return (EPERM);
919 	}
920 	if (mac_mls_valid(&temp) != 0) {
921 		printf("mac_mls_associate_vnode_extattr: invalid\n");
922 		return (EPERM);
923 	}
924 	if ((temp.mm_flags & MAC_MLS_FLAGS_BOTH) != MAC_MLS_FLAG_SINGLE) {
925 		printf("mac_mls_associated_vnode_extattr: not single\n");
926 		return (EPERM);
927 	}
928 
929 	mac_mls_copy_single(&temp, dest);
930 	return (0);
931 }
932 
933 static void
934 mac_mls_associate_vnode_singlelabel(struct mount *mp,
935     struct label *fslabel, struct vnode *vp, struct label *vlabel)
936 {
937 	struct mac_mls *source, *dest;
938 
939 	source = SLOT(fslabel);
940 	dest = SLOT(vlabel);
941 
942 	mac_mls_copy_single(source, dest);
943 }
944 
945 static int
946 mac_mls_create_vnode_extattr(struct ucred *cred, struct mount *mp,
947     struct label *fslabel, struct vnode *dvp, struct label *dlabel,
948     struct vnode *vp, struct label *vlabel, struct componentname *cnp)
949 {
950 	struct mac_mls *source, *dest, temp;
951 	size_t buflen;
952 	int error;
953 
954 	buflen = sizeof(temp);
955 	bzero(&temp, buflen);
956 
957 	source = SLOT(&cred->cr_label);
958 	dest = SLOT(vlabel);
959 	mac_mls_copy_single(source, &temp);
960 
961 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
962 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
963 	if (error == 0)
964 		mac_mls_copy_single(source, dest);
965 	return (error);
966 }
967 
968 static int
969 mac_mls_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
970     struct label *vlabel, struct label *intlabel)
971 {
972 	struct mac_mls *source, temp;
973 	size_t buflen;
974 	int error;
975 
976 	buflen = sizeof(temp);
977 	bzero(&temp, buflen);
978 
979 	source = SLOT(intlabel);
980 	if ((source->mm_flags & MAC_MLS_FLAG_SINGLE) == 0)
981 		return (0);
982 
983 	mac_mls_copy_single(source, &temp);
984 
985 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
986 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &temp, curthread);
987 	return (error);
988 }
989 
990 /*
991  * Labeling event operations: IPC object.
992  */
993 static void
994 mac_mls_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
995     struct mbuf *m, struct label *mbuflabel)
996 {
997 	struct mac_mls *source, *dest;
998 
999 	source = SLOT(socketlabel);
1000 	dest = SLOT(mbuflabel);
1001 
1002 	mac_mls_copy_single(source, dest);
1003 }
1004 
1005 static void
1006 mac_mls_create_socket(struct ucred *cred, struct socket *socket,
1007     struct label *socketlabel)
1008 {
1009 	struct mac_mls *source, *dest;
1010 
1011 	source = SLOT(&cred->cr_label);
1012 	dest = SLOT(socketlabel);
1013 
1014 	mac_mls_copy_single(source, dest);
1015 }
1016 
1017 static void
1018 mac_mls_create_pipe(struct ucred *cred, struct pipe *pipe,
1019     struct label *pipelabel)
1020 {
1021 	struct mac_mls *source, *dest;
1022 
1023 	source = SLOT(&cred->cr_label);
1024 	dest = SLOT(pipelabel);
1025 
1026 	mac_mls_copy_single(source, dest);
1027 }
1028 
1029 static void
1030 mac_mls_create_socket_from_socket(struct socket *oldsocket,
1031     struct label *oldsocketlabel, struct socket *newsocket,
1032     struct label *newsocketlabel)
1033 {
1034 	struct mac_mls *source, *dest;
1035 
1036 	source = SLOT(oldsocketlabel);
1037 	dest = SLOT(newsocketlabel);
1038 
1039 	mac_mls_copy_single(source, dest);
1040 }
1041 
1042 static void
1043 mac_mls_relabel_socket(struct ucred *cred, struct socket *socket,
1044     struct label *socketlabel, struct label *newlabel)
1045 {
1046 	struct mac_mls *source, *dest;
1047 
1048 	source = SLOT(newlabel);
1049 	dest = SLOT(socketlabel);
1050 
1051 	mac_mls_copy(source, dest);
1052 }
1053 
1054 static void
1055 mac_mls_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1056     struct label *pipelabel, struct label *newlabel)
1057 {
1058 	struct mac_mls *source, *dest;
1059 
1060 	source = SLOT(newlabel);
1061 	dest = SLOT(pipelabel);
1062 
1063 	mac_mls_copy(source, dest);
1064 }
1065 
1066 static void
1067 mac_mls_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1068     struct socket *socket, struct label *socketpeerlabel)
1069 {
1070 	struct mac_mls *source, *dest;
1071 
1072 	source = SLOT(mbuflabel);
1073 	dest = SLOT(socketpeerlabel);
1074 
1075 	mac_mls_copy_single(source, dest);
1076 }
1077 
1078 /*
1079  * Labeling event operations: network objects.
1080  */
1081 static void
1082 mac_mls_set_socket_peer_from_socket(struct socket *oldsocket,
1083     struct label *oldsocketlabel, struct socket *newsocket,
1084     struct label *newsocketpeerlabel)
1085 {
1086 	struct mac_mls *source, *dest;
1087 
1088 	source = SLOT(oldsocketlabel);
1089 	dest = SLOT(newsocketpeerlabel);
1090 
1091 	mac_mls_copy_single(source, dest);
1092 }
1093 
1094 static void
1095 mac_mls_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1096     struct label *bpflabel)
1097 {
1098 	struct mac_mls *source, *dest;
1099 
1100 	source = SLOT(&cred->cr_label);
1101 	dest = SLOT(bpflabel);
1102 
1103 	mac_mls_copy_single(source, dest);
1104 }
1105 
1106 static void
1107 mac_mls_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1108 {
1109 	struct mac_mls *dest;
1110 	int level;
1111 
1112 	dest = SLOT(ifnetlabel);
1113 
1114 	if (ifnet->if_type == IFT_LOOP)
1115 		level = MAC_MLS_TYPE_EQUAL;
1116 	else
1117 		level = MAC_MLS_TYPE_LOW;
1118 
1119 	mac_mls_set_single(dest, level, 0, NULL);
1120 	mac_mls_set_range(dest, level, 0, NULL, level, 0, NULL);
1121 }
1122 
1123 static void
1124 mac_mls_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1125     struct ipq *ipq, struct label *ipqlabel)
1126 {
1127 	struct mac_mls *source, *dest;
1128 
1129 	source = SLOT(fragmentlabel);
1130 	dest = SLOT(ipqlabel);
1131 
1132 	mac_mls_copy_single(source, dest);
1133 }
1134 
1135 static void
1136 mac_mls_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1137     struct mbuf *datagram, struct label *datagramlabel)
1138 {
1139 	struct mac_mls *source, *dest;
1140 
1141 	source = SLOT(ipqlabel);
1142 	dest = SLOT(datagramlabel);
1143 
1144 	/* Just use the head, since we require them all to match. */
1145 	mac_mls_copy_single(source, dest);
1146 }
1147 
1148 static void
1149 mac_mls_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1150     struct mbuf *fragment, struct label *fragmentlabel)
1151 {
1152 	struct mac_mls *source, *dest;
1153 
1154 	source = SLOT(datagramlabel);
1155 	dest = SLOT(fragmentlabel);
1156 
1157 	mac_mls_copy_single(source, dest);
1158 }
1159 
1160 static void
1161 mac_mls_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1162     struct label *oldmbuflabel, struct mbuf *newmbuf,
1163     struct label *newmbuflabel)
1164 {
1165 	struct mac_mls *source, *dest;
1166 
1167 	source = SLOT(oldmbuflabel);
1168 	dest = SLOT(newmbuflabel);
1169 
1170 	/*
1171 	 * Because the source mbuf may not yet have been "created",
1172 	 * just initialized, we do a conditional copy.  Since we don't
1173 	 * allow mbufs to have ranges, do a KASSERT to make sure that
1174 	 * doesn't happen.
1175 	 */
1176 	KASSERT((source->mm_flags & MAC_MLS_FLAG_RANGE) == 0,
1177 	    ("mac_mls_create_mbuf_from_mbuf: source mbuf has range"));
1178 	mac_mls_copy(source, dest);
1179 }
1180 
1181 static void
1182 mac_mls_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1183     struct mbuf *mbuf, struct label *mbuflabel)
1184 {
1185 	struct mac_mls *dest;
1186 
1187 	dest = SLOT(mbuflabel);
1188 
1189 	mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1190 }
1191 
1192 static void
1193 mac_mls_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1194     struct mbuf *mbuf, struct label *mbuflabel)
1195 {
1196 	struct mac_mls *source, *dest;
1197 
1198 	source = SLOT(bpflabel);
1199 	dest = SLOT(mbuflabel);
1200 
1201 	mac_mls_copy_single(source, dest);
1202 }
1203 
1204 static void
1205 mac_mls_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1206     struct mbuf *m, struct label *mbuflabel)
1207 {
1208 	struct mac_mls *source, *dest;
1209 
1210 	source = SLOT(ifnetlabel);
1211 	dest = SLOT(mbuflabel);
1212 
1213 	mac_mls_copy_single(source, dest);
1214 }
1215 
1216 static void
1217 mac_mls_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1218     struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1219     struct mbuf *newmbuf, struct label *newmbuflabel)
1220 {
1221 	struct mac_mls *source, *dest;
1222 
1223 	source = SLOT(oldmbuflabel);
1224 	dest = SLOT(newmbuflabel);
1225 
1226 	mac_mls_copy_single(source, dest);
1227 }
1228 
1229 static void
1230 mac_mls_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1231     struct mbuf *newmbuf, struct label *newmbuflabel)
1232 {
1233 	struct mac_mls *source, *dest;
1234 
1235 	source = SLOT(oldmbuflabel);
1236 	dest = SLOT(newmbuflabel);
1237 
1238 	mac_mls_copy_single(source, dest);
1239 }
1240 
1241 static int
1242 mac_mls_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1243     struct ipq *ipq, struct label *ipqlabel)
1244 {
1245 	struct mac_mls *a, *b;
1246 
1247 	a = SLOT(ipqlabel);
1248 	b = SLOT(fragmentlabel);
1249 
1250 	return (mac_mls_equal_single(a, b));
1251 }
1252 
1253 static void
1254 mac_mls_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1255     struct label *ifnetlabel, struct label *newlabel)
1256 {
1257 	struct mac_mls *source, *dest;
1258 
1259 	source = SLOT(newlabel);
1260 	dest = SLOT(ifnetlabel);
1261 
1262 	mac_mls_copy(source, dest);
1263 }
1264 
1265 static void
1266 mac_mls_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1267     struct ipq *ipq, struct label *ipqlabel)
1268 {
1269 
1270 	/* NOOP: we only accept matching labels, so no need to update */
1271 }
1272 
1273 /*
1274  * Labeling event operations: processes.
1275  */
1276 static void
1277 mac_mls_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1278 {
1279 	struct mac_mls *source, *dest;
1280 
1281 	source = SLOT(&cred_parent->cr_label);
1282 	dest = SLOT(&cred_child->cr_label);
1283 
1284 	mac_mls_copy_single(source, dest);
1285 	mac_mls_copy_range(source, dest);
1286 }
1287 
1288 static void
1289 mac_mls_execve_transition(struct ucred *old, struct ucred *new,
1290     struct vnode *vp, struct label *vnodelabel)
1291 {
1292 	struct mac_mls *source, *dest;
1293 
1294 	source = SLOT(&old->cr_label);
1295 	dest = SLOT(&new->cr_label);
1296 
1297 	mac_mls_copy_single(source, dest);
1298 	mac_mls_copy_range(source, dest);
1299 }
1300 
1301 static int
1302 mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
1303     struct label *vnodelabel)
1304 {
1305 
1306 	return (0);
1307 }
1308 
1309 static void
1310 mac_mls_create_proc0(struct ucred *cred)
1311 {
1312 	struct mac_mls *dest;
1313 
1314 	dest = SLOT(&cred->cr_label);
1315 
1316 	mac_mls_set_single(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1317 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1318 	    0, NULL);
1319 }
1320 
1321 static void
1322 mac_mls_create_proc1(struct ucred *cred)
1323 {
1324 	struct mac_mls *dest;
1325 
1326 	dest = SLOT(&cred->cr_label);
1327 
1328 	mac_mls_set_single(dest, MAC_MLS_TYPE_LOW, 0, NULL);
1329 	mac_mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH,
1330 	    0, NULL);
1331 }
1332 
1333 static void
1334 mac_mls_relabel_cred(struct ucred *cred, struct label *newlabel)
1335 {
1336 	struct mac_mls *source, *dest;
1337 
1338 	source = SLOT(newlabel);
1339 	dest = SLOT(&cred->cr_label);
1340 
1341 	mac_mls_copy(source, dest);
1342 }
1343 
1344 /*
1345  * Access control checks.
1346  */
1347 static int
1348 mac_mls_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1349      struct ifnet *ifnet, struct label *ifnetlabel)
1350 {
1351 	struct mac_mls *a, *b;
1352 
1353 	if (!mac_mls_enabled)
1354 		return (0);
1355 
1356 	a = SLOT(bpflabel);
1357 	b = SLOT(ifnetlabel);
1358 
1359 	if (mac_mls_equal_single(a, b))
1360 		return (0);
1361 	return (EACCES);
1362 }
1363 
1364 static int
1365 mac_mls_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1366 {
1367 	struct mac_mls *subj, *new;
1368 	int error;
1369 
1370 	subj = SLOT(&cred->cr_label);
1371 	new = SLOT(newlabel);
1372 
1373 	/*
1374 	 * If there is an MLS label update for the credential, it may be
1375 	 * an update of single, range, or both.
1376 	 */
1377 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1378 	if (error)
1379 		return (error);
1380 
1381 	/*
1382 	 * If the MLS label is to be changed, authorize as appropriate.
1383 	 */
1384 	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1385 		/*
1386 		 * To change the MLS single label on a credential, the
1387 		 * new single label must be in the current range.
1388 		 */
1389 		if (new->mm_flags & MAC_MLS_FLAG_SINGLE &&
1390 		    !mac_mls_single_in_range(new, subj))
1391 			return (EPERM);
1392 
1393 		/*
1394 		 * To change the MLS range label on a credential, the
1395 		 * new range label must be in the current range.
1396 		 */
1397 		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
1398 		    !mac_mls_range_in_range(new, subj))
1399 			return (EPERM);
1400 
1401 		/*
1402 		 * To have EQUAL in any component of the new credential
1403 		 * MLS label, the subject must already have EQUAL in
1404 		 * their label.
1405 		 */
1406 		if (mac_mls_contains_equal(new)) {
1407 			error = mac_mls_subject_equal_ok(subj);
1408 			if (error)
1409 				return (error);
1410 		}
1411 
1412 		/*
1413 		 * XXXMAC: Additional consistency tests regarding the single
1414 		 * and range of the new label might be performed here.
1415 		 */
1416 	}
1417 
1418 	return (0);
1419 }
1420 
1421 static int
1422 mac_mls_check_cred_visible(struct ucred *u1, struct ucred *u2)
1423 {
1424 	struct mac_mls *subj, *obj;
1425 
1426 	if (!mac_mls_enabled)
1427 		return (0);
1428 
1429 	subj = SLOT(&u1->cr_label);
1430 	obj = SLOT(&u2->cr_label);
1431 
1432 	/* XXX: range */
1433 	if (!mac_mls_dominate_single(subj, obj))
1434 		return (ESRCH);
1435 
1436 	return (0);
1437 }
1438 
1439 static int
1440 mac_mls_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1441     struct label *ifnetlabel, struct label *newlabel)
1442 {
1443 	struct mac_mls *subj, *new;
1444 	int error;
1445 
1446 	subj = SLOT(&cred->cr_label);
1447 	new = SLOT(newlabel);
1448 
1449 	/*
1450 	 * If there is an MLS label update for the interface, it may
1451 	 * be an update of single, range, or both.
1452 	 */
1453 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
1454 	if (error)
1455 		return (error);
1456 
1457 	/*
1458 	 * If the MLS label is to be changed, authorize as appropriate.
1459 	 */
1460 	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
1461 		/*
1462 		 * Rely on traditional superuser status for the MLS
1463 		 * interface relabel requirements.  XXX: This will go
1464 		 * away.
1465 		 */
1466 		error = suser_cred(cred, 0);
1467 		if (error)
1468 			return (EPERM);
1469 
1470 		/*
1471 		 * XXXMAC: Additional consistency tests regarding the single
1472 		 * and the range of the new label might be performed here.
1473 		 */
1474 	}
1475 
1476 	return (0);
1477 }
1478 
1479 static int
1480 mac_mls_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1481     struct mbuf *m, struct label *mbuflabel)
1482 {
1483 	struct mac_mls *p, *i;
1484 
1485 	if (!mac_mls_enabled)
1486 		return (0);
1487 
1488 	p = SLOT(mbuflabel);
1489 	i = SLOT(ifnetlabel);
1490 
1491 	return (mac_mls_single_in_range(p, i) ? 0 : EACCES);
1492 }
1493 
1494 static int
1495 mac_mls_check_mount_stat(struct ucred *cred, struct mount *mp,
1496     struct label *mntlabel)
1497 {
1498 	struct mac_mls *subj, *obj;
1499 
1500 	if (!mac_mls_enabled)
1501 		return (0);
1502 
1503 	subj = SLOT(&cred->cr_label);
1504 	obj = SLOT(mntlabel);
1505 
1506 	if (!mac_mls_dominate_single(subj, obj))
1507 		return (EACCES);
1508 
1509 	return (0);
1510 }
1511 
1512 static int
1513 mac_mls_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1514     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1515 {
1516 
1517 	if(!mac_mls_enabled)
1518 		return (0);
1519 
1520 	/* XXX: This will be implemented soon... */
1521 
1522 	return (0);
1523 }
1524 
1525 static int
1526 mac_mls_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1527     struct label *pipelabel)
1528 {
1529 	struct mac_mls *subj, *obj;
1530 
1531 	if (!mac_mls_enabled)
1532 		return (0);
1533 
1534 	subj = SLOT(&cred->cr_label);
1535 	obj = SLOT((pipelabel));
1536 
1537 	if (!mac_mls_dominate_single(subj, obj))
1538 		return (EACCES);
1539 
1540 	return (0);
1541 }
1542 
1543 static int
1544 mac_mls_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1545     struct label *pipelabel)
1546 {
1547 	struct mac_mls *subj, *obj;
1548 
1549 	if (!mac_mls_enabled)
1550 		return (0);
1551 
1552 	subj = SLOT(&cred->cr_label);
1553 	obj = SLOT((pipelabel));
1554 
1555 	if (!mac_mls_dominate_single(subj, obj))
1556 		return (EACCES);
1557 
1558 	return (0);
1559 }
1560 
1561 static int
1562 mac_mls_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1563     struct label *pipelabel, struct label *newlabel)
1564 {
1565 	struct mac_mls *subj, *obj, *new;
1566 	int error;
1567 
1568 	new = SLOT(newlabel);
1569 	subj = SLOT(&cred->cr_label);
1570 	obj = SLOT(pipelabel);
1571 
1572 	/*
1573 	 * If there is an MLS label update for a pipe, it must be a
1574 	 * single update.
1575 	 */
1576 	error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
1577 	if (error)
1578 		return (error);
1579 
1580 	/*
1581 	 * To perform a relabel of a pipe (MLS label or not), MLS must
1582 	 * authorize the relabel.
1583 	 */
1584 	if (!mac_mls_single_in_range(obj, subj))
1585 		return (EPERM);
1586 
1587 	/*
1588 	 * If the MLS label is to be changed, authorize as appropriate.
1589 	 */
1590 	if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
1591 		/*
1592 		 * To change the MLS label on a pipe, the new pipe label
1593 		 * must be in the subject range.
1594 		 */
1595 		if (!mac_mls_single_in_range(new, subj))
1596 			return (EPERM);
1597 
1598 		/*
1599 		 * To change the MLS label on a pipe to be EQUAL, the
1600 		 * subject must have appropriate privilege.
1601 		 */
1602 		if (mac_mls_contains_equal(new)) {
1603 			error = mac_mls_subject_equal_ok(subj);
1604 			if (error)
1605 				return (error);
1606 		}
1607 	}
1608 
1609 	return (0);
1610 }
1611 
1612 static int
1613 mac_mls_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1614     struct label *pipelabel)
1615 {
1616 	struct mac_mls *subj, *obj;
1617 
1618 	if (!mac_mls_enabled)
1619 		return (0);
1620 
1621 	subj = SLOT(&cred->cr_label);
1622 	obj = SLOT((pipelabel));
1623 
1624 	if (!mac_mls_dominate_single(subj, obj))
1625 		return (EACCES);
1626 
1627 	return (0);
1628 }
1629 
1630 static int
1631 mac_mls_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1632     struct label *pipelabel)
1633 {
1634 	struct mac_mls *subj, *obj;
1635 
1636 	if (!mac_mls_enabled)
1637 		return (0);
1638 
1639 	subj = SLOT(&cred->cr_label);
1640 	obj = SLOT((pipelabel));
1641 
1642 	if (!mac_mls_dominate_single(obj, subj))
1643 		return (EACCES);
1644 
1645 	return (0);
1646 }
1647 
1648 static int
1649 mac_mls_check_proc_debug(struct ucred *cred, struct proc *proc)
1650 {
1651 	struct mac_mls *subj, *obj;
1652 
1653 	if (!mac_mls_enabled)
1654 		return (0);
1655 
1656 	subj = SLOT(&cred->cr_label);
1657 	obj = SLOT(&proc->p_ucred->cr_label);
1658 
1659 	/* XXX: range checks */
1660 	if (!mac_mls_dominate_single(subj, obj))
1661 		return (ESRCH);
1662 	if (!mac_mls_dominate_single(obj, subj))
1663 		return (EACCES);
1664 
1665 	return (0);
1666 }
1667 
1668 static int
1669 mac_mls_check_proc_sched(struct ucred *cred, struct proc *proc)
1670 {
1671 	struct mac_mls *subj, *obj;
1672 
1673 	if (!mac_mls_enabled)
1674 		return (0);
1675 
1676 	subj = SLOT(&cred->cr_label);
1677 	obj = SLOT(&proc->p_ucred->cr_label);
1678 
1679 	/* XXX: range checks */
1680 	if (!mac_mls_dominate_single(subj, obj))
1681 		return (ESRCH);
1682 	if (!mac_mls_dominate_single(obj, subj))
1683 		return (EACCES);
1684 
1685 	return (0);
1686 }
1687 
1688 static int
1689 mac_mls_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1690 {
1691 	struct mac_mls *subj, *obj;
1692 
1693 	if (!mac_mls_enabled)
1694 		return (0);
1695 
1696 	subj = SLOT(&cred->cr_label);
1697 	obj = SLOT(&proc->p_ucred->cr_label);
1698 
1699 	/* XXX: range checks */
1700 	if (!mac_mls_dominate_single(subj, obj))
1701 		return (ESRCH);
1702 	if (!mac_mls_dominate_single(obj, subj))
1703 		return (EACCES);
1704 
1705 	return (0);
1706 }
1707 
1708 static int
1709 mac_mls_check_socket_deliver(struct socket *so, struct label *socketlabel,
1710     struct mbuf *m, struct label *mbuflabel)
1711 {
1712 	struct mac_mls *p, *s;
1713 
1714 	if (!mac_mls_enabled)
1715 		return (0);
1716 
1717 	p = SLOT(mbuflabel);
1718 	s = SLOT(socketlabel);
1719 
1720 	return (mac_mls_equal_single(p, s) ? 0 : EACCES);
1721 }
1722 
1723 static int
1724 mac_mls_check_socket_relabel(struct ucred *cred, struct socket *socket,
1725     struct label *socketlabel, struct label *newlabel)
1726 {
1727 	struct mac_mls *subj, *obj, *new;
1728 	int error;
1729 
1730 	new = SLOT(newlabel);
1731 	subj = SLOT(&cred->cr_label);
1732 	obj = SLOT(socketlabel);
1733 
1734 	/*
1735 	 * If there is an MLS label update for the socket, it may be
1736 	 * an update of single.
1737 	 */
1738 	error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
1739 	if (error)
1740 		return (error);
1741 
1742 	/*
1743 	 * To relabel a socket, the old socket single must be in the subject
1744 	 * range.
1745 	 */
1746 	if (!mac_mls_single_in_range(obj, subj))
1747 		return (EPERM);
1748 
1749 	/*
1750 	 * If the MLS label is to be changed, authorize as appropriate.
1751 	 */
1752 	if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
1753 		/*
1754 		 * To relabel a socket, the new socket single must be in
1755 		 * the subject range.
1756 		 */
1757 		if (!mac_mls_single_in_range(new, subj))
1758 			return (EPERM);
1759 
1760 		/*
1761 		 * To change the MLS label on the socket to contain EQUAL,
1762 		 * the subject must have appropriate privilege.
1763 		 */
1764 		if (mac_mls_contains_equal(new)) {
1765 			error = mac_mls_subject_equal_ok(subj);
1766 			if (error)
1767 				return (error);
1768 		}
1769 	}
1770 
1771 	return (0);
1772 }
1773 
1774 static int
1775 mac_mls_check_socket_visible(struct ucred *cred, struct socket *socket,
1776     struct label *socketlabel)
1777 {
1778 	struct mac_mls *subj, *obj;
1779 
1780 	if (!mac_mls_enabled)
1781 		return (0);
1782 
1783 	subj = SLOT(&cred->cr_label);
1784 	obj = SLOT(socketlabel);
1785 
1786 	if (!mac_mls_dominate_single(subj, obj))
1787 		return (ENOENT);
1788 
1789 	return (0);
1790 }
1791 
1792 static int
1793 mac_mls_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
1794     struct label *dlabel)
1795 {
1796 	struct mac_mls *subj, *obj;
1797 
1798 	if (!mac_mls_enabled)
1799 		return (0);
1800 
1801 	subj = SLOT(&cred->cr_label);
1802 	obj = SLOT(dlabel);
1803 
1804 	if (!mac_mls_dominate_single(subj, obj))
1805 		return (EACCES);
1806 
1807 	return (0);
1808 }
1809 
1810 static int
1811 mac_mls_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
1812     struct label *dlabel)
1813 {
1814 	struct mac_mls *subj, *obj;
1815 
1816 	if (!mac_mls_enabled)
1817 		return (0);
1818 
1819 	subj = SLOT(&cred->cr_label);
1820 	obj = SLOT(dlabel);
1821 
1822 	if (!mac_mls_dominate_single(subj, obj))
1823 		return (EACCES);
1824 
1825 	return (0);
1826 }
1827 
1828 static int
1829 mac_mls_check_vnode_create(struct ucred *cred, struct vnode *dvp,
1830     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
1831 {
1832 	struct mac_mls *subj, *obj;
1833 
1834 	if (!mac_mls_enabled)
1835 		return (0);
1836 
1837 	subj = SLOT(&cred->cr_label);
1838 	obj = SLOT(dlabel);
1839 
1840 	if (!mac_mls_dominate_single(obj, subj))
1841 		return (EACCES);
1842 
1843 	return (0);
1844 }
1845 
1846 static int
1847 mac_mls_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
1848     struct label *dlabel, struct vnode *vp, struct label *label,
1849     struct componentname *cnp)
1850 {
1851 	struct mac_mls *subj, *obj;
1852 
1853 	if (!mac_mls_enabled)
1854 		return (0);
1855 
1856 	subj = SLOT(&cred->cr_label);
1857 	obj = SLOT(dlabel);
1858 
1859 	if (!mac_mls_dominate_single(obj, subj))
1860 		return (EACCES);
1861 
1862 	obj = SLOT(label);
1863 
1864 	if (!mac_mls_dominate_single(obj, subj))
1865 		return (EACCES);
1866 
1867 	return (0);
1868 }
1869 
1870 static int
1871 mac_mls_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
1872     struct label *label, acl_type_t type)
1873 {
1874 	struct mac_mls *subj, *obj;
1875 
1876 	if (!mac_mls_enabled)
1877 		return (0);
1878 
1879 	subj = SLOT(&cred->cr_label);
1880 	obj = SLOT(label);
1881 
1882 	if (!mac_mls_dominate_single(obj, subj))
1883 		return (EACCES);
1884 
1885 	return (0);
1886 }
1887 
1888 static int
1889 mac_mls_check_vnode_exec(struct ucred *cred, struct vnode *vp,
1890     struct label *label)
1891 {
1892 	struct mac_mls *subj, *obj;
1893 
1894 	if (!mac_mls_enabled)
1895 		return (0);
1896 
1897 	subj = SLOT(&cred->cr_label);
1898 	obj = SLOT(label);
1899 
1900 	if (!mac_mls_dominate_single(subj, obj))
1901 		return (EACCES);
1902 
1903 	return (0);
1904 }
1905 
1906 static int
1907 mac_mls_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
1908     struct label *label, acl_type_t type)
1909 {
1910 	struct mac_mls *subj, *obj;
1911 
1912 	if (!mac_mls_enabled)
1913 		return (0);
1914 
1915 	subj = SLOT(&cred->cr_label);
1916 	obj = SLOT(label);
1917 
1918 	if (!mac_mls_dominate_single(subj, obj))
1919 		return (EACCES);
1920 
1921 	return (0);
1922 }
1923 
1924 static int
1925 mac_mls_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
1926     struct label *label, int attrnamespace, const char *name, struct uio *uio)
1927 {
1928 	struct mac_mls *subj, *obj;
1929 
1930 	if (!mac_mls_enabled)
1931 		return (0);
1932 
1933 	subj = SLOT(&cred->cr_label);
1934 	obj = SLOT(label);
1935 
1936 	if (!mac_mls_dominate_single(subj, obj))
1937 		return (EACCES);
1938 
1939 	return (0);
1940 }
1941 
1942 static int
1943 mac_mls_check_vnode_link(struct ucred *cred, struct vnode *dvp,
1944     struct label *dlabel, struct vnode *vp, struct label *label,
1945     struct componentname *cnp)
1946 {
1947 	struct mac_mls *subj, *obj;
1948 
1949 	if (!mac_mls_enabled)
1950 		return (0);
1951 
1952 	subj = SLOT(&cred->cr_label);
1953 	obj = SLOT(dlabel);
1954 
1955 	if (!mac_mls_dominate_single(obj, subj))
1956 		return (EACCES);
1957 
1958 	obj = SLOT(dlabel);
1959 	if (!mac_mls_dominate_single(obj, subj))
1960 		return (EACCES);
1961 
1962 	return (0);
1963 }
1964 
1965 static int
1966 mac_mls_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
1967     struct label *dlabel, struct componentname *cnp)
1968 {
1969 	struct mac_mls *subj, *obj;
1970 
1971 	if (!mac_mls_enabled)
1972 		return (0);
1973 
1974 	subj = SLOT(&cred->cr_label);
1975 	obj = SLOT(dlabel);
1976 
1977 	if (!mac_mls_dominate_single(subj, obj))
1978 		return (EACCES);
1979 
1980 	return (0);
1981 }
1982 
1983 static int
1984 mac_mls_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
1985     struct label *label, int prot)
1986 {
1987 	struct mac_mls *subj, *obj;
1988 
1989 	/*
1990 	 * Rely on the use of open()-time protections to handle
1991 	 * non-revocation cases.
1992 	 */
1993 	if (!mac_mls_enabled || !revocation_enabled)
1994 		return (0);
1995 
1996 	subj = SLOT(&cred->cr_label);
1997 	obj = SLOT(label);
1998 
1999 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2000 		if (!mac_mls_dominate_single(subj, obj))
2001 			return (EACCES);
2002 	}
2003 	if (prot & VM_PROT_WRITE) {
2004 		if (!mac_mls_dominate_single(obj, subj))
2005 			return (EACCES);
2006 	}
2007 
2008 	return (0);
2009 }
2010 
2011 static int
2012 mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2013     struct label *vnodelabel, mode_t acc_mode)
2014 {
2015 	struct mac_mls *subj, *obj;
2016 
2017 	if (!mac_mls_enabled)
2018 		return (0);
2019 
2020 	subj = SLOT(&cred->cr_label);
2021 	obj = SLOT(vnodelabel);
2022 
2023 	/* XXX privilege override for admin? */
2024 	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2025 		if (!mac_mls_dominate_single(subj, obj))
2026 			return (EACCES);
2027 	}
2028 	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2029 		if (!mac_mls_dominate_single(obj, subj))
2030 			return (EACCES);
2031 	}
2032 
2033 	return (0);
2034 }
2035 
2036 static int
2037 mac_mls_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2038     struct vnode *vp, struct label *label)
2039 {
2040 	struct mac_mls *subj, *obj;
2041 
2042 	if (!mac_mls_enabled || !revocation_enabled)
2043 		return (0);
2044 
2045 	subj = SLOT(&active_cred->cr_label);
2046 	obj = SLOT(label);
2047 
2048 	if (!mac_mls_dominate_single(subj, obj))
2049 		return (EACCES);
2050 
2051 	return (0);
2052 }
2053 
2054 static int
2055 mac_mls_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2056     struct vnode *vp, struct label *label)
2057 {
2058 	struct mac_mls *subj, *obj;
2059 
2060 	if (!mac_mls_enabled || !revocation_enabled)
2061 		return (0);
2062 
2063 	subj = SLOT(&active_cred->cr_label);
2064 	obj = SLOT(label);
2065 
2066 	if (!mac_mls_dominate_single(subj, obj))
2067 		return (EACCES);
2068 
2069 	return (0);
2070 }
2071 
2072 static int
2073 mac_mls_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2074     struct label *dlabel)
2075 {
2076 	struct mac_mls *subj, *obj;
2077 
2078 	if (!mac_mls_enabled)
2079 		return (0);
2080 
2081 	subj = SLOT(&cred->cr_label);
2082 	obj = SLOT(dlabel);
2083 
2084 	if (!mac_mls_dominate_single(subj, obj))
2085 		return (EACCES);
2086 
2087 	return (0);
2088 }
2089 
2090 static int
2091 mac_mls_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2092     struct label *vnodelabel)
2093 {
2094 	struct mac_mls *subj, *obj;
2095 
2096 	if (!mac_mls_enabled)
2097 		return (0);
2098 
2099 	subj = SLOT(&cred->cr_label);
2100 	obj = SLOT(vnodelabel);
2101 
2102 	if (!mac_mls_dominate_single(subj, obj))
2103 		return (EACCES);
2104 
2105 	return (0);
2106 }
2107 
2108 static int
2109 mac_mls_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2110     struct label *vnodelabel, struct label *newlabel)
2111 {
2112 	struct mac_mls *old, *new, *subj;
2113 	int error;
2114 
2115 	old = SLOT(vnodelabel);
2116 	new = SLOT(newlabel);
2117 	subj = SLOT(&cred->cr_label);
2118 
2119 	/*
2120 	 * If there is an MLS label update for the vnode, it must be a
2121 	 * single label.
2122 	 */
2123 	error = mls_atmostflags(new, MAC_MLS_FLAG_SINGLE);
2124 	if (error)
2125 		return (error);
2126 
2127 	/*
2128 	 * To perform a relabel of the vnode (MLS label or not), MLS must
2129 	 * authorize the relabel.
2130 	 */
2131 	if (!mac_mls_single_in_range(old, subj))
2132 		return (EPERM);
2133 
2134 	/*
2135 	 * If the MLS label is to be changed, authorize as appropriate.
2136 	 */
2137 	if (new->mm_flags & MAC_MLS_FLAG_SINGLE) {
2138 		/*
2139 		 * To change the MLS label on a vnode, the new vnode label
2140 		 * must be in the subject range.
2141 		 */
2142 		if (!mac_mls_single_in_range(new, subj))
2143 			return (EPERM);
2144 
2145 		/*
2146 		 * To change the MLS label on the vnode to be EQUAL,
2147 		 * the subject must have appropriate privilege.
2148 		 */
2149 		if (mac_mls_contains_equal(new)) {
2150 			error = mac_mls_subject_equal_ok(subj);
2151 			if (error)
2152 				return (error);
2153 		}
2154 	}
2155 
2156 	return (0);
2157 }
2158 
2159 
2160 static int
2161 mac_mls_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2162     struct label *dlabel, struct vnode *vp, struct label *label,
2163     struct componentname *cnp)
2164 {
2165 	struct mac_mls *subj, *obj;
2166 
2167 	if (!mac_mls_enabled)
2168 		return (0);
2169 
2170 	subj = SLOT(&cred->cr_label);
2171 	obj = SLOT(dlabel);
2172 
2173 	if (!mac_mls_dominate_single(obj, subj))
2174 		return (EACCES);
2175 
2176 	obj = SLOT(label);
2177 
2178 	if (!mac_mls_dominate_single(obj, subj))
2179 		return (EACCES);
2180 
2181 	return (0);
2182 }
2183 
2184 static int
2185 mac_mls_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2186     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2187     struct componentname *cnp)
2188 {
2189 	struct mac_mls *subj, *obj;
2190 
2191 	if (!mac_mls_enabled)
2192 		return (0);
2193 
2194 	subj = SLOT(&cred->cr_label);
2195 	obj = SLOT(dlabel);
2196 
2197 	if (!mac_mls_dominate_single(obj, subj))
2198 		return (EACCES);
2199 
2200 	if (vp != NULL) {
2201 		obj = SLOT(label);
2202 
2203 		if (!mac_mls_dominate_single(obj, subj))
2204 			return (EACCES);
2205 	}
2206 
2207 	return (0);
2208 }
2209 
2210 static int
2211 mac_mls_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2212     struct label *label)
2213 {
2214 	struct mac_mls *subj, *obj;
2215 
2216 	if (!mac_mls_enabled)
2217 		return (0);
2218 
2219 	subj = SLOT(&cred->cr_label);
2220 	obj = SLOT(label);
2221 
2222 	if (!mac_mls_dominate_single(obj, subj))
2223 		return (EACCES);
2224 
2225 	return (0);
2226 }
2227 
2228 static int
2229 mac_mls_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2230     struct label *label, acl_type_t type, struct acl *acl)
2231 {
2232 	struct mac_mls *subj, *obj;
2233 
2234 	if (!mac_mls_enabled)
2235 		return (0);
2236 
2237 	subj = SLOT(&cred->cr_label);
2238 	obj = SLOT(label);
2239 
2240 	if (!mac_mls_dominate_single(obj, subj))
2241 		return (EACCES);
2242 
2243 	return (0);
2244 }
2245 
2246 static int
2247 mac_mls_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2248     struct label *vnodelabel, int attrnamespace, const char *name,
2249     struct uio *uio)
2250 {
2251 	struct mac_mls *subj, *obj;
2252 
2253 	if (!mac_mls_enabled)
2254 		return (0);
2255 
2256 	subj = SLOT(&cred->cr_label);
2257 	obj = SLOT(vnodelabel);
2258 
2259 	if (!mac_mls_dominate_single(obj, subj))
2260 		return (EACCES);
2261 
2262 	/* XXX: protect the MAC EA in a special way? */
2263 
2264 	return (0);
2265 }
2266 
2267 static int
2268 mac_mls_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2269     struct label *vnodelabel, u_long flags)
2270 {
2271 	struct mac_mls *subj, *obj;
2272 
2273 	if (!mac_mls_enabled)
2274 		return (0);
2275 
2276 	subj = SLOT(&cred->cr_label);
2277 	obj = SLOT(vnodelabel);
2278 
2279 	if (!mac_mls_dominate_single(obj, subj))
2280 		return (EACCES);
2281 
2282 	return (0);
2283 }
2284 
2285 static int
2286 mac_mls_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2287     struct label *vnodelabel, mode_t mode)
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(vnodelabel);
2296 
2297 	if (!mac_mls_dominate_single(obj, subj))
2298 		return (EACCES);
2299 
2300 	return (0);
2301 }
2302 
2303 static int
2304 mac_mls_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2305     struct label *vnodelabel, uid_t uid, gid_t gid)
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(vnodelabel);
2314 
2315 	if (!mac_mls_dominate_single(obj, subj))
2316 		return (EACCES);
2317 
2318 	return (0);
2319 }
2320 
2321 static int
2322 mac_mls_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2323     struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2324 {
2325 	struct mac_mls *subj, *obj;
2326 
2327 	if (!mac_mls_enabled)
2328 		return (0);
2329 
2330 	subj = SLOT(&cred->cr_label);
2331 	obj = SLOT(vnodelabel);
2332 
2333 	if (!mac_mls_dominate_single(obj, subj))
2334 		return (EACCES);
2335 
2336 	return (0);
2337 }
2338 
2339 static int
2340 mac_mls_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2341     struct vnode *vp, struct label *vnodelabel)
2342 {
2343 	struct mac_mls *subj, *obj;
2344 
2345 	if (!mac_mls_enabled)
2346 		return (0);
2347 
2348 	subj = SLOT(&active_cred->cr_label);
2349 	obj = SLOT(vnodelabel);
2350 
2351 	if (!mac_mls_dominate_single(subj, obj))
2352 		return (EACCES);
2353 
2354 	return (0);
2355 }
2356 
2357 static int
2358 mac_mls_check_vnode_write(struct ucred *active_cred, struct ucred *file_cred,
2359     struct vnode *vp, struct label *label)
2360 {
2361 	struct mac_mls *subj, *obj;
2362 
2363 	if (!mac_mls_enabled || !revocation_enabled)
2364 		return (0);
2365 
2366 	subj = SLOT(&active_cred->cr_label);
2367 	obj = SLOT(label);
2368 
2369 	if (!mac_mls_dominate_single(obj, subj))
2370 		return (EACCES);
2371 
2372 	return (0);
2373 }
2374 
2375 static struct mac_policy_op_entry mac_mls_ops[] =
2376 {
2377 	{ MAC_DESTROY,
2378 	    (macop_t)mac_mls_destroy },
2379 	{ MAC_INIT,
2380 	    (macop_t)mac_mls_init },
2381 	{ MAC_INIT_BPFDESC_LABEL,
2382 	    (macop_t)mac_mls_init_label },
2383 	{ MAC_INIT_CRED_LABEL,
2384 	    (macop_t)mac_mls_init_label },
2385 	{ MAC_INIT_DEVFSDIRENT_LABEL,
2386 	    (macop_t)mac_mls_init_label },
2387 	{ MAC_INIT_IFNET_LABEL,
2388 	    (macop_t)mac_mls_init_label },
2389 	{ MAC_INIT_IPQ_LABEL,
2390 	    (macop_t)mac_mls_init_label },
2391 	{ MAC_INIT_MBUF_LABEL,
2392 	    (macop_t)mac_mls_init_label_waitcheck },
2393 	{ MAC_INIT_MOUNT_LABEL,
2394 	    (macop_t)mac_mls_init_label },
2395 	{ MAC_INIT_MOUNT_FS_LABEL,
2396 	    (macop_t)mac_mls_init_label },
2397 	{ MAC_INIT_PIPE_LABEL,
2398 	    (macop_t)mac_mls_init_label },
2399 	{ MAC_INIT_SOCKET_LABEL,
2400 	    (macop_t)mac_mls_init_label_waitcheck },
2401 	{ MAC_INIT_SOCKET_PEER_LABEL,
2402 	    (macop_t)mac_mls_init_label_waitcheck },
2403 	{ MAC_INIT_VNODE_LABEL,
2404 	    (macop_t)mac_mls_init_label },
2405 	{ MAC_DESTROY_BPFDESC_LABEL,
2406 	    (macop_t)mac_mls_destroy_label },
2407 	{ MAC_DESTROY_CRED_LABEL,
2408 	    (macop_t)mac_mls_destroy_label },
2409 	{ MAC_DESTROY_DEVFSDIRENT_LABEL,
2410 	    (macop_t)mac_mls_destroy_label },
2411 	{ MAC_DESTROY_IFNET_LABEL,
2412 	    (macop_t)mac_mls_destroy_label },
2413 	{ MAC_DESTROY_IPQ_LABEL,
2414 	    (macop_t)mac_mls_destroy_label },
2415 	{ MAC_DESTROY_MBUF_LABEL,
2416 	    (macop_t)mac_mls_destroy_label },
2417 	{ MAC_DESTROY_MOUNT_LABEL,
2418 	    (macop_t)mac_mls_destroy_label },
2419 	{ MAC_DESTROY_MOUNT_FS_LABEL,
2420 	    (macop_t)mac_mls_destroy_label },
2421 	{ MAC_DESTROY_PIPE_LABEL,
2422 	    (macop_t)mac_mls_destroy_label },
2423 	{ MAC_DESTROY_SOCKET_LABEL,
2424 	    (macop_t)mac_mls_destroy_label },
2425 	{ MAC_DESTROY_SOCKET_PEER_LABEL,
2426 	    (macop_t)mac_mls_destroy_label },
2427 	{ MAC_DESTROY_VNODE_LABEL,
2428 	    (macop_t)mac_mls_destroy_label },
2429 	{ MAC_COPY_PIPE_LABEL,
2430 	    (macop_t)mac_mls_copy_label },
2431 	{ MAC_COPY_VNODE_LABEL,
2432 	    (macop_t)mac_mls_copy_label },
2433 	{ MAC_EXTERNALIZE_CRED_LABEL,
2434 	    (macop_t)mac_mls_externalize_label },
2435 	{ MAC_EXTERNALIZE_IFNET_LABEL,
2436 	    (macop_t)mac_mls_externalize_label },
2437 	{ MAC_EXTERNALIZE_PIPE_LABEL,
2438 	    (macop_t)mac_mls_externalize_label },
2439 	{ MAC_EXTERNALIZE_SOCKET_LABEL,
2440 	    (macop_t)mac_mls_externalize_label },
2441 	{ MAC_EXTERNALIZE_SOCKET_PEER_LABEL,
2442 	    (macop_t)mac_mls_externalize_label },
2443 	{ MAC_EXTERNALIZE_VNODE_LABEL,
2444 	    (macop_t)mac_mls_externalize_label },
2445 	{ MAC_INTERNALIZE_CRED_LABEL,
2446 	    (macop_t)mac_mls_internalize_label },
2447 	{ MAC_INTERNALIZE_IFNET_LABEL,
2448 	    (macop_t)mac_mls_internalize_label },
2449 	{ MAC_INTERNALIZE_PIPE_LABEL,
2450 	    (macop_t)mac_mls_internalize_label },
2451 	{ MAC_INTERNALIZE_SOCKET_LABEL,
2452 	    (macop_t)mac_mls_internalize_label },
2453 	{ MAC_INTERNALIZE_VNODE_LABEL,
2454 	    (macop_t)mac_mls_internalize_label },
2455 	{ MAC_CREATE_DEVFS_DEVICE,
2456 	    (macop_t)mac_mls_create_devfs_device },
2457 	{ MAC_CREATE_DEVFS_DIRECTORY,
2458 	    (macop_t)mac_mls_create_devfs_directory },
2459 	{ MAC_CREATE_DEVFS_SYMLINK,
2460 	    (macop_t)mac_mls_create_devfs_symlink },
2461 	{ MAC_CREATE_DEVFS_VNODE,
2462 	    (macop_t)mac_mls_create_devfs_vnode },
2463 	{ MAC_CREATE_MOUNT,
2464 	    (macop_t)mac_mls_create_mount },
2465 	{ MAC_CREATE_ROOT_MOUNT,
2466 	    (macop_t)mac_mls_create_root_mount },
2467 	{ MAC_RELABEL_VNODE,
2468 	    (macop_t)mac_mls_relabel_vnode },
2469 	{ MAC_UPDATE_DEVFSDIRENT,
2470 	    (macop_t)mac_mls_update_devfsdirent },
2471 	{ MAC_ASSOCIATE_VNODE_DEVFS,
2472 	    (macop_t)mac_mls_associate_vnode_devfs },
2473 	{ MAC_ASSOCIATE_VNODE_EXTATTR,
2474 	    (macop_t)mac_mls_associate_vnode_extattr },
2475 	{ MAC_ASSOCIATE_VNODE_SINGLELABEL,
2476 	    (macop_t)mac_mls_associate_vnode_singlelabel },
2477 	{ MAC_CREATE_VNODE_EXTATTR,
2478 	    (macop_t)mac_mls_create_vnode_extattr },
2479 	{ MAC_SETLABEL_VNODE_EXTATTR,
2480 	    (macop_t)mac_mls_setlabel_vnode_extattr },
2481 	{ MAC_CREATE_MBUF_FROM_SOCKET,
2482 	    (macop_t)mac_mls_create_mbuf_from_socket },
2483 	{ MAC_CREATE_PIPE,
2484 	    (macop_t)mac_mls_create_pipe },
2485 	{ MAC_CREATE_SOCKET,
2486 	    (macop_t)mac_mls_create_socket },
2487 	{ MAC_CREATE_SOCKET_FROM_SOCKET,
2488 	    (macop_t)mac_mls_create_socket_from_socket },
2489 	{ MAC_RELABEL_PIPE,
2490 	    (macop_t)mac_mls_relabel_pipe },
2491 	{ MAC_RELABEL_SOCKET,
2492 	    (macop_t)mac_mls_relabel_socket },
2493 	{ MAC_SET_SOCKET_PEER_FROM_MBUF,
2494 	    (macop_t)mac_mls_set_socket_peer_from_mbuf },
2495 	{ MAC_SET_SOCKET_PEER_FROM_SOCKET,
2496 	    (macop_t)mac_mls_set_socket_peer_from_socket },
2497 	{ MAC_CREATE_BPFDESC,
2498 	    (macop_t)mac_mls_create_bpfdesc },
2499 	{ MAC_CREATE_DATAGRAM_FROM_IPQ,
2500 	    (macop_t)mac_mls_create_datagram_from_ipq },
2501 	{ MAC_CREATE_FRAGMENT,
2502 	    (macop_t)mac_mls_create_fragment },
2503 	{ MAC_CREATE_IFNET,
2504 	    (macop_t)mac_mls_create_ifnet },
2505 	{ MAC_CREATE_IPQ,
2506 	    (macop_t)mac_mls_create_ipq },
2507 	{ MAC_CREATE_MBUF_FROM_MBUF,
2508 	    (macop_t)mac_mls_create_mbuf_from_mbuf },
2509 	{ MAC_CREATE_MBUF_LINKLAYER,
2510 	    (macop_t)mac_mls_create_mbuf_linklayer },
2511 	{ MAC_CREATE_MBUF_FROM_BPFDESC,
2512 	    (macop_t)mac_mls_create_mbuf_from_bpfdesc },
2513 	{ MAC_CREATE_MBUF_FROM_IFNET,
2514 	    (macop_t)mac_mls_create_mbuf_from_ifnet },
2515 	{ MAC_CREATE_MBUF_MULTICAST_ENCAP,
2516 	    (macop_t)mac_mls_create_mbuf_multicast_encap },
2517 	{ MAC_CREATE_MBUF_NETLAYER,
2518 	    (macop_t)mac_mls_create_mbuf_netlayer },
2519 	{ MAC_FRAGMENT_MATCH,
2520 	    (macop_t)mac_mls_fragment_match },
2521 	{ MAC_RELABEL_IFNET,
2522 	    (macop_t)mac_mls_relabel_ifnet },
2523 	{ MAC_UPDATE_IPQ,
2524 	    (macop_t)mac_mls_update_ipq },
2525 	{ MAC_CREATE_CRED,
2526 	    (macop_t)mac_mls_create_cred },
2527 	{ MAC_EXECVE_TRANSITION,
2528 	    (macop_t)mac_mls_execve_transition },
2529 	{ MAC_EXECVE_WILL_TRANSITION,
2530 	    (macop_t)mac_mls_execve_will_transition },
2531 	{ MAC_CREATE_PROC0,
2532 	    (macop_t)mac_mls_create_proc0 },
2533 	{ MAC_CREATE_PROC1,
2534 	    (macop_t)mac_mls_create_proc1 },
2535 	{ MAC_RELABEL_CRED,
2536 	    (macop_t)mac_mls_relabel_cred },
2537 	{ MAC_CHECK_BPFDESC_RECEIVE,
2538 	    (macop_t)mac_mls_check_bpfdesc_receive },
2539 	{ MAC_CHECK_CRED_RELABEL,
2540 	    (macop_t)mac_mls_check_cred_relabel },
2541 	{ MAC_CHECK_CRED_VISIBLE,
2542 	    (macop_t)mac_mls_check_cred_visible },
2543 	{ MAC_CHECK_IFNET_RELABEL,
2544 	    (macop_t)mac_mls_check_ifnet_relabel },
2545 	{ MAC_CHECK_IFNET_TRANSMIT,
2546 	    (macop_t)mac_mls_check_ifnet_transmit },
2547 	{ MAC_CHECK_MOUNT_STAT,
2548 	    (macop_t)mac_mls_check_mount_stat },
2549 	{ MAC_CHECK_PIPE_IOCTL,
2550 	    (macop_t)mac_mls_check_pipe_ioctl },
2551 	{ MAC_CHECK_PIPE_POLL,
2552 	    (macop_t)mac_mls_check_pipe_poll },
2553 	{ MAC_CHECK_PIPE_READ,
2554 	    (macop_t)mac_mls_check_pipe_read },
2555 	{ MAC_CHECK_PIPE_RELABEL,
2556 	    (macop_t)mac_mls_check_pipe_relabel },
2557 	{ MAC_CHECK_PIPE_STAT,
2558 	    (macop_t)mac_mls_check_pipe_stat },
2559 	{ MAC_CHECK_PIPE_WRITE,
2560 	    (macop_t)mac_mls_check_pipe_write },
2561 	{ MAC_CHECK_PROC_DEBUG,
2562 	    (macop_t)mac_mls_check_proc_debug },
2563 	{ MAC_CHECK_PROC_SCHED,
2564 	    (macop_t)mac_mls_check_proc_sched },
2565 	{ MAC_CHECK_PROC_SIGNAL,
2566 	    (macop_t)mac_mls_check_proc_signal },
2567 	{ MAC_CHECK_SOCKET_DELIVER,
2568 	    (macop_t)mac_mls_check_socket_deliver },
2569 	{ MAC_CHECK_SOCKET_RELABEL,
2570 	    (macop_t)mac_mls_check_socket_relabel },
2571 	{ MAC_CHECK_SOCKET_VISIBLE,
2572 	    (macop_t)mac_mls_check_socket_visible },
2573 	{ MAC_CHECK_VNODE_ACCESS,
2574 	    (macop_t)mac_mls_check_vnode_open },
2575 	{ MAC_CHECK_VNODE_CHDIR,
2576 	    (macop_t)mac_mls_check_vnode_chdir },
2577 	{ MAC_CHECK_VNODE_CHROOT,
2578 	    (macop_t)mac_mls_check_vnode_chroot },
2579 	{ MAC_CHECK_VNODE_CREATE,
2580 	    (macop_t)mac_mls_check_vnode_create },
2581 	{ MAC_CHECK_VNODE_DELETE,
2582 	    (macop_t)mac_mls_check_vnode_delete },
2583 	{ MAC_CHECK_VNODE_DELETEACL,
2584 	    (macop_t)mac_mls_check_vnode_deleteacl },
2585 	{ MAC_CHECK_VNODE_EXEC,
2586 	    (macop_t)mac_mls_check_vnode_exec },
2587 	{ MAC_CHECK_VNODE_GETACL,
2588 	    (macop_t)mac_mls_check_vnode_getacl },
2589 	{ MAC_CHECK_VNODE_GETEXTATTR,
2590 	    (macop_t)mac_mls_check_vnode_getextattr },
2591 	{ MAC_CHECK_VNODE_LINK,
2592 	    (macop_t)mac_mls_check_vnode_link },
2593 	{ MAC_CHECK_VNODE_LOOKUP,
2594 	    (macop_t)mac_mls_check_vnode_lookup },
2595 	{ MAC_CHECK_VNODE_MMAP,
2596 	    (macop_t)mac_mls_check_vnode_mmap },
2597 	{ MAC_CHECK_VNODE_MPROTECT,
2598 	    (macop_t)mac_mls_check_vnode_mmap },
2599 	{ MAC_CHECK_VNODE_OPEN,
2600 	    (macop_t)mac_mls_check_vnode_open },
2601 	{ MAC_CHECK_VNODE_POLL,
2602 	    (macop_t)mac_mls_check_vnode_poll },
2603 	{ MAC_CHECK_VNODE_READ,
2604 	    (macop_t)mac_mls_check_vnode_read },
2605 	{ MAC_CHECK_VNODE_READDIR,
2606 	    (macop_t)mac_mls_check_vnode_readdir },
2607 	{ MAC_CHECK_VNODE_READLINK,
2608 	    (macop_t)mac_mls_check_vnode_readlink },
2609 	{ MAC_CHECK_VNODE_RELABEL,
2610 	    (macop_t)mac_mls_check_vnode_relabel },
2611 	{ MAC_CHECK_VNODE_RENAME_FROM,
2612 	    (macop_t)mac_mls_check_vnode_rename_from },
2613 	{ MAC_CHECK_VNODE_RENAME_TO,
2614 	    (macop_t)mac_mls_check_vnode_rename_to },
2615 	{ MAC_CHECK_VNODE_REVOKE,
2616 	    (macop_t)mac_mls_check_vnode_revoke },
2617 	{ MAC_CHECK_VNODE_SETACL,
2618 	    (macop_t)mac_mls_check_vnode_setacl },
2619 	{ MAC_CHECK_VNODE_SETEXTATTR,
2620 	    (macop_t)mac_mls_check_vnode_setextattr },
2621 	{ MAC_CHECK_VNODE_SETFLAGS,
2622 	    (macop_t)mac_mls_check_vnode_setflags },
2623 	{ MAC_CHECK_VNODE_SETMODE,
2624 	    (macop_t)mac_mls_check_vnode_setmode },
2625 	{ MAC_CHECK_VNODE_SETOWNER,
2626 	    (macop_t)mac_mls_check_vnode_setowner },
2627 	{ MAC_CHECK_VNODE_SETUTIMES,
2628 	    (macop_t)mac_mls_check_vnode_setutimes },
2629 	{ MAC_CHECK_VNODE_STAT,
2630 	    (macop_t)mac_mls_check_vnode_stat },
2631 	{ MAC_CHECK_VNODE_WRITE,
2632 	    (macop_t)mac_mls_check_vnode_write },
2633 	{ MAC_OP_LAST, NULL }
2634 };
2635 
2636 MAC_POLICY_SET(mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2637     MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);
2638