mac_mls.c revision 193391
1/*-
2 * Copyright (c) 1999-2002, 2007-2009 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 193391 2009-06-03 18:46:28Z 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	SOCK_LOCK_ASSERT(so);
1120
1121	source = SLOT(solabel);
1122	dest = SLOT(inplabel);
1123
1124	mls_copy(source, dest);
1125}
1126
1127static void
1128mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1129    struct label *q6label)
1130{
1131	struct mac_mls *source, *dest;
1132
1133	source = SLOT(mlabel);
1134	dest = SLOT(q6label);
1135
1136	mls_copy_effective(source, dest);
1137}
1138
1139static int
1140mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1141    struct label *q6label)
1142{
1143	struct mac_mls *a, *b;
1144
1145	a = SLOT(q6label);
1146	b = SLOT(mlabel);
1147
1148	return (mls_equal_effective(a, b));
1149}
1150
1151static void
1152mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1153    struct label *mlabel)
1154{
1155	struct mac_mls *source, *dest;
1156
1157	source = SLOT(q6label);
1158	dest = SLOT(mlabel);
1159
1160	/* Just use the head, since we require them all to match. */
1161	mls_copy_effective(source, dest);
1162}
1163
1164static void
1165mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1166    struct label *q6label)
1167{
1168
1169	/* NOOP: we only accept matching labels, so no need to update */
1170}
1171
1172static void
1173mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1174    struct label *qlabel)
1175{
1176	struct mac_mls *source, *dest;
1177
1178	source = SLOT(mlabel);
1179	dest = SLOT(qlabel);
1180
1181	mls_copy_effective(source, dest);
1182}
1183
1184static int
1185mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1186    struct label *qlabel)
1187{
1188	struct mac_mls *a, *b;
1189
1190	a = SLOT(qlabel);
1191	b = SLOT(mlabel);
1192
1193	return (mls_equal_effective(a, b));
1194}
1195
1196static void
1197mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1198    struct label *mlabel)
1199{
1200	struct mac_mls *source, *dest;
1201
1202	source = SLOT(qlabel);
1203	dest = SLOT(mlabel);
1204
1205	/* Just use the head, since we require them all to match. */
1206	mls_copy_effective(source, dest);
1207}
1208
1209static void
1210mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1211    struct label *qlabel)
1212{
1213
1214	/* NOOP: we only accept matching labels, so no need to update */
1215}
1216
1217static int
1218mls_mount_check_stat(struct ucred *cred, struct mount *mp,
1219    struct label *mntlabel)
1220{
1221	struct mac_mls *subj, *obj;
1222
1223	if (!mls_enabled)
1224		return (0);
1225
1226	subj = SLOT(cred->cr_label);
1227	obj = SLOT(mntlabel);
1228
1229	if (!mls_dominate_effective(subj, obj))
1230		return (EACCES);
1231
1232	return (0);
1233}
1234
1235static void
1236mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1237{
1238	struct mac_mls *source, *dest;
1239
1240	source = SLOT(cred->cr_label);
1241	dest = SLOT(mplabel);
1242
1243	mls_copy_effective(source, dest);
1244}
1245
1246static void
1247mls_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1248    struct mbuf *m, struct label *mlabel)
1249{
1250	struct mac_mls *dest;
1251
1252	dest = SLOT(mlabel);
1253
1254	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1255}
1256
1257static void
1258mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1259    struct mbuf *m, struct label *mlabel)
1260{
1261	struct mac_mls *dest;
1262
1263	dest = SLOT(mlabel);
1264
1265	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1266}
1267
1268static void
1269mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1270    struct mbuf *msend, struct label *msendlabel)
1271{
1272	struct mac_mls *source, *dest;
1273
1274	source = SLOT(mrecvlabel);
1275	dest = SLOT(msendlabel);
1276
1277	mls_copy_effective(source, dest);
1278}
1279
1280static void
1281mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1282{
1283	struct mac_mls *dest;
1284
1285	dest = SLOT(mlabel);
1286
1287	/* XXX: where is the label for the firewall really comming from? */
1288	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1289}
1290
1291static void
1292mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1293    struct label *fraglabel)
1294{
1295	struct mac_mls *source, *dest;
1296
1297	source = SLOT(mlabel);
1298	dest = SLOT(fraglabel);
1299
1300	mls_copy_effective(source, dest);
1301}
1302
1303static void
1304mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1305    struct mbuf *msend, struct label *msendlabel)
1306{
1307	struct mac_mls *source, *dest;
1308
1309	source = SLOT(mrecvlabel);
1310	dest = SLOT(msendlabel);
1311
1312	mls_copy_effective(source, dest);
1313}
1314
1315static void
1316mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1317    struct mbuf *m, struct label *mlabel)
1318{
1319	struct mac_mls *dest;
1320
1321	dest = SLOT(mlabel);
1322
1323	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1324}
1325
1326static void
1327mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1328    struct mbuf *m, struct label *mlabel)
1329{
1330	struct mac_mls *dest;
1331
1332	dest = SLOT(mlabel);
1333
1334	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1335}
1336
1337static int
1338mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1339    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1340{
1341
1342	if (!mls_enabled)
1343		return (0);
1344
1345	/* XXX: This will be implemented soon... */
1346
1347	return (0);
1348}
1349
1350static int
1351mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1352    struct label *pplabel)
1353{
1354	struct mac_mls *subj, *obj;
1355
1356	if (!mls_enabled)
1357		return (0);
1358
1359	subj = SLOT(cred->cr_label);
1360	obj = SLOT(pplabel);
1361
1362	if (!mls_dominate_effective(subj, obj))
1363		return (EACCES);
1364
1365	return (0);
1366}
1367
1368static int
1369mls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1370    struct label *pplabel)
1371{
1372	struct mac_mls *subj, *obj;
1373
1374	if (!mls_enabled)
1375		return (0);
1376
1377	subj = SLOT(cred->cr_label);
1378	obj = SLOT(pplabel);
1379
1380	if (!mls_dominate_effective(subj, obj))
1381		return (EACCES);
1382
1383	return (0);
1384}
1385
1386static int
1387mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1388    struct label *pplabel, struct label *newlabel)
1389{
1390	struct mac_mls *subj, *obj, *new;
1391	int error;
1392
1393	new = SLOT(newlabel);
1394	subj = SLOT(cred->cr_label);
1395	obj = SLOT(pplabel);
1396
1397	/*
1398	 * If there is an MLS label update for a pipe, it must be a effective
1399	 * update.
1400	 */
1401	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1402	if (error)
1403		return (error);
1404
1405	/*
1406	 * To perform a relabel of a pipe (MLS label or not), MLS must
1407	 * authorize the relabel.
1408	 */
1409	if (!mls_effective_in_range(obj, subj))
1410		return (EPERM);
1411
1412	/*
1413	 * If the MLS label is to be changed, authorize as appropriate.
1414	 */
1415	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1416		/*
1417		 * To change the MLS label on a pipe, the new pipe label must
1418		 * be in the subject range.
1419		 */
1420		if (!mls_effective_in_range(new, subj))
1421			return (EPERM);
1422
1423		/*
1424		 * To change the MLS label on a pipe to be EQUAL, the subject
1425		 * must have appropriate privilege.
1426		 */
1427		if (mls_contains_equal(new)) {
1428			error = mls_subject_privileged(subj);
1429			if (error)
1430				return (error);
1431		}
1432	}
1433
1434	return (0);
1435}
1436
1437static int
1438mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1439    struct label *pplabel)
1440{
1441	struct mac_mls *subj, *obj;
1442
1443	if (!mls_enabled)
1444		return (0);
1445
1446	subj = SLOT(cred->cr_label);
1447	obj = SLOT(pplabel);
1448
1449	if (!mls_dominate_effective(subj, obj))
1450		return (EACCES);
1451
1452	return (0);
1453}
1454
1455static int
1456mls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1457    struct label *pplabel)
1458{
1459	struct mac_mls *subj, *obj;
1460
1461	if (!mls_enabled)
1462		return (0);
1463
1464	subj = SLOT(cred->cr_label);
1465	obj = SLOT(pplabel);
1466
1467	if (!mls_dominate_effective(obj, subj))
1468		return (EACCES);
1469
1470	return (0);
1471}
1472
1473static void
1474mls_pipe_create(struct ucred *cred, struct pipepair *pp,
1475    struct label *pplabel)
1476{
1477	struct mac_mls *source, *dest;
1478
1479	source = SLOT(cred->cr_label);
1480	dest = SLOT(pplabel);
1481
1482	mls_copy_effective(source, dest);
1483}
1484
1485static void
1486mls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1487    struct label *pplabel, struct label *newlabel)
1488{
1489	struct mac_mls *source, *dest;
1490
1491	source = SLOT(newlabel);
1492	dest = SLOT(pplabel);
1493
1494	mls_copy(source, dest);
1495}
1496
1497static int
1498mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1499    struct label *kslabel)
1500{
1501	struct mac_mls *subj, *obj;
1502
1503	if (!mls_enabled)
1504		return (0);
1505
1506	subj = SLOT(cred->cr_label);
1507	obj = SLOT(kslabel);
1508
1509	if (!mls_dominate_effective(obj, subj))
1510		return (EACCES);
1511
1512	return (0);
1513}
1514
1515static int
1516mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1517    struct ksem *ks, struct label *kslabel)
1518{
1519	struct mac_mls *subj, *obj;
1520
1521	if (!mls_enabled)
1522		return (0);
1523
1524	subj = SLOT(active_cred->cr_label);
1525	obj = SLOT(kslabel);
1526
1527	if (!mls_dominate_effective(subj, obj))
1528		return (EACCES);
1529
1530	return (0);
1531}
1532
1533static int
1534mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1535    struct ksem *ks, struct label *kslabel)
1536{
1537	struct mac_mls *subj, *obj;
1538
1539	if (!mls_enabled)
1540		return (0);
1541
1542	subj = SLOT(active_cred->cr_label);
1543	obj = SLOT(kslabel);
1544
1545	if (!mls_dominate_effective(obj, subj))
1546		return (EACCES);
1547
1548	return (0);
1549}
1550
1551static void
1552mls_posixsem_create(struct ucred *cred, struct ksem *ks,
1553    struct label *kslabel)
1554{
1555	struct mac_mls *source, *dest;
1556
1557	source = SLOT(cred->cr_label);
1558	dest = SLOT(kslabel);
1559
1560	mls_copy_effective(source, dest);
1561}
1562
1563static int
1564mls_proc_check_debug(struct ucred *cred, struct proc *p)
1565{
1566	struct mac_mls *subj, *obj;
1567
1568	if (!mls_enabled)
1569		return (0);
1570
1571	subj = SLOT(cred->cr_label);
1572	obj = SLOT(p->p_ucred->cr_label);
1573
1574	/* XXX: range checks */
1575	if (!mls_dominate_effective(subj, obj))
1576		return (ESRCH);
1577	if (!mls_dominate_effective(obj, subj))
1578		return (EACCES);
1579
1580	return (0);
1581}
1582
1583static int
1584mls_proc_check_sched(struct ucred *cred, struct proc *p)
1585{
1586	struct mac_mls *subj, *obj;
1587
1588	if (!mls_enabled)
1589		return (0);
1590
1591	subj = SLOT(cred->cr_label);
1592	obj = SLOT(p->p_ucred->cr_label);
1593
1594	/* XXX: range checks */
1595	if (!mls_dominate_effective(subj, obj))
1596		return (ESRCH);
1597	if (!mls_dominate_effective(obj, subj))
1598		return (EACCES);
1599
1600	return (0);
1601}
1602
1603static int
1604mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1605{
1606	struct mac_mls *subj, *obj;
1607
1608	if (!mls_enabled)
1609		return (0);
1610
1611	subj = SLOT(cred->cr_label);
1612	obj = SLOT(p->p_ucred->cr_label);
1613
1614	/* XXX: range checks */
1615	if (!mls_dominate_effective(subj, obj))
1616		return (ESRCH);
1617	if (!mls_dominate_effective(obj, subj))
1618		return (EACCES);
1619
1620	return (0);
1621}
1622
1623static int
1624mls_socket_check_deliver(struct socket *so, struct label *solabel,
1625    struct mbuf *m, struct label *mlabel)
1626{
1627	struct mac_mls *p, *s;
1628	int error;
1629
1630	if (!mls_enabled)
1631		return (0);
1632
1633	p = SLOT(mlabel);
1634	s = SLOT(solabel);
1635
1636	SOCK_LOCK(so);
1637	error = mls_equal_effective(p, s) ? 0 : EACCES;
1638	SOCK_UNLOCK(so);
1639
1640	return (error);
1641}
1642
1643static int
1644mls_socket_check_relabel(struct ucred *cred, struct socket *so,
1645    struct label *solabel, struct label *newlabel)
1646{
1647	struct mac_mls *subj, *obj, *new;
1648	int error;
1649
1650	SOCK_LOCK_ASSERT(so);
1651
1652	new = SLOT(newlabel);
1653	subj = SLOT(cred->cr_label);
1654	obj = SLOT(solabel);
1655
1656	/*
1657	 * If there is an MLS label update for the socket, it may be an
1658	 * update of effective.
1659	 */
1660	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1661	if (error)
1662		return (error);
1663
1664	/*
1665	 * To relabel a socket, the old socket effective must be in the
1666	 * subject range.
1667	 */
1668	if (!mls_effective_in_range(obj, subj))
1669		return (EPERM);
1670
1671	/*
1672	 * If the MLS label is to be changed, authorize as appropriate.
1673	 */
1674	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1675		/*
1676		 * To relabel a socket, the new socket effective must be in
1677		 * the subject range.
1678		 */
1679		if (!mls_effective_in_range(new, subj))
1680			return (EPERM);
1681
1682		/*
1683		 * To change the MLS label on the socket to contain EQUAL,
1684		 * the subject must have appropriate privilege.
1685		 */
1686		if (mls_contains_equal(new)) {
1687			error = mls_subject_privileged(subj);
1688			if (error)
1689				return (error);
1690		}
1691	}
1692
1693	return (0);
1694}
1695
1696static int
1697mls_socket_check_visible(struct ucred *cred, struct socket *so,
1698    struct label *solabel)
1699{
1700	struct mac_mls *subj, *obj;
1701
1702	if (!mls_enabled)
1703		return (0);
1704
1705	subj = SLOT(cred->cr_label);
1706	obj = SLOT(solabel);
1707
1708	SOCK_LOCK(so);
1709	if (!mls_dominate_effective(subj, obj)) {
1710		SOCK_UNLOCK(so);
1711		return (ENOENT);
1712	}
1713	SOCK_UNLOCK(so);
1714
1715	return (0);
1716}
1717
1718static void
1719mls_socket_create(struct ucred *cred, struct socket *so,
1720    struct label *solabel)
1721{
1722	struct mac_mls *source, *dest;
1723
1724	source = SLOT(cred->cr_label);
1725	dest = SLOT(solabel);
1726
1727	mls_copy_effective(source, dest);
1728}
1729
1730static void
1731mls_socket_create_mbuf(struct socket *so, struct label *solabel,
1732    struct mbuf *m, struct label *mlabel)
1733{
1734	struct mac_mls *source, *dest;
1735
1736	source = SLOT(solabel);
1737	dest = SLOT(mlabel);
1738
1739	SOCK_LOCK(so);
1740	mls_copy_effective(source, dest);
1741	SOCK_UNLOCK(so);
1742}
1743
1744static void
1745mls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1746    struct socket *newso, struct label *newsolabel)
1747{
1748	struct mac_mls source, *dest;
1749
1750	SOCK_LOCK(oldso);
1751	source = *SLOT(oldsolabel);
1752	SOCK_UNLOCK(oldso);
1753
1754	dest = SLOT(newsolabel);
1755
1756	SOCK_LOCK(newso);
1757	mls_copy_effective(&source, dest);
1758	SOCK_UNLOCK(newso);
1759}
1760
1761static void
1762mls_socket_relabel(struct ucred *cred, struct socket *so,
1763    struct label *solabel, struct label *newlabel)
1764{
1765	struct mac_mls *source, *dest;
1766
1767	SOCK_LOCK_ASSERT(so);
1768
1769	source = SLOT(newlabel);
1770	dest = SLOT(solabel);
1771
1772	mls_copy(source, dest);
1773}
1774
1775static void
1776mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1777    struct socket *so, struct label *sopeerlabel)
1778{
1779	struct mac_mls *source, *dest;
1780
1781	source = SLOT(mlabel);
1782	dest = SLOT(sopeerlabel);
1783
1784	SOCK_LOCK(so);
1785	mls_copy_effective(source, dest);
1786	SOCK_UNLOCK(so);
1787}
1788
1789static void
1790mls_socketpeer_set_from_socket(struct socket *oldso,
1791    struct label *oldsolabel, struct socket *newso,
1792    struct label *newsopeerlabel)
1793{
1794	struct mac_mls source, *dest;
1795
1796	SOCK_LOCK(oldso);
1797	source = *SLOT(oldsolabel);
1798	SOCK_UNLOCK(oldso);
1799
1800	dest = SLOT(newsopeerlabel);
1801
1802	SOCK_LOCK(newso);
1803	mls_copy_effective(&source, dest);
1804	SOCK_UNLOCK(newso);
1805}
1806
1807static void
1808mls_syncache_create(struct label *label, struct inpcb *inp)
1809{
1810	struct mac_mls *source, *dest;
1811
1812	source = SLOT(inp->inp_label);
1813	dest = SLOT(label);
1814
1815	mls_copy_effective(source, dest);
1816}
1817
1818static void
1819mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
1820    struct label *mlabel)
1821{
1822	struct mac_mls *source, *dest;
1823
1824	source = SLOT(sc_label);
1825	dest = SLOT(mlabel);
1826
1827	mls_copy_effective(source, dest);
1828}
1829
1830static int
1831mls_system_check_acct(struct ucred *cred, struct vnode *vp,
1832    struct label *vplabel)
1833{
1834	struct mac_mls *subj, *obj;
1835
1836	if (!mls_enabled)
1837		return (0);
1838
1839	subj = SLOT(cred->cr_label);
1840	obj = SLOT(vplabel);
1841
1842	if (!mls_dominate_effective(obj, subj) ||
1843	    !mls_dominate_effective(subj, obj))
1844		return (EACCES);
1845
1846	return (0);
1847}
1848
1849static int
1850mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
1851    struct label *vplabel)
1852{
1853	struct mac_mls *subj, *obj;
1854
1855	if (!mls_enabled)
1856		return (0);
1857
1858	subj = SLOT(cred->cr_label);
1859	obj = SLOT(vplabel);
1860
1861	if (!mls_dominate_effective(obj, subj) ||
1862	    !mls_dominate_effective(subj, obj))
1863		return (EACCES);
1864
1865	return (0);
1866}
1867
1868static int
1869mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
1870    struct label *vplabel)
1871{
1872	struct mac_mls *subj, *obj;
1873
1874	if (!mls_enabled)
1875		return (0);
1876
1877	subj = SLOT(cred->cr_label);
1878	obj = SLOT(vplabel);
1879
1880	if (!mls_dominate_effective(obj, subj) ||
1881	    !mls_dominate_effective(subj, obj))
1882		return (EACCES);
1883
1884	return (0);
1885}
1886
1887static void
1888mls_sysvmsg_cleanup(struct label *msglabel)
1889{
1890
1891	bzero(SLOT(msglabel), sizeof(struct mac_mls));
1892}
1893
1894static void
1895mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
1896    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1897{
1898	struct mac_mls *source, *dest;
1899
1900	/* Ignore the msgq label. */
1901	source = SLOT(cred->cr_label);
1902	dest = SLOT(msglabel);
1903
1904	mls_copy_effective(source, dest);
1905}
1906
1907static int
1908mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
1909    struct label *msglabel)
1910{
1911	struct mac_mls *subj, *obj;
1912
1913	if (!mls_enabled)
1914		return (0);
1915
1916	subj = SLOT(cred->cr_label);
1917	obj = SLOT(msglabel);
1918
1919	if (!mls_dominate_effective(subj, obj))
1920		return (EACCES);
1921
1922	return (0);
1923}
1924
1925static int
1926mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
1927    struct label *msglabel)
1928{
1929	struct mac_mls *subj, *obj;
1930
1931	if (!mls_enabled)
1932		return (0);
1933
1934	subj = SLOT(cred->cr_label);
1935	obj = SLOT(msglabel);
1936
1937	if (!mls_dominate_effective(obj, subj))
1938		return (EACCES);
1939
1940	return (0);
1941}
1942
1943static int
1944mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1945    struct label *msqklabel)
1946{
1947	struct mac_mls *subj, *obj;
1948
1949	if (!mls_enabled)
1950		return (0);
1951
1952	subj = SLOT(cred->cr_label);
1953	obj = SLOT(msqklabel);
1954
1955	if (!mls_dominate_effective(subj, obj))
1956		return (EACCES);
1957
1958	return (0);
1959}
1960
1961static int
1962mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1963    struct label *msqklabel)
1964{
1965	struct mac_mls *subj, *obj;
1966
1967	if (!mls_enabled)
1968		return (0);
1969
1970	subj = SLOT(cred->cr_label);
1971	obj = SLOT(msqklabel);
1972
1973	if (!mls_dominate_effective(obj, subj))
1974		return (EACCES);
1975
1976	return (0);
1977}
1978
1979static int
1980mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1981    struct label *msqklabel)
1982{
1983	struct mac_mls *subj, *obj;
1984
1985	if (!mls_enabled)
1986		return (0);
1987
1988	subj = SLOT(cred->cr_label);
1989	obj = SLOT(msqklabel);
1990
1991	if (!mls_dominate_effective(subj, obj))
1992		return (EACCES);
1993
1994	return (0);
1995}
1996
1997static int
1998mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1999    struct label *msqklabel, int cmd)
2000{
2001	struct mac_mls *subj, *obj;
2002
2003	if (!mls_enabled)
2004		return (0);
2005
2006	subj = SLOT(cred->cr_label);
2007	obj = SLOT(msqklabel);
2008
2009	switch(cmd) {
2010	case IPC_RMID:
2011	case IPC_SET:
2012		if (!mls_dominate_effective(obj, subj))
2013			return (EACCES);
2014		break;
2015
2016	case IPC_STAT:
2017		if (!mls_dominate_effective(subj, obj))
2018			return (EACCES);
2019		break;
2020
2021	default:
2022		return (EACCES);
2023	}
2024
2025	return (0);
2026}
2027
2028static void
2029mls_sysvmsq_cleanup(struct label *msqlabel)
2030{
2031
2032	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2033}
2034
2035static void
2036mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2037    struct label *msqlabel)
2038{
2039	struct mac_mls *source, *dest;
2040
2041	source = SLOT(cred->cr_label);
2042	dest = SLOT(msqlabel);
2043
2044	mls_copy_effective(source, dest);
2045}
2046
2047static int
2048mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2049    struct label *semaklabel, int cmd)
2050{
2051	struct mac_mls *subj, *obj;
2052
2053	if (!mls_enabled)
2054		return (0);
2055
2056	subj = SLOT(cred->cr_label);
2057	obj = SLOT(semaklabel);
2058
2059	switch(cmd) {
2060	case IPC_RMID:
2061	case IPC_SET:
2062	case SETVAL:
2063	case SETALL:
2064		if (!mls_dominate_effective(obj, subj))
2065			return (EACCES);
2066		break;
2067
2068	case IPC_STAT:
2069	case GETVAL:
2070	case GETPID:
2071	case GETNCNT:
2072	case GETZCNT:
2073	case GETALL:
2074		if (!mls_dominate_effective(subj, obj))
2075			return (EACCES);
2076		break;
2077
2078	default:
2079		return (EACCES);
2080	}
2081
2082	return (0);
2083}
2084
2085static int
2086mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2087    struct label *semaklabel)
2088{
2089	struct mac_mls *subj, *obj;
2090
2091	if (!mls_enabled)
2092		return (0);
2093
2094	subj = SLOT(cred->cr_label);
2095	obj = SLOT(semaklabel);
2096
2097	if (!mls_dominate_effective(subj, obj))
2098		return (EACCES);
2099
2100	return (0);
2101}
2102
2103static int
2104mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2105    struct label *semaklabel, size_t accesstype)
2106{
2107	struct mac_mls *subj, *obj;
2108
2109	if (!mls_enabled)
2110		return (0);
2111
2112	subj = SLOT(cred->cr_label);
2113	obj = SLOT(semaklabel);
2114
2115	if( accesstype & SEM_R )
2116		if (!mls_dominate_effective(subj, obj))
2117			return (EACCES);
2118
2119	if( accesstype & SEM_A )
2120		if (!mls_dominate_effective(obj, subj))
2121			return (EACCES);
2122
2123	return (0);
2124}
2125
2126static void
2127mls_sysvsem_cleanup(struct label *semalabel)
2128{
2129
2130	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2131}
2132
2133static void
2134mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2135    struct label *semalabel)
2136{
2137	struct mac_mls *source, *dest;
2138
2139	source = SLOT(cred->cr_label);
2140	dest = SLOT(semalabel);
2141
2142	mls_copy_effective(source, dest);
2143}
2144
2145static int
2146mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2147    struct label *shmseglabel, int shmflg)
2148{
2149	struct mac_mls *subj, *obj;
2150
2151	if (!mls_enabled)
2152		return (0);
2153
2154	subj = SLOT(cred->cr_label);
2155	obj = SLOT(shmseglabel);
2156
2157	if (!mls_dominate_effective(subj, obj))
2158		return (EACCES);
2159	if ((shmflg & SHM_RDONLY) == 0) {
2160		if (!mls_dominate_effective(obj, subj))
2161			return (EACCES);
2162	}
2163
2164	return (0);
2165}
2166
2167static int
2168mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2169    struct label *shmseglabel, int cmd)
2170{
2171	struct mac_mls *subj, *obj;
2172
2173	if (!mls_enabled)
2174		return (0);
2175
2176	subj = SLOT(cred->cr_label);
2177	obj = SLOT(shmseglabel);
2178
2179	switch(cmd) {
2180	case IPC_RMID:
2181	case IPC_SET:
2182		if (!mls_dominate_effective(obj, subj))
2183			return (EACCES);
2184		break;
2185
2186	case IPC_STAT:
2187	case SHM_STAT:
2188		if (!mls_dominate_effective(subj, obj))
2189			return (EACCES);
2190		break;
2191
2192	default:
2193		return (EACCES);
2194	}
2195
2196	return (0);
2197}
2198
2199static int
2200mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2201    struct label *shmseglabel, int shmflg)
2202{
2203	struct mac_mls *subj, *obj;
2204
2205	if (!mls_enabled)
2206		return (0);
2207
2208	subj = SLOT(cred->cr_label);
2209	obj = SLOT(shmseglabel);
2210
2211	if (!mls_dominate_effective(obj, subj))
2212		return (EACCES);
2213
2214	return (0);
2215}
2216
2217static void
2218mls_sysvshm_cleanup(struct label *shmlabel)
2219{
2220
2221	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2222}
2223
2224static void
2225mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2226    struct label *shmlabel)
2227{
2228	struct mac_mls *source, *dest;
2229
2230	source = SLOT(cred->cr_label);
2231	dest = SLOT(shmlabel);
2232
2233	mls_copy_effective(source, dest);
2234}
2235
2236static int
2237mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2238    struct vnode *vp, struct label *vplabel)
2239{
2240	struct mac_mls mm_temp, *source, *dest;
2241	int buflen, error;
2242
2243	source = SLOT(mplabel);
2244	dest = SLOT(vplabel);
2245
2246	buflen = sizeof(mm_temp);
2247	bzero(&mm_temp, buflen);
2248
2249	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2250	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2251	if (error == ENOATTR || error == EOPNOTSUPP) {
2252		/* Fall back to the mntlabel. */
2253		mls_copy_effective(source, dest);
2254		return (0);
2255	} else if (error)
2256		return (error);
2257
2258	if (buflen != sizeof(mm_temp)) {
2259		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2260		return (EPERM);
2261	}
2262	if (mls_valid(&mm_temp) != 0) {
2263		printf("mls_vnode_associate_extattr: invalid\n");
2264		return (EPERM);
2265	}
2266	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2267	    MAC_MLS_FLAG_EFFECTIVE) {
2268		printf("mls_associated_vnode_extattr: not effective\n");
2269		return (EPERM);
2270	}
2271
2272	mls_copy_effective(&mm_temp, dest);
2273	return (0);
2274}
2275
2276static void
2277mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2278    struct vnode *vp, struct label *vplabel)
2279{
2280	struct mac_mls *source, *dest;
2281
2282	source = SLOT(mplabel);
2283	dest = SLOT(vplabel);
2284
2285	mls_copy_effective(source, dest);
2286}
2287
2288static int
2289mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2290    struct label *dvplabel)
2291{
2292	struct mac_mls *subj, *obj;
2293
2294	if (!mls_enabled)
2295		return (0);
2296
2297	subj = SLOT(cred->cr_label);
2298	obj = SLOT(dvplabel);
2299
2300	if (!mls_dominate_effective(subj, obj))
2301		return (EACCES);
2302
2303	return (0);
2304}
2305
2306static int
2307mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2308    struct label *dvplabel)
2309{
2310	struct mac_mls *subj, *obj;
2311
2312	if (!mls_enabled)
2313		return (0);
2314
2315	subj = SLOT(cred->cr_label);
2316	obj = SLOT(dvplabel);
2317
2318	if (!mls_dominate_effective(subj, obj))
2319		return (EACCES);
2320
2321	return (0);
2322}
2323
2324static int
2325mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2326    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2327{
2328	struct mac_mls *subj, *obj;
2329
2330	if (!mls_enabled)
2331		return (0);
2332
2333	subj = SLOT(cred->cr_label);
2334	obj = SLOT(dvplabel);
2335
2336	if (!mls_dominate_effective(obj, subj))
2337		return (EACCES);
2338
2339	return (0);
2340}
2341
2342static int
2343mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2344    struct label *vplabel, acl_type_t type)
2345{
2346	struct mac_mls *subj, *obj;
2347
2348	if (!mls_enabled)
2349		return (0);
2350
2351	subj = SLOT(cred->cr_label);
2352	obj = SLOT(vplabel);
2353
2354	if (!mls_dominate_effective(obj, subj))
2355		return (EACCES);
2356
2357	return (0);
2358}
2359
2360static int
2361mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2362    struct label *vplabel, int attrnamespace, const char *name)
2363{
2364	struct mac_mls *subj, *obj;
2365
2366	if (!mls_enabled)
2367		return (0);
2368
2369	subj = SLOT(cred->cr_label);
2370	obj = SLOT(vplabel);
2371
2372	if (!mls_dominate_effective(obj, subj))
2373		return (EACCES);
2374
2375	return (0);
2376}
2377
2378static int
2379mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2380    struct label *vplabel, struct image_params *imgp,
2381    struct label *execlabel)
2382{
2383	struct mac_mls *subj, *obj, *exec;
2384	int error;
2385
2386	if (execlabel != NULL) {
2387		/*
2388		 * We currently don't permit labels to be changed at
2389		 * exec-time as part of MLS, so disallow non-NULL MLS label
2390		 * elements in the execlabel.
2391		 */
2392		exec = SLOT(execlabel);
2393		error = mls_atmostflags(exec, 0);
2394		if (error)
2395			return (error);
2396	}
2397
2398	if (!mls_enabled)
2399		return (0);
2400
2401	subj = SLOT(cred->cr_label);
2402	obj = SLOT(vplabel);
2403
2404	if (!mls_dominate_effective(subj, obj))
2405		return (EACCES);
2406
2407	return (0);
2408}
2409
2410static int
2411mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2412    struct label *vplabel, acl_type_t type)
2413{
2414	struct mac_mls *subj, *obj;
2415
2416	if (!mls_enabled)
2417		return (0);
2418
2419	subj = SLOT(cred->cr_label);
2420	obj = SLOT(vplabel);
2421
2422	if (!mls_dominate_effective(subj, obj))
2423		return (EACCES);
2424
2425	return (0);
2426}
2427
2428static int
2429mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2430    struct label *vplabel, int attrnamespace, const char *name)
2431{
2432	struct mac_mls *subj, *obj;
2433
2434	if (!mls_enabled)
2435		return (0);
2436
2437	subj = SLOT(cred->cr_label);
2438	obj = SLOT(vplabel);
2439
2440	if (!mls_dominate_effective(subj, obj))
2441		return (EACCES);
2442
2443	return (0);
2444}
2445
2446static int
2447mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2448    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2449    struct componentname *cnp)
2450{
2451	struct mac_mls *subj, *obj;
2452
2453	if (!mls_enabled)
2454		return (0);
2455
2456	subj = SLOT(cred->cr_label);
2457	obj = SLOT(dvplabel);
2458
2459	if (!mls_dominate_effective(obj, subj))
2460		return (EACCES);
2461
2462	obj = SLOT(vplabel);
2463	if (!mls_dominate_effective(obj, subj))
2464		return (EACCES);
2465
2466	return (0);
2467}
2468
2469static int
2470mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
2471    struct label *vplabel, int attrnamespace)
2472{
2473
2474	struct mac_mls *subj, *obj;
2475
2476	if (!mls_enabled)
2477		return (0);
2478
2479	subj = SLOT(cred->cr_label);
2480	obj = SLOT(vplabel);
2481
2482	if (!mls_dominate_effective(subj, obj))
2483		return (EACCES);
2484
2485	return (0);
2486}
2487
2488static int
2489mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
2490    struct label *dvplabel, struct componentname *cnp)
2491{
2492	struct mac_mls *subj, *obj;
2493
2494	if (!mls_enabled)
2495		return (0);
2496
2497	subj = SLOT(cred->cr_label);
2498	obj = SLOT(dvplabel);
2499
2500	if (!mls_dominate_effective(subj, obj))
2501		return (EACCES);
2502
2503	return (0);
2504}
2505
2506static int
2507mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2508    struct label *vplabel, int prot, int flags)
2509{
2510	struct mac_mls *subj, *obj;
2511
2512	/*
2513	 * Rely on the use of open()-time protections to handle
2514	 * non-revocation cases.
2515	 */
2516	if (!mls_enabled || !revocation_enabled)
2517		return (0);
2518
2519	subj = SLOT(cred->cr_label);
2520	obj = SLOT(vplabel);
2521
2522	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2523		if (!mls_dominate_effective(subj, obj))
2524			return (EACCES);
2525	}
2526	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2527		if (!mls_dominate_effective(obj, subj))
2528			return (EACCES);
2529	}
2530
2531	return (0);
2532}
2533
2534static int
2535mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
2536    struct label *vplabel, accmode_t accmode)
2537{
2538	struct mac_mls *subj, *obj;
2539
2540	if (!mls_enabled)
2541		return (0);
2542
2543	subj = SLOT(cred->cr_label);
2544	obj = SLOT(vplabel);
2545
2546	/* XXX privilege override for admin? */
2547	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
2548		if (!mls_dominate_effective(subj, obj))
2549			return (EACCES);
2550	}
2551	if (accmode & VMODIFY_PERMS) {
2552		if (!mls_dominate_effective(obj, subj))
2553			return (EACCES);
2554	}
2555
2556	return (0);
2557}
2558
2559static int
2560mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
2561    struct vnode *vp, struct label *vplabel)
2562{
2563	struct mac_mls *subj, *obj;
2564
2565	if (!mls_enabled || !revocation_enabled)
2566		return (0);
2567
2568	subj = SLOT(active_cred->cr_label);
2569	obj = SLOT(vplabel);
2570
2571	if (!mls_dominate_effective(subj, obj))
2572		return (EACCES);
2573
2574	return (0);
2575}
2576
2577static int
2578mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2579    struct vnode *vp, struct label *vplabel)
2580{
2581	struct mac_mls *subj, *obj;
2582
2583	if (!mls_enabled || !revocation_enabled)
2584		return (0);
2585
2586	subj = SLOT(active_cred->cr_label);
2587	obj = SLOT(vplabel);
2588
2589	if (!mls_dominate_effective(subj, obj))
2590		return (EACCES);
2591
2592	return (0);
2593}
2594
2595static int
2596mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
2597    struct label *dvplabel)
2598{
2599	struct mac_mls *subj, *obj;
2600
2601	if (!mls_enabled)
2602		return (0);
2603
2604	subj = SLOT(cred->cr_label);
2605	obj = SLOT(dvplabel);
2606
2607	if (!mls_dominate_effective(subj, obj))
2608		return (EACCES);
2609
2610	return (0);
2611}
2612
2613static int
2614mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
2615    struct label *vplabel)
2616{
2617	struct mac_mls *subj, *obj;
2618
2619	if (!mls_enabled)
2620		return (0);
2621
2622	subj = SLOT(cred->cr_label);
2623	obj = SLOT(vplabel);
2624
2625	if (!mls_dominate_effective(subj, obj))
2626		return (EACCES);
2627
2628	return (0);
2629}
2630
2631static int
2632mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2633    struct label *vplabel, struct label *newlabel)
2634{
2635	struct mac_mls *old, *new, *subj;
2636	int error;
2637
2638	old = SLOT(vplabel);
2639	new = SLOT(newlabel);
2640	subj = SLOT(cred->cr_label);
2641
2642	/*
2643	 * If there is an MLS label update for the vnode, it must be a
2644	 * effective label.
2645	 */
2646	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2647	if (error)
2648		return (error);
2649
2650	/*
2651	 * To perform a relabel of the vnode (MLS label or not), MLS must
2652	 * authorize the relabel.
2653	 */
2654	if (!mls_effective_in_range(old, subj))
2655		return (EPERM);
2656
2657	/*
2658	 * If the MLS label is to be changed, authorize as appropriate.
2659	 */
2660	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2661		/*
2662		 * To change the MLS label on a vnode, the new vnode label
2663		 * must be in the subject range.
2664		 */
2665		if (!mls_effective_in_range(new, subj))
2666			return (EPERM);
2667
2668		/*
2669		 * To change the MLS label on the vnode to be EQUAL, the
2670		 * subject must have appropriate privilege.
2671		 */
2672		if (mls_contains_equal(new)) {
2673			error = mls_subject_privileged(subj);
2674			if (error)
2675				return (error);
2676		}
2677	}
2678
2679	return (0);
2680}
2681
2682static int
2683mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2684    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2685    struct componentname *cnp)
2686{
2687	struct mac_mls *subj, *obj;
2688
2689	if (!mls_enabled)
2690		return (0);
2691
2692	subj = SLOT(cred->cr_label);
2693	obj = SLOT(dvplabel);
2694
2695	if (!mls_dominate_effective(obj, subj))
2696		return (EACCES);
2697
2698	obj = SLOT(vplabel);
2699
2700	if (!mls_dominate_effective(obj, subj))
2701		return (EACCES);
2702
2703	return (0);
2704}
2705
2706static int
2707mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2708    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2709    int samedir, struct componentname *cnp)
2710{
2711	struct mac_mls *subj, *obj;
2712
2713	if (!mls_enabled)
2714		return (0);
2715
2716	subj = SLOT(cred->cr_label);
2717	obj = SLOT(dvplabel);
2718
2719	if (!mls_dominate_effective(obj, subj))
2720		return (EACCES);
2721
2722	if (vp != NULL) {
2723		obj = SLOT(vplabel);
2724
2725		if (!mls_dominate_effective(obj, subj))
2726			return (EACCES);
2727	}
2728
2729	return (0);
2730}
2731
2732static int
2733mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2734    struct label *vplabel)
2735{
2736	struct mac_mls *subj, *obj;
2737
2738	if (!mls_enabled)
2739		return (0);
2740
2741	subj = SLOT(cred->cr_label);
2742	obj = SLOT(vplabel);
2743
2744	if (!mls_dominate_effective(obj, subj))
2745		return (EACCES);
2746
2747	return (0);
2748}
2749
2750static int
2751mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2752    struct label *vplabel, acl_type_t type, struct acl *acl)
2753{
2754	struct mac_mls *subj, *obj;
2755
2756	if (!mls_enabled)
2757		return (0);
2758
2759	subj = SLOT(cred->cr_label);
2760	obj = SLOT(vplabel);
2761
2762	if (!mls_dominate_effective(obj, subj))
2763		return (EACCES);
2764
2765	return (0);
2766}
2767
2768static int
2769mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2770    struct label *vplabel, int attrnamespace, const char *name)
2771{
2772	struct mac_mls *subj, *obj;
2773
2774	if (!mls_enabled)
2775		return (0);
2776
2777	subj = SLOT(cred->cr_label);
2778	obj = SLOT(vplabel);
2779
2780	if (!mls_dominate_effective(obj, subj))
2781		return (EACCES);
2782
2783	/* XXX: protect the MAC EA in a special way? */
2784
2785	return (0);
2786}
2787
2788static int
2789mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2790    struct label *vplabel, u_long flags)
2791{
2792	struct mac_mls *subj, *obj;
2793
2794	if (!mls_enabled)
2795		return (0);
2796
2797	subj = SLOT(cred->cr_label);
2798	obj = SLOT(vplabel);
2799
2800	if (!mls_dominate_effective(obj, subj))
2801		return (EACCES);
2802
2803	return (0);
2804}
2805
2806static int
2807mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2808    struct label *vplabel, mode_t mode)
2809{
2810	struct mac_mls *subj, *obj;
2811
2812	if (!mls_enabled)
2813		return (0);
2814
2815	subj = SLOT(cred->cr_label);
2816	obj = SLOT(vplabel);
2817
2818	if (!mls_dominate_effective(obj, subj))
2819		return (EACCES);
2820
2821	return (0);
2822}
2823
2824static int
2825mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2826    struct label *vplabel, uid_t uid, gid_t gid)
2827{
2828	struct mac_mls *subj, *obj;
2829
2830	if (!mls_enabled)
2831		return (0);
2832
2833	subj = SLOT(cred->cr_label);
2834	obj = SLOT(vplabel);
2835
2836	if (!mls_dominate_effective(obj, subj))
2837		return (EACCES);
2838
2839	return (0);
2840}
2841
2842static int
2843mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2844    struct label *vplabel, struct timespec atime, struct timespec mtime)
2845{
2846	struct mac_mls *subj, *obj;
2847
2848	if (!mls_enabled)
2849		return (0);
2850
2851	subj = SLOT(cred->cr_label);
2852	obj = SLOT(vplabel);
2853
2854	if (!mls_dominate_effective(obj, subj))
2855		return (EACCES);
2856
2857	return (0);
2858}
2859
2860static int
2861mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
2862    struct vnode *vp, struct label *vplabel)
2863{
2864	struct mac_mls *subj, *obj;
2865
2866	if (!mls_enabled)
2867		return (0);
2868
2869	subj = SLOT(active_cred->cr_label);
2870	obj = SLOT(vplabel);
2871
2872	if (!mls_dominate_effective(subj, obj))
2873		return (EACCES);
2874
2875	return (0);
2876}
2877
2878static int
2879mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2880    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2881    struct componentname *cnp)
2882{
2883	struct mac_mls *subj, *obj;
2884
2885	if (!mls_enabled)
2886		return (0);
2887
2888	subj = SLOT(cred->cr_label);
2889	obj = SLOT(dvplabel);
2890
2891	if (!mls_dominate_effective(obj, subj))
2892		return (EACCES);
2893
2894	obj = SLOT(vplabel);
2895
2896	if (!mls_dominate_effective(obj, subj))
2897		return (EACCES);
2898
2899	return (0);
2900}
2901
2902static int
2903mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
2904    struct vnode *vp, struct label *vplabel)
2905{
2906	struct mac_mls *subj, *obj;
2907
2908	if (!mls_enabled || !revocation_enabled)
2909		return (0);
2910
2911	subj = SLOT(active_cred->cr_label);
2912	obj = SLOT(vplabel);
2913
2914	if (!mls_dominate_effective(obj, subj))
2915		return (EACCES);
2916
2917	return (0);
2918}
2919
2920static int
2921mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2922    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2923    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2924{
2925	struct mac_mls *source, *dest, mm_temp;
2926	size_t buflen;
2927	int error;
2928
2929	buflen = sizeof(mm_temp);
2930	bzero(&mm_temp, buflen);
2931
2932	source = SLOT(cred->cr_label);
2933	dest = SLOT(vplabel);
2934	mls_copy_effective(source, &mm_temp);
2935
2936	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2937	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2938	if (error == 0)
2939		mls_copy_effective(source, dest);
2940	return (error);
2941}
2942
2943static void
2944mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
2945    struct label *vplabel, struct label *label)
2946{
2947	struct mac_mls *source, *dest;
2948
2949	source = SLOT(label);
2950	dest = SLOT(vplabel);
2951
2952	mls_copy(source, dest);
2953}
2954
2955static int
2956mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2957    struct label *vplabel, struct label *intlabel)
2958{
2959	struct mac_mls *source, mm_temp;
2960	size_t buflen;
2961	int error;
2962
2963	buflen = sizeof(mm_temp);
2964	bzero(&mm_temp, buflen);
2965
2966	source = SLOT(intlabel);
2967	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
2968		return (0);
2969
2970	mls_copy_effective(source, &mm_temp);
2971
2972	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2973	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
2974	return (error);
2975}
2976
2977static struct mac_policy_ops mls_ops =
2978{
2979	.mpo_init = mls_init,
2980
2981	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
2982	.mpo_bpfdesc_create = mls_bpfdesc_create,
2983	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
2984	.mpo_bpfdesc_destroy_label = mls_destroy_label,
2985	.mpo_bpfdesc_init_label = mls_init_label,
2986
2987	.mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
2988	.mpo_cred_check_relabel = mls_cred_check_relabel,
2989	.mpo_cred_check_visible = mls_cred_check_visible,
2990	.mpo_cred_copy_label = mls_copy_label,
2991	.mpo_cred_create_init = mls_cred_create_init,
2992	.mpo_cred_create_swapper = mls_cred_create_swapper,
2993	.mpo_cred_destroy_label = mls_destroy_label,
2994	.mpo_cred_externalize_label = mls_externalize_label,
2995	.mpo_cred_init_label = mls_init_label,
2996	.mpo_cred_internalize_label = mls_internalize_label,
2997	.mpo_cred_relabel = mls_cred_relabel,
2998
2999	.mpo_devfs_create_device = mls_devfs_create_device,
3000	.mpo_devfs_create_directory = mls_devfs_create_directory,
3001	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
3002	.mpo_devfs_destroy_label = mls_destroy_label,
3003	.mpo_devfs_init_label = mls_init_label,
3004	.mpo_devfs_update = mls_devfs_update,
3005	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3006
3007	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
3008	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3009	.mpo_ifnet_copy_label = mls_copy_label,
3010	.mpo_ifnet_create = mls_ifnet_create,
3011	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3012	.mpo_ifnet_destroy_label = mls_destroy_label,
3013	.mpo_ifnet_externalize_label = mls_externalize_label,
3014	.mpo_ifnet_init_label = mls_init_label,
3015	.mpo_ifnet_internalize_label = mls_internalize_label,
3016	.mpo_ifnet_relabel = mls_ifnet_relabel,
3017
3018	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
3019	.mpo_inpcb_check_visible = mls_inpcb_check_visible,
3020	.mpo_inpcb_create = mls_inpcb_create,
3021	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3022	.mpo_inpcb_destroy_label = mls_destroy_label,
3023	.mpo_inpcb_init_label = mls_init_label_waitcheck,
3024	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3025
3026	.mpo_ip6q_create = mls_ip6q_create,
3027	.mpo_ip6q_destroy_label = mls_destroy_label,
3028	.mpo_ip6q_init_label = mls_init_label_waitcheck,
3029	.mpo_ip6q_match = mls_ip6q_match,
3030	.mpo_ip6q_reassemble = mls_ip6q_reassemble,
3031	.mpo_ip6q_update = mls_ip6q_update,
3032
3033	.mpo_ipq_create = mls_ipq_create,
3034	.mpo_ipq_destroy_label = mls_destroy_label,
3035	.mpo_ipq_init_label = mls_init_label_waitcheck,
3036	.mpo_ipq_match = mls_ipq_match,
3037	.mpo_ipq_reassemble = mls_ipq_reassemble,
3038	.mpo_ipq_update = mls_ipq_update,
3039
3040	.mpo_mbuf_copy_label = mls_copy_label,
3041	.mpo_mbuf_destroy_label = mls_destroy_label,
3042	.mpo_mbuf_init_label = mls_init_label_waitcheck,
3043
3044	.mpo_mount_check_stat = mls_mount_check_stat,
3045	.mpo_mount_create = mls_mount_create,
3046	.mpo_mount_destroy_label = mls_destroy_label,
3047	.mpo_mount_init_label = mls_init_label,
3048
3049	.mpo_netatalk_aarp_send = mls_netatalk_aarp_send,
3050
3051	.mpo_netinet_arp_send = mls_netinet_arp_send,
3052	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3053	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
3054	.mpo_netinet_fragment = mls_netinet_fragment,
3055	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3056	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
3057
3058	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3059
3060	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
3061	.mpo_pipe_check_poll = mls_pipe_check_poll,
3062	.mpo_pipe_check_read = mls_pipe_check_read,
3063	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
3064	.mpo_pipe_check_stat = mls_pipe_check_stat,
3065	.mpo_pipe_check_write = mls_pipe_check_write,
3066	.mpo_pipe_copy_label = mls_copy_label,
3067	.mpo_pipe_create = mls_pipe_create,
3068	.mpo_pipe_destroy_label = mls_destroy_label,
3069	.mpo_pipe_externalize_label = mls_externalize_label,
3070	.mpo_pipe_init_label = mls_init_label,
3071	.mpo_pipe_internalize_label = mls_internalize_label,
3072	.mpo_pipe_relabel = mls_pipe_relabel,
3073
3074	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
3075	.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
3076	.mpo_posixsem_check_post = mls_posixsem_check_write,
3077	.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
3078	.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
3079	.mpo_posixsem_check_wait = mls_posixsem_check_write,
3080	.mpo_posixsem_create = mls_posixsem_create,
3081	.mpo_posixsem_destroy_label = mls_destroy_label,
3082	.mpo_posixsem_init_label = mls_init_label,
3083
3084	.mpo_proc_check_debug = mls_proc_check_debug,
3085	.mpo_proc_check_sched = mls_proc_check_sched,
3086	.mpo_proc_check_signal = mls_proc_check_signal,
3087
3088	.mpo_socket_check_deliver = mls_socket_check_deliver,
3089	.mpo_socket_check_relabel = mls_socket_check_relabel,
3090	.mpo_socket_check_visible = mls_socket_check_visible,
3091	.mpo_socket_copy_label = mls_copy_label,
3092	.mpo_socket_create = mls_socket_create,
3093	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
3094	.mpo_socket_destroy_label = mls_destroy_label,
3095	.mpo_socket_externalize_label = mls_externalize_label,
3096	.mpo_socket_init_label = mls_init_label_waitcheck,
3097	.mpo_socket_internalize_label = mls_internalize_label,
3098	.mpo_socket_newconn = mls_socket_newconn,
3099	.mpo_socket_relabel = mls_socket_relabel,
3100
3101	.mpo_socketpeer_destroy_label = mls_destroy_label,
3102	.mpo_socketpeer_externalize_label = mls_externalize_label,
3103	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
3104	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3105	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3106
3107	.mpo_syncache_create = mls_syncache_create,
3108	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3109	.mpo_syncache_destroy_label = mls_destroy_label,
3110	.mpo_syncache_init_label = mls_init_label_waitcheck,
3111
3112	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3113	.mpo_sysvmsg_create = mls_sysvmsg_create,
3114	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3115	.mpo_sysvmsg_init_label = mls_init_label,
3116
3117	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3118	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3119	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3120	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3121	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3122	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3123	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3124	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3125	.mpo_sysvmsq_init_label = mls_init_label,
3126	.mpo_sysvmsq_create = mls_sysvmsq_create,
3127
3128	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3129	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3130	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3131	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3132	.mpo_sysvsem_create = mls_sysvsem_create,
3133	.mpo_sysvsem_destroy_label = mls_destroy_label,
3134	.mpo_sysvsem_init_label = mls_init_label,
3135
3136	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3137	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3138	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3139	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3140	.mpo_sysvshm_create = mls_sysvshm_create,
3141	.mpo_sysvshm_destroy_label = mls_destroy_label,
3142	.mpo_sysvshm_init_label = mls_init_label,
3143
3144
3145	.mpo_system_check_acct = mls_system_check_acct,
3146	.mpo_system_check_auditctl = mls_system_check_auditctl,
3147	.mpo_system_check_swapon = mls_system_check_swapon,
3148
3149	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3150	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
3151	.mpo_vnode_check_access = mls_vnode_check_open,
3152	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
3153	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
3154	.mpo_vnode_check_create = mls_vnode_check_create,
3155	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
3156	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
3157	.mpo_vnode_check_exec = mls_vnode_check_exec,
3158	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
3159	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
3160	.mpo_vnode_check_link = mls_vnode_check_link,
3161	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
3162	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
3163	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
3164	.mpo_vnode_check_open = mls_vnode_check_open,
3165	.mpo_vnode_check_poll = mls_vnode_check_poll,
3166	.mpo_vnode_check_read = mls_vnode_check_read,
3167	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
3168	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
3169	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
3170	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
3171	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
3172	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
3173	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
3174	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
3175	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
3176	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
3177	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
3178	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
3179	.mpo_vnode_check_stat = mls_vnode_check_stat,
3180	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
3181	.mpo_vnode_check_write = mls_vnode_check_write,
3182	.mpo_vnode_copy_label = mls_copy_label,
3183	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3184	.mpo_vnode_destroy_label = mls_destroy_label,
3185	.mpo_vnode_externalize_label = mls_externalize_label,
3186	.mpo_vnode_init_label = mls_init_label,
3187	.mpo_vnode_internalize_label = mls_internalize_label,
3188	.mpo_vnode_relabel = mls_vnode_relabel,
3189	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3190};
3191
3192MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
3193    MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);
3194