mac_mls.c revision 106217
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: head/sys/security/mac_mls/mac_mls.c 106217 2002-10-30 18:48:51Z rwatson $
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
82SYSCTL_DECL(_security_mac);
83
84SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
85    "TrustedBSD mac_mls policy controls");
86
87static int	mac_mls_label_size = sizeof(struct mac_mls);
88SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
89    &mac_mls_label_size, 0, "Size of struct mac_mls");
90
91static int	mac_mls_enabled = 0;
92SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW,
93    &mac_mls_enabled, 0, "Enforce MAC/MLS policy");
94TUNABLE_INT("security.mac.mls.enabled", &mac_mls_enabled);
95
96static int	destroyed_not_inited;
97SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99
100static int	ptys_equal = 0;
101SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
102    &ptys_equal, 0, "Label pty devices as mls/equal on create");
103TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
104
105static int	revocation_enabled = 0;
106SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
107    &revocation_enabled, 0, "Revoke access to objects on relabel");
108TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
109
110static int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
111SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
112    &max_compartments, 0, "Maximum compartments the policy supports");
113
114static int	mac_mls_slot;
115#define	SLOT(l)	((struct mac_mls *)LABEL_TO_SLOT((l), mac_mls_slot).l_ptr)
116
117MALLOC_DEFINE(M_MACMLS, "mls label", "MAC/MLS labels");
118
119static __inline int
120mls_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
129static struct mac_mls *
130mls_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
139static void
140mls_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
149static int
150mls_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
158static int
159mac_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
211static int
212mac_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
221static int
222mac_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
238static int
239mac_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
249static int
250mac_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
260static int
261mac_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
272static int
273mac_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
290static int
291mac_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
315static int
316mac_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
387static void
388mac_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
408static void
409mac_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
421static void
422mac_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
433static void
434mac_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
444static void
445mac_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 */
457static void
458mac_mls_destroy(struct mac_policy_conf *conf)
459{
460
461}
462
463static void
464mac_mls_init(struct mac_policy_conf *conf)
465{
466
467}
468
469/*
470 * Label operations.
471 */
472static void
473mac_mls_init_label(struct label *label)
474{
475
476	SLOT(label) = mls_alloc(M_WAITOK);
477}
478
479static int
480mac_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
490static void
491mac_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 */
503static size_t
504mac_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
536static size_t
537mac_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
594static int
595mac_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
616static int
617mac_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 */
675static int
676mac_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
738static int
739mac_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
760static void
761mac_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 */
771static void
772mac_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
796static void
797mac_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
806static void
807mac_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
818static void
819mac_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
829static void
830mac_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
842static void
843mac_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
855static void
856mac_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
867static void
868mac_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
879static void
880mac_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
892static int
893mac_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
933static void
934mac_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
945static int
946mac_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
968static int
969mac_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 */
993static void
994mac_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
1005static void
1006mac_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
1017static void
1018mac_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
1029static void
1030mac_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
1042static void
1043mac_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
1054static void
1055mac_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
1066static void
1067mac_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 */
1081static void
1082mac_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
1094static void
1095mac_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
1106static void
1107mac_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
1123static void
1124mac_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
1135static void
1136mac_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
1148static void
1149mac_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
1160static void
1161mac_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
1181static void
1182mac_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
1192static void
1193mac_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
1204static void
1205mac_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
1216static void
1217mac_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
1229static void
1230mac_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
1241static int
1242mac_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
1253static void
1254mac_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
1265static void
1266mac_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 */
1276static void
1277mac_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
1288static void
1289mac_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
1301static int
1302mac_mls_execve_will_transition(struct ucred *old, struct vnode *vp,
1303    struct label *vnodelabel)
1304{
1305
1306	return (0);
1307}
1308
1309static void
1310mac_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
1321static void
1322mac_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
1333static void
1334mac_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 */
1347static int
1348mac_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
1364static int
1365mac_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
1421static int
1422mac_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
1439static int
1440mac_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
1479static int
1480mac_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
1494static int
1495mac_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
1512static int
1513mac_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
1525static int
1526mac_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
1543static int
1544mac_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
1561static int
1562mac_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
1612static int
1613mac_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
1630static int
1631mac_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
1648static int
1649mac_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
1668static int
1669mac_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
1688static int
1689mac_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
1708static int
1709mac_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
1723static int
1724mac_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
1774static int
1775mac_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
1792static int
1793mac_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
1810static int
1811mac_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
1828static int
1829mac_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
1846static int
1847mac_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
1870static int
1871mac_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
1888static int
1889mac_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
1906static int
1907mac_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
1924static int
1925mac_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
1942static int
1943mac_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
1965static int
1966mac_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
1983static int
1984mac_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
2011static int
2012mac_mls_check_vnode_open(struct ucred *cred, struct vnode *vp,
2013    struct label *vnodelabel, int 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
2036static int
2037mac_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
2054static int
2055mac_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
2072static int
2073mac_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
2090static int
2091mac_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
2108static int
2109mac_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
2160static int
2161mac_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
2184static int
2185mac_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
2210static int
2211mac_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
2228static int
2229mac_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
2246static int
2247mac_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
2267static int
2268mac_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
2285static int
2286mac_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
2303static int
2304mac_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
2321static int
2322mac_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
2339static int
2340mac_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
2357static int
2358mac_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
2375static struct mac_policy_ops mac_mls_ops =
2376{
2377	.mpo_destroy = mac_mls_destroy,
2378	.mpo_init = mac_mls_init,
2379	.mpo_init_bpfdesc_label = mac_mls_init_label,
2380	.mpo_init_cred_label = mac_mls_init_label,
2381	.mpo_init_devfsdirent_label = mac_mls_init_label,
2382	.mpo_init_ifnet_label = mac_mls_init_label,
2383	.mpo_init_ipq_label = mac_mls_init_label,
2384	.mpo_init_mbuf_label = mac_mls_init_label_waitcheck,
2385	.mpo_init_mount_label = mac_mls_init_label,
2386	.mpo_init_mount_fs_label = mac_mls_init_label,
2387	.mpo_init_pipe_label = mac_mls_init_label,
2388	.mpo_init_socket_label = mac_mls_init_label_waitcheck,
2389	.mpo_init_socket_peer_label = mac_mls_init_label_waitcheck,
2390	.mpo_init_vnode_label = mac_mls_init_label,
2391	.mpo_destroy_bpfdesc_label = mac_mls_destroy_label,
2392	.mpo_destroy_cred_label = mac_mls_destroy_label,
2393	.mpo_destroy_devfsdirent_label = mac_mls_destroy_label,
2394	.mpo_destroy_ifnet_label = mac_mls_destroy_label,
2395	.mpo_destroy_ipq_label = mac_mls_destroy_label,
2396	.mpo_destroy_mbuf_label = mac_mls_destroy_label,
2397	.mpo_destroy_mount_label = mac_mls_destroy_label,
2398	.mpo_destroy_mount_fs_label = mac_mls_destroy_label,
2399	.mpo_destroy_pipe_label = mac_mls_destroy_label,
2400	.mpo_destroy_socket_label = mac_mls_destroy_label,
2401	.mpo_destroy_socket_peer_label = mac_mls_destroy_label,
2402	.mpo_destroy_vnode_label = mac_mls_destroy_label,
2403	.mpo_copy_pipe_label = mac_mls_copy_label,
2404	.mpo_copy_vnode_label = mac_mls_copy_label,
2405	.mpo_externalize_cred_label = mac_mls_externalize_label,
2406	.mpo_externalize_ifnet_label = mac_mls_externalize_label,
2407	.mpo_externalize_pipe_label = mac_mls_externalize_label,
2408	.mpo_externalize_socket_label = mac_mls_externalize_label,
2409	.mpo_externalize_socket_peer_label = mac_mls_externalize_label,
2410	.mpo_externalize_vnode_label = mac_mls_externalize_label,
2411	.mpo_internalize_cred_label = mac_mls_internalize_label,
2412	.mpo_internalize_ifnet_label = mac_mls_internalize_label,
2413	.mpo_internalize_pipe_label = mac_mls_internalize_label,
2414	.mpo_internalize_socket_label = mac_mls_internalize_label,
2415	.mpo_internalize_vnode_label = mac_mls_internalize_label,
2416	.mpo_create_devfs_device = mac_mls_create_devfs_device,
2417	.mpo_create_devfs_directory = mac_mls_create_devfs_directory,
2418	.mpo_create_devfs_symlink = mac_mls_create_devfs_symlink,
2419	.mpo_create_devfs_vnode = mac_mls_create_devfs_vnode,
2420	.mpo_create_mount = mac_mls_create_mount,
2421	.mpo_create_root_mount = mac_mls_create_root_mount,
2422	.mpo_relabel_vnode = mac_mls_relabel_vnode,
2423	.mpo_update_devfsdirent = mac_mls_update_devfsdirent,
2424	.mpo_associate_vnode_devfs = mac_mls_associate_vnode_devfs,
2425	.mpo_associate_vnode_extattr = mac_mls_associate_vnode_extattr,
2426	.mpo_associate_vnode_singlelabel = mac_mls_associate_vnode_singlelabel,
2427	.mpo_create_vnode_extattr = mac_mls_create_vnode_extattr,
2428	.mpo_setlabel_vnode_extattr = mac_mls_setlabel_vnode_extattr,
2429	.mpo_create_mbuf_from_socket = mac_mls_create_mbuf_from_socket,
2430	.mpo_create_pipe = mac_mls_create_pipe,
2431	.mpo_create_socket = mac_mls_create_socket,
2432	.mpo_create_socket_from_socket = mac_mls_create_socket_from_socket,
2433	.mpo_relabel_pipe = mac_mls_relabel_pipe,
2434	.mpo_relabel_socket = mac_mls_relabel_socket,
2435	.mpo_set_socket_peer_from_mbuf = mac_mls_set_socket_peer_from_mbuf,
2436	.mpo_set_socket_peer_from_socket = mac_mls_set_socket_peer_from_socket,
2437	.mpo_create_bpfdesc = mac_mls_create_bpfdesc,
2438	.mpo_create_datagram_from_ipq = mac_mls_create_datagram_from_ipq,
2439	.mpo_create_fragment = mac_mls_create_fragment,
2440	.mpo_create_ifnet = mac_mls_create_ifnet,
2441	.mpo_create_ipq = mac_mls_create_ipq,
2442	.mpo_create_mbuf_from_mbuf = mac_mls_create_mbuf_from_mbuf,
2443	.mpo_create_mbuf_linklayer = mac_mls_create_mbuf_linklayer,
2444	.mpo_create_mbuf_from_bpfdesc = mac_mls_create_mbuf_from_bpfdesc,
2445	.mpo_create_mbuf_from_ifnet = mac_mls_create_mbuf_from_ifnet,
2446	.mpo_create_mbuf_multicast_encap = mac_mls_create_mbuf_multicast_encap,
2447	.mpo_create_mbuf_netlayer = mac_mls_create_mbuf_netlayer,
2448	.mpo_fragment_match = mac_mls_fragment_match,
2449	.mpo_relabel_ifnet = mac_mls_relabel_ifnet,
2450	.mpo_update_ipq = mac_mls_update_ipq,
2451	.mpo_create_cred = mac_mls_create_cred,
2452	.mpo_execve_transition = mac_mls_execve_transition,
2453	.mpo_execve_will_transition = mac_mls_execve_will_transition,
2454	.mpo_create_proc0 = mac_mls_create_proc0,
2455	.mpo_create_proc1 = mac_mls_create_proc1,
2456	.mpo_relabel_cred = mac_mls_relabel_cred,
2457	.mpo_check_bpfdesc_receive = mac_mls_check_bpfdesc_receive,
2458	.mpo_check_cred_relabel = mac_mls_check_cred_relabel,
2459	.mpo_check_cred_visible = mac_mls_check_cred_visible,
2460	.mpo_check_ifnet_relabel = mac_mls_check_ifnet_relabel,
2461	.mpo_check_ifnet_transmit = mac_mls_check_ifnet_transmit,
2462	.mpo_check_mount_stat = mac_mls_check_mount_stat,
2463	.mpo_check_pipe_ioctl = mac_mls_check_pipe_ioctl,
2464	.mpo_check_pipe_poll = mac_mls_check_pipe_poll,
2465	.mpo_check_pipe_read = mac_mls_check_pipe_read,
2466	.mpo_check_pipe_relabel = mac_mls_check_pipe_relabel,
2467	.mpo_check_pipe_stat = mac_mls_check_pipe_stat,
2468	.mpo_check_pipe_write = mac_mls_check_pipe_write,
2469	.mpo_check_proc_debug = mac_mls_check_proc_debug,
2470	.mpo_check_proc_sched = mac_mls_check_proc_sched,
2471	.mpo_check_proc_signal = mac_mls_check_proc_signal,
2472	.mpo_check_socket_deliver = mac_mls_check_socket_deliver,
2473	.mpo_check_socket_relabel = mac_mls_check_socket_relabel,
2474	.mpo_check_socket_visible = mac_mls_check_socket_visible,
2475	.mpo_check_vnode_access = mac_mls_check_vnode_open,
2476	.mpo_check_vnode_chdir = mac_mls_check_vnode_chdir,
2477	.mpo_check_vnode_chroot = mac_mls_check_vnode_chroot,
2478	.mpo_check_vnode_create = mac_mls_check_vnode_create,
2479	.mpo_check_vnode_delete = mac_mls_check_vnode_delete,
2480	.mpo_check_vnode_deleteacl = mac_mls_check_vnode_deleteacl,
2481	.mpo_check_vnode_exec = mac_mls_check_vnode_exec,
2482	.mpo_check_vnode_getacl = mac_mls_check_vnode_getacl,
2483	.mpo_check_vnode_getextattr = mac_mls_check_vnode_getextattr,
2484	.mpo_check_vnode_link = mac_mls_check_vnode_link,
2485	.mpo_check_vnode_lookup = mac_mls_check_vnode_lookup,
2486	.mpo_check_vnode_mmap = mac_mls_check_vnode_mmap,
2487	.mpo_check_vnode_mprotect = mac_mls_check_vnode_mmap,
2488	.mpo_check_vnode_open = mac_mls_check_vnode_open,
2489	.mpo_check_vnode_poll = mac_mls_check_vnode_poll,
2490	.mpo_check_vnode_read = mac_mls_check_vnode_read,
2491	.mpo_check_vnode_readdir = mac_mls_check_vnode_readdir,
2492	.mpo_check_vnode_readlink = mac_mls_check_vnode_readlink,
2493	.mpo_check_vnode_relabel = mac_mls_check_vnode_relabel,
2494	.mpo_check_vnode_rename_from = mac_mls_check_vnode_rename_from,
2495	.mpo_check_vnode_rename_to = mac_mls_check_vnode_rename_to,
2496	.mpo_check_vnode_revoke = mac_mls_check_vnode_revoke,
2497	.mpo_check_vnode_setacl = mac_mls_check_vnode_setacl,
2498	.mpo_check_vnode_setextattr = mac_mls_check_vnode_setextattr,
2499	.mpo_check_vnode_setflags = mac_mls_check_vnode_setflags,
2500	.mpo_check_vnode_setmode = mac_mls_check_vnode_setmode,
2501	.mpo_check_vnode_setowner = mac_mls_check_vnode_setowner,
2502	.mpo_check_vnode_setutimes = mac_mls_check_vnode_setutimes,
2503	.mpo_check_vnode_stat = mac_mls_check_vnode_stat,
2504	.mpo_check_vnode_write = mac_mls_check_vnode_write,
2505};
2506
2507MAC_POLICY_SET(&mac_mls_ops, trustedbsd_mac_mls, "TrustedBSD MAC/MLS",
2508    MPC_LOADTIME_FLAG_NOTLATE, &mac_mls_slot);
2509