xref: /freebsd-src/sys/security/mac_mls/mac_mls.c (revision db33c6f3ae9d1231087710068ee4ea5398aacca7)
1d8a7b7a3SRobert Watson /*-
29b6dd12eSRobert Watson  * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
382d16d5eSRobert Watson  * Copyright (c) 2001-2005 McAfee, Inc.
430d239bcSRobert Watson  * Copyright (c) 2006 SPARTA, Inc.
5d8a7b7a3SRobert Watson  * All rights reserved.
6d8a7b7a3SRobert Watson  *
7d8a7b7a3SRobert Watson  * This software was developed by Robert Watson for the TrustedBSD Project.
8d8a7b7a3SRobert Watson  *
982d16d5eSRobert Watson  * This software was developed for the FreeBSD Project in part by McAfee
1082d16d5eSRobert Watson  * Research, the Security Research Division of McAfee, Inc. under
1182d16d5eSRobert Watson  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
1282d16d5eSRobert Watson  * CHATS research program.
13d8a7b7a3SRobert Watson  *
1430d239bcSRobert Watson  * This software was enhanced by SPARTA ISSO under SPAWAR contract
1530d239bcSRobert Watson  * N66001-04-C-6019 ("SEFOS").
1630d239bcSRobert Watson  *
179b6dd12eSRobert Watson  * This software was developed at the University of Cambridge Computer
189b6dd12eSRobert Watson  * Laboratory with support from a grant from Google, Inc.
199b6dd12eSRobert Watson  *
20d8a7b7a3SRobert Watson  * Redistribution and use in source and binary forms, with or without
21d8a7b7a3SRobert Watson  * modification, are permitted provided that the following conditions
22d8a7b7a3SRobert Watson  * are met:
23d8a7b7a3SRobert Watson  * 1. Redistributions of source code must retain the above copyright
24d8a7b7a3SRobert Watson  *    notice, this list of conditions and the following disclaimer.
25d8a7b7a3SRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
26d8a7b7a3SRobert Watson  *    notice, this list of conditions and the following disclaimer in the
27d8a7b7a3SRobert Watson  *    documentation and/or other materials provided with the distribution.
28d8a7b7a3SRobert Watson  *
29d8a7b7a3SRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30d8a7b7a3SRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31d8a7b7a3SRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32d8a7b7a3SRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33d8a7b7a3SRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34d8a7b7a3SRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35d8a7b7a3SRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36d8a7b7a3SRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37d8a7b7a3SRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38d8a7b7a3SRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39d8a7b7a3SRobert Watson  * SUCH DAMAGE.
40d8a7b7a3SRobert Watson  */
41d8a7b7a3SRobert Watson 
42d8a7b7a3SRobert Watson /*
43d8a7b7a3SRobert Watson  * Developed by the TrustedBSD Project.
4430575990SRobert Watson  *
45d8a7b7a3SRobert Watson  * MLS fixed label mandatory confidentiality policy.
46d8a7b7a3SRobert Watson  */
47d8a7b7a3SRobert Watson 
48d8a7b7a3SRobert Watson #include <sys/types.h>
49d8a7b7a3SRobert Watson #include <sys/param.h>
50d8a7b7a3SRobert Watson #include <sys/acl.h>
51d8a7b7a3SRobert Watson #include <sys/conf.h>
52763bbd2fSRobert Watson #include <sys/extattr.h>
53d8a7b7a3SRobert Watson #include <sys/kernel.h>
546aeb05d7STom Rhodes #include <sys/ksem.h>
55c92163dcSChristian S.J. Peron #include <sys/mman.h>
56cebf9431SBruce Evans #include <sys/malloc.h>
57d8a7b7a3SRobert Watson #include <sys/mount.h>
58d8a7b7a3SRobert Watson #include <sys/proc.h>
5905e830f1SRobert Watson #include <sys/sbuf.h>
60d8a7b7a3SRobert Watson #include <sys/systm.h>
61d8a7b7a3SRobert Watson #include <sys/sysproto.h>
62d8a7b7a3SRobert Watson #include <sys/sysent.h>
6324e8d0d0SRobert Watson #include <sys/systm.h>
64d8a7b7a3SRobert Watson #include <sys/vnode.h>
65d8a7b7a3SRobert Watson #include <sys/file.h>
66d8a7b7a3SRobert Watson #include <sys/socket.h>
67d8a7b7a3SRobert Watson #include <sys/socketvar.h>
68d8a7b7a3SRobert Watson #include <sys/pipe.h>
6936422989SPoul-Henning Kamp #include <sys/sx.h>
70d8a7b7a3SRobert Watson #include <sys/sysctl.h>
7182d16d5eSRobert Watson #include <sys/msg.h>
7282d16d5eSRobert Watson #include <sys/sem.h>
7382d16d5eSRobert Watson #include <sys/shm.h>
74d8a7b7a3SRobert Watson 
75d8a7b7a3SRobert Watson #include <fs/devfs/devfs.h>
76d8a7b7a3SRobert Watson 
77d8a7b7a3SRobert Watson #include <net/bpfdesc.h>
78d8a7b7a3SRobert Watson #include <net/if.h>
79d8a7b7a3SRobert Watson #include <net/if_types.h>
80d8a7b7a3SRobert Watson #include <net/if_var.h>
81d8a7b7a3SRobert Watson 
82d8a7b7a3SRobert Watson #include <netinet/in.h>
83a557af22SRobert Watson #include <netinet/in_pcb.h>
84d8a7b7a3SRobert Watson #include <netinet/ip_var.h>
85d8a7b7a3SRobert Watson 
862e8c6b26SRobert Watson #include <vm/uma.h>
87d8a7b7a3SRobert Watson #include <vm/vm.h>
88d8a7b7a3SRobert Watson 
890efd6615SRobert Watson #include <security/mac/mac_policy.h>
90d8a7b7a3SRobert Watson #include <security/mac_mls/mac_mls.h>
91d8a7b7a3SRobert Watson 
927029da5cSPawel Biernacki static SYSCTL_NODE(_security_mac, OID_AUTO, mls,
937029da5cSPawel Biernacki     CTLFLAG_RW | CTLFLAG_MPSAFE, 0,
94d8a7b7a3SRobert Watson     "TrustedBSD mac_mls policy controls");
95d8a7b7a3SRobert Watson 
963f1a7a90SRobert Watson static int	mls_label_size = sizeof(struct mac_mls);
97763bbd2fSRobert Watson SYSCTL_INT(_security_mac_mls, OID_AUTO, label_size, CTLFLAG_RD,
983f1a7a90SRobert Watson     &mls_label_size, 0, "Size of struct mac_mls");
99763bbd2fSRobert Watson 
1003f1a7a90SRobert Watson static int	mls_enabled = 1;
101af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_mls, OID_AUTO, enabled, CTLFLAG_RWTUN, &mls_enabled, 0,
1023f1a7a90SRobert Watson     "Enforce MAC/MLS policy");
103d8a7b7a3SRobert Watson 
104d8a7b7a3SRobert Watson static int	destroyed_not_inited;
105d8a7b7a3SRobert Watson SYSCTL_INT(_security_mac_mls, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
106d8a7b7a3SRobert Watson     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
107d8a7b7a3SRobert Watson 
1080b9b85b9SRobert Watson static int	ptys_equal = 0;
109af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_mls, OID_AUTO, ptys_equal, CTLFLAG_RWTUN,
1100b9b85b9SRobert Watson     &ptys_equal, 0, "Label pty devices as mls/equal on create");
1110b9b85b9SRobert Watson 
112b382fe89SRobert Watson static int	revocation_enabled = 0;
113af3b2549SHans Petter Selasky SYSCTL_INT(_security_mac_mls, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN,
114b382fe89SRobert Watson     &revocation_enabled, 0, "Revoke access to objects on relabel");
115d8a7b7a3SRobert Watson 
1162a1c79afSRobert Watson static int	max_compartments = MAC_MLS_MAX_COMPARTMENTS;
1172a1c79afSRobert Watson SYSCTL_INT(_security_mac_mls, OID_AUTO, max_compartments, CTLFLAG_RD,
1182a1c79afSRobert Watson     &max_compartments, 0, "Maximum compartments the policy supports");
1192a1c79afSRobert Watson 
1203f1a7a90SRobert Watson static int	mls_slot;
1213f1a7a90SRobert Watson #define	SLOT(l)	((struct mac_mls *)mac_label_get((l), mls_slot))
1223f1a7a90SRobert Watson #define	SLOT_SET(l, val) mac_label_set((l), mls_slot, (uintptr_t)(val))
123d8a7b7a3SRobert Watson 
1242e8c6b26SRobert Watson static uma_zone_t	zone_mls;
125d8a7b7a3SRobert Watson 
1262a1c79afSRobert Watson static __inline int
1272a1c79afSRobert Watson mls_bit_set_empty(u_char *set) {
1282a1c79afSRobert Watson 	int i;
1292a1c79afSRobert Watson 
1302a1c79afSRobert Watson 	for (i = 0; i < MAC_MLS_MAX_COMPARTMENTS >> 3; i++)
1312a1c79afSRobert Watson 		if (set[i] != 0)
1322a1c79afSRobert Watson 			return (0);
1332a1c79afSRobert Watson 	return (1);
1342a1c79afSRobert Watson }
1352a1c79afSRobert Watson 
136d8a7b7a3SRobert Watson static struct mac_mls *
13796adb909SRobert Watson mls_alloc(int flag)
138d8a7b7a3SRobert Watson {
139d8a7b7a3SRobert Watson 
1402e8c6b26SRobert Watson 	return (uma_zalloc(zone_mls, flag | M_ZERO));
141d8a7b7a3SRobert Watson }
142d8a7b7a3SRobert Watson 
143d8a7b7a3SRobert Watson static void
1443f1a7a90SRobert Watson mls_free(struct mac_mls *mm)
145d8a7b7a3SRobert Watson {
146d8a7b7a3SRobert Watson 
1473f1a7a90SRobert Watson 	if (mm != NULL)
1483f1a7a90SRobert Watson 		uma_zfree(zone_mls, mm);
149d8a7b7a3SRobert Watson 	else
150d8a7b7a3SRobert Watson 		atomic_add_int(&destroyed_not_inited, 1);
151d8a7b7a3SRobert Watson }
152d8a7b7a3SRobert Watson 
153d8a7b7a3SRobert Watson static int
1543f1a7a90SRobert Watson mls_atmostflags(struct mac_mls *mm, int flags)
155b5f072b5SRobert Watson {
156b5f072b5SRobert Watson 
1573f1a7a90SRobert Watson 	if ((mm->mm_flags & flags) != mm->mm_flags)
158b5f072b5SRobert Watson 		return (EINVAL);
159b5f072b5SRobert Watson 	return (0);
160b5f072b5SRobert Watson }
161b5f072b5SRobert Watson 
162b5f072b5SRobert Watson static int
1633f1a7a90SRobert Watson mls_dominate_element(struct mac_mls_element *a, struct mac_mls_element *b)
164d8a7b7a3SRobert Watson {
1652a1c79afSRobert Watson 	int bit;
166d8a7b7a3SRobert Watson 
167d8a7b7a3SRobert Watson 	switch (a->mme_type) {
168d8a7b7a3SRobert Watson 	case MAC_MLS_TYPE_EQUAL:
169d8a7b7a3SRobert Watson 	case MAC_MLS_TYPE_HIGH:
170d8a7b7a3SRobert Watson 		return (1);
171d8a7b7a3SRobert Watson 
172d8a7b7a3SRobert Watson 	case MAC_MLS_TYPE_LOW:
173d8a7b7a3SRobert Watson 		switch (b->mme_type) {
174d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LEVEL:
175d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_HIGH:
176d8a7b7a3SRobert Watson 			return (0);
177d8a7b7a3SRobert Watson 
178d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_EQUAL:
179d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LOW:
180d8a7b7a3SRobert Watson 			return (1);
181d8a7b7a3SRobert Watson 
182d8a7b7a3SRobert Watson 		default:
1833f1a7a90SRobert Watson 			panic("mls_dominate_element: b->mme_type invalid");
184d8a7b7a3SRobert Watson 		}
185d8a7b7a3SRobert Watson 
186d8a7b7a3SRobert Watson 	case MAC_MLS_TYPE_LEVEL:
187d8a7b7a3SRobert Watson 		switch (b->mme_type) {
188d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_EQUAL:
189d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LOW:
190d8a7b7a3SRobert Watson 			return (1);
191d8a7b7a3SRobert Watson 
192d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_HIGH:
193d8a7b7a3SRobert Watson 			return (0);
194d8a7b7a3SRobert Watson 
195d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LEVEL:
1962a1c79afSRobert Watson 			for (bit = 1; bit <= MAC_MLS_MAX_COMPARTMENTS; bit++)
1972a1c79afSRobert Watson 				if (!MAC_MLS_BIT_TEST(bit,
1982a1c79afSRobert Watson 				    a->mme_compartments) &&
1992a1c79afSRobert Watson 				    MAC_MLS_BIT_TEST(bit, b->mme_compartments))
2002a1c79afSRobert Watson 					return (0);
201d8a7b7a3SRobert Watson 			return (a->mme_level >= b->mme_level);
202d8a7b7a3SRobert Watson 
203d8a7b7a3SRobert Watson 		default:
2043f1a7a90SRobert Watson 			panic("mls_dominate_element: b->mme_type invalid");
205d8a7b7a3SRobert Watson 		}
206d8a7b7a3SRobert Watson 
207d8a7b7a3SRobert Watson 	default:
2083f1a7a90SRobert Watson 		panic("mls_dominate_element: a->mme_type invalid");
209d8a7b7a3SRobert Watson 	}
210d8a7b7a3SRobert Watson 
211d8a7b7a3SRobert Watson 	return (0);
212d8a7b7a3SRobert Watson }
213d8a7b7a3SRobert Watson 
214d8a7b7a3SRobert Watson static int
2153f1a7a90SRobert Watson mls_range_in_range(struct mac_mls *rangea, struct mac_mls *rangeb)
216d8a7b7a3SRobert Watson {
217d8a7b7a3SRobert Watson 
2183f1a7a90SRobert Watson 	return (mls_dominate_element(&rangeb->mm_rangehigh,
219d8a7b7a3SRobert Watson 	    &rangea->mm_rangehigh) &&
2203f1a7a90SRobert Watson 	    mls_dominate_element(&rangea->mm_rangelow,
221d8a7b7a3SRobert Watson 	    &rangeb->mm_rangelow));
222d8a7b7a3SRobert Watson }
223d8a7b7a3SRobert Watson 
224d8a7b7a3SRobert Watson static int
2253f1a7a90SRobert Watson mls_effective_in_range(struct mac_mls *effective, struct mac_mls *range)
226d8a7b7a3SRobert Watson {
227d8a7b7a3SRobert Watson 
228dee57980SRobert Watson 	KASSERT((effective->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
2293f1a7a90SRobert Watson 	    ("mls_effective_in_range: a not effective"));
230728fbeeaSRobert Watson 	KASSERT((range->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
2313f1a7a90SRobert Watson 	    ("mls_effective_in_range: b not range"));
232d8a7b7a3SRobert Watson 
2333f1a7a90SRobert Watson 	return (mls_dominate_element(&range->mm_rangehigh,
234dee57980SRobert Watson 	    &effective->mm_effective) &&
2353f1a7a90SRobert Watson 	    mls_dominate_element(&effective->mm_effective,
236d8a7b7a3SRobert Watson 	    &range->mm_rangelow));
237d8a7b7a3SRobert Watson 
238d8a7b7a3SRobert Watson 	return (1);
239d8a7b7a3SRobert Watson }
240d8a7b7a3SRobert Watson 
241d8a7b7a3SRobert Watson static int
2423f1a7a90SRobert Watson mls_dominate_effective(struct mac_mls *a, struct mac_mls *b)
243d8a7b7a3SRobert Watson {
244dee57980SRobert Watson 	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
2453f1a7a90SRobert Watson 	    ("mls_dominate_effective: a not effective"));
246dee57980SRobert Watson 	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
2473f1a7a90SRobert Watson 	    ("mls_dominate_effective: b not effective"));
248d8a7b7a3SRobert Watson 
2493f1a7a90SRobert Watson 	return (mls_dominate_element(&a->mm_effective, &b->mm_effective));
250d8a7b7a3SRobert Watson }
251d8a7b7a3SRobert Watson 
252d8a7b7a3SRobert Watson static int
2533f1a7a90SRobert Watson mls_equal_element(struct mac_mls_element *a, struct mac_mls_element *b)
254d8a7b7a3SRobert Watson {
255d8a7b7a3SRobert Watson 
256d8a7b7a3SRobert Watson 	if (a->mme_type == MAC_MLS_TYPE_EQUAL ||
257d8a7b7a3SRobert Watson 	    b->mme_type == MAC_MLS_TYPE_EQUAL)
258d8a7b7a3SRobert Watson 		return (1);
259d8a7b7a3SRobert Watson 
260d8a7b7a3SRobert Watson 	return (a->mme_type == b->mme_type && a->mme_level == b->mme_level);
261d8a7b7a3SRobert Watson }
262d8a7b7a3SRobert Watson 
263d8a7b7a3SRobert Watson static int
2643f1a7a90SRobert Watson mls_equal_effective(struct mac_mls *a, struct mac_mls *b)
265d8a7b7a3SRobert Watson {
266d8a7b7a3SRobert Watson 
267dee57980SRobert Watson 	KASSERT((a->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
2683f1a7a90SRobert Watson 	    ("mls_equal_effective: a not effective"));
269dee57980SRobert Watson 	KASSERT((b->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
2703f1a7a90SRobert Watson 	    ("mls_equal_effective: b not effective"));
271d8a7b7a3SRobert Watson 
2723f1a7a90SRobert Watson 	return (mls_equal_element(&a->mm_effective, &b->mm_effective));
273d8a7b7a3SRobert Watson }
274d8a7b7a3SRobert Watson 
275d8a7b7a3SRobert Watson static int
2763f1a7a90SRobert Watson mls_contains_equal(struct mac_mls *mm)
277b5f072b5SRobert Watson {
278b5f072b5SRobert Watson 
2793f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
2803f1a7a90SRobert Watson 		if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
281b5f072b5SRobert Watson 			return (1);
282b5f072b5SRobert Watson 
2833f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
2843f1a7a90SRobert Watson 		if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL)
285b5f072b5SRobert Watson 			return (1);
2863f1a7a90SRobert Watson 		if (mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
287b5f072b5SRobert Watson 			return (1);
288b5f072b5SRobert Watson 	}
289b5f072b5SRobert Watson 
290b5f072b5SRobert Watson 	return (0);
291b5f072b5SRobert Watson }
292b5f072b5SRobert Watson 
293b5f072b5SRobert Watson static int
2943f1a7a90SRobert Watson mls_subject_privileged(struct mac_mls *mm)
295b5f072b5SRobert Watson {
296b5f072b5SRobert Watson 
2973f1a7a90SRobert Watson 	KASSERT((mm->mm_flags & MAC_MLS_FLAGS_BOTH) == MAC_MLS_FLAGS_BOTH,
2983f1a7a90SRobert Watson 	    ("mls_subject_privileged: subject doesn't have both labels"));
299b5f072b5SRobert Watson 
300dee57980SRobert Watson 	/* If the effective is EQUAL, it's ok. */
3013f1a7a90SRobert Watson 	if (mm->mm_effective.mme_type == MAC_MLS_TYPE_EQUAL)
302b5f072b5SRobert Watson 		return (0);
303b5f072b5SRobert Watson 
304b5f072b5SRobert Watson 	/* If either range endpoint is EQUAL, it's ok. */
3053f1a7a90SRobert Watson 	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_EQUAL ||
3063f1a7a90SRobert Watson 	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_EQUAL)
307b5f072b5SRobert Watson 		return (0);
308b5f072b5SRobert Watson 
309b5f072b5SRobert Watson 	/* If the range is low-high, it's ok. */
3103f1a7a90SRobert Watson 	if (mm->mm_rangelow.mme_type == MAC_MLS_TYPE_LOW &&
3113f1a7a90SRobert Watson 	    mm->mm_rangehigh.mme_type == MAC_MLS_TYPE_HIGH)
312b5f072b5SRobert Watson 		return (0);
313b5f072b5SRobert Watson 
314b5f072b5SRobert Watson 	/* It's not ok. */
315b5f072b5SRobert Watson 	return (EPERM);
316b5f072b5SRobert Watson }
317b5f072b5SRobert Watson 
318b5f072b5SRobert Watson static int
3193f1a7a90SRobert Watson mls_valid(struct mac_mls *mm)
320d8a7b7a3SRobert Watson {
321d8a7b7a3SRobert Watson 
3223f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
3233f1a7a90SRobert Watson 		switch (mm->mm_effective.mme_type) {
324d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LEVEL:
325d8a7b7a3SRobert Watson 			break;
326d8a7b7a3SRobert Watson 
327d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_EQUAL:
328d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_HIGH:
329d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LOW:
3303f1a7a90SRobert Watson 			if (mm->mm_effective.mme_level != 0 ||
3312a1c79afSRobert Watson 			    !MAC_MLS_BIT_SET_EMPTY(
3323f1a7a90SRobert Watson 			    mm->mm_effective.mme_compartments))
333d8a7b7a3SRobert Watson 				return (EINVAL);
334d8a7b7a3SRobert Watson 			break;
335d8a7b7a3SRobert Watson 
336d8a7b7a3SRobert Watson 		default:
337d8a7b7a3SRobert Watson 			return (EINVAL);
338d8a7b7a3SRobert Watson 		}
339d8a7b7a3SRobert Watson 	} else {
3403f1a7a90SRobert Watson 		if (mm->mm_effective.mme_type != MAC_MLS_TYPE_UNDEF)
341d8a7b7a3SRobert Watson 			return (EINVAL);
342d8a7b7a3SRobert Watson 	}
343d8a7b7a3SRobert Watson 
3443f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
3453f1a7a90SRobert Watson 		switch (mm->mm_rangelow.mme_type) {
346d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LEVEL:
347d8a7b7a3SRobert Watson 			break;
348d8a7b7a3SRobert Watson 
349d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_EQUAL:
350d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_HIGH:
351d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LOW:
3523f1a7a90SRobert Watson 			if (mm->mm_rangelow.mme_level != 0 ||
3532a1c79afSRobert Watson 			    !MAC_MLS_BIT_SET_EMPTY(
3543f1a7a90SRobert Watson 			    mm->mm_rangelow.mme_compartments))
355d8a7b7a3SRobert Watson 				return (EINVAL);
356d8a7b7a3SRobert Watson 			break;
357d8a7b7a3SRobert Watson 
358d8a7b7a3SRobert Watson 		default:
359d8a7b7a3SRobert Watson 			return (EINVAL);
360d8a7b7a3SRobert Watson 		}
361d8a7b7a3SRobert Watson 
3623f1a7a90SRobert Watson 		switch (mm->mm_rangehigh.mme_type) {
363d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LEVEL:
364d8a7b7a3SRobert Watson 			break;
365d8a7b7a3SRobert Watson 
366d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_EQUAL:
367d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_HIGH:
368d8a7b7a3SRobert Watson 		case MAC_MLS_TYPE_LOW:
3693f1a7a90SRobert Watson 			if (mm->mm_rangehigh.mme_level != 0 ||
3702a1c79afSRobert Watson 			    !MAC_MLS_BIT_SET_EMPTY(
3713f1a7a90SRobert Watson 			    mm->mm_rangehigh.mme_compartments))
372d8a7b7a3SRobert Watson 				return (EINVAL);
373d8a7b7a3SRobert Watson 			break;
374d8a7b7a3SRobert Watson 
375d8a7b7a3SRobert Watson 		default:
376d8a7b7a3SRobert Watson 			return (EINVAL);
377d8a7b7a3SRobert Watson 		}
3783f1a7a90SRobert Watson 		if (!mls_dominate_element(&mm->mm_rangehigh,
3793f1a7a90SRobert Watson 		    &mm->mm_rangelow))
380d8a7b7a3SRobert Watson 			return (EINVAL);
381d8a7b7a3SRobert Watson 	} else {
3823f1a7a90SRobert Watson 		if (mm->mm_rangelow.mme_type != MAC_MLS_TYPE_UNDEF ||
3833f1a7a90SRobert Watson 		    mm->mm_rangehigh.mme_type != MAC_MLS_TYPE_UNDEF)
384d8a7b7a3SRobert Watson 			return (EINVAL);
385d8a7b7a3SRobert Watson 	}
386d8a7b7a3SRobert Watson 
387d8a7b7a3SRobert Watson 	return (0);
388d8a7b7a3SRobert Watson }
389d8a7b7a3SRobert Watson 
390d8a7b7a3SRobert Watson static void
3913f1a7a90SRobert Watson mls_set_range(struct mac_mls *mm, u_short typelow, u_short levellow,
3923f1a7a90SRobert Watson     u_char *compartmentslow, u_short typehigh, u_short levelhigh,
3933f1a7a90SRobert Watson     u_char *compartmentshigh)
394d8a7b7a3SRobert Watson {
395d8a7b7a3SRobert Watson 
3963f1a7a90SRobert Watson 	mm->mm_rangelow.mme_type = typelow;
3973f1a7a90SRobert Watson 	mm->mm_rangelow.mme_level = levellow;
3982a1c79afSRobert Watson 	if (compartmentslow != NULL)
39995b85ca3SRobert Watson 		memcpy(mm->mm_rangelow.mme_compartments, compartmentslow,
4003f1a7a90SRobert Watson 		    sizeof(mm->mm_rangelow.mme_compartments));
4013f1a7a90SRobert Watson 	mm->mm_rangehigh.mme_type = typehigh;
4023f1a7a90SRobert Watson 	mm->mm_rangehigh.mme_level = levelhigh;
4032a1c79afSRobert Watson 	if (compartmentshigh != NULL)
40495b85ca3SRobert Watson 		memcpy(mm->mm_rangehigh.mme_compartments, compartmentshigh,
4053f1a7a90SRobert Watson 		    sizeof(mm->mm_rangehigh.mme_compartments));
4063f1a7a90SRobert Watson 	mm->mm_flags |= MAC_MLS_FLAG_RANGE;
407d8a7b7a3SRobert Watson }
408d8a7b7a3SRobert Watson 
409d8a7b7a3SRobert Watson static void
4103f1a7a90SRobert Watson mls_set_effective(struct mac_mls *mm, u_short type, u_short level,
4112a1c79afSRobert Watson     u_char *compartments)
412d8a7b7a3SRobert Watson {
413d8a7b7a3SRobert Watson 
4143f1a7a90SRobert Watson 	mm->mm_effective.mme_type = type;
4153f1a7a90SRobert Watson 	mm->mm_effective.mme_level = level;
4162a1c79afSRobert Watson 	if (compartments != NULL)
4173f1a7a90SRobert Watson 		memcpy(mm->mm_effective.mme_compartments, compartments,
4183f1a7a90SRobert Watson 		    sizeof(mm->mm_effective.mme_compartments));
4193f1a7a90SRobert Watson 	mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
420d8a7b7a3SRobert Watson }
421d8a7b7a3SRobert Watson 
422d8a7b7a3SRobert Watson static void
4233f1a7a90SRobert Watson mls_copy_range(struct mac_mls *labelfrom, struct mac_mls *labelto)
424d8a7b7a3SRobert Watson {
4252a1c79afSRobert Watson 
426d8a7b7a3SRobert Watson 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_RANGE) != 0,
4273f1a7a90SRobert Watson 	    ("mls_copy_range: labelfrom not range"));
428d8a7b7a3SRobert Watson 
429d8a7b7a3SRobert Watson 	labelto->mm_rangelow = labelfrom->mm_rangelow;
430d8a7b7a3SRobert Watson 	labelto->mm_rangehigh = labelfrom->mm_rangehigh;
431d8a7b7a3SRobert Watson 	labelto->mm_flags |= MAC_MLS_FLAG_RANGE;
432d8a7b7a3SRobert Watson }
433d8a7b7a3SRobert Watson 
434d8a7b7a3SRobert Watson static void
4353f1a7a90SRobert Watson mls_copy_effective(struct mac_mls *labelfrom, struct mac_mls *labelto)
436d8a7b7a3SRobert Watson {
437d8a7b7a3SRobert Watson 
438dee57980SRobert Watson 	KASSERT((labelfrom->mm_flags & MAC_MLS_FLAG_EFFECTIVE) != 0,
4393f1a7a90SRobert Watson 	    ("mls_copy_effective: labelfrom not effective"));
440d8a7b7a3SRobert Watson 
441dee57980SRobert Watson 	labelto->mm_effective = labelfrom->mm_effective;
442dee57980SRobert Watson 	labelto->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
443d8a7b7a3SRobert Watson }
444d8a7b7a3SRobert Watson 
44536cf29fdSRobert Watson static void
4463f1a7a90SRobert Watson mls_copy(struct mac_mls *source, struct mac_mls *dest)
44736cf29fdSRobert Watson {
44836cf29fdSRobert Watson 
449dee57980SRobert Watson 	if (source->mm_flags & MAC_MLS_FLAG_EFFECTIVE)
4503f1a7a90SRobert Watson 		mls_copy_effective(source, dest);
45136cf29fdSRobert Watson 	if (source->mm_flags & MAC_MLS_FLAG_RANGE)
4523f1a7a90SRobert Watson 		mls_copy_range(source, dest);
45336cf29fdSRobert Watson }
45436cf29fdSRobert Watson 
455d8a7b7a3SRobert Watson /*
456d8a7b7a3SRobert Watson  * Policy module operations.
457d8a7b7a3SRobert Watson  */
458d8a7b7a3SRobert Watson static void
4593f1a7a90SRobert Watson mls_init(struct mac_policy_conf *conf)
460d8a7b7a3SRobert Watson {
461d8a7b7a3SRobert Watson 
4622e8c6b26SRobert Watson 	zone_mls = uma_zcreate("mac_mls", sizeof(struct mac_mls), NULL,
4632e8c6b26SRobert Watson 	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
464d8a7b7a3SRobert Watson }
465d8a7b7a3SRobert Watson 
466d8a7b7a3SRobert Watson /*
467d8a7b7a3SRobert Watson  * Label operations.
468d8a7b7a3SRobert Watson  */
469d8a7b7a3SRobert Watson static void
4703f1a7a90SRobert Watson mls_init_label(struct label *label)
471d8a7b7a3SRobert Watson {
472d8a7b7a3SRobert Watson 
4731477f588SAlexander Kabaev 	SLOT_SET(label, mls_alloc(M_WAITOK));
474d8a7b7a3SRobert Watson }
475d8a7b7a3SRobert Watson 
476d8a7b7a3SRobert Watson static int
4773f1a7a90SRobert Watson mls_init_label_waitcheck(struct label *label, int flag)
478d8a7b7a3SRobert Watson {
479d8a7b7a3SRobert Watson 
4801477f588SAlexander Kabaev 	SLOT_SET(label, mls_alloc(flag));
481d8a7b7a3SRobert Watson 	if (SLOT(label) == NULL)
482d8a7b7a3SRobert Watson 		return (ENOMEM);
483d8a7b7a3SRobert Watson 
484d8a7b7a3SRobert Watson 	return (0);
485d8a7b7a3SRobert Watson }
486d8a7b7a3SRobert Watson 
487d8a7b7a3SRobert Watson static void
4883f1a7a90SRobert Watson mls_destroy_label(struct label *label)
489d8a7b7a3SRobert Watson {
490d8a7b7a3SRobert Watson 
491d8a7b7a3SRobert Watson 	mls_free(SLOT(label));
4921477f588SAlexander Kabaev 	SLOT_SET(label, NULL);
493d8a7b7a3SRobert Watson }
494d8a7b7a3SRobert Watson 
49524e8d0d0SRobert Watson /*
4963f1a7a90SRobert Watson  * mls_element_to_string() accepts an sbuf and MLS element.  It converts the
4973f1a7a90SRobert Watson  * MLS element to a string and stores the result in the sbuf; if there isn't
4983f1a7a90SRobert Watson  * space in the sbuf, -1 is returned.
49924e8d0d0SRobert Watson  */
50005e830f1SRobert Watson static int
5013f1a7a90SRobert Watson mls_element_to_string(struct sbuf *sb, struct mac_mls_element *element)
50224e8d0d0SRobert Watson {
50305e830f1SRobert Watson 	int i, first;
50424e8d0d0SRobert Watson 
50524e8d0d0SRobert Watson 	switch (element->mme_type) {
50624e8d0d0SRobert Watson 	case MAC_MLS_TYPE_HIGH:
50705e830f1SRobert Watson 		return (sbuf_printf(sb, "high"));
50824e8d0d0SRobert Watson 
50924e8d0d0SRobert Watson 	case MAC_MLS_TYPE_LOW:
51005e830f1SRobert Watson 		return (sbuf_printf(sb, "low"));
51124e8d0d0SRobert Watson 
51224e8d0d0SRobert Watson 	case MAC_MLS_TYPE_EQUAL:
51305e830f1SRobert Watson 		return (sbuf_printf(sb, "equal"));
51424e8d0d0SRobert Watson 
51524e8d0d0SRobert Watson 	case MAC_MLS_TYPE_LEVEL:
51605e830f1SRobert Watson 		if (sbuf_printf(sb, "%d", element->mme_level) == -1)
51705e830f1SRobert Watson 			return (-1);
51805e830f1SRobert Watson 
51905e830f1SRobert Watson 		first = 1;
52005e830f1SRobert Watson 		for (i = 1; i <= MAC_MLS_MAX_COMPARTMENTS; i++) {
52105e830f1SRobert Watson 			if (MAC_MLS_BIT_TEST(i, element->mme_compartments)) {
52205e830f1SRobert Watson 				if (first) {
52305e830f1SRobert Watson 					if (sbuf_putc(sb, ':') == -1)
52405e830f1SRobert Watson 						return (-1);
52505e830f1SRobert Watson 					if (sbuf_printf(sb, "%d", i) == -1)
52605e830f1SRobert Watson 						return (-1);
52705e830f1SRobert Watson 					first = 0;
52805e830f1SRobert Watson 				} else {
52905e830f1SRobert Watson 					if (sbuf_printf(sb, "+%d", i) == -1)
53005e830f1SRobert Watson 						return (-1);
53124e8d0d0SRobert Watson 				}
53205e830f1SRobert Watson 			}
53305e830f1SRobert Watson 		}
53405e830f1SRobert Watson 		return (0);
53524e8d0d0SRobert Watson 
53624e8d0d0SRobert Watson 	default:
5373f1a7a90SRobert Watson 		panic("mls_element_to_string: invalid type (%d)",
53824e8d0d0SRobert Watson 		    element->mme_type);
53924e8d0d0SRobert Watson 	}
54024e8d0d0SRobert Watson }
54124e8d0d0SRobert Watson 
54205e830f1SRobert Watson /*
5433f1a7a90SRobert Watson  * mls_to_string() converts an MLS label to a string, and places the results
5443f1a7a90SRobert Watson  * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
5453f1a7a90SRobert Watson  * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
5463f1a7a90SRobert Watson  * so the caller may need to revert the sbuf by restoring the offset if
5473f1a7a90SRobert Watson  * that's undesired.
54805e830f1SRobert Watson  */
54905e830f1SRobert Watson static int
5503f1a7a90SRobert Watson mls_to_string(struct sbuf *sb, struct mac_mls *mm)
55124e8d0d0SRobert Watson {
55224e8d0d0SRobert Watson 
5533f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
5543f1a7a90SRobert Watson 		if (mls_element_to_string(sb, &mm->mm_effective) == -1)
55524e8d0d0SRobert Watson 			return (EINVAL);
55624e8d0d0SRobert Watson 	}
55724e8d0d0SRobert Watson 
5583f1a7a90SRobert Watson 	if (mm->mm_flags & MAC_MLS_FLAG_RANGE) {
559f51e5803SRobert Watson 		if (sbuf_putc(sb, '(') == -1)
56024e8d0d0SRobert Watson 			return (EINVAL);
56124e8d0d0SRobert Watson 
5623f1a7a90SRobert Watson 		if (mls_element_to_string(sb, &mm->mm_rangelow) == -1)
56324e8d0d0SRobert Watson 			return (EINVAL);
56424e8d0d0SRobert Watson 
565f51e5803SRobert Watson 		if (sbuf_putc(sb, '-') == -1)
56624e8d0d0SRobert Watson 			return (EINVAL);
56724e8d0d0SRobert Watson 
5683f1a7a90SRobert Watson 		if (mls_element_to_string(sb, &mm->mm_rangehigh) == -1)
56924e8d0d0SRobert Watson 			return (EINVAL);
57024e8d0d0SRobert Watson 
571f51e5803SRobert Watson 		if (sbuf_putc(sb, ')') == -1)
57224e8d0d0SRobert Watson 			return (EINVAL);
57324e8d0d0SRobert Watson 	}
57424e8d0d0SRobert Watson 
57524e8d0d0SRobert Watson 	return (0);
57624e8d0d0SRobert Watson }
57724e8d0d0SRobert Watson 
578d8a7b7a3SRobert Watson static int
5793f1a7a90SRobert Watson mls_externalize_label(struct label *label, char *element_name,
580f51e5803SRobert Watson     struct sbuf *sb, int *claimed)
58124e8d0d0SRobert Watson {
5823f1a7a90SRobert Watson 	struct mac_mls *mm;
58324e8d0d0SRobert Watson 
58424e8d0d0SRobert Watson 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
58524e8d0d0SRobert Watson 		return (0);
58624e8d0d0SRobert Watson 
58724e8d0d0SRobert Watson 	(*claimed)++;
58824e8d0d0SRobert Watson 
5893f1a7a90SRobert Watson 	mm = SLOT(label);
59024e8d0d0SRobert Watson 
5913f1a7a90SRobert Watson 	return (mls_to_string(sb, mm));
59224e8d0d0SRobert Watson }
59324e8d0d0SRobert Watson 
59424e8d0d0SRobert Watson static int
5953f1a7a90SRobert Watson mls_parse_element(struct mac_mls_element *element, char *string)
596d8a7b7a3SRobert Watson {
5977792fe57SRobert Watson 	char *compartment, *end, *level;
5987792fe57SRobert Watson 	int value;
59924e8d0d0SRobert Watson 
6003f1a7a90SRobert Watson 	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
60124e8d0d0SRobert Watson 		element->mme_type = MAC_MLS_TYPE_HIGH;
60224e8d0d0SRobert Watson 		element->mme_level = MAC_MLS_TYPE_UNDEF;
6033f1a7a90SRobert Watson 	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
60424e8d0d0SRobert Watson 		element->mme_type = MAC_MLS_TYPE_LOW;
60524e8d0d0SRobert Watson 		element->mme_level = MAC_MLS_TYPE_UNDEF;
60624e8d0d0SRobert Watson 	} else if (strcmp(string, "equal") == 0 ||
60724e8d0d0SRobert Watson 	    strcmp(string, "eq") == 0) {
60824e8d0d0SRobert Watson 		element->mme_type = MAC_MLS_TYPE_EQUAL;
60924e8d0d0SRobert Watson 		element->mme_level = MAC_MLS_TYPE_UNDEF;
61024e8d0d0SRobert Watson 	} else {
61124e8d0d0SRobert Watson 		element->mme_type = MAC_MLS_TYPE_LEVEL;
61224e8d0d0SRobert Watson 
6137792fe57SRobert Watson 		/*
6147792fe57SRobert Watson 		 * Numeric level piece of the element.
6157792fe57SRobert Watson 		 */
6167792fe57SRobert Watson 		level = strsep(&string, ":");
6177792fe57SRobert Watson 		value = strtol(level, &end, 10);
6187792fe57SRobert Watson 		if (end == level || *end != '\0')
61924e8d0d0SRobert Watson 			return (EINVAL);
6207792fe57SRobert Watson 		if (value < 0 || value > 65535)
6217792fe57SRobert Watson 			return (EINVAL);
6227792fe57SRobert Watson 		element->mme_level = value;
6237792fe57SRobert Watson 
6247792fe57SRobert Watson 		/*
6253f1a7a90SRobert Watson 		 * Optional compartment piece of the element.  If none are
6263f1a7a90SRobert Watson 		 * included, we assume that the label has no compartments.
6277792fe57SRobert Watson 		 */
6287792fe57SRobert Watson 		if (string == NULL)
62924e8d0d0SRobert Watson 			return (0);
6307792fe57SRobert Watson 		if (*string == '\0')
63124e8d0d0SRobert Watson 			return (0);
63224e8d0d0SRobert Watson 
6337792fe57SRobert Watson 		while ((compartment = strsep(&string, "+")) != NULL) {
6347792fe57SRobert Watson 			value = strtol(compartment, &end, 10);
6357792fe57SRobert Watson 			if (compartment == end || *end != '\0')
63624e8d0d0SRobert Watson 				return (EINVAL);
6377792fe57SRobert Watson 			if (value < 1 || value > MAC_MLS_MAX_COMPARTMENTS)
63824e8d0d0SRobert Watson 				return (EINVAL);
6397792fe57SRobert Watson 			MAC_MLS_BIT_SET(value, element->mme_compartments);
64024e8d0d0SRobert Watson 		}
64124e8d0d0SRobert Watson 	}
64224e8d0d0SRobert Watson 
64324e8d0d0SRobert Watson 	return (0);
64424e8d0d0SRobert Watson }
64524e8d0d0SRobert Watson 
64624e8d0d0SRobert Watson /*
6473f1a7a90SRobert Watson  * Note: destructively consumes the string, make a local copy before calling
6483f1a7a90SRobert Watson  * if that's a problem.
64924e8d0d0SRobert Watson  */
65024e8d0d0SRobert Watson static int
6513f1a7a90SRobert Watson mls_parse(struct mac_mls *mm, char *string)
65224e8d0d0SRobert Watson {
653dee57980SRobert Watson 	char *rangehigh, *rangelow, *effective;
654d8a7b7a3SRobert Watson 	int error;
655d8a7b7a3SRobert Watson 
656dee57980SRobert Watson 	effective = strsep(&string, "(");
657dee57980SRobert Watson 	if (*effective == '\0')
658dee57980SRobert Watson 		effective = NULL;
6597792fe57SRobert Watson 
6607792fe57SRobert Watson 	if (string != NULL) {
6617792fe57SRobert Watson 		rangelow = strsep(&string, "-");
6627792fe57SRobert Watson 		if (string == NULL)
6637792fe57SRobert Watson 			return (EINVAL);
6647792fe57SRobert Watson 		rangehigh = strsep(&string, ")");
6657792fe57SRobert Watson 		if (string == NULL)
6667792fe57SRobert Watson 			return (EINVAL);
6677792fe57SRobert Watson 		if (*string != '\0')
6687792fe57SRobert Watson 			return (EINVAL);
669c2ea1fecSRobert Watson 	} else {
670c2ea1fecSRobert Watson 		rangelow = NULL;
671c2ea1fecSRobert Watson 		rangehigh = NULL;
6727792fe57SRobert Watson 	}
6737792fe57SRobert Watson 
67424e8d0d0SRobert Watson 	KASSERT((rangelow != NULL && rangehigh != NULL) ||
67524e8d0d0SRobert Watson 	    (rangelow == NULL && rangehigh == NULL),
6763f1a7a90SRobert Watson 	    ("mls_parse: range mismatch"));
67724e8d0d0SRobert Watson 
6783f1a7a90SRobert Watson 	bzero(mm, sizeof(*mm));
679dee57980SRobert Watson 	if (effective != NULL) {
6803f1a7a90SRobert Watson 		error = mls_parse_element(&mm->mm_effective, effective);
68124e8d0d0SRobert Watson 		if (error)
68224e8d0d0SRobert Watson 			return (error);
6833f1a7a90SRobert Watson 		mm->mm_flags |= MAC_MLS_FLAG_EFFECTIVE;
68424e8d0d0SRobert Watson 	}
68524e8d0d0SRobert Watson 
68624e8d0d0SRobert Watson 	if (rangelow != NULL) {
68795b85ca3SRobert Watson 		error = mls_parse_element(&mm->mm_rangelow, rangelow);
68824e8d0d0SRobert Watson 		if (error)
68924e8d0d0SRobert Watson 			return (error);
69095b85ca3SRobert Watson 		error = mls_parse_element(&mm->mm_rangehigh, rangehigh);
69124e8d0d0SRobert Watson 		if (error)
69224e8d0d0SRobert Watson 			return (error);
6933f1a7a90SRobert Watson 		mm->mm_flags |= MAC_MLS_FLAG_RANGE;
69424e8d0d0SRobert Watson 	}
695d8a7b7a3SRobert Watson 
6963f1a7a90SRobert Watson 	error = mls_valid(mm);
697d8a7b7a3SRobert Watson 	if (error)
698d8a7b7a3SRobert Watson 		return (error);
699d8a7b7a3SRobert Watson 
70024e8d0d0SRobert Watson 	return (0);
70124e8d0d0SRobert Watson }
70224e8d0d0SRobert Watson 
70324e8d0d0SRobert Watson static int
7043f1a7a90SRobert Watson mls_internalize_label(struct label *label, char *element_name,
70524e8d0d0SRobert Watson     char *element_data, int *claimed)
70624e8d0d0SRobert Watson {
7073f1a7a90SRobert Watson 	struct mac_mls *mm, mm_temp;
70824e8d0d0SRobert Watson 	int error;
70924e8d0d0SRobert Watson 
71024e8d0d0SRobert Watson 	if (strcmp(MAC_MLS_LABEL_NAME, element_name) != 0)
71124e8d0d0SRobert Watson 		return (0);
71224e8d0d0SRobert Watson 
71324e8d0d0SRobert Watson 	(*claimed)++;
71424e8d0d0SRobert Watson 
7153f1a7a90SRobert Watson 	error = mls_parse(&mm_temp, element_data);
71624e8d0d0SRobert Watson 	if (error)
71724e8d0d0SRobert Watson 		return (error);
71824e8d0d0SRobert Watson 
7193f1a7a90SRobert Watson 	mm = SLOT(label);
7203f1a7a90SRobert Watson 	*mm = mm_temp;
721d8a7b7a3SRobert Watson 
722d8a7b7a3SRobert Watson 	return (0);
723d8a7b7a3SRobert Watson }
724d8a7b7a3SRobert Watson 
72524e8d0d0SRobert Watson static void
7263f1a7a90SRobert Watson mls_copy_label(struct label *src, struct label *dest)
72724e8d0d0SRobert Watson {
72824e8d0d0SRobert Watson 
72924e8d0d0SRobert Watson 	*SLOT(dest) = *SLOT(src);
73024e8d0d0SRobert Watson }
73124e8d0d0SRobert Watson 
732d8a7b7a3SRobert Watson /*
733eb320b0eSRobert Watson  * Object-specific entry point implementations are sorted alphabetically by
734eb320b0eSRobert Watson  * object type name and then by operation.
735d8a7b7a3SRobert Watson  */
736d8a7b7a3SRobert Watson static int
7373f1a7a90SRobert Watson mls_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
73878007886SRobert Watson      struct ifnet *ifp, struct label *ifplabel)
739d8a7b7a3SRobert Watson {
740d8a7b7a3SRobert Watson 	struct mac_mls *a, *b;
741d8a7b7a3SRobert Watson 
7423f1a7a90SRobert Watson 	if (!mls_enabled)
743d8a7b7a3SRobert Watson 		return (0);
744d8a7b7a3SRobert Watson 
74578007886SRobert Watson 	a = SLOT(dlabel);
74678007886SRobert Watson 	b = SLOT(ifplabel);
747d8a7b7a3SRobert Watson 
7483f1a7a90SRobert Watson 	if (mls_equal_effective(a, b))
749d8a7b7a3SRobert Watson 		return (0);
750d8a7b7a3SRobert Watson 	return (EACCES);
751d8a7b7a3SRobert Watson }
752d8a7b7a3SRobert Watson 
753eb320b0eSRobert Watson static void
754eb320b0eSRobert Watson mls_bpfdesc_create(struct ucred *cred, struct bpf_d *d, struct label *dlabel)
755eb320b0eSRobert Watson {
756eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
757eb320b0eSRobert Watson 
758eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
759eb320b0eSRobert Watson 	dest = SLOT(dlabel);
760eb320b0eSRobert Watson 
761eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
762eb320b0eSRobert Watson }
763eb320b0eSRobert Watson 
764eb320b0eSRobert Watson static void
765eb320b0eSRobert Watson mls_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
766eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
767eb320b0eSRobert Watson {
768eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
769eb320b0eSRobert Watson 
770eb320b0eSRobert Watson 	source = SLOT(dlabel);
771eb320b0eSRobert Watson 	dest = SLOT(mlabel);
772eb320b0eSRobert Watson 
773eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
774eb320b0eSRobert Watson }
775eb320b0eSRobert Watson 
776212ab0cfSRobert Watson static void
777212ab0cfSRobert Watson mls_cred_associate_nfsd(struct ucred *cred)
778212ab0cfSRobert Watson {
779212ab0cfSRobert Watson 	struct mac_mls *label;
780212ab0cfSRobert Watson 
781212ab0cfSRobert Watson 	label = SLOT(cred->cr_label);
782212ab0cfSRobert Watson 	mls_set_effective(label, MAC_MLS_TYPE_LOW, 0, NULL);
783212ab0cfSRobert Watson 	mls_set_range(label, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
784212ab0cfSRobert Watson 	    NULL);
785212ab0cfSRobert Watson }
786212ab0cfSRobert Watson 
787d8a7b7a3SRobert Watson static int
7883f1a7a90SRobert Watson mls_cred_check_relabel(struct ucred *cred, struct label *newlabel)
789d8a7b7a3SRobert Watson {
790d8a7b7a3SRobert Watson 	struct mac_mls *subj, *new;
791b5f072b5SRobert Watson 	int error;
792d8a7b7a3SRobert Watson 
793eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
794d8a7b7a3SRobert Watson 	new = SLOT(newlabel);
795d8a7b7a3SRobert Watson 
796b5f072b5SRobert Watson 	/*
7973f1a7a90SRobert Watson 	 * If there is an MLS label update for the credential, it may be an
7983f1a7a90SRobert Watson 	 * update of effective, range, or both.
799b5f072b5SRobert Watson 	 */
800b5f072b5SRobert Watson 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
801b5f072b5SRobert Watson 	if (error)
802b5f072b5SRobert Watson 		return (error);
803d8a7b7a3SRobert Watson 
804d8a7b7a3SRobert Watson 	/*
805b5f072b5SRobert Watson 	 * If the MLS label is to be changed, authorize as appropriate.
806d8a7b7a3SRobert Watson 	 */
807b5f072b5SRobert Watson 	if (new->mm_flags & MAC_MLS_FLAGS_BOTH) {
808d8a7b7a3SRobert Watson 		/*
8093f1a7a90SRobert Watson 		 * If the change request modifies both the MLS label
8103f1a7a90SRobert Watson 		 * effective and range, check that the new effective will be
8113f1a7a90SRobert Watson 		 * in the new range.
81212613c76SRobert Watson 		 */
81312613c76SRobert Watson 		if ((new->mm_flags & MAC_MLS_FLAGS_BOTH) ==
8143f1a7a90SRobert Watson 		    MAC_MLS_FLAGS_BOTH && !mls_effective_in_range(new, new))
81512613c76SRobert Watson 			return (EINVAL);
81612613c76SRobert Watson 
81712613c76SRobert Watson 		/*
8183f1a7a90SRobert Watson 		 * To change the MLS effective label on a credential, the new
8193f1a7a90SRobert Watson 		 * effective label must be in the current range.
820d8a7b7a3SRobert Watson 		 */
821dee57980SRobert Watson 		if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE &&
8223f1a7a90SRobert Watson 		    !mls_effective_in_range(new, subj))
823d8a7b7a3SRobert Watson 			return (EPERM);
824d8a7b7a3SRobert Watson 
825d8a7b7a3SRobert Watson 		/*
8263f1a7a90SRobert Watson 		 * To change the MLS range label on a credential, the new
8273f1a7a90SRobert Watson 		 * range must be in the current range.
828d8a7b7a3SRobert Watson 		 */
829b5f072b5SRobert Watson 		if (new->mm_flags & MAC_MLS_FLAG_RANGE &&
8303f1a7a90SRobert Watson 		    !mls_range_in_range(new, subj))
831d8a7b7a3SRobert Watson 			return (EPERM);
832d8a7b7a3SRobert Watson 
833d8a7b7a3SRobert Watson 		/*
8343f1a7a90SRobert Watson 		 * To have EQUAL in any component of the new credential MLS
8353f1a7a90SRobert Watson 		 * label, the subject must already have EQUAL in their label.
836d8a7b7a3SRobert Watson 		 */
8373f1a7a90SRobert Watson 		if (mls_contains_equal(new)) {
8383f1a7a90SRobert Watson 			error = mls_subject_privileged(subj);
839b5f072b5SRobert Watson 			if (error)
840b5f072b5SRobert Watson 				return (error);
841b5f072b5SRobert Watson 		}
842b5f072b5SRobert Watson 	}
843d8a7b7a3SRobert Watson 
844d8a7b7a3SRobert Watson 	return (0);
845d8a7b7a3SRobert Watson }
846d8a7b7a3SRobert Watson 
847d8a7b7a3SRobert Watson static int
8483f1a7a90SRobert Watson mls_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
849d8a7b7a3SRobert Watson {
850d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
851d8a7b7a3SRobert Watson 
8523f1a7a90SRobert Watson 	if (!mls_enabled)
853d8a7b7a3SRobert Watson 		return (0);
854d8a7b7a3SRobert Watson 
85578007886SRobert Watson 	subj = SLOT(cr1->cr_label);
85678007886SRobert Watson 	obj = SLOT(cr2->cr_label);
857d8a7b7a3SRobert Watson 
858d8a7b7a3SRobert Watson 	/* XXX: range */
8593f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
860d8a7b7a3SRobert Watson 		return (ESRCH);
861d8a7b7a3SRobert Watson 
862d8a7b7a3SRobert Watson 	return (0);
863d8a7b7a3SRobert Watson }
864d8a7b7a3SRobert Watson 
865eb320b0eSRobert Watson static void
866212ab0cfSRobert Watson mls_cred_create_init(struct ucred *cred)
867212ab0cfSRobert Watson {
868212ab0cfSRobert Watson 	struct mac_mls *dest;
869212ab0cfSRobert Watson 
870212ab0cfSRobert Watson 	dest = SLOT(cred->cr_label);
871212ab0cfSRobert Watson 
872212ab0cfSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_LOW, 0, NULL);
873212ab0cfSRobert Watson 	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
874212ab0cfSRobert Watson 	    NULL);
875212ab0cfSRobert Watson }
876212ab0cfSRobert Watson 
877212ab0cfSRobert Watson static void
878212ab0cfSRobert Watson mls_cred_create_swapper(struct ucred *cred)
879212ab0cfSRobert Watson {
880212ab0cfSRobert Watson 	struct mac_mls *dest;
881212ab0cfSRobert Watson 
882212ab0cfSRobert Watson 	dest = SLOT(cred->cr_label);
883212ab0cfSRobert Watson 
884212ab0cfSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
885212ab0cfSRobert Watson 	mls_set_range(dest, MAC_MLS_TYPE_LOW, 0, NULL, MAC_MLS_TYPE_HIGH, 0,
886212ab0cfSRobert Watson 	    NULL);
887212ab0cfSRobert Watson }
888212ab0cfSRobert Watson 
889212ab0cfSRobert Watson static void
890eb320b0eSRobert Watson mls_cred_relabel(struct ucred *cred, struct label *newlabel)
891eb320b0eSRobert Watson {
892eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
893eb320b0eSRobert Watson 
894eb320b0eSRobert Watson 	source = SLOT(newlabel);
895eb320b0eSRobert Watson 	dest = SLOT(cred->cr_label);
896eb320b0eSRobert Watson 
897eb320b0eSRobert Watson 	mls_copy(source, dest);
898eb320b0eSRobert Watson }
899eb320b0eSRobert Watson 
900eb320b0eSRobert Watson static void
901eb320b0eSRobert Watson mls_devfs_create_device(struct ucred *cred, struct mount *mp,
902eb320b0eSRobert Watson     struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
903eb320b0eSRobert Watson {
904eb320b0eSRobert Watson 	struct mac_mls *mm;
9057870adb6SEd Schouten 	const char *dn;
906eb320b0eSRobert Watson 	int mls_type;
907eb320b0eSRobert Watson 
908eb320b0eSRobert Watson 	mm = SLOT(delabel);
9097870adb6SEd Schouten 	dn = devtoname(dev);
9107870adb6SEd Schouten 	if (strcmp(dn, "null") == 0 ||
9117870adb6SEd Schouten 	    strcmp(dn, "zero") == 0 ||
9127870adb6SEd Schouten 	    strcmp(dn, "random") == 0 ||
9137870adb6SEd Schouten 	    strncmp(dn, "fd/", strlen("fd/")) == 0)
914eb320b0eSRobert Watson 		mls_type = MAC_MLS_TYPE_EQUAL;
9157870adb6SEd Schouten 	else if (strcmp(dn, "kmem") == 0 ||
9167870adb6SEd Schouten 	    strcmp(dn, "mem") == 0)
917eb320b0eSRobert Watson 		mls_type = MAC_MLS_TYPE_HIGH;
918eb320b0eSRobert Watson 	else if (ptys_equal &&
9197870adb6SEd Schouten 	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
9207870adb6SEd Schouten 	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
9217870adb6SEd Schouten 	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
922eb320b0eSRobert Watson 		mls_type = MAC_MLS_TYPE_EQUAL;
923eb320b0eSRobert Watson 	else
924eb320b0eSRobert Watson 		mls_type = MAC_MLS_TYPE_LOW;
925eb320b0eSRobert Watson 	mls_set_effective(mm, mls_type, 0, NULL);
926eb320b0eSRobert Watson }
927eb320b0eSRobert Watson 
928eb320b0eSRobert Watson static void
929eb320b0eSRobert Watson mls_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
930eb320b0eSRobert Watson     struct devfs_dirent *de, struct label *delabel)
931eb320b0eSRobert Watson {
932eb320b0eSRobert Watson 	struct mac_mls *mm;
933eb320b0eSRobert Watson 
934eb320b0eSRobert Watson 	mm = SLOT(delabel);
935eb320b0eSRobert Watson 	mls_set_effective(mm, MAC_MLS_TYPE_LOW, 0, NULL);
936eb320b0eSRobert Watson }
937eb320b0eSRobert Watson 
938eb320b0eSRobert Watson static void
939eb320b0eSRobert Watson mls_devfs_create_symlink(struct ucred *cred, struct mount *mp,
940eb320b0eSRobert Watson     struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
941eb320b0eSRobert Watson     struct label *delabel)
942eb320b0eSRobert Watson {
943eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
944eb320b0eSRobert Watson 
945eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
946eb320b0eSRobert Watson 	dest = SLOT(delabel);
947eb320b0eSRobert Watson 
948eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
949eb320b0eSRobert Watson }
950eb320b0eSRobert Watson 
951eb320b0eSRobert Watson static void
952eb320b0eSRobert Watson mls_devfs_update(struct mount *mp, struct devfs_dirent *de,
953eb320b0eSRobert Watson     struct label *delabel, struct vnode *vp, struct label *vplabel)
954eb320b0eSRobert Watson {
955eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
956eb320b0eSRobert Watson 
957eb320b0eSRobert Watson 	source = SLOT(vplabel);
958eb320b0eSRobert Watson 	dest = SLOT(delabel);
959eb320b0eSRobert Watson 
960eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
961eb320b0eSRobert Watson }
962eb320b0eSRobert Watson 
963eb320b0eSRobert Watson static void
964eb320b0eSRobert Watson mls_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
965eb320b0eSRobert Watson     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
966eb320b0eSRobert Watson     struct label *vplabel)
967eb320b0eSRobert Watson {
968eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
969eb320b0eSRobert Watson 
970eb320b0eSRobert Watson 	source = SLOT(delabel);
971eb320b0eSRobert Watson 	dest = SLOT(vplabel);
972eb320b0eSRobert Watson 
973eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
974eb320b0eSRobert Watson }
975eb320b0eSRobert Watson 
976d8a7b7a3SRobert Watson static int
9773f1a7a90SRobert Watson mls_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
97878007886SRobert Watson     struct label *ifplabel, struct label *newlabel)
979d8a7b7a3SRobert Watson {
980d8a7b7a3SRobert Watson 	struct mac_mls *subj, *new;
981b5f072b5SRobert Watson 	int error;
982d8a7b7a3SRobert Watson 
983eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
984d8a7b7a3SRobert Watson 	new = SLOT(newlabel);
985d8a7b7a3SRobert Watson 
986b5f072b5SRobert Watson 	/*
9873f1a7a90SRobert Watson 	 * If there is an MLS label update for the interface, it may be an
9883f1a7a90SRobert Watson 	 * update of effective, range, or both.
989b5f072b5SRobert Watson 	 */
990b5f072b5SRobert Watson 	error = mls_atmostflags(new, MAC_MLS_FLAGS_BOTH);
991b5f072b5SRobert Watson 	if (error)
992b5f072b5SRobert Watson 		return (error);
993d8a7b7a3SRobert Watson 
994b5f072b5SRobert Watson 	/*
99513031647SRobert Watson 	 * Relabeling network interfaces requires MLS privilege.
996b5f072b5SRobert Watson 	 */
9975ac3b035SRobert Watson 	return (mls_subject_privileged(subj));
998d8a7b7a3SRobert Watson }
999d8a7b7a3SRobert Watson 
1000d8a7b7a3SRobert Watson static int
10013f1a7a90SRobert Watson mls_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
100278007886SRobert Watson     struct mbuf *m, struct label *mlabel)
1003d8a7b7a3SRobert Watson {
1004d8a7b7a3SRobert Watson 	struct mac_mls *p, *i;
1005d8a7b7a3SRobert Watson 
10063f1a7a90SRobert Watson 	if (!mls_enabled)
1007d8a7b7a3SRobert Watson 		return (0);
1008d8a7b7a3SRobert Watson 
100978007886SRobert Watson 	p = SLOT(mlabel);
101078007886SRobert Watson 	i = SLOT(ifplabel);
1011d8a7b7a3SRobert Watson 
10123f1a7a90SRobert Watson 	return (mls_effective_in_range(p, i) ? 0 : EACCES);
1013d8a7b7a3SRobert Watson }
1014d8a7b7a3SRobert Watson 
1015eb320b0eSRobert Watson static void
1016eb320b0eSRobert Watson mls_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1017eb320b0eSRobert Watson {
1018eb320b0eSRobert Watson 	struct mac_mls *dest;
1019eb320b0eSRobert Watson 	int type;
1020eb320b0eSRobert Watson 
1021eb320b0eSRobert Watson 	dest = SLOT(ifplabel);
1022eb320b0eSRobert Watson 
1023*30af2c13SJustin Hibbits 	if (if_gettype(ifp) == IFT_LOOP)
1024eb320b0eSRobert Watson 		type = MAC_MLS_TYPE_EQUAL;
1025eb320b0eSRobert Watson 	else
1026eb320b0eSRobert Watson 		type = MAC_MLS_TYPE_LOW;
1027eb320b0eSRobert Watson 
1028eb320b0eSRobert Watson 	mls_set_effective(dest, type, 0, NULL);
1029eb320b0eSRobert Watson 	mls_set_range(dest, type, 0, NULL, type, 0, NULL);
1030eb320b0eSRobert Watson }
1031eb320b0eSRobert Watson 
1032eb320b0eSRobert Watson static void
1033eb320b0eSRobert Watson mls_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1034eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1035eb320b0eSRobert Watson {
1036eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1037eb320b0eSRobert Watson 
1038eb320b0eSRobert Watson 	source = SLOT(ifplabel);
1039eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1040eb320b0eSRobert Watson 
1041eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1042eb320b0eSRobert Watson }
1043eb320b0eSRobert Watson 
1044eb320b0eSRobert Watson static void
1045eb320b0eSRobert Watson mls_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1046eb320b0eSRobert Watson     struct label *ifplabel, struct label *newlabel)
1047eb320b0eSRobert Watson {
1048eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1049eb320b0eSRobert Watson 
1050eb320b0eSRobert Watson 	source = SLOT(newlabel);
1051eb320b0eSRobert Watson 	dest = SLOT(ifplabel);
1052eb320b0eSRobert Watson 
1053eb320b0eSRobert Watson 	mls_copy(source, dest);
1054eb320b0eSRobert Watson }
1055eb320b0eSRobert Watson 
1056d8a7b7a3SRobert Watson static int
10573f1a7a90SRobert Watson mls_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1058a557af22SRobert Watson     struct mbuf *m, struct label *mlabel)
1059a557af22SRobert Watson {
1060a557af22SRobert Watson 	struct mac_mls *p, *i;
1061a557af22SRobert Watson 
10623f1a7a90SRobert Watson 	if (!mls_enabled)
1063a557af22SRobert Watson 		return (0);
1064a557af22SRobert Watson 
1065a557af22SRobert Watson 	p = SLOT(mlabel);
1066a557af22SRobert Watson 	i = SLOT(inplabel);
1067a557af22SRobert Watson 
10683f1a7a90SRobert Watson 	return (mls_equal_effective(p, i) ? 0 : EACCES);
1069a557af22SRobert Watson }
1070a557af22SRobert Watson 
10717fb179baSBjoern A. Zeeb static int
10727fb179baSBjoern A. Zeeb mls_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
10737fb179baSBjoern A. Zeeb     struct label *inplabel)
10747fb179baSBjoern A. Zeeb {
10757fb179baSBjoern A. Zeeb 	struct mac_mls *subj, *obj;
10767fb179baSBjoern A. Zeeb 
10777fb179baSBjoern A. Zeeb 	if (!mls_enabled)
10787fb179baSBjoern A. Zeeb 		return (0);
10797fb179baSBjoern A. Zeeb 
10807fb179baSBjoern A. Zeeb 	subj = SLOT(cred->cr_label);
10817fb179baSBjoern A. Zeeb 	obj = SLOT(inplabel);
10827fb179baSBjoern A. Zeeb 
10837fb179baSBjoern A. Zeeb 	if (!mls_dominate_effective(subj, obj))
10847fb179baSBjoern A. Zeeb 		return (ENOENT);
10857fb179baSBjoern A. Zeeb 
10867fb179baSBjoern A. Zeeb 	return (0);
10877fb179baSBjoern A. Zeeb }
10887fb179baSBjoern A. Zeeb 
1089eb320b0eSRobert Watson static void
1090eb320b0eSRobert Watson mls_inpcb_create(struct socket *so, struct label *solabel, struct inpcb *inp,
1091eb320b0eSRobert Watson     struct label *inplabel)
109282d16d5eSRobert Watson {
1093eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
109482d16d5eSRobert Watson 
1095eb320b0eSRobert Watson 	source = SLOT(solabel);
1096eb320b0eSRobert Watson 	dest = SLOT(inplabel);
109782d16d5eSRobert Watson 
1098eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1099eb320b0eSRobert Watson }
110082d16d5eSRobert Watson 
1101eb320b0eSRobert Watson static void
1102eb320b0eSRobert Watson mls_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1103eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1104eb320b0eSRobert Watson {
1105eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
110682d16d5eSRobert Watson 
1107eb320b0eSRobert Watson 	source = SLOT(inplabel);
1108eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1109eb320b0eSRobert Watson 
1110eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1111eb320b0eSRobert Watson }
1112eb320b0eSRobert Watson 
1113eb320b0eSRobert Watson static void
1114eb320b0eSRobert Watson mls_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1115eb320b0eSRobert Watson     struct inpcb *inp, struct label *inplabel)
1116eb320b0eSRobert Watson {
1117eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1118eb320b0eSRobert Watson 
11193de40469SRobert Watson 	SOCK_LOCK_ASSERT(so);
11203de40469SRobert Watson 
1121eb320b0eSRobert Watson 	source = SLOT(solabel);
1122eb320b0eSRobert Watson 	dest = SLOT(inplabel);
1123eb320b0eSRobert Watson 
1124eb320b0eSRobert Watson 	mls_copy(source, dest);
1125eb320b0eSRobert Watson }
1126eb320b0eSRobert Watson 
1127eb320b0eSRobert Watson static void
1128048e1287SRobert Watson mls_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1129048e1287SRobert Watson     struct label *q6label)
1130048e1287SRobert Watson {
1131048e1287SRobert Watson 	struct mac_mls *source, *dest;
1132048e1287SRobert Watson 
1133048e1287SRobert Watson 	source = SLOT(mlabel);
1134048e1287SRobert Watson 	dest = SLOT(q6label);
1135048e1287SRobert Watson 
1136048e1287SRobert Watson 	mls_copy_effective(source, dest);
1137048e1287SRobert Watson }
1138048e1287SRobert Watson 
1139048e1287SRobert Watson static int
1140048e1287SRobert Watson mls_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1141048e1287SRobert Watson     struct label *q6label)
1142048e1287SRobert Watson {
1143048e1287SRobert Watson 	struct mac_mls *a, *b;
1144048e1287SRobert Watson 
1145048e1287SRobert Watson 	a = SLOT(q6label);
1146048e1287SRobert Watson 	b = SLOT(mlabel);
1147048e1287SRobert Watson 
1148048e1287SRobert Watson 	return (mls_equal_effective(a, b));
1149048e1287SRobert Watson }
1150048e1287SRobert Watson 
1151048e1287SRobert Watson static void
1152048e1287SRobert Watson mls_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1153048e1287SRobert Watson     struct label *mlabel)
1154048e1287SRobert Watson {
1155048e1287SRobert Watson 	struct mac_mls *source, *dest;
1156048e1287SRobert Watson 
1157048e1287SRobert Watson 	source = SLOT(q6label);
1158048e1287SRobert Watson 	dest = SLOT(mlabel);
1159048e1287SRobert Watson 
1160048e1287SRobert Watson 	/* Just use the head, since we require them all to match. */
1161048e1287SRobert Watson 	mls_copy_effective(source, dest);
1162048e1287SRobert Watson }
1163048e1287SRobert Watson 
1164048e1287SRobert Watson static void
1165048e1287SRobert Watson mls_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1166048e1287SRobert Watson     struct label *q6label)
1167048e1287SRobert Watson {
1168048e1287SRobert Watson 
1169048e1287SRobert Watson 	/* NOOP: we only accept matching labels, so no need to update */
1170048e1287SRobert Watson }
1171048e1287SRobert Watson 
1172048e1287SRobert Watson static void
117337f44cb4SRobert Watson mls_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
117437f44cb4SRobert Watson     struct label *qlabel)
1175eb320b0eSRobert Watson {
1176eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1177eb320b0eSRobert Watson 
1178eb320b0eSRobert Watson 	source = SLOT(mlabel);
117937f44cb4SRobert Watson 	dest = SLOT(qlabel);
1180eb320b0eSRobert Watson 
1181eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
118282d16d5eSRobert Watson }
118382d16d5eSRobert Watson 
118482d16d5eSRobert Watson static int
118537f44cb4SRobert Watson mls_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
118637f44cb4SRobert Watson     struct label *qlabel)
118782d16d5eSRobert Watson {
1188eb320b0eSRobert Watson 	struct mac_mls *a, *b;
118982d16d5eSRobert Watson 
119037f44cb4SRobert Watson 	a = SLOT(qlabel);
1191eb320b0eSRobert Watson 	b = SLOT(mlabel);
119282d16d5eSRobert Watson 
1193eb320b0eSRobert Watson 	return (mls_equal_effective(a, b));
119482d16d5eSRobert Watson }
119582d16d5eSRobert Watson 
1196eb320b0eSRobert Watson static void
119737f44cb4SRobert Watson mls_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1198eb320b0eSRobert Watson     struct label *mlabel)
119982d16d5eSRobert Watson {
1200eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
120182d16d5eSRobert Watson 
120237f44cb4SRobert Watson 	source = SLOT(qlabel);
1203eb320b0eSRobert Watson 	dest = SLOT(mlabel);
120482d16d5eSRobert Watson 
1205eb320b0eSRobert Watson 	/* Just use the head, since we require them all to match. */
1206eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
120782d16d5eSRobert Watson }
120882d16d5eSRobert Watson 
1209eb320b0eSRobert Watson static void
121037f44cb4SRobert Watson mls_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
121137f44cb4SRobert Watson     struct label *qlabel)
121282d16d5eSRobert Watson {
121382d16d5eSRobert Watson 
1214eb320b0eSRobert Watson 	/* NOOP: we only accept matching labels, so no need to update */
121582d16d5eSRobert Watson }
121682d16d5eSRobert Watson 
121782d16d5eSRobert Watson static int
12183f1a7a90SRobert Watson mls_mount_check_stat(struct ucred *cred, struct mount *mp,
1219d8a7b7a3SRobert Watson     struct label *mntlabel)
1220d8a7b7a3SRobert Watson {
1221d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1222d8a7b7a3SRobert Watson 
12233f1a7a90SRobert Watson 	if (!mls_enabled)
1224d8a7b7a3SRobert Watson 		return (0);
1225d8a7b7a3SRobert Watson 
1226eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
1227d8a7b7a3SRobert Watson 	obj = SLOT(mntlabel);
1228d8a7b7a3SRobert Watson 
12293f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1230d8a7b7a3SRobert Watson 		return (EACCES);
1231d8a7b7a3SRobert Watson 
1232d8a7b7a3SRobert Watson 	return (0);
1233d8a7b7a3SRobert Watson }
1234d8a7b7a3SRobert Watson 
1235eb320b0eSRobert Watson static void
1236eb320b0eSRobert Watson mls_mount_create(struct ucred *cred, struct mount *mp, struct label *mplabel)
1237eb320b0eSRobert Watson {
1238eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1239eb320b0eSRobert Watson 
1240eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
1241eb320b0eSRobert Watson 	dest = SLOT(mplabel);
1242eb320b0eSRobert Watson 
1243eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1244eb320b0eSRobert Watson }
1245eb320b0eSRobert Watson 
1246eb320b0eSRobert Watson static void
1247eb320b0eSRobert Watson mls_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1248eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1249eb320b0eSRobert Watson {
1250eb320b0eSRobert Watson 	struct mac_mls *dest;
1251eb320b0eSRobert Watson 
1252eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1253eb320b0eSRobert Watson 
1254eb320b0eSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1255eb320b0eSRobert Watson }
1256eb320b0eSRobert Watson 
1257eb320b0eSRobert Watson static void
1258eb320b0eSRobert Watson mls_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1259eb320b0eSRobert Watson     struct mbuf *msend, struct label *msendlabel)
1260eb320b0eSRobert Watson {
1261eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1262eb320b0eSRobert Watson 
1263eb320b0eSRobert Watson 	source = SLOT(mrecvlabel);
1264eb320b0eSRobert Watson 	dest = SLOT(msendlabel);
1265eb320b0eSRobert Watson 
1266eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1267eb320b0eSRobert Watson }
1268eb320b0eSRobert Watson 
1269eb320b0eSRobert Watson static void
1270eb320b0eSRobert Watson mls_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1271eb320b0eSRobert Watson {
1272eb320b0eSRobert Watson 	struct mac_mls *dest;
1273eb320b0eSRobert Watson 
1274eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1275eb320b0eSRobert Watson 
1276bc5ade0dSPedro F. Giffuni 	/* XXX: where is the label for the firewall really coming from? */
1277eb320b0eSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1278eb320b0eSRobert Watson }
1279eb320b0eSRobert Watson 
1280eb320b0eSRobert Watson static void
1281eb320b0eSRobert Watson mls_netinet_fragment(struct mbuf *m, struct label *mlabel, struct mbuf *frag,
1282eb320b0eSRobert Watson     struct label *fraglabel)
1283eb320b0eSRobert Watson {
1284eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1285eb320b0eSRobert Watson 
1286eb320b0eSRobert Watson 	source = SLOT(mlabel);
1287eb320b0eSRobert Watson 	dest = SLOT(fraglabel);
1288eb320b0eSRobert Watson 
1289eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1290eb320b0eSRobert Watson }
1291eb320b0eSRobert Watson 
1292eb320b0eSRobert Watson static void
1293eb320b0eSRobert Watson mls_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1294eb320b0eSRobert Watson     struct mbuf *msend, struct label *msendlabel)
1295eb320b0eSRobert Watson {
1296eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1297eb320b0eSRobert Watson 
1298eb320b0eSRobert Watson 	source = SLOT(mrecvlabel);
1299eb320b0eSRobert Watson 	dest = SLOT(msendlabel);
1300eb320b0eSRobert Watson 
1301eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1302eb320b0eSRobert Watson }
1303eb320b0eSRobert Watson 
1304eb320b0eSRobert Watson static void
1305eb320b0eSRobert Watson mls_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1306eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1307eb320b0eSRobert Watson {
1308eb320b0eSRobert Watson 	struct mac_mls *dest;
1309eb320b0eSRobert Watson 
1310eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1311eb320b0eSRobert Watson 
1312eb320b0eSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1313eb320b0eSRobert Watson }
1314eb320b0eSRobert Watson 
1315eb320b0eSRobert Watson static void
1316eb320b0eSRobert Watson mls_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1317eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1318eb320b0eSRobert Watson {
1319eb320b0eSRobert Watson 	struct mac_mls *dest;
1320eb320b0eSRobert Watson 
1321eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1322eb320b0eSRobert Watson 
1323eb320b0eSRobert Watson 	mls_set_effective(dest, MAC_MLS_TYPE_EQUAL, 0, NULL);
1324eb320b0eSRobert Watson }
1325eb320b0eSRobert Watson 
1326d8a7b7a3SRobert Watson static int
13273f1a7a90SRobert Watson mls_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
132878007886SRobert Watson     struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1329d8a7b7a3SRobert Watson {
1330d8a7b7a3SRobert Watson 
13313f1a7a90SRobert Watson 	if (!mls_enabled)
1332d8a7b7a3SRobert Watson 		return (0);
1333d8a7b7a3SRobert Watson 
1334d8a7b7a3SRobert Watson 	/* XXX: This will be implemented soon... */
1335d8a7b7a3SRobert Watson 
1336d8a7b7a3SRobert Watson 	return (0);
1337d8a7b7a3SRobert Watson }
1338d8a7b7a3SRobert Watson 
1339d8a7b7a3SRobert Watson static int
13403f1a7a90SRobert Watson mls_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
134178007886SRobert Watson     struct label *pplabel)
1342d8a7b7a3SRobert Watson {
1343d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1344d8a7b7a3SRobert Watson 
13453f1a7a90SRobert Watson 	if (!mls_enabled)
1346d8a7b7a3SRobert Watson 		return (0);
1347d8a7b7a3SRobert Watson 
1348eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
134978007886SRobert Watson 	obj = SLOT(pplabel);
1350d8a7b7a3SRobert Watson 
13513f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1352d8a7b7a3SRobert Watson 		return (EACCES);
1353c024c3eeSRobert Watson 
1354c024c3eeSRobert Watson 	return (0);
1355d8a7b7a3SRobert Watson }
1356d8a7b7a3SRobert Watson 
1357c024c3eeSRobert Watson static int
13583f1a7a90SRobert Watson mls_pipe_check_read(struct ucred *cred, struct pipepair *pp,
135978007886SRobert Watson     struct label *pplabel)
1360c024c3eeSRobert Watson {
1361c024c3eeSRobert Watson 	struct mac_mls *subj, *obj;
1362c024c3eeSRobert Watson 
13633f1a7a90SRobert Watson 	if (!mls_enabled)
1364c024c3eeSRobert Watson 		return (0);
1365c024c3eeSRobert Watson 
1366eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
136778007886SRobert Watson 	obj = SLOT(pplabel);
1368c024c3eeSRobert Watson 
13693f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1370c024c3eeSRobert Watson 		return (EACCES);
1371c024c3eeSRobert Watson 
1372d8a7b7a3SRobert Watson 	return (0);
1373d8a7b7a3SRobert Watson }
1374d8a7b7a3SRobert Watson 
1375d8a7b7a3SRobert Watson static int
13763f1a7a90SRobert Watson mls_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
137778007886SRobert Watson     struct label *pplabel, struct label *newlabel)
1378d8a7b7a3SRobert Watson {
1379d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj, *new;
1380b5f072b5SRobert Watson 	int error;
1381d8a7b7a3SRobert Watson 
1382d8a7b7a3SRobert Watson 	new = SLOT(newlabel);
1383eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
138478007886SRobert Watson 	obj = SLOT(pplabel);
1385d8a7b7a3SRobert Watson 
1386b5f072b5SRobert Watson 	/*
13873f1a7a90SRobert Watson 	 * If there is an MLS label update for a pipe, it must be a effective
13883f1a7a90SRobert Watson 	 * update.
1389b5f072b5SRobert Watson 	 */
1390dee57980SRobert Watson 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1391b5f072b5SRobert Watson 	if (error)
1392b5f072b5SRobert Watson 		return (error);
1393d8a7b7a3SRobert Watson 
1394d8a7b7a3SRobert Watson 	/*
1395b5f072b5SRobert Watson 	 * To perform a relabel of a pipe (MLS label or not), MLS must
1396b5f072b5SRobert Watson 	 * authorize the relabel.
1397d8a7b7a3SRobert Watson 	 */
13983f1a7a90SRobert Watson 	if (!mls_effective_in_range(obj, subj))
1399d8a7b7a3SRobert Watson 		return (EPERM);
1400d8a7b7a3SRobert Watson 
1401d8a7b7a3SRobert Watson 	/*
1402b5f072b5SRobert Watson 	 * If the MLS label is to be changed, authorize as appropriate.
1403b5f072b5SRobert Watson 	 */
1404dee57980SRobert Watson 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1405b5f072b5SRobert Watson 		/*
14063f1a7a90SRobert Watson 		 * To change the MLS label on a pipe, the new pipe label must
14073f1a7a90SRobert Watson 		 * be in the subject range.
1408d8a7b7a3SRobert Watson 		 */
14093f1a7a90SRobert Watson 		if (!mls_effective_in_range(new, subj))
1410d8a7b7a3SRobert Watson 			return (EPERM);
1411d8a7b7a3SRobert Watson 
1412d8a7b7a3SRobert Watson 		/*
14133f1a7a90SRobert Watson 		 * To change the MLS label on a pipe to be EQUAL, the subject
14143f1a7a90SRobert Watson 		 * must have appropriate privilege.
1415d8a7b7a3SRobert Watson 		 */
14163f1a7a90SRobert Watson 		if (mls_contains_equal(new)) {
14173f1a7a90SRobert Watson 			error = mls_subject_privileged(subj);
1418b5f072b5SRobert Watson 			if (error)
1419b5f072b5SRobert Watson 				return (error);
1420b5f072b5SRobert Watson 		}
1421b5f072b5SRobert Watson 	}
1422d8a7b7a3SRobert Watson 
1423d8a7b7a3SRobert Watson 	return (0);
1424d8a7b7a3SRobert Watson }
1425d8a7b7a3SRobert Watson 
1426d8a7b7a3SRobert Watson static int
14273f1a7a90SRobert Watson mls_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
142878007886SRobert Watson     struct label *pplabel)
1429c024c3eeSRobert Watson {
1430c024c3eeSRobert Watson 	struct mac_mls *subj, *obj;
1431c024c3eeSRobert Watson 
14323f1a7a90SRobert Watson 	if (!mls_enabled)
1433c024c3eeSRobert Watson 		return (0);
1434c024c3eeSRobert Watson 
1435eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
143678007886SRobert Watson 	obj = SLOT(pplabel);
1437c024c3eeSRobert Watson 
14383f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1439c024c3eeSRobert Watson 		return (EACCES);
1440c024c3eeSRobert Watson 
1441c024c3eeSRobert Watson 	return (0);
1442c024c3eeSRobert Watson }
1443c024c3eeSRobert Watson 
1444c024c3eeSRobert Watson static int
14453f1a7a90SRobert Watson mls_pipe_check_write(struct ucred *cred, struct pipepair *pp,
144678007886SRobert Watson     struct label *pplabel)
1447c024c3eeSRobert Watson {
1448c024c3eeSRobert Watson 	struct mac_mls *subj, *obj;
1449c024c3eeSRobert Watson 
14503f1a7a90SRobert Watson 	if (!mls_enabled)
1451c024c3eeSRobert Watson 		return (0);
1452c024c3eeSRobert Watson 
1453eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
145478007886SRobert Watson 	obj = SLOT(pplabel);
1455c024c3eeSRobert Watson 
14563f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
1457c024c3eeSRobert Watson 		return (EACCES);
1458c024c3eeSRobert Watson 
1459c024c3eeSRobert Watson 	return (0);
1460c024c3eeSRobert Watson }
1461c024c3eeSRobert Watson 
1462eb320b0eSRobert Watson static void
1463eb320b0eSRobert Watson mls_pipe_create(struct ucred *cred, struct pipepair *pp,
1464eb320b0eSRobert Watson     struct label *pplabel)
146552648411SRobert Watson {
1466eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
146752648411SRobert Watson 
1468eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
1469eb320b0eSRobert Watson 	dest = SLOT(pplabel);
147052648411SRobert Watson 
1471eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1472eb320b0eSRobert Watson }
147352648411SRobert Watson 
1474eb320b0eSRobert Watson static void
1475eb320b0eSRobert Watson mls_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1476eb320b0eSRobert Watson     struct label *pplabel, struct label *newlabel)
1477eb320b0eSRobert Watson {
1478eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
147952648411SRobert Watson 
1480eb320b0eSRobert Watson 	source = SLOT(newlabel);
1481eb320b0eSRobert Watson 	dest = SLOT(pplabel);
1482eb320b0eSRobert Watson 
1483eb320b0eSRobert Watson 	mls_copy(source, dest);
148452648411SRobert Watson }
148552648411SRobert Watson 
148652648411SRobert Watson static int
14876bc1e9cdSJohn Baldwin mls_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1488fe09513eSRobert Watson     struct label *kslabel)
148952648411SRobert Watson {
149052648411SRobert Watson 	struct mac_mls *subj, *obj;
149152648411SRobert Watson 
14923f1a7a90SRobert Watson 	if (!mls_enabled)
149352648411SRobert Watson 		return (0);
149452648411SRobert Watson 
149552648411SRobert Watson 	subj = SLOT(cred->cr_label);
1496fe09513eSRobert Watson 	obj = SLOT(kslabel);
149752648411SRobert Watson 
14986bc1e9cdSJohn Baldwin 	if (!mls_dominate_effective(obj, subj))
14996bc1e9cdSJohn Baldwin 		return (EACCES);
15006bc1e9cdSJohn Baldwin 
15016bc1e9cdSJohn Baldwin 	return (0);
15026bc1e9cdSJohn Baldwin }
15036bc1e9cdSJohn Baldwin 
15046bc1e9cdSJohn Baldwin static int
15056bc1e9cdSJohn Baldwin mls_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
15066bc1e9cdSJohn Baldwin     struct ksem *ks, struct label *kslabel)
15076bc1e9cdSJohn Baldwin {
15086bc1e9cdSJohn Baldwin 	struct mac_mls *subj, *obj;
15096bc1e9cdSJohn Baldwin 
15106bc1e9cdSJohn Baldwin 	if (!mls_enabled)
15116bc1e9cdSJohn Baldwin 		return (0);
15126bc1e9cdSJohn Baldwin 
15136bc1e9cdSJohn Baldwin 	subj = SLOT(active_cred->cr_label);
15146bc1e9cdSJohn Baldwin 	obj = SLOT(kslabel);
15156bc1e9cdSJohn Baldwin 
15163f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
151752648411SRobert Watson 		return (EACCES);
151852648411SRobert Watson 
151952648411SRobert Watson 	return (0);
152052648411SRobert Watson }
152152648411SRobert Watson 
152252648411SRobert Watson static int
15239b6dd12eSRobert Watson mls_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
15249b6dd12eSRobert Watson     struct label *shmlabel, mode_t mode)
15259b6dd12eSRobert Watson {
15269b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
15279b6dd12eSRobert Watson 
15289b6dd12eSRobert Watson 	if (!mls_enabled)
15299b6dd12eSRobert Watson 		return (0);
15309b6dd12eSRobert Watson 
15319b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
15329b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
15339b6dd12eSRobert Watson 
15349b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
15359b6dd12eSRobert Watson 		return (EACCES);
15369b6dd12eSRobert Watson 
15379b6dd12eSRobert Watson 	return (0);
15389b6dd12eSRobert Watson }
15399b6dd12eSRobert Watson 
15409b6dd12eSRobert Watson static int
15419b6dd12eSRobert Watson mls_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
15429b6dd12eSRobert Watson     struct label *shmlabel, uid_t uid, gid_t gid)
15439b6dd12eSRobert Watson {
15449b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
15459b6dd12eSRobert Watson 
15469b6dd12eSRobert Watson 	if (!mls_enabled)
15479b6dd12eSRobert Watson 		return (0);
15489b6dd12eSRobert Watson 
15499b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
15509b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
15519b6dd12eSRobert Watson 
15529b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
15539b6dd12eSRobert Watson 		return (EACCES);
15549b6dd12eSRobert Watson 
15559b6dd12eSRobert Watson 	return (0);
15569b6dd12eSRobert Watson }
15579b6dd12eSRobert Watson 
15589b6dd12eSRobert Watson static int
15596bc1e9cdSJohn Baldwin mls_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
15606bc1e9cdSJohn Baldwin     struct ksem *ks, struct label *kslabel)
1561eb320b0eSRobert Watson {
1562eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
1563eb320b0eSRobert Watson 
1564eb320b0eSRobert Watson 	if (!mls_enabled)
1565eb320b0eSRobert Watson 		return (0);
1566eb320b0eSRobert Watson 
15676bc1e9cdSJohn Baldwin 	subj = SLOT(active_cred->cr_label);
1568eb320b0eSRobert Watson 	obj = SLOT(kslabel);
1569eb320b0eSRobert Watson 
1570eb320b0eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
1571eb320b0eSRobert Watson 		return (EACCES);
1572eb320b0eSRobert Watson 
1573eb320b0eSRobert Watson 	return (0);
1574eb320b0eSRobert Watson }
1575eb320b0eSRobert Watson 
1576eb320b0eSRobert Watson static void
1577eb320b0eSRobert Watson mls_posixsem_create(struct ucred *cred, struct ksem *ks,
1578eb320b0eSRobert Watson     struct label *kslabel)
1579eb320b0eSRobert Watson {
1580eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1581eb320b0eSRobert Watson 
1582eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
1583eb320b0eSRobert Watson 	dest = SLOT(kslabel);
1584eb320b0eSRobert Watson 
1585eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1586eb320b0eSRobert Watson }
1587eb320b0eSRobert Watson 
1588eb320b0eSRobert Watson static int
15899b6dd12eSRobert Watson mls_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
15909b6dd12eSRobert Watson     struct label *shmlabel, int prot, int flags)
15919b6dd12eSRobert Watson {
15929b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
15939b6dd12eSRobert Watson 
15949b6dd12eSRobert Watson 	if (!mls_enabled)
15959b6dd12eSRobert Watson 		return (0);
15969b6dd12eSRobert Watson 
15979b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
15989b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
15999b6dd12eSRobert Watson 
16009b6dd12eSRobert Watson 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
16019b6dd12eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
16029b6dd12eSRobert Watson 			return (EACCES);
16039b6dd12eSRobert Watson 	}
16049b6dd12eSRobert Watson 	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
16059b6dd12eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
16069b6dd12eSRobert Watson 			return (EACCES);
16079b6dd12eSRobert Watson 	}
16089b6dd12eSRobert Watson 
16099b6dd12eSRobert Watson 	return (0);
16109b6dd12eSRobert Watson }
16119b6dd12eSRobert Watson 
16129b6dd12eSRobert Watson static int
16139b6dd12eSRobert Watson mls_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
16149b6dd12eSRobert Watson     struct label *shmlabel, accmode_t accmode)
16159b6dd12eSRobert Watson {
16169b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
16179b6dd12eSRobert Watson 
16189b6dd12eSRobert Watson 	if (!mls_enabled)
16199b6dd12eSRobert Watson 		return (0);
16209b6dd12eSRobert Watson 
16219b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
16229b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
16239b6dd12eSRobert Watson 
16249b6dd12eSRobert Watson 	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
16259b6dd12eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
16269b6dd12eSRobert Watson 			return (EACCES);
16279b6dd12eSRobert Watson 	}
16289b6dd12eSRobert Watson 	if (accmode & VMODIFY_PERMS) {
16299b6dd12eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
16309b6dd12eSRobert Watson 			return (EACCES);
16319b6dd12eSRobert Watson 	}
16329b6dd12eSRobert Watson 
16339b6dd12eSRobert Watson 	return (0);
16349b6dd12eSRobert Watson }
16359b6dd12eSRobert Watson 
16369b6dd12eSRobert Watson static int
1637940cb0e2SKonstantin Belousov mls_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
1638940cb0e2SKonstantin Belousov     struct shmfd *shm, struct label *shmlabel)
1639940cb0e2SKonstantin Belousov {
1640940cb0e2SKonstantin Belousov 	struct mac_mls *subj, *obj;
1641940cb0e2SKonstantin Belousov 
1642940cb0e2SKonstantin Belousov 	if (!mls_enabled || !revocation_enabled)
1643940cb0e2SKonstantin Belousov 		return (0);
1644940cb0e2SKonstantin Belousov 
1645940cb0e2SKonstantin Belousov 	subj = SLOT(active_cred->cr_label);
1646940cb0e2SKonstantin Belousov 	obj = SLOT(shmlabel);
1647940cb0e2SKonstantin Belousov 
1648940cb0e2SKonstantin Belousov 	if (!mls_dominate_effective(subj, obj))
1649940cb0e2SKonstantin Belousov 		return (EACCES);
1650940cb0e2SKonstantin Belousov 
1651940cb0e2SKonstantin Belousov 	return (0);
1652940cb0e2SKonstantin Belousov }
1653940cb0e2SKonstantin Belousov 
1654940cb0e2SKonstantin Belousov static int
16559b6dd12eSRobert Watson mls_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
16569b6dd12eSRobert Watson     struct label *shmlabel, mode_t mode)
16579b6dd12eSRobert Watson {
16589b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
16599b6dd12eSRobert Watson 
16609b6dd12eSRobert Watson 	if (!mls_enabled)
16619b6dd12eSRobert Watson 		return (0);
16629b6dd12eSRobert Watson 
16639b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
16649b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
16659b6dd12eSRobert Watson 
16669b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
16679b6dd12eSRobert Watson 		return (EACCES);
16689b6dd12eSRobert Watson 
16699b6dd12eSRobert Watson 	return (0);
16709b6dd12eSRobert Watson }
16719b6dd12eSRobert Watson 
16729b6dd12eSRobert Watson static int
16739b6dd12eSRobert Watson mls_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
16749b6dd12eSRobert Watson     struct label *shmlabel, uid_t uid, gid_t gid)
16759b6dd12eSRobert Watson {
16769b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
16779b6dd12eSRobert Watson 
16789b6dd12eSRobert Watson 	if (!mls_enabled)
16799b6dd12eSRobert Watson 		return (0);
16809b6dd12eSRobert Watson 
16819b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
16829b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
16839b6dd12eSRobert Watson 
16849b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
16859b6dd12eSRobert Watson 		return (EACCES);
16869b6dd12eSRobert Watson 
16879b6dd12eSRobert Watson 	return (0);
16889b6dd12eSRobert Watson }
16899b6dd12eSRobert Watson 
16909b6dd12eSRobert Watson static int
16919b6dd12eSRobert Watson mls_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
16929b6dd12eSRobert Watson     struct shmfd *shmfd, struct label *shmlabel)
16939b6dd12eSRobert Watson {
16949b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
16959b6dd12eSRobert Watson 
16969b6dd12eSRobert Watson 	if (!mls_enabled)
16979b6dd12eSRobert Watson 		return (0);
16989b6dd12eSRobert Watson 
16999b6dd12eSRobert Watson 	subj = SLOT(active_cred->cr_label);
17009b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
17019b6dd12eSRobert Watson 
17029b6dd12eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
17039b6dd12eSRobert Watson 		return (EACCES);
17049b6dd12eSRobert Watson 
17059b6dd12eSRobert Watson 	return (0);
17069b6dd12eSRobert Watson }
17079b6dd12eSRobert Watson 
17089b6dd12eSRobert Watson static int
17099b6dd12eSRobert Watson mls_posixshm_check_truncate(struct ucred *active_cred,
17109b6dd12eSRobert Watson     struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
17119b6dd12eSRobert Watson {
17129b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
17139b6dd12eSRobert Watson 
17149b6dd12eSRobert Watson 	if (!mls_enabled)
17159b6dd12eSRobert Watson 		return (0);
17169b6dd12eSRobert Watson 
17179b6dd12eSRobert Watson 	subj = SLOT(active_cred->cr_label);
17189b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
17199b6dd12eSRobert Watson 
17209b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
17219b6dd12eSRobert Watson 		return (EACCES);
17229b6dd12eSRobert Watson 
17239b6dd12eSRobert Watson 	return (0);
17249b6dd12eSRobert Watson }
17259b6dd12eSRobert Watson 
17269b6dd12eSRobert Watson static int
17279b6dd12eSRobert Watson mls_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
17289b6dd12eSRobert Watson     struct label *shmlabel)
17299b6dd12eSRobert Watson {
17309b6dd12eSRobert Watson 	struct mac_mls *subj, *obj;
17319b6dd12eSRobert Watson 
17329b6dd12eSRobert Watson 	if (!mls_enabled)
17339b6dd12eSRobert Watson 		return (0);
17349b6dd12eSRobert Watson 
17359b6dd12eSRobert Watson 	subj = SLOT(cred->cr_label);
17369b6dd12eSRobert Watson 	obj = SLOT(shmlabel);
17379b6dd12eSRobert Watson 
17389b6dd12eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
17399b6dd12eSRobert Watson 		return (EACCES);
17409b6dd12eSRobert Watson 
17419b6dd12eSRobert Watson 	return (0);
17429b6dd12eSRobert Watson }
17439b6dd12eSRobert Watson 
1744940cb0e2SKonstantin Belousov static int
1745940cb0e2SKonstantin Belousov mls_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
1746940cb0e2SKonstantin Belousov     struct shmfd *shm, struct label *shmlabel)
1747940cb0e2SKonstantin Belousov {
1748940cb0e2SKonstantin Belousov 	struct mac_mls *subj, *obj;
1749940cb0e2SKonstantin Belousov 
1750940cb0e2SKonstantin Belousov 	if (!mls_enabled || !revocation_enabled)
1751940cb0e2SKonstantin Belousov 		return (0);
1752940cb0e2SKonstantin Belousov 
1753940cb0e2SKonstantin Belousov 	subj = SLOT(active_cred->cr_label);
1754940cb0e2SKonstantin Belousov 	obj = SLOT(shmlabel);
1755940cb0e2SKonstantin Belousov 
1756940cb0e2SKonstantin Belousov 	if (!mls_dominate_effective(subj, obj))
1757940cb0e2SKonstantin Belousov 		return (EACCES);
1758940cb0e2SKonstantin Belousov 
1759940cb0e2SKonstantin Belousov 	return (0);
1760940cb0e2SKonstantin Belousov }
1761940cb0e2SKonstantin Belousov 
17629b6dd12eSRobert Watson static void
17639b6dd12eSRobert Watson mls_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
17649b6dd12eSRobert Watson     struct label *shmlabel)
17659b6dd12eSRobert Watson {
17669b6dd12eSRobert Watson 	struct mac_mls *source, *dest;
17679b6dd12eSRobert Watson 
17689b6dd12eSRobert Watson 	source = SLOT(cred->cr_label);
17699b6dd12eSRobert Watson 	dest = SLOT(shmlabel);
17709b6dd12eSRobert Watson 
17719b6dd12eSRobert Watson 	mls_copy_effective(source, dest);
17729b6dd12eSRobert Watson }
17739b6dd12eSRobert Watson 
17749b6dd12eSRobert Watson static int
17753f1a7a90SRobert Watson mls_proc_check_debug(struct ucred *cred, struct proc *p)
1776d8a7b7a3SRobert Watson {
1777d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1778d8a7b7a3SRobert Watson 
17793f1a7a90SRobert Watson 	if (!mls_enabled)
1780d8a7b7a3SRobert Watson 		return (0);
1781d8a7b7a3SRobert Watson 
1782eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
178378007886SRobert Watson 	obj = SLOT(p->p_ucred->cr_label);
1784d8a7b7a3SRobert Watson 
1785d8a7b7a3SRobert Watson 	/* XXX: range checks */
17863f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1787d8a7b7a3SRobert Watson 		return (ESRCH);
17883f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
1789d8a7b7a3SRobert Watson 		return (EACCES);
1790d8a7b7a3SRobert Watson 
1791d8a7b7a3SRobert Watson 	return (0);
1792d8a7b7a3SRobert Watson }
1793d8a7b7a3SRobert Watson 
1794d8a7b7a3SRobert Watson static int
17953f1a7a90SRobert Watson mls_proc_check_sched(struct ucred *cred, struct proc *p)
1796d8a7b7a3SRobert Watson {
1797d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1798d8a7b7a3SRobert Watson 
17993f1a7a90SRobert Watson 	if (!mls_enabled)
1800d8a7b7a3SRobert Watson 		return (0);
1801d8a7b7a3SRobert Watson 
1802eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
180378007886SRobert Watson 	obj = SLOT(p->p_ucred->cr_label);
1804d8a7b7a3SRobert Watson 
1805d8a7b7a3SRobert Watson 	/* XXX: range checks */
18063f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1807d8a7b7a3SRobert Watson 		return (ESRCH);
18083f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
1809d8a7b7a3SRobert Watson 		return (EACCES);
1810d8a7b7a3SRobert Watson 
1811d8a7b7a3SRobert Watson 	return (0);
1812d8a7b7a3SRobert Watson }
1813d8a7b7a3SRobert Watson 
1814d8a7b7a3SRobert Watson static int
18153f1a7a90SRobert Watson mls_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1816d8a7b7a3SRobert Watson {
1817d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1818d8a7b7a3SRobert Watson 
18193f1a7a90SRobert Watson 	if (!mls_enabled)
1820d8a7b7a3SRobert Watson 		return (0);
1821d8a7b7a3SRobert Watson 
1822eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
182378007886SRobert Watson 	obj = SLOT(p->p_ucred->cr_label);
1824d8a7b7a3SRobert Watson 
1825d8a7b7a3SRobert Watson 	/* XXX: range checks */
18263f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
1827d8a7b7a3SRobert Watson 		return (ESRCH);
18283f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
1829d8a7b7a3SRobert Watson 		return (EACCES);
1830d8a7b7a3SRobert Watson 
1831d8a7b7a3SRobert Watson 	return (0);
1832d8a7b7a3SRobert Watson }
1833d8a7b7a3SRobert Watson 
1834d8a7b7a3SRobert Watson static int
18353f1a7a90SRobert Watson mls_socket_check_deliver(struct socket *so, struct label *solabel,
183678007886SRobert Watson     struct mbuf *m, struct label *mlabel)
1837d8a7b7a3SRobert Watson {
1838d8a7b7a3SRobert Watson 	struct mac_mls *p, *s;
18393de40469SRobert Watson 	int error;
1840d8a7b7a3SRobert Watson 
18413f1a7a90SRobert Watson 	if (!mls_enabled)
1842d8a7b7a3SRobert Watson 		return (0);
1843d8a7b7a3SRobert Watson 
184478007886SRobert Watson 	p = SLOT(mlabel);
184578007886SRobert Watson 	s = SLOT(solabel);
1846d8a7b7a3SRobert Watson 
18473de40469SRobert Watson 	SOCK_LOCK(so);
18483de40469SRobert Watson 	error = mls_equal_effective(p, s) ? 0 : EACCES;
18493de40469SRobert Watson 	SOCK_UNLOCK(so);
18503de40469SRobert Watson 
18513de40469SRobert Watson 	return (error);
1852d8a7b7a3SRobert Watson }
1853d8a7b7a3SRobert Watson 
1854d8a7b7a3SRobert Watson static int
18553f1a7a90SRobert Watson mls_socket_check_relabel(struct ucred *cred, struct socket *so,
185678007886SRobert Watson     struct label *solabel, struct label *newlabel)
1857d8a7b7a3SRobert Watson {
1858d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj, *new;
1859b5f072b5SRobert Watson 	int error;
1860d8a7b7a3SRobert Watson 
18613de40469SRobert Watson 	SOCK_LOCK_ASSERT(so);
18623de40469SRobert Watson 
1863d8a7b7a3SRobert Watson 	new = SLOT(newlabel);
1864eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
186578007886SRobert Watson 	obj = SLOT(solabel);
1866d8a7b7a3SRobert Watson 
1867b5f072b5SRobert Watson 	/*
18683f1a7a90SRobert Watson 	 * If there is an MLS label update for the socket, it may be an
18693f1a7a90SRobert Watson 	 * update of effective.
1870b5f072b5SRobert Watson 	 */
1871dee57980SRobert Watson 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
1872b5f072b5SRobert Watson 	if (error)
1873b5f072b5SRobert Watson 		return (error);
1874d8a7b7a3SRobert Watson 
1875d8a7b7a3SRobert Watson 	/*
18763f1a7a90SRobert Watson 	 * To relabel a socket, the old socket effective must be in the
18773f1a7a90SRobert Watson 	 * subject range.
1878d8a7b7a3SRobert Watson 	 */
18793f1a7a90SRobert Watson 	if (!mls_effective_in_range(obj, subj))
1880d8a7b7a3SRobert Watson 		return (EPERM);
1881d8a7b7a3SRobert Watson 
1882d8a7b7a3SRobert Watson 	/*
1883b5f072b5SRobert Watson 	 * If the MLS label is to be changed, authorize as appropriate.
1884b5f072b5SRobert Watson 	 */
1885dee57980SRobert Watson 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
1886b5f072b5SRobert Watson 		/*
1887dee57980SRobert Watson 		 * To relabel a socket, the new socket effective must be in
1888b5f072b5SRobert Watson 		 * the subject range.
1889d8a7b7a3SRobert Watson 		 */
18903f1a7a90SRobert Watson 		if (!mls_effective_in_range(new, subj))
1891d8a7b7a3SRobert Watson 			return (EPERM);
1892d8a7b7a3SRobert Watson 
1893d8a7b7a3SRobert Watson 		/*
1894b5f072b5SRobert Watson 		 * To change the MLS label on the socket to contain EQUAL,
1895b5f072b5SRobert Watson 		 * the subject must have appropriate privilege.
1896d8a7b7a3SRobert Watson 		 */
18973f1a7a90SRobert Watson 		if (mls_contains_equal(new)) {
18983f1a7a90SRobert Watson 			error = mls_subject_privileged(subj);
1899b5f072b5SRobert Watson 			if (error)
1900b5f072b5SRobert Watson 				return (error);
1901b5f072b5SRobert Watson 		}
1902b5f072b5SRobert Watson 	}
1903d8a7b7a3SRobert Watson 
1904d8a7b7a3SRobert Watson 	return (0);
1905d8a7b7a3SRobert Watson }
1906d8a7b7a3SRobert Watson 
1907d8a7b7a3SRobert Watson static int
19083f1a7a90SRobert Watson mls_socket_check_visible(struct ucred *cred, struct socket *so,
190978007886SRobert Watson     struct label *solabel)
1910d8a7b7a3SRobert Watson {
1911d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
1912d8a7b7a3SRobert Watson 
19133f1a7a90SRobert Watson 	if (!mls_enabled)
1914d8a7b7a3SRobert Watson 		return (0);
1915d8a7b7a3SRobert Watson 
1916eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
191778007886SRobert Watson 	obj = SLOT(solabel);
1918d8a7b7a3SRobert Watson 
19193de40469SRobert Watson 	SOCK_LOCK(so);
19203de40469SRobert Watson 	if (!mls_dominate_effective(subj, obj)) {
19213de40469SRobert Watson 		SOCK_UNLOCK(so);
1922d8a7b7a3SRobert Watson 		return (ENOENT);
19233de40469SRobert Watson 	}
19243de40469SRobert Watson 	SOCK_UNLOCK(so);
1925d8a7b7a3SRobert Watson 
1926d8a7b7a3SRobert Watson 	return (0);
1927d8a7b7a3SRobert Watson }
1928d8a7b7a3SRobert Watson 
1929eb320b0eSRobert Watson static void
1930eb320b0eSRobert Watson mls_socket_create(struct ucred *cred, struct socket *so,
1931eb320b0eSRobert Watson     struct label *solabel)
1932eb320b0eSRobert Watson {
1933eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1934eb320b0eSRobert Watson 
1935eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
1936eb320b0eSRobert Watson 	dest = SLOT(solabel);
1937eb320b0eSRobert Watson 
1938eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
1939eb320b0eSRobert Watson }
1940eb320b0eSRobert Watson 
1941eb320b0eSRobert Watson static void
1942eb320b0eSRobert Watson mls_socket_create_mbuf(struct socket *so, struct label *solabel,
1943eb320b0eSRobert Watson     struct mbuf *m, struct label *mlabel)
1944eb320b0eSRobert Watson {
1945eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1946eb320b0eSRobert Watson 
1947eb320b0eSRobert Watson 	source = SLOT(solabel);
1948eb320b0eSRobert Watson 	dest = SLOT(mlabel);
1949eb320b0eSRobert Watson 
19503de40469SRobert Watson 	SOCK_LOCK(so);
1951eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
19523de40469SRobert Watson 	SOCK_UNLOCK(so);
1953eb320b0eSRobert Watson }
1954eb320b0eSRobert Watson 
1955eb320b0eSRobert Watson static void
1956eb320b0eSRobert Watson mls_socket_newconn(struct socket *oldso, struct label *oldsolabel,
1957eb320b0eSRobert Watson     struct socket *newso, struct label *newsolabel)
1958eb320b0eSRobert Watson {
19593de40469SRobert Watson 	struct mac_mls source, *dest;
1960eb320b0eSRobert Watson 
19613de40469SRobert Watson 	SOCK_LOCK(oldso);
19623de40469SRobert Watson 	source = *SLOT(oldsolabel);
19633de40469SRobert Watson 	SOCK_UNLOCK(oldso);
19643de40469SRobert Watson 
1965eb320b0eSRobert Watson 	dest = SLOT(newsolabel);
1966eb320b0eSRobert Watson 
19673de40469SRobert Watson 	SOCK_LOCK(newso);
19683de40469SRobert Watson 	mls_copy_effective(&source, dest);
19693de40469SRobert Watson 	SOCK_UNLOCK(newso);
1970eb320b0eSRobert Watson }
1971eb320b0eSRobert Watson 
1972eb320b0eSRobert Watson static void
1973eb320b0eSRobert Watson mls_socket_relabel(struct ucred *cred, struct socket *so,
1974eb320b0eSRobert Watson     struct label *solabel, struct label *newlabel)
1975eb320b0eSRobert Watson {
1976eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1977eb320b0eSRobert Watson 
19783de40469SRobert Watson 	SOCK_LOCK_ASSERT(so);
19793de40469SRobert Watson 
1980eb320b0eSRobert Watson 	source = SLOT(newlabel);
1981eb320b0eSRobert Watson 	dest = SLOT(solabel);
1982eb320b0eSRobert Watson 
1983eb320b0eSRobert Watson 	mls_copy(source, dest);
1984eb320b0eSRobert Watson }
1985eb320b0eSRobert Watson 
1986eb320b0eSRobert Watson static void
1987eb320b0eSRobert Watson mls_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
1988eb320b0eSRobert Watson     struct socket *so, struct label *sopeerlabel)
1989eb320b0eSRobert Watson {
1990eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
1991eb320b0eSRobert Watson 
1992eb320b0eSRobert Watson 	source = SLOT(mlabel);
1993eb320b0eSRobert Watson 	dest = SLOT(sopeerlabel);
1994eb320b0eSRobert Watson 
19953de40469SRobert Watson 	SOCK_LOCK(so);
1996eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
19973de40469SRobert Watson 	SOCK_UNLOCK(so);
1998eb320b0eSRobert Watson }
1999eb320b0eSRobert Watson 
2000eb320b0eSRobert Watson static void
2001eb320b0eSRobert Watson mls_socketpeer_set_from_socket(struct socket *oldso,
2002eb320b0eSRobert Watson     struct label *oldsolabel, struct socket *newso,
2003eb320b0eSRobert Watson     struct label *newsopeerlabel)
2004eb320b0eSRobert Watson {
20053de40469SRobert Watson 	struct mac_mls source, *dest;
2006eb320b0eSRobert Watson 
20073de40469SRobert Watson 	SOCK_LOCK(oldso);
20083de40469SRobert Watson 	source = *SLOT(oldsolabel);
20093de40469SRobert Watson 	SOCK_UNLOCK(oldso);
20103de40469SRobert Watson 
2011eb320b0eSRobert Watson 	dest = SLOT(newsopeerlabel);
2012eb320b0eSRobert Watson 
20133de40469SRobert Watson 	SOCK_LOCK(newso);
20143de40469SRobert Watson 	mls_copy_effective(&source, dest);
20153de40469SRobert Watson 	SOCK_UNLOCK(newso);
2016eb320b0eSRobert Watson }
2017eb320b0eSRobert Watson 
2018eb320b0eSRobert Watson static void
2019eb320b0eSRobert Watson mls_syncache_create(struct label *label, struct inpcb *inp)
2020eb320b0eSRobert Watson {
2021eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2022eb320b0eSRobert Watson 
2023eb320b0eSRobert Watson 	source = SLOT(inp->inp_label);
2024eb320b0eSRobert Watson 	dest = SLOT(label);
2025eb320b0eSRobert Watson 
2026eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2027eb320b0eSRobert Watson }
2028eb320b0eSRobert Watson 
2029eb320b0eSRobert Watson static void
2030eb320b0eSRobert Watson mls_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2031eb320b0eSRobert Watson     struct label *mlabel)
2032eb320b0eSRobert Watson {
2033eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2034eb320b0eSRobert Watson 
2035eb320b0eSRobert Watson 	source = SLOT(sc_label);
2036eb320b0eSRobert Watson 	dest = SLOT(mlabel);
2037eb320b0eSRobert Watson 
2038eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2039eb320b0eSRobert Watson }
2040eb320b0eSRobert Watson 
2041d8a7b7a3SRobert Watson static int
20423f1a7a90SRobert Watson mls_system_check_acct(struct ucred *cred, struct vnode *vp,
204378007886SRobert Watson     struct label *vplabel)
204418717f69SRobert Watson {
204518717f69SRobert Watson 	struct mac_mls *subj, *obj;
204618717f69SRobert Watson 
20473f1a7a90SRobert Watson 	if (!mls_enabled)
204818717f69SRobert Watson 		return (0);
204918717f69SRobert Watson 
2050e623c220SChristian Brueffer 	if (vplabel == NULL)
2051e623c220SChristian Brueffer 		return (0);
2052e623c220SChristian Brueffer 
205318717f69SRobert Watson 	subj = SLOT(cred->cr_label);
205478007886SRobert Watson 	obj = SLOT(vplabel);
205518717f69SRobert Watson 
20563f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj) ||
20573f1a7a90SRobert Watson 	    !mls_dominate_effective(subj, obj))
205818717f69SRobert Watson 		return (EACCES);
205918717f69SRobert Watson 
206018717f69SRobert Watson 	return (0);
206118717f69SRobert Watson }
206218717f69SRobert Watson 
206318717f69SRobert Watson static int
20643f1a7a90SRobert Watson mls_system_check_auditctl(struct ucred *cred, struct vnode *vp,
206578007886SRobert Watson     struct label *vplabel)
206618717f69SRobert Watson {
206718717f69SRobert Watson 	struct mac_mls *subj, *obj;
206818717f69SRobert Watson 
20693f1a7a90SRobert Watson 	if (!mls_enabled)
207018717f69SRobert Watson 		return (0);
207118717f69SRobert Watson 
207218717f69SRobert Watson 	subj = SLOT(cred->cr_label);
207378007886SRobert Watson 	obj = SLOT(vplabel);
207418717f69SRobert Watson 
20753f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj) ||
20763f1a7a90SRobert Watson 	    !mls_dominate_effective(subj, obj))
207718717f69SRobert Watson 		return (EACCES);
207818717f69SRobert Watson 
207918717f69SRobert Watson 	return (0);
208018717f69SRobert Watson }
208118717f69SRobert Watson 
208218717f69SRobert Watson static int
20833f1a7a90SRobert Watson mls_system_check_swapon(struct ucred *cred, struct vnode *vp,
208478007886SRobert Watson     struct label *vplabel)
20854c64787aSRobert Watson {
20864c64787aSRobert Watson 	struct mac_mls *subj, *obj;
20874c64787aSRobert Watson 
20883f1a7a90SRobert Watson 	if (!mls_enabled)
20894c64787aSRobert Watson 		return (0);
20904c64787aSRobert Watson 
2091eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
209278007886SRobert Watson 	obj = SLOT(vplabel);
20934c64787aSRobert Watson 
20943f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj) ||
20953f1a7a90SRobert Watson 	    !mls_dominate_effective(subj, obj))
20964c64787aSRobert Watson 		return (EACCES);
20974c64787aSRobert Watson 
20984c64787aSRobert Watson 	return (0);
20994c64787aSRobert Watson }
21004c64787aSRobert Watson 
2101eb320b0eSRobert Watson static void
2102eb320b0eSRobert Watson mls_sysvmsg_cleanup(struct label *msglabel)
2103eb320b0eSRobert Watson {
2104eb320b0eSRobert Watson 
2105eb320b0eSRobert Watson 	bzero(SLOT(msglabel), sizeof(struct mac_mls));
2106eb320b0eSRobert Watson }
2107eb320b0eSRobert Watson 
2108eb320b0eSRobert Watson static void
2109eb320b0eSRobert Watson mls_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2110eb320b0eSRobert Watson     struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
2111eb320b0eSRobert Watson {
2112eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2113eb320b0eSRobert Watson 
2114eb320b0eSRobert Watson 	/* Ignore the msgq label. */
2115eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
2116eb320b0eSRobert Watson 	dest = SLOT(msglabel);
2117eb320b0eSRobert Watson 
2118eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2119eb320b0eSRobert Watson }
2120eb320b0eSRobert Watson 
2121eb320b0eSRobert Watson static int
2122eb320b0eSRobert Watson mls_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
2123eb320b0eSRobert Watson     struct label *msglabel)
2124eb320b0eSRobert Watson {
2125eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2126eb320b0eSRobert Watson 
2127eb320b0eSRobert Watson 	if (!mls_enabled)
2128eb320b0eSRobert Watson 		return (0);
2129eb320b0eSRobert Watson 
2130eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2131eb320b0eSRobert Watson 	obj = SLOT(msglabel);
2132eb320b0eSRobert Watson 
2133eb320b0eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
2134eb320b0eSRobert Watson 		return (EACCES);
2135eb320b0eSRobert Watson 
2136eb320b0eSRobert Watson 	return (0);
2137eb320b0eSRobert Watson }
2138eb320b0eSRobert Watson 
2139eb320b0eSRobert Watson static int
2140eb320b0eSRobert Watson mls_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
2141eb320b0eSRobert Watson     struct label *msglabel)
2142eb320b0eSRobert Watson {
2143eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2144eb320b0eSRobert Watson 
2145eb320b0eSRobert Watson 	if (!mls_enabled)
2146eb320b0eSRobert Watson 		return (0);
2147eb320b0eSRobert Watson 
2148eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2149eb320b0eSRobert Watson 	obj = SLOT(msglabel);
2150eb320b0eSRobert Watson 
2151eb320b0eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
2152eb320b0eSRobert Watson 		return (EACCES);
2153eb320b0eSRobert Watson 
2154eb320b0eSRobert Watson 	return (0);
2155eb320b0eSRobert Watson }
2156eb320b0eSRobert Watson 
2157eb320b0eSRobert Watson static int
2158eb320b0eSRobert Watson mls_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
2159eb320b0eSRobert Watson     struct label *msqklabel)
2160eb320b0eSRobert Watson {
2161eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2162eb320b0eSRobert Watson 
2163eb320b0eSRobert Watson 	if (!mls_enabled)
2164eb320b0eSRobert Watson 		return (0);
2165eb320b0eSRobert Watson 
2166eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2167eb320b0eSRobert Watson 	obj = SLOT(msqklabel);
2168eb320b0eSRobert Watson 
2169eb320b0eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
2170eb320b0eSRobert Watson 		return (EACCES);
2171eb320b0eSRobert Watson 
2172eb320b0eSRobert Watson 	return (0);
2173eb320b0eSRobert Watson }
2174eb320b0eSRobert Watson 
2175eb320b0eSRobert Watson static int
2176eb320b0eSRobert Watson mls_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
2177eb320b0eSRobert Watson     struct label *msqklabel)
2178eb320b0eSRobert Watson {
2179eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2180eb320b0eSRobert Watson 
2181eb320b0eSRobert Watson 	if (!mls_enabled)
2182eb320b0eSRobert Watson 		return (0);
2183eb320b0eSRobert Watson 
2184eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2185eb320b0eSRobert Watson 	obj = SLOT(msqklabel);
2186eb320b0eSRobert Watson 
2187eb320b0eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
2188eb320b0eSRobert Watson 		return (EACCES);
2189eb320b0eSRobert Watson 
2190eb320b0eSRobert Watson 	return (0);
2191eb320b0eSRobert Watson }
2192eb320b0eSRobert Watson 
2193eb320b0eSRobert Watson static int
2194eb320b0eSRobert Watson mls_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
2195eb320b0eSRobert Watson     struct label *msqklabel)
2196eb320b0eSRobert Watson {
2197eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2198eb320b0eSRobert Watson 
2199eb320b0eSRobert Watson 	if (!mls_enabled)
2200eb320b0eSRobert Watson 		return (0);
2201eb320b0eSRobert Watson 
2202eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2203eb320b0eSRobert Watson 	obj = SLOT(msqklabel);
2204eb320b0eSRobert Watson 
2205eb320b0eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
2206eb320b0eSRobert Watson 		return (EACCES);
2207eb320b0eSRobert Watson 
2208eb320b0eSRobert Watson 	return (0);
2209eb320b0eSRobert Watson }
2210eb320b0eSRobert Watson 
2211eb320b0eSRobert Watson static int
2212eb320b0eSRobert Watson mls_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2213eb320b0eSRobert Watson     struct label *msqklabel, int cmd)
2214eb320b0eSRobert Watson {
2215eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2216eb320b0eSRobert Watson 
2217eb320b0eSRobert Watson 	if (!mls_enabled)
2218eb320b0eSRobert Watson 		return (0);
2219eb320b0eSRobert Watson 
2220eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2221eb320b0eSRobert Watson 	obj = SLOT(msqklabel);
2222eb320b0eSRobert Watson 
2223eb320b0eSRobert Watson 	switch(cmd) {
2224eb320b0eSRobert Watson 	case IPC_RMID:
2225eb320b0eSRobert Watson 	case IPC_SET:
2226eb320b0eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
2227eb320b0eSRobert Watson 			return (EACCES);
2228eb320b0eSRobert Watson 		break;
2229eb320b0eSRobert Watson 
2230eb320b0eSRobert Watson 	case IPC_STAT:
2231eb320b0eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
2232eb320b0eSRobert Watson 			return (EACCES);
2233eb320b0eSRobert Watson 		break;
2234eb320b0eSRobert Watson 
2235eb320b0eSRobert Watson 	default:
2236eb320b0eSRobert Watson 		return (EACCES);
2237eb320b0eSRobert Watson 	}
2238eb320b0eSRobert Watson 
2239eb320b0eSRobert Watson 	return (0);
2240eb320b0eSRobert Watson }
2241eb320b0eSRobert Watson 
2242eb320b0eSRobert Watson static void
2243eb320b0eSRobert Watson mls_sysvmsq_cleanup(struct label *msqlabel)
2244eb320b0eSRobert Watson {
2245eb320b0eSRobert Watson 
2246eb320b0eSRobert Watson 	bzero(SLOT(msqlabel), sizeof(struct mac_mls));
2247eb320b0eSRobert Watson }
2248eb320b0eSRobert Watson 
2249eb320b0eSRobert Watson static void
2250eb320b0eSRobert Watson mls_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2251eb320b0eSRobert Watson     struct label *msqlabel)
2252eb320b0eSRobert Watson {
2253eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2254eb320b0eSRobert Watson 
2255eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
2256eb320b0eSRobert Watson 	dest = SLOT(msqlabel);
2257eb320b0eSRobert Watson 
2258eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2259eb320b0eSRobert Watson }
2260eb320b0eSRobert Watson 
2261eb320b0eSRobert Watson static int
2262eb320b0eSRobert Watson mls_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2263eb320b0eSRobert Watson     struct label *semaklabel, int cmd)
2264eb320b0eSRobert Watson {
2265eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2266eb320b0eSRobert Watson 
2267eb320b0eSRobert Watson 	if (!mls_enabled)
2268eb320b0eSRobert Watson 		return (0);
2269eb320b0eSRobert Watson 
2270eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2271eb320b0eSRobert Watson 	obj = SLOT(semaklabel);
2272eb320b0eSRobert Watson 
2273eb320b0eSRobert Watson 	switch(cmd) {
2274eb320b0eSRobert Watson 	case IPC_RMID:
2275eb320b0eSRobert Watson 	case IPC_SET:
2276eb320b0eSRobert Watson 	case SETVAL:
2277eb320b0eSRobert Watson 	case SETALL:
2278eb320b0eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
2279eb320b0eSRobert Watson 			return (EACCES);
2280eb320b0eSRobert Watson 		break;
2281eb320b0eSRobert Watson 
2282eb320b0eSRobert Watson 	case IPC_STAT:
2283eb320b0eSRobert Watson 	case GETVAL:
2284eb320b0eSRobert Watson 	case GETPID:
2285eb320b0eSRobert Watson 	case GETNCNT:
2286eb320b0eSRobert Watson 	case GETZCNT:
2287eb320b0eSRobert Watson 	case GETALL:
2288eb320b0eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
2289eb320b0eSRobert Watson 			return (EACCES);
2290eb320b0eSRobert Watson 		break;
2291eb320b0eSRobert Watson 
2292eb320b0eSRobert Watson 	default:
2293eb320b0eSRobert Watson 		return (EACCES);
2294eb320b0eSRobert Watson 	}
2295eb320b0eSRobert Watson 
2296eb320b0eSRobert Watson 	return (0);
2297eb320b0eSRobert Watson }
2298eb320b0eSRobert Watson 
2299eb320b0eSRobert Watson static int
2300eb320b0eSRobert Watson mls_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2301eb320b0eSRobert Watson     struct label *semaklabel)
2302eb320b0eSRobert Watson {
2303eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2304eb320b0eSRobert Watson 
2305eb320b0eSRobert Watson 	if (!mls_enabled)
2306eb320b0eSRobert Watson 		return (0);
2307eb320b0eSRobert Watson 
2308eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2309eb320b0eSRobert Watson 	obj = SLOT(semaklabel);
2310eb320b0eSRobert Watson 
2311eb320b0eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
2312eb320b0eSRobert Watson 		return (EACCES);
2313eb320b0eSRobert Watson 
2314eb320b0eSRobert Watson 	return (0);
2315eb320b0eSRobert Watson }
2316eb320b0eSRobert Watson 
2317eb320b0eSRobert Watson static int
2318eb320b0eSRobert Watson mls_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2319eb320b0eSRobert Watson     struct label *semaklabel, size_t accesstype)
2320eb320b0eSRobert Watson {
2321eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2322eb320b0eSRobert Watson 
2323eb320b0eSRobert Watson 	if (!mls_enabled)
2324eb320b0eSRobert Watson 		return (0);
2325eb320b0eSRobert Watson 
2326eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2327eb320b0eSRobert Watson 	obj = SLOT(semaklabel);
2328eb320b0eSRobert Watson 
2329eb320b0eSRobert Watson 	if( accesstype & SEM_R )
2330eb320b0eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
2331eb320b0eSRobert Watson 			return (EACCES);
2332eb320b0eSRobert Watson 
2333eb320b0eSRobert Watson 	if( accesstype & SEM_A )
2334eb320b0eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
2335eb320b0eSRobert Watson 			return (EACCES);
2336eb320b0eSRobert Watson 
2337eb320b0eSRobert Watson 	return (0);
2338eb320b0eSRobert Watson }
2339eb320b0eSRobert Watson 
2340eb320b0eSRobert Watson static void
2341eb320b0eSRobert Watson mls_sysvsem_cleanup(struct label *semalabel)
2342eb320b0eSRobert Watson {
2343eb320b0eSRobert Watson 
2344eb320b0eSRobert Watson 	bzero(SLOT(semalabel), sizeof(struct mac_mls));
2345eb320b0eSRobert Watson }
2346eb320b0eSRobert Watson 
2347eb320b0eSRobert Watson static void
2348eb320b0eSRobert Watson mls_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2349eb320b0eSRobert Watson     struct label *semalabel)
2350eb320b0eSRobert Watson {
2351eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2352eb320b0eSRobert Watson 
2353eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
2354eb320b0eSRobert Watson 	dest = SLOT(semalabel);
2355eb320b0eSRobert Watson 
2356eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2357eb320b0eSRobert Watson }
2358eb320b0eSRobert Watson 
2359eb320b0eSRobert Watson static int
2360eb320b0eSRobert Watson mls_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2361eb320b0eSRobert Watson     struct label *shmseglabel, int shmflg)
2362eb320b0eSRobert Watson {
2363eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2364eb320b0eSRobert Watson 
2365eb320b0eSRobert Watson 	if (!mls_enabled)
2366eb320b0eSRobert Watson 		return (0);
2367eb320b0eSRobert Watson 
2368eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2369eb320b0eSRobert Watson 	obj = SLOT(shmseglabel);
2370eb320b0eSRobert Watson 
2371eb320b0eSRobert Watson 	if (!mls_dominate_effective(subj, obj))
2372eb320b0eSRobert Watson 		return (EACCES);
2373eb320b0eSRobert Watson 	if ((shmflg & SHM_RDONLY) == 0) {
2374eb320b0eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
2375eb320b0eSRobert Watson 			return (EACCES);
2376eb320b0eSRobert Watson 	}
2377eb320b0eSRobert Watson 
2378eb320b0eSRobert Watson 	return (0);
2379eb320b0eSRobert Watson }
2380eb320b0eSRobert Watson 
2381eb320b0eSRobert Watson static int
2382eb320b0eSRobert Watson mls_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2383eb320b0eSRobert Watson     struct label *shmseglabel, int cmd)
2384eb320b0eSRobert Watson {
2385eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2386eb320b0eSRobert Watson 
2387eb320b0eSRobert Watson 	if (!mls_enabled)
2388eb320b0eSRobert Watson 		return (0);
2389eb320b0eSRobert Watson 
2390eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2391eb320b0eSRobert Watson 	obj = SLOT(shmseglabel);
2392eb320b0eSRobert Watson 
2393eb320b0eSRobert Watson 	switch(cmd) {
2394eb320b0eSRobert Watson 	case IPC_RMID:
2395eb320b0eSRobert Watson 	case IPC_SET:
2396eb320b0eSRobert Watson 		if (!mls_dominate_effective(obj, subj))
2397eb320b0eSRobert Watson 			return (EACCES);
2398eb320b0eSRobert Watson 		break;
2399eb320b0eSRobert Watson 
2400eb320b0eSRobert Watson 	case IPC_STAT:
2401eb320b0eSRobert Watson 	case SHM_STAT:
2402eb320b0eSRobert Watson 		if (!mls_dominate_effective(subj, obj))
2403eb320b0eSRobert Watson 			return (EACCES);
2404eb320b0eSRobert Watson 		break;
2405eb320b0eSRobert Watson 
2406eb320b0eSRobert Watson 	default:
2407eb320b0eSRobert Watson 		return (EACCES);
2408eb320b0eSRobert Watson 	}
2409eb320b0eSRobert Watson 
2410eb320b0eSRobert Watson 	return (0);
2411eb320b0eSRobert Watson }
2412eb320b0eSRobert Watson 
2413eb320b0eSRobert Watson static int
2414eb320b0eSRobert Watson mls_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2415eb320b0eSRobert Watson     struct label *shmseglabel, int shmflg)
2416eb320b0eSRobert Watson {
2417eb320b0eSRobert Watson 	struct mac_mls *subj, *obj;
2418eb320b0eSRobert Watson 
2419eb320b0eSRobert Watson 	if (!mls_enabled)
2420eb320b0eSRobert Watson 		return (0);
2421eb320b0eSRobert Watson 
2422eb320b0eSRobert Watson 	subj = SLOT(cred->cr_label);
2423eb320b0eSRobert Watson 	obj = SLOT(shmseglabel);
2424eb320b0eSRobert Watson 
2425eb320b0eSRobert Watson 	if (!mls_dominate_effective(obj, subj))
2426eb320b0eSRobert Watson 		return (EACCES);
2427eb320b0eSRobert Watson 
2428eb320b0eSRobert Watson 	return (0);
2429eb320b0eSRobert Watson }
2430eb320b0eSRobert Watson 
2431eb320b0eSRobert Watson static void
2432eb320b0eSRobert Watson mls_sysvshm_cleanup(struct label *shmlabel)
2433eb320b0eSRobert Watson {
2434eb320b0eSRobert Watson 
2435eb320b0eSRobert Watson 	bzero(SLOT(shmlabel), sizeof(struct mac_mls));
2436eb320b0eSRobert Watson }
2437eb320b0eSRobert Watson 
2438eb320b0eSRobert Watson static void
2439eb320b0eSRobert Watson mls_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2440eb320b0eSRobert Watson     struct label *shmlabel)
2441eb320b0eSRobert Watson {
2442eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2443eb320b0eSRobert Watson 
2444eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
2445eb320b0eSRobert Watson 	dest = SLOT(shmlabel);
2446eb320b0eSRobert Watson 
2447eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2448eb320b0eSRobert Watson }
2449eb320b0eSRobert Watson 
2450eb320b0eSRobert Watson static int
2451eb320b0eSRobert Watson mls_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2452eb320b0eSRobert Watson     struct vnode *vp, struct label *vplabel)
2453eb320b0eSRobert Watson {
2454eb320b0eSRobert Watson 	struct mac_mls mm_temp, *source, *dest;
2455eb320b0eSRobert Watson 	int buflen, error;
2456eb320b0eSRobert Watson 
2457eb320b0eSRobert Watson 	source = SLOT(mplabel);
2458eb320b0eSRobert Watson 	dest = SLOT(vplabel);
2459eb320b0eSRobert Watson 
2460eb320b0eSRobert Watson 	buflen = sizeof(mm_temp);
2461eb320b0eSRobert Watson 	bzero(&mm_temp, buflen);
2462eb320b0eSRobert Watson 
2463eb320b0eSRobert Watson 	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
2464eb320b0eSRobert Watson 	    MAC_MLS_EXTATTR_NAME, &buflen, (char *) &mm_temp, curthread);
2465eb320b0eSRobert Watson 	if (error == ENOATTR || error == EOPNOTSUPP) {
2466eb320b0eSRobert Watson 		/* Fall back to the mntlabel. */
2467eb320b0eSRobert Watson 		mls_copy_effective(source, dest);
2468eb320b0eSRobert Watson 		return (0);
2469eb320b0eSRobert Watson 	} else if (error)
2470eb320b0eSRobert Watson 		return (error);
2471eb320b0eSRobert Watson 
2472eb320b0eSRobert Watson 	if (buflen != sizeof(mm_temp)) {
2473eb320b0eSRobert Watson 		printf("mls_vnode_associate_extattr: bad size %d\n", buflen);
2474eb320b0eSRobert Watson 		return (EPERM);
2475eb320b0eSRobert Watson 	}
2476eb320b0eSRobert Watson 	if (mls_valid(&mm_temp) != 0) {
2477eb320b0eSRobert Watson 		printf("mls_vnode_associate_extattr: invalid\n");
2478eb320b0eSRobert Watson 		return (EPERM);
2479eb320b0eSRobert Watson 	}
2480eb320b0eSRobert Watson 	if ((mm_temp.mm_flags & MAC_MLS_FLAGS_BOTH) !=
2481eb320b0eSRobert Watson 	    MAC_MLS_FLAG_EFFECTIVE) {
2482eb320b0eSRobert Watson 		printf("mls_associated_vnode_extattr: not effective\n");
2483eb320b0eSRobert Watson 		return (EPERM);
2484eb320b0eSRobert Watson 	}
2485eb320b0eSRobert Watson 
2486eb320b0eSRobert Watson 	mls_copy_effective(&mm_temp, dest);
2487eb320b0eSRobert Watson 	return (0);
2488eb320b0eSRobert Watson }
2489eb320b0eSRobert Watson 
2490eb320b0eSRobert Watson static void
2491eb320b0eSRobert Watson mls_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2492eb320b0eSRobert Watson     struct vnode *vp, struct label *vplabel)
2493eb320b0eSRobert Watson {
2494eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
2495eb320b0eSRobert Watson 
2496eb320b0eSRobert Watson 	source = SLOT(mplabel);
2497eb320b0eSRobert Watson 	dest = SLOT(vplabel);
2498eb320b0eSRobert Watson 
2499eb320b0eSRobert Watson 	mls_copy_effective(source, dest);
2500eb320b0eSRobert Watson }
2501eb320b0eSRobert Watson 
25024c64787aSRobert Watson static int
25033f1a7a90SRobert Watson mls_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
250478007886SRobert Watson     struct label *dvplabel)
2505d8a7b7a3SRobert Watson {
2506d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2507d8a7b7a3SRobert Watson 
25083f1a7a90SRobert Watson 	if (!mls_enabled)
2509d8a7b7a3SRobert Watson 		return (0);
2510d8a7b7a3SRobert Watson 
2511eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
251278007886SRobert Watson 	obj = SLOT(dvplabel);
2513d8a7b7a3SRobert Watson 
25143f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2515d8a7b7a3SRobert Watson 		return (EACCES);
2516d8a7b7a3SRobert Watson 
2517d8a7b7a3SRobert Watson 	return (0);
2518d8a7b7a3SRobert Watson }
2519d8a7b7a3SRobert Watson 
2520d8a7b7a3SRobert Watson static int
25213f1a7a90SRobert Watson mls_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
252278007886SRobert Watson     struct label *dvplabel)
2523d8a7b7a3SRobert Watson {
2524d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2525d8a7b7a3SRobert Watson 
25263f1a7a90SRobert Watson 	if (!mls_enabled)
2527d8a7b7a3SRobert Watson 		return (0);
2528d8a7b7a3SRobert Watson 
2529eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
253078007886SRobert Watson 	obj = SLOT(dvplabel);
2531d8a7b7a3SRobert Watson 
25323f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2533d8a7b7a3SRobert Watson 		return (EACCES);
2534d8a7b7a3SRobert Watson 
2535d8a7b7a3SRobert Watson 	return (0);
2536d8a7b7a3SRobert Watson }
2537d8a7b7a3SRobert Watson 
2538d8a7b7a3SRobert Watson static int
25393f1a7a90SRobert Watson mls_vnode_check_create(struct ucred *cred, struct vnode *dvp,
254078007886SRobert Watson     struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2541d8a7b7a3SRobert Watson {
2542d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2543d8a7b7a3SRobert Watson 
25443f1a7a90SRobert Watson 	if (!mls_enabled)
2545d8a7b7a3SRobert Watson 		return (0);
2546d8a7b7a3SRobert Watson 
2547eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
254878007886SRobert Watson 	obj = SLOT(dvplabel);
2549d8a7b7a3SRobert Watson 
25503f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2551d8a7b7a3SRobert Watson 		return (EACCES);
2552d8a7b7a3SRobert Watson 
2553d8a7b7a3SRobert Watson 	return (0);
2554d8a7b7a3SRobert Watson }
2555d8a7b7a3SRobert Watson 
2556d8a7b7a3SRobert Watson static int
25573f1a7a90SRobert Watson mls_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
255878007886SRobert Watson     struct label *vplabel, acl_type_t type)
2559d8a7b7a3SRobert Watson {
2560d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2561d8a7b7a3SRobert Watson 
25623f1a7a90SRobert Watson 	if (!mls_enabled)
2563d8a7b7a3SRobert Watson 		return (0);
2564d8a7b7a3SRobert Watson 
2565eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
256678007886SRobert Watson 	obj = SLOT(vplabel);
2567d8a7b7a3SRobert Watson 
25683f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2569d8a7b7a3SRobert Watson 		return (EACCES);
2570d8a7b7a3SRobert Watson 
2571d8a7b7a3SRobert Watson 	return (0);
2572d8a7b7a3SRobert Watson }
2573d8a7b7a3SRobert Watson 
2574d8a7b7a3SRobert Watson static int
25753f1a7a90SRobert Watson mls_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
257678007886SRobert Watson     struct label *vplabel, int attrnamespace, const char *name)
257754e2c147SRobert Watson {
257854e2c147SRobert Watson 	struct mac_mls *subj, *obj;
257954e2c147SRobert Watson 
25803f1a7a90SRobert Watson 	if (!mls_enabled)
258154e2c147SRobert Watson 		return (0);
258254e2c147SRobert Watson 
2583eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
258478007886SRobert Watson 	obj = SLOT(vplabel);
258554e2c147SRobert Watson 
25863f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
258754e2c147SRobert Watson 		return (EACCES);
258854e2c147SRobert Watson 
258954e2c147SRobert Watson 	return (0);
259054e2c147SRobert Watson }
259154e2c147SRobert Watson 
259254e2c147SRobert Watson static int
25933f1a7a90SRobert Watson mls_vnode_check_exec(struct ucred *cred, struct vnode *vp,
259478007886SRobert Watson     struct label *vplabel, struct image_params *imgp,
2595ef5def59SRobert Watson     struct label *execlabel)
2596d8a7b7a3SRobert Watson {
2597ef5def59SRobert Watson 	struct mac_mls *subj, *obj, *exec;
2598ef5def59SRobert Watson 	int error;
2599ef5def59SRobert Watson 
2600ef5def59SRobert Watson 	if (execlabel != NULL) {
2601ef5def59SRobert Watson 		/*
2602ef5def59SRobert Watson 		 * We currently don't permit labels to be changed at
26033f1a7a90SRobert Watson 		 * exec-time as part of MLS, so disallow non-NULL MLS label
26043f1a7a90SRobert Watson 		 * elements in the execlabel.
2605ef5def59SRobert Watson 		 */
2606ef5def59SRobert Watson 		exec = SLOT(execlabel);
2607ef5def59SRobert Watson 		error = mls_atmostflags(exec, 0);
2608ef5def59SRobert Watson 		if (error)
2609ef5def59SRobert Watson 			return (error);
2610ef5def59SRobert Watson 	}
2611d8a7b7a3SRobert Watson 
26123f1a7a90SRobert Watson 	if (!mls_enabled)
2613d8a7b7a3SRobert Watson 		return (0);
2614d8a7b7a3SRobert Watson 
2615eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
261678007886SRobert Watson 	obj = SLOT(vplabel);
2617d8a7b7a3SRobert Watson 
26183f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2619d8a7b7a3SRobert Watson 		return (EACCES);
2620d8a7b7a3SRobert Watson 
2621d8a7b7a3SRobert Watson 	return (0);
2622d8a7b7a3SRobert Watson }
2623d8a7b7a3SRobert Watson 
2624d8a7b7a3SRobert Watson static int
26253f1a7a90SRobert Watson mls_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
262678007886SRobert Watson     struct label *vplabel, acl_type_t type)
2627d8a7b7a3SRobert Watson {
2628d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2629d8a7b7a3SRobert Watson 
26303f1a7a90SRobert Watson 	if (!mls_enabled)
2631d8a7b7a3SRobert Watson 		return (0);
2632d8a7b7a3SRobert Watson 
2633eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
263478007886SRobert Watson 	obj = SLOT(vplabel);
2635d8a7b7a3SRobert Watson 
26363f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2637d8a7b7a3SRobert Watson 		return (EACCES);
2638d8a7b7a3SRobert Watson 
2639d8a7b7a3SRobert Watson 	return (0);
2640d8a7b7a3SRobert Watson }
2641d8a7b7a3SRobert Watson 
2642d8a7b7a3SRobert Watson static int
26433f1a7a90SRobert Watson mls_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
2644fefd0ac8SRobert Watson     struct label *vplabel, int attrnamespace, const char *name)
2645d8a7b7a3SRobert Watson {
2646d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2647d8a7b7a3SRobert Watson 
26483f1a7a90SRobert Watson 	if (!mls_enabled)
2649d8a7b7a3SRobert Watson 		return (0);
2650d8a7b7a3SRobert Watson 
2651eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
265278007886SRobert Watson 	obj = SLOT(vplabel);
2653d8a7b7a3SRobert Watson 
26543f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2655d8a7b7a3SRobert Watson 		return (EACCES);
2656d8a7b7a3SRobert Watson 
2657d8a7b7a3SRobert Watson 	return (0);
2658d8a7b7a3SRobert Watson }
2659d8a7b7a3SRobert Watson 
2660d8a7b7a3SRobert Watson static int
26613f1a7a90SRobert Watson mls_vnode_check_link(struct ucred *cred, struct vnode *dvp,
266278007886SRobert Watson     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2663c27b50f5SRobert Watson     struct componentname *cnp)
2664c27b50f5SRobert Watson {
2665c27b50f5SRobert Watson 	struct mac_mls *subj, *obj;
2666c27b50f5SRobert Watson 
26673f1a7a90SRobert Watson 	if (!mls_enabled)
2668c27b50f5SRobert Watson 		return (0);
2669c27b50f5SRobert Watson 
2670eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
267178007886SRobert Watson 	obj = SLOT(dvplabel);
2672c27b50f5SRobert Watson 
26733f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2674c27b50f5SRobert Watson 		return (EACCES);
2675c27b50f5SRobert Watson 
26767bb9c8a0SRobert Watson 	obj = SLOT(vplabel);
26773f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2678c27b50f5SRobert Watson 		return (EACCES);
2679c27b50f5SRobert Watson 
2680c27b50f5SRobert Watson 	return (0);
2681c27b50f5SRobert Watson }
2682c27b50f5SRobert Watson 
2683c27b50f5SRobert Watson static int
26843f1a7a90SRobert Watson mls_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
268578007886SRobert Watson     struct label *vplabel, int attrnamespace)
268654e2c147SRobert Watson {
268754e2c147SRobert Watson 
268854e2c147SRobert Watson 	struct mac_mls *subj, *obj;
268954e2c147SRobert Watson 
26903f1a7a90SRobert Watson 	if (!mls_enabled)
269154e2c147SRobert Watson 		return (0);
269254e2c147SRobert Watson 
2693eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
269478007886SRobert Watson 	obj = SLOT(vplabel);
269554e2c147SRobert Watson 
26963f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
269754e2c147SRobert Watson 		return (EACCES);
269854e2c147SRobert Watson 
269954e2c147SRobert Watson 	return (0);
270054e2c147SRobert Watson }
270154e2c147SRobert Watson 
270254e2c147SRobert Watson static int
27033f1a7a90SRobert Watson mls_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
270478007886SRobert Watson     struct label *dvplabel, struct componentname *cnp)
2705d8a7b7a3SRobert Watson {
2706d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2707d8a7b7a3SRobert Watson 
27083f1a7a90SRobert Watson 	if (!mls_enabled)
2709d8a7b7a3SRobert Watson 		return (0);
2710d8a7b7a3SRobert Watson 
2711eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
271278007886SRobert Watson 	obj = SLOT(dvplabel);
2713d8a7b7a3SRobert Watson 
27143f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2715d8a7b7a3SRobert Watson 		return (EACCES);
2716d8a7b7a3SRobert Watson 
2717d8a7b7a3SRobert Watson 	return (0);
2718d8a7b7a3SRobert Watson }
2719d8a7b7a3SRobert Watson 
2720d8a7b7a3SRobert Watson static int
27213f1a7a90SRobert Watson mls_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
272278007886SRobert Watson     struct label *vplabel, int prot, int flags)
2723e183f80eSRobert Watson {
2724e183f80eSRobert Watson 	struct mac_mls *subj, *obj;
2725e183f80eSRobert Watson 
2726e183f80eSRobert Watson 	/*
2727e183f80eSRobert Watson 	 * Rely on the use of open()-time protections to handle
2728e183f80eSRobert Watson 	 * non-revocation cases.
2729e183f80eSRobert Watson 	 */
27303f1a7a90SRobert Watson 	if (!mls_enabled || !revocation_enabled)
2731e183f80eSRobert Watson 		return (0);
2732e183f80eSRobert Watson 
2733eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
273478007886SRobert Watson 	obj = SLOT(vplabel);
2735e183f80eSRobert Watson 
2736e183f80eSRobert Watson 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
27373f1a7a90SRobert Watson 		if (!mls_dominate_effective(subj, obj))
2738e183f80eSRobert Watson 			return (EACCES);
2739e183f80eSRobert Watson 	}
2740c92163dcSChristian S.J. Peron 	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
27413f1a7a90SRobert Watson 		if (!mls_dominate_effective(obj, subj))
2742e183f80eSRobert Watson 			return (EACCES);
2743e183f80eSRobert Watson 	}
2744e183f80eSRobert Watson 
2745e183f80eSRobert Watson 	return (0);
2746e183f80eSRobert Watson }
2747e183f80eSRobert Watson 
2748e183f80eSRobert Watson static int
27493f1a7a90SRobert Watson mls_vnode_check_open(struct ucred *cred, struct vnode *vp,
275015bc6b2bSEdward Tomasz Napierala     struct label *vplabel, accmode_t accmode)
2751d8a7b7a3SRobert Watson {
2752d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2753d8a7b7a3SRobert Watson 
27543f1a7a90SRobert Watson 	if (!mls_enabled)
2755d8a7b7a3SRobert Watson 		return (0);
2756d8a7b7a3SRobert Watson 
2757eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
275878007886SRobert Watson 	obj = SLOT(vplabel);
2759d8a7b7a3SRobert Watson 
2760d8a7b7a3SRobert Watson 	/* XXX privilege override for admin? */
27616180d318SEdward Tomasz Napierala 	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
27623f1a7a90SRobert Watson 		if (!mls_dominate_effective(subj, obj))
2763d8a7b7a3SRobert Watson 			return (EACCES);
2764d8a7b7a3SRobert Watson 	}
27656180d318SEdward Tomasz Napierala 	if (accmode & VMODIFY_PERMS) {
27663f1a7a90SRobert Watson 		if (!mls_dominate_effective(obj, subj))
2767d8a7b7a3SRobert Watson 			return (EACCES);
2768d8a7b7a3SRobert Watson 	}
2769d8a7b7a3SRobert Watson 
2770d8a7b7a3SRobert Watson 	return (0);
2771d8a7b7a3SRobert Watson }
2772d8a7b7a3SRobert Watson 
2773d8a7b7a3SRobert Watson static int
27743f1a7a90SRobert Watson mls_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
277578007886SRobert Watson     struct vnode *vp, struct label *vplabel)
27767f724f8bSRobert Watson {
27777f724f8bSRobert Watson 	struct mac_mls *subj, *obj;
27787f724f8bSRobert Watson 
27793f1a7a90SRobert Watson 	if (!mls_enabled || !revocation_enabled)
27807f724f8bSRobert Watson 		return (0);
27817f724f8bSRobert Watson 
2782eca8a663SRobert Watson 	subj = SLOT(active_cred->cr_label);
278378007886SRobert Watson 	obj = SLOT(vplabel);
27847f724f8bSRobert Watson 
27853f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
27867f724f8bSRobert Watson 		return (EACCES);
27877f724f8bSRobert Watson 
27887f724f8bSRobert Watson 	return (0);
27897f724f8bSRobert Watson }
27907f724f8bSRobert Watson 
27917f724f8bSRobert Watson static int
27923f1a7a90SRobert Watson mls_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
279378007886SRobert Watson     struct vnode *vp, struct label *vplabel)
27947f724f8bSRobert Watson {
27957f724f8bSRobert Watson 	struct mac_mls *subj, *obj;
27967f724f8bSRobert Watson 
27973f1a7a90SRobert Watson 	if (!mls_enabled || !revocation_enabled)
27987f724f8bSRobert Watson 		return (0);
27997f724f8bSRobert Watson 
2800eca8a663SRobert Watson 	subj = SLOT(active_cred->cr_label);
280178007886SRobert Watson 	obj = SLOT(vplabel);
28027f724f8bSRobert Watson 
28033f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
28047f724f8bSRobert Watson 		return (EACCES);
28057f724f8bSRobert Watson 
28067f724f8bSRobert Watson 	return (0);
28077f724f8bSRobert Watson }
28087f724f8bSRobert Watson 
28097f724f8bSRobert Watson static int
28103f1a7a90SRobert Watson mls_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
281178007886SRobert Watson     struct label *dvplabel)
2812d8a7b7a3SRobert Watson {
2813d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2814d8a7b7a3SRobert Watson 
28153f1a7a90SRobert Watson 	if (!mls_enabled)
2816d8a7b7a3SRobert Watson 		return (0);
2817d8a7b7a3SRobert Watson 
2818eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
281978007886SRobert Watson 	obj = SLOT(dvplabel);
2820d8a7b7a3SRobert Watson 
28213f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2822d8a7b7a3SRobert Watson 		return (EACCES);
2823d8a7b7a3SRobert Watson 
2824d8a7b7a3SRobert Watson 	return (0);
2825d8a7b7a3SRobert Watson }
2826d8a7b7a3SRobert Watson 
2827d8a7b7a3SRobert Watson static int
28283f1a7a90SRobert Watson mls_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
282978007886SRobert Watson     struct label *vplabel)
2830d8a7b7a3SRobert Watson {
2831d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2832d8a7b7a3SRobert Watson 
28333f1a7a90SRobert Watson 	if (!mls_enabled)
2834d8a7b7a3SRobert Watson 		return (0);
2835d8a7b7a3SRobert Watson 
2836eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
283778007886SRobert Watson 	obj = SLOT(vplabel);
2838d8a7b7a3SRobert Watson 
28393f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
2840d8a7b7a3SRobert Watson 		return (EACCES);
2841d8a7b7a3SRobert Watson 
2842d8a7b7a3SRobert Watson 	return (0);
2843d8a7b7a3SRobert Watson }
2844d8a7b7a3SRobert Watson 
2845d8a7b7a3SRobert Watson static int
28463f1a7a90SRobert Watson mls_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
284778007886SRobert Watson     struct label *vplabel, struct label *newlabel)
2848d8a7b7a3SRobert Watson {
2849d8a7b7a3SRobert Watson 	struct mac_mls *old, *new, *subj;
2850b5f072b5SRobert Watson 	int error;
2851d8a7b7a3SRobert Watson 
285278007886SRobert Watson 	old = SLOT(vplabel);
2853d8a7b7a3SRobert Watson 	new = SLOT(newlabel);
2854eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
2855d8a7b7a3SRobert Watson 
2856b5f072b5SRobert Watson 	/*
2857b5f072b5SRobert Watson 	 * If there is an MLS label update for the vnode, it must be a
2858dee57980SRobert Watson 	 * effective label.
2859b5f072b5SRobert Watson 	 */
2860dee57980SRobert Watson 	error = mls_atmostflags(new, MAC_MLS_FLAG_EFFECTIVE);
2861b5f072b5SRobert Watson 	if (error)
2862b5f072b5SRobert Watson 		return (error);
2863d8a7b7a3SRobert Watson 
2864d8a7b7a3SRobert Watson 	/*
2865b5f072b5SRobert Watson 	 * To perform a relabel of the vnode (MLS label or not), MLS must
2866b5f072b5SRobert Watson 	 * authorize the relabel.
2867d8a7b7a3SRobert Watson 	 */
28683f1a7a90SRobert Watson 	if (!mls_effective_in_range(old, subj))
2869d8a7b7a3SRobert Watson 		return (EPERM);
2870d8a7b7a3SRobert Watson 
2871d8a7b7a3SRobert Watson 	/*
2872b5f072b5SRobert Watson 	 * If the MLS label is to be changed, authorize as appropriate.
2873b5f072b5SRobert Watson 	 */
2874dee57980SRobert Watson 	if (new->mm_flags & MAC_MLS_FLAG_EFFECTIVE) {
2875b5f072b5SRobert Watson 		/*
2876b5f072b5SRobert Watson 		 * To change the MLS label on a vnode, the new vnode label
2877b5f072b5SRobert Watson 		 * must be in the subject range.
2878d8a7b7a3SRobert Watson 		 */
28793f1a7a90SRobert Watson 		if (!mls_effective_in_range(new, subj))
2880d8a7b7a3SRobert Watson 			return (EPERM);
2881d8a7b7a3SRobert Watson 
2882d8a7b7a3SRobert Watson 		/*
28833f1a7a90SRobert Watson 		 * To change the MLS label on the vnode to be EQUAL, the
28843f1a7a90SRobert Watson 		 * subject must have appropriate privilege.
2885d8a7b7a3SRobert Watson 		 */
28863f1a7a90SRobert Watson 		if (mls_contains_equal(new)) {
28873f1a7a90SRobert Watson 			error = mls_subject_privileged(subj);
2888b5f072b5SRobert Watson 			if (error)
2889b5f072b5SRobert Watson 				return (error);
2890b5f072b5SRobert Watson 		}
2891b5f072b5SRobert Watson 	}
2892d8a7b7a3SRobert Watson 
2893b5f072b5SRobert Watson 	return (0);
2894d8a7b7a3SRobert Watson }
2895d8a7b7a3SRobert Watson 
2896d8a7b7a3SRobert Watson static int
28973f1a7a90SRobert Watson mls_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
289878007886SRobert Watson     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2899d8a7b7a3SRobert Watson     struct componentname *cnp)
2900d8a7b7a3SRobert Watson {
2901d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2902d8a7b7a3SRobert Watson 
29033f1a7a90SRobert Watson 	if (!mls_enabled)
2904d8a7b7a3SRobert Watson 		return (0);
2905d8a7b7a3SRobert Watson 
2906eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
290778007886SRobert Watson 	obj = SLOT(dvplabel);
2908d8a7b7a3SRobert Watson 
29093f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2910d8a7b7a3SRobert Watson 		return (EACCES);
2911d8a7b7a3SRobert Watson 
291278007886SRobert Watson 	obj = SLOT(vplabel);
2913d8a7b7a3SRobert Watson 
29143f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2915d8a7b7a3SRobert Watson 		return (EACCES);
2916d8a7b7a3SRobert Watson 
2917d8a7b7a3SRobert Watson 	return (0);
2918d8a7b7a3SRobert Watson }
2919d8a7b7a3SRobert Watson 
2920d8a7b7a3SRobert Watson static int
29213f1a7a90SRobert Watson mls_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
292278007886SRobert Watson     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
292378007886SRobert Watson     int samedir, struct componentname *cnp)
2924d8a7b7a3SRobert Watson {
2925d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2926d8a7b7a3SRobert Watson 
29273f1a7a90SRobert Watson 	if (!mls_enabled)
2928d8a7b7a3SRobert Watson 		return (0);
2929d8a7b7a3SRobert Watson 
2930eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
293178007886SRobert Watson 	obj = SLOT(dvplabel);
2932d8a7b7a3SRobert Watson 
29333f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2934d8a7b7a3SRobert Watson 		return (EACCES);
2935d8a7b7a3SRobert Watson 
2936d8a7b7a3SRobert Watson 	if (vp != NULL) {
293778007886SRobert Watson 		obj = SLOT(vplabel);
2938d8a7b7a3SRobert Watson 
29393f1a7a90SRobert Watson 		if (!mls_dominate_effective(obj, subj))
2940d8a7b7a3SRobert Watson 			return (EACCES);
2941d8a7b7a3SRobert Watson 	}
2942d8a7b7a3SRobert Watson 
2943d8a7b7a3SRobert Watson 	return (0);
2944d8a7b7a3SRobert Watson }
2945d8a7b7a3SRobert Watson 
2946d8a7b7a3SRobert Watson static int
29473f1a7a90SRobert Watson mls_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
294878007886SRobert Watson     struct label *vplabel)
2949d8a7b7a3SRobert Watson {
2950d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2951d8a7b7a3SRobert Watson 
29523f1a7a90SRobert Watson 	if (!mls_enabled)
2953d8a7b7a3SRobert Watson 		return (0);
2954d8a7b7a3SRobert Watson 
2955eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
295678007886SRobert Watson 	obj = SLOT(vplabel);
2957d8a7b7a3SRobert Watson 
29583f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2959d8a7b7a3SRobert Watson 		return (EACCES);
2960d8a7b7a3SRobert Watson 
2961d8a7b7a3SRobert Watson 	return (0);
2962d8a7b7a3SRobert Watson }
2963d8a7b7a3SRobert Watson 
2964d8a7b7a3SRobert Watson static int
29653f1a7a90SRobert Watson mls_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
296678007886SRobert Watson     struct label *vplabel, acl_type_t type, struct acl *acl)
2967d8a7b7a3SRobert Watson {
2968d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2969d8a7b7a3SRobert Watson 
29703f1a7a90SRobert Watson 	if (!mls_enabled)
2971d8a7b7a3SRobert Watson 		return (0);
2972d8a7b7a3SRobert Watson 
2973eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
297478007886SRobert Watson 	obj = SLOT(vplabel);
2975d8a7b7a3SRobert Watson 
29763f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2977d8a7b7a3SRobert Watson 		return (EACCES);
2978d8a7b7a3SRobert Watson 
2979d8a7b7a3SRobert Watson 	return (0);
2980d8a7b7a3SRobert Watson }
2981d8a7b7a3SRobert Watson 
2982d8a7b7a3SRobert Watson static int
29833f1a7a90SRobert Watson mls_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2984fefd0ac8SRobert Watson     struct label *vplabel, int attrnamespace, const char *name)
2985d8a7b7a3SRobert Watson {
2986d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
2987d8a7b7a3SRobert Watson 
29883f1a7a90SRobert Watson 	if (!mls_enabled)
2989d8a7b7a3SRobert Watson 		return (0);
2990d8a7b7a3SRobert Watson 
2991eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
299278007886SRobert Watson 	obj = SLOT(vplabel);
2993d8a7b7a3SRobert Watson 
29943f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
2995d8a7b7a3SRobert Watson 		return (EACCES);
2996d8a7b7a3SRobert Watson 
2997d8a7b7a3SRobert Watson 	/* XXX: protect the MAC EA in a special way? */
2998d8a7b7a3SRobert Watson 
2999d8a7b7a3SRobert Watson 	return (0);
3000d8a7b7a3SRobert Watson }
3001d8a7b7a3SRobert Watson 
3002d8a7b7a3SRobert Watson static int
30033f1a7a90SRobert Watson mls_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
300478007886SRobert Watson     struct label *vplabel, u_long flags)
3005d8a7b7a3SRobert Watson {
3006d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
3007d8a7b7a3SRobert Watson 
30083f1a7a90SRobert Watson 	if (!mls_enabled)
3009d8a7b7a3SRobert Watson 		return (0);
3010d8a7b7a3SRobert Watson 
3011eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
301278007886SRobert Watson 	obj = SLOT(vplabel);
3013d8a7b7a3SRobert Watson 
30143f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
3015d8a7b7a3SRobert Watson 		return (EACCES);
3016d8a7b7a3SRobert Watson 
3017d8a7b7a3SRobert Watson 	return (0);
3018d8a7b7a3SRobert Watson }
3019d8a7b7a3SRobert Watson 
3020d8a7b7a3SRobert Watson static int
30213f1a7a90SRobert Watson mls_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
302278007886SRobert Watson     struct label *vplabel, mode_t mode)
3023d8a7b7a3SRobert Watson {
3024d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
3025d8a7b7a3SRobert Watson 
30263f1a7a90SRobert Watson 	if (!mls_enabled)
3027d8a7b7a3SRobert Watson 		return (0);
3028d8a7b7a3SRobert Watson 
3029eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
303078007886SRobert Watson 	obj = SLOT(vplabel);
3031d8a7b7a3SRobert Watson 
30323f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
3033d8a7b7a3SRobert Watson 		return (EACCES);
3034d8a7b7a3SRobert Watson 
3035d8a7b7a3SRobert Watson 	return (0);
3036d8a7b7a3SRobert Watson }
3037d8a7b7a3SRobert Watson 
3038d8a7b7a3SRobert Watson static int
30393f1a7a90SRobert Watson mls_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
304078007886SRobert Watson     struct label *vplabel, uid_t uid, gid_t gid)
3041d8a7b7a3SRobert Watson {
3042d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
3043d8a7b7a3SRobert Watson 
30443f1a7a90SRobert Watson 	if (!mls_enabled)
3045d8a7b7a3SRobert Watson 		return (0);
3046d8a7b7a3SRobert Watson 
3047eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
304878007886SRobert Watson 	obj = SLOT(vplabel);
3049d8a7b7a3SRobert Watson 
30503f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
3051d8a7b7a3SRobert Watson 		return (EACCES);
3052d8a7b7a3SRobert Watson 
3053d8a7b7a3SRobert Watson 	return (0);
3054d8a7b7a3SRobert Watson }
3055d8a7b7a3SRobert Watson 
3056d8a7b7a3SRobert Watson static int
30573f1a7a90SRobert Watson mls_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
305878007886SRobert Watson     struct label *vplabel, struct timespec atime, struct timespec mtime)
3059d8a7b7a3SRobert Watson {
3060d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
3061d8a7b7a3SRobert Watson 
30623f1a7a90SRobert Watson 	if (!mls_enabled)
3063d8a7b7a3SRobert Watson 		return (0);
3064d8a7b7a3SRobert Watson 
3065eca8a663SRobert Watson 	subj = SLOT(cred->cr_label);
306678007886SRobert Watson 	obj = SLOT(vplabel);
3067d8a7b7a3SRobert Watson 
30683f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
3069d8a7b7a3SRobert Watson 		return (EACCES);
3070d8a7b7a3SRobert Watson 
3071d8a7b7a3SRobert Watson 	return (0);
3072d8a7b7a3SRobert Watson }
3073d8a7b7a3SRobert Watson 
3074d8a7b7a3SRobert Watson static int
30753f1a7a90SRobert Watson mls_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
307678007886SRobert Watson     struct vnode *vp, struct label *vplabel)
3077d8a7b7a3SRobert Watson {
3078d8a7b7a3SRobert Watson 	struct mac_mls *subj, *obj;
3079d8a7b7a3SRobert Watson 
30803f1a7a90SRobert Watson 	if (!mls_enabled)
3081d8a7b7a3SRobert Watson 		return (0);
3082d8a7b7a3SRobert Watson 
3083eca8a663SRobert Watson 	subj = SLOT(active_cred->cr_label);
308478007886SRobert Watson 	obj = SLOT(vplabel);
3085d8a7b7a3SRobert Watson 
30863f1a7a90SRobert Watson 	if (!mls_dominate_effective(subj, obj))
3087d8a7b7a3SRobert Watson 		return (EACCES);
3088d8a7b7a3SRobert Watson 
3089d8a7b7a3SRobert Watson 	return (0);
3090d8a7b7a3SRobert Watson }
3091d8a7b7a3SRobert Watson 
30927f724f8bSRobert Watson static int
30933f1a7a90SRobert Watson mls_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
309445e0f3d6SRobert Watson     struct label *dvplabel, struct vnode *vp, struct label *vplabel,
309545e0f3d6SRobert Watson     struct componentname *cnp)
309645e0f3d6SRobert Watson {
309745e0f3d6SRobert Watson 	struct mac_mls *subj, *obj;
309845e0f3d6SRobert Watson 
30993f1a7a90SRobert Watson 	if (!mls_enabled)
310045e0f3d6SRobert Watson 		return (0);
310145e0f3d6SRobert Watson 
310245e0f3d6SRobert Watson 	subj = SLOT(cred->cr_label);
310345e0f3d6SRobert Watson 	obj = SLOT(dvplabel);
310445e0f3d6SRobert Watson 
31053f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
310645e0f3d6SRobert Watson 		return (EACCES);
310745e0f3d6SRobert Watson 
310845e0f3d6SRobert Watson 	obj = SLOT(vplabel);
310945e0f3d6SRobert Watson 
31103f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
311145e0f3d6SRobert Watson 		return (EACCES);
311245e0f3d6SRobert Watson 
311345e0f3d6SRobert Watson 	return (0);
311445e0f3d6SRobert Watson }
311545e0f3d6SRobert Watson 
311645e0f3d6SRobert Watson static int
31173f1a7a90SRobert Watson mls_vnode_check_write(struct ucred *active_cred, struct ucred *file_cred,
311878007886SRobert Watson     struct vnode *vp, struct label *vplabel)
31197f724f8bSRobert Watson {
31207f724f8bSRobert Watson 	struct mac_mls *subj, *obj;
31217f724f8bSRobert Watson 
31223f1a7a90SRobert Watson 	if (!mls_enabled || !revocation_enabled)
31237f724f8bSRobert Watson 		return (0);
31247f724f8bSRobert Watson 
3125eca8a663SRobert Watson 	subj = SLOT(active_cred->cr_label);
312678007886SRobert Watson 	obj = SLOT(vplabel);
31277f724f8bSRobert Watson 
31283f1a7a90SRobert Watson 	if (!mls_dominate_effective(obj, subj))
31297f724f8bSRobert Watson 		return (EACCES);
31307f724f8bSRobert Watson 
31317f724f8bSRobert Watson 	return (0);
31327f724f8bSRobert Watson }
31337f724f8bSRobert Watson 
3134eb320b0eSRobert Watson static int
3135eb320b0eSRobert Watson mls_vnode_create_extattr(struct ucred *cred, struct mount *mp,
3136eb320b0eSRobert Watson     struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
3137eb320b0eSRobert Watson     struct vnode *vp, struct label *vplabel, struct componentname *cnp)
3138eb320b0eSRobert Watson {
3139eb320b0eSRobert Watson 	struct mac_mls *source, *dest, mm_temp;
3140eb320b0eSRobert Watson 	size_t buflen;
3141eb320b0eSRobert Watson 	int error;
3142eb320b0eSRobert Watson 
3143eb320b0eSRobert Watson 	buflen = sizeof(mm_temp);
3144eb320b0eSRobert Watson 	bzero(&mm_temp, buflen);
3145eb320b0eSRobert Watson 
3146eb320b0eSRobert Watson 	source = SLOT(cred->cr_label);
3147eb320b0eSRobert Watson 	dest = SLOT(vplabel);
3148eb320b0eSRobert Watson 	mls_copy_effective(source, &mm_temp);
3149eb320b0eSRobert Watson 
3150eb320b0eSRobert Watson 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3151eb320b0eSRobert Watson 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3152eb320b0eSRobert Watson 	if (error == 0)
3153eb320b0eSRobert Watson 		mls_copy_effective(source, dest);
3154eb320b0eSRobert Watson 	return (error);
3155eb320b0eSRobert Watson }
3156eb320b0eSRobert Watson 
3157eb320b0eSRobert Watson static void
3158eb320b0eSRobert Watson mls_vnode_relabel(struct ucred *cred, struct vnode *vp,
3159eb320b0eSRobert Watson     struct label *vplabel, struct label *label)
3160eb320b0eSRobert Watson {
3161eb320b0eSRobert Watson 	struct mac_mls *source, *dest;
3162eb320b0eSRobert Watson 
3163eb320b0eSRobert Watson 	source = SLOT(label);
3164eb320b0eSRobert Watson 	dest = SLOT(vplabel);
3165eb320b0eSRobert Watson 
3166eb320b0eSRobert Watson 	mls_copy(source, dest);
3167eb320b0eSRobert Watson }
3168eb320b0eSRobert Watson 
3169eb320b0eSRobert Watson static int
3170eb320b0eSRobert Watson mls_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
3171eb320b0eSRobert Watson     struct label *vplabel, struct label *intlabel)
3172eb320b0eSRobert Watson {
3173eb320b0eSRobert Watson 	struct mac_mls *source, mm_temp;
3174eb320b0eSRobert Watson 	size_t buflen;
3175eb320b0eSRobert Watson 	int error;
3176eb320b0eSRobert Watson 
3177eb320b0eSRobert Watson 	buflen = sizeof(mm_temp);
3178eb320b0eSRobert Watson 	bzero(&mm_temp, buflen);
3179eb320b0eSRobert Watson 
3180eb320b0eSRobert Watson 	source = SLOT(intlabel);
3181eb320b0eSRobert Watson 	if ((source->mm_flags & MAC_MLS_FLAG_EFFECTIVE) == 0)
3182eb320b0eSRobert Watson 		return (0);
3183eb320b0eSRobert Watson 
3184eb320b0eSRobert Watson 	mls_copy_effective(source, &mm_temp);
3185eb320b0eSRobert Watson 
3186eb320b0eSRobert Watson 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_MLS_EXTATTR_NAMESPACE,
3187eb320b0eSRobert Watson 	    MAC_MLS_EXTATTR_NAME, buflen, (char *) &mm_temp, curthread);
3188eb320b0eSRobert Watson 	return (error);
3189eb320b0eSRobert Watson }
3190eb320b0eSRobert Watson 
31913f1a7a90SRobert Watson static struct mac_policy_ops mls_ops =
3192d8a7b7a3SRobert Watson {
31933f1a7a90SRobert Watson 	.mpo_init = mls_init,
3194eb320b0eSRobert Watson 
3195eb320b0eSRobert Watson 	.mpo_bpfdesc_check_receive = mls_bpfdesc_check_receive,
3196eb320b0eSRobert Watson 	.mpo_bpfdesc_create = mls_bpfdesc_create,
3197eb320b0eSRobert Watson 	.mpo_bpfdesc_create_mbuf = mls_bpfdesc_create_mbuf,
31983f1a7a90SRobert Watson 	.mpo_bpfdesc_destroy_label = mls_destroy_label,
3199eb320b0eSRobert Watson 	.mpo_bpfdesc_init_label = mls_init_label,
3200eb320b0eSRobert Watson 
3201212ab0cfSRobert Watson 	.mpo_cred_associate_nfsd = mls_cred_associate_nfsd,
3202eb320b0eSRobert Watson 	.mpo_cred_check_relabel = mls_cred_check_relabel,
3203eb320b0eSRobert Watson 	.mpo_cred_check_visible = mls_cred_check_visible,
32043f1a7a90SRobert Watson 	.mpo_cred_copy_label = mls_copy_label,
3205212ab0cfSRobert Watson 	.mpo_cred_create_init = mls_cred_create_init,
3206212ab0cfSRobert Watson 	.mpo_cred_create_swapper = mls_cred_create_swapper,
3207eb320b0eSRobert Watson 	.mpo_cred_destroy_label = mls_destroy_label,
32083f1a7a90SRobert Watson 	.mpo_cred_externalize_label = mls_externalize_label,
3209eb320b0eSRobert Watson 	.mpo_cred_init_label = mls_init_label,
32103f1a7a90SRobert Watson 	.mpo_cred_internalize_label = mls_internalize_label,
3211eb320b0eSRobert Watson 	.mpo_cred_relabel = mls_cred_relabel,
3212eb320b0eSRobert Watson 
32133f1a7a90SRobert Watson 	.mpo_devfs_create_device = mls_devfs_create_device,
32143f1a7a90SRobert Watson 	.mpo_devfs_create_directory = mls_devfs_create_directory,
32153f1a7a90SRobert Watson 	.mpo_devfs_create_symlink = mls_devfs_create_symlink,
3216eb320b0eSRobert Watson 	.mpo_devfs_destroy_label = mls_destroy_label,
3217eb320b0eSRobert Watson 	.mpo_devfs_init_label = mls_init_label,
32183f1a7a90SRobert Watson 	.mpo_devfs_update = mls_devfs_update,
32193f1a7a90SRobert Watson 	.mpo_devfs_vnode_associate = mls_devfs_vnode_associate,
3220eb320b0eSRobert Watson 
32213f1a7a90SRobert Watson 	.mpo_ifnet_check_relabel = mls_ifnet_check_relabel,
32223f1a7a90SRobert Watson 	.mpo_ifnet_check_transmit = mls_ifnet_check_transmit,
3223eb320b0eSRobert Watson 	.mpo_ifnet_copy_label = mls_copy_label,
3224eb320b0eSRobert Watson 	.mpo_ifnet_create = mls_ifnet_create,
3225eb320b0eSRobert Watson 	.mpo_ifnet_create_mbuf = mls_ifnet_create_mbuf,
3226eb320b0eSRobert Watson 	.mpo_ifnet_destroy_label = mls_destroy_label,
3227eb320b0eSRobert Watson 	.mpo_ifnet_externalize_label = mls_externalize_label,
3228eb320b0eSRobert Watson 	.mpo_ifnet_init_label = mls_init_label,
3229eb320b0eSRobert Watson 	.mpo_ifnet_internalize_label = mls_internalize_label,
3230eb320b0eSRobert Watson 	.mpo_ifnet_relabel = mls_ifnet_relabel,
3231eb320b0eSRobert Watson 
32323f1a7a90SRobert Watson 	.mpo_inpcb_check_deliver = mls_inpcb_check_deliver,
32337fb179baSBjoern A. Zeeb 	.mpo_inpcb_check_visible = mls_inpcb_check_visible,
3234eb320b0eSRobert Watson 	.mpo_inpcb_create = mls_inpcb_create,
3235eb320b0eSRobert Watson 	.mpo_inpcb_create_mbuf = mls_inpcb_create_mbuf,
3236eb320b0eSRobert Watson 	.mpo_inpcb_destroy_label = mls_destroy_label,
3237eb320b0eSRobert Watson 	.mpo_inpcb_init_label = mls_init_label_waitcheck,
3238eb320b0eSRobert Watson 	.mpo_inpcb_sosetlabel = mls_inpcb_sosetlabel,
3239eb320b0eSRobert Watson 
3240048e1287SRobert Watson 	.mpo_ip6q_create = mls_ip6q_create,
3241048e1287SRobert Watson 	.mpo_ip6q_destroy_label = mls_destroy_label,
3242048e1287SRobert Watson 	.mpo_ip6q_init_label = mls_init_label_waitcheck,
3243048e1287SRobert Watson 	.mpo_ip6q_match = mls_ip6q_match,
3244048e1287SRobert Watson 	.mpo_ip6q_reassemble = mls_ip6q_reassemble,
3245048e1287SRobert Watson 	.mpo_ip6q_update = mls_ip6q_update,
3246048e1287SRobert Watson 
3247eb320b0eSRobert Watson 	.mpo_ipq_create = mls_ipq_create,
3248eb320b0eSRobert Watson 	.mpo_ipq_destroy_label = mls_destroy_label,
3249eb320b0eSRobert Watson 	.mpo_ipq_init_label = mls_init_label_waitcheck,
3250eb320b0eSRobert Watson 	.mpo_ipq_match = mls_ipq_match,
3251eb320b0eSRobert Watson 	.mpo_ipq_reassemble = mls_ipq_reassemble,
3252eb320b0eSRobert Watson 	.mpo_ipq_update = mls_ipq_update,
3253eb320b0eSRobert Watson 
3254eb320b0eSRobert Watson 	.mpo_mbuf_copy_label = mls_copy_label,
3255eb320b0eSRobert Watson 	.mpo_mbuf_destroy_label = mls_destroy_label,
3256eb320b0eSRobert Watson 	.mpo_mbuf_init_label = mls_init_label_waitcheck,
3257eb320b0eSRobert Watson 
32583f1a7a90SRobert Watson 	.mpo_mount_check_stat = mls_mount_check_stat,
3259eb320b0eSRobert Watson 	.mpo_mount_create = mls_mount_create,
3260eb320b0eSRobert Watson 	.mpo_mount_destroy_label = mls_destroy_label,
3261eb320b0eSRobert Watson 	.mpo_mount_init_label = mls_init_label,
3262eb320b0eSRobert Watson 
3263eb320b0eSRobert Watson 	.mpo_netinet_arp_send = mls_netinet_arp_send,
3264eb320b0eSRobert Watson 	.mpo_netinet_firewall_reply = mls_netinet_firewall_reply,
3265eb320b0eSRobert Watson 	.mpo_netinet_firewall_send = mls_netinet_firewall_send,
3266eb320b0eSRobert Watson 	.mpo_netinet_fragment = mls_netinet_fragment,
3267eb320b0eSRobert Watson 	.mpo_netinet_icmp_reply = mls_netinet_icmp_reply,
3268eb320b0eSRobert Watson 	.mpo_netinet_igmp_send = mls_netinet_igmp_send,
3269eb320b0eSRobert Watson 
3270eb320b0eSRobert Watson 	.mpo_netinet6_nd6_send = mls_netinet6_nd6_send,
3271eb320b0eSRobert Watson 
32723f1a7a90SRobert Watson 	.mpo_pipe_check_ioctl = mls_pipe_check_ioctl,
32733f1a7a90SRobert Watson 	.mpo_pipe_check_poll = mls_pipe_check_poll,
32743f1a7a90SRobert Watson 	.mpo_pipe_check_read = mls_pipe_check_read,
32753f1a7a90SRobert Watson 	.mpo_pipe_check_relabel = mls_pipe_check_relabel,
32763f1a7a90SRobert Watson 	.mpo_pipe_check_stat = mls_pipe_check_stat,
32773f1a7a90SRobert Watson 	.mpo_pipe_check_write = mls_pipe_check_write,
3278eb320b0eSRobert Watson 	.mpo_pipe_copy_label = mls_copy_label,
3279eb320b0eSRobert Watson 	.mpo_pipe_create = mls_pipe_create,
3280eb320b0eSRobert Watson 	.mpo_pipe_destroy_label = mls_destroy_label,
3281eb320b0eSRobert Watson 	.mpo_pipe_externalize_label = mls_externalize_label,
3282eb320b0eSRobert Watson 	.mpo_pipe_init_label = mls_init_label,
3283eb320b0eSRobert Watson 	.mpo_pipe_internalize_label = mls_internalize_label,
3284eb320b0eSRobert Watson 	.mpo_pipe_relabel = mls_pipe_relabel,
3285eb320b0eSRobert Watson 
32863f1a7a90SRobert Watson 	.mpo_posixsem_check_getvalue = mls_posixsem_check_rdonly,
32876bc1e9cdSJohn Baldwin 	.mpo_posixsem_check_open = mls_posixsem_check_openunlink,
32883f1a7a90SRobert Watson 	.mpo_posixsem_check_post = mls_posixsem_check_write,
32899b6dd12eSRobert Watson 	.mpo_posixsem_check_setmode = mls_posixsem_check_setmode,
32909b6dd12eSRobert Watson 	.mpo_posixsem_check_setowner = mls_posixsem_check_setowner,
32916bc1e9cdSJohn Baldwin 	.mpo_posixsem_check_stat = mls_posixsem_check_rdonly,
32926bc1e9cdSJohn Baldwin 	.mpo_posixsem_check_unlink = mls_posixsem_check_openunlink,
32933f1a7a90SRobert Watson 	.mpo_posixsem_check_wait = mls_posixsem_check_write,
3294eb320b0eSRobert Watson 	.mpo_posixsem_create = mls_posixsem_create,
3295eb320b0eSRobert Watson 	.mpo_posixsem_destroy_label = mls_destroy_label,
3296eb320b0eSRobert Watson 	.mpo_posixsem_init_label = mls_init_label,
3297eb320b0eSRobert Watson 
32989b6dd12eSRobert Watson 	.mpo_posixshm_check_mmap = mls_posixshm_check_mmap,
32999b6dd12eSRobert Watson 	.mpo_posixshm_check_open = mls_posixshm_check_open,
3300940cb0e2SKonstantin Belousov 	.mpo_posixshm_check_read = mls_posixshm_check_read,
33019b6dd12eSRobert Watson 	.mpo_posixshm_check_setmode = mls_posixshm_check_setmode,
33029b6dd12eSRobert Watson 	.mpo_posixshm_check_setowner = mls_posixshm_check_setowner,
33039b6dd12eSRobert Watson 	.mpo_posixshm_check_stat = mls_posixshm_check_stat,
33049b6dd12eSRobert Watson 	.mpo_posixshm_check_truncate = mls_posixshm_check_truncate,
33059b6dd12eSRobert Watson 	.mpo_posixshm_check_unlink = mls_posixshm_check_unlink,
3306940cb0e2SKonstantin Belousov 	.mpo_posixshm_check_write = mls_posixshm_check_write,
33079b6dd12eSRobert Watson 	.mpo_posixshm_create = mls_posixshm_create,
33089b6dd12eSRobert Watson 	.mpo_posixshm_destroy_label = mls_destroy_label,
33099b6dd12eSRobert Watson 	.mpo_posixshm_init_label = mls_init_label,
33109b6dd12eSRobert Watson 
33113f1a7a90SRobert Watson 	.mpo_proc_check_debug = mls_proc_check_debug,
33123f1a7a90SRobert Watson 	.mpo_proc_check_sched = mls_proc_check_sched,
33133f1a7a90SRobert Watson 	.mpo_proc_check_signal = mls_proc_check_signal,
3314eb320b0eSRobert Watson 
33153f1a7a90SRobert Watson 	.mpo_socket_check_deliver = mls_socket_check_deliver,
33163f1a7a90SRobert Watson 	.mpo_socket_check_relabel = mls_socket_check_relabel,
33173f1a7a90SRobert Watson 	.mpo_socket_check_visible = mls_socket_check_visible,
3318eb320b0eSRobert Watson 	.mpo_socket_copy_label = mls_copy_label,
3319eb320b0eSRobert Watson 	.mpo_socket_create = mls_socket_create,
3320eb320b0eSRobert Watson 	.mpo_socket_create_mbuf = mls_socket_create_mbuf,
3321eb320b0eSRobert Watson 	.mpo_socket_destroy_label = mls_destroy_label,
3322eb320b0eSRobert Watson 	.mpo_socket_externalize_label = mls_externalize_label,
3323eb320b0eSRobert Watson 	.mpo_socket_init_label = mls_init_label_waitcheck,
3324eb320b0eSRobert Watson 	.mpo_socket_internalize_label = mls_internalize_label,
3325eb320b0eSRobert Watson 	.mpo_socket_newconn = mls_socket_newconn,
3326eb320b0eSRobert Watson 	.mpo_socket_relabel = mls_socket_relabel,
3327eb320b0eSRobert Watson 
3328eb320b0eSRobert Watson 	.mpo_socketpeer_destroy_label = mls_destroy_label,
3329eb320b0eSRobert Watson 	.mpo_socketpeer_externalize_label = mls_externalize_label,
3330eb320b0eSRobert Watson 	.mpo_socketpeer_init_label = mls_init_label_waitcheck,
3331eb320b0eSRobert Watson 	.mpo_socketpeer_set_from_mbuf = mls_socketpeer_set_from_mbuf,
3332eb320b0eSRobert Watson 	.mpo_socketpeer_set_from_socket = mls_socketpeer_set_from_socket,
3333eb320b0eSRobert Watson 
3334eb320b0eSRobert Watson 	.mpo_syncache_create = mls_syncache_create,
3335eb320b0eSRobert Watson 	.mpo_syncache_create_mbuf = mls_syncache_create_mbuf,
3336eb320b0eSRobert Watson 	.mpo_syncache_destroy_label = mls_destroy_label,
3337eb320b0eSRobert Watson 	.mpo_syncache_init_label = mls_init_label_waitcheck,
3338eb320b0eSRobert Watson 
3339eb320b0eSRobert Watson 	.mpo_sysvmsg_cleanup = mls_sysvmsg_cleanup,
3340eb320b0eSRobert Watson 	.mpo_sysvmsg_create = mls_sysvmsg_create,
3341eb320b0eSRobert Watson 	.mpo_sysvmsg_destroy_label = mls_destroy_label,
3342eb320b0eSRobert Watson 	.mpo_sysvmsg_init_label = mls_init_label,
3343eb320b0eSRobert Watson 
3344eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msgrcv = mls_sysvmsq_check_msgrcv,
3345eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msgrmid = mls_sysvmsq_check_msgrmid,
3346eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msqget = mls_sysvmsq_check_msqget,
3347eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msqsnd = mls_sysvmsq_check_msqsnd,
3348eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msqrcv = mls_sysvmsq_check_msqrcv,
3349eb320b0eSRobert Watson 	.mpo_sysvmsq_check_msqctl = mls_sysvmsq_check_msqctl,
3350eb320b0eSRobert Watson 	.mpo_sysvmsq_cleanup = mls_sysvmsq_cleanup,
3351eb320b0eSRobert Watson 	.mpo_sysvmsq_destroy_label = mls_destroy_label,
3352eb320b0eSRobert Watson 	.mpo_sysvmsq_init_label = mls_init_label,
3353eb320b0eSRobert Watson 	.mpo_sysvmsq_create = mls_sysvmsq_create,
3354eb320b0eSRobert Watson 
3355eb320b0eSRobert Watson 	.mpo_sysvsem_check_semctl = mls_sysvsem_check_semctl,
3356eb320b0eSRobert Watson 	.mpo_sysvsem_check_semget = mls_sysvsem_check_semget,
3357eb320b0eSRobert Watson 	.mpo_sysvsem_check_semop = mls_sysvsem_check_semop,
3358eb320b0eSRobert Watson 	.mpo_sysvsem_cleanup = mls_sysvsem_cleanup,
3359eb320b0eSRobert Watson 	.mpo_sysvsem_create = mls_sysvsem_create,
3360eb320b0eSRobert Watson 	.mpo_sysvsem_destroy_label = mls_destroy_label,
3361eb320b0eSRobert Watson 	.mpo_sysvsem_init_label = mls_init_label,
3362eb320b0eSRobert Watson 
3363eb320b0eSRobert Watson 	.mpo_sysvshm_check_shmat = mls_sysvshm_check_shmat,
3364eb320b0eSRobert Watson 	.mpo_sysvshm_check_shmctl = mls_sysvshm_check_shmctl,
3365eb320b0eSRobert Watson 	.mpo_sysvshm_check_shmget = mls_sysvshm_check_shmget,
3366eb320b0eSRobert Watson 	.mpo_sysvshm_cleanup = mls_sysvshm_cleanup,
3367eb320b0eSRobert Watson 	.mpo_sysvshm_create = mls_sysvshm_create,
3368eb320b0eSRobert Watson 	.mpo_sysvshm_destroy_label = mls_destroy_label,
3369eb320b0eSRobert Watson 	.mpo_sysvshm_init_label = mls_init_label,
3370eb320b0eSRobert Watson 
33713f1a7a90SRobert Watson 	.mpo_system_check_acct = mls_system_check_acct,
33723f1a7a90SRobert Watson 	.mpo_system_check_auditctl = mls_system_check_auditctl,
33733f1a7a90SRobert Watson 	.mpo_system_check_swapon = mls_system_check_swapon,
3374eb320b0eSRobert Watson 
3375eb320b0eSRobert Watson 	.mpo_vnode_associate_extattr = mls_vnode_associate_extattr,
3376eb320b0eSRobert Watson 	.mpo_vnode_associate_singlelabel = mls_vnode_associate_singlelabel,
33773f1a7a90SRobert Watson 	.mpo_vnode_check_access = mls_vnode_check_open,
33783f1a7a90SRobert Watson 	.mpo_vnode_check_chdir = mls_vnode_check_chdir,
33793f1a7a90SRobert Watson 	.mpo_vnode_check_chroot = mls_vnode_check_chroot,
33803f1a7a90SRobert Watson 	.mpo_vnode_check_create = mls_vnode_check_create,
33813f1a7a90SRobert Watson 	.mpo_vnode_check_deleteacl = mls_vnode_check_deleteacl,
33823f1a7a90SRobert Watson 	.mpo_vnode_check_deleteextattr = mls_vnode_check_deleteextattr,
33833f1a7a90SRobert Watson 	.mpo_vnode_check_exec = mls_vnode_check_exec,
33843f1a7a90SRobert Watson 	.mpo_vnode_check_getacl = mls_vnode_check_getacl,
33853f1a7a90SRobert Watson 	.mpo_vnode_check_getextattr = mls_vnode_check_getextattr,
33863f1a7a90SRobert Watson 	.mpo_vnode_check_link = mls_vnode_check_link,
33873f1a7a90SRobert Watson 	.mpo_vnode_check_listextattr = mls_vnode_check_listextattr,
33883f1a7a90SRobert Watson 	.mpo_vnode_check_lookup = mls_vnode_check_lookup,
33893f1a7a90SRobert Watson 	.mpo_vnode_check_mmap = mls_vnode_check_mmap,
33903f1a7a90SRobert Watson 	.mpo_vnode_check_open = mls_vnode_check_open,
33913f1a7a90SRobert Watson 	.mpo_vnode_check_poll = mls_vnode_check_poll,
33923f1a7a90SRobert Watson 	.mpo_vnode_check_read = mls_vnode_check_read,
33933f1a7a90SRobert Watson 	.mpo_vnode_check_readdir = mls_vnode_check_readdir,
33943f1a7a90SRobert Watson 	.mpo_vnode_check_readlink = mls_vnode_check_readlink,
33953f1a7a90SRobert Watson 	.mpo_vnode_check_relabel = mls_vnode_check_relabel,
33963f1a7a90SRobert Watson 	.mpo_vnode_check_rename_from = mls_vnode_check_rename_from,
33973f1a7a90SRobert Watson 	.mpo_vnode_check_rename_to = mls_vnode_check_rename_to,
33983f1a7a90SRobert Watson 	.mpo_vnode_check_revoke = mls_vnode_check_revoke,
33993f1a7a90SRobert Watson 	.mpo_vnode_check_setacl = mls_vnode_check_setacl,
34003f1a7a90SRobert Watson 	.mpo_vnode_check_setextattr = mls_vnode_check_setextattr,
34013f1a7a90SRobert Watson 	.mpo_vnode_check_setflags = mls_vnode_check_setflags,
34023f1a7a90SRobert Watson 	.mpo_vnode_check_setmode = mls_vnode_check_setmode,
34033f1a7a90SRobert Watson 	.mpo_vnode_check_setowner = mls_vnode_check_setowner,
34043f1a7a90SRobert Watson 	.mpo_vnode_check_setutimes = mls_vnode_check_setutimes,
34053f1a7a90SRobert Watson 	.mpo_vnode_check_stat = mls_vnode_check_stat,
34063f1a7a90SRobert Watson 	.mpo_vnode_check_unlink = mls_vnode_check_unlink,
34073f1a7a90SRobert Watson 	.mpo_vnode_check_write = mls_vnode_check_write,
3408eb320b0eSRobert Watson 	.mpo_vnode_copy_label = mls_copy_label,
3409eb320b0eSRobert Watson 	.mpo_vnode_create_extattr = mls_vnode_create_extattr,
3410eb320b0eSRobert Watson 	.mpo_vnode_destroy_label = mls_destroy_label,
3411eb320b0eSRobert Watson 	.mpo_vnode_externalize_label = mls_externalize_label,
3412eb320b0eSRobert Watson 	.mpo_vnode_init_label = mls_init_label,
3413eb320b0eSRobert Watson 	.mpo_vnode_internalize_label = mls_internalize_label,
3414eb320b0eSRobert Watson 	.mpo_vnode_relabel = mls_vnode_relabel,
3415eb320b0eSRobert Watson 	.mpo_vnode_setlabel_extattr = mls_vnode_setlabel_extattr,
3416d8a7b7a3SRobert Watson };
3417d8a7b7a3SRobert Watson 
34183f1a7a90SRobert Watson MAC_POLICY_SET(&mls_ops, mac_mls, "TrustedBSD MAC/MLS",
34199162f64bSRobert Watson     MPC_LOADTIME_FLAG_NOTLATE, &mls_slot);
3420