xref: /freebsd/sys/security/mac_lomac/mac_lomac.c (revision db2661ce969f3a57af2f94d322836ec6a913a17d)
1db2661ceSRobert Watson /*-
2db2661ceSRobert Watson  * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3db2661ceSRobert Watson  * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
4db2661ceSRobert Watson  * All rights reserved.
5db2661ceSRobert Watson  *
6db2661ceSRobert Watson  * This software was developed by Robert Watson for the TrustedBSD Project.
7db2661ceSRobert Watson  *
8db2661ceSRobert Watson  * This software was developed for the FreeBSD Project in part by NAI Labs,
9db2661ceSRobert Watson  * the Security Research Division of Network Associates, Inc. under
10db2661ceSRobert Watson  * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
11db2661ceSRobert Watson  * CHATS research program.
12db2661ceSRobert Watson  *
13db2661ceSRobert Watson  * Redistribution and use in source and binary forms, with or without
14db2661ceSRobert Watson  * modification, are permitted provided that the following conditions
15db2661ceSRobert Watson  * are met:
16db2661ceSRobert Watson  * 1. Redistributions of source code must retain the above copyright
17db2661ceSRobert Watson  *    notice, this list of conditions and the following disclaimer.
18db2661ceSRobert Watson  * 2. Redistributions in binary form must reproduce the above copyright
19db2661ceSRobert Watson  *    notice, this list of conditions and the following disclaimer in the
20db2661ceSRobert Watson  *    documentation and/or other materials provided with the distribution.
21db2661ceSRobert Watson  * 3. The names of the authors may not be used to endorse or promote
22db2661ceSRobert Watson  *    products derived from this software without specific prior written
23db2661ceSRobert Watson  *    permission.
24db2661ceSRobert Watson  *
25db2661ceSRobert Watson  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
26db2661ceSRobert Watson  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
27db2661ceSRobert Watson  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
28db2661ceSRobert Watson  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
29db2661ceSRobert Watson  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
30db2661ceSRobert Watson  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
31db2661ceSRobert Watson  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
32db2661ceSRobert Watson  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
33db2661ceSRobert Watson  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
34db2661ceSRobert Watson  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
35db2661ceSRobert Watson  * SUCH DAMAGE.
36db2661ceSRobert Watson  *
37db2661ceSRobert Watson  * $FreeBSD$
38db2661ceSRobert Watson  */
39db2661ceSRobert Watson 
40db2661ceSRobert Watson /*
41db2661ceSRobert Watson  * Developed by the TrustedBSD Project.
42db2661ceSRobert Watson  * Low-watermark floating label mandatory integrity policy.
43db2661ceSRobert Watson  */
44db2661ceSRobert Watson 
45db2661ceSRobert Watson #include <sys/types.h>
46db2661ceSRobert Watson #include <sys/param.h>
47db2661ceSRobert Watson #include <sys/acl.h>
48db2661ceSRobert Watson #include <sys/conf.h>
49db2661ceSRobert Watson #include <sys/extattr.h>
50db2661ceSRobert Watson #include <sys/kernel.h>
51db2661ceSRobert Watson #include <sys/mac.h>
52db2661ceSRobert Watson #include <sys/malloc.h>
53db2661ceSRobert Watson #include <sys/mount.h>
54db2661ceSRobert Watson #include <sys/proc.h>
55db2661ceSRobert Watson #include <sys/systm.h>
56db2661ceSRobert Watson #include <sys/sysproto.h>
57db2661ceSRobert Watson #include <sys/sysent.h>
58db2661ceSRobert Watson #include <sys/systm.h>
59db2661ceSRobert Watson #include <sys/vnode.h>
60db2661ceSRobert Watson #include <sys/file.h>
61db2661ceSRobert Watson #include <sys/socket.h>
62db2661ceSRobert Watson #include <sys/socketvar.h>
63db2661ceSRobert Watson #include <sys/pipe.h>
64db2661ceSRobert Watson #include <sys/sysctl.h>
65db2661ceSRobert Watson #include <sys/syslog.h>
66db2661ceSRobert Watson 
67db2661ceSRobert Watson #include <fs/devfs/devfs.h>
68db2661ceSRobert Watson 
69db2661ceSRobert Watson #include <net/bpfdesc.h>
70db2661ceSRobert Watson #include <net/if.h>
71db2661ceSRobert Watson #include <net/if_types.h>
72db2661ceSRobert Watson #include <net/if_var.h>
73db2661ceSRobert Watson 
74db2661ceSRobert Watson #include <netinet/in.h>
75db2661ceSRobert Watson #include <netinet/ip_var.h>
76db2661ceSRobert Watson 
77db2661ceSRobert Watson #include <vm/vm.h>
78db2661ceSRobert Watson 
79db2661ceSRobert Watson #include <sys/mac_policy.h>
80db2661ceSRobert Watson 
81db2661ceSRobert Watson #include <security/mac_lomac/mac_lomac.h>
82db2661ceSRobert Watson 
83db2661ceSRobert Watson struct mac_lomac_proc {
84db2661ceSRobert Watson 	struct mac_lomac mac_lomac;
85db2661ceSRobert Watson 	struct mtx mtx;
86db2661ceSRobert Watson };
87db2661ceSRobert Watson 
88db2661ceSRobert Watson SYSCTL_DECL(_security_mac);
89db2661ceSRobert Watson 
90db2661ceSRobert Watson SYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
91db2661ceSRobert Watson     "TrustedBSD mac_lomac policy controls");
92db2661ceSRobert Watson 
93db2661ceSRobert Watson static int	mac_lomac_label_size = sizeof(struct mac_lomac);
94db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
95db2661ceSRobert Watson     &mac_lomac_label_size, 0, "Size of struct mac_lomac");
96db2661ceSRobert Watson 
97db2661ceSRobert Watson static int	mac_lomac_enabled = 0;
98db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW,
99db2661ceSRobert Watson     &mac_lomac_enabled, 0, "Enforce MAC/LOMAC policy");
100db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.enabled", &mac_lomac_enabled);
101db2661ceSRobert Watson 
102db2661ceSRobert Watson static int	destroyed_not_inited;
103db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
104db2661ceSRobert Watson     &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
105db2661ceSRobert Watson 
106db2661ceSRobert Watson static int	trust_all_interfaces = 0;
107db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
108db2661ceSRobert Watson     &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
109db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces);
110db2661ceSRobert Watson 
111db2661ceSRobert Watson static char	trusted_interfaces[128];
112db2661ceSRobert Watson SYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
113db2661ceSRobert Watson     trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
114db2661ceSRobert Watson TUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces,
115db2661ceSRobert Watson     sizeof(trusted_interfaces));
116db2661ceSRobert Watson 
117db2661ceSRobert Watson static int	ptys_equal = 0;
118db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW,
119db2661ceSRobert Watson     &ptys_equal, 0, "Label pty devices as lomac/equal on create");
120db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal);
121db2661ceSRobert Watson 
122db2661ceSRobert Watson static int	revocation_enabled = 1;
123db2661ceSRobert Watson SYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW,
124db2661ceSRobert Watson     &revocation_enabled, 0, "Revoke access to objects on relabel");
125db2661ceSRobert Watson TUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled);
126db2661ceSRobert Watson 
127db2661ceSRobert Watson static int	mac_lomac_slot;
128db2661ceSRobert Watson #define	SLOT(l)	((struct mac_lomac *)LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
129db2661ceSRobert Watson #define	PSLOT(l) ((struct mac_lomac_proc *)				\
130db2661ceSRobert Watson     LABEL_TO_SLOT((l), mac_lomac_slot).l_ptr)
131db2661ceSRobert Watson 
132db2661ceSRobert Watson MALLOC_DEFINE(M_MACLOMAC, "lomac label", "MAC/LOMAC labels");
133db2661ceSRobert Watson 
134db2661ceSRobert Watson static struct mac_lomac *
135db2661ceSRobert Watson lomac_alloc(int flag)
136db2661ceSRobert Watson {
137db2661ceSRobert Watson 	struct mac_lomac *mac_lomac;
138db2661ceSRobert Watson 
139db2661ceSRobert Watson 	mac_lomac = malloc(sizeof(struct mac_lomac), M_MACLOMAC, M_ZERO | flag);
140db2661ceSRobert Watson 
141db2661ceSRobert Watson 	return (mac_lomac);
142db2661ceSRobert Watson }
143db2661ceSRobert Watson 
144db2661ceSRobert Watson static void
145db2661ceSRobert Watson lomac_free(struct mac_lomac *mac_lomac)
146db2661ceSRobert Watson {
147db2661ceSRobert Watson 
148db2661ceSRobert Watson 	if (mac_lomac != NULL)
149db2661ceSRobert Watson 		free(mac_lomac, M_MACLOMAC);
150db2661ceSRobert Watson 	else
151db2661ceSRobert Watson 		atomic_add_int(&destroyed_not_inited, 1);
152db2661ceSRobert Watson }
153db2661ceSRobert Watson 
154db2661ceSRobert Watson static int
155db2661ceSRobert Watson lomac_atmostflags(struct mac_lomac *mac_lomac, int flags)
156db2661ceSRobert Watson {
157db2661ceSRobert Watson 
158db2661ceSRobert Watson 	if ((mac_lomac->ml_flags & flags) != mac_lomac->ml_flags)
159db2661ceSRobert Watson 		return (EINVAL);
160db2661ceSRobert Watson 	return (0);
161db2661ceSRobert Watson }
162db2661ceSRobert Watson 
163db2661ceSRobert Watson static int
164db2661ceSRobert Watson mac_lomac_dominate_element(struct mac_lomac_element *a,
165db2661ceSRobert Watson     struct mac_lomac_element *b)
166db2661ceSRobert Watson {
167db2661ceSRobert Watson 
168db2661ceSRobert Watson 	switch (a->mle_type) {
169db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_EQUAL:
170db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_HIGH:
171db2661ceSRobert Watson 		return (1);
172db2661ceSRobert Watson 
173db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_LOW:
174db2661ceSRobert Watson 		switch (b->mle_type) {
175db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
176db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
177db2661ceSRobert Watson 			return (0);
178db2661ceSRobert Watson 
179db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
180db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
181db2661ceSRobert Watson 			return (1);
182db2661ceSRobert Watson 
183db2661ceSRobert Watson 		default:
184db2661ceSRobert Watson 			panic("mac_lomac_dominate_element: b->mle_type invalid");
185db2661ceSRobert Watson 		}
186db2661ceSRobert Watson 
187db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_GRADE:
188db2661ceSRobert Watson 		switch (b->mle_type) {
189db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
190db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
191db2661ceSRobert Watson 			return (1);
192db2661ceSRobert Watson 
193db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
194db2661ceSRobert Watson 			return (0);
195db2661ceSRobert Watson 
196db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
197db2661ceSRobert Watson 			return (a->mle_grade >= b->mle_grade);
198db2661ceSRobert Watson 
199db2661ceSRobert Watson 		default:
200db2661ceSRobert Watson 			panic("mac_lomac_dominate_element: b->mle_type invalid");
201db2661ceSRobert Watson 		}
202db2661ceSRobert Watson 
203db2661ceSRobert Watson 	default:
204db2661ceSRobert Watson 		panic("mac_lomac_dominate_element: a->mle_type invalid");
205db2661ceSRobert Watson 	}
206db2661ceSRobert Watson }
207db2661ceSRobert Watson 
208db2661ceSRobert Watson static int
209db2661ceSRobert Watson mac_lomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
210db2661ceSRobert Watson {
211db2661ceSRobert Watson 
212db2661ceSRobert Watson 	return (mac_lomac_dominate_element(&rangeb->ml_rangehigh,
213db2661ceSRobert Watson 	    &rangea->ml_rangehigh) &&
214db2661ceSRobert Watson 	    mac_lomac_dominate_element(&rangea->ml_rangelow,
215db2661ceSRobert Watson 	    &rangeb->ml_rangelow));
216db2661ceSRobert Watson }
217db2661ceSRobert Watson 
218db2661ceSRobert Watson static int
219db2661ceSRobert Watson mac_lomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
220db2661ceSRobert Watson {
221db2661ceSRobert Watson 
222db2661ceSRobert Watson 	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
223db2661ceSRobert Watson 	    ("mac_lomac_single_in_range: a not single"));
224db2661ceSRobert Watson 	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
225db2661ceSRobert Watson 	    ("mac_lomac_single_in_range: b not range"));
226db2661ceSRobert Watson 
227db2661ceSRobert Watson 	return (mac_lomac_dominate_element(&range->ml_rangehigh,
228db2661ceSRobert Watson 	    &single->ml_single) &&
229db2661ceSRobert Watson 	    mac_lomac_dominate_element(&single->ml_single,
230db2661ceSRobert Watson 	    &range->ml_rangelow));
231db2661ceSRobert Watson }
232db2661ceSRobert Watson 
233db2661ceSRobert Watson static int
234db2661ceSRobert Watson mac_lomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
235db2661ceSRobert Watson {
236db2661ceSRobert Watson 
237db2661ceSRobert Watson 	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
238db2661ceSRobert Watson 	    ("mac_lomac_single_in_range: a not auxsingle"));
239db2661ceSRobert Watson 	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
240db2661ceSRobert Watson 	    ("mac_lomac_single_in_range: b not range"));
241db2661ceSRobert Watson 
242db2661ceSRobert Watson 	return (mac_lomac_dominate_element(&range->ml_rangehigh,
243db2661ceSRobert Watson 	    &single->ml_auxsingle) &&
244db2661ceSRobert Watson 	    mac_lomac_dominate_element(&single->ml_auxsingle,
245db2661ceSRobert Watson 	    &range->ml_rangelow));
246db2661ceSRobert Watson 
247db2661ceSRobert Watson 	return (1);
248db2661ceSRobert Watson }
249db2661ceSRobert Watson 
250db2661ceSRobert Watson static int
251db2661ceSRobert Watson mac_lomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
252db2661ceSRobert Watson {
253db2661ceSRobert Watson 	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
254db2661ceSRobert Watson 	    ("mac_lomac_dominate_single: a not single"));
255db2661ceSRobert Watson 	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
256db2661ceSRobert Watson 	    ("mac_lomac_dominate_single: b not single"));
257db2661ceSRobert Watson 
258db2661ceSRobert Watson 	return (mac_lomac_dominate_element(&a->ml_single, &b->ml_single));
259db2661ceSRobert Watson }
260db2661ceSRobert Watson 
261db2661ceSRobert Watson static int
262db2661ceSRobert Watson mac_lomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
263db2661ceSRobert Watson {
264db2661ceSRobert Watson 	KASSERT((~a->ml_flags &
265db2661ceSRobert Watson 	    (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
266db2661ceSRobert Watson 	    ("mac_lomac_dominate_single: a not subject"));
267db2661ceSRobert Watson 	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
268db2661ceSRobert Watson 	    ("mac_lomac_dominate_single: b not single"));
269db2661ceSRobert Watson 
270db2661ceSRobert Watson 	return (mac_lomac_dominate_element(&a->ml_rangehigh,
271db2661ceSRobert Watson 	    &b->ml_single));
272db2661ceSRobert Watson }
273db2661ceSRobert Watson 
274db2661ceSRobert Watson static int
275db2661ceSRobert Watson mac_lomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
276db2661ceSRobert Watson {
277db2661ceSRobert Watson 
278db2661ceSRobert Watson 	if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
279db2661ceSRobert Watson 	    b->mle_type == MAC_LOMAC_TYPE_EQUAL)
280db2661ceSRobert Watson 		return (1);
281db2661ceSRobert Watson 
282db2661ceSRobert Watson 	return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
283db2661ceSRobert Watson }
284db2661ceSRobert Watson 
285db2661ceSRobert Watson static int
286db2661ceSRobert Watson mac_lomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
287db2661ceSRobert Watson {
288db2661ceSRobert Watson 
289db2661ceSRobert Watson 	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
290db2661ceSRobert Watson 	    ("mac_lomac_equal_single: a not single"));
291db2661ceSRobert Watson 	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
292db2661ceSRobert Watson 	    ("mac_lomac_equal_single: b not single"));
293db2661ceSRobert Watson 
294db2661ceSRobert Watson 	return (mac_lomac_equal_element(&a->ml_single, &b->ml_single));
295db2661ceSRobert Watson }
296db2661ceSRobert Watson 
297db2661ceSRobert Watson static int
298db2661ceSRobert Watson mac_lomac_contains_equal(struct mac_lomac *mac_lomac)
299db2661ceSRobert Watson {
300db2661ceSRobert Watson 
301db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE)
302db2661ceSRobert Watson 		if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
303db2661ceSRobert Watson 			return (1);
304db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX)
305db2661ceSRobert Watson 		if (mac_lomac->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
306db2661ceSRobert Watson 			return (1);
307db2661ceSRobert Watson 
308db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
309db2661ceSRobert Watson 		if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
310db2661ceSRobert Watson 			return (1);
311db2661ceSRobert Watson 		if (mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
312db2661ceSRobert Watson 			return (1);
313db2661ceSRobert Watson 	}
314db2661ceSRobert Watson 
315db2661ceSRobert Watson 	return (0);
316db2661ceSRobert Watson }
317db2661ceSRobert Watson 
318db2661ceSRobert Watson static int
319db2661ceSRobert Watson mac_lomac_subject_privileged(struct mac_lomac *mac_lomac)
320db2661ceSRobert Watson {
321db2661ceSRobert Watson 
322db2661ceSRobert Watson 	KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
323db2661ceSRobert Watson 	    MAC_LOMAC_FLAGS_BOTH,
324db2661ceSRobert Watson 	    ("mac_lomac_subject_privileged: subject doesn't have both labels"));
325db2661ceSRobert Watson 
326db2661ceSRobert Watson 	/* If the single is EQUAL, it's ok. */
327db2661ceSRobert Watson 	if (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
328db2661ceSRobert Watson 		return (0);
329db2661ceSRobert Watson 
330db2661ceSRobert Watson 	/* If either range endpoint is EQUAL, it's ok. */
331db2661ceSRobert Watson 	if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
332db2661ceSRobert Watson 	    mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
333db2661ceSRobert Watson 		return (0);
334db2661ceSRobert Watson 
335db2661ceSRobert Watson 	/* If the range is low-high, it's ok. */
336db2661ceSRobert Watson 	if (mac_lomac->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
337db2661ceSRobert Watson 	    mac_lomac->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
338db2661ceSRobert Watson 		return (0);
339db2661ceSRobert Watson 
340db2661ceSRobert Watson 	/* It's not ok. */
341db2661ceSRobert Watson 	return (EPERM);
342db2661ceSRobert Watson }
343db2661ceSRobert Watson 
344db2661ceSRobert Watson static int
345db2661ceSRobert Watson mac_lomac_high_single(struct mac_lomac *mac_lomac)
346db2661ceSRobert Watson {
347db2661ceSRobert Watson 
348db2661ceSRobert Watson 	KASSERT((mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
349db2661ceSRobert Watson 	    ("mac_lomac_high_single: mac_lomac not single"));
350db2661ceSRobert Watson 
351db2661ceSRobert Watson 	return (mac_lomac->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
352db2661ceSRobert Watson }
353db2661ceSRobert Watson 
354db2661ceSRobert Watson static int
355db2661ceSRobert Watson mac_lomac_valid(struct mac_lomac *mac_lomac)
356db2661ceSRobert Watson {
357db2661ceSRobert Watson 
358db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
359db2661ceSRobert Watson 		switch (mac_lomac->ml_single.mle_type) {
360db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
361db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
362db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
363db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
364db2661ceSRobert Watson 			break;
365db2661ceSRobert Watson 
366db2661ceSRobert Watson 		default:
367db2661ceSRobert Watson 			return (EINVAL);
368db2661ceSRobert Watson 		}
369db2661ceSRobert Watson 	} else {
370db2661ceSRobert Watson 		if (mac_lomac->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
371db2661ceSRobert Watson 			return (EINVAL);
372db2661ceSRobert Watson 	}
373db2661ceSRobert Watson 
374db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
375db2661ceSRobert Watson 		switch (mac_lomac->ml_auxsingle.mle_type) {
376db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
377db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
378db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
379db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
380db2661ceSRobert Watson 			break;
381db2661ceSRobert Watson 
382db2661ceSRobert Watson 		default:
383db2661ceSRobert Watson 			return (EINVAL);
384db2661ceSRobert Watson 		}
385db2661ceSRobert Watson 	} else {
386db2661ceSRobert Watson 		if (mac_lomac->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
387db2661ceSRobert Watson 			return (EINVAL);
388db2661ceSRobert Watson 	}
389db2661ceSRobert Watson 
390db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
391db2661ceSRobert Watson 		switch (mac_lomac->ml_rangelow.mle_type) {
392db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
393db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
394db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
395db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
396db2661ceSRobert Watson 			break;
397db2661ceSRobert Watson 
398db2661ceSRobert Watson 		default:
399db2661ceSRobert Watson 			return (EINVAL);
400db2661ceSRobert Watson 		}
401db2661ceSRobert Watson 
402db2661ceSRobert Watson 		switch (mac_lomac->ml_rangehigh.mle_type) {
403db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_GRADE:
404db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_EQUAL:
405db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_HIGH:
406db2661ceSRobert Watson 		case MAC_LOMAC_TYPE_LOW:
407db2661ceSRobert Watson 			break;
408db2661ceSRobert Watson 
409db2661ceSRobert Watson 		default:
410db2661ceSRobert Watson 			return (EINVAL);
411db2661ceSRobert Watson 		}
412db2661ceSRobert Watson 		if (!mac_lomac_dominate_element(&mac_lomac->ml_rangehigh,
413db2661ceSRobert Watson 		    &mac_lomac->ml_rangelow))
414db2661ceSRobert Watson 			return (EINVAL);
415db2661ceSRobert Watson 	} else {
416db2661ceSRobert Watson 		if (mac_lomac->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
417db2661ceSRobert Watson 		    mac_lomac->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
418db2661ceSRobert Watson 			return (EINVAL);
419db2661ceSRobert Watson 	}
420db2661ceSRobert Watson 
421db2661ceSRobert Watson 	return (0);
422db2661ceSRobert Watson }
423db2661ceSRobert Watson 
424db2661ceSRobert Watson static void
425db2661ceSRobert Watson mac_lomac_set_range(struct mac_lomac *mac_lomac, u_short typelow,
426db2661ceSRobert Watson     u_short gradelow, u_short typehigh, u_short gradehigh)
427db2661ceSRobert Watson {
428db2661ceSRobert Watson 
429db2661ceSRobert Watson 	mac_lomac->ml_rangelow.mle_type = typelow;
430db2661ceSRobert Watson 	mac_lomac->ml_rangelow.mle_grade = gradelow;
431db2661ceSRobert Watson 	mac_lomac->ml_rangehigh.mle_type = typehigh;
432db2661ceSRobert Watson 	mac_lomac->ml_rangehigh.mle_grade = gradehigh;
433db2661ceSRobert Watson 	mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
434db2661ceSRobert Watson }
435db2661ceSRobert Watson 
436db2661ceSRobert Watson static void
437db2661ceSRobert Watson mac_lomac_set_single(struct mac_lomac *mac_lomac, u_short type, u_short grade)
438db2661ceSRobert Watson {
439db2661ceSRobert Watson 
440db2661ceSRobert Watson 	mac_lomac->ml_single.mle_type = type;
441db2661ceSRobert Watson 	mac_lomac->ml_single.mle_grade = grade;
442db2661ceSRobert Watson 	mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
443db2661ceSRobert Watson }
444db2661ceSRobert Watson 
445db2661ceSRobert Watson static void
446db2661ceSRobert Watson mac_lomac_set_auxsingle(struct mac_lomac *mac_lomac, u_short type,
447db2661ceSRobert Watson     u_short grade)
448db2661ceSRobert Watson {
449db2661ceSRobert Watson 
450db2661ceSRobert Watson 	mac_lomac->ml_auxsingle.mle_type = type;
451db2661ceSRobert Watson 	mac_lomac->ml_auxsingle.mle_grade = grade;
452db2661ceSRobert Watson 	mac_lomac->ml_flags |= MAC_LOMAC_FLAG_AUX;
453db2661ceSRobert Watson }
454db2661ceSRobert Watson 
455db2661ceSRobert Watson static void
456db2661ceSRobert Watson mac_lomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
457db2661ceSRobert Watson {
458db2661ceSRobert Watson 
459db2661ceSRobert Watson 	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
460db2661ceSRobert Watson 	    ("mac_lomac_copy_range: labelfrom not range"));
461db2661ceSRobert Watson 
462db2661ceSRobert Watson 	labelto->ml_rangelow = labelfrom->ml_rangelow;
463db2661ceSRobert Watson 	labelto->ml_rangehigh = labelfrom->ml_rangehigh;
464db2661ceSRobert Watson 	labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
465db2661ceSRobert Watson }
466db2661ceSRobert Watson 
467db2661ceSRobert Watson static void
468db2661ceSRobert Watson mac_lomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
469db2661ceSRobert Watson {
470db2661ceSRobert Watson 
471db2661ceSRobert Watson 	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
472db2661ceSRobert Watson 	    ("mac_lomac_copy_single: labelfrom not single"));
473db2661ceSRobert Watson 
474db2661ceSRobert Watson 	labelto->ml_single = labelfrom->ml_single;
475db2661ceSRobert Watson 	labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
476db2661ceSRobert Watson }
477db2661ceSRobert Watson 
478db2661ceSRobert Watson static void
479db2661ceSRobert Watson mac_lomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
480db2661ceSRobert Watson {
481db2661ceSRobert Watson 
482db2661ceSRobert Watson 	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
483db2661ceSRobert Watson 	    ("mac_lomac_copy_auxsingle: labelfrom not auxsingle"));
484db2661ceSRobert Watson 
485db2661ceSRobert Watson 	labelto->ml_auxsingle = labelfrom->ml_auxsingle;
486db2661ceSRobert Watson 	labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
487db2661ceSRobert Watson }
488db2661ceSRobert Watson 
489db2661ceSRobert Watson static void
490db2661ceSRobert Watson mac_lomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
491db2661ceSRobert Watson {
492db2661ceSRobert Watson 
493db2661ceSRobert Watson 	if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
494db2661ceSRobert Watson 		mac_lomac_copy_single(source, dest);
495db2661ceSRobert Watson 	if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
496db2661ceSRobert Watson 		mac_lomac_copy_auxsingle(source, dest);
497db2661ceSRobert Watson 	if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
498db2661ceSRobert Watson 		mac_lomac_copy_range(source, dest);
499db2661ceSRobert Watson }
500db2661ceSRobert Watson 
501db2661ceSRobert Watson static int	mac_lomac_to_string(char *string, size_t size,
502db2661ceSRobert Watson 	    size_t *caller_len, struct mac_lomac *mac_lomac);
503db2661ceSRobert Watson 
504db2661ceSRobert Watson static int
505db2661ceSRobert Watson maybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
506db2661ceSRobert Watson     const char *actionname, const char *objname, struct vnode *vpq)
507db2661ceSRobert Watson {
508db2661ceSRobert Watson 	struct vattr va;
509db2661ceSRobert Watson 	static const char xxx[] = "<<XXX>>";
510db2661ceSRobert Watson 	struct mac_lomac_proc *subj = PSLOT(&curthread->td_proc->p_label);
511db2661ceSRobert Watson 	char *subjlabeltext, *objlabeltext, *subjtext, *text;
512db2661ceSRobert Watson 	struct proc *p;
513db2661ceSRobert Watson 	size_t len;
514db2661ceSRobert Watson 	pid_t pgid;
515db2661ceSRobert Watson 
516db2661ceSRobert Watson 	p = curthread->td_proc;
517db2661ceSRobert Watson 	mtx_lock(&subj->mtx);
518db2661ceSRobert Watson         if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
519db2661ceSRobert Watson 		/*
520db2661ceSRobert Watson 		 * Check to see if the pending demotion would be more or
521db2661ceSRobert Watson 		 * less severe than this one, and keep the more severe.
522db2661ceSRobert Watson 		 * This can only happen for a multi-threaded application.
523db2661ceSRobert Watson 		 */
524db2661ceSRobert Watson 		if (mac_lomac_dominate_single(objlabel, &subj->mac_lomac)) {
525db2661ceSRobert Watson 			mtx_unlock(&subj->mtx);
526db2661ceSRobert Watson 			return (0);
527db2661ceSRobert Watson 		}
528db2661ceSRobert Watson 	}
529db2661ceSRobert Watson 	bzero(&subj->mac_lomac, sizeof(subj->mac_lomac));
530db2661ceSRobert Watson 	/*
531db2661ceSRobert Watson 	 * Always demote the single label.
532db2661ceSRobert Watson 	 */
533db2661ceSRobert Watson 	mac_lomac_copy_single(objlabel, &subj->mac_lomac);
534db2661ceSRobert Watson 	/*
535db2661ceSRobert Watson 	 * Start with the original range, then minimize each side of
536db2661ceSRobert Watson 	 * the range to the point of not dominating the object.  The
537db2661ceSRobert Watson 	 * high side will always be demoted, of course.
538db2661ceSRobert Watson 	 */
539db2661ceSRobert Watson 	mac_lomac_copy_range(subjlabel, &subj->mac_lomac);
540db2661ceSRobert Watson 	if (!mac_lomac_dominate_element(&objlabel->ml_single,
541db2661ceSRobert Watson 	    &subj->mac_lomac.ml_rangelow))
542db2661ceSRobert Watson 		subj->mac_lomac.ml_rangelow = objlabel->ml_single;
543db2661ceSRobert Watson 	subj->mac_lomac.ml_rangehigh = objlabel->ml_single;
544db2661ceSRobert Watson 	subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE;
545db2661ceSRobert Watson 	mtx_lock_spin(&sched_lock);
546db2661ceSRobert Watson 	curthread->td_kse->ke_flags |= KEF_ASTPENDING;
547db2661ceSRobert Watson 	curthread->td_proc->p_sflag |= PS_MACPEND;
548db2661ceSRobert Watson 	mtx_unlock_spin(&sched_lock);
549db2661ceSRobert Watson 	subjtext = subjlabeltext = objlabeltext = xxx;
550db2661ceSRobert Watson 	if (mac_lomac_to_string(NULL, 0, &len, &subj->mac_lomac) == 0 &&
551db2661ceSRobert Watson 	    (text = malloc(len + 1, M_MACLOMAC, M_NOWAIT)) != NULL) {
552db2661ceSRobert Watson 		if (mac_lomac_to_string(text, len + 1, &len,
553db2661ceSRobert Watson 		    &subj->mac_lomac) == 0)
554db2661ceSRobert Watson 			subjtext = text;
555db2661ceSRobert Watson 		else
556db2661ceSRobert Watson 			free(text, M_MACLOMAC);
557db2661ceSRobert Watson 	}
558db2661ceSRobert Watson 	mtx_unlock(&subj->mtx);
559db2661ceSRobert Watson 	if (mac_lomac_to_string(NULL, 0, &len, subjlabel) == 0 &&
560db2661ceSRobert Watson 	    (text = malloc(len + 1, M_MACLOMAC, M_NOWAIT)) != NULL) {
561db2661ceSRobert Watson 		if (mac_lomac_to_string(text, len + 1, &len,
562db2661ceSRobert Watson 		    subjlabel) == 0)
563db2661ceSRobert Watson 			subjlabeltext = text;
564db2661ceSRobert Watson 		else
565db2661ceSRobert Watson 			free(text, M_MACLOMAC);
566db2661ceSRobert Watson 	}
567db2661ceSRobert Watson 	if (mac_lomac_to_string(NULL, 0, &len, objlabel) == 0 &&
568db2661ceSRobert Watson 	    (text = malloc(len + 1, M_MACLOMAC, M_NOWAIT)) != NULL) {
569db2661ceSRobert Watson 		if (mac_lomac_to_string(text, len + 1, &len,
570db2661ceSRobert Watson 		    objlabel) == 0)
571db2661ceSRobert Watson 			objlabeltext = text;
572db2661ceSRobert Watson 		else
573db2661ceSRobert Watson 			free(text, M_MACLOMAC);
574db2661ceSRobert Watson 	}
575db2661ceSRobert Watson 	pgid = p->p_pgrp->pg_id;		/* XXX could be stale? */
576db2661ceSRobert Watson 	if (vpq != NULL && VOP_GETATTR(vpq, &va, curthread->td_ucred,
577db2661ceSRobert Watson 	    curthread) == 0) {
578db2661ceSRobert Watson 		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
579db2661ceSRobert Watson 		    " level %s after %s a level-%s %s (inode=%ld, "
580db2661ceSRobert Watson 		    "mountpount=%s)\n",
581db2661ceSRobert Watson 		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
582db2661ceSRobert Watson 		    p->p_comm, subjtext, actionname, objlabeltext, objname,
583db2661ceSRobert Watson 		    va.va_fileid, vpq->v_mount->mnt_stat.f_mntonname);
584db2661ceSRobert Watson 	} else {
585db2661ceSRobert Watson 		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
586db2661ceSRobert Watson 		    " level %s after %s a level-%s %s\n",
587db2661ceSRobert Watson 		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
588db2661ceSRobert Watson 		    p->p_comm, subjtext, actionname, objlabeltext, objname);
589db2661ceSRobert Watson 	}
590db2661ceSRobert Watson 
591db2661ceSRobert Watson 	if (subjlabeltext != xxx)
592db2661ceSRobert Watson 		free(subjlabeltext, M_MACLOMAC);
593db2661ceSRobert Watson 	if (objlabeltext != xxx)
594db2661ceSRobert Watson 		free(objlabeltext, M_MACLOMAC);
595db2661ceSRobert Watson 	if (subjtext != xxx)
596db2661ceSRobert Watson 		free(subjtext, M_MACLOMAC);
597db2661ceSRobert Watson 	return (0);
598db2661ceSRobert Watson }
599db2661ceSRobert Watson 
600db2661ceSRobert Watson /*
601db2661ceSRobert Watson  * Relabel "to" to "from" only if "from" is a valid label (contains
602db2661ceSRobert Watson  * at least a single), as for a relabel operation which may or may
603db2661ceSRobert Watson  * not involve a relevant label.
604db2661ceSRobert Watson  */
605db2661ceSRobert Watson void
606db2661ceSRobert Watson try_relabel(struct mac_lomac *from, struct mac_lomac *to)
607db2661ceSRobert Watson {
608db2661ceSRobert Watson 
609db2661ceSRobert Watson 	if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
610db2661ceSRobert Watson 		bzero(to, sizeof(*to));
611db2661ceSRobert Watson 		mac_lomac_copy(from, to);
612db2661ceSRobert Watson 	}
613db2661ceSRobert Watson }
614db2661ceSRobert Watson 
615db2661ceSRobert Watson /*
616db2661ceSRobert Watson  * Policy module operations.
617db2661ceSRobert Watson  */
618db2661ceSRobert Watson static void
619db2661ceSRobert Watson mac_lomac_destroy(struct mac_policy_conf *conf)
620db2661ceSRobert Watson {
621db2661ceSRobert Watson 
622db2661ceSRobert Watson }
623db2661ceSRobert Watson 
624db2661ceSRobert Watson static void
625db2661ceSRobert Watson mac_lomac_init(struct mac_policy_conf *conf)
626db2661ceSRobert Watson {
627db2661ceSRobert Watson 
628db2661ceSRobert Watson }
629db2661ceSRobert Watson 
630db2661ceSRobert Watson /*
631db2661ceSRobert Watson  * Label operations.
632db2661ceSRobert Watson  */
633db2661ceSRobert Watson static void
634db2661ceSRobert Watson mac_lomac_init_label(struct label *label)
635db2661ceSRobert Watson {
636db2661ceSRobert Watson 
637db2661ceSRobert Watson 	SLOT(label) = lomac_alloc(M_WAITOK);
638db2661ceSRobert Watson }
639db2661ceSRobert Watson 
640db2661ceSRobert Watson static int
641db2661ceSRobert Watson mac_lomac_init_label_waitcheck(struct label *label, int flag)
642db2661ceSRobert Watson {
643db2661ceSRobert Watson 
644db2661ceSRobert Watson 	SLOT(label) = lomac_alloc(flag);
645db2661ceSRobert Watson 	if (SLOT(label) == NULL)
646db2661ceSRobert Watson 		return (ENOMEM);
647db2661ceSRobert Watson 
648db2661ceSRobert Watson 	return (0);
649db2661ceSRobert Watson }
650db2661ceSRobert Watson 
651db2661ceSRobert Watson static void
652db2661ceSRobert Watson mac_lomac_init_proc_label(struct label *label)
653db2661ceSRobert Watson {
654db2661ceSRobert Watson 
655db2661ceSRobert Watson 	PSLOT(label) = malloc(sizeof(struct mac_lomac_proc), M_MACLOMAC,
656db2661ceSRobert Watson 	    M_ZERO | M_WAITOK);
657db2661ceSRobert Watson 	mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
658db2661ceSRobert Watson }
659db2661ceSRobert Watson 
660db2661ceSRobert Watson static void
661db2661ceSRobert Watson mac_lomac_destroy_label(struct label *label)
662db2661ceSRobert Watson {
663db2661ceSRobert Watson 
664db2661ceSRobert Watson 	lomac_free(SLOT(label));
665db2661ceSRobert Watson 	SLOT(label) = NULL;
666db2661ceSRobert Watson }
667db2661ceSRobert Watson 
668db2661ceSRobert Watson static void
669db2661ceSRobert Watson mac_lomac_destroy_proc_label(struct label *label)
670db2661ceSRobert Watson {
671db2661ceSRobert Watson 
672db2661ceSRobert Watson 	mtx_destroy(&PSLOT(label)->mtx);
673db2661ceSRobert Watson 	FREE(PSLOT(label), M_MACLOMAC);
674db2661ceSRobert Watson 	PSLOT(label) = NULL;
675db2661ceSRobert Watson }
676db2661ceSRobert Watson 
677db2661ceSRobert Watson /*
678db2661ceSRobert Watson  * mac_lomac_element_to_string() is basically an snprintf wrapper with
679db2661ceSRobert Watson  * the same properties as snprintf().  It returns the length it would
680db2661ceSRobert Watson  * have added to the string in the event the string is too short.
681db2661ceSRobert Watson  */
682db2661ceSRobert Watson static size_t
683db2661ceSRobert Watson mac_lomac_element_to_string(char *string, size_t size,
684db2661ceSRobert Watson     struct mac_lomac_element *element)
685db2661ceSRobert Watson {
686db2661ceSRobert Watson 
687db2661ceSRobert Watson 	switch (element->mle_type) {
688db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_HIGH:
689db2661ceSRobert Watson 		return (snprintf(string, size, "high"));
690db2661ceSRobert Watson 
691db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_LOW:
692db2661ceSRobert Watson 		return (snprintf(string, size, "low"));
693db2661ceSRobert Watson 
694db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_EQUAL:
695db2661ceSRobert Watson 		return (snprintf(string, size, "equal"));
696db2661ceSRobert Watson 
697db2661ceSRobert Watson 	case MAC_LOMAC_TYPE_GRADE:
698db2661ceSRobert Watson 		return (snprintf(string, size, "%d", element->mle_grade));
699db2661ceSRobert Watson 
700db2661ceSRobert Watson 	default:
701db2661ceSRobert Watson 		panic("mac_lomac_element_to_string: invalid type (%d)",
702db2661ceSRobert Watson 		    element->mle_type);
703db2661ceSRobert Watson 	}
704db2661ceSRobert Watson }
705db2661ceSRobert Watson 
706db2661ceSRobert Watson static int
707db2661ceSRobert Watson mac_lomac_to_string(char *string, size_t size, size_t *caller_len,
708db2661ceSRobert Watson     struct mac_lomac *mac_lomac)
709db2661ceSRobert Watson {
710db2661ceSRobert Watson 	size_t left, len, curlen;
711db2661ceSRobert Watson 	char *curptr;
712db2661ceSRobert Watson 
713db2661ceSRobert Watson 	/*
714db2661ceSRobert Watson 	 * Also accept NULL string to allow for predetermination of total
715db2661ceSRobert Watson 	 * string length.
716db2661ceSRobert Watson 	 */
717db2661ceSRobert Watson 	if (string != NULL)
718db2661ceSRobert Watson 		bzero(string, size);
719db2661ceSRobert Watson 	else if (size != 0)
720db2661ceSRobert Watson 		return (EINVAL);
721db2661ceSRobert Watson 	curptr = string;
722db2661ceSRobert Watson 	left = size;
723db2661ceSRobert Watson 	curlen = 0;
724db2661ceSRobert Watson 
725db2661ceSRobert Watson #define	INCLEN(length, leftover) do {					\
726db2661ceSRobert Watson 	if (string != NULL) {						\
727db2661ceSRobert Watson 		if (length >= leftover)					\
728db2661ceSRobert Watson 			return (EINVAL);				\
729db2661ceSRobert Watson 		leftover -= length;					\
730db2661ceSRobert Watson 		curptr += length;					\
731db2661ceSRobert Watson 	}								\
732db2661ceSRobert Watson 	curlen += length;						\
733db2661ceSRobert Watson } while (0)
734db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
735db2661ceSRobert Watson 		len = mac_lomac_element_to_string(curptr, left,
736db2661ceSRobert Watson 		    &mac_lomac->ml_single);
737db2661ceSRobert Watson 		INCLEN(len, left);
738db2661ceSRobert Watson 	}
739db2661ceSRobert Watson 
740db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_AUX) {
741db2661ceSRobert Watson 		len = snprintf(curptr, left, "[");
742db2661ceSRobert Watson 		INCLEN(len, left);
743db2661ceSRobert Watson 
744db2661ceSRobert Watson 		len = mac_lomac_element_to_string(curptr, left,
745db2661ceSRobert Watson 		    &mac_lomac->ml_auxsingle);
746db2661ceSRobert Watson 		INCLEN(len, left);
747db2661ceSRobert Watson 
748db2661ceSRobert Watson 		len = snprintf(curptr, left, "]");
749db2661ceSRobert Watson 		INCLEN(len, left);
750db2661ceSRobert Watson 	}
751db2661ceSRobert Watson 
752db2661ceSRobert Watson 	if (mac_lomac->ml_flags & MAC_LOMAC_FLAG_RANGE) {
753db2661ceSRobert Watson 		len = snprintf(curptr, left, "(");
754db2661ceSRobert Watson 		INCLEN(len, left);
755db2661ceSRobert Watson 
756db2661ceSRobert Watson 		len = mac_lomac_element_to_string(curptr, left,
757db2661ceSRobert Watson 		    &mac_lomac->ml_rangelow);
758db2661ceSRobert Watson 		INCLEN(len, left);
759db2661ceSRobert Watson 
760db2661ceSRobert Watson 		len = snprintf(curptr, left, "-");
761db2661ceSRobert Watson 		INCLEN(len, left);
762db2661ceSRobert Watson 
763db2661ceSRobert Watson 		len = mac_lomac_element_to_string(curptr, left,
764db2661ceSRobert Watson 		    &mac_lomac->ml_rangehigh);
765db2661ceSRobert Watson 		INCLEN(len, left);
766db2661ceSRobert Watson 
767db2661ceSRobert Watson 		len = snprintf(curptr, left, ")");
768db2661ceSRobert Watson 		INCLEN(len, left);
769db2661ceSRobert Watson 	}
770db2661ceSRobert Watson #undef INCLEN
771db2661ceSRobert Watson 
772db2661ceSRobert Watson 	*caller_len = curlen;
773db2661ceSRobert Watson 	return (0);
774db2661ceSRobert Watson }
775db2661ceSRobert Watson 
776db2661ceSRobert Watson static int
777db2661ceSRobert Watson mac_lomac_externalize_label(struct label *label, char *element_name,
778db2661ceSRobert Watson     char *element_data, size_t size, size_t *len, int *claimed)
779db2661ceSRobert Watson {
780db2661ceSRobert Watson 	struct mac_lomac *mac_lomac;
781db2661ceSRobert Watson 	int error;
782db2661ceSRobert Watson 
783db2661ceSRobert Watson 	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
784db2661ceSRobert Watson 		return (0);
785db2661ceSRobert Watson 
786db2661ceSRobert Watson 	(*claimed)++;
787db2661ceSRobert Watson 
788db2661ceSRobert Watson 	mac_lomac = SLOT(label);
789db2661ceSRobert Watson 	error = mac_lomac_to_string(element_data, size, len, mac_lomac);
790db2661ceSRobert Watson 	if (error)
791db2661ceSRobert Watson 		return (error);
792db2661ceSRobert Watson 
793db2661ceSRobert Watson 	*len = strlen(element_data);
794db2661ceSRobert Watson 	return (0);
795db2661ceSRobert Watson }
796db2661ceSRobert Watson 
797db2661ceSRobert Watson static int
798db2661ceSRobert Watson mac_lomac_parse_element(struct mac_lomac_element *element, char *string)
799db2661ceSRobert Watson {
800db2661ceSRobert Watson 
801db2661ceSRobert Watson 	if (strcmp(string, "high") == 0 ||
802db2661ceSRobert Watson 	    strcmp(string, "hi") == 0) {
803db2661ceSRobert Watson 		element->mle_type = MAC_LOMAC_TYPE_HIGH;
804db2661ceSRobert Watson 		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
805db2661ceSRobert Watson 	} else if (strcmp(string, "low") == 0 ||
806db2661ceSRobert Watson 	    strcmp(string, "lo") == 0) {
807db2661ceSRobert Watson 		element->mle_type = MAC_LOMAC_TYPE_LOW;
808db2661ceSRobert Watson 		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
809db2661ceSRobert Watson 	} else if (strcmp(string, "equal") == 0 ||
810db2661ceSRobert Watson 	    strcmp(string, "eq") == 0) {
811db2661ceSRobert Watson 		element->mle_type = MAC_LOMAC_TYPE_EQUAL;
812db2661ceSRobert Watson 		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
813db2661ceSRobert Watson 	} else {
814db2661ceSRobert Watson 		char *p0, *p1;
815db2661ceSRobert Watson 		int d;
816db2661ceSRobert Watson 
817db2661ceSRobert Watson 		p0 = string;
818db2661ceSRobert Watson 		d = strtol(p0, &p1, 10);
819db2661ceSRobert Watson 
820db2661ceSRobert Watson 		if (d < 0 || d > 65535)
821db2661ceSRobert Watson 			return (EINVAL);
822db2661ceSRobert Watson 		element->mle_type = MAC_LOMAC_TYPE_GRADE;
823db2661ceSRobert Watson 		element->mle_grade = d;
824db2661ceSRobert Watson 
825db2661ceSRobert Watson 		if (p1 == p0 || *p1 != '\0')
826db2661ceSRobert Watson 			return (EINVAL);
827db2661ceSRobert Watson 	}
828db2661ceSRobert Watson 
829db2661ceSRobert Watson 	return (0);
830db2661ceSRobert Watson }
831db2661ceSRobert Watson 
832db2661ceSRobert Watson /*
833db2661ceSRobert Watson  * Note: destructively consumes the string, make a local copy before
834db2661ceSRobert Watson  * calling if that's a problem.
835db2661ceSRobert Watson  */
836db2661ceSRobert Watson static int
837db2661ceSRobert Watson mac_lomac_parse(struct mac_lomac *mac_lomac, char *string)
838db2661ceSRobert Watson {
839db2661ceSRobert Watson 	char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
840db2661ceSRobert Watson 	    *auxsingleend;
841db2661ceSRobert Watson 	int error;
842db2661ceSRobert Watson 
843db2661ceSRobert Watson 	/* Do we have a range? */
844db2661ceSRobert Watson 	single = string;
845db2661ceSRobert Watson 	range = index(string, '(');
846db2661ceSRobert Watson 	if (range == single)
847db2661ceSRobert Watson 		single = NULL;
848db2661ceSRobert Watson 	auxsingle = index(string, '[');
849db2661ceSRobert Watson 	if (auxsingle == single)
850db2661ceSRobert Watson 		single = NULL;
851db2661ceSRobert Watson 	if (range != NULL && auxsingle != NULL)
852db2661ceSRobert Watson 		return (EINVAL);
853db2661ceSRobert Watson 	rangelow = rangehigh = NULL;
854db2661ceSRobert Watson 	if (range != NULL) {
855db2661ceSRobert Watson 		/* Nul terminate the end of the single string. */
856db2661ceSRobert Watson 		*range = '\0';
857db2661ceSRobert Watson 		range++;
858db2661ceSRobert Watson 		rangelow = range;
859db2661ceSRobert Watson 		rangehigh = index(rangelow, '-');
860db2661ceSRobert Watson 		if (rangehigh == NULL)
861db2661ceSRobert Watson 			return (EINVAL);
862db2661ceSRobert Watson 		rangehigh++;
863db2661ceSRobert Watson 		if (*rangelow == '\0' || *rangehigh == '\0')
864db2661ceSRobert Watson 			return (EINVAL);
865db2661ceSRobert Watson 		rangeend = index(rangehigh, ')');
866db2661ceSRobert Watson 		if (rangeend == NULL)
867db2661ceSRobert Watson 			return (EINVAL);
868db2661ceSRobert Watson 		if (*(rangeend + 1) != '\0')
869db2661ceSRobert Watson 			return (EINVAL);
870db2661ceSRobert Watson 		/* Nul terminate the ends of the ranges. */
871db2661ceSRobert Watson 		*(rangehigh - 1) = '\0';
872db2661ceSRobert Watson 		*rangeend = '\0';
873db2661ceSRobert Watson 	}
874db2661ceSRobert Watson 	KASSERT((rangelow != NULL && rangehigh != NULL) ||
875db2661ceSRobert Watson 	    (rangelow == NULL && rangehigh == NULL),
876db2661ceSRobert Watson 	    ("mac_lomac_internalize_label: range mismatch"));
877db2661ceSRobert Watson 	if (auxsingle != NULL) {
878db2661ceSRobert Watson 		/* Nul terminate the end of the single string. */
879db2661ceSRobert Watson 		*auxsingle = '\0';
880db2661ceSRobert Watson 		auxsingle++;
881db2661ceSRobert Watson 		auxsingleend = index(auxsingle, ']');
882db2661ceSRobert Watson 		if (auxsingleend == NULL)
883db2661ceSRobert Watson 			return (EINVAL);
884db2661ceSRobert Watson 		if (*(auxsingleend + 1) != '\0')
885db2661ceSRobert Watson 			return (EINVAL);
886db2661ceSRobert Watson 		/* Nul terminate the end of the auxsingle. */
887db2661ceSRobert Watson 		*auxsingleend = '\0';
888db2661ceSRobert Watson 	}
889db2661ceSRobert Watson 
890db2661ceSRobert Watson 	bzero(mac_lomac, sizeof(*mac_lomac));
891db2661ceSRobert Watson 	if (single != NULL) {
892db2661ceSRobert Watson 		error = mac_lomac_parse_element(&mac_lomac->ml_single, single);
893db2661ceSRobert Watson 		if (error)
894db2661ceSRobert Watson 			return (error);
895db2661ceSRobert Watson 		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
896db2661ceSRobert Watson 	}
897db2661ceSRobert Watson 
898db2661ceSRobert Watson 	if (auxsingle != NULL) {
899db2661ceSRobert Watson 		error = mac_lomac_parse_element(&mac_lomac->ml_auxsingle,
900db2661ceSRobert Watson 		    auxsingle);
901db2661ceSRobert Watson 		if (error)
902db2661ceSRobert Watson 			return (error);
903db2661ceSRobert Watson 		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_AUX;
904db2661ceSRobert Watson 	}
905db2661ceSRobert Watson 
906db2661ceSRobert Watson 	if (rangelow != NULL) {
907db2661ceSRobert Watson 		error = mac_lomac_parse_element(&mac_lomac->ml_rangelow,
908db2661ceSRobert Watson 		    rangelow);
909db2661ceSRobert Watson 		if (error)
910db2661ceSRobert Watson 			return (error);
911db2661ceSRobert Watson 		error = mac_lomac_parse_element(&mac_lomac->ml_rangehigh,
912db2661ceSRobert Watson 		    rangehigh);
913db2661ceSRobert Watson 		if (error)
914db2661ceSRobert Watson 			return (error);
915db2661ceSRobert Watson 		mac_lomac->ml_flags |= MAC_LOMAC_FLAG_RANGE;
916db2661ceSRobert Watson 	}
917db2661ceSRobert Watson 
918db2661ceSRobert Watson 	error = mac_lomac_valid(mac_lomac);
919db2661ceSRobert Watson 	if (error)
920db2661ceSRobert Watson 		return (error);
921db2661ceSRobert Watson 
922db2661ceSRobert Watson 	return (0);
923db2661ceSRobert Watson }
924db2661ceSRobert Watson 
925db2661ceSRobert Watson static int
926db2661ceSRobert Watson mac_lomac_internalize_label(struct label *label, char *element_name,
927db2661ceSRobert Watson     char *element_data, int *claimed)
928db2661ceSRobert Watson {
929db2661ceSRobert Watson 	struct mac_lomac *mac_lomac, mac_lomac_temp;
930db2661ceSRobert Watson 	int error;
931db2661ceSRobert Watson 
932db2661ceSRobert Watson 	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
933db2661ceSRobert Watson 		return (0);
934db2661ceSRobert Watson 
935db2661ceSRobert Watson 	(*claimed)++;
936db2661ceSRobert Watson 
937db2661ceSRobert Watson 	error = mac_lomac_parse(&mac_lomac_temp, element_data);
938db2661ceSRobert Watson 	if (error)
939db2661ceSRobert Watson 		return (error);
940db2661ceSRobert Watson 
941db2661ceSRobert Watson 	mac_lomac = SLOT(label);
942db2661ceSRobert Watson 	*mac_lomac = mac_lomac_temp;
943db2661ceSRobert Watson 
944db2661ceSRobert Watson 	return (0);
945db2661ceSRobert Watson }
946db2661ceSRobert Watson 
947db2661ceSRobert Watson static void
948db2661ceSRobert Watson mac_lomac_copy_label(struct label *src, struct label *dest)
949db2661ceSRobert Watson {
950db2661ceSRobert Watson 
951db2661ceSRobert Watson 	*SLOT(dest) = *SLOT(src);
952db2661ceSRobert Watson }
953db2661ceSRobert Watson 
954db2661ceSRobert Watson /*
955db2661ceSRobert Watson  * Labeling event operations: file system objects, and things that look
956db2661ceSRobert Watson  * a lot like file system objects.
957db2661ceSRobert Watson  */
958db2661ceSRobert Watson static void
959db2661ceSRobert Watson mac_lomac_create_devfs_device(dev_t dev, struct devfs_dirent *devfs_dirent,
960db2661ceSRobert Watson     struct label *label)
961db2661ceSRobert Watson {
962db2661ceSRobert Watson 	struct mac_lomac *mac_lomac;
963db2661ceSRobert Watson 	int lomac_type;
964db2661ceSRobert Watson 
965db2661ceSRobert Watson 	mac_lomac = SLOT(label);
966db2661ceSRobert Watson 	if (strcmp(dev->si_name, "null") == 0 ||
967db2661ceSRobert Watson 	    strcmp(dev->si_name, "zero") == 0 ||
968db2661ceSRobert Watson 	    strcmp(dev->si_name, "random") == 0 ||
969db2661ceSRobert Watson 	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 ||
970db2661ceSRobert Watson 	    strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0)
971db2661ceSRobert Watson 		lomac_type = MAC_LOMAC_TYPE_EQUAL;
972db2661ceSRobert Watson 	else if (ptys_equal &&
973db2661ceSRobert Watson 	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
974db2661ceSRobert Watson 	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
975db2661ceSRobert Watson 		lomac_type = MAC_LOMAC_TYPE_EQUAL;
976db2661ceSRobert Watson 	else
977db2661ceSRobert Watson 		lomac_type = MAC_LOMAC_TYPE_HIGH;
978db2661ceSRobert Watson 	mac_lomac_set_single(mac_lomac, lomac_type, 0);
979db2661ceSRobert Watson }
980db2661ceSRobert Watson 
981db2661ceSRobert Watson static void
982db2661ceSRobert Watson mac_lomac_create_devfs_directory(char *dirname, int dirnamelen,
983db2661ceSRobert Watson     struct devfs_dirent *devfs_dirent, struct label *label)
984db2661ceSRobert Watson {
985db2661ceSRobert Watson 	struct mac_lomac *mac_lomac;
986db2661ceSRobert Watson 
987db2661ceSRobert Watson 	mac_lomac = SLOT(label);
988db2661ceSRobert Watson 	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
989db2661ceSRobert Watson }
990db2661ceSRobert Watson 
991db2661ceSRobert Watson static void
992db2661ceSRobert Watson mac_lomac_create_devfs_symlink(struct ucred *cred, struct devfs_dirent *dd,
993db2661ceSRobert Watson     struct label *ddlabel, struct devfs_dirent *de, struct label *delabel)
994db2661ceSRobert Watson {
995db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
996db2661ceSRobert Watson 
997db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
998db2661ceSRobert Watson 	dest = SLOT(delabel);
999db2661ceSRobert Watson 
1000db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1001db2661ceSRobert Watson }
1002db2661ceSRobert Watson 
1003db2661ceSRobert Watson static void
1004db2661ceSRobert Watson mac_lomac_create_mount(struct ucred *cred, struct mount *mp,
1005db2661ceSRobert Watson     struct label *mntlabel, struct label *fslabel)
1006db2661ceSRobert Watson {
1007db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1008db2661ceSRobert Watson 
1009db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
1010db2661ceSRobert Watson 	dest = SLOT(mntlabel);
1011db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1012db2661ceSRobert Watson 	dest = SLOT(fslabel);
1013db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1014db2661ceSRobert Watson }
1015db2661ceSRobert Watson 
1016db2661ceSRobert Watson static void
1017db2661ceSRobert Watson mac_lomac_create_root_mount(struct ucred *cred, struct mount *mp,
1018db2661ceSRobert Watson     struct label *mntlabel, struct label *fslabel)
1019db2661ceSRobert Watson {
1020db2661ceSRobert Watson 	struct mac_lomac *mac_lomac;
1021db2661ceSRobert Watson 
1022db2661ceSRobert Watson 	/* Always mount root as high integrity. */
1023db2661ceSRobert Watson 	mac_lomac = SLOT(fslabel);
1024db2661ceSRobert Watson 	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
1025db2661ceSRobert Watson 	mac_lomac = SLOT(mntlabel);
1026db2661ceSRobert Watson 	mac_lomac_set_single(mac_lomac, MAC_LOMAC_TYPE_HIGH, 0);
1027db2661ceSRobert Watson }
1028db2661ceSRobert Watson 
1029db2661ceSRobert Watson static void
1030db2661ceSRobert Watson mac_lomac_relabel_vnode(struct ucred *cred, struct vnode *vp,
1031db2661ceSRobert Watson     struct label *vnodelabel, struct label *label)
1032db2661ceSRobert Watson {
1033db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1034db2661ceSRobert Watson 
1035db2661ceSRobert Watson 	source = SLOT(label);
1036db2661ceSRobert Watson 	dest = SLOT(vnodelabel);
1037db2661ceSRobert Watson 
1038db2661ceSRobert Watson 	try_relabel(source, dest);
1039db2661ceSRobert Watson }
1040db2661ceSRobert Watson 
1041db2661ceSRobert Watson static void
1042db2661ceSRobert Watson mac_lomac_update_devfsdirent(struct devfs_dirent *devfs_dirent,
1043db2661ceSRobert Watson     struct label *direntlabel, struct vnode *vp, struct label *vnodelabel)
1044db2661ceSRobert Watson {
1045db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1046db2661ceSRobert Watson 
1047db2661ceSRobert Watson 	source = SLOT(vnodelabel);
1048db2661ceSRobert Watson 	dest = SLOT(direntlabel);
1049db2661ceSRobert Watson 
1050db2661ceSRobert Watson 	mac_lomac_copy(source, dest);
1051db2661ceSRobert Watson }
1052db2661ceSRobert Watson 
1053db2661ceSRobert Watson static void
1054db2661ceSRobert Watson mac_lomac_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
1055db2661ceSRobert Watson     struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
1056db2661ceSRobert Watson     struct label *vlabel)
1057db2661ceSRobert Watson {
1058db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1059db2661ceSRobert Watson 
1060db2661ceSRobert Watson 	source = SLOT(delabel);
1061db2661ceSRobert Watson 	dest = SLOT(vlabel);
1062db2661ceSRobert Watson 
1063db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1064db2661ceSRobert Watson }
1065db2661ceSRobert Watson 
1066db2661ceSRobert Watson static int
1067db2661ceSRobert Watson mac_lomac_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
1068db2661ceSRobert Watson     struct vnode *vp, struct label *vlabel)
1069db2661ceSRobert Watson {
1070db2661ceSRobert Watson 	struct mac_lomac temp, *source, *dest;
1071db2661ceSRobert Watson 	size_t buflen;
1072db2661ceSRobert Watson 	int error;
1073db2661ceSRobert Watson 
1074db2661ceSRobert Watson 	source = SLOT(fslabel);
1075db2661ceSRobert Watson 	dest = SLOT(vlabel);
1076db2661ceSRobert Watson 
1077db2661ceSRobert Watson 	buflen = sizeof(temp);
1078db2661ceSRobert Watson 	bzero(&temp, buflen);
1079db2661ceSRobert Watson 
1080db2661ceSRobert Watson 	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1081db2661ceSRobert Watson 	    MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&temp, curthread);
1082db2661ceSRobert Watson 	if (error == ENOATTR || error == EOPNOTSUPP) {
1083db2661ceSRobert Watson 		/* Fall back to the fslabel. */
1084db2661ceSRobert Watson 		mac_lomac_copy_single(source, dest);
1085db2661ceSRobert Watson 		return (0);
1086db2661ceSRobert Watson 	} else if (error)
1087db2661ceSRobert Watson 		return (error);
1088db2661ceSRobert Watson 
1089db2661ceSRobert Watson 	if (buflen != sizeof(temp)) {
1090db2661ceSRobert Watson 		if (buflen != sizeof(temp) - sizeof(temp.ml_auxsingle)) {
1091db2661ceSRobert Watson 			printf("mac_lomac_associate_vnode_extattr: bad size %d\n",
1092db2661ceSRobert Watson 			    buflen);
1093db2661ceSRobert Watson 			return (EPERM);
1094db2661ceSRobert Watson 		}
1095db2661ceSRobert Watson 		bzero(&temp.ml_auxsingle, sizeof(temp.ml_auxsingle));
1096db2661ceSRobert Watson 		buflen = sizeof(temp);
1097db2661ceSRobert Watson 		(void)vn_extattr_set(vp, IO_NODELOCKED,
1098db2661ceSRobert Watson 		    MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
1099db2661ceSRobert Watson 		    buflen, (char *)&temp, curthread);
1100db2661ceSRobert Watson 	}
1101db2661ceSRobert Watson 	if (mac_lomac_valid(&temp) != 0) {
1102db2661ceSRobert Watson 		printf("mac_lomac_associate_vnode_extattr: invalid\n");
1103db2661ceSRobert Watson 		return (EPERM);
1104db2661ceSRobert Watson 	}
1105db2661ceSRobert Watson 	if ((temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) != MAC_LOMAC_FLAG_SINGLE) {
1106db2661ceSRobert Watson 		printf("mac_lomac_associate_vnode_extattr: not single\n");
1107db2661ceSRobert Watson 		return (EPERM);
1108db2661ceSRobert Watson 	}
1109db2661ceSRobert Watson 
1110db2661ceSRobert Watson 	mac_lomac_copy_single(&temp, dest);
1111db2661ceSRobert Watson 	return (0);
1112db2661ceSRobert Watson }
1113db2661ceSRobert Watson 
1114db2661ceSRobert Watson static void
1115db2661ceSRobert Watson mac_lomac_associate_vnode_singlelabel(struct mount *mp,
1116db2661ceSRobert Watson     struct label *fslabel, struct vnode *vp, struct label *vlabel)
1117db2661ceSRobert Watson {
1118db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1119db2661ceSRobert Watson 
1120db2661ceSRobert Watson 	source = SLOT(fslabel);
1121db2661ceSRobert Watson 	dest = SLOT(vlabel);
1122db2661ceSRobert Watson 
1123db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1124db2661ceSRobert Watson }
1125db2661ceSRobert Watson 
1126db2661ceSRobert Watson static int
1127db2661ceSRobert Watson mac_lomac_create_vnode_extattr(struct ucred *cred, struct mount *mp,
1128db2661ceSRobert Watson     struct label *fslabel, struct vnode *dvp, struct label *dlabel,
1129db2661ceSRobert Watson     struct vnode *vp, struct label *vlabel, struct componentname *cnp)
1130db2661ceSRobert Watson {
1131db2661ceSRobert Watson 	struct mac_lomac *source, *dest, *dir, temp;
1132db2661ceSRobert Watson 	size_t buflen;
1133db2661ceSRobert Watson 	int error;
1134db2661ceSRobert Watson 
1135db2661ceSRobert Watson 	buflen = sizeof(temp);
1136db2661ceSRobert Watson 	bzero(&temp, buflen);
1137db2661ceSRobert Watson 
1138db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
1139db2661ceSRobert Watson 	dest = SLOT(vlabel);
1140db2661ceSRobert Watson 	dir = SLOT(dlabel);
1141db2661ceSRobert Watson 	if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
1142db2661ceSRobert Watson 		mac_lomac_copy_auxsingle(dir, &temp);
1143db2661ceSRobert Watson 		mac_lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
1144db2661ceSRobert Watson 		    dir->ml_auxsingle.mle_grade);
1145db2661ceSRobert Watson 	} else {
1146db2661ceSRobert Watson 		mac_lomac_copy_single(source, &temp);
1147db2661ceSRobert Watson 	}
1148db2661ceSRobert Watson 
1149db2661ceSRobert Watson 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1150db2661ceSRobert Watson 	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1151db2661ceSRobert Watson 	if (error == 0)
1152db2661ceSRobert Watson 		mac_lomac_copy(&temp, dest);
1153db2661ceSRobert Watson 	return (error);
1154db2661ceSRobert Watson }
1155db2661ceSRobert Watson 
1156db2661ceSRobert Watson static int
1157db2661ceSRobert Watson mac_lomac_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
1158db2661ceSRobert Watson     struct label *vlabel, struct label *intlabel)
1159db2661ceSRobert Watson {
1160db2661ceSRobert Watson 	struct mac_lomac *source, temp;
1161db2661ceSRobert Watson 	size_t buflen;
1162db2661ceSRobert Watson 	int error;
1163db2661ceSRobert Watson 
1164db2661ceSRobert Watson 	buflen = sizeof(temp);
1165db2661ceSRobert Watson 	bzero(&temp, buflen);
1166db2661ceSRobert Watson 
1167db2661ceSRobert Watson 	source = SLOT(intlabel);
1168db2661ceSRobert Watson 	if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1169db2661ceSRobert Watson 		return (0);
1170db2661ceSRobert Watson 
1171db2661ceSRobert Watson 	mac_lomac_copy_single(source, &temp);
1172db2661ceSRobert Watson 	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
1173db2661ceSRobert Watson 	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
1174db2661ceSRobert Watson 	return (error);
1175db2661ceSRobert Watson }
1176db2661ceSRobert Watson 
1177db2661ceSRobert Watson /*
1178db2661ceSRobert Watson  * Labeling event operations: IPC object.
1179db2661ceSRobert Watson  */
1180db2661ceSRobert Watson static void
1181db2661ceSRobert Watson mac_lomac_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
1182db2661ceSRobert Watson     struct mbuf *m, struct label *mbuflabel)
1183db2661ceSRobert Watson {
1184db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1185db2661ceSRobert Watson 
1186db2661ceSRobert Watson 	source = SLOT(socketlabel);
1187db2661ceSRobert Watson 	dest = SLOT(mbuflabel);
1188db2661ceSRobert Watson 
1189db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1190db2661ceSRobert Watson }
1191db2661ceSRobert Watson 
1192db2661ceSRobert Watson static void
1193db2661ceSRobert Watson mac_lomac_create_socket(struct ucred *cred, struct socket *socket,
1194db2661ceSRobert Watson     struct label *socketlabel)
1195db2661ceSRobert Watson {
1196db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1197db2661ceSRobert Watson 
1198db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
1199db2661ceSRobert Watson 	dest = SLOT(socketlabel);
1200db2661ceSRobert Watson 
1201db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1202db2661ceSRobert Watson }
1203db2661ceSRobert Watson 
1204db2661ceSRobert Watson static void
1205db2661ceSRobert Watson mac_lomac_create_pipe(struct ucred *cred, struct pipe *pipe,
1206db2661ceSRobert Watson     struct label *pipelabel)
1207db2661ceSRobert Watson {
1208db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1209db2661ceSRobert Watson 
1210db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
1211db2661ceSRobert Watson 	dest = SLOT(pipelabel);
1212db2661ceSRobert Watson 
1213db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1214db2661ceSRobert Watson }
1215db2661ceSRobert Watson 
1216db2661ceSRobert Watson static void
1217db2661ceSRobert Watson mac_lomac_create_socket_from_socket(struct socket *oldsocket,
1218db2661ceSRobert Watson     struct label *oldsocketlabel, struct socket *newsocket,
1219db2661ceSRobert Watson     struct label *newsocketlabel)
1220db2661ceSRobert Watson {
1221db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1222db2661ceSRobert Watson 
1223db2661ceSRobert Watson 	source = SLOT(oldsocketlabel);
1224db2661ceSRobert Watson 	dest = SLOT(newsocketlabel);
1225db2661ceSRobert Watson 
1226db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1227db2661ceSRobert Watson }
1228db2661ceSRobert Watson 
1229db2661ceSRobert Watson static void
1230db2661ceSRobert Watson mac_lomac_relabel_socket(struct ucred *cred, struct socket *socket,
1231db2661ceSRobert Watson     struct label *socketlabel, struct label *newlabel)
1232db2661ceSRobert Watson {
1233db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1234db2661ceSRobert Watson 
1235db2661ceSRobert Watson 	source = SLOT(newlabel);
1236db2661ceSRobert Watson 	dest = SLOT(socketlabel);
1237db2661ceSRobert Watson 
1238db2661ceSRobert Watson 	try_relabel(source, dest);
1239db2661ceSRobert Watson }
1240db2661ceSRobert Watson 
1241db2661ceSRobert Watson static void
1242db2661ceSRobert Watson mac_lomac_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1243db2661ceSRobert Watson     struct label *pipelabel, struct label *newlabel)
1244db2661ceSRobert Watson {
1245db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1246db2661ceSRobert Watson 
1247db2661ceSRobert Watson 	source = SLOT(newlabel);
1248db2661ceSRobert Watson 	dest = SLOT(pipelabel);
1249db2661ceSRobert Watson 
1250db2661ceSRobert Watson 	try_relabel(source, dest);
1251db2661ceSRobert Watson }
1252db2661ceSRobert Watson 
1253db2661ceSRobert Watson static void
1254db2661ceSRobert Watson mac_lomac_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1255db2661ceSRobert Watson     struct socket *socket, struct label *socketpeerlabel)
1256db2661ceSRobert Watson {
1257db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1258db2661ceSRobert Watson 
1259db2661ceSRobert Watson 	source = SLOT(mbuflabel);
1260db2661ceSRobert Watson 	dest = SLOT(socketpeerlabel);
1261db2661ceSRobert Watson 
1262db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1263db2661ceSRobert Watson }
1264db2661ceSRobert Watson 
1265db2661ceSRobert Watson /*
1266db2661ceSRobert Watson  * Labeling event operations: network objects.
1267db2661ceSRobert Watson  */
1268db2661ceSRobert Watson static void
1269db2661ceSRobert Watson mac_lomac_set_socket_peer_from_socket(struct socket *oldsocket,
1270db2661ceSRobert Watson     struct label *oldsocketlabel, struct socket *newsocket,
1271db2661ceSRobert Watson     struct label *newsocketpeerlabel)
1272db2661ceSRobert Watson {
1273db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1274db2661ceSRobert Watson 
1275db2661ceSRobert Watson 	source = SLOT(oldsocketlabel);
1276db2661ceSRobert Watson 	dest = SLOT(newsocketpeerlabel);
1277db2661ceSRobert Watson 
1278db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1279db2661ceSRobert Watson }
1280db2661ceSRobert Watson 
1281db2661ceSRobert Watson static void
1282db2661ceSRobert Watson mac_lomac_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1283db2661ceSRobert Watson     struct label *bpflabel)
1284db2661ceSRobert Watson {
1285db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1286db2661ceSRobert Watson 
1287db2661ceSRobert Watson 	source = SLOT(&cred->cr_label);
1288db2661ceSRobert Watson 	dest = SLOT(bpflabel);
1289db2661ceSRobert Watson 
1290db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1291db2661ceSRobert Watson }
1292db2661ceSRobert Watson 
1293db2661ceSRobert Watson static void
1294db2661ceSRobert Watson mac_lomac_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1295db2661ceSRobert Watson {
1296db2661ceSRobert Watson 	char tifname[IFNAMSIZ], ifname[IFNAMSIZ], *p, *q;
1297db2661ceSRobert Watson 	char tiflist[sizeof(trusted_interfaces)];
1298db2661ceSRobert Watson 	struct mac_lomac *dest;
1299db2661ceSRobert Watson 	int len, grade;
1300db2661ceSRobert Watson 
1301db2661ceSRobert Watson 	dest = SLOT(ifnetlabel);
1302db2661ceSRobert Watson 
1303db2661ceSRobert Watson 	if (ifnet->if_type == IFT_LOOP) {
1304db2661ceSRobert Watson 		grade = MAC_LOMAC_TYPE_EQUAL;
1305db2661ceSRobert Watson 		goto set;
1306db2661ceSRobert Watson 	}
1307db2661ceSRobert Watson 
1308db2661ceSRobert Watson 	if (trust_all_interfaces) {
1309db2661ceSRobert Watson 		grade = MAC_LOMAC_TYPE_HIGH;
1310db2661ceSRobert Watson 		goto set;
1311db2661ceSRobert Watson 	}
1312db2661ceSRobert Watson 
1313db2661ceSRobert Watson 	grade = MAC_LOMAC_TYPE_LOW;
1314db2661ceSRobert Watson 
1315db2661ceSRobert Watson 	if (trusted_interfaces[0] == '\0' ||
1316db2661ceSRobert Watson 	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1317db2661ceSRobert Watson 		goto set;
1318db2661ceSRobert Watson 
1319db2661ceSRobert Watson 	bzero(tiflist, sizeof(tiflist));
1320db2661ceSRobert Watson 	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1321db2661ceSRobert Watson 		if(*p != ' ' && *p != '\t')
1322db2661ceSRobert Watson 			*q = *p;
1323db2661ceSRobert Watson 
1324db2661ceSRobert Watson 	snprintf(ifname, IFNAMSIZ, "%s%d", ifnet->if_name, ifnet->if_unit);
1325db2661ceSRobert Watson 
1326db2661ceSRobert Watson 	for (p = q = tiflist;; p++) {
1327db2661ceSRobert Watson 		if (*p == ',' || *p == '\0') {
1328db2661ceSRobert Watson 			len = p - q;
1329db2661ceSRobert Watson 			if (len < IFNAMSIZ) {
1330db2661ceSRobert Watson 				bzero(tifname, sizeof(tifname));
1331db2661ceSRobert Watson 				bcopy(q, tifname, len);
1332db2661ceSRobert Watson 				if (strcmp(tifname, ifname) == 0) {
1333db2661ceSRobert Watson 					grade = MAC_LOMAC_TYPE_HIGH;
1334db2661ceSRobert Watson 					break;
1335db2661ceSRobert Watson 				}
1336db2661ceSRobert Watson 			}
1337db2661ceSRobert Watson 			else {
1338db2661ceSRobert Watson 				*p = '\0';
1339db2661ceSRobert Watson 				printf("MAC/LOMAC warning: interface name "
1340db2661ceSRobert Watson 				    "\"%s\" is too long (must be < %d)\n",
1341db2661ceSRobert Watson 				    q, IFNAMSIZ);
1342db2661ceSRobert Watson 			}
1343db2661ceSRobert Watson 			if (*p == '\0')
1344db2661ceSRobert Watson 				break;
1345db2661ceSRobert Watson 			q = p + 1;
1346db2661ceSRobert Watson 		}
1347db2661ceSRobert Watson 	}
1348db2661ceSRobert Watson set:
1349db2661ceSRobert Watson 	mac_lomac_set_single(dest, grade, 0);
1350db2661ceSRobert Watson 	mac_lomac_set_range(dest, grade, 0, grade, 0);
1351db2661ceSRobert Watson }
1352db2661ceSRobert Watson 
1353db2661ceSRobert Watson static void
1354db2661ceSRobert Watson mac_lomac_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1355db2661ceSRobert Watson     struct ipq *ipq, struct label *ipqlabel)
1356db2661ceSRobert Watson {
1357db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1358db2661ceSRobert Watson 
1359db2661ceSRobert Watson 	source = SLOT(fragmentlabel);
1360db2661ceSRobert Watson 	dest = SLOT(ipqlabel);
1361db2661ceSRobert Watson 
1362db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1363db2661ceSRobert Watson }
1364db2661ceSRobert Watson 
1365db2661ceSRobert Watson static void
1366db2661ceSRobert Watson mac_lomac_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1367db2661ceSRobert Watson     struct mbuf *datagram, struct label *datagramlabel)
1368db2661ceSRobert Watson {
1369db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1370db2661ceSRobert Watson 
1371db2661ceSRobert Watson 	source = SLOT(ipqlabel);
1372db2661ceSRobert Watson 	dest = SLOT(datagramlabel);
1373db2661ceSRobert Watson 
1374db2661ceSRobert Watson 	/* Just use the head, since we require them all to match. */
1375db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1376db2661ceSRobert Watson }
1377db2661ceSRobert Watson 
1378db2661ceSRobert Watson static void
1379db2661ceSRobert Watson mac_lomac_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1380db2661ceSRobert Watson     struct mbuf *fragment, struct label *fragmentlabel)
1381db2661ceSRobert Watson {
1382db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1383db2661ceSRobert Watson 
1384db2661ceSRobert Watson 	source = SLOT(datagramlabel);
1385db2661ceSRobert Watson 	dest = SLOT(fragmentlabel);
1386db2661ceSRobert Watson 
1387db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1388db2661ceSRobert Watson }
1389db2661ceSRobert Watson 
1390db2661ceSRobert Watson static void
1391db2661ceSRobert Watson mac_lomac_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1392db2661ceSRobert Watson     struct label *oldmbuflabel, struct mbuf *newmbuf,
1393db2661ceSRobert Watson     struct label *newmbuflabel)
1394db2661ceSRobert Watson {
1395db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1396db2661ceSRobert Watson 
1397db2661ceSRobert Watson 	source = SLOT(oldmbuflabel);
1398db2661ceSRobert Watson 	dest = SLOT(newmbuflabel);
1399db2661ceSRobert Watson 
1400db2661ceSRobert Watson 	/*
1401db2661ceSRobert Watson 	 * Because the source mbuf may not yet have been "created",
1402db2661ceSRobert Watson 	 * just initialized, we do a conditional copy.  Since we don't
1403db2661ceSRobert Watson 	 * allow mbufs to have ranges, do a KASSERT to make sure that
1404db2661ceSRobert Watson 	 * doesn't happen.
1405db2661ceSRobert Watson 	 */
1406db2661ceSRobert Watson 	KASSERT((source->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0,
1407db2661ceSRobert Watson 	    ("mac_lomac_create_mbuf_from_mbuf: source mbuf has range"));
1408db2661ceSRobert Watson 	mac_lomac_copy(source, dest);
1409db2661ceSRobert Watson }
1410db2661ceSRobert Watson 
1411db2661ceSRobert Watson static void
1412db2661ceSRobert Watson mac_lomac_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1413db2661ceSRobert Watson     struct mbuf *mbuf, struct label *mbuflabel)
1414db2661ceSRobert Watson {
1415db2661ceSRobert Watson 	struct mac_lomac *dest;
1416db2661ceSRobert Watson 
1417db2661ceSRobert Watson 	dest = SLOT(mbuflabel);
1418db2661ceSRobert Watson 
1419db2661ceSRobert Watson 	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1420db2661ceSRobert Watson }
1421db2661ceSRobert Watson 
1422db2661ceSRobert Watson static void
1423db2661ceSRobert Watson mac_lomac_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1424db2661ceSRobert Watson     struct mbuf *mbuf, struct label *mbuflabel)
1425db2661ceSRobert Watson {
1426db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1427db2661ceSRobert Watson 
1428db2661ceSRobert Watson 	source = SLOT(bpflabel);
1429db2661ceSRobert Watson 	dest = SLOT(mbuflabel);
1430db2661ceSRobert Watson 
1431db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1432db2661ceSRobert Watson }
1433db2661ceSRobert Watson 
1434db2661ceSRobert Watson static void
1435db2661ceSRobert Watson mac_lomac_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1436db2661ceSRobert Watson     struct mbuf *m, struct label *mbuflabel)
1437db2661ceSRobert Watson {
1438db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1439db2661ceSRobert Watson 
1440db2661ceSRobert Watson 	source = SLOT(ifnetlabel);
1441db2661ceSRobert Watson 	dest = SLOT(mbuflabel);
1442db2661ceSRobert Watson 
1443db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1444db2661ceSRobert Watson }
1445db2661ceSRobert Watson 
1446db2661ceSRobert Watson static void
1447db2661ceSRobert Watson mac_lomac_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1448db2661ceSRobert Watson     struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1449db2661ceSRobert Watson     struct mbuf *newmbuf, struct label *newmbuflabel)
1450db2661ceSRobert Watson {
1451db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1452db2661ceSRobert Watson 
1453db2661ceSRobert Watson 	source = SLOT(oldmbuflabel);
1454db2661ceSRobert Watson 	dest = SLOT(newmbuflabel);
1455db2661ceSRobert Watson 
1456db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1457db2661ceSRobert Watson }
1458db2661ceSRobert Watson 
1459db2661ceSRobert Watson static void
1460db2661ceSRobert Watson mac_lomac_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1461db2661ceSRobert Watson     struct mbuf *newmbuf, struct label *newmbuflabel)
1462db2661ceSRobert Watson {
1463db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1464db2661ceSRobert Watson 
1465db2661ceSRobert Watson 	source = SLOT(oldmbuflabel);
1466db2661ceSRobert Watson 	dest = SLOT(newmbuflabel);
1467db2661ceSRobert Watson 
1468db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1469db2661ceSRobert Watson }
1470db2661ceSRobert Watson 
1471db2661ceSRobert Watson static int
1472db2661ceSRobert Watson mac_lomac_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1473db2661ceSRobert Watson     struct ipq *ipq, struct label *ipqlabel)
1474db2661ceSRobert Watson {
1475db2661ceSRobert Watson 	struct mac_lomac *a, *b;
1476db2661ceSRobert Watson 
1477db2661ceSRobert Watson 	a = SLOT(ipqlabel);
1478db2661ceSRobert Watson 	b = SLOT(fragmentlabel);
1479db2661ceSRobert Watson 
1480db2661ceSRobert Watson 	return (mac_lomac_equal_single(a, b));
1481db2661ceSRobert Watson }
1482db2661ceSRobert Watson 
1483db2661ceSRobert Watson static void
1484db2661ceSRobert Watson mac_lomac_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1485db2661ceSRobert Watson     struct label *ifnetlabel, struct label *newlabel)
1486db2661ceSRobert Watson {
1487db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1488db2661ceSRobert Watson 
1489db2661ceSRobert Watson 	source = SLOT(newlabel);
1490db2661ceSRobert Watson 	dest = SLOT(ifnetlabel);
1491db2661ceSRobert Watson 
1492db2661ceSRobert Watson 	try_relabel(source, dest);
1493db2661ceSRobert Watson }
1494db2661ceSRobert Watson 
1495db2661ceSRobert Watson static void
1496db2661ceSRobert Watson mac_lomac_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1497db2661ceSRobert Watson     struct ipq *ipq, struct label *ipqlabel)
1498db2661ceSRobert Watson {
1499db2661ceSRobert Watson 
1500db2661ceSRobert Watson 	/* NOOP: we only accept matching labels, so no need to update */
1501db2661ceSRobert Watson }
1502db2661ceSRobert Watson 
1503db2661ceSRobert Watson /*
1504db2661ceSRobert Watson  * Labeling event operations: processes.
1505db2661ceSRobert Watson  */
1506db2661ceSRobert Watson static void
1507db2661ceSRobert Watson mac_lomac_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1508db2661ceSRobert Watson {
1509db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1510db2661ceSRobert Watson 
1511db2661ceSRobert Watson 	source = SLOT(&cred_parent->cr_label);
1512db2661ceSRobert Watson 	dest = SLOT(&cred_child->cr_label);
1513db2661ceSRobert Watson 
1514db2661ceSRobert Watson 	mac_lomac_copy_single(source, dest);
1515db2661ceSRobert Watson 	mac_lomac_copy_range(source, dest);
1516db2661ceSRobert Watson }
1517db2661ceSRobert Watson 
1518db2661ceSRobert Watson static void
1519db2661ceSRobert Watson mac_lomac_execve_transition(struct ucred *old, struct ucred *new,
1520db2661ceSRobert Watson     struct vnode *vp, struct label *vnodelabel,
1521db2661ceSRobert Watson     struct label *interpvnodelabel, struct image_params *imgp,
1522db2661ceSRobert Watson     struct label *execlabel)
1523db2661ceSRobert Watson {
1524db2661ceSRobert Watson 	struct mac_lomac *source, *dest, *obj, *robj;
1525db2661ceSRobert Watson 
1526db2661ceSRobert Watson 	source = SLOT(&old->cr_label);
1527db2661ceSRobert Watson 	dest = SLOT(&new->cr_label);
1528db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
1529db2661ceSRobert Watson 	robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1530db2661ceSRobert Watson 
1531db2661ceSRobert Watson 	mac_lomac_copy(source, dest);
1532db2661ceSRobert Watson 	/*
1533db2661ceSRobert Watson 	 * If there's an auxiliary label on the real object, respect it
1534db2661ceSRobert Watson 	 * and assume that this level should be assumed immediately if
1535db2661ceSRobert Watson 	 * a higher level is currently in place.
1536db2661ceSRobert Watson 	 */
1537db2661ceSRobert Watson 	if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1538db2661ceSRobert Watson 	    !mac_lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
1539db2661ceSRobert Watson 	    && mac_lomac_auxsingle_in_range(robj, dest))
1540db2661ceSRobert Watson 		mac_lomac_set_single(dest, robj->ml_auxsingle.mle_type,
1541db2661ceSRobert Watson 		    robj->ml_auxsingle.mle_grade);
1542db2661ceSRobert Watson 	/*
1543db2661ceSRobert Watson 	 * Restructuring to use the execve transitioning mechanism
1544db2661ceSRobert Watson 	 * instead of the normal demotion mechanism here would be
1545db2661ceSRobert Watson 	 * difficult, so just copy the label over and perform standard
1546db2661ceSRobert Watson 	 * demotion.  This is also non-optimal because it will result
1547db2661ceSRobert Watson 	 * in the intermediate label "new" being created and immediately
1548db2661ceSRobert Watson 	 * recycled.
1549db2661ceSRobert Watson 	 */
1550db2661ceSRobert Watson 	if (mac_lomac_enabled && revocation_enabled &&
1551db2661ceSRobert Watson 	    !mac_lomac_dominate_single(obj, source))
1552db2661ceSRobert Watson 		(void)maybe_demote(source, obj, "executing", "file", vp);
1553db2661ceSRobert Watson }
1554db2661ceSRobert Watson 
1555db2661ceSRobert Watson static int
1556db2661ceSRobert Watson mac_lomac_execve_will_transition(struct ucred *old, struct vnode *vp,
1557db2661ceSRobert Watson     struct label *vnodelabel, struct label *interpvnodelabel,
1558db2661ceSRobert Watson     struct image_params *imgp, struct label *execlabel)
1559db2661ceSRobert Watson {
1560db2661ceSRobert Watson 	struct mac_lomac *subj, *obj, *robj;
1561db2661ceSRobert Watson 
1562db2661ceSRobert Watson 	if (!mac_lomac_enabled || !revocation_enabled)
1563db2661ceSRobert Watson 		return (0);
1564db2661ceSRobert Watson 
1565db2661ceSRobert Watson 	subj = SLOT(&old->cr_label);
1566db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
1567db2661ceSRobert Watson 	robj = interpvnodelabel != NULL ? SLOT(interpvnodelabel) : obj;
1568db2661ceSRobert Watson 
1569db2661ceSRobert Watson 	return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
1570db2661ceSRobert Watson 	    !mac_lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
1571db2661ceSRobert Watson 	    && mac_lomac_auxsingle_in_range(robj, subj)) ||
1572db2661ceSRobert Watson 	    !mac_lomac_dominate_single(obj, subj));
1573db2661ceSRobert Watson }
1574db2661ceSRobert Watson 
1575db2661ceSRobert Watson static void
1576db2661ceSRobert Watson mac_lomac_create_proc0(struct ucred *cred)
1577db2661ceSRobert Watson {
1578db2661ceSRobert Watson 	struct mac_lomac *dest;
1579db2661ceSRobert Watson 
1580db2661ceSRobert Watson 	dest = SLOT(&cred->cr_label);
1581db2661ceSRobert Watson 
1582db2661ceSRobert Watson 	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1583db2661ceSRobert Watson 	mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1584db2661ceSRobert Watson 	    0);
1585db2661ceSRobert Watson }
1586db2661ceSRobert Watson 
1587db2661ceSRobert Watson static void
1588db2661ceSRobert Watson mac_lomac_create_proc1(struct ucred *cred)
1589db2661ceSRobert Watson {
1590db2661ceSRobert Watson 	struct mac_lomac *dest;
1591db2661ceSRobert Watson 
1592db2661ceSRobert Watson 	dest = SLOT(&cred->cr_label);
1593db2661ceSRobert Watson 
1594db2661ceSRobert Watson 	mac_lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
1595db2661ceSRobert Watson 	mac_lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH,
1596db2661ceSRobert Watson 	    0);
1597db2661ceSRobert Watson }
1598db2661ceSRobert Watson 
1599db2661ceSRobert Watson static void
1600db2661ceSRobert Watson mac_lomac_relabel_cred(struct ucred *cred, struct label *newlabel)
1601db2661ceSRobert Watson {
1602db2661ceSRobert Watson 	struct mac_lomac *source, *dest;
1603db2661ceSRobert Watson 
1604db2661ceSRobert Watson 	source = SLOT(newlabel);
1605db2661ceSRobert Watson 	dest = SLOT(&cred->cr_label);
1606db2661ceSRobert Watson 
1607db2661ceSRobert Watson 	try_relabel(source, dest);
1608db2661ceSRobert Watson }
1609db2661ceSRobert Watson 
1610db2661ceSRobert Watson /*
1611db2661ceSRobert Watson  * Access control checks.
1612db2661ceSRobert Watson  */
1613db2661ceSRobert Watson static int
1614db2661ceSRobert Watson mac_lomac_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1615db2661ceSRobert Watson     struct ifnet *ifnet, struct label *ifnetlabel)
1616db2661ceSRobert Watson {
1617db2661ceSRobert Watson 	struct mac_lomac *a, *b;
1618db2661ceSRobert Watson 
1619db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1620db2661ceSRobert Watson 		return (0);
1621db2661ceSRobert Watson 
1622db2661ceSRobert Watson 	a = SLOT(bpflabel);
1623db2661ceSRobert Watson 	b = SLOT(ifnetlabel);
1624db2661ceSRobert Watson 
1625db2661ceSRobert Watson 	if (mac_lomac_equal_single(a, b))
1626db2661ceSRobert Watson 		return (0);
1627db2661ceSRobert Watson 	return (EACCES);
1628db2661ceSRobert Watson }
1629db2661ceSRobert Watson 
1630db2661ceSRobert Watson static int
1631db2661ceSRobert Watson mac_lomac_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1632db2661ceSRobert Watson {
1633db2661ceSRobert Watson 	struct mac_lomac *subj, *new;
1634db2661ceSRobert Watson 	int error;
1635db2661ceSRobert Watson 
1636db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1637db2661ceSRobert Watson 	new = SLOT(newlabel);
1638db2661ceSRobert Watson 
1639db2661ceSRobert Watson 	/*
1640db2661ceSRobert Watson 	 * If there is a LOMAC label update for the credential, it may
1641db2661ceSRobert Watson 	 * be an update of the single, range, or both.
1642db2661ceSRobert Watson 	 */
1643db2661ceSRobert Watson 	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1644db2661ceSRobert Watson 	if (error)
1645db2661ceSRobert Watson 		return (error);
1646db2661ceSRobert Watson 
1647db2661ceSRobert Watson 	/*
1648db2661ceSRobert Watson 	 * If the LOMAC label is to be changed, authorize as appropriate.
1649db2661ceSRobert Watson 	 */
1650db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1651db2661ceSRobert Watson 		/*
1652db2661ceSRobert Watson 		 * To change the LOMAC single label on a credential, the
1653db2661ceSRobert Watson 		 * new single label must be in the current range.
1654db2661ceSRobert Watson 		 */
1655db2661ceSRobert Watson 		if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE &&
1656db2661ceSRobert Watson 		    !mac_lomac_single_in_range(new, subj))
1657db2661ceSRobert Watson 			return (EPERM);
1658db2661ceSRobert Watson 
1659db2661ceSRobert Watson 		/*
1660db2661ceSRobert Watson 		 * To change the LOMAC range on a credential, the new
1661db2661ceSRobert Watson 		 * range label must be in the current range.
1662db2661ceSRobert Watson 		 */
1663db2661ceSRobert Watson 		if (new->ml_flags & MAC_LOMAC_FLAG_RANGE &&
1664db2661ceSRobert Watson 		    !mac_lomac_range_in_range(new, subj))
1665db2661ceSRobert Watson 			return (EPERM);
1666db2661ceSRobert Watson 
1667db2661ceSRobert Watson 		/*
1668db2661ceSRobert Watson 		 * To have EQUAL in any component of the new credential
1669db2661ceSRobert Watson 		 * LOMAC label, the subject must already have EQUAL in
1670db2661ceSRobert Watson 		 * their label.
1671db2661ceSRobert Watson 		 */
1672db2661ceSRobert Watson 		if (mac_lomac_contains_equal(new)) {
1673db2661ceSRobert Watson 			error = mac_lomac_subject_privileged(subj);
1674db2661ceSRobert Watson 			if (error)
1675db2661ceSRobert Watson 				return (error);
1676db2661ceSRobert Watson 		}
1677db2661ceSRobert Watson 
1678db2661ceSRobert Watson 		/*
1679db2661ceSRobert Watson 		 * XXXMAC: Additional consistency tests regarding the
1680db2661ceSRobert Watson 		 * single and range of the new label might be performed
1681db2661ceSRobert Watson 		 * here.
1682db2661ceSRobert Watson 		 */
1683db2661ceSRobert Watson 	}
1684db2661ceSRobert Watson 
1685db2661ceSRobert Watson 	return (0);
1686db2661ceSRobert Watson }
1687db2661ceSRobert Watson 
1688db2661ceSRobert Watson static int
1689db2661ceSRobert Watson mac_lomac_check_cred_visible(struct ucred *u1, struct ucred *u2)
1690db2661ceSRobert Watson {
1691db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1692db2661ceSRobert Watson 
1693db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1694db2661ceSRobert Watson 		return (0);
1695db2661ceSRobert Watson 
1696db2661ceSRobert Watson 	subj = SLOT(&u1->cr_label);
1697db2661ceSRobert Watson 	obj = SLOT(&u2->cr_label);
1698db2661ceSRobert Watson 
1699db2661ceSRobert Watson 	/* XXX: range */
1700db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
1701db2661ceSRobert Watson 		return (ESRCH);
1702db2661ceSRobert Watson 
1703db2661ceSRobert Watson 	return (0);
1704db2661ceSRobert Watson }
1705db2661ceSRobert Watson 
1706db2661ceSRobert Watson static int
1707db2661ceSRobert Watson mac_lomac_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1708db2661ceSRobert Watson     struct label *ifnetlabel, struct label *newlabel)
1709db2661ceSRobert Watson {
1710db2661ceSRobert Watson 	struct mac_lomac *subj, *new;
1711db2661ceSRobert Watson 	int error;
1712db2661ceSRobert Watson 
1713db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1714db2661ceSRobert Watson 	new = SLOT(newlabel);
1715db2661ceSRobert Watson 
1716db2661ceSRobert Watson 	/*
1717db2661ceSRobert Watson 	 * If there is a LOMAC label update for the interface, it may
1718db2661ceSRobert Watson 	 * be an update of the single, range, or both.
1719db2661ceSRobert Watson 	 */
1720db2661ceSRobert Watson 	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1721db2661ceSRobert Watson 	if (error)
1722db2661ceSRobert Watson 		return (error);
1723db2661ceSRobert Watson 
1724db2661ceSRobert Watson 	/*
1725db2661ceSRobert Watson 	 * Relabling network interfaces requires LOMAC privilege.
1726db2661ceSRobert Watson 	 */
1727db2661ceSRobert Watson 	error = mac_lomac_subject_privileged(subj);
1728db2661ceSRobert Watson 	if (error)
1729db2661ceSRobert Watson 		return (error);
1730db2661ceSRobert Watson 
1731db2661ceSRobert Watson 	/*
1732db2661ceSRobert Watson 	 * If the LOMAC label is to be changed, authorize as appropriate.
1733db2661ceSRobert Watson 	 */
1734db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1735db2661ceSRobert Watson 		/*
1736db2661ceSRobert Watson 		 * Rely on the traditional superuser status for the LOMAC
1737db2661ceSRobert Watson 		 * interface relabel requirements.  XXXMAC: This will go
1738db2661ceSRobert Watson 		 * away.
1739db2661ceSRobert Watson 		 */
1740db2661ceSRobert Watson 		error = suser_cred(cred, 0);
1741db2661ceSRobert Watson 		if (error)
1742db2661ceSRobert Watson 			return (EPERM);
1743db2661ceSRobert Watson 
1744db2661ceSRobert Watson 		/*
1745db2661ceSRobert Watson 		 * XXXMAC: Additional consistency tests regarding the single
1746db2661ceSRobert Watson 		 * and the range of the new label might be performed here.
1747db2661ceSRobert Watson 		 */
1748db2661ceSRobert Watson 	}
1749db2661ceSRobert Watson 
1750db2661ceSRobert Watson 	return (0);
1751db2661ceSRobert Watson }
1752db2661ceSRobert Watson 
1753db2661ceSRobert Watson static int
1754db2661ceSRobert Watson mac_lomac_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1755db2661ceSRobert Watson     struct mbuf *m, struct label *mbuflabel)
1756db2661ceSRobert Watson {
1757db2661ceSRobert Watson 	struct mac_lomac *p, *i;
1758db2661ceSRobert Watson 
1759db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1760db2661ceSRobert Watson 		return (0);
1761db2661ceSRobert Watson 
1762db2661ceSRobert Watson 	p = SLOT(mbuflabel);
1763db2661ceSRobert Watson 	i = SLOT(ifnetlabel);
1764db2661ceSRobert Watson 
1765db2661ceSRobert Watson 	return (mac_lomac_single_in_range(p, i) ? 0 : EACCES);
1766db2661ceSRobert Watson }
1767db2661ceSRobert Watson 
1768db2661ceSRobert Watson static int
1769db2661ceSRobert Watson mac_lomac_check_kld_load(struct ucred *cred, struct vnode *vp,
1770db2661ceSRobert Watson     struct label *label)
1771db2661ceSRobert Watson {
1772db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1773db2661ceSRobert Watson 
1774db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1775db2661ceSRobert Watson 		return (0);
1776db2661ceSRobert Watson 
1777db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1778db2661ceSRobert Watson 	obj = SLOT(label);
1779db2661ceSRobert Watson 
1780db2661ceSRobert Watson 	if (mac_lomac_subject_privileged(subj))
1781db2661ceSRobert Watson 		return (EPERM);
1782db2661ceSRobert Watson 
1783db2661ceSRobert Watson 	if (!mac_lomac_high_single(obj))
1784db2661ceSRobert Watson 		return (EACCES);
1785db2661ceSRobert Watson 
1786db2661ceSRobert Watson 	return (0);
1787db2661ceSRobert Watson }
1788db2661ceSRobert Watson 
1789db2661ceSRobert Watson static int
1790db2661ceSRobert Watson mac_lomac_check_kld_unload(struct ucred *cred)
1791db2661ceSRobert Watson {
1792db2661ceSRobert Watson 	struct mac_lomac *subj;
1793db2661ceSRobert Watson 
1794db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1795db2661ceSRobert Watson 		return (0);
1796db2661ceSRobert Watson 
1797db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1798db2661ceSRobert Watson 
1799db2661ceSRobert Watson 	if (mac_lomac_subject_privileged(subj))
1800db2661ceSRobert Watson 		return (EPERM);
1801db2661ceSRobert Watson 
1802db2661ceSRobert Watson 	return (0);
1803db2661ceSRobert Watson }
1804db2661ceSRobert Watson 
1805db2661ceSRobert Watson static int
1806db2661ceSRobert Watson mac_lomac_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1807db2661ceSRobert Watson     struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1808db2661ceSRobert Watson {
1809db2661ceSRobert Watson 
1810db2661ceSRobert Watson 	if(!mac_lomac_enabled)
1811db2661ceSRobert Watson 		return (0);
1812db2661ceSRobert Watson 
1813db2661ceSRobert Watson 	/* XXX: This will be implemented soon... */
1814db2661ceSRobert Watson 
1815db2661ceSRobert Watson 	return (0);
1816db2661ceSRobert Watson }
1817db2661ceSRobert Watson 
1818db2661ceSRobert Watson static int
1819db2661ceSRobert Watson mac_lomac_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1820db2661ceSRobert Watson     struct label *pipelabel)
1821db2661ceSRobert Watson {
1822db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1823db2661ceSRobert Watson 
1824db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1825db2661ceSRobert Watson 		return (0);
1826db2661ceSRobert Watson 
1827db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1828db2661ceSRobert Watson 	obj = SLOT((pipelabel));
1829db2661ceSRobert Watson 
1830db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
1831db2661ceSRobert Watson 		return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1832db2661ceSRobert Watson 
1833db2661ceSRobert Watson 	return (0);
1834db2661ceSRobert Watson }
1835db2661ceSRobert Watson 
1836db2661ceSRobert Watson static int
1837db2661ceSRobert Watson mac_lomac_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1838db2661ceSRobert Watson     struct label *pipelabel, struct label *newlabel)
1839db2661ceSRobert Watson {
1840db2661ceSRobert Watson 	struct mac_lomac *subj, *obj, *new;
1841db2661ceSRobert Watson 	int error;
1842db2661ceSRobert Watson 
1843db2661ceSRobert Watson 	new = SLOT(newlabel);
1844db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1845db2661ceSRobert Watson 	obj = SLOT(pipelabel);
1846db2661ceSRobert Watson 
1847db2661ceSRobert Watson 	/*
1848db2661ceSRobert Watson 	 * If there is a LOMAC label update for a pipe, it must be a
1849db2661ceSRobert Watson 	 * single update.
1850db2661ceSRobert Watson 	 */
1851db2661ceSRobert Watson 	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1852db2661ceSRobert Watson 	if (error)
1853db2661ceSRobert Watson 		return (error);
1854db2661ceSRobert Watson 
1855db2661ceSRobert Watson 	/*
1856db2661ceSRobert Watson 	 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1857db2661ceSRobert Watson 	 * authorize the relabel.
1858db2661ceSRobert Watson 	 */
1859db2661ceSRobert Watson 	if (!mac_lomac_single_in_range(obj, subj))
1860db2661ceSRobert Watson 		return (EPERM);
1861db2661ceSRobert Watson 
1862db2661ceSRobert Watson 	/*
1863db2661ceSRobert Watson 	 * If the LOMAC label is to be changed, authorize as appropriate.
1864db2661ceSRobert Watson 	 */
1865db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1866db2661ceSRobert Watson 		/*
1867db2661ceSRobert Watson 		 * To change the LOMAC label on a pipe, the new pipe label
1868db2661ceSRobert Watson 		 * must be in the subject range.
1869db2661ceSRobert Watson 		 */
1870db2661ceSRobert Watson 		if (!mac_lomac_single_in_range(new, subj))
1871db2661ceSRobert Watson 			return (EPERM);
1872db2661ceSRobert Watson 
1873db2661ceSRobert Watson 		/*
1874db2661ceSRobert Watson 		 * To change the LOMAC label on a pipe to be EQUAL, the
1875db2661ceSRobert Watson 		 * subject must have appropriate privilege.
1876db2661ceSRobert Watson 		 */
1877db2661ceSRobert Watson 		if (mac_lomac_contains_equal(new)) {
1878db2661ceSRobert Watson 			error = mac_lomac_subject_privileged(subj);
1879db2661ceSRobert Watson 			if (error)
1880db2661ceSRobert Watson 				return (error);
1881db2661ceSRobert Watson 		}
1882db2661ceSRobert Watson 	}
1883db2661ceSRobert Watson 
1884db2661ceSRobert Watson 	return (0);
1885db2661ceSRobert Watson }
1886db2661ceSRobert Watson 
1887db2661ceSRobert Watson static int
1888db2661ceSRobert Watson mac_lomac_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1889db2661ceSRobert Watson     struct label *pipelabel)
1890db2661ceSRobert Watson {
1891db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1892db2661ceSRobert Watson 
1893db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1894db2661ceSRobert Watson 		return (0);
1895db2661ceSRobert Watson 
1896db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1897db2661ceSRobert Watson 	obj = SLOT((pipelabel));
1898db2661ceSRobert Watson 
1899db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
1900db2661ceSRobert Watson 		return (EACCES);
1901db2661ceSRobert Watson 
1902db2661ceSRobert Watson 	return (0);
1903db2661ceSRobert Watson }
1904db2661ceSRobert Watson 
1905db2661ceSRobert Watson static int
1906db2661ceSRobert Watson mac_lomac_check_proc_debug(struct ucred *cred, struct proc *proc)
1907db2661ceSRobert Watson {
1908db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1909db2661ceSRobert Watson 
1910db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1911db2661ceSRobert Watson 		return (0);
1912db2661ceSRobert Watson 
1913db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1914db2661ceSRobert Watson 	obj = SLOT(&proc->p_ucred->cr_label);
1915db2661ceSRobert Watson 
1916db2661ceSRobert Watson 	/* XXX: range checks */
1917db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
1918db2661ceSRobert Watson 		return (ESRCH);
1919db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
1920db2661ceSRobert Watson 		return (EACCES);
1921db2661ceSRobert Watson 
1922db2661ceSRobert Watson 	return (0);
1923db2661ceSRobert Watson }
1924db2661ceSRobert Watson 
1925db2661ceSRobert Watson static int
1926db2661ceSRobert Watson mac_lomac_check_proc_sched(struct ucred *cred, struct proc *proc)
1927db2661ceSRobert Watson {
1928db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1929db2661ceSRobert Watson 
1930db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1931db2661ceSRobert Watson 		return (0);
1932db2661ceSRobert Watson 
1933db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1934db2661ceSRobert Watson 	obj = SLOT(&proc->p_ucred->cr_label);
1935db2661ceSRobert Watson 
1936db2661ceSRobert Watson 	/* XXX: range checks */
1937db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
1938db2661ceSRobert Watson 		return (ESRCH);
1939db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
1940db2661ceSRobert Watson 		return (EACCES);
1941db2661ceSRobert Watson 
1942db2661ceSRobert Watson 	return (0);
1943db2661ceSRobert Watson }
1944db2661ceSRobert Watson 
1945db2661ceSRobert Watson static int
1946db2661ceSRobert Watson mac_lomac_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1947db2661ceSRobert Watson {
1948db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
1949db2661ceSRobert Watson 
1950db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1951db2661ceSRobert Watson 		return (0);
1952db2661ceSRobert Watson 
1953db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1954db2661ceSRobert Watson 	obj = SLOT(&proc->p_ucred->cr_label);
1955db2661ceSRobert Watson 
1956db2661ceSRobert Watson 	/* XXX: range checks */
1957db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
1958db2661ceSRobert Watson 		return (ESRCH);
1959db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
1960db2661ceSRobert Watson 		return (EACCES);
1961db2661ceSRobert Watson 
1962db2661ceSRobert Watson 	return (0);
1963db2661ceSRobert Watson }
1964db2661ceSRobert Watson 
1965db2661ceSRobert Watson static int
1966db2661ceSRobert Watson mac_lomac_check_socket_deliver(struct socket *so, struct label *socketlabel,
1967db2661ceSRobert Watson     struct mbuf *m, struct label *mbuflabel)
1968db2661ceSRobert Watson {
1969db2661ceSRobert Watson 	struct mac_lomac *p, *s;
1970db2661ceSRobert Watson 
1971db2661ceSRobert Watson 	if (!mac_lomac_enabled)
1972db2661ceSRobert Watson 		return (0);
1973db2661ceSRobert Watson 
1974db2661ceSRobert Watson 	p = SLOT(mbuflabel);
1975db2661ceSRobert Watson 	s = SLOT(socketlabel);
1976db2661ceSRobert Watson 
1977db2661ceSRobert Watson 	return (mac_lomac_equal_single(p, s) ? 0 : EACCES);
1978db2661ceSRobert Watson }
1979db2661ceSRobert Watson 
1980db2661ceSRobert Watson static int
1981db2661ceSRobert Watson mac_lomac_check_socket_relabel(struct ucred *cred, struct socket *socket,
1982db2661ceSRobert Watson     struct label *socketlabel, struct label *newlabel)
1983db2661ceSRobert Watson {
1984db2661ceSRobert Watson 	struct mac_lomac *subj, *obj, *new;
1985db2661ceSRobert Watson 	int error;
1986db2661ceSRobert Watson 
1987db2661ceSRobert Watson 	new = SLOT(newlabel);
1988db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
1989db2661ceSRobert Watson 	obj = SLOT(socketlabel);
1990db2661ceSRobert Watson 
1991db2661ceSRobert Watson 	/*
1992db2661ceSRobert Watson 	 * If there is a LOMAC label update for the socket, it may be
1993db2661ceSRobert Watson 	 * an update of single.
1994db2661ceSRobert Watson 	 */
1995db2661ceSRobert Watson 	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1996db2661ceSRobert Watson 	if (error)
1997db2661ceSRobert Watson 		return (error);
1998db2661ceSRobert Watson 
1999db2661ceSRobert Watson 	/*
2000db2661ceSRobert Watson 	 * To relabel a socket, the old socket single must be in the subject
2001db2661ceSRobert Watson 	 * range.
2002db2661ceSRobert Watson 	 */
2003db2661ceSRobert Watson 	if (!mac_lomac_single_in_range(obj, subj))
2004db2661ceSRobert Watson 		return (EPERM);
2005db2661ceSRobert Watson 
2006db2661ceSRobert Watson 	/*
2007db2661ceSRobert Watson 	 * If the LOMAC label is to be changed, authorize as appropriate.
2008db2661ceSRobert Watson 	 */
2009db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2010db2661ceSRobert Watson 		/*
2011db2661ceSRobert Watson 		 * To relabel a socket, the new socket single must be in
2012db2661ceSRobert Watson 		 * the subject range.
2013db2661ceSRobert Watson 		 */
2014db2661ceSRobert Watson 		if (!mac_lomac_single_in_range(new, subj))
2015db2661ceSRobert Watson 			return (EPERM);
2016db2661ceSRobert Watson 
2017db2661ceSRobert Watson 		/*
2018db2661ceSRobert Watson 		 * To change the LOMAC label on the socket to contain EQUAL,
2019db2661ceSRobert Watson 		 * the subject must have appropriate privilege.
2020db2661ceSRobert Watson 		 */
2021db2661ceSRobert Watson 		if (mac_lomac_contains_equal(new)) {
2022db2661ceSRobert Watson 			error = mac_lomac_subject_privileged(subj);
2023db2661ceSRobert Watson 			if (error)
2024db2661ceSRobert Watson 				return (error);
2025db2661ceSRobert Watson 		}
2026db2661ceSRobert Watson 	}
2027db2661ceSRobert Watson 
2028db2661ceSRobert Watson 	return (0);
2029db2661ceSRobert Watson }
2030db2661ceSRobert Watson 
2031db2661ceSRobert Watson static int
2032db2661ceSRobert Watson mac_lomac_check_socket_visible(struct ucred *cred, struct socket *socket,
2033db2661ceSRobert Watson     struct label *socketlabel)
2034db2661ceSRobert Watson {
2035db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2036db2661ceSRobert Watson 
2037db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2038db2661ceSRobert Watson 		return (0);
2039db2661ceSRobert Watson 
2040db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2041db2661ceSRobert Watson 	obj = SLOT(socketlabel);
2042db2661ceSRobert Watson 
2043db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
2044db2661ceSRobert Watson 		return (ENOENT);
2045db2661ceSRobert Watson 
2046db2661ceSRobert Watson 	return (0);
2047db2661ceSRobert Watson }
2048db2661ceSRobert Watson 
2049db2661ceSRobert Watson static int
2050db2661ceSRobert Watson mac_lomac_check_system_swapon(struct ucred *cred, struct vnode *vp,
2051db2661ceSRobert Watson     struct label *label)
2052db2661ceSRobert Watson {
2053db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2054db2661ceSRobert Watson 
2055db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2056db2661ceSRobert Watson 		return (0);
2057db2661ceSRobert Watson 
2058db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2059db2661ceSRobert Watson 	obj = SLOT(label);
2060db2661ceSRobert Watson 
2061db2661ceSRobert Watson 	if (mac_lomac_subject_privileged(subj))
2062db2661ceSRobert Watson 		return (EPERM);
2063db2661ceSRobert Watson 
2064db2661ceSRobert Watson 	if (!mac_lomac_high_single(obj))
2065db2661ceSRobert Watson 		return (EACCES);
2066db2661ceSRobert Watson 
2067db2661ceSRobert Watson 	return (0);
2068db2661ceSRobert Watson }
2069db2661ceSRobert Watson 
2070db2661ceSRobert Watson static int
2071db2661ceSRobert Watson mac_lomac_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
2072db2661ceSRobert Watson     void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
2073db2661ceSRobert Watson {
2074db2661ceSRobert Watson 	struct mac_lomac *subj;
2075db2661ceSRobert Watson 
2076db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2077db2661ceSRobert Watson 		return (0);
2078db2661ceSRobert Watson 
2079db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2080db2661ceSRobert Watson 
2081db2661ceSRobert Watson 	/*
2082db2661ceSRobert Watson 	 * In general, treat sysctl variables as lomac/high, but also
2083db2661ceSRobert Watson 	 * require privilege to change them, since they are a
2084db2661ceSRobert Watson 	 * communications channel between grades.  Exempt MIB
2085db2661ceSRobert Watson 	 * queries from this due to undocmented sysctl magic.
2086db2661ceSRobert Watson 	 * XXXMAC: This probably requires some more review.
2087db2661ceSRobert Watson 	 */
2088db2661ceSRobert Watson 	if (new != NULL) {
2089db2661ceSRobert Watson 		if (namelen > 0 && name[0] == 0)
2090db2661ceSRobert Watson 			return (0);
2091db2661ceSRobert Watson 
2092db2661ceSRobert Watson #ifdef notdef
2093db2661ceSRobert Watson 		if (!mac_lomac_subject_dominate_high(subj))
2094db2661ceSRobert Watson 			return (EACCES);
2095db2661ceSRobert Watson #endif
2096db2661ceSRobert Watson 
2097db2661ceSRobert Watson 		if (mac_lomac_subject_privileged(subj))
2098db2661ceSRobert Watson 			return (EPERM);
2099db2661ceSRobert Watson 	}
2100db2661ceSRobert Watson 
2101db2661ceSRobert Watson 	return (0);
2102db2661ceSRobert Watson }
2103db2661ceSRobert Watson 
2104db2661ceSRobert Watson static int
2105db2661ceSRobert Watson mac_lomac_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2106db2661ceSRobert Watson     struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2107db2661ceSRobert Watson {
2108db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2109db2661ceSRobert Watson 
2110db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2111db2661ceSRobert Watson 		return (0);
2112db2661ceSRobert Watson 
2113db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2114db2661ceSRobert Watson 	obj = SLOT(dlabel);
2115db2661ceSRobert Watson 
2116db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2117db2661ceSRobert Watson 		return (EACCES);
2118db2661ceSRobert Watson 	if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2119db2661ceSRobert Watson 	    !mac_lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2120db2661ceSRobert Watson 		return (EACCES);
2121db2661ceSRobert Watson 
2122db2661ceSRobert Watson 	return (0);
2123db2661ceSRobert Watson }
2124db2661ceSRobert Watson 
2125db2661ceSRobert Watson static int
2126db2661ceSRobert Watson mac_lomac_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2127db2661ceSRobert Watson     struct label *dlabel, struct vnode *vp, struct label *label,
2128db2661ceSRobert Watson     struct componentname *cnp)
2129db2661ceSRobert Watson {
2130db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2131db2661ceSRobert Watson 
2132db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2133db2661ceSRobert Watson 		return (0);
2134db2661ceSRobert Watson 
2135db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2136db2661ceSRobert Watson 	obj = SLOT(dlabel);
2137db2661ceSRobert Watson 
2138db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2139db2661ceSRobert Watson 		return (EACCES);
2140db2661ceSRobert Watson 
2141db2661ceSRobert Watson 	obj = SLOT(label);
2142db2661ceSRobert Watson 
2143db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2144db2661ceSRobert Watson 		return (EACCES);
2145db2661ceSRobert Watson 
2146db2661ceSRobert Watson 	return (0);
2147db2661ceSRobert Watson }
2148db2661ceSRobert Watson 
2149db2661ceSRobert Watson static int
2150db2661ceSRobert Watson mac_lomac_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2151db2661ceSRobert Watson     struct label *label, acl_type_t type)
2152db2661ceSRobert Watson {
2153db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2154db2661ceSRobert Watson 
2155db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2156db2661ceSRobert Watson 		return (0);
2157db2661ceSRobert Watson 
2158db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2159db2661ceSRobert Watson 	obj = SLOT(label);
2160db2661ceSRobert Watson 
2161db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2162db2661ceSRobert Watson 		return (EACCES);
2163db2661ceSRobert Watson 
2164db2661ceSRobert Watson 	return (0);
2165db2661ceSRobert Watson }
2166db2661ceSRobert Watson 
2167db2661ceSRobert Watson static int
2168db2661ceSRobert Watson mac_lomac_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2169db2661ceSRobert Watson     struct label *dlabel, struct vnode *vp, struct label *label,
2170db2661ceSRobert Watson     struct componentname *cnp)
2171db2661ceSRobert Watson {
2172db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2173db2661ceSRobert Watson 
2174db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2175db2661ceSRobert Watson 		return (0);
2176db2661ceSRobert Watson 
2177db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2178db2661ceSRobert Watson 	obj = SLOT(dlabel);
2179db2661ceSRobert Watson 
2180db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2181db2661ceSRobert Watson 		return (EACCES);
2182db2661ceSRobert Watson 
2183db2661ceSRobert Watson 	obj = SLOT(label);
2184db2661ceSRobert Watson 
2185db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2186db2661ceSRobert Watson 		return (EACCES);
2187db2661ceSRobert Watson 
2188db2661ceSRobert Watson 	return (0);
2189db2661ceSRobert Watson }
2190db2661ceSRobert Watson 
2191db2661ceSRobert Watson static int
2192db2661ceSRobert Watson mac_lomac_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2193db2661ceSRobert Watson     struct label *label, int prot)
2194db2661ceSRobert Watson {
2195db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2196db2661ceSRobert Watson 
2197db2661ceSRobert Watson 	/*
2198db2661ceSRobert Watson 	 * Rely on the use of open()-time protections to handle
2199db2661ceSRobert Watson 	 * non-revocation cases.
2200db2661ceSRobert Watson 	 */
2201db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2202db2661ceSRobert Watson 		return (0);
2203db2661ceSRobert Watson 
2204db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2205db2661ceSRobert Watson 	obj = SLOT(label);
2206db2661ceSRobert Watson 
2207db2661ceSRobert Watson 	if (prot & VM_PROT_WRITE) {
2208db2661ceSRobert Watson 		if (!mac_lomac_subject_dominate(subj, obj))
2209db2661ceSRobert Watson 			return (EACCES);
2210db2661ceSRobert Watson 	}
2211db2661ceSRobert Watson 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2212db2661ceSRobert Watson 		if (!mac_lomac_dominate_single(obj, subj))
2213db2661ceSRobert Watson 			return (maybe_demote(subj, obj, "mapping", "file", vp));
2214db2661ceSRobert Watson 	}
2215db2661ceSRobert Watson 
2216db2661ceSRobert Watson 	return (0);
2217db2661ceSRobert Watson }
2218db2661ceSRobert Watson 
2219db2661ceSRobert Watson static int
2220db2661ceSRobert Watson mac_lomac_check_vnode_mprotect(struct ucred *cred, struct vnode *vp,
2221db2661ceSRobert Watson     struct label *label, int prot)
2222db2661ceSRobert Watson {
2223db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2224db2661ceSRobert Watson 
2225db2661ceSRobert Watson 	/*
2226db2661ceSRobert Watson 	 * Rely on the use of open()-time protections to handle
2227db2661ceSRobert Watson 	 * non-revocation cases.
2228db2661ceSRobert Watson 	 */
2229db2661ceSRobert Watson 	if (!mac_lomac_enabled || !revocation_enabled)
2230db2661ceSRobert Watson 		return (0);
2231db2661ceSRobert Watson 
2232db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2233db2661ceSRobert Watson 	obj = SLOT(label);
2234db2661ceSRobert Watson 
2235db2661ceSRobert Watson 	if (prot & VM_PROT_WRITE) {
2236db2661ceSRobert Watson 		if (!mac_lomac_subject_dominate(subj, obj))
2237db2661ceSRobert Watson 			return (EACCES);
2238db2661ceSRobert Watson 	}
2239db2661ceSRobert Watson 	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2240db2661ceSRobert Watson 		if (!mac_lomac_dominate_single(obj, subj))
2241db2661ceSRobert Watson 			return (EACCES);
2242db2661ceSRobert Watson 	}
2243db2661ceSRobert Watson 
2244db2661ceSRobert Watson 	return (0);
2245db2661ceSRobert Watson }
2246db2661ceSRobert Watson 
2247db2661ceSRobert Watson static void
2248db2661ceSRobert Watson mac_lomac_check_vnode_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2249db2661ceSRobert Watson     struct label *label, /* XXX vm_prot_t */ int *prot)
2250db2661ceSRobert Watson {
2251db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2252db2661ceSRobert Watson 
2253db2661ceSRobert Watson 	/*
2254db2661ceSRobert Watson 	 * Rely on the use of open()-time protections to handle
2255db2661ceSRobert Watson 	 * non-revocation cases.
2256db2661ceSRobert Watson 	 */
2257db2661ceSRobert Watson 	if (!mac_lomac_enabled || !revocation_enabled)
2258db2661ceSRobert Watson 		return;
2259db2661ceSRobert Watson 
2260db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2261db2661ceSRobert Watson 	obj = SLOT(label);
2262db2661ceSRobert Watson 
2263db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2264db2661ceSRobert Watson 		*prot &= ~VM_PROT_WRITE;
2265db2661ceSRobert Watson }
2266db2661ceSRobert Watson 
2267db2661ceSRobert Watson static int
2268db2661ceSRobert Watson mac_lomac_check_vnode_open(struct ucred *cred, struct vnode *vp,
2269db2661ceSRobert Watson     struct label *vnodelabel, int acc_mode)
2270db2661ceSRobert Watson {
2271db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2272db2661ceSRobert Watson 
2273db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2274db2661ceSRobert Watson 		return (0);
2275db2661ceSRobert Watson 
2276db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2277db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2278db2661ceSRobert Watson 
2279db2661ceSRobert Watson 	/* XXX privilege override for admin? */
2280db2661ceSRobert Watson 	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2281db2661ceSRobert Watson 		if (!mac_lomac_subject_dominate(subj, obj))
2282db2661ceSRobert Watson 			return (EACCES);
2283db2661ceSRobert Watson 	}
2284db2661ceSRobert Watson 
2285db2661ceSRobert Watson 	return (0);
2286db2661ceSRobert Watson }
2287db2661ceSRobert Watson 
2288db2661ceSRobert Watson static int
2289db2661ceSRobert Watson mac_lomac_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2290db2661ceSRobert Watson     struct vnode *vp, struct label *label)
2291db2661ceSRobert Watson {
2292db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2293db2661ceSRobert Watson 
2294db2661ceSRobert Watson 	if (!mac_lomac_enabled || !revocation_enabled)
2295db2661ceSRobert Watson 		return (0);
2296db2661ceSRobert Watson 
2297db2661ceSRobert Watson 	subj = SLOT(&active_cred->cr_label);
2298db2661ceSRobert Watson 	obj = SLOT(label);
2299db2661ceSRobert Watson 
2300db2661ceSRobert Watson 	if (!mac_lomac_dominate_single(obj, subj))
2301db2661ceSRobert Watson 		return (maybe_demote(subj, obj, "reading", "file", vp));
2302db2661ceSRobert Watson 
2303db2661ceSRobert Watson 	return (0);
2304db2661ceSRobert Watson }
2305db2661ceSRobert Watson 
2306db2661ceSRobert Watson static int
2307db2661ceSRobert Watson mac_lomac_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2308db2661ceSRobert Watson     struct label *vnodelabel, struct label *newlabel)
2309db2661ceSRobert Watson {
2310db2661ceSRobert Watson 	struct mac_lomac *old, *new, *subj;
2311db2661ceSRobert Watson 	int error;
2312db2661ceSRobert Watson 
2313db2661ceSRobert Watson 	old = SLOT(vnodelabel);
2314db2661ceSRobert Watson 	new = SLOT(newlabel);
2315db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2316db2661ceSRobert Watson 
2317db2661ceSRobert Watson 	/*
2318db2661ceSRobert Watson 	 * If there is a LOMAC label update for the vnode, it must be a
2319db2661ceSRobert Watson 	 * single label, with an optional explicit auxiliary single.
2320db2661ceSRobert Watson 	 */
2321db2661ceSRobert Watson 	error = lomac_atmostflags(new,
2322db2661ceSRobert Watson 	    MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2323db2661ceSRobert Watson 	if (error)
2324db2661ceSRobert Watson 		return (error);
2325db2661ceSRobert Watson 
2326db2661ceSRobert Watson 	/*
2327db2661ceSRobert Watson 	 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2328db2661ceSRobert Watson 	 * authorize the relabel.
2329db2661ceSRobert Watson 	 */
2330db2661ceSRobert Watson 	if (!mac_lomac_single_in_range(old, subj))
2331db2661ceSRobert Watson 		return (EPERM);
2332db2661ceSRobert Watson 
2333db2661ceSRobert Watson 	/*
2334db2661ceSRobert Watson 	 * If the LOMAC label is to be changed, authorize as appropriate.
2335db2661ceSRobert Watson 	 */
2336db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2337db2661ceSRobert Watson 		/*
2338db2661ceSRobert Watson 		 * To change the LOMAC label on a vnode, the new vnode label
2339db2661ceSRobert Watson 		 * must be in the subject range.
2340db2661ceSRobert Watson 		 */
2341db2661ceSRobert Watson 		if (!mac_lomac_single_in_range(new, subj))
2342db2661ceSRobert Watson 			return (EPERM);
2343db2661ceSRobert Watson 
2344db2661ceSRobert Watson 		/*
2345db2661ceSRobert Watson 		 * To change the LOMAC label on the vnode to be EQUAL,
2346db2661ceSRobert Watson 		 * the subject must have appropriate privilege.
2347db2661ceSRobert Watson 		 */
2348db2661ceSRobert Watson 		if (mac_lomac_contains_equal(new)) {
2349db2661ceSRobert Watson 			error = mac_lomac_subject_privileged(subj);
2350db2661ceSRobert Watson 			if (error)
2351db2661ceSRobert Watson 				return (error);
2352db2661ceSRobert Watson 		}
2353db2661ceSRobert Watson 	}
2354db2661ceSRobert Watson 	if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2355db2661ceSRobert Watson 		/*
2356db2661ceSRobert Watson 		 * To change the auxiliary LOMAC label on a vnode, the new
2357db2661ceSRobert Watson 		 * vnode label must be in the subject range.
2358db2661ceSRobert Watson 		 */
2359db2661ceSRobert Watson 		if (!mac_lomac_auxsingle_in_range(new, subj))
2360db2661ceSRobert Watson 			return (EPERM);
2361db2661ceSRobert Watson 
2362db2661ceSRobert Watson 		/*
2363db2661ceSRobert Watson 		 * To change the auxiliary LOMAC label on the vnode to be
2364db2661ceSRobert Watson 		 * EQUAL, the subject must have appropriate privilege.
2365db2661ceSRobert Watson 		 */
2366db2661ceSRobert Watson 		if (mac_lomac_contains_equal(new)) {
2367db2661ceSRobert Watson 			error = mac_lomac_subject_privileged(subj);
2368db2661ceSRobert Watson 			if (error)
2369db2661ceSRobert Watson 				return (error);
2370db2661ceSRobert Watson 		}
2371db2661ceSRobert Watson 	}
2372db2661ceSRobert Watson 
2373db2661ceSRobert Watson 	return (0);
2374db2661ceSRobert Watson }
2375db2661ceSRobert Watson 
2376db2661ceSRobert Watson static int
2377db2661ceSRobert Watson mac_lomac_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2378db2661ceSRobert Watson     struct label *dlabel, struct vnode *vp, struct label *label,
2379db2661ceSRobert Watson     struct componentname *cnp)
2380db2661ceSRobert Watson {
2381db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2382db2661ceSRobert Watson 
2383db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2384db2661ceSRobert Watson 		return (0);
2385db2661ceSRobert Watson 
2386db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2387db2661ceSRobert Watson 	obj = SLOT(dlabel);
2388db2661ceSRobert Watson 
2389db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2390db2661ceSRobert Watson 		return (EACCES);
2391db2661ceSRobert Watson 
2392db2661ceSRobert Watson 	obj = SLOT(label);
2393db2661ceSRobert Watson 
2394db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2395db2661ceSRobert Watson 		return (EACCES);
2396db2661ceSRobert Watson 
2397db2661ceSRobert Watson 	return (0);
2398db2661ceSRobert Watson }
2399db2661ceSRobert Watson 
2400db2661ceSRobert Watson static int
2401db2661ceSRobert Watson mac_lomac_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2402db2661ceSRobert Watson     struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2403db2661ceSRobert Watson     struct componentname *cnp)
2404db2661ceSRobert Watson {
2405db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2406db2661ceSRobert Watson 
2407db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2408db2661ceSRobert Watson 		return (0);
2409db2661ceSRobert Watson 
2410db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2411db2661ceSRobert Watson 	obj = SLOT(dlabel);
2412db2661ceSRobert Watson 
2413db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2414db2661ceSRobert Watson 		return (EACCES);
2415db2661ceSRobert Watson 
2416db2661ceSRobert Watson 	if (vp != NULL) {
2417db2661ceSRobert Watson 		obj = SLOT(label);
2418db2661ceSRobert Watson 
2419db2661ceSRobert Watson 		if (!mac_lomac_subject_dominate(subj, obj))
2420db2661ceSRobert Watson 			return (EACCES);
2421db2661ceSRobert Watson 	}
2422db2661ceSRobert Watson 
2423db2661ceSRobert Watson 	return (0);
2424db2661ceSRobert Watson }
2425db2661ceSRobert Watson 
2426db2661ceSRobert Watson static int
2427db2661ceSRobert Watson mac_lomac_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2428db2661ceSRobert Watson     struct label *label)
2429db2661ceSRobert Watson {
2430db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2431db2661ceSRobert Watson 
2432db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2433db2661ceSRobert Watson 		return (0);
2434db2661ceSRobert Watson 
2435db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2436db2661ceSRobert Watson 	obj = SLOT(label);
2437db2661ceSRobert Watson 
2438db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2439db2661ceSRobert Watson 		return (EACCES);
2440db2661ceSRobert Watson 
2441db2661ceSRobert Watson 	return (0);
2442db2661ceSRobert Watson }
2443db2661ceSRobert Watson 
2444db2661ceSRobert Watson static int
2445db2661ceSRobert Watson mac_lomac_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2446db2661ceSRobert Watson     struct label *label, acl_type_t type, struct acl *acl)
2447db2661ceSRobert Watson {
2448db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2449db2661ceSRobert Watson 
2450db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2451db2661ceSRobert Watson 		return (0);
2452db2661ceSRobert Watson 
2453db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2454db2661ceSRobert Watson 	obj = SLOT(label);
2455db2661ceSRobert Watson 
2456db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2457db2661ceSRobert Watson 		return (EACCES);
2458db2661ceSRobert Watson 
2459db2661ceSRobert Watson 	return (0);
2460db2661ceSRobert Watson }
2461db2661ceSRobert Watson 
2462db2661ceSRobert Watson static int
2463db2661ceSRobert Watson mac_lomac_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2464db2661ceSRobert Watson     struct label *vnodelabel, int attrnamespace, const char *name,
2465db2661ceSRobert Watson     struct uio *uio)
2466db2661ceSRobert Watson {
2467db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2468db2661ceSRobert Watson 
2469db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2470db2661ceSRobert Watson 		return (0);
2471db2661ceSRobert Watson 
2472db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2473db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2474db2661ceSRobert Watson 
2475db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2476db2661ceSRobert Watson 		return (EACCES);
2477db2661ceSRobert Watson 
2478db2661ceSRobert Watson 	/* XXX: protect the MAC EA in a special way? */
2479db2661ceSRobert Watson 
2480db2661ceSRobert Watson 	return (0);
2481db2661ceSRobert Watson }
2482db2661ceSRobert Watson 
2483db2661ceSRobert Watson static int
2484db2661ceSRobert Watson mac_lomac_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2485db2661ceSRobert Watson     struct label *vnodelabel, u_long flags)
2486db2661ceSRobert Watson {
2487db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2488db2661ceSRobert Watson 
2489db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2490db2661ceSRobert Watson 		return (0);
2491db2661ceSRobert Watson 
2492db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2493db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2494db2661ceSRobert Watson 
2495db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2496db2661ceSRobert Watson 		return (EACCES);
2497db2661ceSRobert Watson 
2498db2661ceSRobert Watson 	return (0);
2499db2661ceSRobert Watson }
2500db2661ceSRobert Watson 
2501db2661ceSRobert Watson static int
2502db2661ceSRobert Watson mac_lomac_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2503db2661ceSRobert Watson     struct label *vnodelabel, mode_t mode)
2504db2661ceSRobert Watson {
2505db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2506db2661ceSRobert Watson 
2507db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2508db2661ceSRobert Watson 		return (0);
2509db2661ceSRobert Watson 
2510db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2511db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2512db2661ceSRobert Watson 
2513db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2514db2661ceSRobert Watson 		return (EACCES);
2515db2661ceSRobert Watson 
2516db2661ceSRobert Watson 	return (0);
2517db2661ceSRobert Watson }
2518db2661ceSRobert Watson 
2519db2661ceSRobert Watson static int
2520db2661ceSRobert Watson mac_lomac_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2521db2661ceSRobert Watson     struct label *vnodelabel, uid_t uid, gid_t gid)
2522db2661ceSRobert Watson {
2523db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2524db2661ceSRobert Watson 
2525db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2526db2661ceSRobert Watson 		return (0);
2527db2661ceSRobert Watson 
2528db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2529db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2530db2661ceSRobert Watson 
2531db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2532db2661ceSRobert Watson 		return (EACCES);
2533db2661ceSRobert Watson 
2534db2661ceSRobert Watson 	return (0);
2535db2661ceSRobert Watson }
2536db2661ceSRobert Watson 
2537db2661ceSRobert Watson static int
2538db2661ceSRobert Watson mac_lomac_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2539db2661ceSRobert Watson     struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2540db2661ceSRobert Watson {
2541db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2542db2661ceSRobert Watson 
2543db2661ceSRobert Watson 	if (!mac_lomac_enabled)
2544db2661ceSRobert Watson 		return (0);
2545db2661ceSRobert Watson 
2546db2661ceSRobert Watson 	subj = SLOT(&cred->cr_label);
2547db2661ceSRobert Watson 	obj = SLOT(vnodelabel);
2548db2661ceSRobert Watson 
2549db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2550db2661ceSRobert Watson 		return (EACCES);
2551db2661ceSRobert Watson 
2552db2661ceSRobert Watson 	return (0);
2553db2661ceSRobert Watson }
2554db2661ceSRobert Watson 
2555db2661ceSRobert Watson static int
2556db2661ceSRobert Watson mac_lomac_check_vnode_write(struct ucred *active_cred,
2557db2661ceSRobert Watson     struct ucred *file_cred, struct vnode *vp, struct label *label)
2558db2661ceSRobert Watson {
2559db2661ceSRobert Watson 	struct mac_lomac *subj, *obj;
2560db2661ceSRobert Watson 
2561db2661ceSRobert Watson 	if (!mac_lomac_enabled || !revocation_enabled)
2562db2661ceSRobert Watson 		return (0);
2563db2661ceSRobert Watson 
2564db2661ceSRobert Watson 	subj = SLOT(&active_cred->cr_label);
2565db2661ceSRobert Watson 	obj = SLOT(label);
2566db2661ceSRobert Watson 
2567db2661ceSRobert Watson 	if (!mac_lomac_subject_dominate(subj, obj))
2568db2661ceSRobert Watson 		return (EACCES);
2569db2661ceSRobert Watson 
2570db2661ceSRobert Watson 	return (0);
2571db2661ceSRobert Watson }
2572db2661ceSRobert Watson 
2573db2661ceSRobert Watson static void
2574db2661ceSRobert Watson mac_lomac_thread_userret(struct thread *td)
2575db2661ceSRobert Watson {
2576db2661ceSRobert Watson 	struct proc *p = td->td_proc;
2577db2661ceSRobert Watson 	struct mac_lomac_proc *subj = PSLOT(&p->p_label);
2578db2661ceSRobert Watson 	struct ucred *newcred, *oldcred;
2579db2661ceSRobert Watson 	int dodrop;
2580db2661ceSRobert Watson 
2581db2661ceSRobert Watson 	mtx_lock(&subj->mtx);
2582db2661ceSRobert Watson 	if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2583db2661ceSRobert Watson 		dodrop = 0;
2584db2661ceSRobert Watson 		mtx_unlock(&subj->mtx);
2585db2661ceSRobert Watson 		newcred = crget();
2586db2661ceSRobert Watson 		/*
2587db2661ceSRobert Watson 		 * Prevent a lock order reversal in
2588db2661ceSRobert Watson 		 * mac_cred_mmapped_drop_perms; ideally, the other
2589db2661ceSRobert Watson 		 * user of subj->mtx wouldn't be holding Giant.
2590db2661ceSRobert Watson 		 */
2591db2661ceSRobert Watson 		mtx_lock(&Giant);
2592db2661ceSRobert Watson 		PROC_LOCK(p);
2593db2661ceSRobert Watson 		mtx_lock(&subj->mtx);
2594db2661ceSRobert Watson 		/*
2595db2661ceSRobert Watson 		 * Check if we lost the race while allocating the cred.
2596db2661ceSRobert Watson 		 */
2597db2661ceSRobert Watson 		if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2598db2661ceSRobert Watson 			crfree(newcred);
2599db2661ceSRobert Watson 			goto out;
2600db2661ceSRobert Watson 		}
2601db2661ceSRobert Watson 		oldcred = p->p_ucred;
2602db2661ceSRobert Watson 		crcopy(newcred, oldcred);
2603db2661ceSRobert Watson 		crhold(newcred);
2604db2661ceSRobert Watson 		mac_lomac_copy(&subj->mac_lomac, SLOT(&newcred->cr_label));
2605db2661ceSRobert Watson 		p->p_ucred = newcred;
2606db2661ceSRobert Watson 		crfree(oldcred);
2607db2661ceSRobert Watson 		dodrop = 1;
2608db2661ceSRobert Watson 	out:
2609db2661ceSRobert Watson 		mtx_unlock(&subj->mtx);
2610db2661ceSRobert Watson 		PROC_UNLOCK(p);
2611db2661ceSRobert Watson 		if (dodrop)
2612db2661ceSRobert Watson 			mac_cred_mmapped_drop_perms(curthread, newcred);
2613db2661ceSRobert Watson 		mtx_unlock(&Giant);
2614db2661ceSRobert Watson 	} else {
2615db2661ceSRobert Watson 		mtx_unlock(&subj->mtx);
2616db2661ceSRobert Watson 	}
2617db2661ceSRobert Watson }
2618db2661ceSRobert Watson 
2619db2661ceSRobert Watson static struct mac_policy_ops mac_lomac_ops =
2620db2661ceSRobert Watson {
2621db2661ceSRobert Watson 	.mpo_destroy = mac_lomac_destroy,
2622db2661ceSRobert Watson 	.mpo_init = mac_lomac_init,
2623db2661ceSRobert Watson 	.mpo_init_bpfdesc_label = mac_lomac_init_label,
2624db2661ceSRobert Watson 	.mpo_init_cred_label = mac_lomac_init_label,
2625db2661ceSRobert Watson 	.mpo_init_devfsdirent_label = mac_lomac_init_label,
2626db2661ceSRobert Watson 	.mpo_init_ifnet_label = mac_lomac_init_label,
2627db2661ceSRobert Watson 	.mpo_init_ipq_label = mac_lomac_init_label,
2628db2661ceSRobert Watson 	.mpo_init_mbuf_label = mac_lomac_init_label_waitcheck,
2629db2661ceSRobert Watson 	.mpo_init_mount_label = mac_lomac_init_label,
2630db2661ceSRobert Watson 	.mpo_init_mount_fs_label = mac_lomac_init_label,
2631db2661ceSRobert Watson 	.mpo_init_pipe_label = mac_lomac_init_label,
2632db2661ceSRobert Watson 	.mpo_init_proc_label = mac_lomac_init_proc_label,
2633db2661ceSRobert Watson 	.mpo_init_socket_label = mac_lomac_init_label_waitcheck,
2634db2661ceSRobert Watson 	.mpo_init_socket_peer_label = mac_lomac_init_label_waitcheck,
2635db2661ceSRobert Watson 	.mpo_init_vnode_label = mac_lomac_init_label,
2636db2661ceSRobert Watson 	.mpo_destroy_bpfdesc_label = mac_lomac_destroy_label,
2637db2661ceSRobert Watson 	.mpo_destroy_cred_label = mac_lomac_destroy_label,
2638db2661ceSRobert Watson 	.mpo_destroy_devfsdirent_label = mac_lomac_destroy_label,
2639db2661ceSRobert Watson 	.mpo_destroy_ifnet_label = mac_lomac_destroy_label,
2640db2661ceSRobert Watson 	.mpo_destroy_ipq_label = mac_lomac_destroy_label,
2641db2661ceSRobert Watson 	.mpo_destroy_mbuf_label = mac_lomac_destroy_label,
2642db2661ceSRobert Watson 	.mpo_destroy_mount_label = mac_lomac_destroy_label,
2643db2661ceSRobert Watson 	.mpo_destroy_mount_fs_label = mac_lomac_destroy_label,
2644db2661ceSRobert Watson 	.mpo_destroy_pipe_label = mac_lomac_destroy_label,
2645db2661ceSRobert Watson 	.mpo_destroy_proc_label = mac_lomac_destroy_proc_label,
2646db2661ceSRobert Watson 	.mpo_destroy_socket_label = mac_lomac_destroy_label,
2647db2661ceSRobert Watson 	.mpo_destroy_socket_peer_label = mac_lomac_destroy_label,
2648db2661ceSRobert Watson 	.mpo_destroy_vnode_label = mac_lomac_destroy_label,
2649db2661ceSRobert Watson 	.mpo_copy_pipe_label = mac_lomac_copy_label,
2650db2661ceSRobert Watson 	.mpo_copy_vnode_label = mac_lomac_copy_label,
2651db2661ceSRobert Watson 	.mpo_externalize_cred_label = mac_lomac_externalize_label,
2652db2661ceSRobert Watson 	.mpo_externalize_ifnet_label = mac_lomac_externalize_label,
2653db2661ceSRobert Watson 	.mpo_externalize_pipe_label = mac_lomac_externalize_label,
2654db2661ceSRobert Watson 	.mpo_externalize_socket_label = mac_lomac_externalize_label,
2655db2661ceSRobert Watson 	.mpo_externalize_socket_peer_label = mac_lomac_externalize_label,
2656db2661ceSRobert Watson 	.mpo_externalize_vnode_label = mac_lomac_externalize_label,
2657db2661ceSRobert Watson 	.mpo_internalize_cred_label = mac_lomac_internalize_label,
2658db2661ceSRobert Watson 	.mpo_internalize_ifnet_label = mac_lomac_internalize_label,
2659db2661ceSRobert Watson 	.mpo_internalize_pipe_label = mac_lomac_internalize_label,
2660db2661ceSRobert Watson 	.mpo_internalize_socket_label = mac_lomac_internalize_label,
2661db2661ceSRobert Watson 	.mpo_internalize_vnode_label = mac_lomac_internalize_label,
2662db2661ceSRobert Watson 	.mpo_create_devfs_device = mac_lomac_create_devfs_device,
2663db2661ceSRobert Watson 	.mpo_create_devfs_directory = mac_lomac_create_devfs_directory,
2664db2661ceSRobert Watson 	.mpo_create_devfs_symlink = mac_lomac_create_devfs_symlink,
2665db2661ceSRobert Watson 	.mpo_create_mount = mac_lomac_create_mount,
2666db2661ceSRobert Watson 	.mpo_create_root_mount = mac_lomac_create_root_mount,
2667db2661ceSRobert Watson 	.mpo_relabel_vnode = mac_lomac_relabel_vnode,
2668db2661ceSRobert Watson 	.mpo_update_devfsdirent = mac_lomac_update_devfsdirent,
2669db2661ceSRobert Watson 	.mpo_associate_vnode_devfs = mac_lomac_associate_vnode_devfs,
2670db2661ceSRobert Watson 	.mpo_associate_vnode_extattr = mac_lomac_associate_vnode_extattr,
2671db2661ceSRobert Watson 	.mpo_associate_vnode_singlelabel =
2672db2661ceSRobert Watson 	    mac_lomac_associate_vnode_singlelabel,
2673db2661ceSRobert Watson 	.mpo_create_vnode_extattr = mac_lomac_create_vnode_extattr,
2674db2661ceSRobert Watson 	.mpo_setlabel_vnode_extattr = mac_lomac_setlabel_vnode_extattr,
2675db2661ceSRobert Watson 	.mpo_create_mbuf_from_socket = mac_lomac_create_mbuf_from_socket,
2676db2661ceSRobert Watson 	.mpo_create_pipe = mac_lomac_create_pipe,
2677db2661ceSRobert Watson 	.mpo_create_socket = mac_lomac_create_socket,
2678db2661ceSRobert Watson 	.mpo_create_socket_from_socket = mac_lomac_create_socket_from_socket,
2679db2661ceSRobert Watson 	.mpo_relabel_pipe = mac_lomac_relabel_pipe,
2680db2661ceSRobert Watson 	.mpo_relabel_socket = mac_lomac_relabel_socket,
2681db2661ceSRobert Watson 	.mpo_set_socket_peer_from_mbuf = mac_lomac_set_socket_peer_from_mbuf,
2682db2661ceSRobert Watson 	.mpo_set_socket_peer_from_socket =
2683db2661ceSRobert Watson 	    mac_lomac_set_socket_peer_from_socket,
2684db2661ceSRobert Watson 	.mpo_create_bpfdesc = mac_lomac_create_bpfdesc,
2685db2661ceSRobert Watson 	.mpo_create_datagram_from_ipq = mac_lomac_create_datagram_from_ipq,
2686db2661ceSRobert Watson 	.mpo_create_fragment = mac_lomac_create_fragment,
2687db2661ceSRobert Watson 	.mpo_create_ifnet = mac_lomac_create_ifnet,
2688db2661ceSRobert Watson 	.mpo_create_ipq = mac_lomac_create_ipq,
2689db2661ceSRobert Watson 	.mpo_create_mbuf_from_mbuf = mac_lomac_create_mbuf_from_mbuf,
2690db2661ceSRobert Watson 	.mpo_create_mbuf_linklayer = mac_lomac_create_mbuf_linklayer,
2691db2661ceSRobert Watson 	.mpo_create_mbuf_from_bpfdesc = mac_lomac_create_mbuf_from_bpfdesc,
2692db2661ceSRobert Watson 	.mpo_create_mbuf_from_ifnet = mac_lomac_create_mbuf_from_ifnet,
2693db2661ceSRobert Watson 	.mpo_create_mbuf_multicast_encap =
2694db2661ceSRobert Watson 	    mac_lomac_create_mbuf_multicast_encap,
2695db2661ceSRobert Watson 	.mpo_create_mbuf_netlayer = mac_lomac_create_mbuf_netlayer,
2696db2661ceSRobert Watson 	.mpo_fragment_match = mac_lomac_fragment_match,
2697db2661ceSRobert Watson 	.mpo_relabel_ifnet = mac_lomac_relabel_ifnet,
2698db2661ceSRobert Watson 	.mpo_update_ipq = mac_lomac_update_ipq,
2699db2661ceSRobert Watson 	.mpo_create_cred = mac_lomac_create_cred,
2700db2661ceSRobert Watson 	.mpo_execve_transition = mac_lomac_execve_transition,
2701db2661ceSRobert Watson 	.mpo_execve_will_transition = mac_lomac_execve_will_transition,
2702db2661ceSRobert Watson 	.mpo_create_proc0 = mac_lomac_create_proc0,
2703db2661ceSRobert Watson 	.mpo_create_proc1 = mac_lomac_create_proc1,
2704db2661ceSRobert Watson 	.mpo_relabel_cred = mac_lomac_relabel_cred,
2705db2661ceSRobert Watson 	.mpo_check_bpfdesc_receive = mac_lomac_check_bpfdesc_receive,
2706db2661ceSRobert Watson 	.mpo_check_cred_relabel = mac_lomac_check_cred_relabel,
2707db2661ceSRobert Watson 	.mpo_check_cred_visible = mac_lomac_check_cred_visible,
2708db2661ceSRobert Watson 	.mpo_check_ifnet_relabel = mac_lomac_check_ifnet_relabel,
2709db2661ceSRobert Watson 	.mpo_check_ifnet_transmit = mac_lomac_check_ifnet_transmit,
2710db2661ceSRobert Watson 	.mpo_check_kld_load = mac_lomac_check_kld_load,
2711db2661ceSRobert Watson 	.mpo_check_kld_unload = mac_lomac_check_kld_unload,
2712db2661ceSRobert Watson 	.mpo_check_pipe_ioctl = mac_lomac_check_pipe_ioctl,
2713db2661ceSRobert Watson 	.mpo_check_pipe_read = mac_lomac_check_pipe_read,
2714db2661ceSRobert Watson 	.mpo_check_pipe_relabel = mac_lomac_check_pipe_relabel,
2715db2661ceSRobert Watson 	.mpo_check_pipe_write = mac_lomac_check_pipe_write,
2716db2661ceSRobert Watson 	.mpo_check_proc_debug = mac_lomac_check_proc_debug,
2717db2661ceSRobert Watson 	.mpo_check_proc_sched = mac_lomac_check_proc_sched,
2718db2661ceSRobert Watson 	.mpo_check_proc_signal = mac_lomac_check_proc_signal,
2719db2661ceSRobert Watson 	.mpo_check_socket_deliver = mac_lomac_check_socket_deliver,
2720db2661ceSRobert Watson 	.mpo_check_socket_relabel = mac_lomac_check_socket_relabel,
2721db2661ceSRobert Watson 	.mpo_check_socket_visible = mac_lomac_check_socket_visible,
2722db2661ceSRobert Watson 	.mpo_check_system_swapon = mac_lomac_check_system_swapon,
2723db2661ceSRobert Watson 	.mpo_check_system_sysctl = mac_lomac_check_system_sysctl,
2724db2661ceSRobert Watson 	.mpo_check_vnode_access = mac_lomac_check_vnode_open,
2725db2661ceSRobert Watson 	.mpo_check_vnode_create = mac_lomac_check_vnode_create,
2726db2661ceSRobert Watson 	.mpo_check_vnode_delete = mac_lomac_check_vnode_delete,
2727db2661ceSRobert Watson 	.mpo_check_vnode_deleteacl = mac_lomac_check_vnode_deleteacl,
2728db2661ceSRobert Watson 	.mpo_check_vnode_link = mac_lomac_check_vnode_link,
2729db2661ceSRobert Watson 	.mpo_check_vnode_mmap = mac_lomac_check_vnode_mmap,
2730db2661ceSRobert Watson 	.mpo_check_vnode_mmap_downgrade = mac_lomac_check_vnode_mmap_downgrade,
2731db2661ceSRobert Watson 	.mpo_check_vnode_mprotect = mac_lomac_check_vnode_mprotect,
2732db2661ceSRobert Watson 	.mpo_check_vnode_open = mac_lomac_check_vnode_open,
2733db2661ceSRobert Watson 	.mpo_check_vnode_read = mac_lomac_check_vnode_read,
2734db2661ceSRobert Watson 	.mpo_check_vnode_relabel = mac_lomac_check_vnode_relabel,
2735db2661ceSRobert Watson 	.mpo_check_vnode_rename_from = mac_lomac_check_vnode_rename_from,
2736db2661ceSRobert Watson 	.mpo_check_vnode_rename_to = mac_lomac_check_vnode_rename_to,
2737db2661ceSRobert Watson 	.mpo_check_vnode_revoke = mac_lomac_check_vnode_revoke,
2738db2661ceSRobert Watson 	.mpo_check_vnode_setacl = mac_lomac_check_vnode_setacl,
2739db2661ceSRobert Watson 	.mpo_check_vnode_setextattr = mac_lomac_check_vnode_setextattr,
2740db2661ceSRobert Watson 	.mpo_check_vnode_setflags = mac_lomac_check_vnode_setflags,
2741db2661ceSRobert Watson 	.mpo_check_vnode_setmode = mac_lomac_check_vnode_setmode,
2742db2661ceSRobert Watson 	.mpo_check_vnode_setowner = mac_lomac_check_vnode_setowner,
2743db2661ceSRobert Watson 	.mpo_check_vnode_setutimes = mac_lomac_check_vnode_setutimes,
2744db2661ceSRobert Watson 	.mpo_check_vnode_write = mac_lomac_check_vnode_write,
2745db2661ceSRobert Watson 	.mpo_thread_userret = mac_lomac_thread_userret,
2746db2661ceSRobert Watson };
2747db2661ceSRobert Watson 
2748db2661ceSRobert Watson MAC_POLICY_SET(&mac_lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
2749db2661ceSRobert Watson     MPC_LOADTIME_FLAG_NOTLATE, &mac_lomac_slot);
2750