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