mac_lomac.c revision 187016
1107273Srwatson/*-
2184308Srwatson * Copyright (c) 1999-2002, 2007-2008 Robert N. M. Watson
3140879Srwatson * Copyright (c) 2001-2005 Networks Associates Technology, Inc.
4172930Srwatson * Copyright (c) 2006 SPARTA, Inc.
5107273Srwatson * All rights reserved.
6107273Srwatson *
7107273Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
8107273Srwatson *
9107273Srwatson * This software was developed for the FreeBSD Project in part by NAI Labs,
10107273Srwatson * the Security Research Division of Network Associates, Inc. under
11107273Srwatson * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12107273Srwatson * CHATS research program.
13107273Srwatson *
14172930Srwatson * This software was enhanced by SPARTA ISSO under SPAWAR contract
15172930Srwatson * N66001-04-C-6019 ("SEFOS").
16172930Srwatson *
17107273Srwatson * Redistribution and use in source and binary forms, with or without
18107273Srwatson * modification, are permitted provided that the following conditions
19107273Srwatson * are met:
20107273Srwatson * 1. Redistributions of source code must retain the above copyright
21107273Srwatson *    notice, this list of conditions and the following disclaimer.
22107273Srwatson * 2. Redistributions in binary form must reproduce the above copyright
23107273Srwatson *    notice, this list of conditions and the following disclaimer in the
24107273Srwatson *    documentation and/or other materials provided with the distribution.
25107273Srwatson *
26107273Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
27107273Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
28107273Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
29107273Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
30107273Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
31107273Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
32107273Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
33107273Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
34107273Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
35107273Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
36107273Srwatson * SUCH DAMAGE.
37107273Srwatson *
38107273Srwatson * $FreeBSD: head/sys/security/mac_lomac/mac_lomac.c 187016 2009-01-10 10:58:41Z rwatson $
39107273Srwatson */
40107273Srwatson
41107273Srwatson/*
42107273Srwatson * Developed by the TrustedBSD Project.
43168951Srwatson *
44107273Srwatson * Low-watermark floating label mandatory integrity policy.
45107273Srwatson */
46107273Srwatson
47107273Srwatson#include <sys/types.h>
48107273Srwatson#include <sys/param.h>
49107273Srwatson#include <sys/acl.h>
50107273Srwatson#include <sys/conf.h>
51107273Srwatson#include <sys/extattr.h>
52107273Srwatson#include <sys/kernel.h>
53107273Srwatson#include <sys/malloc.h>
54145076Scsjp#include <sys/mman.h>
55107273Srwatson#include <sys/mount.h>
56164033Srwatson#include <sys/priv.h>
57107273Srwatson#include <sys/proc.h>
58116701Srwatson#include <sys/sbuf.h>
59107273Srwatson#include <sys/systm.h>
60107273Srwatson#include <sys/sysproto.h>
61107273Srwatson#include <sys/sysent.h>
62107273Srwatson#include <sys/systm.h>
63107273Srwatson#include <sys/vnode.h>
64107273Srwatson#include <sys/file.h>
65107273Srwatson#include <sys/socket.h>
66107273Srwatson#include <sys/socketvar.h>
67150340Sphk#include <sys/sx.h>
68107273Srwatson#include <sys/pipe.h>
69107273Srwatson#include <sys/sysctl.h>
70107273Srwatson#include <sys/syslog.h>
71107273Srwatson
72107273Srwatson#include <fs/devfs/devfs.h>
73107273Srwatson
74107273Srwatson#include <net/bpfdesc.h>
75107273Srwatson#include <net/if.h>
76107273Srwatson#include <net/if_types.h>
77107273Srwatson#include <net/if_var.h>
78107273Srwatson
79107273Srwatson#include <netinet/in.h>
80122875Srwatson#include <netinet/in_pcb.h>
81107273Srwatson#include <netinet/ip_var.h>
82107273Srwatson
83107273Srwatson#include <vm/vm.h>
84107273Srwatson
85165469Srwatson#include <security/mac/mac_policy.h>
86163606Srwatson#include <security/mac/mac_framework.h>
87107273Srwatson#include <security/mac_lomac/mac_lomac.h>
88107273Srwatson
89107273Srwatsonstruct mac_lomac_proc {
90107273Srwatson	struct mac_lomac mac_lomac;
91107273Srwatson	struct mtx mtx;
92107273Srwatson};
93107273Srwatson
94107273SrwatsonSYSCTL_DECL(_security_mac);
95107273Srwatson
96107273SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, lomac, CTLFLAG_RW, 0,
97107273Srwatson    "TrustedBSD mac_lomac policy controls");
98107273Srwatson
99172955Srwatsonstatic int	lomac_label_size = sizeof(struct mac_lomac);
100107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, label_size, CTLFLAG_RD,
101172955Srwatson    &lomac_label_size, 0, "Size of struct mac_lomac");
102107273Srwatson
103172955Srwatsonstatic int	lomac_enabled = 1;
104107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, enabled, CTLFLAG_RW,
105172955Srwatson    &lomac_enabled, 0, "Enforce MAC/LOMAC policy");
106172955SrwatsonTUNABLE_INT("security.mac.lomac.enabled", &lomac_enabled);
107107273Srwatson
108107273Srwatsonstatic int	destroyed_not_inited;
109107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
110107273Srwatson    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
111107273Srwatson
112107273Srwatsonstatic int	trust_all_interfaces = 0;
113107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
114107273Srwatson    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/LOMAC");
115107273SrwatsonTUNABLE_INT("security.mac.lomac.trust_all_interfaces", &trust_all_interfaces);
116107273Srwatson
117107273Srwatsonstatic char	trusted_interfaces[128];
118107273SrwatsonSYSCTL_STRING(_security_mac_lomac, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
119107273Srwatson    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/LOMAC");
120107273SrwatsonTUNABLE_STR("security.mac.lomac.trusted_interfaces", trusted_interfaces,
121107273Srwatson    sizeof(trusted_interfaces));
122107273Srwatson
123107273Srwatsonstatic int	ptys_equal = 0;
124107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, ptys_equal, CTLFLAG_RW,
125107273Srwatson    &ptys_equal, 0, "Label pty devices as lomac/equal on create");
126107273SrwatsonTUNABLE_INT("security.mac.lomac.ptys_equal", &ptys_equal);
127107273Srwatson
128107273Srwatsonstatic int	revocation_enabled = 1;
129107273SrwatsonSYSCTL_INT(_security_mac_lomac, OID_AUTO, revocation_enabled, CTLFLAG_RW,
130107273Srwatson    &revocation_enabled, 0, "Revoke access to objects on relabel");
131107273SrwatsonTUNABLE_INT("security.mac.lomac.revocation_enabled", &revocation_enabled);
132107273Srwatson
133172955Srwatsonstatic int	lomac_slot;
134172955Srwatson#define	SLOT(l)	((struct mac_lomac *)mac_label_get((l), lomac_slot))
135172955Srwatson#define	SLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val))
136107273Srwatson#define	PSLOT(l) ((struct mac_lomac_proc *)				\
137172955Srwatson    mac_label_get((l), lomac_slot))
138172955Srwatson#define	PSLOT_SET(l, val) mac_label_set((l), lomac_slot, (uintptr_t)(val))
139107273Srwatson
140172955SrwatsonMALLOC_DEFINE(M_LOMAC, "mac_lomac_label", "MAC/LOMAC labels");
141107273Srwatson
142107273Srwatsonstatic struct mac_lomac *
143107273Srwatsonlomac_alloc(int flag)
144107273Srwatson{
145172955Srwatson	struct mac_lomac *ml;
146107273Srwatson
147172955Srwatson	ml = malloc(sizeof(*ml), M_LOMAC, M_ZERO | flag);
148107273Srwatson
149172955Srwatson	return (ml);
150107273Srwatson}
151107273Srwatson
152107273Srwatsonstatic void
153172955Srwatsonlomac_free(struct mac_lomac *ml)
154107273Srwatson{
155107273Srwatson
156172955Srwatson	if (ml != NULL)
157172955Srwatson		free(ml, M_LOMAC);
158107273Srwatson	else
159107273Srwatson		atomic_add_int(&destroyed_not_inited, 1);
160107273Srwatson}
161107273Srwatson
162107273Srwatsonstatic int
163172955Srwatsonlomac_atmostflags(struct mac_lomac *ml, int flags)
164107273Srwatson{
165107273Srwatson
166172955Srwatson	if ((ml->ml_flags & flags) != ml->ml_flags)
167107273Srwatson		return (EINVAL);
168107273Srwatson	return (0);
169107273Srwatson}
170107273Srwatson
171107273Srwatsonstatic int
172172955Srwatsonlomac_dominate_element(struct mac_lomac_element *a,
173107273Srwatson    struct mac_lomac_element *b)
174107273Srwatson{
175107273Srwatson
176107273Srwatson	switch (a->mle_type) {
177107273Srwatson	case MAC_LOMAC_TYPE_EQUAL:
178107273Srwatson	case MAC_LOMAC_TYPE_HIGH:
179107273Srwatson		return (1);
180107273Srwatson
181107273Srwatson	case MAC_LOMAC_TYPE_LOW:
182107273Srwatson		switch (b->mle_type) {
183107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
184107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
185107273Srwatson			return (0);
186107273Srwatson
187107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
188107273Srwatson		case MAC_LOMAC_TYPE_LOW:
189107273Srwatson			return (1);
190107273Srwatson
191107273Srwatson		default:
192172955Srwatson			panic("lomac_dominate_element: b->mle_type invalid");
193107273Srwatson		}
194107273Srwatson
195107273Srwatson	case MAC_LOMAC_TYPE_GRADE:
196107273Srwatson		switch (b->mle_type) {
197107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
198107273Srwatson		case MAC_LOMAC_TYPE_LOW:
199107273Srwatson			return (1);
200107273Srwatson
201107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
202107273Srwatson			return (0);
203107273Srwatson
204107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
205107273Srwatson			return (a->mle_grade >= b->mle_grade);
206107273Srwatson
207107273Srwatson		default:
208172955Srwatson			panic("lomac_dominate_element: b->mle_type invalid");
209107273Srwatson		}
210107273Srwatson
211107273Srwatson	default:
212172955Srwatson		panic("lomac_dominate_element: a->mle_type invalid");
213107273Srwatson	}
214107273Srwatson}
215107273Srwatson
216107273Srwatsonstatic int
217172955Srwatsonlomac_range_in_range(struct mac_lomac *rangea, struct mac_lomac *rangeb)
218107273Srwatson{
219107273Srwatson
220172955Srwatson	return (lomac_dominate_element(&rangeb->ml_rangehigh,
221107273Srwatson	    &rangea->ml_rangehigh) &&
222172955Srwatson	    lomac_dominate_element(&rangea->ml_rangelow,
223107273Srwatson	    &rangeb->ml_rangelow));
224107273Srwatson}
225107273Srwatson
226107273Srwatsonstatic int
227172955Srwatsonlomac_single_in_range(struct mac_lomac *single, struct mac_lomac *range)
228107273Srwatson{
229107273Srwatson
230107273Srwatson	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
231172955Srwatson	    ("lomac_single_in_range: a not single"));
232107273Srwatson	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
233172955Srwatson	    ("lomac_single_in_range: b not range"));
234107273Srwatson
235172955Srwatson	return (lomac_dominate_element(&range->ml_rangehigh,
236172955Srwatson	    &single->ml_single) && lomac_dominate_element(&single->ml_single,
237107273Srwatson	    &range->ml_rangelow));
238107273Srwatson}
239107273Srwatson
240107273Srwatsonstatic int
241172955Srwatsonlomac_auxsingle_in_range(struct mac_lomac *single, struct mac_lomac *range)
242107273Srwatson{
243107273Srwatson
244107273Srwatson	KASSERT((single->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
245172955Srwatson	    ("lomac_single_in_range: a not auxsingle"));
246107273Srwatson	KASSERT((range->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
247172955Srwatson	    ("lomac_single_in_range: b not range"));
248107273Srwatson
249172955Srwatson	return (lomac_dominate_element(&range->ml_rangehigh,
250107273Srwatson	    &single->ml_auxsingle) &&
251172955Srwatson	    lomac_dominate_element(&single->ml_auxsingle,
252107273Srwatson	    &range->ml_rangelow));
253107273Srwatson}
254107273Srwatson
255107273Srwatsonstatic int
256172955Srwatsonlomac_dominate_single(struct mac_lomac *a, struct mac_lomac *b)
257107273Srwatson{
258107273Srwatson	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
259172955Srwatson	    ("lomac_dominate_single: a not single"));
260107273Srwatson	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
261172955Srwatson	    ("lomac_dominate_single: b not single"));
262107273Srwatson
263172955Srwatson	return (lomac_dominate_element(&a->ml_single, &b->ml_single));
264107273Srwatson}
265107273Srwatson
266107273Srwatsonstatic int
267172955Srwatsonlomac_subject_dominate(struct mac_lomac *a, struct mac_lomac *b)
268107273Srwatson{
269107273Srwatson	KASSERT((~a->ml_flags &
270107273Srwatson	    (MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_RANGE)) == 0,
271172955Srwatson	    ("lomac_dominate_single: a not subject"));
272107273Srwatson	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
273172955Srwatson	    ("lomac_dominate_single: b not single"));
274107273Srwatson
275172955Srwatson	return (lomac_dominate_element(&a->ml_rangehigh, &b->ml_single));
276107273Srwatson}
277107273Srwatson
278107273Srwatsonstatic int
279172955Srwatsonlomac_equal_element(struct mac_lomac_element *a, struct mac_lomac_element *b)
280107273Srwatson{
281107273Srwatson
282107273Srwatson	if (a->mle_type == MAC_LOMAC_TYPE_EQUAL ||
283107273Srwatson	    b->mle_type == MAC_LOMAC_TYPE_EQUAL)
284107273Srwatson		return (1);
285107273Srwatson
286107273Srwatson	return (a->mle_type == b->mle_type && a->mle_grade == b->mle_grade);
287107273Srwatson}
288107273Srwatson
289107273Srwatsonstatic int
290172955Srwatsonlomac_equal_single(struct mac_lomac *a, struct mac_lomac *b)
291107273Srwatson{
292107273Srwatson
293107273Srwatson	KASSERT((a->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
294172955Srwatson	    ("lomac_equal_single: a not single"));
295107273Srwatson	KASSERT((b->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
296172955Srwatson	    ("lomac_equal_single: b not single"));
297107273Srwatson
298172955Srwatson	return (lomac_equal_element(&a->ml_single, &b->ml_single));
299107273Srwatson}
300107273Srwatson
301107273Srwatsonstatic int
302172955Srwatsonlomac_contains_equal(struct mac_lomac *ml)
303107273Srwatson{
304107273Srwatson
305172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE)
306172955Srwatson		if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
307107273Srwatson			return (1);
308172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX)
309172955Srwatson		if (ml->ml_auxsingle.mle_type == MAC_LOMAC_TYPE_EQUAL)
310107273Srwatson			return (1);
311107273Srwatson
312172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
313172955Srwatson		if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL)
314107273Srwatson			return (1);
315172955Srwatson		if (ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
316107273Srwatson			return (1);
317107273Srwatson	}
318107273Srwatson
319107273Srwatson	return (0);
320107273Srwatson}
321107273Srwatson
322107273Srwatsonstatic int
323172955Srwatsonlomac_subject_privileged(struct mac_lomac *ml)
324107273Srwatson{
325107273Srwatson
326172955Srwatson	KASSERT((ml->ml_flags & MAC_LOMAC_FLAGS_BOTH) ==
327107273Srwatson	    MAC_LOMAC_FLAGS_BOTH,
328172955Srwatson	    ("lomac_subject_privileged: subject doesn't have both labels"));
329107273Srwatson
330107273Srwatson	/* If the single is EQUAL, it's ok. */
331172955Srwatson	if (ml->ml_single.mle_type == MAC_LOMAC_TYPE_EQUAL)
332107273Srwatson		return (0);
333107273Srwatson
334107273Srwatson	/* If either range endpoint is EQUAL, it's ok. */
335172955Srwatson	if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_EQUAL ||
336172955Srwatson	    ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_EQUAL)
337107273Srwatson		return (0);
338107273Srwatson
339107273Srwatson	/* If the range is low-high, it's ok. */
340172955Srwatson	if (ml->ml_rangelow.mle_type == MAC_LOMAC_TYPE_LOW &&
341172955Srwatson	    ml->ml_rangehigh.mle_type == MAC_LOMAC_TYPE_HIGH)
342107273Srwatson		return (0);
343107273Srwatson
344107273Srwatson	/* It's not ok. */
345107273Srwatson	return (EPERM);
346107273Srwatson}
347107273Srwatson
348107273Srwatsonstatic int
349172955Srwatsonlomac_high_single(struct mac_lomac *ml)
350107273Srwatson{
351107273Srwatson
352172955Srwatson	KASSERT((ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
353172955Srwatson	    ("lomac_high_single: mac_lomac not single"));
354117247Srwatson
355172955Srwatson	return (ml->ml_single.mle_type == MAC_LOMAC_TYPE_HIGH);
356107273Srwatson}
357107273Srwatson
358107273Srwatsonstatic int
359172955Srwatsonlomac_valid(struct mac_lomac *ml)
360107273Srwatson{
361107273Srwatson
362172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
363172955Srwatson		switch (ml->ml_single.mle_type) {
364107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
365107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
366107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
367107273Srwatson		case MAC_LOMAC_TYPE_LOW:
368107273Srwatson			break;
369107273Srwatson
370107273Srwatson		default:
371107273Srwatson			return (EINVAL);
372107273Srwatson		}
373107273Srwatson	} else {
374172955Srwatson		if (ml->ml_single.mle_type != MAC_LOMAC_TYPE_UNDEF)
375107273Srwatson			return (EINVAL);
376107273Srwatson	}
377107273Srwatson
378172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) {
379172955Srwatson		switch (ml->ml_auxsingle.mle_type) {
380107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
381107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
382107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
383107273Srwatson		case MAC_LOMAC_TYPE_LOW:
384107273Srwatson			break;
385107273Srwatson
386107273Srwatson		default:
387107273Srwatson			return (EINVAL);
388107273Srwatson		}
389107273Srwatson	} else {
390172955Srwatson		if (ml->ml_auxsingle.mle_type != MAC_LOMAC_TYPE_UNDEF)
391107273Srwatson			return (EINVAL);
392107273Srwatson	}
393107273Srwatson
394172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
395172955Srwatson		switch (ml->ml_rangelow.mle_type) {
396107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
397107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
398107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
399107273Srwatson		case MAC_LOMAC_TYPE_LOW:
400107273Srwatson			break;
401107273Srwatson
402107273Srwatson		default:
403107273Srwatson			return (EINVAL);
404107273Srwatson		}
405107273Srwatson
406172955Srwatson		switch (ml->ml_rangehigh.mle_type) {
407107273Srwatson		case MAC_LOMAC_TYPE_GRADE:
408107273Srwatson		case MAC_LOMAC_TYPE_EQUAL:
409107273Srwatson		case MAC_LOMAC_TYPE_HIGH:
410107273Srwatson		case MAC_LOMAC_TYPE_LOW:
411107273Srwatson			break;
412107273Srwatson
413107273Srwatson		default:
414107273Srwatson			return (EINVAL);
415107273Srwatson		}
416172955Srwatson		if (!lomac_dominate_element(&ml->ml_rangehigh,
417172955Srwatson		    &ml->ml_rangelow))
418107273Srwatson			return (EINVAL);
419107273Srwatson	} else {
420172955Srwatson		if (ml->ml_rangelow.mle_type != MAC_LOMAC_TYPE_UNDEF ||
421172955Srwatson		    ml->ml_rangehigh.mle_type != MAC_LOMAC_TYPE_UNDEF)
422107273Srwatson			return (EINVAL);
423107273Srwatson	}
424107273Srwatson
425107273Srwatson	return (0);
426107273Srwatson}
427107273Srwatson
428107273Srwatsonstatic void
429172955Srwatsonlomac_set_range(struct mac_lomac *ml, u_short typelow, u_short gradelow,
430172955Srwatson    u_short typehigh, u_short gradehigh)
431107273Srwatson{
432107273Srwatson
433172955Srwatson	ml->ml_rangelow.mle_type = typelow;
434172955Srwatson	ml->ml_rangelow.mle_grade = gradelow;
435172955Srwatson	ml->ml_rangehigh.mle_type = typehigh;
436172955Srwatson	ml->ml_rangehigh.mle_grade = gradehigh;
437172955Srwatson	ml->ml_flags |= MAC_LOMAC_FLAG_RANGE;
438107273Srwatson}
439107273Srwatson
440107273Srwatsonstatic void
441172955Srwatsonlomac_set_single(struct mac_lomac *ml, u_short type, u_short grade)
442107273Srwatson{
443107273Srwatson
444172955Srwatson	ml->ml_single.mle_type = type;
445172955Srwatson	ml->ml_single.mle_grade = grade;
446172955Srwatson	ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
447107273Srwatson}
448107273Srwatson
449107273Srwatsonstatic void
450172955Srwatsonlomac_copy_range(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
451107273Srwatson{
452107273Srwatson
453107273Srwatson	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_RANGE) != 0,
454172955Srwatson	    ("lomac_copy_range: labelfrom not range"));
455107273Srwatson
456107273Srwatson	labelto->ml_rangelow = labelfrom->ml_rangelow;
457107273Srwatson	labelto->ml_rangehigh = labelfrom->ml_rangehigh;
458107273Srwatson	labelto->ml_flags |= MAC_LOMAC_FLAG_RANGE;
459107273Srwatson}
460107273Srwatson
461107273Srwatsonstatic void
462172955Srwatsonlomac_copy_single(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
463107273Srwatson{
464107273Srwatson
465107273Srwatson	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_SINGLE) != 0,
466172955Srwatson	    ("lomac_copy_single: labelfrom not single"));
467107273Srwatson
468107273Srwatson	labelto->ml_single = labelfrom->ml_single;
469107273Srwatson	labelto->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
470107273Srwatson}
471107273Srwatson
472107273Srwatsonstatic void
473172955Srwatsonlomac_copy_auxsingle(struct mac_lomac *labelfrom, struct mac_lomac *labelto)
474107273Srwatson{
475107273Srwatson
476107273Srwatson	KASSERT((labelfrom->ml_flags & MAC_LOMAC_FLAG_AUX) != 0,
477172955Srwatson	    ("lomac_copy_auxsingle: labelfrom not auxsingle"));
478107273Srwatson
479107273Srwatson	labelto->ml_auxsingle = labelfrom->ml_auxsingle;
480107273Srwatson	labelto->ml_flags |= MAC_LOMAC_FLAG_AUX;
481107273Srwatson}
482107273Srwatson
483107273Srwatsonstatic void
484172955Srwatsonlomac_copy(struct mac_lomac *source, struct mac_lomac *dest)
485107273Srwatson{
486107273Srwatson
487107273Srwatson	if (source->ml_flags & MAC_LOMAC_FLAG_SINGLE)
488172955Srwatson		lomac_copy_single(source, dest);
489107273Srwatson	if (source->ml_flags & MAC_LOMAC_FLAG_AUX)
490172955Srwatson		lomac_copy_auxsingle(source, dest);
491107273Srwatson	if (source->ml_flags & MAC_LOMAC_FLAG_RANGE)
492172955Srwatson		lomac_copy_range(source, dest);
493107273Srwatson}
494107273Srwatson
495172955Srwatsonstatic int	lomac_to_string(struct sbuf *sb, struct mac_lomac *ml);
496107273Srwatson
497107273Srwatsonstatic int
498107273Srwatsonmaybe_demote(struct mac_lomac *subjlabel, struct mac_lomac *objlabel,
499168976Srwatson    const char *actionname, const char *objname, struct vnode *vp)
500107273Srwatson{
501116701Srwatson	struct sbuf subjlabel_sb, subjtext_sb, objlabel_sb;
502116701Srwatson	char *subjlabeltext, *objlabeltext, *subjtext;
503116701Srwatson	struct mac_lomac cached_subjlabel;
504116701Srwatson	struct mac_lomac_proc *subj;
505107273Srwatson	struct vattr va;
506107273Srwatson	struct proc *p;
507107273Srwatson	pid_t pgid;
508107273Srwatson
509122524Srwatson	subj = PSLOT(curthread->td_proc->p_label);
510116701Srwatson
511107273Srwatson	p = curthread->td_proc;
512107273Srwatson	mtx_lock(&subj->mtx);
513107273Srwatson        if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
514107273Srwatson		/*
515172955Srwatson		 * Check to see if the pending demotion would be more or less
516172955Srwatson		 * severe than this one, and keep the more severe.  This can
517172955Srwatson		 * only happen for a multi-threaded application.
518107273Srwatson		 */
519172955Srwatson		if (lomac_dominate_single(objlabel, &subj->mac_lomac)) {
520107273Srwatson			mtx_unlock(&subj->mtx);
521107273Srwatson			return (0);
522107273Srwatson		}
523107273Srwatson	}
524107273Srwatson	bzero(&subj->mac_lomac, sizeof(subj->mac_lomac));
525107273Srwatson	/*
526107273Srwatson	 * Always demote the single label.
527107273Srwatson	 */
528172955Srwatson	lomac_copy_single(objlabel, &subj->mac_lomac);
529107273Srwatson	/*
530172955Srwatson	 * Start with the original range, then minimize each side of the
531172955Srwatson	 * range to the point of not dominating the object.  The high side
532172955Srwatson	 * will always be demoted, of course.
533107273Srwatson	 */
534172955Srwatson	lomac_copy_range(subjlabel, &subj->mac_lomac);
535172955Srwatson	if (!lomac_dominate_element(&objlabel->ml_single,
536107273Srwatson	    &subj->mac_lomac.ml_rangelow))
537107273Srwatson		subj->mac_lomac.ml_rangelow = objlabel->ml_single;
538107273Srwatson	subj->mac_lomac.ml_rangehigh = objlabel->ml_single;
539107273Srwatson	subj->mac_lomac.ml_flags |= MAC_LOMAC_FLAG_UPDATE;
540170307Sjeff	thread_lock(curthread);
541172207Sjeff	curthread->td_flags |= TDF_ASTPENDING | TDF_MACPEND;
542170307Sjeff	thread_unlock(curthread);
543116701Srwatson
544116701Srwatson	/*
545172955Srwatson	 * Avoid memory allocation while holding a mutex; cache the label.
546116701Srwatson	 */
547172955Srwatson	lomac_copy_single(&subj->mac_lomac, &cached_subjlabel);
548107273Srwatson	mtx_unlock(&subj->mtx);
549116701Srwatson
550116701Srwatson	sbuf_new(&subjlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
551172955Srwatson	lomac_to_string(&subjlabel_sb, subjlabel);
552116701Srwatson	sbuf_finish(&subjlabel_sb);
553116701Srwatson	subjlabeltext = sbuf_data(&subjlabel_sb);
554116701Srwatson
555116701Srwatson	sbuf_new(&subjtext_sb, NULL, 0, SBUF_AUTOEXTEND);
556172955Srwatson	lomac_to_string(&subjtext_sb, &subj->mac_lomac);
557116701Srwatson	sbuf_finish(&subjtext_sb);
558116701Srwatson	subjtext = sbuf_data(&subjtext_sb);
559116701Srwatson
560116701Srwatson	sbuf_new(&objlabel_sb, NULL, 0, SBUF_AUTOEXTEND);
561172955Srwatson	lomac_to_string(&objlabel_sb, objlabel);
562116701Srwatson	sbuf_finish(&objlabel_sb);
563116701Srwatson	objlabeltext = sbuf_data(&objlabel_sb);
564116701Srwatson
565107273Srwatson	pgid = p->p_pgrp->pg_id;		/* XXX could be stale? */
566182371Sattilio	if (vp != NULL && VOP_GETATTR(vp, &va, curthread->td_ucred) == 0) {
567107273Srwatson		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
568107273Srwatson		    " level %s after %s a level-%s %s (inode=%ld, "
569107273Srwatson		    "mountpount=%s)\n",
570107273Srwatson		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
571107273Srwatson		    p->p_comm, subjtext, actionname, objlabeltext, objname,
572168976Srwatson		    va.va_fileid, vp->v_mount->mnt_stat.f_mntonname);
573107273Srwatson	} else {
574107273Srwatson		log(LOG_INFO, "LOMAC: level-%s subject p%dg%du%d:%s demoted to"
575107273Srwatson		    " level %s after %s a level-%s %s\n",
576107273Srwatson		    subjlabeltext, p->p_pid, pgid, curthread->td_ucred->cr_uid,
577107273Srwatson		    p->p_comm, subjtext, actionname, objlabeltext, objname);
578107273Srwatson	}
579116701Srwatson
580116701Srwatson	sbuf_delete(&subjlabel_sb);
581116701Srwatson	sbuf_delete(&subjtext_sb);
582116701Srwatson	sbuf_delete(&objlabel_sb);
583107273Srwatson
584107273Srwatson	return (0);
585107273Srwatson}
586107273Srwatson
587107273Srwatson/*
588172955Srwatson * Relabel "to" to "from" only if "from" is a valid label (contains at least
589172955Srwatson * a single), as for a relabel operation which may or may not involve a
590172955Srwatson * relevant label.
591107273Srwatson */
592107279Srwatsonstatic void
593107273Srwatsontry_relabel(struct mac_lomac *from, struct mac_lomac *to)
594107273Srwatson{
595107273Srwatson
596107273Srwatson	if (from->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
597107273Srwatson		bzero(to, sizeof(*to));
598172955Srwatson		lomac_copy(from, to);
599107273Srwatson	}
600107273Srwatson}
601107273Srwatson
602107273Srwatson/*
603107273Srwatson * Policy module operations.
604107273Srwatson */
605107273Srwatsonstatic void
606172955Srwatsonlomac_init(struct mac_policy_conf *conf)
607107273Srwatson{
608107273Srwatson
609107273Srwatson}
610107273Srwatson
611107273Srwatson/*
612107273Srwatson * Label operations.
613107273Srwatson */
614107273Srwatsonstatic void
615172955Srwatsonlomac_init_label(struct label *label)
616107273Srwatson{
617107273Srwatson
618132781Skan	SLOT_SET(label, lomac_alloc(M_WAITOK));
619107273Srwatson}
620107273Srwatson
621107273Srwatsonstatic int
622172955Srwatsonlomac_init_label_waitcheck(struct label *label, int flag)
623107273Srwatson{
624107273Srwatson
625132781Skan	SLOT_SET(label, lomac_alloc(flag));
626107273Srwatson	if (SLOT(label) == NULL)
627107273Srwatson		return (ENOMEM);
628107273Srwatson
629107273Srwatson	return (0);
630107273Srwatson}
631107273Srwatson
632107273Srwatsonstatic void
633172955Srwatsonlomac_destroy_label(struct label *label)
634107273Srwatson{
635107273Srwatson
636107273Srwatson	lomac_free(SLOT(label));
637132781Skan	SLOT_SET(label, NULL);
638107273Srwatson}
639107273Srwatson
640116701Srwatsonstatic int
641172955Srwatsonlomac_element_to_string(struct sbuf *sb, struct mac_lomac_element *element)
642107273Srwatson{
643107273Srwatson
644107273Srwatson	switch (element->mle_type) {
645107273Srwatson	case MAC_LOMAC_TYPE_HIGH:
646116701Srwatson		return (sbuf_printf(sb, "high"));
647107273Srwatson
648107273Srwatson	case MAC_LOMAC_TYPE_LOW:
649116701Srwatson		return (sbuf_printf(sb, "low"));
650107273Srwatson
651107273Srwatson	case MAC_LOMAC_TYPE_EQUAL:
652116701Srwatson		return (sbuf_printf(sb, "equal"));
653107273Srwatson
654107273Srwatson	case MAC_LOMAC_TYPE_GRADE:
655116701Srwatson		return (sbuf_printf(sb, "%d", element->mle_grade));
656107273Srwatson
657107273Srwatson	default:
658172955Srwatson		panic("lomac_element_to_string: invalid type (%d)",
659107273Srwatson		    element->mle_type);
660107273Srwatson	}
661107273Srwatson}
662107273Srwatson
663107273Srwatsonstatic int
664172955Srwatsonlomac_to_string(struct sbuf *sb, struct mac_lomac *ml)
665107273Srwatson{
666107273Srwatson
667172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
668172955Srwatson		if (lomac_element_to_string(sb, &ml->ml_single) == -1)
669116701Srwatson			return (EINVAL);
670107273Srwatson	}
671107273Srwatson
672172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_AUX) {
673116701Srwatson		if (sbuf_putc(sb, '[') == -1)
674116701Srwatson			return (EINVAL);
675107273Srwatson
676172955Srwatson		if (lomac_element_to_string(sb, &ml->ml_auxsingle) == -1)
677116701Srwatson			return (EINVAL);
678107273Srwatson
679116701Srwatson		if (sbuf_putc(sb, ']') == -1)
680116701Srwatson			return (EINVAL);
681107273Srwatson	}
682107273Srwatson
683172955Srwatson	if (ml->ml_flags & MAC_LOMAC_FLAG_RANGE) {
684116701Srwatson		if (sbuf_putc(sb, '(') == -1)
685116701Srwatson			return (EINVAL);
686107273Srwatson
687172955Srwatson		if (lomac_element_to_string(sb, &ml->ml_rangelow) == -1)
688116701Srwatson			return (EINVAL);
689107273Srwatson
690116701Srwatson		if (sbuf_putc(sb, '-') == -1)
691116701Srwatson			return (EINVAL);
692107273Srwatson
693172955Srwatson		if (lomac_element_to_string(sb, &ml->ml_rangehigh) == -1)
694116701Srwatson			return (EINVAL);
695107273Srwatson
696122270Srwatson		if (sbuf_putc(sb, ')') == -1)
697116701Srwatson			return (EINVAL);
698107273Srwatson	}
699107273Srwatson
700107273Srwatson	return (0);
701107273Srwatson}
702107273Srwatson
703107273Srwatsonstatic int
704172955Srwatsonlomac_externalize_label(struct label *label, char *element_name,
705116701Srwatson    struct sbuf *sb, int *claimed)
706107273Srwatson{
707172955Srwatson	struct mac_lomac *ml;
708107273Srwatson
709107273Srwatson	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
710107273Srwatson		return (0);
711107273Srwatson
712107273Srwatson	(*claimed)++;
713107273Srwatson
714172955Srwatson	ml = SLOT(label);
715107273Srwatson
716172955Srwatson	return (lomac_to_string(sb, ml));
717107273Srwatson}
718107273Srwatson
719107273Srwatsonstatic int
720172955Srwatsonlomac_parse_element(struct mac_lomac_element *element, char *string)
721107273Srwatson{
722107273Srwatson
723172955Srwatson	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
724107273Srwatson		element->mle_type = MAC_LOMAC_TYPE_HIGH;
725107273Srwatson		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
726172955Srwatson	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
727107273Srwatson		element->mle_type = MAC_LOMAC_TYPE_LOW;
728107273Srwatson		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
729181217Srwatson	} else if (strcmp(string, "equal") == 0 ||
730181217Srwatson	    strcmp(string, "eq") == 0) {
731107273Srwatson		element->mle_type = MAC_LOMAC_TYPE_EQUAL;
732107273Srwatson		element->mle_grade = MAC_LOMAC_TYPE_UNDEF;
733107273Srwatson	} else {
734107273Srwatson		char *p0, *p1;
735107273Srwatson		int d;
736107273Srwatson
737107273Srwatson		p0 = string;
738107273Srwatson		d = strtol(p0, &p1, 10);
739107273Srwatson
740107273Srwatson		if (d < 0 || d > 65535)
741107273Srwatson			return (EINVAL);
742107273Srwatson		element->mle_type = MAC_LOMAC_TYPE_GRADE;
743107273Srwatson		element->mle_grade = d;
744107273Srwatson
745107273Srwatson		if (p1 == p0 || *p1 != '\0')
746107273Srwatson			return (EINVAL);
747107273Srwatson	}
748107273Srwatson
749107273Srwatson	return (0);
750107273Srwatson}
751107273Srwatson
752107273Srwatson/*
753172955Srwatson * Note: destructively consumes the string, make a local copy before calling
754172955Srwatson * if that's a problem.
755107273Srwatson */
756107273Srwatsonstatic int
757172955Srwatsonlomac_parse(struct mac_lomac *ml, char *string)
758107273Srwatson{
759107273Srwatson	char *range, *rangeend, *rangehigh, *rangelow, *single, *auxsingle,
760107273Srwatson	    *auxsingleend;
761107273Srwatson	int error;
762107273Srwatson
763107273Srwatson	/* Do we have a range? */
764107273Srwatson	single = string;
765107273Srwatson	range = index(string, '(');
766107273Srwatson	if (range == single)
767107273Srwatson		single = NULL;
768107273Srwatson	auxsingle = index(string, '[');
769107273Srwatson	if (auxsingle == single)
770107273Srwatson		single = NULL;
771107273Srwatson	if (range != NULL && auxsingle != NULL)
772107273Srwatson		return (EINVAL);
773107273Srwatson	rangelow = rangehigh = NULL;
774107273Srwatson	if (range != NULL) {
775107273Srwatson		/* Nul terminate the end of the single string. */
776107273Srwatson		*range = '\0';
777107273Srwatson		range++;
778107273Srwatson		rangelow = range;
779107273Srwatson		rangehigh = index(rangelow, '-');
780107273Srwatson		if (rangehigh == NULL)
781107273Srwatson			return (EINVAL);
782107273Srwatson		rangehigh++;
783107273Srwatson		if (*rangelow == '\0' || *rangehigh == '\0')
784107273Srwatson			return (EINVAL);
785107273Srwatson		rangeend = index(rangehigh, ')');
786107273Srwatson		if (rangeend == NULL)
787107273Srwatson			return (EINVAL);
788107273Srwatson		if (*(rangeend + 1) != '\0')
789107273Srwatson			return (EINVAL);
790107273Srwatson		/* Nul terminate the ends of the ranges. */
791107273Srwatson		*(rangehigh - 1) = '\0';
792107273Srwatson		*rangeend = '\0';
793107273Srwatson	}
794107273Srwatson	KASSERT((rangelow != NULL && rangehigh != NULL) ||
795107273Srwatson	    (rangelow == NULL && rangehigh == NULL),
796172955Srwatson	    ("lomac_internalize_label: range mismatch"));
797107273Srwatson	if (auxsingle != NULL) {
798107273Srwatson		/* Nul terminate the end of the single string. */
799107273Srwatson		*auxsingle = '\0';
800107273Srwatson		auxsingle++;
801107273Srwatson		auxsingleend = index(auxsingle, ']');
802107273Srwatson		if (auxsingleend == NULL)
803107273Srwatson			return (EINVAL);
804107273Srwatson		if (*(auxsingleend + 1) != '\0')
805107273Srwatson			return (EINVAL);
806107273Srwatson		/* Nul terminate the end of the auxsingle. */
807107273Srwatson		*auxsingleend = '\0';
808107273Srwatson	}
809107273Srwatson
810172955Srwatson	bzero(ml, sizeof(*ml));
811107273Srwatson	if (single != NULL) {
812172955Srwatson		error = lomac_parse_element(&ml->ml_single, single);
813107273Srwatson		if (error)
814107273Srwatson			return (error);
815172955Srwatson		ml->ml_flags |= MAC_LOMAC_FLAG_SINGLE;
816107273Srwatson	}
817107273Srwatson
818107273Srwatson	if (auxsingle != NULL) {
819181217Srwatson		error = lomac_parse_element(&ml->ml_auxsingle, auxsingle);
820107273Srwatson		if (error)
821107273Srwatson			return (error);
822172955Srwatson		ml->ml_flags |= MAC_LOMAC_FLAG_AUX;
823107273Srwatson	}
824107273Srwatson
825107273Srwatson	if (rangelow != NULL) {
826172955Srwatson		error = lomac_parse_element(&ml->ml_rangelow, rangelow);
827107273Srwatson		if (error)
828107273Srwatson			return (error);
829172955Srwatson		error = lomac_parse_element(&ml->ml_rangehigh, rangehigh);
830107273Srwatson		if (error)
831107273Srwatson			return (error);
832172955Srwatson		ml->ml_flags |= MAC_LOMAC_FLAG_RANGE;
833107273Srwatson	}
834107273Srwatson
835172955Srwatson	error = lomac_valid(ml);
836107273Srwatson	if (error)
837107273Srwatson		return (error);
838107273Srwatson
839107273Srwatson	return (0);
840107273Srwatson}
841107273Srwatson
842107273Srwatsonstatic int
843172955Srwatsonlomac_internalize_label(struct label *label, char *element_name,
844107273Srwatson    char *element_data, int *claimed)
845107273Srwatson{
846172955Srwatson	struct mac_lomac *ml, ml_temp;
847107273Srwatson	int error;
848107273Srwatson
849107273Srwatson	if (strcmp(MAC_LOMAC_LABEL_NAME, element_name) != 0)
850107273Srwatson		return (0);
851107273Srwatson
852107273Srwatson	(*claimed)++;
853107273Srwatson
854172955Srwatson	error = lomac_parse(&ml_temp, element_data);
855107273Srwatson	if (error)
856107273Srwatson		return (error);
857107273Srwatson
858172955Srwatson	ml = SLOT(label);
859172955Srwatson	*ml = ml_temp;
860107273Srwatson
861107273Srwatson	return (0);
862107273Srwatson}
863107273Srwatson
864107273Srwatsonstatic void
865172955Srwatsonlomac_copy_label(struct label *src, struct label *dest)
866107273Srwatson{
867107273Srwatson
868107273Srwatson	*SLOT(dest) = *SLOT(src);
869107273Srwatson}
870107273Srwatson
871107273Srwatson/*
872173138Srwatson * Object-specific entry point implementations are sorted alphabetically by
873173138Srwatson * object type name and then by operation.
874107273Srwatson */
875173138Srwatsonstatic int
876173138Srwatsonlomac_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
877173138Srwatson    struct ifnet *ifp, struct label *ifplabel)
878107273Srwatson{
879173138Srwatson	struct mac_lomac *a, *b;
880107273Srwatson
881173138Srwatson	if (!lomac_enabled)
882173138Srwatson		return (0);
883107273Srwatson
884173138Srwatson	a = SLOT(dlabel);
885173138Srwatson	b = SLOT(ifplabel);
886107273Srwatson
887173138Srwatson	if (lomac_equal_single(a, b))
888173138Srwatson		return (0);
889173138Srwatson	return (EACCES);
890107273Srwatson}
891107273Srwatson
892107273Srwatsonstatic void
893173138Srwatsonlomac_bpfdesc_create(struct ucred *cred, struct bpf_d *d,
894173138Srwatson    struct label *dlabel)
895107273Srwatson{
896107273Srwatson	struct mac_lomac *source, *dest;
897107273Srwatson
898122524Srwatson	source = SLOT(cred->cr_label);
899173138Srwatson	dest = SLOT(dlabel);
900107273Srwatson
901172955Srwatson	lomac_copy_single(source, dest);
902107273Srwatson}
903107273Srwatson
904107273Srwatsonstatic void
905173138Srwatsonlomac_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
906173138Srwatson    struct mbuf *m, struct label *mlabel)
907107273Srwatson{
908107273Srwatson	struct mac_lomac *source, *dest;
909107273Srwatson
910173138Srwatson	source = SLOT(dlabel);
911173138Srwatson	dest = SLOT(mlabel);
912173138Srwatson
913172955Srwatson	lomac_copy_single(source, dest);
914107273Srwatson}
915107273Srwatson
916173138Srwatsonstatic int
917173138Srwatsonlomac_cred_check_relabel(struct ucred *cred, struct label *newlabel)
918107273Srwatson{
919173138Srwatson	struct mac_lomac *subj, *new;
920173138Srwatson	int error;
921107273Srwatson
922173138Srwatson	subj = SLOT(cred->cr_label);
923173138Srwatson	new = SLOT(newlabel);
924107273Srwatson
925173138Srwatson	/*
926173138Srwatson	 * If there is a LOMAC label update for the credential, it may be an
927173138Srwatson	 * update of the single, range, or both.
928173138Srwatson	 */
929173138Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
930173138Srwatson	if (error)
931173138Srwatson		return (error);
932107273Srwatson
933173138Srwatson	/*
934173138Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
935173138Srwatson	 */
936173138Srwatson	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
937173138Srwatson		/*
938173138Srwatson		 * Fill in the missing parts from the previous label.
939173138Srwatson		 */
940173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
941173138Srwatson			lomac_copy_single(subj, new);
942173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
943173138Srwatson			lomac_copy_range(subj, new);
944107273Srwatson
945173138Srwatson		/*
946173138Srwatson		 * To change the LOMAC range on a credential, the new range
947173138Srwatson		 * label must be in the current range.
948173138Srwatson		 */
949173138Srwatson		if (!lomac_range_in_range(new, subj))
950173138Srwatson			return (EPERM);
951107273Srwatson
952173138Srwatson		/*
953173138Srwatson		 * To change the LOMAC single label on a credential, the new
954173138Srwatson		 * single label must be in the new range.  Implicitly from
955173138Srwatson		 * the previous check, the new single is in the old range.
956173138Srwatson		 */
957173138Srwatson		if (!lomac_single_in_range(new, new))
958173138Srwatson			return (EPERM);
959107273Srwatson
960173138Srwatson		/*
961173138Srwatson		 * To have EQUAL in any component of the new credential LOMAC
962173138Srwatson		 * label, the subject must already have EQUAL in their label.
963173138Srwatson		 */
964173138Srwatson		if (lomac_contains_equal(new)) {
965173138Srwatson			error = lomac_subject_privileged(subj);
966173138Srwatson			if (error)
967173138Srwatson				return (error);
968173138Srwatson		}
969107273Srwatson
970173138Srwatson		/*
971173138Srwatson		 * XXXMAC: Additional consistency tests regarding the single
972173138Srwatson		 * and range of the new label might be performed here.
973173138Srwatson		 */
974173138Srwatson	}
975107273Srwatson
976173138Srwatson	return (0);
977107273Srwatson}
978107273Srwatson
979107273Srwatsonstatic int
980173138Srwatsonlomac_cred_check_visible(struct ucred *cr1, struct ucred *cr2)
981107273Srwatson{
982173138Srwatson	struct mac_lomac *subj, *obj;
983107273Srwatson
984173138Srwatson	if (!lomac_enabled)
985173138Srwatson		return (0);
986107273Srwatson
987173138Srwatson	subj = SLOT(cr1->cr_label);
988173138Srwatson	obj = SLOT(cr2->cr_label);
989107273Srwatson
990173138Srwatson	/* XXX: range */
991173138Srwatson	if (!lomac_dominate_single(obj, subj))
992173138Srwatson		return (ESRCH);
993107273Srwatson
994107273Srwatson	return (0);
995107273Srwatson}
996184407Srwatson
997107273Srwatsonstatic void
998184407Srwatsonlomac_cred_create_init(struct ucred *cred)
999184407Srwatson{
1000184407Srwatson	struct mac_lomac *dest;
1001184407Srwatson
1002184407Srwatson	dest = SLOT(cred->cr_label);
1003184407Srwatson
1004184407Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_HIGH, 0);
1005184407Srwatson	lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0);
1006184407Srwatson}
1007184407Srwatson
1008184407Srwatsonstatic void
1009184407Srwatsonlomac_cred_create_swapper(struct ucred *cred)
1010184407Srwatson{
1011184407Srwatson	struct mac_lomac *dest;
1012184407Srwatson
1013184407Srwatson	dest = SLOT(cred->cr_label);
1014184407Srwatson
1015184407Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1016184407Srwatson	lomac_set_range(dest, MAC_LOMAC_TYPE_LOW, 0, MAC_LOMAC_TYPE_HIGH, 0);
1017184407Srwatson}
1018184407Srwatson
1019184407Srwatsonstatic void
1020173138Srwatsonlomac_cred_relabel(struct ucred *cred, struct label *newlabel)
1021107273Srwatson{
1022107273Srwatson	struct mac_lomac *source, *dest;
1023107273Srwatson
1024173138Srwatson	source = SLOT(newlabel);
1025173138Srwatson	dest = SLOT(cred->cr_label);
1026107273Srwatson
1027173138Srwatson	try_relabel(source, dest);
1028107273Srwatson}
1029107273Srwatson
1030107273Srwatsonstatic void
1031173138Srwatsonlomac_devfs_create_device(struct ucred *cred, struct mount *mp,
1032173138Srwatson    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
1033122875Srwatson{
1034173138Srwatson	struct mac_lomac *ml;
1035173138Srwatson	int lomac_type;
1036122875Srwatson
1037173138Srwatson	ml = SLOT(delabel);
1038173138Srwatson	if (strcmp(dev->si_name, "null") == 0 ||
1039173138Srwatson	    strcmp(dev->si_name, "zero") == 0 ||
1040173138Srwatson	    strcmp(dev->si_name, "random") == 0 ||
1041173138Srwatson	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0 ||
1042173138Srwatson	    strncmp(dev->si_name, "ttyv", strlen("ttyv")) == 0)
1043173138Srwatson		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1044173138Srwatson	else if (ptys_equal &&
1045173138Srwatson	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
1046173138Srwatson	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
1047173138Srwatson		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1048173138Srwatson	else
1049173138Srwatson		lomac_type = MAC_LOMAC_TYPE_HIGH;
1050173138Srwatson	lomac_set_single(ml, lomac_type, 0);
1051122875Srwatson}
1052122875Srwatson
1053122875Srwatsonstatic void
1054173138Srwatsonlomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
1055173138Srwatson    struct devfs_dirent *de, struct label *delabel)
1056107273Srwatson{
1057173138Srwatson	struct mac_lomac *ml;
1058107273Srwatson
1059173138Srwatson	ml = SLOT(delabel);
1060173138Srwatson	lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0);
1061107273Srwatson}
1062107273Srwatson
1063107273Srwatsonstatic void
1064173138Srwatsonlomac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
1065173138Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
1066173138Srwatson    struct label *delabel)
1067107273Srwatson{
1068107273Srwatson	struct mac_lomac *source, *dest;
1069107273Srwatson
1070122524Srwatson	source = SLOT(cred->cr_label);
1071173138Srwatson	dest = SLOT(delabel);
1072107273Srwatson
1073172955Srwatson	lomac_copy_single(source, dest);
1074107273Srwatson}
1075107273Srwatson
1076107273Srwatsonstatic void
1077173138Srwatsonlomac_devfs_update(struct mount *mp, struct devfs_dirent *de,
1078173138Srwatson    struct label *delabel, struct vnode *vp, struct label *vplabel)
1079107273Srwatson{
1080107273Srwatson	struct mac_lomac *source, *dest;
1081107273Srwatson
1082173138Srwatson	source = SLOT(vplabel);
1083173138Srwatson	dest = SLOT(delabel);
1084107273Srwatson
1085173138Srwatson	lomac_copy(source, dest);
1086107273Srwatson}
1087107273Srwatson
1088107273Srwatsonstatic void
1089173138Srwatsonlomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
1090173138Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
1091173138Srwatson    struct label *vplabel)
1092107273Srwatson{
1093107273Srwatson	struct mac_lomac *source, *dest;
1094107273Srwatson
1095173138Srwatson	source = SLOT(delabel);
1096173138Srwatson	dest = SLOT(vplabel);
1097107273Srwatson
1098172955Srwatson	lomac_copy_single(source, dest);
1099107273Srwatson}
1100107273Srwatson
1101173138Srwatsonstatic int
1102173138Srwatsonlomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
1103173138Srwatson    struct label *ifplabel, struct label *newlabel)
1104107273Srwatson{
1105173138Srwatson	struct mac_lomac *subj, *new;
1106173138Srwatson	int error;
1107107273Srwatson
1108173138Srwatson	subj = SLOT(cred->cr_label);
1109173138Srwatson	new = SLOT(newlabel);
1110107273Srwatson
1111173138Srwatson	/*
1112173138Srwatson	 * If there is a LOMAC label update for the interface, it may be an
1113173138Srwatson	 * update of the single, range, or both.
1114173138Srwatson	 */
1115173138Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1116173138Srwatson	if (error)
1117173138Srwatson		return (error);
1118107273Srwatson
1119173138Srwatson	/*
1120173138Srwatson	 * Relabling network interfaces requires LOMAC privilege.
1121173138Srwatson	 */
1122173138Srwatson	error = lomac_subject_privileged(subj);
1123173138Srwatson	if (error)
1124173138Srwatson		return (error);
1125107273Srwatson
1126173138Srwatson	/*
1127173138Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1128173138Srwatson	 */
1129173138Srwatson	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1130173138Srwatson		/*
1131173138Srwatson		 * Fill in the missing parts from the previous label.
1132173138Srwatson		 */
1133173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1134173138Srwatson			lomac_copy_single(subj, new);
1135173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1136173138Srwatson			lomac_copy_range(subj, new);
1137107273Srwatson
1138173138Srwatson		/*
1139173138Srwatson		 * Rely on the traditional superuser status for the LOMAC
1140173138Srwatson		 * interface relabel requirements.  XXXMAC: This will go
1141173138Srwatson		 * away.
1142173138Srwatson		 *
1143173138Srwatson		 * XXXRW: This is also redundant to a higher layer check.
1144173138Srwatson		 */
1145173138Srwatson		error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
1146173138Srwatson		if (error)
1147173138Srwatson			return (EPERM);
1148107273Srwatson
1149173138Srwatson		/*
1150173138Srwatson		 * XXXMAC: Additional consistency tests regarding the single
1151173138Srwatson		 * and the range of the new label might be performed here.
1152173138Srwatson		 */
1153173138Srwatson	}
1154107273Srwatson
1155173138Srwatson	return (0);
1156107273Srwatson}
1157107273Srwatson
1158173138Srwatsonstatic int
1159173138Srwatsonlomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1160173138Srwatson    struct mbuf *m, struct label *mlabel)
1161107273Srwatson{
1162173138Srwatson	struct mac_lomac *p, *i;
1163107273Srwatson
1164173138Srwatson	if (!lomac_enabled)
1165173138Srwatson		return (0);
1166107273Srwatson
1167173138Srwatson	p = SLOT(mlabel);
1168173138Srwatson	i = SLOT(ifplabel);
1169107273Srwatson
1170173138Srwatson	return (lomac_single_in_range(p, i) ? 0 : EACCES);
1171107273Srwatson}
1172107273Srwatson
1173107273Srwatsonstatic void
1174172955Srwatsonlomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1175107273Srwatson{
1176121816Sbrooks	char tifname[IFNAMSIZ], *p, *q;
1177107273Srwatson	char tiflist[sizeof(trusted_interfaces)];
1178107273Srwatson	struct mac_lomac *dest;
1179107273Srwatson	int len, grade;
1180107273Srwatson
1181168976Srwatson	dest = SLOT(ifplabel);
1182107273Srwatson
1183168976Srwatson	if (ifp->if_type == IFT_LOOP) {
1184107273Srwatson		grade = MAC_LOMAC_TYPE_EQUAL;
1185107273Srwatson		goto set;
1186107273Srwatson	}
1187107273Srwatson
1188107273Srwatson	if (trust_all_interfaces) {
1189107273Srwatson		grade = MAC_LOMAC_TYPE_HIGH;
1190107273Srwatson		goto set;
1191107273Srwatson	}
1192107273Srwatson
1193107273Srwatson	grade = MAC_LOMAC_TYPE_LOW;
1194107273Srwatson
1195107273Srwatson	if (trusted_interfaces[0] == '\0' ||
1196107273Srwatson	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1197107273Srwatson		goto set;
1198107273Srwatson
1199107273Srwatson	bzero(tiflist, sizeof(tiflist));
1200107273Srwatson	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1201107273Srwatson		if(*p != ' ' && *p != '\t')
1202107273Srwatson			*q = *p;
1203107273Srwatson
1204107273Srwatson	for (p = q = tiflist;; p++) {
1205107273Srwatson		if (*p == ',' || *p == '\0') {
1206107273Srwatson			len = p - q;
1207107273Srwatson			if (len < IFNAMSIZ) {
1208107273Srwatson				bzero(tifname, sizeof(tifname));
1209107273Srwatson				bcopy(q, tifname, len);
1210168976Srwatson				if (strcmp(tifname, ifp->if_xname) == 0) {
1211107273Srwatson					grade = MAC_LOMAC_TYPE_HIGH;
1212107273Srwatson					break;
1213107273Srwatson				}
1214107273Srwatson			}
1215107273Srwatson			else {
1216107273Srwatson				*p = '\0';
1217107273Srwatson				printf("MAC/LOMAC warning: interface name "
1218107273Srwatson				    "\"%s\" is too long (must be < %d)\n",
1219107273Srwatson				    q, IFNAMSIZ);
1220107273Srwatson			}
1221107273Srwatson			if (*p == '\0')
1222107273Srwatson				break;
1223107273Srwatson			q = p + 1;
1224107273Srwatson		}
1225107273Srwatson	}
1226107273Srwatsonset:
1227172955Srwatson	lomac_set_single(dest, grade, 0);
1228172955Srwatson	lomac_set_range(dest, grade, 0, grade, 0);
1229107273Srwatson}
1230107273Srwatson
1231107273Srwatsonstatic void
1232173138Srwatsonlomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1233173138Srwatson    struct mbuf *m, struct label *mlabel)
1234107273Srwatson{
1235107273Srwatson	struct mac_lomac *source, *dest;
1236107273Srwatson
1237173138Srwatson	source = SLOT(ifplabel);
1238173138Srwatson	dest = SLOT(mlabel);
1239107273Srwatson
1240172955Srwatson	lomac_copy_single(source, dest);
1241107273Srwatson}
1242107273Srwatson
1243107273Srwatsonstatic void
1244173138Srwatsonlomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1245173138Srwatson    struct label *ifplabel, struct label *newlabel)
1246107273Srwatson{
1247107273Srwatson	struct mac_lomac *source, *dest;
1248107273Srwatson
1249173138Srwatson	source = SLOT(newlabel);
1250173138Srwatson	dest = SLOT(ifplabel);
1251107273Srwatson
1252173138Srwatson	try_relabel(source, dest);
1253107273Srwatson}
1254107273Srwatson
1255173138Srwatsonstatic int
1256173138Srwatsonlomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1257173138Srwatson    struct mbuf *m, struct label *mlabel)
1258173138Srwatson{
1259173138Srwatson	struct mac_lomac *p, *i;
1260173138Srwatson
1261173138Srwatson	if (!lomac_enabled)
1262173138Srwatson		return (0);
1263173138Srwatson
1264173138Srwatson	p = SLOT(mlabel);
1265173138Srwatson	i = SLOT(inplabel);
1266173138Srwatson
1267173138Srwatson	return (lomac_equal_single(p, i) ? 0 : EACCES);
1268173138Srwatson}
1269173138Srwatson
1270183980Sbzstatic int
1271183980Sbzlomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1272183980Sbz    struct label *inplabel)
1273183980Sbz{
1274183980Sbz	struct mac_lomac *subj, *obj;
1275183980Sbz
1276183980Sbz	if (!lomac_enabled)
1277183980Sbz		return (0);
1278183980Sbz
1279183980Sbz	subj = SLOT(cred->cr_label);
1280183980Sbz	obj = SLOT(inplabel);
1281183980Sbz
1282183980Sbz	if (!lomac_dominate_single(obj, subj))
1283183980Sbz		return (ENOENT);
1284183980Sbz
1285183980Sbz	return (0);
1286183980Sbz}
1287183980Sbz
1288107273Srwatsonstatic void
1289173138Srwatsonlomac_inpcb_create(struct socket *so, struct label *solabel,
1290173138Srwatson    struct inpcb *inp, struct label *inplabel)
1291107273Srwatson{
1292107273Srwatson	struct mac_lomac *source, *dest;
1293107273Srwatson
1294173138Srwatson	source = SLOT(solabel);
1295173138Srwatson	dest = SLOT(inplabel);
1296107273Srwatson
1297172955Srwatson	lomac_copy_single(source, dest);
1298107273Srwatson}
1299107273Srwatson
1300107273Srwatsonstatic void
1301172955Srwatsonlomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1302123607Srwatson    struct mbuf *m, struct label *mlabel)
1303123607Srwatson{
1304123607Srwatson	struct mac_lomac *source, *dest;
1305123607Srwatson
1306123607Srwatson	source = SLOT(inplabel);
1307123607Srwatson	dest = SLOT(mlabel);
1308123607Srwatson
1309172955Srwatson	lomac_copy_single(source, dest);
1310123607Srwatson}
1311123607Srwatson
1312123607Srwatsonstatic void
1313173138Srwatsonlomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1314173138Srwatson    struct inpcb *inp, struct label *inplabel)
1315107273Srwatson{
1316107273Srwatson	struct mac_lomac *source, *dest;
1317107273Srwatson
1318173138Srwatson	source = SLOT(solabel);
1319173138Srwatson	dest = SLOT(inplabel);
1320107273Srwatson
1321172955Srwatson	lomac_copy_single(source, dest);
1322107273Srwatson}
1323107273Srwatson
1324107273Srwatsonstatic void
1325184308Srwatsonlomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1326184308Srwatson    struct label *q6label)
1327184308Srwatson{
1328184308Srwatson	struct mac_lomac *source, *dest;
1329184308Srwatson
1330184308Srwatson	source = SLOT(mlabel);
1331184308Srwatson	dest = SLOT(q6label);
1332184308Srwatson
1333184308Srwatson	lomac_copy_single(source, dest);
1334184308Srwatson}
1335184308Srwatson
1336184308Srwatsonstatic int
1337184308Srwatsonlomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1338184308Srwatson    struct label *q6label)
1339184308Srwatson{
1340184308Srwatson	struct mac_lomac *a, *b;
1341184308Srwatson
1342184308Srwatson	a = SLOT(q6label);
1343184308Srwatson	b = SLOT(mlabel);
1344184308Srwatson
1345184308Srwatson	return (lomac_equal_single(a, b));
1346184308Srwatson}
1347184308Srwatson
1348184308Srwatsonstatic void
1349184308Srwatsonlomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1350184308Srwatson    struct label *mlabel)
1351184308Srwatson{
1352184308Srwatson	struct mac_lomac *source, *dest;
1353184308Srwatson
1354184308Srwatson	source = SLOT(q6label);
1355184308Srwatson	dest = SLOT(mlabel);
1356184308Srwatson
1357184308Srwatson	/* Just use the head, since we require them all to match. */
1358184308Srwatson	lomac_copy_single(source, dest);
1359184308Srwatson}
1360184308Srwatson
1361184308Srwatsonstatic void
1362184308Srwatsonlomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1363184308Srwatson    struct label *q6label)
1364184308Srwatson{
1365184308Srwatson
1366184308Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1367184308Srwatson}
1368184308Srwatson
1369184308Srwatsonstatic void
1370179781Srwatsonlomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1371179781Srwatson    struct label *qlabel)
1372107273Srwatson{
1373107273Srwatson	struct mac_lomac *source, *dest;
1374107273Srwatson
1375173138Srwatson	source = SLOT(mlabel);
1376179781Srwatson	dest = SLOT(qlabel);
1377107273Srwatson
1378172955Srwatson	lomac_copy_single(source, dest);
1379107273Srwatson}
1380107273Srwatson
1381107273Srwatsonstatic int
1382179781Srwatsonlomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1383179781Srwatson    struct label *qlabel)
1384107273Srwatson{
1385107273Srwatson	struct mac_lomac *a, *b;
1386107273Srwatson
1387179781Srwatson	a = SLOT(qlabel);
1388168976Srwatson	b = SLOT(mlabel);
1389107273Srwatson
1390172955Srwatson	return (lomac_equal_single(a, b));
1391107273Srwatson}
1392107273Srwatson
1393107273Srwatsonstatic void
1394179781Srwatsonlomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1395179781Srwatson    struct label *mlabel)
1396107273Srwatson{
1397107273Srwatson	struct mac_lomac *source, *dest;
1398107273Srwatson
1399179781Srwatson	source = SLOT(qlabel);
1400173138Srwatson	dest = SLOT(mlabel);
1401107273Srwatson
1402173138Srwatson	/* Just use the head, since we require them all to match. */
1403173138Srwatson	lomac_copy_single(source, dest);
1404107273Srwatson}
1405107273Srwatson
1406107273Srwatsonstatic void
1407179781Srwatsonlomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1408179781Srwatson    struct label *qlabel)
1409107273Srwatson{
1410107273Srwatson
1411107273Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1412107273Srwatson}
1413107273Srwatson
1414173138Srwatsonstatic int
1415173138Srwatsonlomac_kld_check_load(struct ucred *cred, struct vnode *vp,
1416173138Srwatson    struct label *vplabel)
1417122875Srwatson{
1418173138Srwatson	struct mac_lomac *subj, *obj;
1419122875Srwatson
1420173138Srwatson	if (!lomac_enabled)
1421173138Srwatson		return (0);
1422122875Srwatson
1423173138Srwatson	subj = SLOT(cred->cr_label);
1424173138Srwatson	obj = SLOT(vplabel);
1425122875Srwatson
1426173138Srwatson	if (lomac_subject_privileged(subj))
1427173138Srwatson		return (EPERM);
1428165150Scsjp
1429173138Srwatson	if (!lomac_high_single(obj))
1430173138Srwatson		return (EACCES);
1431173138Srwatson
1432173138Srwatson	return (0);
1433165150Scsjp}
1434165150Scsjp
1435165150Scsjpstatic void
1436173138Srwatsonlomac_mount_create(struct ucred *cred, struct mount *mp,
1437173138Srwatson    struct label *mplabel)
1438165150Scsjp{
1439165150Scsjp	struct mac_lomac *source, *dest;
1440165150Scsjp
1441173138Srwatson	source = SLOT(cred->cr_label);
1442173138Srwatson	dest = SLOT(mplabel);
1443173138Srwatson	lomac_copy_single(source, dest);
1444165150Scsjp}
1445165150Scsjp
1446165150Scsjpstatic void
1447173095Srwatsonlomac_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1448173095Srwatson    struct mbuf *m, struct label *mlabel)
1449173095Srwatson{
1450173095Srwatson	struct mac_lomac *dest;
1451173095Srwatson
1452173095Srwatson	dest = SLOT(mlabel);
1453173095Srwatson
1454173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1455173095Srwatson}
1456173095Srwatson
1457173095Srwatsonstatic void
1458173095Srwatsonlomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1459173095Srwatson    struct mbuf *m, struct label *mlabel)
1460173095Srwatson{
1461173095Srwatson	struct mac_lomac *dest;
1462173095Srwatson
1463173095Srwatson	dest = SLOT(mlabel);
1464173095Srwatson
1465173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1466173095Srwatson}
1467173095Srwatson
1468173095Srwatsonstatic void
1469173102Srwatsonlomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1470173102Srwatson    struct mbuf *msend, struct label *msendlabel)
1471173102Srwatson{
1472173102Srwatson	struct mac_lomac *source, *dest;
1473173102Srwatson
1474173102Srwatson	source = SLOT(mrecvlabel);
1475173102Srwatson	dest = SLOT(msendlabel);
1476173102Srwatson
1477173102Srwatson	lomac_copy_single(source, dest);
1478173102Srwatson}
1479173102Srwatson
1480173102Srwatsonstatic void
1481173018Srwatsonlomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1482162238Scsjp{
1483162238Scsjp	struct mac_lomac *dest;
1484162238Scsjp
1485168976Srwatson	dest = SLOT(mlabel);
1486162238Scsjp
1487162238Scsjp	/* XXX: where is the label for the firewall really comming from? */
1488172955Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1489162238Scsjp}
1490162238Scsjp
1491173095Srwatsonstatic void
1492173138Srwatsonlomac_netinet_fragment(struct mbuf *m, struct label *mlabel,
1493173138Srwatson    struct mbuf *frag, struct label *fraglabel)
1494173138Srwatson{
1495173138Srwatson	struct mac_lomac *source, *dest;
1496173138Srwatson
1497173138Srwatson	source = SLOT(mlabel);
1498173138Srwatson	dest = SLOT(fraglabel);
1499173138Srwatson
1500173138Srwatson	lomac_copy_single(source, dest);
1501173138Srwatson}
1502173138Srwatson
1503173138Srwatsonstatic void
1504173102Srwatsonlomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1505173102Srwatson    struct mbuf *msend, struct label *msendlabel)
1506173102Srwatson{
1507173102Srwatson	struct mac_lomac *source, *dest;
1508173102Srwatson
1509173102Srwatson	source = SLOT(mrecvlabel);
1510173102Srwatson	dest = SLOT(msendlabel);
1511173102Srwatson
1512173102Srwatson	lomac_copy_single(source, dest);
1513173102Srwatson}
1514173102Srwatson
1515173102Srwatsonstatic void
1516173095Srwatsonlomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1517173095Srwatson    struct mbuf *m, struct label *mlabel)
1518173095Srwatson{
1519173095Srwatson	struct mac_lomac *dest;
1520173095Srwatson
1521173095Srwatson	dest = SLOT(mlabel);
1522173095Srwatson
1523173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1524173095Srwatson}
1525173095Srwatson
1526173095Srwatsonstatic void
1527173095Srwatsonlomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1528173095Srwatson    struct mbuf *m, struct label *mlabel)
1529173095Srwatson{
1530173095Srwatson	struct mac_lomac *dest;
1531173095Srwatson
1532173095Srwatson	dest = SLOT(mlabel);
1533173095Srwatson
1534173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1535173095Srwatson}
1536173095Srwatson
1537107273Srwatsonstatic int
1538172955Srwatsonlomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1539168976Srwatson    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1540107273Srwatson{
1541107273Srwatson
1542172955Srwatson	if (!lomac_enabled)
1543107273Srwatson		return (0);
1544107273Srwatson
1545107273Srwatson	/* XXX: This will be implemented soon... */
1546107273Srwatson
1547107273Srwatson	return (0);
1548107273Srwatson}
1549107273Srwatson
1550107273Srwatsonstatic int
1551172955Srwatsonlomac_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1552168976Srwatson    struct label *pplabel)
1553107273Srwatson{
1554107273Srwatson	struct mac_lomac *subj, *obj;
1555107273Srwatson
1556172955Srwatson	if (!lomac_enabled)
1557107273Srwatson		return (0);
1558107273Srwatson
1559122524Srwatson	subj = SLOT(cred->cr_label);
1560168976Srwatson	obj = SLOT(pplabel);
1561107273Srwatson
1562172955Srwatson	if (!lomac_dominate_single(obj, subj))
1563107273Srwatson		return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1564107273Srwatson
1565107273Srwatson	return (0);
1566107273Srwatson}
1567107273Srwatson
1568107273Srwatsonstatic int
1569172955Srwatsonlomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1570168976Srwatson    struct label *pplabel, struct label *newlabel)
1571107273Srwatson{
1572107273Srwatson	struct mac_lomac *subj, *obj, *new;
1573107273Srwatson	int error;
1574107273Srwatson
1575107273Srwatson	new = SLOT(newlabel);
1576122524Srwatson	subj = SLOT(cred->cr_label);
1577168976Srwatson	obj = SLOT(pplabel);
1578107273Srwatson
1579107273Srwatson	/*
1580172955Srwatson	 * If there is a LOMAC label update for a pipe, it must be a single
1581172955Srwatson	 * update.
1582107273Srwatson	 */
1583107273Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1584107273Srwatson	if (error)
1585107273Srwatson		return (error);
1586107273Srwatson
1587107273Srwatson	/*
1588107273Srwatson	 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1589107273Srwatson	 * authorize the relabel.
1590107273Srwatson	 */
1591172955Srwatson	if (!lomac_single_in_range(obj, subj))
1592107273Srwatson		return (EPERM);
1593107273Srwatson
1594107273Srwatson	/*
1595107273Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1596107273Srwatson	 */
1597107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1598107273Srwatson		/*
1599107273Srwatson		 * To change the LOMAC label on a pipe, the new pipe label
1600107273Srwatson		 * must be in the subject range.
1601107273Srwatson		 */
1602172955Srwatson		if (!lomac_single_in_range(new, subj))
1603107273Srwatson			return (EPERM);
1604107273Srwatson
1605107273Srwatson		/*
1606107273Srwatson		 * To change the LOMAC label on a pipe to be EQUAL, the
1607107273Srwatson		 * subject must have appropriate privilege.
1608107273Srwatson		 */
1609172955Srwatson		if (lomac_contains_equal(new)) {
1610172955Srwatson			error = lomac_subject_privileged(subj);
1611107273Srwatson			if (error)
1612107273Srwatson				return (error);
1613107273Srwatson		}
1614107273Srwatson	}
1615107273Srwatson
1616107273Srwatson	return (0);
1617107273Srwatson}
1618107273Srwatson
1619107273Srwatsonstatic int
1620172955Srwatsonlomac_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1621168976Srwatson    struct label *pplabel)
1622107273Srwatson{
1623107273Srwatson	struct mac_lomac *subj, *obj;
1624107273Srwatson
1625172955Srwatson	if (!lomac_enabled)
1626107273Srwatson		return (0);
1627107273Srwatson
1628122524Srwatson	subj = SLOT(cred->cr_label);
1629168976Srwatson	obj = SLOT(pplabel);
1630107273Srwatson
1631172955Srwatson	if (!lomac_subject_dominate(subj, obj))
1632107273Srwatson		return (EACCES);
1633107273Srwatson
1634107273Srwatson	return (0);
1635107273Srwatson}
1636107273Srwatson
1637173138Srwatsonstatic void
1638173138Srwatsonlomac_pipe_create(struct ucred *cred, struct pipepair *pp,
1639173138Srwatson    struct label *pplabel)
1640107273Srwatson{
1641173138Srwatson	struct mac_lomac *source, *dest;
1642107273Srwatson
1643173138Srwatson	source = SLOT(cred->cr_label);
1644173138Srwatson	dest = SLOT(pplabel);
1645107273Srwatson
1646173138Srwatson	lomac_copy_single(source, dest);
1647107273Srwatson}
1648107273Srwatson
1649173138Srwatsonstatic void
1650173138Srwatsonlomac_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1651173138Srwatson    struct label *pplabel, struct label *newlabel)
1652107273Srwatson{
1653173138Srwatson	struct mac_lomac *source, *dest;
1654107273Srwatson
1655173138Srwatson	source = SLOT(newlabel);
1656173138Srwatson	dest = SLOT(pplabel);
1657107273Srwatson
1658173138Srwatson	try_relabel(source, dest);
1659107273Srwatson}
1660107273Srwatson
1661168951Srwatson/*
1662168951Srwatson * Some system privileges are allowed regardless of integrity grade; others
1663168951Srwatson * are allowed only when running with privilege with respect to the LOMAC
1664168951Srwatson * policy as they might otherwise allow bypassing of the integrity policy.
1665168951Srwatson */
1666107273Srwatsonstatic int
1667172955Srwatsonlomac_priv_check(struct ucred *cred, int priv)
1668168951Srwatson{
1669168951Srwatson	struct mac_lomac *subj;
1670168951Srwatson	int error;
1671168951Srwatson
1672172955Srwatson	if (!lomac_enabled)
1673168951Srwatson		return (0);
1674168951Srwatson
1675168951Srwatson	/*
1676168951Srwatson	 * Exempt only specific privileges from the LOMAC integrity policy.
1677168951Srwatson	 */
1678168951Srwatson	switch (priv) {
1679168951Srwatson	case PRIV_KTRACE:
1680168951Srwatson	case PRIV_MSGBUF:
1681168951Srwatson
1682168951Srwatson	/*
1683168951Srwatson	 * Allow processes to manipulate basic process audit properties, and
1684168951Srwatson	 * to submit audit records.
1685168951Srwatson	 */
1686168951Srwatson	case PRIV_AUDIT_GETAUDIT:
1687168951Srwatson	case PRIV_AUDIT_SETAUDIT:
1688168951Srwatson	case PRIV_AUDIT_SUBMIT:
1689168951Srwatson
1690168951Srwatson	/*
1691168951Srwatson	 * Allow processes to manipulate their regular UNIX credentials.
1692168951Srwatson	 */
1693168951Srwatson	case PRIV_CRED_SETUID:
1694168951Srwatson	case PRIV_CRED_SETEUID:
1695168951Srwatson	case PRIV_CRED_SETGID:
1696168951Srwatson	case PRIV_CRED_SETEGID:
1697168951Srwatson	case PRIV_CRED_SETGROUPS:
1698168951Srwatson	case PRIV_CRED_SETREUID:
1699168951Srwatson	case PRIV_CRED_SETREGID:
1700168951Srwatson	case PRIV_CRED_SETRESUID:
1701168951Srwatson	case PRIV_CRED_SETRESGID:
1702168951Srwatson
1703168951Srwatson	/*
1704168951Srwatson	 * Allow processes to perform system monitoring.
1705168951Srwatson	 */
1706168951Srwatson	case PRIV_SEEOTHERGIDS:
1707168951Srwatson	case PRIV_SEEOTHERUIDS:
1708168951Srwatson		break;
1709168951Srwatson
1710168951Srwatson	/*
1711168951Srwatson	 * Allow access to general process debugging facilities.  We
1712168951Srwatson	 * separately control debugging based on MAC label.
1713168951Srwatson	 */
1714168951Srwatson	case PRIV_DEBUG_DIFFCRED:
1715168951Srwatson	case PRIV_DEBUG_SUGID:
1716168951Srwatson	case PRIV_DEBUG_UNPRIV:
1717168951Srwatson
1718168951Srwatson	/*
1719168951Srwatson	 * Allow manipulating jails.
1720168951Srwatson	 */
1721168951Srwatson	case PRIV_JAIL_ATTACH:
1722168951Srwatson
1723168951Srwatson	/*
1724168951Srwatson	 * Allow privilege with respect to the Partition policy, but not the
1725168951Srwatson	 * Privs policy.
1726168951Srwatson	 */
1727168951Srwatson	case PRIV_MAC_PARTITION:
1728168951Srwatson
1729168951Srwatson	/*
1730168951Srwatson	 * Allow privilege with respect to process resource limits and login
1731168951Srwatson	 * context.
1732168951Srwatson	 */
1733168951Srwatson	case PRIV_PROC_LIMIT:
1734168951Srwatson	case PRIV_PROC_SETLOGIN:
1735168951Srwatson	case PRIV_PROC_SETRLIMIT:
1736168951Srwatson
1737168951Srwatson	/*
1738168951Srwatson	 * Allow System V and POSIX IPC privileges.
1739168951Srwatson	 */
1740168951Srwatson	case PRIV_IPC_READ:
1741168951Srwatson	case PRIV_IPC_WRITE:
1742168951Srwatson	case PRIV_IPC_ADMIN:
1743168951Srwatson	case PRIV_IPC_MSGSIZE:
1744168951Srwatson	case PRIV_MQ_ADMIN:
1745168951Srwatson
1746168951Srwatson	/*
1747168951Srwatson	 * Allow certain scheduler manipulations -- possibly this should be
1748168951Srwatson	 * controlled by more fine-grained policy, as potentially low
1749168951Srwatson	 * integrity processes can deny CPU to higher integrity ones.
1750168951Srwatson	 */
1751168951Srwatson	case PRIV_SCHED_DIFFCRED:
1752168951Srwatson	case PRIV_SCHED_SETPRIORITY:
1753168951Srwatson	case PRIV_SCHED_RTPRIO:
1754168951Srwatson	case PRIV_SCHED_SETPOLICY:
1755168951Srwatson	case PRIV_SCHED_SET:
1756168951Srwatson	case PRIV_SCHED_SETPARAM:
1757168951Srwatson
1758168951Srwatson	/*
1759168951Srwatson	 * More IPC privileges.
1760168951Srwatson	 */
1761168951Srwatson	case PRIV_SEM_WRITE:
1762168951Srwatson
1763168951Srwatson	/*
1764168951Srwatson	 * Allow signaling privileges subject to integrity policy.
1765168951Srwatson	 */
1766168951Srwatson	case PRIV_SIGNAL_DIFFCRED:
1767168951Srwatson	case PRIV_SIGNAL_SUGID:
1768168951Srwatson
1769168951Srwatson	/*
1770168951Srwatson	 * Allow access to only limited sysctls from lower integrity levels;
1771168951Srwatson	 * piggy-back on the Jail definition.
1772168951Srwatson	 */
1773168951Srwatson	case PRIV_SYSCTL_WRITEJAIL:
1774168951Srwatson
1775168951Srwatson	/*
1776168951Srwatson	 * Allow TTY-based privileges, subject to general device access using
1777168951Srwatson	 * labels on TTY device nodes, but not console privilege.
1778168951Srwatson	 */
1779168951Srwatson	case PRIV_TTY_DRAINWAIT:
1780168951Srwatson	case PRIV_TTY_DTRWAIT:
1781168951Srwatson	case PRIV_TTY_EXCLUSIVE:
1782168951Srwatson	case PRIV_TTY_PRISON:
1783168951Srwatson	case PRIV_TTY_STI:
1784168951Srwatson	case PRIV_TTY_SETA:
1785168951Srwatson
1786168951Srwatson	/*
1787168951Srwatson	 * Grant most VFS privileges, as almost all are in practice bounded
1788168951Srwatson	 * by more specific checks using labels.
1789168951Srwatson	 */
1790168951Srwatson	case PRIV_VFS_READ:
1791168951Srwatson	case PRIV_VFS_WRITE:
1792168951Srwatson	case PRIV_VFS_ADMIN:
1793168951Srwatson	case PRIV_VFS_EXEC:
1794168951Srwatson	case PRIV_VFS_LOOKUP:
1795168951Srwatson	case PRIV_VFS_CHFLAGS_DEV:
1796168951Srwatson	case PRIV_VFS_CHOWN:
1797168951Srwatson	case PRIV_VFS_CHROOT:
1798168951Srwatson	case PRIV_VFS_RETAINSUGID:
1799168951Srwatson	case PRIV_VFS_EXCEEDQUOTA:
1800168951Srwatson	case PRIV_VFS_FCHROOT:
1801168951Srwatson	case PRIV_VFS_FHOPEN:
1802168951Srwatson	case PRIV_VFS_FHSTATFS:
1803168951Srwatson	case PRIV_VFS_GENERATION:
1804168951Srwatson	case PRIV_VFS_GETFH:
1805168951Srwatson	case PRIV_VFS_GETQUOTA:
1806168951Srwatson	case PRIV_VFS_LINK:
1807168951Srwatson	case PRIV_VFS_MOUNT:
1808168951Srwatson	case PRIV_VFS_MOUNT_OWNER:
1809168951Srwatson	case PRIV_VFS_MOUNT_PERM:
1810168951Srwatson	case PRIV_VFS_MOUNT_SUIDDIR:
1811168951Srwatson	case PRIV_VFS_MOUNT_NONUSER:
1812168951Srwatson	case PRIV_VFS_SETGID:
1813168951Srwatson	case PRIV_VFS_STICKYFILE:
1814168951Srwatson	case PRIV_VFS_SYSFLAGS:
1815168951Srwatson	case PRIV_VFS_UNMOUNT:
1816168951Srwatson
1817168951Srwatson	/*
1818168951Srwatson	 * Allow VM privileges; it would be nice if these were subject to
1819168951Srwatson	 * resource limits.
1820168951Srwatson	 */
1821168951Srwatson	case PRIV_VM_MADV_PROTECT:
1822168951Srwatson	case PRIV_VM_MLOCK:
1823168951Srwatson	case PRIV_VM_MUNLOCK:
1824168951Srwatson
1825168951Srwatson	/*
1826168951Srwatson	 * Allow some but not all network privileges.  In general, dont allow
1827168951Srwatson	 * reconfiguring the network stack, just normal use.
1828168951Srwatson	 */
1829168951Srwatson	case PRIV_NETATALK_RESERVEDPORT:
1830168951Srwatson	case PRIV_NETINET_RESERVEDPORT:
1831168951Srwatson	case PRIV_NETINET_RAW:
1832168951Srwatson	case PRIV_NETINET_REUSEPORT:
1833168951Srwatson	case PRIV_NETIPX_RESERVEDPORT:
1834168951Srwatson	case PRIV_NETIPX_RAW:
1835168951Srwatson		break;
1836168951Srwatson
1837168951Srwatson	/*
1838168951Srwatson	 * All remaining system privileges are allow only if the process
1839168951Srwatson	 * holds privilege with respect to the LOMAC policy.
1840168951Srwatson	 */
1841168951Srwatson	default:
1842168951Srwatson		subj = SLOT(cred->cr_label);
1843172955Srwatson		error = lomac_subject_privileged(subj);
1844168951Srwatson		if (error)
1845168951Srwatson			return (error);
1846168951Srwatson	}
1847168951Srwatson	return (0);
1848168951Srwatson}
1849168951Srwatson
1850173138Srwatsonstatic int
1851173138Srwatsonlomac_proc_check_debug(struct ucred *cred, struct proc *p)
1852173138Srwatson{
1853173138Srwatson	struct mac_lomac *subj, *obj;
1854168951Srwatson
1855173138Srwatson	if (!lomac_enabled)
1856173138Srwatson		return (0);
1857173138Srwatson
1858173138Srwatson	subj = SLOT(cred->cr_label);
1859173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1860173138Srwatson
1861173138Srwatson	/* XXX: range checks */
1862173138Srwatson	if (!lomac_dominate_single(obj, subj))
1863173138Srwatson		return (ESRCH);
1864173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1865173138Srwatson		return (EACCES);
1866173138Srwatson
1867173138Srwatson	return (0);
1868173138Srwatson}
1869173138Srwatson
1870168951Srwatsonstatic int
1871173138Srwatsonlomac_proc_check_sched(struct ucred *cred, struct proc *p)
1872173138Srwatson{
1873173138Srwatson	struct mac_lomac *subj, *obj;
1874173138Srwatson
1875173138Srwatson	if (!lomac_enabled)
1876173138Srwatson		return (0);
1877173138Srwatson
1878173138Srwatson	subj = SLOT(cred->cr_label);
1879173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1880173138Srwatson
1881173138Srwatson	/* XXX: range checks */
1882173138Srwatson	if (!lomac_dominate_single(obj, subj))
1883173138Srwatson		return (ESRCH);
1884173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1885173138Srwatson		return (EACCES);
1886173138Srwatson
1887173138Srwatson	return (0);
1888173138Srwatson}
1889173138Srwatson
1890173138Srwatsonstatic int
1891173138Srwatsonlomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1892173138Srwatson{
1893173138Srwatson	struct mac_lomac *subj, *obj;
1894173138Srwatson
1895173138Srwatson	if (!lomac_enabled)
1896173138Srwatson		return (0);
1897173138Srwatson
1898173138Srwatson	subj = SLOT(cred->cr_label);
1899173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1900173138Srwatson
1901173138Srwatson	/* XXX: range checks */
1902173138Srwatson	if (!lomac_dominate_single(obj, subj))
1903173138Srwatson		return (ESRCH);
1904173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1905173138Srwatson		return (EACCES);
1906173138Srwatson
1907173138Srwatson	return (0);
1908173138Srwatson}
1909173138Srwatson
1910173138Srwatsonstatic void
1911173138Srwatsonlomac_proc_destroy_label(struct label *label)
1912173138Srwatson{
1913173138Srwatson
1914173138Srwatson	mtx_destroy(&PSLOT(label)->mtx);
1915184205Sdes	free(PSLOT(label), M_LOMAC);
1916173138Srwatson	PSLOT_SET(label, NULL);
1917173138Srwatson}
1918173138Srwatson
1919173138Srwatsonstatic void
1920173138Srwatsonlomac_proc_init_label(struct label *label)
1921173138Srwatson{
1922173138Srwatson
1923173138Srwatson	PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC,
1924173138Srwatson	    M_ZERO | M_WAITOK));
1925173138Srwatson	mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
1926173138Srwatson}
1927173138Srwatson
1928173138Srwatsonstatic int
1929173138Srwatsonlomac_socket_check_deliver(struct socket *so, struct label *solabel,
1930173138Srwatson    struct mbuf *m, struct label *mlabel)
1931173138Srwatson{
1932173138Srwatson	struct mac_lomac *p, *s;
1933173138Srwatson
1934173138Srwatson	if (!lomac_enabled)
1935173138Srwatson		return (0);
1936173138Srwatson
1937173138Srwatson	p = SLOT(mlabel);
1938173138Srwatson	s = SLOT(solabel);
1939173138Srwatson
1940173138Srwatson	return (lomac_equal_single(p, s) ? 0 : EACCES);
1941173138Srwatson}
1942173138Srwatson
1943173138Srwatsonstatic int
1944173138Srwatsonlomac_socket_check_relabel(struct ucred *cred, struct socket *so,
1945173138Srwatson    struct label *solabel, struct label *newlabel)
1946173138Srwatson{
1947173138Srwatson	struct mac_lomac *subj, *obj, *new;
1948173138Srwatson	int error;
1949173138Srwatson
1950173138Srwatson	new = SLOT(newlabel);
1951173138Srwatson	subj = SLOT(cred->cr_label);
1952173138Srwatson	obj = SLOT(solabel);
1953173138Srwatson
1954173138Srwatson	/*
1955173138Srwatson	 * If there is a LOMAC label update for the socket, it may be an
1956173138Srwatson	 * update of single.
1957173138Srwatson	 */
1958173138Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1959173138Srwatson	if (error)
1960173138Srwatson		return (error);
1961173138Srwatson
1962173138Srwatson	/*
1963173138Srwatson	 * To relabel a socket, the old socket single must be in the subject
1964173138Srwatson	 * range.
1965173138Srwatson	 */
1966173138Srwatson	if (!lomac_single_in_range(obj, subj))
1967173138Srwatson		return (EPERM);
1968173138Srwatson
1969173138Srwatson	/*
1970173138Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1971173138Srwatson	 */
1972173138Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1973173138Srwatson		/*
1974173138Srwatson		 * To relabel a socket, the new socket single must be in the
1975173138Srwatson		 * subject range.
1976173138Srwatson		 */
1977173138Srwatson		if (!lomac_single_in_range(new, subj))
1978173138Srwatson			return (EPERM);
1979173138Srwatson
1980173138Srwatson		/*
1981173138Srwatson		 * To change the LOMAC label on the socket to contain EQUAL,
1982173138Srwatson		 * the subject must have appropriate privilege.
1983173138Srwatson		 */
1984173138Srwatson		if (lomac_contains_equal(new)) {
1985173138Srwatson			error = lomac_subject_privileged(subj);
1986173138Srwatson			if (error)
1987173138Srwatson				return (error);
1988173138Srwatson		}
1989173138Srwatson	}
1990173138Srwatson
1991173138Srwatson	return (0);
1992173138Srwatson}
1993173138Srwatson
1994173138Srwatsonstatic int
1995173138Srwatsonlomac_socket_check_visible(struct ucred *cred, struct socket *so,
1996173138Srwatson    struct label *solabel)
1997173138Srwatson{
1998173138Srwatson	struct mac_lomac *subj, *obj;
1999173138Srwatson
2000173138Srwatson	if (!lomac_enabled)
2001173138Srwatson		return (0);
2002173138Srwatson
2003173138Srwatson	subj = SLOT(cred->cr_label);
2004173138Srwatson	obj = SLOT(solabel);
2005173138Srwatson
2006173138Srwatson	if (!lomac_dominate_single(obj, subj))
2007173138Srwatson		return (ENOENT);
2008173138Srwatson
2009173138Srwatson	return (0);
2010173138Srwatson}
2011173138Srwatson
2012173138Srwatsonstatic void
2013173138Srwatsonlomac_socket_create(struct ucred *cred, struct socket *so,
2014173138Srwatson    struct label *solabel)
2015173138Srwatson{
2016173138Srwatson	struct mac_lomac *source, *dest;
2017173138Srwatson
2018173138Srwatson	source = SLOT(cred->cr_label);
2019173138Srwatson	dest = SLOT(solabel);
2020173138Srwatson
2021173138Srwatson	lomac_copy_single(source, dest);
2022173138Srwatson}
2023173138Srwatson
2024173138Srwatsonstatic void
2025173138Srwatsonlomac_socket_create_mbuf(struct socket *so, struct label *solabel,
2026173138Srwatson    struct mbuf *m, struct label *mlabel)
2027173138Srwatson{
2028173138Srwatson	struct mac_lomac *source, *dest;
2029173138Srwatson
2030173138Srwatson	source = SLOT(solabel);
2031173138Srwatson	dest = SLOT(mlabel);
2032173138Srwatson
2033173138Srwatson	lomac_copy_single(source, dest);
2034173138Srwatson}
2035173138Srwatson
2036173138Srwatsonstatic void
2037173138Srwatsonlomac_socket_newconn(struct socket *oldso, struct label *oldsolabel,
2038173138Srwatson    struct socket *newso, struct label *newsolabel)
2039173138Srwatson{
2040173138Srwatson	struct mac_lomac *source, *dest;
2041173138Srwatson
2042173138Srwatson	source = SLOT(oldsolabel);
2043173138Srwatson	dest = SLOT(newsolabel);
2044173138Srwatson
2045173138Srwatson	lomac_copy_single(source, dest);
2046173138Srwatson}
2047173138Srwatson
2048173138Srwatsonstatic void
2049173138Srwatsonlomac_socket_relabel(struct ucred *cred, struct socket *so,
2050173138Srwatson    struct label *solabel, struct label *newlabel)
2051173138Srwatson{
2052173138Srwatson	struct mac_lomac *source, *dest;
2053173138Srwatson
2054173138Srwatson	source = SLOT(newlabel);
2055173138Srwatson	dest = SLOT(solabel);
2056173138Srwatson
2057173138Srwatson	try_relabel(source, dest);
2058173138Srwatson}
2059173138Srwatson
2060173138Srwatsonstatic void
2061173138Srwatsonlomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
2062173138Srwatson    struct socket *so, struct label *sopeerlabel)
2063173138Srwatson{
2064173138Srwatson	struct mac_lomac *source, *dest;
2065173138Srwatson
2066173138Srwatson	source = SLOT(mlabel);
2067173138Srwatson	dest = SLOT(sopeerlabel);
2068173138Srwatson
2069173138Srwatson	lomac_copy_single(source, dest);
2070173138Srwatson}
2071173138Srwatson
2072173138Srwatsonstatic void
2073173138Srwatsonlomac_socketpeer_set_from_socket(struct socket *oldso,
2074173138Srwatson    struct label *oldsolabel, struct socket *newso,
2075173138Srwatson    struct label *newsopeerlabel)
2076173138Srwatson{
2077173138Srwatson	struct mac_lomac *source, *dest;
2078173138Srwatson
2079173138Srwatson	source = SLOT(oldsolabel);
2080173138Srwatson	dest = SLOT(newsopeerlabel);
2081173138Srwatson
2082173138Srwatson	lomac_copy_single(source, dest);
2083173138Srwatson}
2084173138Srwatson
2085173138Srwatsonstatic void
2086173138Srwatsonlomac_syncache_create(struct label *label, struct inpcb *inp)
2087173138Srwatson{
2088173138Srwatson	struct mac_lomac *source, *dest;
2089173138Srwatson
2090173138Srwatson	source = SLOT(inp->inp_label);
2091173138Srwatson	dest = SLOT(label);
2092173138Srwatson	lomac_copy(source, dest);
2093173138Srwatson}
2094173138Srwatson
2095173138Srwatsonstatic void
2096173138Srwatsonlomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2097173138Srwatson    struct label *mlabel)
2098173138Srwatson{
2099173138Srwatson	struct mac_lomac *source, *dest;
2100173138Srwatson
2101173138Srwatson	source = SLOT(sc_label);
2102173138Srwatson	dest = SLOT(mlabel);
2103173138Srwatson	lomac_copy(source, dest);
2104173138Srwatson}
2105173138Srwatson
2106173138Srwatsonstatic int
2107172955Srwatsonlomac_system_check_acct(struct ucred *cred, struct vnode *vp,
2108168976Srwatson    struct label *vplabel)
2109168933Srwatson{
2110168933Srwatson	struct mac_lomac *subj, *obj;
2111168933Srwatson
2112172955Srwatson	if (!lomac_enabled)
2113168933Srwatson		return (0);
2114168933Srwatson
2115168933Srwatson	subj = SLOT(cred->cr_label);
2116168976Srwatson	obj = SLOT(vplabel);
2117168933Srwatson
2118172955Srwatson	if (lomac_subject_privileged(subj))
2119168933Srwatson		return (EPERM);
2120168933Srwatson
2121172955Srwatson	if (!lomac_high_single(obj))
2122168933Srwatson		return (EACCES);
2123168933Srwatson
2124168933Srwatson	return (0);
2125168933Srwatson}
2126168933Srwatson
2127168933Srwatsonstatic int
2128172955Srwatsonlomac_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2129168976Srwatson    struct label *vplabel)
2130168933Srwatson{
2131168933Srwatson	struct mac_lomac *subj, *obj;
2132168933Srwatson
2133172955Srwatson	if (!lomac_enabled)
2134168933Srwatson		return (0);
2135168933Srwatson
2136168933Srwatson	subj = SLOT(cred->cr_label);
2137168976Srwatson	obj = SLOT(vplabel);
2138168933Srwatson
2139172955Srwatson	if (lomac_subject_privileged(subj))
2140168933Srwatson		return (EPERM);
2141168933Srwatson
2142172955Srwatson	if (!lomac_high_single(obj))
2143168933Srwatson		return (EACCES);
2144168933Srwatson
2145168933Srwatson	return (0);
2146168933Srwatson}
2147168933Srwatson
2148168933Srwatsonstatic int
2149172955Srwatsonlomac_system_check_swapoff(struct ucred *cred, struct vnode *vp,
2150168976Srwatson    struct label *vplabel)
2151168933Srwatson{
2152168933Srwatson	struct mac_lomac *subj;
2153168933Srwatson
2154172955Srwatson	if (!lomac_enabled)
2155168933Srwatson		return (0);
2156168933Srwatson
2157168933Srwatson	subj = SLOT(cred->cr_label);
2158168933Srwatson
2159172955Srwatson	if (lomac_subject_privileged(subj))
2160168933Srwatson		return (EPERM);
2161168933Srwatson
2162168933Srwatson	return (0);
2163168933Srwatson}
2164168933Srwatson
2165168933Srwatsonstatic int
2166172955Srwatsonlomac_system_check_swapon(struct ucred *cred, struct vnode *vp,
2167168976Srwatson    struct label *vplabel)
2168107273Srwatson{
2169107273Srwatson	struct mac_lomac *subj, *obj;
2170107273Srwatson
2171172955Srwatson	if (!lomac_enabled)
2172107273Srwatson		return (0);
2173107273Srwatson
2174122524Srwatson	subj = SLOT(cred->cr_label);
2175168976Srwatson	obj = SLOT(vplabel);
2176107273Srwatson
2177172955Srwatson	if (lomac_subject_privileged(subj))
2178107273Srwatson		return (EPERM);
2179107273Srwatson
2180172955Srwatson	if (!lomac_high_single(obj))
2181107273Srwatson		return (EACCES);
2182107273Srwatson
2183107273Srwatson	return (0);
2184107273Srwatson}
2185107273Srwatson
2186107273Srwatsonstatic int
2187172955Srwatsonlomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2188126121Spjd    void *arg1, int arg2, struct sysctl_req *req)
2189107273Srwatson{
2190107273Srwatson	struct mac_lomac *subj;
2191107273Srwatson
2192172955Srwatson	if (!lomac_enabled)
2193107273Srwatson		return (0);
2194107273Srwatson
2195122524Srwatson	subj = SLOT(cred->cr_label);
2196107273Srwatson
2197107273Srwatson	/*
2198172955Srwatson	 * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high,
2199172955Srwatson	 * but also require privilege to change them.
2200107273Srwatson	 */
2201126121Spjd	if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2202107273Srwatson#ifdef notdef
2203172955Srwatson		if (!lomac_subject_dominate_high(subj))
2204107273Srwatson			return (EACCES);
2205107273Srwatson#endif
2206107273Srwatson
2207172955Srwatson		if (lomac_subject_privileged(subj))
2208107273Srwatson			return (EPERM);
2209107273Srwatson	}
2210107273Srwatson
2211107273Srwatson	return (0);
2212107273Srwatson}
2213107273Srwatson
2214173138Srwatsonstatic void
2215173138Srwatsonlomac_thread_userret(struct thread *td)
2216173138Srwatson{
2217173138Srwatson	struct proc *p = td->td_proc;
2218173138Srwatson	struct mac_lomac_proc *subj = PSLOT(p->p_label);
2219173138Srwatson	struct ucred *newcred, *oldcred;
2220173138Srwatson	int dodrop;
2221173138Srwatson
2222173138Srwatson	mtx_lock(&subj->mtx);
2223173138Srwatson	if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2224173138Srwatson		dodrop = 0;
2225173138Srwatson		mtx_unlock(&subj->mtx);
2226173138Srwatson		newcred = crget();
2227173138Srwatson		/*
2228184412Srwatson		 * Prevent a lock order reversal in mac_proc_vm_revoke;
2229184412Srwatson		 * ideally, the other user of subj->mtx wouldn't be holding
2230184412Srwatson		 * Giant.
2231173138Srwatson		 */
2232173138Srwatson		mtx_lock(&Giant);
2233173138Srwatson		PROC_LOCK(p);
2234173138Srwatson		mtx_lock(&subj->mtx);
2235173138Srwatson		/*
2236173138Srwatson		 * Check if we lost the race while allocating the cred.
2237173138Srwatson		 */
2238173138Srwatson		if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2239173138Srwatson			crfree(newcred);
2240173138Srwatson			goto out;
2241173138Srwatson		}
2242173138Srwatson		oldcred = p->p_ucred;
2243173138Srwatson		crcopy(newcred, oldcred);
2244173138Srwatson		crhold(newcred);
2245173138Srwatson		lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2246173138Srwatson		p->p_ucred = newcred;
2247173138Srwatson		crfree(oldcred);
2248173138Srwatson		dodrop = 1;
2249173138Srwatson	out:
2250173138Srwatson		mtx_unlock(&subj->mtx);
2251173138Srwatson		PROC_UNLOCK(p);
2252173138Srwatson		if (dodrop)
2253184412Srwatson			mac_proc_vm_revoke(curthread);
2254173138Srwatson		mtx_unlock(&Giant);
2255173138Srwatson	} else {
2256173138Srwatson		mtx_unlock(&subj->mtx);
2257173138Srwatson	}
2258173138Srwatson}
2259173138Srwatson
2260107273Srwatsonstatic int
2261173138Srwatsonlomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2262173138Srwatson    struct vnode *vp, struct label *vplabel)
2263173138Srwatson{
2264173138Srwatson	struct mac_lomac ml_temp, *source, *dest;
2265173138Srwatson	int buflen, error;
2266173138Srwatson
2267173138Srwatson	source = SLOT(mplabel);
2268173138Srwatson	dest = SLOT(vplabel);
2269173138Srwatson
2270173138Srwatson	buflen = sizeof(ml_temp);
2271173138Srwatson	bzero(&ml_temp, buflen);
2272173138Srwatson
2273173138Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2274173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread);
2275173138Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
2276173138Srwatson		/* Fall back to the mntlabel. */
2277173138Srwatson		lomac_copy_single(source, dest);
2278173138Srwatson		return (0);
2279173138Srwatson	} else if (error)
2280173138Srwatson		return (error);
2281173138Srwatson
2282173138Srwatson	if (buflen != sizeof(ml_temp)) {
2283173138Srwatson		if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) {
2284173138Srwatson			printf("lomac_vnode_associate_extattr: bad size %d\n",
2285173138Srwatson			    buflen);
2286173138Srwatson			return (EPERM);
2287173138Srwatson		}
2288173138Srwatson		bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle));
2289173138Srwatson		buflen = sizeof(ml_temp);
2290173138Srwatson		(void)vn_extattr_set(vp, IO_NODELOCKED,
2291173138Srwatson		    MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
2292173138Srwatson		    buflen, (char *)&ml_temp, curthread);
2293173138Srwatson	}
2294173138Srwatson	if (lomac_valid(&ml_temp) != 0) {
2295173138Srwatson		printf("lomac_vnode_associate_extattr: invalid\n");
2296173138Srwatson		return (EPERM);
2297173138Srwatson	}
2298173138Srwatson	if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) !=
2299173138Srwatson	    MAC_LOMAC_FLAG_SINGLE) {
2300173138Srwatson		printf("lomac_vnode_associate_extattr: not single\n");
2301173138Srwatson		return (EPERM);
2302173138Srwatson	}
2303173138Srwatson
2304173138Srwatson	lomac_copy_single(&ml_temp, dest);
2305173138Srwatson	return (0);
2306173138Srwatson}
2307173138Srwatson
2308173138Srwatsonstatic void
2309173138Srwatsonlomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2310173138Srwatson    struct vnode *vp, struct label *vplabel)
2311173138Srwatson{
2312173138Srwatson	struct mac_lomac *source, *dest;
2313173138Srwatson
2314173138Srwatson	source = SLOT(mplabel);
2315173138Srwatson	dest = SLOT(vplabel);
2316173138Srwatson
2317173138Srwatson	lomac_copy_single(source, dest);
2318173138Srwatson}
2319173138Srwatson
2320173138Srwatsonstatic int
2321172955Srwatsonlomac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2322168976Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2323107273Srwatson{
2324107273Srwatson	struct mac_lomac *subj, *obj;
2325107273Srwatson
2326172955Srwatson	if (!lomac_enabled)
2327107273Srwatson		return (0);
2328107273Srwatson
2329122524Srwatson	subj = SLOT(cred->cr_label);
2330168976Srwatson	obj = SLOT(dvplabel);
2331107273Srwatson
2332172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2333107273Srwatson		return (EACCES);
2334107273Srwatson	if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2335172955Srwatson	    !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2336107273Srwatson		return (EACCES);
2337107273Srwatson
2338107273Srwatson	return (0);
2339107273Srwatson}
2340107273Srwatson
2341107273Srwatsonstatic int
2342172955Srwatsonlomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2343168976Srwatson    struct label *vplabel, acl_type_t type)
2344107273Srwatson{
2345107273Srwatson	struct mac_lomac *subj, *obj;
2346107273Srwatson
2347172955Srwatson	if (!lomac_enabled)
2348107273Srwatson		return (0);
2349107273Srwatson
2350122524Srwatson	subj = SLOT(cred->cr_label);
2351168976Srwatson	obj = SLOT(vplabel);
2352107273Srwatson
2353172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2354107273Srwatson		return (EACCES);
2355107273Srwatson
2356107273Srwatson	return (0);
2357107273Srwatson}
2358107273Srwatson
2359107273Srwatsonstatic int
2360172955Srwatsonlomac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2361168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2362107273Srwatson    struct componentname *cnp)
2363107273Srwatson{
2364107273Srwatson	struct mac_lomac *subj, *obj;
2365107273Srwatson
2366172955Srwatson	if (!lomac_enabled)
2367107273Srwatson		return (0);
2368107273Srwatson
2369122524Srwatson	subj = SLOT(cred->cr_label);
2370168976Srwatson	obj = SLOT(dvplabel);
2371107273Srwatson
2372172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2373107273Srwatson		return (EACCES);
2374107273Srwatson
2375168976Srwatson	obj = SLOT(vplabel);
2376107273Srwatson
2377172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2378107273Srwatson		return (EACCES);
2379107273Srwatson
2380107273Srwatson	return (0);
2381107273Srwatson}
2382107273Srwatson
2383107273Srwatsonstatic int
2384172955Srwatsonlomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2385168976Srwatson    struct label *vplabel, int prot, int flags)
2386107273Srwatson{
2387107273Srwatson	struct mac_lomac *subj, *obj;
2388107273Srwatson
2389107273Srwatson	/*
2390107273Srwatson	 * Rely on the use of open()-time protections to handle
2391107273Srwatson	 * non-revocation cases.
2392107273Srwatson	 */
2393172955Srwatson	if (!lomac_enabled)
2394107273Srwatson		return (0);
2395107273Srwatson
2396122524Srwatson	subj = SLOT(cred->cr_label);
2397168976Srwatson	obj = SLOT(vplabel);
2398107273Srwatson
2399145076Scsjp	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2400172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2401107273Srwatson			return (EACCES);
2402107273Srwatson	}
2403107273Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2404172955Srwatson		if (!lomac_dominate_single(obj, subj))
2405107273Srwatson			return (maybe_demote(subj, obj, "mapping", "file", vp));
2406107273Srwatson	}
2407107273Srwatson
2408107273Srwatson	return (0);
2409107273Srwatson}
2410107273Srwatson
2411107273Srwatsonstatic void
2412172955Srwatsonlomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2413168976Srwatson    struct label *vplabel, /* XXX vm_prot_t */ int *prot)
2414107273Srwatson{
2415107273Srwatson	struct mac_lomac *subj, *obj;
2416107273Srwatson
2417107273Srwatson	/*
2418107273Srwatson	 * Rely on the use of open()-time protections to handle
2419107273Srwatson	 * non-revocation cases.
2420107273Srwatson	 */
2421172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2422107273Srwatson		return;
2423107273Srwatson
2424122524Srwatson	subj = SLOT(cred->cr_label);
2425168976Srwatson	obj = SLOT(vplabel);
2426107273Srwatson
2427172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2428107273Srwatson		*prot &= ~VM_PROT_WRITE;
2429107273Srwatson}
2430107273Srwatson
2431107273Srwatsonstatic int
2432172955Srwatsonlomac_vnode_check_open(struct ucred *cred, struct vnode *vp,
2433184413Strasz    struct label *vplabel, accmode_t accmode)
2434107273Srwatson{
2435107273Srwatson	struct mac_lomac *subj, *obj;
2436107273Srwatson
2437172955Srwatson	if (!lomac_enabled)
2438107273Srwatson		return (0);
2439107273Srwatson
2440122524Srwatson	subj = SLOT(cred->cr_label);
2441168976Srwatson	obj = SLOT(vplabel);
2442107273Srwatson
2443107273Srwatson	/* XXX privilege override for admin? */
2444184413Strasz	if (accmode & (VWRITE | VAPPEND | VADMIN)) {
2445172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2446107273Srwatson			return (EACCES);
2447107273Srwatson	}
2448107273Srwatson
2449107273Srwatson	return (0);
2450107273Srwatson}
2451107273Srwatson
2452107273Srwatsonstatic int
2453172955Srwatsonlomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2454168976Srwatson    struct vnode *vp, struct label *vplabel)
2455107273Srwatson{
2456107273Srwatson	struct mac_lomac *subj, *obj;
2457107273Srwatson
2458172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2459107273Srwatson		return (0);
2460107273Srwatson
2461122524Srwatson	subj = SLOT(active_cred->cr_label);
2462168976Srwatson	obj = SLOT(vplabel);
2463107273Srwatson
2464172955Srwatson	if (!lomac_dominate_single(obj, subj))
2465107273Srwatson		return (maybe_demote(subj, obj, "reading", "file", vp));
2466107273Srwatson
2467107273Srwatson	return (0);
2468107273Srwatson}
2469107273Srwatson
2470107273Srwatsonstatic int
2471172955Srwatsonlomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2472168976Srwatson    struct label *vplabel, struct label *newlabel)
2473107273Srwatson{
2474107273Srwatson	struct mac_lomac *old, *new, *subj;
2475107273Srwatson	int error;
2476107273Srwatson
2477168976Srwatson	old = SLOT(vplabel);
2478107273Srwatson	new = SLOT(newlabel);
2479122524Srwatson	subj = SLOT(cred->cr_label);
2480107273Srwatson
2481107273Srwatson	/*
2482107273Srwatson	 * If there is a LOMAC label update for the vnode, it must be a
2483107273Srwatson	 * single label, with an optional explicit auxiliary single.
2484107273Srwatson	 */
2485107273Srwatson	error = lomac_atmostflags(new,
2486107273Srwatson	    MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2487107273Srwatson	if (error)
2488107273Srwatson		return (error);
2489107273Srwatson
2490107273Srwatson	/*
2491107273Srwatson	 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2492107273Srwatson	 * authorize the relabel.
2493107273Srwatson	 */
2494172955Srwatson	if (!lomac_single_in_range(old, subj))
2495107273Srwatson		return (EPERM);
2496107273Srwatson
2497107273Srwatson	/*
2498107273Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
2499107273Srwatson	 */
2500107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2501107273Srwatson		/*
2502107273Srwatson		 * To change the LOMAC label on a vnode, the new vnode label
2503107273Srwatson		 * must be in the subject range.
2504107273Srwatson		 */
2505172955Srwatson		if (!lomac_single_in_range(new, subj))
2506107273Srwatson			return (EPERM);
2507107273Srwatson
2508107273Srwatson		/*
2509172955Srwatson		 * To change the LOMAC label on the vnode to be EQUAL, the
2510172955Srwatson		 * subject must have appropriate privilege.
2511107273Srwatson		 */
2512172955Srwatson		if (lomac_contains_equal(new)) {
2513172955Srwatson			error = lomac_subject_privileged(subj);
2514107273Srwatson			if (error)
2515107273Srwatson				return (error);
2516107273Srwatson		}
2517107273Srwatson	}
2518107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2519107273Srwatson		/*
2520119242Srwatson		 * Fill in the missing parts from the previous label.
2521119242Srwatson		 */
2522119242Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2523172955Srwatson			lomac_copy_single(subj, new);
2524119242Srwatson
2525119242Srwatson		/*
2526107273Srwatson		 * To change the auxiliary LOMAC label on a vnode, the new
2527107273Srwatson		 * vnode label must be in the subject range.
2528107273Srwatson		 */
2529172955Srwatson		if (!lomac_auxsingle_in_range(new, subj))
2530107273Srwatson			return (EPERM);
2531107273Srwatson
2532107273Srwatson		/*
2533107273Srwatson		 * To change the auxiliary LOMAC label on the vnode to be
2534107273Srwatson		 * EQUAL, the subject must have appropriate privilege.
2535107273Srwatson		 */
2536172955Srwatson		if (lomac_contains_equal(new)) {
2537172955Srwatson			error = lomac_subject_privileged(subj);
2538107273Srwatson			if (error)
2539107273Srwatson				return (error);
2540107273Srwatson		}
2541107273Srwatson	}
2542107273Srwatson
2543107273Srwatson	return (0);
2544107273Srwatson}
2545107273Srwatson
2546107273Srwatsonstatic int
2547172955Srwatsonlomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2548168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2549107273Srwatson    struct componentname *cnp)
2550107273Srwatson{
2551107273Srwatson	struct mac_lomac *subj, *obj;
2552107273Srwatson
2553172955Srwatson	if (!lomac_enabled)
2554107273Srwatson		return (0);
2555107273Srwatson
2556122524Srwatson	subj = SLOT(cred->cr_label);
2557168976Srwatson	obj = SLOT(dvplabel);
2558107273Srwatson
2559172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2560107273Srwatson		return (EACCES);
2561107273Srwatson
2562168976Srwatson	obj = SLOT(vplabel);
2563107273Srwatson
2564172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2565107273Srwatson		return (EACCES);
2566107273Srwatson
2567107273Srwatson	return (0);
2568107273Srwatson}
2569107273Srwatson
2570107273Srwatsonstatic int
2571172955Srwatsonlomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2572168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2573168976Srwatson    int samedir, struct componentname *cnp)
2574107273Srwatson{
2575107273Srwatson	struct mac_lomac *subj, *obj;
2576107273Srwatson
2577172955Srwatson	if (!lomac_enabled)
2578107273Srwatson		return (0);
2579107273Srwatson
2580122524Srwatson	subj = SLOT(cred->cr_label);
2581168976Srwatson	obj = SLOT(dvplabel);
2582107273Srwatson
2583172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2584107273Srwatson		return (EACCES);
2585107273Srwatson
2586107273Srwatson	if (vp != NULL) {
2587168976Srwatson		obj = SLOT(vplabel);
2588107273Srwatson
2589172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2590107273Srwatson			return (EACCES);
2591107273Srwatson	}
2592107273Srwatson
2593107273Srwatson	return (0);
2594107273Srwatson}
2595107273Srwatson
2596107273Srwatsonstatic int
2597172955Srwatsonlomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2598168976Srwatson    struct label *vplabel)
2599107273Srwatson{
2600107273Srwatson	struct mac_lomac *subj, *obj;
2601107273Srwatson
2602172955Srwatson	if (!lomac_enabled)
2603107273Srwatson		return (0);
2604107273Srwatson
2605122524Srwatson	subj = SLOT(cred->cr_label);
2606168976Srwatson	obj = SLOT(vplabel);
2607107273Srwatson
2608172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2609107273Srwatson		return (EACCES);
2610107273Srwatson
2611107273Srwatson	return (0);
2612107273Srwatson}
2613107273Srwatson
2614107273Srwatsonstatic int
2615172955Srwatsonlomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2616168976Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
2617107273Srwatson{
2618107273Srwatson	struct mac_lomac *subj, *obj;
2619107273Srwatson
2620172955Srwatson	if (!lomac_enabled)
2621107273Srwatson		return (0);
2622107273Srwatson
2623122524Srwatson	subj = SLOT(cred->cr_label);
2624168976Srwatson	obj = SLOT(vplabel);
2625107273Srwatson
2626172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2627107273Srwatson		return (EACCES);
2628107273Srwatson
2629107273Srwatson	return (0);
2630107273Srwatson}
2631107273Srwatson
2632107273Srwatsonstatic int
2633172955Srwatsonlomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2634168976Srwatson    struct label *vplabel, int attrnamespace, const char *name,
2635107273Srwatson    struct uio *uio)
2636107273Srwatson{
2637107273Srwatson	struct mac_lomac *subj, *obj;
2638107273Srwatson
2639172955Srwatson	if (!lomac_enabled)
2640107273Srwatson		return (0);
2641107273Srwatson
2642122524Srwatson	subj = SLOT(cred->cr_label);
2643168976Srwatson	obj = SLOT(vplabel);
2644107273Srwatson
2645172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2646107273Srwatson		return (EACCES);
2647107273Srwatson
2648107273Srwatson	/* XXX: protect the MAC EA in a special way? */
2649107273Srwatson
2650107273Srwatson	return (0);
2651107273Srwatson}
2652107273Srwatson
2653107273Srwatsonstatic int
2654172955Srwatsonlomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2655168976Srwatson    struct label *vplabel, u_long flags)
2656107273Srwatson{
2657107273Srwatson	struct mac_lomac *subj, *obj;
2658107273Srwatson
2659172955Srwatson	if (!lomac_enabled)
2660107273Srwatson		return (0);
2661107273Srwatson
2662122524Srwatson	subj = SLOT(cred->cr_label);
2663168976Srwatson	obj = SLOT(vplabel);
2664107273Srwatson
2665172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2666107273Srwatson		return (EACCES);
2667107273Srwatson
2668107273Srwatson	return (0);
2669107273Srwatson}
2670107273Srwatson
2671107273Srwatsonstatic int
2672172955Srwatsonlomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2673168976Srwatson    struct label *vplabel, mode_t mode)
2674107273Srwatson{
2675107273Srwatson	struct mac_lomac *subj, *obj;
2676107273Srwatson
2677172955Srwatson	if (!lomac_enabled)
2678107273Srwatson		return (0);
2679107273Srwatson
2680122524Srwatson	subj = SLOT(cred->cr_label);
2681168976Srwatson	obj = SLOT(vplabel);
2682107273Srwatson
2683172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2684107273Srwatson		return (EACCES);
2685107273Srwatson
2686107273Srwatson	return (0);
2687107273Srwatson}
2688107273Srwatson
2689107273Srwatsonstatic int
2690172955Srwatsonlomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2691168976Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
2692107273Srwatson{
2693107273Srwatson	struct mac_lomac *subj, *obj;
2694107273Srwatson
2695172955Srwatson	if (!lomac_enabled)
2696107273Srwatson		return (0);
2697107273Srwatson
2698122524Srwatson	subj = SLOT(cred->cr_label);
2699168976Srwatson	obj = SLOT(vplabel);
2700107273Srwatson
2701172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2702107273Srwatson		return (EACCES);
2703107273Srwatson
2704107273Srwatson	return (0);
2705107273Srwatson}
2706107273Srwatson
2707107273Srwatsonstatic int
2708172955Srwatsonlomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2709168976Srwatson    struct label *vplabel, struct timespec atime, struct timespec mtime)
2710107273Srwatson{
2711107273Srwatson	struct mac_lomac *subj, *obj;
2712107273Srwatson
2713172955Srwatson	if (!lomac_enabled)
2714107273Srwatson		return (0);
2715107273Srwatson
2716122524Srwatson	subj = SLOT(cred->cr_label);
2717168976Srwatson	obj = SLOT(vplabel);
2718107273Srwatson
2719172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2720107273Srwatson		return (EACCES);
2721107273Srwatson
2722107273Srwatson	return (0);
2723107273Srwatson}
2724107273Srwatson
2725107273Srwatsonstatic int
2726172955Srwatsonlomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2727172107Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2728172107Srwatson    struct componentname *cnp)
2729172107Srwatson{
2730172107Srwatson	struct mac_lomac *subj, *obj;
2731172107Srwatson
2732172955Srwatson	if (!lomac_enabled)
2733172107Srwatson		return (0);
2734172107Srwatson
2735172107Srwatson	subj = SLOT(cred->cr_label);
2736172107Srwatson	obj = SLOT(dvplabel);
2737172107Srwatson
2738172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2739172107Srwatson		return (EACCES);
2740172107Srwatson
2741172107Srwatson	obj = SLOT(vplabel);
2742172107Srwatson
2743172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2744172107Srwatson		return (EACCES);
2745172107Srwatson
2746172107Srwatson	return (0);
2747172107Srwatson}
2748172107Srwatson
2749172107Srwatsonstatic int
2750172955Srwatsonlomac_vnode_check_write(struct ucred *active_cred,
2751168976Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
2752107273Srwatson{
2753107273Srwatson	struct mac_lomac *subj, *obj;
2754107273Srwatson
2755172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2756107273Srwatson		return (0);
2757107273Srwatson
2758122524Srwatson	subj = SLOT(active_cred->cr_label);
2759168976Srwatson	obj = SLOT(vplabel);
2760107273Srwatson
2761172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2762107273Srwatson		return (EACCES);
2763107273Srwatson
2764107273Srwatson	return (0);
2765107273Srwatson}
2766107273Srwatson
2767173138Srwatsonstatic int
2768173138Srwatsonlomac_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2769173138Srwatson    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2770173138Srwatson    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2771107273Srwatson{
2772173138Srwatson	struct mac_lomac *source, *dest, *dir, temp;
2773173138Srwatson	size_t buflen;
2774173138Srwatson	int error;
2775107273Srwatson
2776173138Srwatson	buflen = sizeof(temp);
2777173138Srwatson	bzero(&temp, buflen);
2778173138Srwatson
2779173138Srwatson	source = SLOT(cred->cr_label);
2780173138Srwatson	dest = SLOT(vplabel);
2781173138Srwatson	dir = SLOT(dvplabel);
2782173138Srwatson	if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
2783173138Srwatson		lomac_copy_auxsingle(dir, &temp);
2784173138Srwatson		lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
2785173138Srwatson		    dir->ml_auxsingle.mle_grade);
2786107273Srwatson	} else {
2787173138Srwatson		lomac_copy_single(source, &temp);
2788107273Srwatson	}
2789173138Srwatson
2790173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2791173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2792173138Srwatson	if (error == 0)
2793173138Srwatson		lomac_copy(&temp, dest);
2794173138Srwatson	return (error);
2795107273Srwatson}
2796107273Srwatson
2797173138Srwatsonstatic void
2798173138Srwatsonlomac_vnode_execve_transition(struct ucred *old, struct ucred *new,
2799173138Srwatson    struct vnode *vp, struct label *vplabel, struct label *interpvplabel,
2800173138Srwatson    struct image_params *imgp, struct label *execlabel)
2801173138Srwatson{
2802173138Srwatson	struct mac_lomac *source, *dest, *obj, *robj;
2803173138Srwatson
2804173138Srwatson	source = SLOT(old->cr_label);
2805173138Srwatson	dest = SLOT(new->cr_label);
2806173138Srwatson	obj = SLOT(vplabel);
2807173138Srwatson	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2808173138Srwatson
2809173138Srwatson	lomac_copy(source, dest);
2810173138Srwatson	/*
2811173138Srwatson	 * If there's an auxiliary label on the real object, respect it and
2812173138Srwatson	 * assume that this level should be assumed immediately if a higher
2813173138Srwatson	 * level is currently in place.
2814173138Srwatson	 */
2815173138Srwatson	if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2816173138Srwatson	    !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
2817173138Srwatson	    && lomac_auxsingle_in_range(robj, dest))
2818173138Srwatson		lomac_set_single(dest, robj->ml_auxsingle.mle_type,
2819173138Srwatson		    robj->ml_auxsingle.mle_grade);
2820173138Srwatson	/*
2821173138Srwatson	 * Restructuring to use the execve transitioning mechanism instead of
2822173138Srwatson	 * the normal demotion mechanism here would be difficult, so just
2823173138Srwatson	 * copy the label over and perform standard demotion.  This is also
2824173138Srwatson	 * non-optimal because it will result in the intermediate label "new"
2825173138Srwatson	 * being created and immediately recycled.
2826173138Srwatson	 */
2827173138Srwatson	if (lomac_enabled && revocation_enabled &&
2828173138Srwatson	    !lomac_dominate_single(obj, source))
2829173138Srwatson		(void)maybe_demote(source, obj, "executing", "file", vp);
2830173138Srwatson}
2831173138Srwatson
2832173138Srwatsonstatic int
2833173138Srwatsonlomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
2834173138Srwatson    struct label *vplabel, struct label *interpvplabel,
2835173138Srwatson    struct image_params *imgp, struct label *execlabel)
2836173138Srwatson{
2837173138Srwatson	struct mac_lomac *subj, *obj, *robj;
2838173138Srwatson
2839173138Srwatson	if (!lomac_enabled || !revocation_enabled)
2840173138Srwatson		return (0);
2841173138Srwatson
2842173138Srwatson	subj = SLOT(old->cr_label);
2843173138Srwatson	obj = SLOT(vplabel);
2844173138Srwatson	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2845173138Srwatson
2846173138Srwatson	return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2847173138Srwatson	    !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
2848173138Srwatson	    && lomac_auxsingle_in_range(robj, subj)) ||
2849173138Srwatson	    !lomac_dominate_single(obj, subj));
2850173138Srwatson}
2851173138Srwatson
2852173138Srwatsonstatic void
2853173138Srwatsonlomac_vnode_relabel(struct ucred *cred, struct vnode *vp,
2854173138Srwatson    struct label *vplabel, struct label *newlabel)
2855173138Srwatson{
2856173138Srwatson	struct mac_lomac *source, *dest;
2857173138Srwatson
2858173138Srwatson	source = SLOT(newlabel);
2859173138Srwatson	dest = SLOT(vplabel);
2860173138Srwatson
2861173138Srwatson	try_relabel(source, dest);
2862173138Srwatson}
2863173138Srwatson
2864173138Srwatsonstatic int
2865173138Srwatsonlomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2866173138Srwatson    struct label *vplabel, struct label *intlabel)
2867173138Srwatson{
2868173138Srwatson	struct mac_lomac *source, temp;
2869173138Srwatson	size_t buflen;
2870173138Srwatson	int error;
2871173138Srwatson
2872173138Srwatson	buflen = sizeof(temp);
2873173138Srwatson	bzero(&temp, buflen);
2874173138Srwatson
2875173138Srwatson	source = SLOT(intlabel);
2876173138Srwatson	if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2877173138Srwatson		return (0);
2878173138Srwatson
2879173138Srwatson	lomac_copy_single(source, &temp);
2880173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2881173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2882173138Srwatson	return (error);
2883173138Srwatson}
2884173138Srwatson
2885172955Srwatsonstatic struct mac_policy_ops lomac_ops =
2886107273Srwatson{
2887172955Srwatson	.mpo_init = lomac_init,
2888173138Srwatson
2889173138Srwatson	.mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive,
2890173138Srwatson	.mpo_bpfdesc_create = lomac_bpfdesc_create,
2891173138Srwatson	.mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf,
2892173138Srwatson	.mpo_bpfdesc_destroy_label = lomac_destroy_label,
2893172955Srwatson	.mpo_bpfdesc_init_label = lomac_init_label,
2894173138Srwatson
2895173138Srwatson	.mpo_cred_check_relabel = lomac_cred_check_relabel,
2896173138Srwatson	.mpo_cred_check_visible = lomac_cred_check_visible,
2897173138Srwatson	.mpo_cred_copy_label = lomac_copy_label,
2898184407Srwatson	.mpo_cred_create_swapper = lomac_cred_create_swapper,
2899184407Srwatson	.mpo_cred_create_init = lomac_cred_create_init,
2900172955Srwatson	.mpo_cred_destroy_label = lomac_destroy_label,
2901172955Srwatson	.mpo_cred_externalize_label = lomac_externalize_label,
2902173138Srwatson	.mpo_cred_init_label = lomac_init_label,
2903172955Srwatson	.mpo_cred_internalize_label = lomac_internalize_label,
2904173138Srwatson	.mpo_cred_relabel = lomac_cred_relabel,
2905173138Srwatson
2906172955Srwatson	.mpo_devfs_create_device = lomac_devfs_create_device,
2907172955Srwatson	.mpo_devfs_create_directory = lomac_devfs_create_directory,
2908172955Srwatson	.mpo_devfs_create_symlink = lomac_devfs_create_symlink,
2909173138Srwatson	.mpo_devfs_destroy_label = lomac_destroy_label,
2910173138Srwatson	.mpo_devfs_init_label = lomac_init_label,
2911172955Srwatson	.mpo_devfs_update = lomac_devfs_update,
2912172955Srwatson	.mpo_devfs_vnode_associate = lomac_devfs_vnode_associate,
2913173138Srwatson
2914173138Srwatson	.mpo_ifnet_check_relabel = lomac_ifnet_check_relabel,
2915173138Srwatson	.mpo_ifnet_check_transmit = lomac_ifnet_check_transmit,
2916173138Srwatson	.mpo_ifnet_copy_label = lomac_copy_label,
2917172955Srwatson	.mpo_ifnet_create = lomac_ifnet_create,
2918173138Srwatson	.mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf,
2919173138Srwatson	.mpo_ifnet_destroy_label = lomac_destroy_label,
2920173138Srwatson	.mpo_ifnet_externalize_label = lomac_externalize_label,
2921173138Srwatson	.mpo_ifnet_init_label = lomac_init_label,
2922173138Srwatson	.mpo_ifnet_internalize_label = lomac_internalize_label,
2923173138Srwatson	.mpo_ifnet_relabel = lomac_ifnet_relabel,
2924173138Srwatson
2925173138Srwatson	.mpo_syncache_create = lomac_syncache_create,
2926173138Srwatson	.mpo_syncache_destroy_label = lomac_destroy_label,
2927173138Srwatson	.mpo_syncache_init_label = lomac_init_label_waitcheck,
2928173138Srwatson
2929173138Srwatson	.mpo_inpcb_check_deliver = lomac_inpcb_check_deliver,
2930183980Sbz	.mpo_inpcb_check_visible = lomac_inpcb_check_visible,
2931172955Srwatson	.mpo_inpcb_create = lomac_inpcb_create,
2932173138Srwatson	.mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf,
2933173138Srwatson	.mpo_inpcb_destroy_label = lomac_destroy_label,
2934173138Srwatson	.mpo_inpcb_init_label = lomac_init_label_waitcheck,
2935173138Srwatson	.mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel,
2936173138Srwatson
2937184308Srwatson	.mpo_ip6q_create = lomac_ip6q_create,
2938184308Srwatson	.mpo_ip6q_destroy_label = lomac_destroy_label,
2939184308Srwatson	.mpo_ip6q_init_label = lomac_init_label_waitcheck,
2940184308Srwatson	.mpo_ip6q_match = lomac_ip6q_match,
2941184308Srwatson	.mpo_ip6q_reassemble = lomac_ip6q_reassemble,
2942184308Srwatson	.mpo_ip6q_update = lomac_ip6q_update,
2943184308Srwatson
2944172955Srwatson	.mpo_ipq_create = lomac_ipq_create,
2945173138Srwatson	.mpo_ipq_destroy_label = lomac_destroy_label,
2946173138Srwatson	.mpo_ipq_init_label = lomac_init_label_waitcheck,
2947172955Srwatson	.mpo_ipq_match = lomac_ipq_match,
2948173138Srwatson	.mpo_ipq_reassemble = lomac_ipq_reassemble,
2949172955Srwatson	.mpo_ipq_update = lomac_ipq_update,
2950173138Srwatson
2951172955Srwatson	.mpo_kld_check_load = lomac_kld_check_load,
2952173138Srwatson
2953173138Srwatson	.mpo_mbuf_copy_label = lomac_copy_label,
2954173138Srwatson	.mpo_mbuf_destroy_label = lomac_destroy_label,
2955173138Srwatson	.mpo_mbuf_init_label = lomac_init_label_waitcheck,
2956173138Srwatson
2957173138Srwatson	.mpo_mount_create = lomac_mount_create,
2958173138Srwatson	.mpo_mount_destroy_label = lomac_destroy_label,
2959173138Srwatson	.mpo_mount_init_label = lomac_init_label,
2960173138Srwatson
2961173138Srwatson	.mpo_netatalk_aarp_send = lomac_netatalk_aarp_send,
2962173138Srwatson
2963173138Srwatson	.mpo_netinet_arp_send = lomac_netinet_arp_send,
2964173138Srwatson	.mpo_netinet_firewall_reply = lomac_netinet_firewall_reply,
2965173138Srwatson	.mpo_netinet_firewall_send = lomac_netinet_firewall_send,
2966173138Srwatson	.mpo_netinet_fragment = lomac_netinet_fragment,
2967173138Srwatson	.mpo_netinet_icmp_reply = lomac_netinet_icmp_reply,
2968173138Srwatson	.mpo_netinet_igmp_send = lomac_netinet_igmp_send,
2969173138Srwatson
2970173138Srwatson	.mpo_netinet6_nd6_send = lomac_netinet6_nd6_send,
2971173138Srwatson
2972172955Srwatson	.mpo_pipe_check_ioctl = lomac_pipe_check_ioctl,
2973172955Srwatson	.mpo_pipe_check_read = lomac_pipe_check_read,
2974172955Srwatson	.mpo_pipe_check_relabel = lomac_pipe_check_relabel,
2975172955Srwatson	.mpo_pipe_check_write = lomac_pipe_check_write,
2976173138Srwatson	.mpo_pipe_copy_label = lomac_copy_label,
2977173138Srwatson	.mpo_pipe_create = lomac_pipe_create,
2978173138Srwatson	.mpo_pipe_destroy_label = lomac_destroy_label,
2979173138Srwatson	.mpo_pipe_externalize_label = lomac_externalize_label,
2980173138Srwatson	.mpo_pipe_init_label = lomac_init_label,
2981173138Srwatson	.mpo_pipe_internalize_label = lomac_internalize_label,
2982173138Srwatson	.mpo_pipe_relabel = lomac_pipe_relabel,
2983173138Srwatson
2984173138Srwatson	.mpo_priv_check = lomac_priv_check,
2985173138Srwatson
2986172955Srwatson	.mpo_proc_check_debug = lomac_proc_check_debug,
2987172955Srwatson	.mpo_proc_check_sched = lomac_proc_check_sched,
2988172955Srwatson	.mpo_proc_check_signal = lomac_proc_check_signal,
2989173138Srwatson	.mpo_proc_destroy_label = lomac_proc_destroy_label,
2990173138Srwatson	.mpo_proc_init_label = lomac_proc_init_label,
2991173138Srwatson
2992172955Srwatson	.mpo_socket_check_deliver = lomac_socket_check_deliver,
2993172955Srwatson	.mpo_socket_check_relabel = lomac_socket_check_relabel,
2994172955Srwatson	.mpo_socket_check_visible = lomac_socket_check_visible,
2995173138Srwatson	.mpo_socket_copy_label = lomac_copy_label,
2996173138Srwatson	.mpo_socket_create = lomac_socket_create,
2997173138Srwatson	.mpo_socket_create_mbuf = lomac_socket_create_mbuf,
2998173138Srwatson	.mpo_socket_destroy_label = lomac_destroy_label,
2999173138Srwatson	.mpo_socket_externalize_label = lomac_externalize_label,
3000173138Srwatson	.mpo_socket_init_label = lomac_init_label_waitcheck,
3001173138Srwatson	.mpo_socket_internalize_label = lomac_internalize_label,
3002173138Srwatson	.mpo_socket_newconn = lomac_socket_newconn,
3003173138Srwatson	.mpo_socket_relabel = lomac_socket_relabel,
3004173138Srwatson
3005173138Srwatson	.mpo_socketpeer_destroy_label = lomac_destroy_label,
3006173138Srwatson	.mpo_socketpeer_externalize_label = lomac_externalize_label,
3007173138Srwatson	.mpo_socketpeer_init_label = lomac_init_label_waitcheck,
3008173138Srwatson	.mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf,
3009173138Srwatson	.mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket,
3010173138Srwatson
3011173138Srwatson	.mpo_syncache_create_mbuf = lomac_syncache_create_mbuf,
3012173138Srwatson
3013172955Srwatson	.mpo_system_check_acct = lomac_system_check_acct,
3014172955Srwatson	.mpo_system_check_auditctl = lomac_system_check_auditctl,
3015172955Srwatson	.mpo_system_check_swapoff = lomac_system_check_swapoff,
3016172955Srwatson	.mpo_system_check_swapon = lomac_system_check_swapon,
3017172955Srwatson	.mpo_system_check_sysctl = lomac_system_check_sysctl,
3018173138Srwatson
3019173138Srwatson	.mpo_thread_userret = lomac_thread_userret,
3020173138Srwatson
3021173138Srwatson	.mpo_vnode_associate_extattr = lomac_vnode_associate_extattr,
3022173138Srwatson	.mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel,
3023172955Srwatson	.mpo_vnode_check_access = lomac_vnode_check_open,
3024172955Srwatson	.mpo_vnode_check_create = lomac_vnode_check_create,
3025172955Srwatson	.mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl,
3026172955Srwatson	.mpo_vnode_check_link = lomac_vnode_check_link,
3027172955Srwatson	.mpo_vnode_check_mmap = lomac_vnode_check_mmap,
3028172955Srwatson	.mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade,
3029172955Srwatson	.mpo_vnode_check_open = lomac_vnode_check_open,
3030172955Srwatson	.mpo_vnode_check_read = lomac_vnode_check_read,
3031172955Srwatson	.mpo_vnode_check_relabel = lomac_vnode_check_relabel,
3032172955Srwatson	.mpo_vnode_check_rename_from = lomac_vnode_check_rename_from,
3033172955Srwatson	.mpo_vnode_check_rename_to = lomac_vnode_check_rename_to,
3034172955Srwatson	.mpo_vnode_check_revoke = lomac_vnode_check_revoke,
3035172955Srwatson	.mpo_vnode_check_setacl = lomac_vnode_check_setacl,
3036172955Srwatson	.mpo_vnode_check_setextattr = lomac_vnode_check_setextattr,
3037172955Srwatson	.mpo_vnode_check_setflags = lomac_vnode_check_setflags,
3038172955Srwatson	.mpo_vnode_check_setmode = lomac_vnode_check_setmode,
3039172955Srwatson	.mpo_vnode_check_setowner = lomac_vnode_check_setowner,
3040172955Srwatson	.mpo_vnode_check_setutimes = lomac_vnode_check_setutimes,
3041172955Srwatson	.mpo_vnode_check_unlink = lomac_vnode_check_unlink,
3042172955Srwatson	.mpo_vnode_check_write = lomac_vnode_check_write,
3043173138Srwatson	.mpo_vnode_copy_label = lomac_copy_label,
3044173138Srwatson	.mpo_vnode_create_extattr = lomac_vnode_create_extattr,
3045173138Srwatson	.mpo_vnode_destroy_label = lomac_destroy_label,
3046173138Srwatson	.mpo_vnode_execve_transition = lomac_vnode_execve_transition,
3047173138Srwatson	.mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition,
3048173138Srwatson	.mpo_vnode_externalize_label = lomac_externalize_label,
3049173138Srwatson	.mpo_vnode_init_label = lomac_init_label,
3050173138Srwatson	.mpo_vnode_internalize_label = lomac_internalize_label,
3051173138Srwatson	.mpo_vnode_relabel = lomac_vnode_relabel,
3052173138Srwatson	.mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr,
3053107273Srwatson};
3054107273Srwatson
3055172955SrwatsonMAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
3056187016Srwatson    MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot);
3057