mac_mls.c revision 184407
1/*-
2 * Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson
3 * Copyright (c) 2001-2005 McAfee, Inc.
4 * Copyright (c) 2006 SPARTA, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 *
9 * This software was developed for the FreeBSD Project in part by McAfee
10 * Research, the Security Research Division of McAfee, Inc. under
11 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12 * CHATS research program.
13 *
14 * This software was enhanced by SPARTA ISSO under SPAWAR contract
15 * N66001-04-C-6019 ("SEFOS").
16 *
17 * Redistribution and use in source and binary forms, with or without
18 * modification, are permitted provided that the following conditions
19 * are met:
20 * 1. Redistributions of source code must retain the above copyright
21 *    notice, this list of conditions and the following disclaimer.
22 * 2. Redistributions in binary form must reproduce the above copyright
23 *    notice, this list of conditions and the following disclaimer in the
24 *    documentation and/or other materials provided with the distribution.
25 *
26 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36 * SUCH DAMAGE.
37 *
38 * $FreeBSD: head/sys/security/mac_mls/mac_mls.c 184407 2008-10-28 11:33:06Z rwatson $
39 */
40
41/*
42 * Developed by the TrustedBSD Project.
43 *
44 * MLS fixed label mandatory confidentiality policy.
45 */
46
47#include <sys/types.h>
48#include <sys/param.h>
49#include <sys/acl.h>
50#include <sys/conf.h>
51#include <sys/extattr.h>
52#include <sys/kernel.h>
53#include <sys/ksem.h>
54#include <sys/mman.h>
55#include <sys/malloc.h>
56#include <sys/mount.h>
57#include <sys/proc.h>
58#include <sys/sbuf.h>
59#include <sys/systm.h>
60#include <sys/sysproto.h>
61#include <sys/sysent.h>
62#include <sys/systm.h>
63#include <sys/vnode.h>
64#include <sys/file.h>
65#include <sys/socket.h>
66#include <sys/socketvar.h>
67#include <sys/pipe.h>
68#include <sys/sx.h>
69#include <sys/sysctl.h>
70#include <sys/msg.h>
71#include <sys/sem.h>
72#include <sys/shm.h>
73
74#include <fs/devfs/devfs.h>
75
76#include <net/bpfdesc.h>
77#include <net/if.h>
78#include <net/if_types.h>
79#include <net/if_var.h>
80
81#include <netinet/in.h>
82#include <netinet/in_pcb.h>
83#include <netinet/ip_var.h>
84
85#include <vm/uma.h>
86#include <vm/vm.h>
87
88#include <security/mac/mac_policy.h>
89#include <security/mac_mls/mac_mls.h>
90
91SYSCTL_DECL(_security_mac);
92
93SYSCTL_NODE(_security_mac, OID_AUTO, mls, CTLFLAG_RW, 0,
94    "TrustedBSD mac_mls policy controls");
95
96static int	mls_label_size = sizeof(struct mac_mls);
97SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
98    &mls_label_size, 0, "Size of struct mac_mls");
99
100static int	mls_enabled = 1;
101SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RW, &mls_enabled, 0,
102    "Enforce MAC/MLS policy");
103TUNABLE_INT("security.mac.mls.enabled", &mls_enabled);
104
105static int	destroyed_not_inited;
106SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
107    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
108
109static int	ptys_equal = 0;
110SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RW,
111    &ptys_equal, 0, "Label pty devices as mls/equal on create");
112TUNABLE_INT("security.mac.mls.ptys_equal", &ptys_equal);
113
114static int	revocation_enabled = 0;
115SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RW,
116    &revocation_enabled, 0, "Revoke access to objects on relabel");
117TUNABLE_INT("security.mac.mls.revocation_enabled", &revocation_enabled);
118
119static int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
120SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
121    &max_compartments, 0, "Maximum compartments the policy supports");
122
123static int	mls_slot;
124#define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mls_slot))
125#define	SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
126
127static uma_zone_t	zone_mls;
128
129static __inline int
130mls_bit_set_empty(u_char *set) {
131	int i;
132
133	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
134		if (set[i] != 0)
135			return (0);
136	return (1);
137}
138
139static struct mac_mls *
140mls_alloc(int flag)
141{
142
143	return (uma_zalloc(zone_mls, flag | M_ZERO));
144}
145
146static void
147mls_free(struct mac_mls *mm)
148{
149
150	if (mm != NULL)
151		uma_zfree(zone_mls, mm);
152	else
153		atomic_add_int(&destroyed_not_inited, 1);
154}
155
156static int
157mls_atmostflags(struct mac_mls *mm, int flags)
158{
159
160	if ((mm->mm_flags & flags) != mm->mm_flags)
161		return (EINVAL);
162	return (0);
163}
164
165static int
166mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
167{
168	int bit;
169
170	switch (a->mme_type) {
171	case MAC_MLS_TYPE_EQUAL:
172	case MAC_MLS_TYPE_HIGH:
173		return (1);
174
175	case MAC_MLS_TYPE_LOW:
176		switch (b->mme_type) {
177		case MAC_MLS_TYPE_LEVEL:
178		case MAC_MLS_TYPE_HIGH:
179			return (0);
180
181		case MAC_MLS_TYPE_EQUAL:
182		case MAC_MLS_TYPE_LOW:
183			return (1);
184
185		default:
186			panic("mls_dominate_element: b->mme_type invalid");
187		}
188
189	case MAC_MLS_TYPE_LEVEL:
190		switch (b->mme_type) {
191		case MAC_MLS_TYPE_EQUAL:
192		case MAC_MLS_TYPE_LOW:
193			return (1);
194
195		case MAC_MLS_TYPE_HIGH:
196			return (0);
197
198		case MAC_MLS_TYPE_LEVEL:
199			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
200				if (!MAC_MLS_BIT_TEST(bit,
201				    a->mme_compartments) &&
202				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
203					return (0);
204			return (a->mme_level >= b->mme_level);
205
206		default:
207			panic("mls_dominate_element: b->mme_type invalid");
208		}
209
210	default:
211		panic("mls_dominate_element: a->mme_type invalid");
212	}
213
214	return (0);
215}
216
217static int
218mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
219{
220
221	return (mls_dominate_element(&rangeb->mm_rangehigh,
222	    &rangea->mm_rangehigh) &&
223	    mls_dominate_element(&rangea->mm_rangelow,
224	    &rangeb->mm_rangelow));
225}
226
227static int
228mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
229{
230
231	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
232	    ("mls_effective_in_range: a not effective"));
233	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
234	    ("mls_effective_in_range: b not range"));
235
236	return (mls_dominate_element(&range->mm_rangehigh,
237	    &effective->mm_effective) &&
238	    mls_dominate_element(&effective->mm_effective,
239	    &range->mm_rangelow));
240
241	return (1);
242}
243
244static int
245mls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
246{
247	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
248	    ("mls_dominate_effective: a not effective"));
249	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
250	    ("mls_dominate_effective: b not effective"));
251
252	return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
253}
254
255static int
256mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
257{
258
259	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
260	    b->mme_type == MAC_MLS_TYPE_EQUAL)
261		return (1);
262
263	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
264}
265
266static int
267mls_equal_effective(struct mac_mls *a, struct mac_mls *b)
268{
269
270	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
271	    ("mls_equal_effective: a not effective"));
272	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
273	    ("mls_equal_effective: b not effective"));
274
275	return (mls_equal_element(&a->mm_effective, &b->mm_effective));
276}
277
278static int
279mls_contains_equal(struct mac_mls *mm)
280{
281
282	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
283		if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
284			return (1);
285
286	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
287		if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
288			return (1);
289		if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
290			return (1);
291	}
292
293	return (0);
294}
295
296static int
297mls_subject_privileged(struct mac_mls *mm)
298{
299
300	KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
301	    ("mls_subject_privileged: subject doesn't have both labels"));
302
303	/* If the effective is EQUAL, it's ok. */
304	if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
305		return (0);
306
307	/* If either range endpoint is EQUAL, it's ok. */
308	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
309	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
310		return (0);
311
312	/* If the range is low-high, it's ok. */
313	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
314	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
315		return (0);
316
317	/* It's not ok. */
318	return (EPERM);
319}
320
321static int
322mls_valid(struct mac_mls *mm)
323{
324
325	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
326		switch (mm->mm_effective.mme_type) {
327		case MAC_MLS_TYPE_LEVEL:
328			break;
329
330		case MAC_MLS_TYPE_EQUAL:
331		case MAC_MLS_TYPE_HIGH:
332		case MAC_MLS_TYPE_LOW:
333			if (mm->mm_effective.mme_level != 0 ||
334			    !MAC_MLS_BIT_SET_EMPTY(
335			    mm->mm_effective.mme_compartments))
336				return (EINVAL);
337			break;
338
339		default:
340			return (EINVAL);
341		}
342	} else {
343		if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
344			return (EINVAL);
345	}
346
347	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
348		switch (mm->mm_rangelow.mme_type) {
349		case MAC_MLS_TYPE_LEVEL:
350			break;
351
352		case MAC_MLS_TYPE_EQUAL:
353		case MAC_MLS_TYPE_HIGH:
354		case MAC_MLS_TYPE_LOW:
355			if (mm->mm_rangelow.mme_level != 0 ||
356			    !MAC_MLS_BIT_SET_EMPTY(
357			    mm->mm_rangelow.mme_compartments))
358				return (EINVAL);
359			break;
360
361		default:
362			return (EINVAL);
363		}
364
365		switch (mm->mm_rangehigh.mme_type) {
366		case MAC_MLS_TYPE_LEVEL:
367			break;
368
369		case MAC_MLS_TYPE_EQUAL:
370		case MAC_MLS_TYPE_HIGH:
371		case MAC_MLS_TYPE_LOW:
372			if (mm->mm_rangehigh.mme_level != 0 ||
373			    !MAC_MLS_BIT_SET_EMPTY(
374			    mm->mm_rangehigh.mme_compartments))
375				return (EINVAL);
376			break;
377
378		default:
379			return (EINVAL);
380		}
381		if (!mls_dominate_element(&mm->mm_rangehigh,
382		    &mm->mm_rangelow))
383			return (EINVAL);
384	} else {
385		if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
386		    mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
387			return (EINVAL);
388	}
389
390	return (0);
391}
392
393static void
394mls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
395    u_char *compartmentslow, u_short typehigh, u_short levelhigh,
396    u_char *compartmentshigh)
397{
398
399	mm->mm_rangelow.mme_type = typelow;
400	mm->mm_rangelow.mme_level = levellow;
401	if (compartmentslow != NULL)
402		memcpy(mm->mm_rangelow.mme_compartments, compartmentslow,
403		    sizeof(mm->mm_rangelow.mme_compartments));
404	mm->mm_rangehigh.mme_type = typehigh;
405	mm->mm_rangehigh.mme_level = levelhigh;
406	if (compartmentshigh != NULL)
407		memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh,
408		    sizeof(mm->mm_rangehigh.mme_compartments));
409	mm->mm_flags |= MAC_MLS_FLAG_RANGE;
410}
411
412static void
413mls_set_effective(struct mac_mls *mm, u_short type, u_short level,
414    u_char *compartments)
415{
416
417	mm->mm_effective.mme_type = type;
418	mm->mm_effective.mme_level = level;
419	if (compartments != NULL)
420		memcpy(mm->mm_effective.mme_compartments, compartments,
421		    sizeof(mm->mm_effective.mme_compartments));
422	mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
423}
424
425static void
426mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
427{
428
429	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
430	    ("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
438mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
439{
440
441	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
442	    ("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
449mls_copy(struct mac_mls *source, struct mac_mls *dest)
450{
451
452	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
453		mls_copy_effective(source, dest);
454	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
455		mls_copy_range(source, dest);
456}
457
458/*
459 * Policy module operations.
460 */
461static void
462mls_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
473mls_init_label(struct label *label)
474{
475
476	SLOT_SET(label, mls_alloc(M_WAITOK));
477}
478
479static int
480mls_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
491mls_destroy_label(struct label *label)
492{
493
494	mls_free(SLOT(label));
495	SLOT_SET(label, NULL);
496}
497
498/*
499 * mls_element_to_string() accepts an sbuf and MLS element.  It converts the
500 * MLS element to a string and stores the result in the sbuf; if there isn't
501 * space in the sbuf, -1 is returned.
502 */
503static int
504mls_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("mls_element_to_string: invalid type (%d)",
541		    element->mme_type);
542	}
543}
544
545/*
546 * mls_to_string() converts an MLS label to a string, and places the results
547 * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
548 * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
549 * so the caller may need to revert the sbuf by restoring the offset if
550 * that's undesired.
551 */
552static int
553mls_to_string(struct sbuf *sb, struct mac_mls *mm)
554{
555
556	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
557		if (mls_element_to_string(sb, &mm->mm_effective) == -1)
558			return (EINVAL);
559	}
560
561	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
562		if (sbuf_putc(sb, '(') == -1)
563			return (EINVAL);
564
565		if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
566			return (EINVAL);
567
568		if (sbuf_putc(sb, '-') == -1)
569			return (EINVAL);
570
571		if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
572			return (EINVAL);
573
574		if (sbuf_putc(sb, ')') == -1)
575			return (EINVAL);
576	}
577
578	return (0);
579}
580
581static int
582mls_externalize_label(struct label *label, char *element_name,
583    struct sbuf *sb, int *claimed)
584{
585	struct mac_mls *mm;
586
587	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
588		return (0);
589
590	(*claimed)++;
591
592	mm = SLOT(label);
593
594	return (mls_to_string(sb, mm));
595}
596
597static int
598mls_parse_element(struct mac_mls_element *element, char *string)
599{
600	char *compartment, *end, *level;
601	int value;
602
603	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
604		element->mme_type = MAC_MLS_TYPE_HIGH;
605		element->mme_level = MAC_MLS_TYPE_UNDEF;
606	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
607		element->mme_type = MAC_MLS_TYPE_LOW;
608		element->mme_level = MAC_MLS_TYPE_UNDEF;
609	} else if (strcmp(string, "equal") == 0 ||
610	    strcmp(string, "eq") == 0) {
611		element->mme_type = MAC_MLS_TYPE_EQUAL;
612		element->mme_level = MAC_MLS_TYPE_UNDEF;
613	} else {
614		element->mme_type = MAC_MLS_TYPE_LEVEL;
615
616		/*
617		 * Numeric level piece of the element.
618		 */
619		level = strsep(&string, ":");
620		value = strtol(level, &end, 10);
621		if (end == level || *end != '\0')
622			return (EINVAL);
623		if (value < 0 || value > 65535)
624			return (EINVAL);
625		element->mme_level = value;
626
627		/*
628		 * Optional compartment piece of the element.  If none are
629		 * included, we assume that the label has no compartments.
630		 */
631		if (string == NULL)
632			return (0);
633		if (*string == '\0')
634			return (0);
635
636		while ((compartment = strsep(&string, "+")) != NULL) {
637			value = strtol(compartment, &end, 10);
638			if (compartment == end || *end != '\0')
639				return (EINVAL);
640			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
641				return (EINVAL);
642			MAC_MLS_BIT_SET(value, element->mme_compartments);
643		}
644	}
645
646	return (0);
647}
648
649/*
650 * Note: destructively consumes the string, make a local copy before calling
651 * if that's a problem.
652 */
653static int
654mls_parse(struct mac_mls *mm, char *string)
655{
656	char *rangehigh, *rangelow, *effective;
657	int error;
658
659	effective = strsep(&string, "(");
660	if (*effective == '\0')
661		effective = NULL;
662
663	if (string != NULL) {
664		rangelow = strsep(&string, "-");
665		if (string == NULL)
666			return (EINVAL);
667		rangehigh = strsep(&string, ")");
668		if (string == NULL)
669			return (EINVAL);
670		if (*string != '\0')
671			return (EINVAL);
672	} else {
673		rangelow = NULL;
674		rangehigh = NULL;
675	}
676
677	KASSERT((rangelow != NULL && rangehigh != NULL) ||
678	    (rangelow == NULL && rangehigh == NULL),
679	    ("mls_parse: range mismatch"));
680
681	bzero(mm, sizeof(*mm));
682	if (effective != NULL) {
683		error = mls_parse_element(&mm->mm_effective, effective);
684		if (error)
685			return (error);
686		mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
687	}
688
689	if (rangelow != NULL) {
690		error = mls_parse_element(&mm->mm_rangelow, rangelow);
691		if (error)
692			return (error);
693		error = mls_parse_element(&mm->mm_rangehigh, rangehigh);
694		if (error)
695			return (error);
696		mm->mm_flags |= MAC_MLS_FLAG_RANGE;
697	}
698
699	error = mls_valid(mm);
700	if (error)
701		return (error);
702
703	return (0);
704}
705
706static int
707mls_internalize_label(struct label *label, char *element_name,
708    char *element_data, int *claimed)
709{
710	struct mac_mls *mm, mm_temp;
711	int error;
712
713	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
714		return (0);
715
716	(*claimed)++;
717
718	error = mls_parse(&mm_temp, element_data);
719	if (error)
720		return (error);
721
722	mm = SLOT(label);
723	*mm = mm_temp;
724
725	return (0);
726}
727
728static void
729mls_copy_label(struct label *src, struct label *dest)
730{
731
732	*SLOT(dest) = *SLOT(src);
733}
734
735/*
736 * Object-specific entry point implementations are sorted alphabetically by
737 * object type name and then by operation.
738 */
739static int
740mls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
741     struct ifnet *ifp, struct label *ifplabel)
742{
743	struct mac_mls *a, *b;
744
745	if (!mls_enabled)
746		return (0);
747
748	a = SLOT(dlabel);
749	b = SLOT(ifplabel);
750
751	if (mls_equal_effective(a, b))
752		return (0);
753	return (EACCES);
754}
755
756static void
757mls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
758{
759	struct mac_mls *source, *dest;
760
761	source = SLOT(cred->cr_label);
762	dest = SLOT(dlabel);
763
764	mls_copy_effective(source, dest);
765}
766
767static void
768mls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
769    struct mbuf *m, struct label *mlabel)
770{
771	struct mac_mls *source, *dest;
772
773	source = SLOT(dlabel);
774	dest = SLOT(mlabel);
775
776	mls_copy_effective(source, dest);
777}
778
779static void
780mls_cred_associate_nfsd(struct ucred *cred)
781{
782	struct mac_mls *label;
783
784	label = SLOT(cred->cr_label);
785	mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
786	mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
787	    NULL);
788}
789
790static int
791mls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
792{
793	struct mac_mls *subj, *new;
794	int error;
795
796	subj = SLOT(cred->cr_label);
797	new = SLOT(newlabel);
798
799	/*
800	 * If there is an MLS label update for the credential, it may be an
801	 * update of effective, range, or both.
802	 */
803	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
804	if (error)
805		return (error);
806
807	/*
808	 * If the MLS label is to be changed, authorize as appropriate.
809	 */
810	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
811		/*
812		 * If the change request modifies both the MLS label
813		 * effective and range, check that the new effective will be
814		 * in the new range.
815		 */
816		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
817		    MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
818			return (EINVAL);
819
820		/*
821		 * To change the MLS effective label on a credential, the new
822		 * effective label must be in the current range.
823		 */
824		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
825		    !mls_effective_in_range(new, subj))
826			return (EPERM);
827
828		/*
829		 * To change the MLS range label on a credential, the new
830		 * range must be in the current range.
831		 */
832		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
833		    !mls_range_in_range(new, subj))
834			return (EPERM);
835
836		/*
837		 * To have EQUAL in any component of the new credential MLS
838		 * label, the subject must already have EQUAL in their label.
839		 */
840		if (mls_contains_equal(new)) {
841			error = mls_subject_privileged(subj);
842			if (error)
843				return (error);
844		}
845	}
846
847	return (0);
848}
849
850static int
851mls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
852{
853	struct mac_mls *subj, *obj;
854
855	if (!mls_enabled)
856		return (0);
857
858	subj = SLOT(cr1->cr_label);
859	obj = SLOT(cr2->cr_label);
860
861	/* XXX: range */
862	if (!mls_dominate_effective(subj, obj))
863		return (ESRCH);
864
865	return (0);
866}
867
868static void
869mls_cred_create_init(struct ucred *cred)
870{
871	struct mac_mls *dest;
872
873	dest = SLOT(cred->cr_label);
874
875	mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
876	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
877	    NULL);
878}
879
880static void
881mls_cred_create_swapper(struct ucred *cred)
882{
883	struct mac_mls *dest;
884
885	dest = SLOT(cred->cr_label);
886
887	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
888	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
889	    NULL);
890}
891
892static void
893mls_cred_relabel(struct ucred *cred, struct label *newlabel)
894{
895	struct mac_mls *source, *dest;
896
897	source = SLOT(newlabel);
898	dest = SLOT(cred->cr_label);
899
900	mls_copy(source, dest);
901}
902
903static void
904mls_devfs_create_device(struct ucred *cred, struct mount *mp,
905    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
906{
907	struct mac_mls *mm;
908	int mls_type;
909
910	mm = SLOT(delabel);
911	if (strcmp(dev->si_name, "null") == 0 ||
912	    strcmp(dev->si_name, "zero") == 0 ||
913	    strcmp(dev->si_name, "random") == 0 ||
914	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
915		mls_type = MAC_MLS_TYPE_EQUAL;
916	else if (strcmp(dev->si_name, "kmem") == 0 ||
917	    strcmp(dev->si_name, "mem") == 0)
918		mls_type = MAC_MLS_TYPE_HIGH;
919	else if (ptys_equal &&
920	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
921	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
922		mls_type = MAC_MLS_TYPE_EQUAL;
923	else
924		mls_type = MAC_MLS_TYPE_LOW;
925	mls_set_effective(mm, mls_type, 0, NULL);
926}
927
928static void
929mls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
930    struct devfs_dirent *de, struct label *delabel)
931{
932	struct mac_mls *mm;
933
934	mm = SLOT(delabel);
935	mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
936}
937
938static void
939mls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
940    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
941    struct label *delabel)
942{
943	struct mac_mls *source, *dest;
944
945	source = SLOT(cred->cr_label);
946	dest = SLOT(delabel);
947
948	mls_copy_effective(source, dest);
949}
950
951static void
952mls_devfs_update(struct mount *mp, struct devfs_dirent *de,
953    struct label *delabel, struct vnode *vp, struct label *vplabel)
954{
955	struct mac_mls *source, *dest;
956
957	source = SLOT(vplabel);
958	dest = SLOT(delabel);
959
960	mls_copy_effective(source, dest);
961}
962
963static void
964mls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
965    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
966    struct label *vplabel)
967{
968	struct mac_mls *source, *dest;
969
970	source = SLOT(delabel);
971	dest = SLOT(vplabel);
972
973	mls_copy_effective(source, dest);
974}
975
976static int
977mls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
978    struct label *ifplabel, struct label *newlabel)
979{
980	struct mac_mls *subj, *new;
981	int error;
982
983	subj = SLOT(cred->cr_label);
984	new = SLOT(newlabel);
985
986	/*
987	 * If there is an MLS label update for the interface, it may be an
988	 * update of effective, range, or both.
989	 */
990	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
991	if (error)
992		return (error);
993
994	/*
995	 * Relabeling network interfaces requires MLS privilege.
996	 */
997	return (mls_subject_privileged(subj));
998}
999
1000static int
1001mls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1002    struct mbuf *m, struct label *mlabel)
1003{
1004	struct mac_mls *p, *i;
1005
1006	if (!mls_enabled)
1007		return (0);
1008
1009	p = SLOT(mlabel);
1010	i = SLOT(ifplabel);
1011
1012	return (mls_effective_in_range(p, i) ? 0 : EACCES);
1013}
1014
1015static void
1016mls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1017{
1018	struct mac_mls *dest;
1019	int type;
1020
1021	dest = SLOT(ifplabel);
1022
1023	if (ifp->if_type == IFT_LOOP)
1024		type = MAC_MLS_TYPE_EQUAL;
1025	else
1026		type = MAC_MLS_TYPE_LOW;
1027
1028	mls_set_effective(dest, type, 0, NULL);
1029	mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1030}
1031
1032static void
1033mls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1034    struct mbuf *m, struct label *mlabel)
1035{
1036	struct mac_mls *source, *dest;
1037
1038	source = SLOT(ifplabel);
1039	dest = SLOT(mlabel);
1040
1041	mls_copy_effective(source, dest);
1042}
1043
1044static void
1045mls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1046    struct label *ifplabel, struct label *newlabel)
1047{
1048	struct mac_mls *source, *dest;
1049
1050	source = SLOT(newlabel);
1051	dest = SLOT(ifplabel);
1052
1053	mls_copy(source, dest);
1054}
1055
1056static int
1057mls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1058    struct mbuf *m, struct label *mlabel)
1059{
1060	struct mac_mls *p, *i;
1061
1062	if (!mls_enabled)
1063		return (0);
1064
1065	p = SLOT(mlabel);
1066	i = SLOT(inplabel);
1067
1068	return (mls_equal_effective(p, i) ? 0 : EACCES);
1069}
1070
1071static int
1072mls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1073    struct label *inplabel)
1074{
1075	struct mac_mls *subj, *obj;
1076
1077	if (!mls_enabled)
1078		return (0);
1079
1080	subj = SLOT(cred->cr_label);
1081	obj = SLOT(inplabel);
1082
1083	if (!mls_dominate_effective(subj, obj))
1084		return (ENOENT);
1085
1086	return (0);
1087}
1088
1089static void
1090mls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1091    struct label *inplabel)
1092{
1093	struct mac_mls *source, *dest;
1094
1095	source = SLOT(solabel);
1096	dest = SLOT(inplabel);
1097
1098	mls_copy_effective(source, dest);
1099}
1100
1101static void
1102mls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1103    struct mbuf *m, struct label *mlabel)
1104{
1105	struct mac_mls *source, *dest;
1106
1107	source = SLOT(inplabel);
1108	dest = SLOT(mlabel);
1109
1110	mls_copy_effective(source, dest);
1111}
1112
1113static void
1114mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1115    struct inpcb *inp, struct label *inplabel)
1116{
1117	struct mac_mls *source, *dest;
1118
1119	source = SLOT(solabel);
1120	dest = SLOT(inplabel);
1121
1122	mls_copy(source, dest);
1123}
1124
1125static void
1126mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1127    struct label *q6label)
1128{
1129	struct mac_mls *source, *dest;
1130
1131	source = SLOT(mlabel);
1132	dest = SLOT(q6label);
1133
1134	mls_copy_effective(source, dest);
1135}
1136
1137static int
1138mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1139    struct label *q6label)
1140{
1141	struct mac_mls *a, *b;
1142
1143	a = SLOT(q6label);
1144	b = SLOT(mlabel);
1145
1146	return (mls_equal_effective(a, b));
1147}
1148
1149static void
1150mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1151    struct label *mlabel)
1152{
1153	struct mac_mls *source, *dest;
1154
1155	source = SLOT(q6label);
1156	dest = SLOT(mlabel);
1157
1158	/* Just use the head, since we require them all to match. */
1159	mls_copy_effective(source, dest);
1160}
1161
1162static void
1163mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1164    struct label *q6label)
1165{
1166
1167	/* NOOP: we only accept matching labels, so no need to update */
1168}
1169
1170static void
1171mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1172    struct label *qlabel)
1173{
1174	struct mac_mls *source, *dest;
1175
1176	source = SLOT(mlabel);
1177	dest = SLOT(qlabel);
1178
1179	mls_copy_effective(source, dest);
1180}
1181
1182static int
1183mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1184    struct label *qlabel)
1185{
1186	struct mac_mls *a, *b;
1187
1188	a = SLOT(qlabel);
1189	b = SLOT(mlabel);
1190
1191	return (mls_equal_effective(a, b));
1192}
1193
1194static void
1195mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1196    struct label *mlabel)
1197{
1198	struct mac_mls *source, *dest;
1199
1200	source = SLOT(qlabel);
1201	dest = SLOT(mlabel);
1202
1203	/* Just use the head, since we require them all to match. */
1204	mls_copy_effective(source, dest);
1205}
1206
1207static void
1208mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1209    struct label *qlabel)
1210{
1211
1212	/* NOOP: we only accept matching labels, so no need to update */
1213}
1214
1215static int
1216mls_mount_check_stat(struct ucred *cred, struct mount *mp,
1217    struct label *mntlabel)
1218{
1219	struct mac_mls *subj, *obj;
1220
1221	if (!mls_enabled)
1222		return (0);
1223
1224	subj = SLOT(cred->cr_label);
1225	obj = SLOT(mntlabel);
1226
1227	if (!mls_dominate_effective(subj, obj))
1228		return (EACCES);
1229
1230	return (0);
1231}
1232
1233static void
1234mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1235{
1236	struct mac_mls *source, *dest;
1237
1238	source = SLOT(cred->cr_label);
1239	dest = SLOT(mplabel);
1240
1241	mls_copy_effective(source, dest);
1242}
1243
1244static void
1245mls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1246    struct mbuf *m, struct label *mlabel)
1247{
1248	struct mac_mls *dest;
1249
1250	dest = SLOT(mlabel);
1251
1252	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1253}
1254
1255static void
1256mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1257    struct mbuf *m, struct label *mlabel)
1258{
1259	struct mac_mls *dest;
1260
1261	dest = SLOT(mlabel);
1262
1263	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1264}
1265
1266static void
1267mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1268    struct mbuf *msend, struct label *msendlabel)
1269{
1270	struct mac_mls *source, *dest;
1271
1272	source = SLOT(mrecvlabel);
1273	dest = SLOT(msendlabel);
1274
1275	mls_copy_effective(source, dest);
1276}
1277
1278static void
1279mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1280{
1281	struct mac_mls *dest;
1282
1283	dest = SLOT(mlabel);
1284
1285	/* XXX: where is the label for the firewall really comming from? */
1286	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1287}
1288
1289static void
1290mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1291    struct label *fraglabel)
1292{
1293	struct mac_mls *source, *dest;
1294
1295	source = SLOT(mlabel);
1296	dest = SLOT(fraglabel);
1297
1298	mls_copy_effective(source, dest);
1299}
1300
1301static void
1302mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1303    struct mbuf *msend, struct label *msendlabel)
1304{
1305	struct mac_mls *source, *dest;
1306
1307	source = SLOT(mrecvlabel);
1308	dest = SLOT(msendlabel);
1309
1310	mls_copy_effective(source, dest);
1311}
1312
1313static void
1314mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1315    struct mbuf *m, struct label *mlabel)
1316{
1317	struct mac_mls *dest;
1318
1319	dest = SLOT(mlabel);
1320
1321	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1322}
1323
1324static void
1325mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1326    struct mbuf *m, struct label *mlabel)
1327{
1328	struct mac_mls *dest;
1329
1330	dest = SLOT(mlabel);
1331
1332	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1333}
1334
1335static int
1336mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1337    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1338{
1339
1340	if (!mls_enabled)
1341		return (0);
1342
1343	/* XXX: This will be implemented soon... */
1344
1345	return (0);
1346}
1347
1348static int
1349mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1350    struct label *pplabel)
1351{
1352	struct mac_mls *subj, *obj;
1353
1354	if (!mls_enabled)
1355		return (0);
1356
1357	subj = SLOT(cred->cr_label);
1358	obj = SLOT(pplabel);
1359
1360	if (!mls_dominate_effective(subj, obj))
1361		return (EACCES);
1362
1363	return (0);
1364}
1365
1366static int
1367mls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1368    struct label *pplabel)
1369{
1370	struct mac_mls *subj, *obj;
1371
1372	if (!mls_enabled)
1373		return (0);
1374
1375	subj = SLOT(cred->cr_label);
1376	obj = SLOT(pplabel);
1377
1378	if (!mls_dominate_effective(subj, obj))
1379		return (EACCES);
1380
1381	return (0);
1382}
1383
1384static int
1385mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1386    struct label *pplabel, struct label *newlabel)
1387{
1388	struct mac_mls *subj, *obj, *new;
1389	int error;
1390
1391	new = SLOT(newlabel);
1392	subj = SLOT(cred->cr_label);
1393	obj = SLOT(pplabel);
1394
1395	/*
1396	 * If there is an MLS label update for a pipe, it must be a effective
1397	 * update.
1398	 */
1399	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1400	if (error)
1401		return (error);
1402
1403	/*
1404	 * To perform a relabel of a pipe (MLS label or not), MLS must
1405	 * authorize the relabel.
1406	 */
1407	if (!mls_effective_in_range(obj, subj))
1408		return (EPERM);
1409
1410	/*
1411	 * If the MLS label is to be changed, authorize as appropriate.
1412	 */
1413	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1414		/*
1415		 * To change the MLS label on a pipe, the new pipe label must
1416		 * be in the subject range.
1417		 */
1418		if (!mls_effective_in_range(new, subj))
1419			return (EPERM);
1420
1421		/*
1422		 * To change the MLS label on a pipe to be EQUAL, the subject
1423		 * must have appropriate privilege.
1424		 */
1425		if (mls_contains_equal(new)) {
1426			error = mls_subject_privileged(subj);
1427			if (error)
1428				return (error);
1429		}
1430	}
1431
1432	return (0);
1433}
1434
1435static int
1436mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1437    struct label *pplabel)
1438{
1439	struct mac_mls *subj, *obj;
1440
1441	if (!mls_enabled)
1442		return (0);
1443
1444	subj = SLOT(cred->cr_label);
1445	obj = SLOT(pplabel);
1446
1447	if (!mls_dominate_effective(subj, obj))
1448		return (EACCES);
1449
1450	return (0);
1451}
1452
1453static int
1454mls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1455    struct label *pplabel)
1456{
1457	struct mac_mls *subj, *obj;
1458
1459	if (!mls_enabled)
1460		return (0);
1461
1462	subj = SLOT(cred->cr_label);
1463	obj = SLOT(pplabel);
1464
1465	if (!mls_dominate_effective(obj, subj))
1466		return (EACCES);
1467
1468	return (0);
1469}
1470
1471static void
1472mls_pipe_create(struct ucred *cred, struct pipepair *pp,
1473    struct label *pplabel)
1474{
1475	struct mac_mls *source, *dest;
1476
1477	source = SLOT(cred->cr_label);
1478	dest = SLOT(pplabel);
1479
1480	mls_copy_effective(source, dest);
1481}
1482
1483static void
1484mls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1485    struct label *pplabel, struct label *newlabel)
1486{
1487	struct mac_mls *source, *dest;
1488
1489	source = SLOT(newlabel);
1490	dest = SLOT(pplabel);
1491
1492	mls_copy(source, dest);
1493}
1494
1495static int
1496mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1497    struct label *kslabel)
1498{
1499	struct mac_mls *subj, *obj;
1500
1501	if (!mls_enabled)
1502		return (0);
1503
1504	subj = SLOT(cred->cr_label);
1505	obj = SLOT(kslabel);
1506
1507	if (!mls_dominate_effective(obj, subj))
1508		return (EACCES);
1509
1510	return (0);
1511}
1512
1513static int
1514mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1515    struct ksem *ks, struct label *kslabel)
1516{
1517	struct mac_mls *subj, *obj;
1518
1519	if (!mls_enabled)
1520		return (0);
1521
1522	subj = SLOT(active_cred->cr_label);
1523	obj = SLOT(kslabel);
1524
1525	if (!mls_dominate_effective(subj, obj))
1526		return (EACCES);
1527
1528	return (0);
1529}
1530
1531static int
1532mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1533    struct ksem *ks, struct label *kslabel)
1534{
1535	struct mac_mls *subj, *obj;
1536
1537	if (!mls_enabled)
1538		return (0);
1539
1540	subj = SLOT(active_cred->cr_label);
1541	obj = SLOT(kslabel);
1542
1543	if (!mls_dominate_effective(obj, subj))
1544		return (EACCES);
1545
1546	return (0);
1547}
1548
1549static void
1550mls_posixsem_create(struct ucred *cred, struct ksem *ks,
1551    struct label *kslabel)
1552{
1553	struct mac_mls *source, *dest;
1554
1555	source = SLOT(cred->cr_label);
1556	dest = SLOT(kslabel);
1557
1558	mls_copy_effective(source, dest);
1559}
1560
1561static int
1562mls_proc_check_debug(struct ucred *cred, struct proc *p)
1563{
1564	struct mac_mls *subj, *obj;
1565
1566	if (!mls_enabled)
1567		return (0);
1568
1569	subj = SLOT(cred->cr_label);
1570	obj = SLOT(p->p_ucred->cr_label);
1571
1572	/* XXX: range checks */
1573	if (!mls_dominate_effective(subj, obj))
1574		return (ESRCH);
1575	if (!mls_dominate_effective(obj, subj))
1576		return (EACCES);
1577
1578	return (0);
1579}
1580
1581static int
1582mls_proc_check_sched(struct ucred *cred, struct proc *p)
1583{
1584	struct mac_mls *subj, *obj;
1585
1586	if (!mls_enabled)
1587		return (0);
1588
1589	subj = SLOT(cred->cr_label);
1590	obj = SLOT(p->p_ucred->cr_label);
1591
1592	/* XXX: range checks */
1593	if (!mls_dominate_effective(subj, obj))
1594		return (ESRCH);
1595	if (!mls_dominate_effective(obj, subj))
1596		return (EACCES);
1597
1598	return (0);
1599}
1600
1601static int
1602mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1603{
1604	struct mac_mls *subj, *obj;
1605
1606	if (!mls_enabled)
1607		return (0);
1608
1609	subj = SLOT(cred->cr_label);
1610	obj = SLOT(p->p_ucred->cr_label);
1611
1612	/* XXX: range checks */
1613	if (!mls_dominate_effective(subj, obj))
1614		return (ESRCH);
1615	if (!mls_dominate_effective(obj, subj))
1616		return (EACCES);
1617
1618	return (0);
1619}
1620
1621static int
1622mls_socket_check_deliver(struct socket *so, struct label *solabel,
1623    struct mbuf *m, struct label *mlabel)
1624{
1625	struct mac_mls *p, *s;
1626
1627	if (!mls_enabled)
1628		return (0);
1629
1630	p = SLOT(mlabel);
1631	s = SLOT(solabel);
1632
1633	return (mls_equal_effective(p, s) ? 0 : EACCES);
1634}
1635
1636static int
1637mls_socket_check_relabel(struct ucred *cred, struct socket *so,
1638    struct label *solabel, struct label *newlabel)
1639{
1640	struct mac_mls *subj, *obj, *new;
1641	int error;
1642
1643	new = SLOT(newlabel);
1644	subj = SLOT(cred->cr_label);
1645	obj = SLOT(solabel);
1646
1647	/*
1648	 * If there is an MLS label update for the socket, it may be an
1649	 * update of effective.
1650	 */
1651	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1652	if (error)
1653		return (error);
1654
1655	/*
1656	 * To relabel a socket, the old socket effective must be in the
1657	 * subject range.
1658	 */
1659	if (!mls_effective_in_range(obj, subj))
1660		return (EPERM);
1661
1662	/*
1663	 * If the MLS label is to be changed, authorize as appropriate.
1664	 */
1665	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1666		/*
1667		 * To relabel a socket, the new socket effective must be in
1668		 * the subject range.
1669		 */
1670		if (!mls_effective_in_range(new, subj))
1671			return (EPERM);
1672
1673		/*
1674		 * To change the MLS label on the socket to contain EQUAL,
1675		 * the subject must have appropriate privilege.
1676		 */
1677		if (mls_contains_equal(new)) {
1678			error = mls_subject_privileged(subj);
1679			if (error)
1680				return (error);
1681		}
1682	}
1683
1684	return (0);
1685}
1686
1687static int
1688mls_socket_check_visible(struct ucred *cred, struct socket *so,
1689    struct label *solabel)
1690{
1691	struct mac_mls *subj, *obj;
1692
1693	if (!mls_enabled)
1694		return (0);
1695
1696	subj = SLOT(cred->cr_label);
1697	obj = SLOT(solabel);
1698
1699	if (!mls_dominate_effective(subj, obj))
1700		return (ENOENT);
1701
1702	return (0);
1703}
1704
1705static void
1706mls_socket_create(struct ucred *cred, struct socket *so,
1707    struct label *solabel)
1708{
1709	struct mac_mls *source, *dest;
1710
1711	source = SLOT(cred->cr_label);
1712	dest = SLOT(solabel);
1713
1714	mls_copy_effective(source, dest);
1715}
1716
1717static void
1718mls_socket_create_mbuf(struct socket *so, struct label *solabel,
1719    struct mbuf *m, struct label *mlabel)
1720{
1721	struct mac_mls *source, *dest;
1722
1723	source = SLOT(solabel);
1724	dest = SLOT(mlabel);
1725
1726	mls_copy_effective(source, dest);
1727}
1728
1729static void
1730mls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1731    struct socket *newso, struct label *newsolabel)
1732{
1733	struct mac_mls *source, *dest;
1734
1735	source = SLOT(oldsolabel);
1736	dest = SLOT(newsolabel);
1737
1738	mls_copy_effective(source, dest);
1739}
1740
1741static void
1742mls_socket_relabel(struct ucred *cred, struct socket *so,
1743    struct label *solabel, struct label *newlabel)
1744{
1745	struct mac_mls *source, *dest;
1746
1747	source = SLOT(newlabel);
1748	dest = SLOT(solabel);
1749
1750	mls_copy(source, dest);
1751}
1752
1753static void
1754mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1755    struct socket *so, struct label *sopeerlabel)
1756{
1757	struct mac_mls *source, *dest;
1758
1759	source = SLOT(mlabel);
1760	dest = SLOT(sopeerlabel);
1761
1762	mls_copy_effective(source, dest);
1763}
1764
1765static void
1766mls_socketpeer_set_from_socket(struct socket *oldso,
1767    struct label *oldsolabel, struct socket *newso,
1768    struct label *newsopeerlabel)
1769{
1770	struct mac_mls *source, *dest;
1771
1772	source = SLOT(oldsolabel);
1773	dest = SLOT(newsopeerlabel);
1774
1775	mls_copy_effective(source, dest);
1776}
1777
1778static void
1779mls_syncache_create(struct label *label, struct inpcb *inp)
1780{
1781	struct mac_mls *source, *dest;
1782
1783	source = SLOT(inp->inp_label);
1784	dest = SLOT(label);
1785
1786	mls_copy_effective(source, dest);
1787}
1788
1789static void
1790mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
1791    struct label *mlabel)
1792{
1793	struct mac_mls *source, *dest;
1794
1795	source = SLOT(sc_label);
1796	dest = SLOT(mlabel);
1797
1798	mls_copy_effective(source, dest);
1799}
1800
1801static int
1802mls_system_check_acct(struct ucred *cred, struct vnode *vp,
1803    struct label *vplabel)
1804{
1805	struct mac_mls *subj, *obj;
1806
1807	if (!mls_enabled)
1808		return (0);
1809
1810	subj = SLOT(cred->cr_label);
1811	obj = SLOT(vplabel);
1812
1813	if (!mls_dominate_effective(obj, subj) ||
1814	    !mls_dominate_effective(subj, obj))
1815		return (EACCES);
1816
1817	return (0);
1818}
1819
1820static int
1821mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
1822    struct label *vplabel)
1823{
1824	struct mac_mls *subj, *obj;
1825
1826	if (!mls_enabled)
1827		return (0);
1828
1829	subj = SLOT(cred->cr_label);
1830	obj = SLOT(vplabel);
1831
1832	if (!mls_dominate_effective(obj, subj) ||
1833	    !mls_dominate_effective(subj, obj))
1834		return (EACCES);
1835
1836	return (0);
1837}
1838
1839static int
1840mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
1841    struct label *vplabel)
1842{
1843	struct mac_mls *subj, *obj;
1844
1845	if (!mls_enabled)
1846		return (0);
1847
1848	subj = SLOT(cred->cr_label);
1849	obj = SLOT(vplabel);
1850
1851	if (!mls_dominate_effective(obj, subj) ||
1852	    !mls_dominate_effective(subj, obj))
1853		return (EACCES);
1854
1855	return (0);
1856}
1857
1858static void
1859mls_sysvmsg_cleanup(struct label *msglabel)
1860{
1861
1862	bzero(SLOT(msglabel), sizeof(struct mac_mls));
1863}
1864
1865static void
1866mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1867    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1868{
1869	struct mac_mls *source, *dest;
1870
1871	/* Ignore the msgq label. */
1872	source = SLOT(cred->cr_label);
1873	dest = SLOT(msglabel);
1874
1875	mls_copy_effective(source, dest);
1876}
1877
1878static int
1879mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
1880    struct label *msglabel)
1881{
1882	struct mac_mls *subj, *obj;
1883
1884	if (!mls_enabled)
1885		return (0);
1886
1887	subj = SLOT(cred->cr_label);
1888	obj = SLOT(msglabel);
1889
1890	if (!mls_dominate_effective(subj, obj))
1891		return (EACCES);
1892
1893	return (0);
1894}
1895
1896static int
1897mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
1898    struct label *msglabel)
1899{
1900	struct mac_mls *subj, *obj;
1901
1902	if (!mls_enabled)
1903		return (0);
1904
1905	subj = SLOT(cred->cr_label);
1906	obj = SLOT(msglabel);
1907
1908	if (!mls_dominate_effective(obj, subj))
1909		return (EACCES);
1910
1911	return (0);
1912}
1913
1914static int
1915mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1916    struct label *msqklabel)
1917{
1918	struct mac_mls *subj, *obj;
1919
1920	if (!mls_enabled)
1921		return (0);
1922
1923	subj = SLOT(cred->cr_label);
1924	obj = SLOT(msqklabel);
1925
1926	if (!mls_dominate_effective(subj, obj))
1927		return (EACCES);
1928
1929	return (0);
1930}
1931
1932static int
1933mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1934    struct label *msqklabel)
1935{
1936	struct mac_mls *subj, *obj;
1937
1938	if (!mls_enabled)
1939		return (0);
1940
1941	subj = SLOT(cred->cr_label);
1942	obj = SLOT(msqklabel);
1943
1944	if (!mls_dominate_effective(obj, subj))
1945		return (EACCES);
1946
1947	return (0);
1948}
1949
1950static int
1951mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1952    struct label *msqklabel)
1953{
1954	struct mac_mls *subj, *obj;
1955
1956	if (!mls_enabled)
1957		return (0);
1958
1959	subj = SLOT(cred->cr_label);
1960	obj = SLOT(msqklabel);
1961
1962	if (!mls_dominate_effective(subj, obj))
1963		return (EACCES);
1964
1965	return (0);
1966}
1967
1968static int
1969mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1970    struct label *msqklabel, int cmd)
1971{
1972	struct mac_mls *subj, *obj;
1973
1974	if (!mls_enabled)
1975		return (0);
1976
1977	subj = SLOT(cred->cr_label);
1978	obj = SLOT(msqklabel);
1979
1980	switch(cmd) {
1981	case IPC_RMID:
1982	case IPC_SET:
1983		if (!mls_dominate_effective(obj, subj))
1984			return (EACCES);
1985		break;
1986
1987	case IPC_STAT:
1988		if (!mls_dominate_effective(subj, obj))
1989			return (EACCES);
1990		break;
1991
1992	default:
1993		return (EACCES);
1994	}
1995
1996	return (0);
1997}
1998
1999static void
2000mls_sysvmsq_cleanup(struct label *msqlabel)
2001{
2002
2003	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2004}
2005
2006static void
2007mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2008    struct label *msqlabel)
2009{
2010	struct mac_mls *source, *dest;
2011
2012	source = SLOT(cred->cr_label);
2013	dest = SLOT(msqlabel);
2014
2015	mls_copy_effective(source, dest);
2016}
2017
2018static int
2019mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2020    struct label *semaklabel, int cmd)
2021{
2022	struct mac_mls *subj, *obj;
2023
2024	if (!mls_enabled)
2025		return (0);
2026
2027	subj = SLOT(cred->cr_label);
2028	obj = SLOT(semaklabel);
2029
2030	switch(cmd) {
2031	case IPC_RMID:
2032	case IPC_SET:
2033	case SETVAL:
2034	case SETALL:
2035		if (!mls_dominate_effective(obj, subj))
2036			return (EACCES);
2037		break;
2038
2039	case IPC_STAT:
2040	case GETVAL:
2041	case GETPID:
2042	case GETNCNT:
2043	case GETZCNT:
2044	case GETALL:
2045		if (!mls_dominate_effective(subj, obj))
2046			return (EACCES);
2047		break;
2048
2049	default:
2050		return (EACCES);
2051	}
2052
2053	return (0);
2054}
2055
2056static int
2057mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2058    struct label *semaklabel)
2059{
2060	struct mac_mls *subj, *obj;
2061
2062	if (!mls_enabled)
2063		return (0);
2064
2065	subj = SLOT(cred->cr_label);
2066	obj = SLOT(semaklabel);
2067
2068	if (!mls_dominate_effective(subj, obj))
2069		return (EACCES);
2070
2071	return (0);
2072}
2073
2074static int
2075mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2076    struct label *semaklabel, size_t accesstype)
2077{
2078	struct mac_mls *subj, *obj;
2079
2080	if (!mls_enabled)
2081		return (0);
2082
2083	subj = SLOT(cred->cr_label);
2084	obj = SLOT(semaklabel);
2085
2086	if( accesstype & SEM_R )
2087		if (!mls_dominate_effective(subj, obj))
2088			return (EACCES);
2089
2090	if( accesstype & SEM_A )
2091		if (!mls_dominate_effective(obj, subj))
2092			return (EACCES);
2093
2094	return (0);
2095}
2096
2097static void
2098mls_sysvsem_cleanup(struct label *semalabel)
2099{
2100
2101	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2102}
2103
2104static void
2105mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2106    struct label *semalabel)
2107{
2108	struct mac_mls *source, *dest;
2109
2110	source = SLOT(cred->cr_label);
2111	dest = SLOT(semalabel);
2112
2113	mls_copy_effective(source, dest);
2114}
2115
2116static int
2117mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2118    struct label *shmseglabel, int shmflg)
2119{
2120	struct mac_mls *subj, *obj;
2121
2122	if (!mls_enabled)
2123		return (0);
2124
2125	subj = SLOT(cred->cr_label);
2126	obj = SLOT(shmseglabel);
2127
2128	if (!mls_dominate_effective(subj, obj))
2129		return (EACCES);
2130	if ((shmflg & SHM_RDONLY) == 0) {
2131		if (!mls_dominate_effective(obj, subj))
2132			return (EACCES);
2133	}
2134
2135	return (0);
2136}
2137
2138static int
2139mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2140    struct label *shmseglabel, int cmd)
2141{
2142	struct mac_mls *subj, *obj;
2143
2144	if (!mls_enabled)
2145		return (0);
2146
2147	subj = SLOT(cred->cr_label);
2148	obj = SLOT(shmseglabel);
2149
2150	switch(cmd) {
2151	case IPC_RMID:
2152	case IPC_SET:
2153		if (!mls_dominate_effective(obj, subj))
2154			return (EACCES);
2155		break;
2156
2157	case IPC_STAT:
2158	case SHM_STAT:
2159		if (!mls_dominate_effective(subj, obj))
2160			return (EACCES);
2161		break;
2162
2163	default:
2164		return (EACCES);
2165	}
2166
2167	return (0);
2168}
2169
2170static int
2171mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2172    struct label *shmseglabel, int shmflg)
2173{
2174	struct mac_mls *subj, *obj;
2175
2176	if (!mls_enabled)
2177		return (0);
2178
2179	subj = SLOT(cred->cr_label);
2180	obj = SLOT(shmseglabel);
2181
2182	if (!mls_dominate_effective(obj, subj))
2183		return (EACCES);
2184
2185	return (0);
2186}
2187
2188static void
2189mls_sysvshm_cleanup(struct label *shmlabel)
2190{
2191
2192	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2193}
2194
2195static void
2196mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2197    struct label *shmlabel)
2198{
2199	struct mac_mls *source, *dest;
2200
2201	source = SLOT(cred->cr_label);
2202	dest = SLOT(shmlabel);
2203
2204	mls_copy_effective(source, dest);
2205}
2206
2207static int
2208mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2209    struct vnode *vp, struct label *vplabel)
2210{
2211	struct mac_mls mm_temp, *source, *dest;
2212	int buflen, error;
2213
2214	source = SLOT(mplabel);
2215	dest = SLOT(vplabel);
2216
2217	buflen = sizeof(mm_temp);
2218	bzero(&mm_temp, buflen);
2219
2220	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2221	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2222	if (error == ENOATTR || error == EOPNOTSUPP) {
2223		/* Fall back to the mntlabel. */
2224		mls_copy_effective(source, dest);
2225		return (0);
2226	} else if (error)
2227		return (error);
2228
2229	if (buflen != sizeof(mm_temp)) {
2230		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2231		return (EPERM);
2232	}
2233	if (mls_valid(&mm_temp) != 0) {
2234		printf("mls_vnode_associate_extattr: invalid\n");
2235		return (EPERM);
2236	}
2237	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2238	    MAC_MLS_FLAG_EFFECTIVE) {
2239		printf("mls_associated_vnode_extattr: not effective\n");
2240		return (EPERM);
2241	}
2242
2243	mls_copy_effective(&mm_temp, dest);
2244	return (0);
2245}
2246
2247static void
2248mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2249    struct vnode *vp, struct label *vplabel)
2250{
2251	struct mac_mls *source, *dest;
2252
2253	source = SLOT(mplabel);
2254	dest = SLOT(vplabel);
2255
2256	mls_copy_effective(source, dest);
2257}
2258
2259static int
2260mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2261    struct label *dvplabel)
2262{
2263	struct mac_mls *subj, *obj;
2264
2265	if (!mls_enabled)
2266		return (0);
2267
2268	subj = SLOT(cred->cr_label);
2269	obj = SLOT(dvplabel);
2270
2271	if (!mls_dominate_effective(subj, obj))
2272		return (EACCES);
2273
2274	return (0);
2275}
2276
2277static int
2278mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2279    struct label *dvplabel)
2280{
2281	struct mac_mls *subj, *obj;
2282
2283	if (!mls_enabled)
2284		return (0);
2285
2286	subj = SLOT(cred->cr_label);
2287	obj = SLOT(dvplabel);
2288
2289	if (!mls_dominate_effective(subj, obj))
2290		return (EACCES);
2291
2292	return (0);
2293}
2294
2295static int
2296mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2297    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2298{
2299	struct mac_mls *subj, *obj;
2300
2301	if (!mls_enabled)
2302		return (0);
2303
2304	subj = SLOT(cred->cr_label);
2305	obj = SLOT(dvplabel);
2306
2307	if (!mls_dominate_effective(obj, subj))
2308		return (EACCES);
2309
2310	return (0);
2311}
2312
2313static int
2314mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2315    struct label *vplabel, acl_type_t type)
2316{
2317	struct mac_mls *subj, *obj;
2318
2319	if (!mls_enabled)
2320		return (0);
2321
2322	subj = SLOT(cred->cr_label);
2323	obj = SLOT(vplabel);
2324
2325	if (!mls_dominate_effective(obj, subj))
2326		return (EACCES);
2327
2328	return (0);
2329}
2330
2331static int
2332mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2333    struct label *vplabel, int attrnamespace, const char *name)
2334{
2335	struct mac_mls *subj, *obj;
2336
2337	if (!mls_enabled)
2338		return (0);
2339
2340	subj = SLOT(cred->cr_label);
2341	obj = SLOT(vplabel);
2342
2343	if (!mls_dominate_effective(obj, subj))
2344		return (EACCES);
2345
2346	return (0);
2347}
2348
2349static int
2350mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2351    struct label *vplabel, struct image_params *imgp,
2352    struct label *execlabel)
2353{
2354	struct mac_mls *subj, *obj, *exec;
2355	int error;
2356
2357	if (execlabel != NULL) {
2358		/*
2359		 * We currently don't permit labels to be changed at
2360		 * exec-time as part of MLS, so disallow non-NULL MLS label
2361		 * elements in the execlabel.
2362		 */
2363		exec = SLOT(execlabel);
2364		error = mls_atmostflags(exec, 0);
2365		if (error)
2366			return (error);
2367	}
2368
2369	if (!mls_enabled)
2370		return (0);
2371
2372	subj = SLOT(cred->cr_label);
2373	obj = SLOT(vplabel);
2374
2375	if (!mls_dominate_effective(subj, obj))
2376		return (EACCES);
2377
2378	return (0);
2379}
2380
2381static int
2382mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2383    struct label *vplabel, acl_type_t type)
2384{
2385	struct mac_mls *subj, *obj;
2386
2387	if (!mls_enabled)
2388		return (0);
2389
2390	subj = SLOT(cred->cr_label);
2391	obj = SLOT(vplabel);
2392
2393	if (!mls_dominate_effective(subj, obj))
2394		return (EACCES);
2395
2396	return (0);
2397}
2398
2399static int
2400mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2401    struct label *vplabel, int attrnamespace, const char *name,
2402    struct uio *uio)
2403{
2404	struct mac_mls *subj, *obj;
2405
2406	if (!mls_enabled)
2407		return (0);
2408
2409	subj = SLOT(cred->cr_label);
2410	obj = SLOT(vplabel);
2411
2412	if (!mls_dominate_effective(subj, obj))
2413		return (EACCES);
2414
2415	return (0);
2416}
2417
2418static int
2419mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2420    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2421    struct componentname *cnp)
2422{
2423	struct mac_mls *subj, *obj;
2424
2425	if (!mls_enabled)
2426		return (0);
2427
2428	subj = SLOT(cred->cr_label);
2429	obj = SLOT(dvplabel);
2430
2431	if (!mls_dominate_effective(obj, subj))
2432		return (EACCES);
2433
2434	obj = SLOT(vplabel);
2435	if (!mls_dominate_effective(obj, subj))
2436		return (EACCES);
2437
2438	return (0);
2439}
2440
2441static int
2442mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2443    struct label *vplabel, int attrnamespace)
2444{
2445
2446	struct mac_mls *subj, *obj;
2447
2448	if (!mls_enabled)
2449		return (0);
2450
2451	subj = SLOT(cred->cr_label);
2452	obj = SLOT(vplabel);
2453
2454	if (!mls_dominate_effective(subj, obj))
2455		return (EACCES);
2456
2457	return (0);
2458}
2459
2460static int
2461mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2462    struct label *dvplabel, struct componentname *cnp)
2463{
2464	struct mac_mls *subj, *obj;
2465
2466	if (!mls_enabled)
2467		return (0);
2468
2469	subj = SLOT(cred->cr_label);
2470	obj = SLOT(dvplabel);
2471
2472	if (!mls_dominate_effective(subj, obj))
2473		return (EACCES);
2474
2475	return (0);
2476}
2477
2478static int
2479mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2480    struct label *vplabel, int prot, int flags)
2481{
2482	struct mac_mls *subj, *obj;
2483
2484	/*
2485	 * Rely on the use of open()-time protections to handle
2486	 * non-revocation cases.
2487	 */
2488	if (!mls_enabled || !revocation_enabled)
2489		return (0);
2490
2491	subj = SLOT(cred->cr_label);
2492	obj = SLOT(vplabel);
2493
2494	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2495		if (!mls_dominate_effective(subj, obj))
2496			return (EACCES);
2497	}
2498	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2499		if (!mls_dominate_effective(obj, subj))
2500			return (EACCES);
2501	}
2502
2503	return (0);
2504}
2505
2506static int
2507mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2508    struct label *vplabel, int acc_mode)
2509{
2510	struct mac_mls *subj, *obj;
2511
2512	if (!mls_enabled)
2513		return (0);
2514
2515	subj = SLOT(cred->cr_label);
2516	obj = SLOT(vplabel);
2517
2518	/* XXX privilege override for admin? */
2519	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2520		if (!mls_dominate_effective(subj, obj))
2521			return (EACCES);
2522	}
2523	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2524		if (!mls_dominate_effective(obj, subj))
2525			return (EACCES);
2526	}
2527
2528	return (0);
2529}
2530
2531static int
2532mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2533    struct vnode *vp, struct label *vplabel)
2534{
2535	struct mac_mls *subj, *obj;
2536
2537	if (!mls_enabled || !revocation_enabled)
2538		return (0);
2539
2540	subj = SLOT(active_cred->cr_label);
2541	obj = SLOT(vplabel);
2542
2543	if (!mls_dominate_effective(subj, obj))
2544		return (EACCES);
2545
2546	return (0);
2547}
2548
2549static int
2550mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2551    struct vnode *vp, struct label *vplabel)
2552{
2553	struct mac_mls *subj, *obj;
2554
2555	if (!mls_enabled || !revocation_enabled)
2556		return (0);
2557
2558	subj = SLOT(active_cred->cr_label);
2559	obj = SLOT(vplabel);
2560
2561	if (!mls_dominate_effective(subj, obj))
2562		return (EACCES);
2563
2564	return (0);
2565}
2566
2567static int
2568mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2569    struct label *dvplabel)
2570{
2571	struct mac_mls *subj, *obj;
2572
2573	if (!mls_enabled)
2574		return (0);
2575
2576	subj = SLOT(cred->cr_label);
2577	obj = SLOT(dvplabel);
2578
2579	if (!mls_dominate_effective(subj, obj))
2580		return (EACCES);
2581
2582	return (0);
2583}
2584
2585static int
2586mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2587    struct label *vplabel)
2588{
2589	struct mac_mls *subj, *obj;
2590
2591	if (!mls_enabled)
2592		return (0);
2593
2594	subj = SLOT(cred->cr_label);
2595	obj = SLOT(vplabel);
2596
2597	if (!mls_dominate_effective(subj, obj))
2598		return (EACCES);
2599
2600	return (0);
2601}
2602
2603static int
2604mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2605    struct label *vplabel, struct label *newlabel)
2606{
2607	struct mac_mls *old, *new, *subj;
2608	int error;
2609
2610	old = SLOT(vplabel);
2611	new = SLOT(newlabel);
2612	subj = SLOT(cred->cr_label);
2613
2614	/*
2615	 * If there is an MLS label update for the vnode, it must be a
2616	 * effective label.
2617	 */
2618	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2619	if (error)
2620		return (error);
2621
2622	/*
2623	 * To perform a relabel of the vnode (MLS label or not), MLS must
2624	 * authorize the relabel.
2625	 */
2626	if (!mls_effective_in_range(old, subj))
2627		return (EPERM);
2628
2629	/*
2630	 * If the MLS label is to be changed, authorize as appropriate.
2631	 */
2632	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2633		/*
2634		 * To change the MLS label on a vnode, the new vnode label
2635		 * must be in the subject range.
2636		 */
2637		if (!mls_effective_in_range(new, subj))
2638			return (EPERM);
2639
2640		/*
2641		 * To change the MLS label on the vnode to be EQUAL, the
2642		 * subject must have appropriate privilege.
2643		 */
2644		if (mls_contains_equal(new)) {
2645			error = mls_subject_privileged(subj);
2646			if (error)
2647				return (error);
2648		}
2649	}
2650
2651	return (0);
2652}
2653
2654static int
2655mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2656    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2657    struct componentname *cnp)
2658{
2659	struct mac_mls *subj, *obj;
2660
2661	if (!mls_enabled)
2662		return (0);
2663
2664	subj = SLOT(cred->cr_label);
2665	obj = SLOT(dvplabel);
2666
2667	if (!mls_dominate_effective(obj, subj))
2668		return (EACCES);
2669
2670	obj = SLOT(vplabel);
2671
2672	if (!mls_dominate_effective(obj, subj))
2673		return (EACCES);
2674
2675	return (0);
2676}
2677
2678static int
2679mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2680    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2681    int samedir, struct componentname *cnp)
2682{
2683	struct mac_mls *subj, *obj;
2684
2685	if (!mls_enabled)
2686		return (0);
2687
2688	subj = SLOT(cred->cr_label);
2689	obj = SLOT(dvplabel);
2690
2691	if (!mls_dominate_effective(obj, subj))
2692		return (EACCES);
2693
2694	if (vp != NULL) {
2695		obj = SLOT(vplabel);
2696
2697		if (!mls_dominate_effective(obj, subj))
2698			return (EACCES);
2699	}
2700
2701	return (0);
2702}
2703
2704static int
2705mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2706    struct label *vplabel)
2707{
2708	struct mac_mls *subj, *obj;
2709
2710	if (!mls_enabled)
2711		return (0);
2712
2713	subj = SLOT(cred->cr_label);
2714	obj = SLOT(vplabel);
2715
2716	if (!mls_dominate_effective(obj, subj))
2717		return (EACCES);
2718
2719	return (0);
2720}
2721
2722static int
2723mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2724    struct label *vplabel, acl_type_t type, struct acl *acl)
2725{
2726	struct mac_mls *subj, *obj;
2727
2728	if (!mls_enabled)
2729		return (0);
2730
2731	subj = SLOT(cred->cr_label);
2732	obj = SLOT(vplabel);
2733
2734	if (!mls_dominate_effective(obj, subj))
2735		return (EACCES);
2736
2737	return (0);
2738}
2739
2740static int
2741mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2742    struct label *vplabel, int attrnamespace, const char *name,
2743    struct uio *uio)
2744{
2745	struct mac_mls *subj, *obj;
2746
2747	if (!mls_enabled)
2748		return (0);
2749
2750	subj = SLOT(cred->cr_label);
2751	obj = SLOT(vplabel);
2752
2753	if (!mls_dominate_effective(obj, subj))
2754		return (EACCES);
2755
2756	/* XXX: protect the MAC EA in a special way? */
2757
2758	return (0);
2759}
2760
2761static int
2762mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2763    struct label *vplabel, u_long flags)
2764{
2765	struct mac_mls *subj, *obj;
2766
2767	if (!mls_enabled)
2768		return (0);
2769
2770	subj = SLOT(cred->cr_label);
2771	obj = SLOT(vplabel);
2772
2773	if (!mls_dominate_effective(obj, subj))
2774		return (EACCES);
2775
2776	return (0);
2777}
2778
2779static int
2780mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2781    struct label *vplabel, mode_t mode)
2782{
2783	struct mac_mls *subj, *obj;
2784
2785	if (!mls_enabled)
2786		return (0);
2787
2788	subj = SLOT(cred->cr_label);
2789	obj = SLOT(vplabel);
2790
2791	if (!mls_dominate_effective(obj, subj))
2792		return (EACCES);
2793
2794	return (0);
2795}
2796
2797static int
2798mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2799    struct label *vplabel, uid_t uid, gid_t gid)
2800{
2801	struct mac_mls *subj, *obj;
2802
2803	if (!mls_enabled)
2804		return (0);
2805
2806	subj = SLOT(cred->cr_label);
2807	obj = SLOT(vplabel);
2808
2809	if (!mls_dominate_effective(obj, subj))
2810		return (EACCES);
2811
2812	return (0);
2813}
2814
2815static int
2816mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2817    struct label *vplabel, struct timespec atime, struct timespec mtime)
2818{
2819	struct mac_mls *subj, *obj;
2820
2821	if (!mls_enabled)
2822		return (0);
2823
2824	subj = SLOT(cred->cr_label);
2825	obj = SLOT(vplabel);
2826
2827	if (!mls_dominate_effective(obj, subj))
2828		return (EACCES);
2829
2830	return (0);
2831}
2832
2833static int
2834mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
2835    struct vnode *vp, struct label *vplabel)
2836{
2837	struct mac_mls *subj, *obj;
2838
2839	if (!mls_enabled)
2840		return (0);
2841
2842	subj = SLOT(active_cred->cr_label);
2843	obj = SLOT(vplabel);
2844
2845	if (!mls_dominate_effective(subj, obj))
2846		return (EACCES);
2847
2848	return (0);
2849}
2850
2851static int
2852mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2853    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2854    struct componentname *cnp)
2855{
2856	struct mac_mls *subj, *obj;
2857
2858	if (!mls_enabled)
2859		return (0);
2860
2861	subj = SLOT(cred->cr_label);
2862	obj = SLOT(dvplabel);
2863
2864	if (!mls_dominate_effective(obj, subj))
2865		return (EACCES);
2866
2867	obj = SLOT(vplabel);
2868
2869	if (!mls_dominate_effective(obj, subj))
2870		return (EACCES);
2871
2872	return (0);
2873}
2874
2875static int
2876mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
2877    struct vnode *vp, struct label *vplabel)
2878{
2879	struct mac_mls *subj, *obj;
2880
2881	if (!mls_enabled || !revocation_enabled)
2882		return (0);
2883
2884	subj = SLOT(active_cred->cr_label);
2885	obj = SLOT(vplabel);
2886
2887	if (!mls_dominate_effective(obj, subj))
2888		return (EACCES);
2889
2890	return (0);
2891}
2892
2893static int
2894mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2895    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2896    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2897{
2898	struct mac_mls *source, *dest, mm_temp;
2899	size_t buflen;
2900	int error;
2901
2902	buflen = sizeof(mm_temp);
2903	bzero(&mm_temp, buflen);
2904
2905	source = SLOT(cred->cr_label);
2906	dest = SLOT(vplabel);
2907	mls_copy_effective(source, &mm_temp);
2908
2909	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2910	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2911	if (error == 0)
2912		mls_copy_effective(source, dest);
2913	return (error);
2914}
2915
2916static void
2917mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
2918    struct label *vplabel, struct label *label)
2919{
2920	struct mac_mls *source, *dest;
2921
2922	source = SLOT(label);
2923	dest = SLOT(vplabel);
2924
2925	mls_copy(source, dest);
2926}
2927
2928static int
2929mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2930    struct label *vplabel, struct label *intlabel)
2931{
2932	struct mac_mls *source, mm_temp;
2933	size_t buflen;
2934	int error;
2935
2936	buflen = sizeof(mm_temp);
2937	bzero(&mm_temp, buflen);
2938
2939	source = SLOT(intlabel);
2940	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
2941		return (0);
2942
2943	mls_copy_effective(source, &mm_temp);
2944
2945	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2946	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2947	return (error);
2948}
2949
2950static struct mac_policy_ops mls_ops =
2951{
2952	.mpo_init = mls_init,
2953
2954	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
2955	.mpo_bpfdesc_create = mls_bpfdesc_create,
2956	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
2957	.mpo_bpfdesc_destroy_label = mls_destroy_label,
2958	.mpo_bpfdesc_init_label = mls_init_label,
2959
2960	.mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
2961	.mpo_cred_check_relabel = mls_cred_check_relabel,
2962	.mpo_cred_check_visible = mls_cred_check_visible,
2963	.mpo_cred_copy_label = mls_copy_label,
2964	.mpo_cred_create_init = mls_cred_create_init,
2965	.mpo_cred_create_swapper = mls_cred_create_swapper,
2966	.mpo_cred_destroy_label = mls_destroy_label,
2967	.mpo_cred_externalize_label = mls_externalize_label,
2968	.mpo_cred_init_label = mls_init_label,
2969	.mpo_cred_internalize_label = mls_internalize_label,
2970	.mpo_cred_relabel = mls_cred_relabel,
2971
2972	.mpo_devfs_create_device = mls_devfs_create_device,
2973	.mpo_devfs_create_directory = mls_devfs_create_directory,
2974	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
2975	.mpo_devfs_destroy_label = mls_destroy_label,
2976	.mpo_devfs_init_label = mls_init_label,
2977	.mpo_devfs_update = mls_devfs_update,
2978	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
2979
2980	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
2981	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
2982	.mpo_ifnet_copy_label = mls_copy_label,
2983	.mpo_ifnet_create = mls_ifnet_create,
2984	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
2985	.mpo_ifnet_destroy_label = mls_destroy_label,
2986	.mpo_ifnet_externalize_label = mls_externalize_label,
2987	.mpo_ifnet_init_label = mls_init_label,
2988	.mpo_ifnet_internalize_label = mls_internalize_label,
2989	.mpo_ifnet_relabel = mls_ifnet_relabel,
2990
2991	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
2992	.mpo_inpcb_check_visible = mls_inpcb_check_visible,
2993	.mpo_inpcb_create = mls_inpcb_create,
2994	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
2995	.mpo_inpcb_destroy_label = mls_destroy_label,
2996	.mpo_inpcb_init_label = mls_init_label_waitcheck,
2997	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
2998
2999	.mpo_ip6q_create = mls_ip6q_create,
3000	.mpo_ip6q_destroy_label = mls_destroy_label,
3001	.mpo_ip6q_init_label = mls_init_label_waitcheck,
3002	.mpo_ip6q_match = mls_ip6q_match,
3003	.mpo_ip6q_reassemble = mls_ip6q_reassemble,
3004	.mpo_ip6q_update = mls_ip6q_update,
3005
3006	.mpo_ipq_create = mls_ipq_create,
3007	.mpo_ipq_destroy_label = mls_destroy_label,
3008	.mpo_ipq_init_label = mls_init_label_waitcheck,
3009	.mpo_ipq_match = mls_ipq_match,
3010	.mpo_ipq_reassemble = mls_ipq_reassemble,
3011	.mpo_ipq_update = mls_ipq_update,
3012
3013	.mpo_mbuf_copy_label = mls_copy_label,
3014	.mpo_mbuf_destroy_label = mls_destroy_label,
3015	.mpo_mbuf_init_label = mls_init_label_waitcheck,
3016
3017	.mpo_mount_check_stat = mls_mount_check_stat,
3018	.mpo_mount_create = mls_mount_create,
3019	.mpo_mount_destroy_label = mls_destroy_label,
3020	.mpo_mount_init_label = mls_init_label,
3021
3022	.mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3023
3024	.mpo_netinet_arp_send = mls_netinet_arp_send,
3025	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3026	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
3027	.mpo_netinet_fragment = mls_netinet_fragment,
3028	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3029	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
3030
3031	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3032
3033	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3034	.mpo_pipe_check_poll = mls_pipe_check_poll,
3035	.mpo_pipe_check_read = mls_pipe_check_read,
3036	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
3037	.mpo_pipe_check_stat = mls_pipe_check_stat,
3038	.mpo_pipe_check_write = mls_pipe_check_write,
3039	.mpo_pipe_copy_label = mls_copy_label,
3040	.mpo_pipe_create = mls_pipe_create,
3041	.mpo_pipe_destroy_label = mls_destroy_label,
3042	.mpo_pipe_externalize_label = mls_externalize_label,
3043	.mpo_pipe_init_label = mls_init_label,
3044	.mpo_pipe_internalize_label = mls_internalize_label,
3045	.mpo_pipe_relabel = mls_pipe_relabel,
3046
3047	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3048	.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3049	.mpo_posixsem_check_post = mls_posixsem_check_write,
3050	.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3051	.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3052	.mpo_posixsem_check_wait = mls_posixsem_check_write,
3053	.mpo_posixsem_create = mls_posixsem_create,
3054	.mpo_posixsem_destroy_label = mls_destroy_label,
3055	.mpo_posixsem_init_label = mls_init_label,
3056
3057	.mpo_proc_check_debug = mls_proc_check_debug,
3058	.mpo_proc_check_sched = mls_proc_check_sched,
3059	.mpo_proc_check_signal = mls_proc_check_signal,
3060
3061	.mpo_socket_check_deliver = mls_socket_check_deliver,
3062	.mpo_socket_check_relabel = mls_socket_check_relabel,
3063	.mpo_socket_check_visible = mls_socket_check_visible,
3064	.mpo_socket_copy_label = mls_copy_label,
3065	.mpo_socket_create = mls_socket_create,
3066	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
3067	.mpo_socket_destroy_label = mls_destroy_label,
3068	.mpo_socket_externalize_label = mls_externalize_label,
3069	.mpo_socket_init_label = mls_init_label_waitcheck,
3070	.mpo_socket_internalize_label = mls_internalize_label,
3071	.mpo_socket_newconn = mls_socket_newconn,
3072	.mpo_socket_relabel = mls_socket_relabel,
3073
3074	.mpo_socketpeer_destroy_label = mls_destroy_label,
3075	.mpo_socketpeer_externalize_label = mls_externalize_label,
3076	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
3077	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3078	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3079
3080	.mpo_syncache_create = mls_syncache_create,
3081	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3082	.mpo_syncache_destroy_label = mls_destroy_label,
3083	.mpo_syncache_init_label = mls_init_label_waitcheck,
3084
3085	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3086	.mpo_sysvmsg_create = mls_sysvmsg_create,
3087	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3088	.mpo_sysvmsg_init_label = mls_init_label,
3089
3090	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3091	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3092	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3093	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3094	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3095	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3096	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3097	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3098	.mpo_sysvmsq_init_label = mls_init_label,
3099	.mpo_sysvmsq_create = mls_sysvmsq_create,
3100
3101	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3102	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3103	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3104	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3105	.mpo_sysvsem_create = mls_sysvsem_create,
3106	.mpo_sysvsem_destroy_label = mls_destroy_label,
3107	.mpo_sysvsem_init_label = mls_init_label,
3108
3109	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3110	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3111	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3112	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3113	.mpo_sysvshm_create = mls_sysvshm_create,
3114	.mpo_sysvshm_destroy_label = mls_destroy_label,
3115	.mpo_sysvshm_init_label = mls_init_label,
3116
3117
3118	.mpo_system_check_acct = mls_system_check_acct,
3119	.mpo_system_check_auditctl = mls_system_check_auditctl,
3120	.mpo_system_check_swapon = mls_system_check_swapon,
3121
3122	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3123	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3124	.mpo_vnode_check_access = mls_vnode_check_open,
3125	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
3126	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
3127	.mpo_vnode_check_create = mls_vnode_check_create,
3128	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3129	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3130	.mpo_vnode_check_exec = mls_vnode_check_exec,
3131	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
3132	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3133	.mpo_vnode_check_link = mls_vnode_check_link,
3134	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3135	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
3136	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
3137	.mpo_vnode_check_open = mls_vnode_check_open,
3138	.mpo_vnode_check_poll = mls_vnode_check_poll,
3139	.mpo_vnode_check_read = mls_vnode_check_read,
3140	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
3141	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
3142	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
3143	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3144	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3145	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
3146	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
3147	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3148	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
3149	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
3150	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
3151	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3152	.mpo_vnode_check_stat = mls_vnode_check_stat,
3153	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
3154	.mpo_vnode_check_write = mls_vnode_check_write,
3155	.mpo_vnode_copy_label = mls_copy_label,
3156	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3157	.mpo_vnode_destroy_label = mls_destroy_label,
3158	.mpo_vnode_externalize_label = mls_externalize_label,
3159	.mpo_vnode_init_label = mls_init_label,
3160	.mpo_vnode_internalize_label = mls_internalize_label,
3161	.mpo_vnode_relabel = mls_vnode_relabel,
3162	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3163};
3164
3165#define	MLS_OBJECTS	(MPC_OBJECT_CRED |				\
3166			 /* MPC_OBJECT_PROC | */			\
3167			 MPC_OBJECT_VNODE |				\
3168			 MPC_OBJECT_INPCB |				\
3169			 MPC_OBJECT_SOCKET |				\
3170			 MPC_OBJECT_DEVFS |				\
3171			 MPC_OBJECT_MBUF |				\
3172			 MPC_OBJECT_IPQ |				\
3173			 MPC_OBJECT_IFNET |				\
3174			 MPC_OBJECT_BPFDESC |				\
3175			 MPC_OBJECT_PIPE |				\
3176			 MPC_OBJECT_MOUNT |				\
3177			 MPC_OBJECT_POSIXSEM |				\
3178			 /* MPC_OBJECT_POSIXSHM | */			\
3179			 MPC_OBJECT_SYSVMSG |				\
3180			 MPC_OBJECT_SYSVMSQ |				\
3181			 MPC_OBJECT_SYSVSEM |				\
3182			 MPC_OBJECT_SYSVSHM |				\
3183			 MPC_OBJECT_SYNCACHE)
3184
3185MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3186    MPC_LOADTIME_FLAG_NOTLATE, &mls_slot, MLS_OBJECTS);
3187