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