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