1107273Srwatson/*-
2193391Srwatson * Copyright (c) 1999-2002, 2007-2009 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$
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
96227309Sedstatic SYSCTL_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
140227293Sedstatic MALLOC_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;
765229272Sed	range = strchr(string, '(');
766107273Srwatson	if (range == single)
767107273Srwatson		single = NULL;
768229272Sed	auxsingle = strchr(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;
779229272Sed		rangehigh = strchr(rangelow, '-');
780107273Srwatson		if (rangehigh == NULL)
781107273Srwatson			return (EINVAL);
782107273Srwatson		rangehigh++;
783107273Srwatson		if (*rangelow == '\0' || *rangehigh == '\0')
784107273Srwatson			return (EINVAL);
785229272Sed		rangeend = strchr(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++;
801229272Sed		auxsingleend = strchr(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;
1035231378Sed	const char *dn;
1036173138Srwatson	int lomac_type;
1037122875Srwatson
1038173138Srwatson	ml = SLOT(delabel);
1039231378Sed	dn = devtoname(dev);
1040231378Sed	if (strcmp(dn, "null") == 0 ||
1041231378Sed	    strcmp(dn, "zero") == 0 ||
1042231378Sed	    strcmp(dn, "random") == 0 ||
1043231378Sed	    strncmp(dn, "fd/", strlen("fd/")) == 0 ||
1044231378Sed	    strncmp(dn, "ttyv", strlen("ttyv")) == 0)
1045173138Srwatson		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1046173138Srwatson	else if (ptys_equal &&
1047231378Sed	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
1048231378Sed	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
1049231378Sed	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
1050173138Srwatson		lomac_type = MAC_LOMAC_TYPE_EQUAL;
1051173138Srwatson	else
1052173138Srwatson		lomac_type = MAC_LOMAC_TYPE_HIGH;
1053173138Srwatson	lomac_set_single(ml, lomac_type, 0);
1054122875Srwatson}
1055122875Srwatson
1056122875Srwatsonstatic void
1057173138Srwatsonlomac_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
1058173138Srwatson    struct devfs_dirent *de, struct label *delabel)
1059107273Srwatson{
1060173138Srwatson	struct mac_lomac *ml;
1061107273Srwatson
1062173138Srwatson	ml = SLOT(delabel);
1063173138Srwatson	lomac_set_single(ml, MAC_LOMAC_TYPE_HIGH, 0);
1064107273Srwatson}
1065107273Srwatson
1066107273Srwatsonstatic void
1067173138Srwatsonlomac_devfs_create_symlink(struct ucred *cred, struct mount *mp,
1068173138Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
1069173138Srwatson    struct label *delabel)
1070107273Srwatson{
1071107273Srwatson	struct mac_lomac *source, *dest;
1072107273Srwatson
1073122524Srwatson	source = SLOT(cred->cr_label);
1074173138Srwatson	dest = SLOT(delabel);
1075107273Srwatson
1076172955Srwatson	lomac_copy_single(source, dest);
1077107273Srwatson}
1078107273Srwatson
1079107273Srwatsonstatic void
1080173138Srwatsonlomac_devfs_update(struct mount *mp, struct devfs_dirent *de,
1081173138Srwatson    struct label *delabel, struct vnode *vp, struct label *vplabel)
1082107273Srwatson{
1083107273Srwatson	struct mac_lomac *source, *dest;
1084107273Srwatson
1085173138Srwatson	source = SLOT(vplabel);
1086173138Srwatson	dest = SLOT(delabel);
1087107273Srwatson
1088173138Srwatson	lomac_copy(source, dest);
1089107273Srwatson}
1090107273Srwatson
1091107273Srwatsonstatic void
1092173138Srwatsonlomac_devfs_vnode_associate(struct mount *mp, struct label *mplabel,
1093173138Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
1094173138Srwatson    struct label *vplabel)
1095107273Srwatson{
1096107273Srwatson	struct mac_lomac *source, *dest;
1097107273Srwatson
1098173138Srwatson	source = SLOT(delabel);
1099173138Srwatson	dest = SLOT(vplabel);
1100107273Srwatson
1101172955Srwatson	lomac_copy_single(source, dest);
1102107273Srwatson}
1103107273Srwatson
1104173138Srwatsonstatic int
1105173138Srwatsonlomac_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
1106173138Srwatson    struct label *ifplabel, struct label *newlabel)
1107107273Srwatson{
1108173138Srwatson	struct mac_lomac *subj, *new;
1109173138Srwatson	int error;
1110107273Srwatson
1111173138Srwatson	subj = SLOT(cred->cr_label);
1112173138Srwatson	new = SLOT(newlabel);
1113107273Srwatson
1114173138Srwatson	/*
1115173138Srwatson	 * If there is a LOMAC label update for the interface, it may be an
1116173138Srwatson	 * update of the single, range, or both.
1117173138Srwatson	 */
1118173138Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAGS_BOTH);
1119173138Srwatson	if (error)
1120173138Srwatson		return (error);
1121107273Srwatson
1122173138Srwatson	/*
1123173138Srwatson	 * Relabling network interfaces requires LOMAC privilege.
1124173138Srwatson	 */
1125173138Srwatson	error = lomac_subject_privileged(subj);
1126173138Srwatson	if (error)
1127173138Srwatson		return (error);
1128107273Srwatson
1129173138Srwatson	/*
1130173138Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1131173138Srwatson	 */
1132173138Srwatson	if (new->ml_flags & MAC_LOMAC_FLAGS_BOTH) {
1133173138Srwatson		/*
1134173138Srwatson		 * Fill in the missing parts from the previous label.
1135173138Srwatson		 */
1136173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
1137173138Srwatson			lomac_copy_single(subj, new);
1138173138Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_RANGE) == 0)
1139173138Srwatson			lomac_copy_range(subj, new);
1140107273Srwatson
1141173138Srwatson		/*
1142173138Srwatson		 * Rely on the traditional superuser status for the LOMAC
1143173138Srwatson		 * interface relabel requirements.  XXXMAC: This will go
1144173138Srwatson		 * away.
1145173138Srwatson		 *
1146173138Srwatson		 * XXXRW: This is also redundant to a higher layer check.
1147173138Srwatson		 */
1148173138Srwatson		error = priv_check_cred(cred, PRIV_NET_SETIFMAC, 0);
1149173138Srwatson		if (error)
1150173138Srwatson			return (EPERM);
1151107273Srwatson
1152173138Srwatson		/*
1153173138Srwatson		 * XXXMAC: Additional consistency tests regarding the single
1154173138Srwatson		 * and the range of the new label might be performed here.
1155173138Srwatson		 */
1156173138Srwatson	}
1157107273Srwatson
1158173138Srwatson	return (0);
1159107273Srwatson}
1160107273Srwatson
1161173138Srwatsonstatic int
1162173138Srwatsonlomac_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1163173138Srwatson    struct mbuf *m, struct label *mlabel)
1164107273Srwatson{
1165173138Srwatson	struct mac_lomac *p, *i;
1166107273Srwatson
1167173138Srwatson	if (!lomac_enabled)
1168173138Srwatson		return (0);
1169107273Srwatson
1170173138Srwatson	p = SLOT(mlabel);
1171173138Srwatson	i = SLOT(ifplabel);
1172107273Srwatson
1173173138Srwatson	return (lomac_single_in_range(p, i) ? 0 : EACCES);
1174107273Srwatson}
1175107273Srwatson
1176107273Srwatsonstatic void
1177172955Srwatsonlomac_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1178107273Srwatson{
1179121816Sbrooks	char tifname[IFNAMSIZ], *p, *q;
1180107273Srwatson	char tiflist[sizeof(trusted_interfaces)];
1181107273Srwatson	struct mac_lomac *dest;
1182107273Srwatson	int len, grade;
1183107273Srwatson
1184168976Srwatson	dest = SLOT(ifplabel);
1185107273Srwatson
1186168976Srwatson	if (ifp->if_type == IFT_LOOP) {
1187107273Srwatson		grade = MAC_LOMAC_TYPE_EQUAL;
1188107273Srwatson		goto set;
1189107273Srwatson	}
1190107273Srwatson
1191107273Srwatson	if (trust_all_interfaces) {
1192107273Srwatson		grade = MAC_LOMAC_TYPE_HIGH;
1193107273Srwatson		goto set;
1194107273Srwatson	}
1195107273Srwatson
1196107273Srwatson	grade = MAC_LOMAC_TYPE_LOW;
1197107273Srwatson
1198107273Srwatson	if (trusted_interfaces[0] == '\0' ||
1199107273Srwatson	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1200107273Srwatson		goto set;
1201107273Srwatson
1202107273Srwatson	bzero(tiflist, sizeof(tiflist));
1203107273Srwatson	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1204107273Srwatson		if(*p != ' ' && *p != '\t')
1205107273Srwatson			*q = *p;
1206107273Srwatson
1207107273Srwatson	for (p = q = tiflist;; p++) {
1208107273Srwatson		if (*p == ',' || *p == '\0') {
1209107273Srwatson			len = p - q;
1210107273Srwatson			if (len < IFNAMSIZ) {
1211107273Srwatson				bzero(tifname, sizeof(tifname));
1212107273Srwatson				bcopy(q, tifname, len);
1213168976Srwatson				if (strcmp(tifname, ifp->if_xname) == 0) {
1214107273Srwatson					grade = MAC_LOMAC_TYPE_HIGH;
1215107273Srwatson					break;
1216107273Srwatson				}
1217107273Srwatson			}
1218107273Srwatson			else {
1219107273Srwatson				*p = '\0';
1220107273Srwatson				printf("MAC/LOMAC warning: interface name "
1221107273Srwatson				    "\"%s\" is too long (must be < %d)\n",
1222107273Srwatson				    q, IFNAMSIZ);
1223107273Srwatson			}
1224107273Srwatson			if (*p == '\0')
1225107273Srwatson				break;
1226107273Srwatson			q = p + 1;
1227107273Srwatson		}
1228107273Srwatson	}
1229107273Srwatsonset:
1230172955Srwatson	lomac_set_single(dest, grade, 0);
1231172955Srwatson	lomac_set_range(dest, grade, 0, grade, 0);
1232107273Srwatson}
1233107273Srwatson
1234107273Srwatsonstatic void
1235173138Srwatsonlomac_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1236173138Srwatson    struct mbuf *m, struct label *mlabel)
1237107273Srwatson{
1238107273Srwatson	struct mac_lomac *source, *dest;
1239107273Srwatson
1240173138Srwatson	source = SLOT(ifplabel);
1241173138Srwatson	dest = SLOT(mlabel);
1242107273Srwatson
1243172955Srwatson	lomac_copy_single(source, dest);
1244107273Srwatson}
1245107273Srwatson
1246107273Srwatsonstatic void
1247173138Srwatsonlomac_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1248173138Srwatson    struct label *ifplabel, struct label *newlabel)
1249107273Srwatson{
1250107273Srwatson	struct mac_lomac *source, *dest;
1251107273Srwatson
1252173138Srwatson	source = SLOT(newlabel);
1253173138Srwatson	dest = SLOT(ifplabel);
1254107273Srwatson
1255173138Srwatson	try_relabel(source, dest);
1256107273Srwatson}
1257107273Srwatson
1258173138Srwatsonstatic int
1259173138Srwatsonlomac_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1260173138Srwatson    struct mbuf *m, struct label *mlabel)
1261173138Srwatson{
1262173138Srwatson	struct mac_lomac *p, *i;
1263173138Srwatson
1264173138Srwatson	if (!lomac_enabled)
1265173138Srwatson		return (0);
1266173138Srwatson
1267173138Srwatson	p = SLOT(mlabel);
1268173138Srwatson	i = SLOT(inplabel);
1269173138Srwatson
1270173138Srwatson	return (lomac_equal_single(p, i) ? 0 : EACCES);
1271173138Srwatson}
1272173138Srwatson
1273183980Sbzstatic int
1274183980Sbzlomac_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1275183980Sbz    struct label *inplabel)
1276183980Sbz{
1277183980Sbz	struct mac_lomac *subj, *obj;
1278183980Sbz
1279183980Sbz	if (!lomac_enabled)
1280183980Sbz		return (0);
1281183980Sbz
1282183980Sbz	subj = SLOT(cred->cr_label);
1283183980Sbz	obj = SLOT(inplabel);
1284183980Sbz
1285183980Sbz	if (!lomac_dominate_single(obj, subj))
1286183980Sbz		return (ENOENT);
1287183980Sbz
1288183980Sbz	return (0);
1289183980Sbz}
1290183980Sbz
1291107273Srwatsonstatic void
1292173138Srwatsonlomac_inpcb_create(struct socket *so, struct label *solabel,
1293173138Srwatson    struct inpcb *inp, struct label *inplabel)
1294107273Srwatson{
1295107273Srwatson	struct mac_lomac *source, *dest;
1296107273Srwatson
1297173138Srwatson	source = SLOT(solabel);
1298173138Srwatson	dest = SLOT(inplabel);
1299107273Srwatson
1300172955Srwatson	lomac_copy_single(source, dest);
1301107273Srwatson}
1302107273Srwatson
1303107273Srwatsonstatic void
1304172955Srwatsonlomac_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1305123607Srwatson    struct mbuf *m, struct label *mlabel)
1306123607Srwatson{
1307123607Srwatson	struct mac_lomac *source, *dest;
1308123607Srwatson
1309123607Srwatson	source = SLOT(inplabel);
1310123607Srwatson	dest = SLOT(mlabel);
1311123607Srwatson
1312172955Srwatson	lomac_copy_single(source, dest);
1313123607Srwatson}
1314123607Srwatson
1315123607Srwatsonstatic void
1316173138Srwatsonlomac_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1317173138Srwatson    struct inpcb *inp, struct label *inplabel)
1318107273Srwatson{
1319107273Srwatson	struct mac_lomac *source, *dest;
1320107273Srwatson
1321193391Srwatson	SOCK_LOCK_ASSERT(so);
1322193391Srwatson
1323173138Srwatson	source = SLOT(solabel);
1324173138Srwatson	dest = SLOT(inplabel);
1325107273Srwatson
1326172955Srwatson	lomac_copy_single(source, dest);
1327107273Srwatson}
1328107273Srwatson
1329107273Srwatsonstatic void
1330184308Srwatsonlomac_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1331184308Srwatson    struct label *q6label)
1332184308Srwatson{
1333184308Srwatson	struct mac_lomac *source, *dest;
1334184308Srwatson
1335184308Srwatson	source = SLOT(mlabel);
1336184308Srwatson	dest = SLOT(q6label);
1337184308Srwatson
1338184308Srwatson	lomac_copy_single(source, dest);
1339184308Srwatson}
1340184308Srwatson
1341184308Srwatsonstatic int
1342184308Srwatsonlomac_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1343184308Srwatson    struct label *q6label)
1344184308Srwatson{
1345184308Srwatson	struct mac_lomac *a, *b;
1346184308Srwatson
1347184308Srwatson	a = SLOT(q6label);
1348184308Srwatson	b = SLOT(mlabel);
1349184308Srwatson
1350184308Srwatson	return (lomac_equal_single(a, b));
1351184308Srwatson}
1352184308Srwatson
1353184308Srwatsonstatic void
1354184308Srwatsonlomac_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1355184308Srwatson    struct label *mlabel)
1356184308Srwatson{
1357184308Srwatson	struct mac_lomac *source, *dest;
1358184308Srwatson
1359184308Srwatson	source = SLOT(q6label);
1360184308Srwatson	dest = SLOT(mlabel);
1361184308Srwatson
1362184308Srwatson	/* Just use the head, since we require them all to match. */
1363184308Srwatson	lomac_copy_single(source, dest);
1364184308Srwatson}
1365184308Srwatson
1366184308Srwatsonstatic void
1367184308Srwatsonlomac_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1368184308Srwatson    struct label *q6label)
1369184308Srwatson{
1370184308Srwatson
1371184308Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1372184308Srwatson}
1373184308Srwatson
1374184308Srwatsonstatic void
1375179781Srwatsonlomac_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1376179781Srwatson    struct label *qlabel)
1377107273Srwatson{
1378107273Srwatson	struct mac_lomac *source, *dest;
1379107273Srwatson
1380173138Srwatson	source = SLOT(mlabel);
1381179781Srwatson	dest = SLOT(qlabel);
1382107273Srwatson
1383172955Srwatson	lomac_copy_single(source, dest);
1384107273Srwatson}
1385107273Srwatson
1386107273Srwatsonstatic int
1387179781Srwatsonlomac_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1388179781Srwatson    struct label *qlabel)
1389107273Srwatson{
1390107273Srwatson	struct mac_lomac *a, *b;
1391107273Srwatson
1392179781Srwatson	a = SLOT(qlabel);
1393168976Srwatson	b = SLOT(mlabel);
1394107273Srwatson
1395172955Srwatson	return (lomac_equal_single(a, b));
1396107273Srwatson}
1397107273Srwatson
1398107273Srwatsonstatic void
1399179781Srwatsonlomac_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1400179781Srwatson    struct label *mlabel)
1401107273Srwatson{
1402107273Srwatson	struct mac_lomac *source, *dest;
1403107273Srwatson
1404179781Srwatson	source = SLOT(qlabel);
1405173138Srwatson	dest = SLOT(mlabel);
1406107273Srwatson
1407173138Srwatson	/* Just use the head, since we require them all to match. */
1408173138Srwatson	lomac_copy_single(source, dest);
1409107273Srwatson}
1410107273Srwatson
1411107273Srwatsonstatic void
1412179781Srwatsonlomac_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1413179781Srwatson    struct label *qlabel)
1414107273Srwatson{
1415107273Srwatson
1416107273Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1417107273Srwatson}
1418107273Srwatson
1419173138Srwatsonstatic int
1420173138Srwatsonlomac_kld_check_load(struct ucred *cred, struct vnode *vp,
1421173138Srwatson    struct label *vplabel)
1422122875Srwatson{
1423173138Srwatson	struct mac_lomac *subj, *obj;
1424122875Srwatson
1425173138Srwatson	if (!lomac_enabled)
1426173138Srwatson		return (0);
1427122875Srwatson
1428173138Srwatson	subj = SLOT(cred->cr_label);
1429173138Srwatson	obj = SLOT(vplabel);
1430122875Srwatson
1431173138Srwatson	if (lomac_subject_privileged(subj))
1432173138Srwatson		return (EPERM);
1433165150Scsjp
1434173138Srwatson	if (!lomac_high_single(obj))
1435173138Srwatson		return (EACCES);
1436173138Srwatson
1437173138Srwatson	return (0);
1438165150Scsjp}
1439165150Scsjp
1440165150Scsjpstatic void
1441173138Srwatsonlomac_mount_create(struct ucred *cred, struct mount *mp,
1442173138Srwatson    struct label *mplabel)
1443165150Scsjp{
1444165150Scsjp	struct mac_lomac *source, *dest;
1445165150Scsjp
1446173138Srwatson	source = SLOT(cred->cr_label);
1447173138Srwatson	dest = SLOT(mplabel);
1448173138Srwatson	lomac_copy_single(source, dest);
1449165150Scsjp}
1450165150Scsjp
1451165150Scsjpstatic void
1452173095Srwatsonlomac_netatalk_aarp_send(struct ifnet *ifp, struct label *ifplabel,
1453173095Srwatson    struct mbuf *m, struct label *mlabel)
1454173095Srwatson{
1455173095Srwatson	struct mac_lomac *dest;
1456173095Srwatson
1457173095Srwatson	dest = SLOT(mlabel);
1458173095Srwatson
1459173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1460173095Srwatson}
1461173095Srwatson
1462173095Srwatsonstatic void
1463173095Srwatsonlomac_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1464173095Srwatson    struct mbuf *m, struct label *mlabel)
1465173095Srwatson{
1466173095Srwatson	struct mac_lomac *dest;
1467173095Srwatson
1468173095Srwatson	dest = SLOT(mlabel);
1469173095Srwatson
1470173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1471173095Srwatson}
1472173095Srwatson
1473173095Srwatsonstatic void
1474173102Srwatsonlomac_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1475173102Srwatson    struct mbuf *msend, struct label *msendlabel)
1476173102Srwatson{
1477173102Srwatson	struct mac_lomac *source, *dest;
1478173102Srwatson
1479173102Srwatson	source = SLOT(mrecvlabel);
1480173102Srwatson	dest = SLOT(msendlabel);
1481173102Srwatson
1482173102Srwatson	lomac_copy_single(source, dest);
1483173102Srwatson}
1484173102Srwatson
1485173102Srwatsonstatic void
1486173018Srwatsonlomac_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1487162238Scsjp{
1488162238Scsjp	struct mac_lomac *dest;
1489162238Scsjp
1490168976Srwatson	dest = SLOT(mlabel);
1491162238Scsjp
1492162238Scsjp	/* XXX: where is the label for the firewall really comming from? */
1493172955Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1494162238Scsjp}
1495162238Scsjp
1496173095Srwatsonstatic void
1497173138Srwatsonlomac_netinet_fragment(struct mbuf *m, struct label *mlabel,
1498173138Srwatson    struct mbuf *frag, struct label *fraglabel)
1499173138Srwatson{
1500173138Srwatson	struct mac_lomac *source, *dest;
1501173138Srwatson
1502173138Srwatson	source = SLOT(mlabel);
1503173138Srwatson	dest = SLOT(fraglabel);
1504173138Srwatson
1505173138Srwatson	lomac_copy_single(source, dest);
1506173138Srwatson}
1507173138Srwatson
1508173138Srwatsonstatic void
1509173102Srwatsonlomac_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1510173102Srwatson    struct mbuf *msend, struct label *msendlabel)
1511173102Srwatson{
1512173102Srwatson	struct mac_lomac *source, *dest;
1513173102Srwatson
1514173102Srwatson	source = SLOT(mrecvlabel);
1515173102Srwatson	dest = SLOT(msendlabel);
1516173102Srwatson
1517173102Srwatson	lomac_copy_single(source, dest);
1518173102Srwatson}
1519173102Srwatson
1520173102Srwatsonstatic void
1521173095Srwatsonlomac_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1522173095Srwatson    struct mbuf *m, struct label *mlabel)
1523173095Srwatson{
1524173095Srwatson	struct mac_lomac *dest;
1525173095Srwatson
1526173095Srwatson	dest = SLOT(mlabel);
1527173095Srwatson
1528173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1529173095Srwatson}
1530173095Srwatson
1531173095Srwatsonstatic void
1532173095Srwatsonlomac_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1533173095Srwatson    struct mbuf *m, struct label *mlabel)
1534173095Srwatson{
1535173095Srwatson	struct mac_lomac *dest;
1536173095Srwatson
1537173095Srwatson	dest = SLOT(mlabel);
1538173095Srwatson
1539173095Srwatson	lomac_set_single(dest, MAC_LOMAC_TYPE_EQUAL, 0);
1540173095Srwatson}
1541173095Srwatson
1542107273Srwatsonstatic int
1543172955Srwatsonlomac_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1544168976Srwatson    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1545107273Srwatson{
1546107273Srwatson
1547172955Srwatson	if (!lomac_enabled)
1548107273Srwatson		return (0);
1549107273Srwatson
1550107273Srwatson	/* XXX: This will be implemented soon... */
1551107273Srwatson
1552107273Srwatson	return (0);
1553107273Srwatson}
1554107273Srwatson
1555107273Srwatsonstatic int
1556172955Srwatsonlomac_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1557168976Srwatson    struct label *pplabel)
1558107273Srwatson{
1559107273Srwatson	struct mac_lomac *subj, *obj;
1560107273Srwatson
1561172955Srwatson	if (!lomac_enabled)
1562107273Srwatson		return (0);
1563107273Srwatson
1564122524Srwatson	subj = SLOT(cred->cr_label);
1565168976Srwatson	obj = SLOT(pplabel);
1566107273Srwatson
1567172955Srwatson	if (!lomac_dominate_single(obj, subj))
1568107273Srwatson		return (maybe_demote(subj, obj, "reading", "pipe", NULL));
1569107273Srwatson
1570107273Srwatson	return (0);
1571107273Srwatson}
1572107273Srwatson
1573107273Srwatsonstatic int
1574172955Srwatsonlomac_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1575168976Srwatson    struct label *pplabel, struct label *newlabel)
1576107273Srwatson{
1577107273Srwatson	struct mac_lomac *subj, *obj, *new;
1578107273Srwatson	int error;
1579107273Srwatson
1580107273Srwatson	new = SLOT(newlabel);
1581122524Srwatson	subj = SLOT(cred->cr_label);
1582168976Srwatson	obj = SLOT(pplabel);
1583107273Srwatson
1584107273Srwatson	/*
1585172955Srwatson	 * If there is a LOMAC label update for a pipe, it must be a single
1586172955Srwatson	 * update.
1587107273Srwatson	 */
1588107273Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1589107273Srwatson	if (error)
1590107273Srwatson		return (error);
1591107273Srwatson
1592107273Srwatson	/*
1593107273Srwatson	 * To perform a relabel of a pipe (LOMAC label or not), LOMAC must
1594107273Srwatson	 * authorize the relabel.
1595107273Srwatson	 */
1596172955Srwatson	if (!lomac_single_in_range(obj, subj))
1597107273Srwatson		return (EPERM);
1598107273Srwatson
1599107273Srwatson	/*
1600107273Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1601107273Srwatson	 */
1602107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1603107273Srwatson		/*
1604107273Srwatson		 * To change the LOMAC label on a pipe, the new pipe label
1605107273Srwatson		 * must be in the subject range.
1606107273Srwatson		 */
1607172955Srwatson		if (!lomac_single_in_range(new, subj))
1608107273Srwatson			return (EPERM);
1609107273Srwatson
1610107273Srwatson		/*
1611107273Srwatson		 * To change the LOMAC label on a pipe to be EQUAL, the
1612107273Srwatson		 * subject must have appropriate privilege.
1613107273Srwatson		 */
1614172955Srwatson		if (lomac_contains_equal(new)) {
1615172955Srwatson			error = lomac_subject_privileged(subj);
1616107273Srwatson			if (error)
1617107273Srwatson				return (error);
1618107273Srwatson		}
1619107273Srwatson	}
1620107273Srwatson
1621107273Srwatson	return (0);
1622107273Srwatson}
1623107273Srwatson
1624107273Srwatsonstatic int
1625172955Srwatsonlomac_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1626168976Srwatson    struct label *pplabel)
1627107273Srwatson{
1628107273Srwatson	struct mac_lomac *subj, *obj;
1629107273Srwatson
1630172955Srwatson	if (!lomac_enabled)
1631107273Srwatson		return (0);
1632107273Srwatson
1633122524Srwatson	subj = SLOT(cred->cr_label);
1634168976Srwatson	obj = SLOT(pplabel);
1635107273Srwatson
1636172955Srwatson	if (!lomac_subject_dominate(subj, obj))
1637107273Srwatson		return (EACCES);
1638107273Srwatson
1639107273Srwatson	return (0);
1640107273Srwatson}
1641107273Srwatson
1642173138Srwatsonstatic void
1643173138Srwatsonlomac_pipe_create(struct ucred *cred, struct pipepair *pp,
1644173138Srwatson    struct label *pplabel)
1645107273Srwatson{
1646173138Srwatson	struct mac_lomac *source, *dest;
1647107273Srwatson
1648173138Srwatson	source = SLOT(cred->cr_label);
1649173138Srwatson	dest = SLOT(pplabel);
1650107273Srwatson
1651173138Srwatson	lomac_copy_single(source, dest);
1652107273Srwatson}
1653107273Srwatson
1654173138Srwatsonstatic void
1655173138Srwatsonlomac_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1656173138Srwatson    struct label *pplabel, struct label *newlabel)
1657107273Srwatson{
1658173138Srwatson	struct mac_lomac *source, *dest;
1659107273Srwatson
1660173138Srwatson	source = SLOT(newlabel);
1661173138Srwatson	dest = SLOT(pplabel);
1662107273Srwatson
1663173138Srwatson	try_relabel(source, dest);
1664107273Srwatson}
1665107273Srwatson
1666168951Srwatson/*
1667168951Srwatson * Some system privileges are allowed regardless of integrity grade; others
1668168951Srwatson * are allowed only when running with privilege with respect to the LOMAC
1669168951Srwatson * policy as they might otherwise allow bypassing of the integrity policy.
1670168951Srwatson */
1671107273Srwatsonstatic int
1672172955Srwatsonlomac_priv_check(struct ucred *cred, int priv)
1673168951Srwatson{
1674168951Srwatson	struct mac_lomac *subj;
1675168951Srwatson	int error;
1676168951Srwatson
1677172955Srwatson	if (!lomac_enabled)
1678168951Srwatson		return (0);
1679168951Srwatson
1680168951Srwatson	/*
1681168951Srwatson	 * Exempt only specific privileges from the LOMAC integrity policy.
1682168951Srwatson	 */
1683168951Srwatson	switch (priv) {
1684168951Srwatson	case PRIV_KTRACE:
1685168951Srwatson	case PRIV_MSGBUF:
1686168951Srwatson
1687168951Srwatson	/*
1688168951Srwatson	 * Allow processes to manipulate basic process audit properties, and
1689168951Srwatson	 * to submit audit records.
1690168951Srwatson	 */
1691168951Srwatson	case PRIV_AUDIT_GETAUDIT:
1692168951Srwatson	case PRIV_AUDIT_SETAUDIT:
1693168951Srwatson	case PRIV_AUDIT_SUBMIT:
1694168951Srwatson
1695168951Srwatson	/*
1696168951Srwatson	 * Allow processes to manipulate their regular UNIX credentials.
1697168951Srwatson	 */
1698168951Srwatson	case PRIV_CRED_SETUID:
1699168951Srwatson	case PRIV_CRED_SETEUID:
1700168951Srwatson	case PRIV_CRED_SETGID:
1701168951Srwatson	case PRIV_CRED_SETEGID:
1702168951Srwatson	case PRIV_CRED_SETGROUPS:
1703168951Srwatson	case PRIV_CRED_SETREUID:
1704168951Srwatson	case PRIV_CRED_SETREGID:
1705168951Srwatson	case PRIV_CRED_SETRESUID:
1706168951Srwatson	case PRIV_CRED_SETRESGID:
1707168951Srwatson
1708168951Srwatson	/*
1709168951Srwatson	 * Allow processes to perform system monitoring.
1710168951Srwatson	 */
1711168951Srwatson	case PRIV_SEEOTHERGIDS:
1712168951Srwatson	case PRIV_SEEOTHERUIDS:
1713168951Srwatson		break;
1714168951Srwatson
1715168951Srwatson	/*
1716168951Srwatson	 * Allow access to general process debugging facilities.  We
1717168951Srwatson	 * separately control debugging based on MAC label.
1718168951Srwatson	 */
1719168951Srwatson	case PRIV_DEBUG_DIFFCRED:
1720168951Srwatson	case PRIV_DEBUG_SUGID:
1721168951Srwatson	case PRIV_DEBUG_UNPRIV:
1722168951Srwatson
1723168951Srwatson	/*
1724168951Srwatson	 * Allow manipulating jails.
1725168951Srwatson	 */
1726168951Srwatson	case PRIV_JAIL_ATTACH:
1727168951Srwatson
1728168951Srwatson	/*
1729168951Srwatson	 * Allow privilege with respect to the Partition policy, but not the
1730168951Srwatson	 * Privs policy.
1731168951Srwatson	 */
1732168951Srwatson	case PRIV_MAC_PARTITION:
1733168951Srwatson
1734168951Srwatson	/*
1735168951Srwatson	 * Allow privilege with respect to process resource limits and login
1736168951Srwatson	 * context.
1737168951Srwatson	 */
1738168951Srwatson	case PRIV_PROC_LIMIT:
1739168951Srwatson	case PRIV_PROC_SETLOGIN:
1740168951Srwatson	case PRIV_PROC_SETRLIMIT:
1741168951Srwatson
1742168951Srwatson	/*
1743168951Srwatson	 * Allow System V and POSIX IPC privileges.
1744168951Srwatson	 */
1745168951Srwatson	case PRIV_IPC_READ:
1746168951Srwatson	case PRIV_IPC_WRITE:
1747168951Srwatson	case PRIV_IPC_ADMIN:
1748168951Srwatson	case PRIV_IPC_MSGSIZE:
1749168951Srwatson	case PRIV_MQ_ADMIN:
1750168951Srwatson
1751168951Srwatson	/*
1752168951Srwatson	 * Allow certain scheduler manipulations -- possibly this should be
1753168951Srwatson	 * controlled by more fine-grained policy, as potentially low
1754168951Srwatson	 * integrity processes can deny CPU to higher integrity ones.
1755168951Srwatson	 */
1756168951Srwatson	case PRIV_SCHED_DIFFCRED:
1757168951Srwatson	case PRIV_SCHED_SETPRIORITY:
1758168951Srwatson	case PRIV_SCHED_RTPRIO:
1759168951Srwatson	case PRIV_SCHED_SETPOLICY:
1760168951Srwatson	case PRIV_SCHED_SET:
1761168951Srwatson	case PRIV_SCHED_SETPARAM:
1762168951Srwatson
1763168951Srwatson	/*
1764168951Srwatson	 * More IPC privileges.
1765168951Srwatson	 */
1766168951Srwatson	case PRIV_SEM_WRITE:
1767168951Srwatson
1768168951Srwatson	/*
1769168951Srwatson	 * Allow signaling privileges subject to integrity policy.
1770168951Srwatson	 */
1771168951Srwatson	case PRIV_SIGNAL_DIFFCRED:
1772168951Srwatson	case PRIV_SIGNAL_SUGID:
1773168951Srwatson
1774168951Srwatson	/*
1775168951Srwatson	 * Allow access to only limited sysctls from lower integrity levels;
1776168951Srwatson	 * piggy-back on the Jail definition.
1777168951Srwatson	 */
1778168951Srwatson	case PRIV_SYSCTL_WRITEJAIL:
1779168951Srwatson
1780168951Srwatson	/*
1781168951Srwatson	 * Allow TTY-based privileges, subject to general device access using
1782168951Srwatson	 * labels on TTY device nodes, but not console privilege.
1783168951Srwatson	 */
1784168951Srwatson	case PRIV_TTY_DRAINWAIT:
1785168951Srwatson	case PRIV_TTY_DTRWAIT:
1786168951Srwatson	case PRIV_TTY_EXCLUSIVE:
1787168951Srwatson	case PRIV_TTY_STI:
1788168951Srwatson	case PRIV_TTY_SETA:
1789168951Srwatson
1790168951Srwatson	/*
1791168951Srwatson	 * Grant most VFS privileges, as almost all are in practice bounded
1792168951Srwatson	 * by more specific checks using labels.
1793168951Srwatson	 */
1794168951Srwatson	case PRIV_VFS_READ:
1795168951Srwatson	case PRIV_VFS_WRITE:
1796168951Srwatson	case PRIV_VFS_ADMIN:
1797168951Srwatson	case PRIV_VFS_EXEC:
1798168951Srwatson	case PRIV_VFS_LOOKUP:
1799168951Srwatson	case PRIV_VFS_CHFLAGS_DEV:
1800168951Srwatson	case PRIV_VFS_CHOWN:
1801168951Srwatson	case PRIV_VFS_CHROOT:
1802168951Srwatson	case PRIV_VFS_RETAINSUGID:
1803168951Srwatson	case PRIV_VFS_EXCEEDQUOTA:
1804168951Srwatson	case PRIV_VFS_FCHROOT:
1805168951Srwatson	case PRIV_VFS_FHOPEN:
1806168951Srwatson	case PRIV_VFS_FHSTATFS:
1807168951Srwatson	case PRIV_VFS_GENERATION:
1808168951Srwatson	case PRIV_VFS_GETFH:
1809168951Srwatson	case PRIV_VFS_GETQUOTA:
1810168951Srwatson	case PRIV_VFS_LINK:
1811168951Srwatson	case PRIV_VFS_MOUNT:
1812168951Srwatson	case PRIV_VFS_MOUNT_OWNER:
1813168951Srwatson	case PRIV_VFS_MOUNT_PERM:
1814168951Srwatson	case PRIV_VFS_MOUNT_SUIDDIR:
1815168951Srwatson	case PRIV_VFS_MOUNT_NONUSER:
1816168951Srwatson	case PRIV_VFS_SETGID:
1817168951Srwatson	case PRIV_VFS_STICKYFILE:
1818168951Srwatson	case PRIV_VFS_SYSFLAGS:
1819168951Srwatson	case PRIV_VFS_UNMOUNT:
1820168951Srwatson
1821168951Srwatson	/*
1822168951Srwatson	 * Allow VM privileges; it would be nice if these were subject to
1823168951Srwatson	 * resource limits.
1824168951Srwatson	 */
1825168951Srwatson	case PRIV_VM_MADV_PROTECT:
1826168951Srwatson	case PRIV_VM_MLOCK:
1827168951Srwatson	case PRIV_VM_MUNLOCK:
1828194766Skib	case PRIV_VM_SWAP_NOQUOTA:
1829194766Skib	case PRIV_VM_SWAP_NORLIMIT:
1830168951Srwatson
1831168951Srwatson	/*
1832168951Srwatson	 * Allow some but not all network privileges.  In general, dont allow
1833168951Srwatson	 * reconfiguring the network stack, just normal use.
1834168951Srwatson	 */
1835168951Srwatson	case PRIV_NETATALK_RESERVEDPORT:
1836168951Srwatson	case PRIV_NETINET_RESERVEDPORT:
1837168951Srwatson	case PRIV_NETINET_RAW:
1838168951Srwatson	case PRIV_NETINET_REUSEPORT:
1839168951Srwatson	case PRIV_NETIPX_RESERVEDPORT:
1840168951Srwatson	case PRIV_NETIPX_RAW:
1841168951Srwatson		break;
1842168951Srwatson
1843168951Srwatson	/*
1844168951Srwatson	 * All remaining system privileges are allow only if the process
1845168951Srwatson	 * holds privilege with respect to the LOMAC policy.
1846168951Srwatson	 */
1847168951Srwatson	default:
1848168951Srwatson		subj = SLOT(cred->cr_label);
1849172955Srwatson		error = lomac_subject_privileged(subj);
1850168951Srwatson		if (error)
1851168951Srwatson			return (error);
1852168951Srwatson	}
1853168951Srwatson	return (0);
1854168951Srwatson}
1855168951Srwatson
1856173138Srwatsonstatic int
1857173138Srwatsonlomac_proc_check_debug(struct ucred *cred, struct proc *p)
1858173138Srwatson{
1859173138Srwatson	struct mac_lomac *subj, *obj;
1860168951Srwatson
1861173138Srwatson	if (!lomac_enabled)
1862173138Srwatson		return (0);
1863173138Srwatson
1864173138Srwatson	subj = SLOT(cred->cr_label);
1865173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1866173138Srwatson
1867173138Srwatson	/* XXX: range checks */
1868173138Srwatson	if (!lomac_dominate_single(obj, subj))
1869173138Srwatson		return (ESRCH);
1870173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1871173138Srwatson		return (EACCES);
1872173138Srwatson
1873173138Srwatson	return (0);
1874173138Srwatson}
1875173138Srwatson
1876168951Srwatsonstatic int
1877173138Srwatsonlomac_proc_check_sched(struct ucred *cred, struct proc *p)
1878173138Srwatson{
1879173138Srwatson	struct mac_lomac *subj, *obj;
1880173138Srwatson
1881173138Srwatson	if (!lomac_enabled)
1882173138Srwatson		return (0);
1883173138Srwatson
1884173138Srwatson	subj = SLOT(cred->cr_label);
1885173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1886173138Srwatson
1887173138Srwatson	/* XXX: range checks */
1888173138Srwatson	if (!lomac_dominate_single(obj, subj))
1889173138Srwatson		return (ESRCH);
1890173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1891173138Srwatson		return (EACCES);
1892173138Srwatson
1893173138Srwatson	return (0);
1894173138Srwatson}
1895173138Srwatson
1896173138Srwatsonstatic int
1897173138Srwatsonlomac_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
1898173138Srwatson{
1899173138Srwatson	struct mac_lomac *subj, *obj;
1900173138Srwatson
1901173138Srwatson	if (!lomac_enabled)
1902173138Srwatson		return (0);
1903173138Srwatson
1904173138Srwatson	subj = SLOT(cred->cr_label);
1905173138Srwatson	obj = SLOT(p->p_ucred->cr_label);
1906173138Srwatson
1907173138Srwatson	/* XXX: range checks */
1908173138Srwatson	if (!lomac_dominate_single(obj, subj))
1909173138Srwatson		return (ESRCH);
1910173138Srwatson	if (!lomac_subject_dominate(subj, obj))
1911173138Srwatson		return (EACCES);
1912173138Srwatson
1913173138Srwatson	return (0);
1914173138Srwatson}
1915173138Srwatson
1916173138Srwatsonstatic void
1917173138Srwatsonlomac_proc_destroy_label(struct label *label)
1918173138Srwatson{
1919173138Srwatson
1920173138Srwatson	mtx_destroy(&PSLOT(label)->mtx);
1921184205Sdes	free(PSLOT(label), M_LOMAC);
1922173138Srwatson	PSLOT_SET(label, NULL);
1923173138Srwatson}
1924173138Srwatson
1925173138Srwatsonstatic void
1926173138Srwatsonlomac_proc_init_label(struct label *label)
1927173138Srwatson{
1928173138Srwatson
1929173138Srwatson	PSLOT_SET(label, malloc(sizeof(struct mac_lomac_proc), M_LOMAC,
1930173138Srwatson	    M_ZERO | M_WAITOK));
1931173138Srwatson	mtx_init(&PSLOT(label)->mtx, "MAC/Lomac proc lock", NULL, MTX_DEF);
1932173138Srwatson}
1933173138Srwatson
1934173138Srwatsonstatic int
1935173138Srwatsonlomac_socket_check_deliver(struct socket *so, struct label *solabel,
1936173138Srwatson    struct mbuf *m, struct label *mlabel)
1937173138Srwatson{
1938173138Srwatson	struct mac_lomac *p, *s;
1939193391Srwatson	int error;
1940173138Srwatson
1941173138Srwatson	if (!lomac_enabled)
1942173138Srwatson		return (0);
1943173138Srwatson
1944173138Srwatson	p = SLOT(mlabel);
1945173138Srwatson	s = SLOT(solabel);
1946173138Srwatson
1947193391Srwatson	SOCK_LOCK(so);
1948193391Srwatson	error = lomac_equal_single(p, s) ? 0 : EACCES;
1949193391Srwatson	SOCK_UNLOCK(so);
1950193391Srwatson	return (error);
1951173138Srwatson}
1952173138Srwatson
1953173138Srwatsonstatic int
1954173138Srwatsonlomac_socket_check_relabel(struct ucred *cred, struct socket *so,
1955173138Srwatson    struct label *solabel, struct label *newlabel)
1956173138Srwatson{
1957173138Srwatson	struct mac_lomac *subj, *obj, *new;
1958173138Srwatson	int error;
1959173138Srwatson
1960193391Srwatson	SOCK_LOCK_ASSERT(so);
1961193391Srwatson
1962173138Srwatson	new = SLOT(newlabel);
1963173138Srwatson	subj = SLOT(cred->cr_label);
1964173138Srwatson	obj = SLOT(solabel);
1965173138Srwatson
1966173138Srwatson	/*
1967173138Srwatson	 * If there is a LOMAC label update for the socket, it may be an
1968173138Srwatson	 * update of single.
1969173138Srwatson	 */
1970173138Srwatson	error = lomac_atmostflags(new, MAC_LOMAC_FLAG_SINGLE);
1971173138Srwatson	if (error)
1972173138Srwatson		return (error);
1973173138Srwatson
1974173138Srwatson	/*
1975173138Srwatson	 * To relabel a socket, the old socket single must be in the subject
1976173138Srwatson	 * range.
1977173138Srwatson	 */
1978173138Srwatson	if (!lomac_single_in_range(obj, subj))
1979173138Srwatson		return (EPERM);
1980173138Srwatson
1981173138Srwatson	/*
1982173138Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
1983173138Srwatson	 */
1984173138Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
1985173138Srwatson		/*
1986173138Srwatson		 * To relabel a socket, the new socket single must be in the
1987173138Srwatson		 * subject range.
1988173138Srwatson		 */
1989173138Srwatson		if (!lomac_single_in_range(new, subj))
1990173138Srwatson			return (EPERM);
1991173138Srwatson
1992173138Srwatson		/*
1993173138Srwatson		 * To change the LOMAC label on the socket to contain EQUAL,
1994173138Srwatson		 * the subject must have appropriate privilege.
1995173138Srwatson		 */
1996173138Srwatson		if (lomac_contains_equal(new)) {
1997173138Srwatson			error = lomac_subject_privileged(subj);
1998173138Srwatson			if (error)
1999173138Srwatson				return (error);
2000173138Srwatson		}
2001173138Srwatson	}
2002173138Srwatson
2003173138Srwatson	return (0);
2004173138Srwatson}
2005173138Srwatson
2006173138Srwatsonstatic int
2007173138Srwatsonlomac_socket_check_visible(struct ucred *cred, struct socket *so,
2008173138Srwatson    struct label *solabel)
2009173138Srwatson{
2010173138Srwatson	struct mac_lomac *subj, *obj;
2011173138Srwatson
2012173138Srwatson	if (!lomac_enabled)
2013173138Srwatson		return (0);
2014173138Srwatson
2015173138Srwatson	subj = SLOT(cred->cr_label);
2016173138Srwatson	obj = SLOT(solabel);
2017173138Srwatson
2018193391Srwatson	SOCK_LOCK(so);
2019193391Srwatson	if (!lomac_dominate_single(obj, subj)) {
2020193391Srwatson		SOCK_UNLOCK(so);
2021173138Srwatson		return (ENOENT);
2022193391Srwatson	}
2023193391Srwatson	SOCK_UNLOCK(so);
2024173138Srwatson
2025173138Srwatson	return (0);
2026173138Srwatson}
2027173138Srwatson
2028173138Srwatsonstatic void
2029173138Srwatsonlomac_socket_create(struct ucred *cred, struct socket *so,
2030173138Srwatson    struct label *solabel)
2031173138Srwatson{
2032173138Srwatson	struct mac_lomac *source, *dest;
2033173138Srwatson
2034173138Srwatson	source = SLOT(cred->cr_label);
2035173138Srwatson	dest = SLOT(solabel);
2036173138Srwatson
2037173138Srwatson	lomac_copy_single(source, dest);
2038173138Srwatson}
2039173138Srwatson
2040173138Srwatsonstatic void
2041173138Srwatsonlomac_socket_create_mbuf(struct socket *so, struct label *solabel,
2042173138Srwatson    struct mbuf *m, struct label *mlabel)
2043173138Srwatson{
2044173138Srwatson	struct mac_lomac *source, *dest;
2045173138Srwatson
2046173138Srwatson	source = SLOT(solabel);
2047173138Srwatson	dest = SLOT(mlabel);
2048173138Srwatson
2049193391Srwatson	SOCK_LOCK(so);
2050173138Srwatson	lomac_copy_single(source, dest);
2051193391Srwatson	SOCK_UNLOCK(so);
2052173138Srwatson}
2053173138Srwatson
2054173138Srwatsonstatic void
2055173138Srwatsonlomac_socket_newconn(struct socket *oldso, struct label *oldsolabel,
2056173138Srwatson    struct socket *newso, struct label *newsolabel)
2057173138Srwatson{
2058193391Srwatson	struct mac_lomac source, *dest;
2059173138Srwatson
2060193391Srwatson	SOCK_LOCK(oldso);
2061193391Srwatson	source = *SLOT(oldsolabel);
2062193391Srwatson	SOCK_UNLOCK(oldso);
2063193391Srwatson
2064173138Srwatson	dest = SLOT(newsolabel);
2065173138Srwatson
2066193391Srwatson	SOCK_LOCK(newso);
2067193391Srwatson	lomac_copy_single(&source, dest);
2068193391Srwatson	SOCK_UNLOCK(newso);
2069173138Srwatson}
2070173138Srwatson
2071173138Srwatsonstatic void
2072173138Srwatsonlomac_socket_relabel(struct ucred *cred, struct socket *so,
2073173138Srwatson    struct label *solabel, struct label *newlabel)
2074173138Srwatson{
2075173138Srwatson	struct mac_lomac *source, *dest;
2076173138Srwatson
2077193391Srwatson	SOCK_LOCK_ASSERT(so);
2078193391Srwatson
2079173138Srwatson	source = SLOT(newlabel);
2080173138Srwatson	dest = SLOT(solabel);
2081173138Srwatson
2082173138Srwatson	try_relabel(source, dest);
2083173138Srwatson}
2084173138Srwatson
2085173138Srwatsonstatic void
2086173138Srwatsonlomac_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
2087173138Srwatson    struct socket *so, struct label *sopeerlabel)
2088173138Srwatson{
2089173138Srwatson	struct mac_lomac *source, *dest;
2090173138Srwatson
2091173138Srwatson	source = SLOT(mlabel);
2092173138Srwatson	dest = SLOT(sopeerlabel);
2093173138Srwatson
2094193391Srwatson	SOCK_LOCK(so);
2095173138Srwatson	lomac_copy_single(source, dest);
2096193391Srwatson	SOCK_UNLOCK(so);
2097173138Srwatson}
2098173138Srwatson
2099173138Srwatsonstatic void
2100173138Srwatsonlomac_socketpeer_set_from_socket(struct socket *oldso,
2101173138Srwatson    struct label *oldsolabel, struct socket *newso,
2102173138Srwatson    struct label *newsopeerlabel)
2103173138Srwatson{
2104193391Srwatson	struct mac_lomac source, *dest;
2105173138Srwatson
2106193391Srwatson	SOCK_LOCK(oldso);
2107193391Srwatson	source = *SLOT(oldsolabel);
2108193391Srwatson	SOCK_UNLOCK(oldso);
2109193391Srwatson
2110173138Srwatson	dest = SLOT(newsopeerlabel);
2111173138Srwatson
2112193391Srwatson	SOCK_LOCK(newso);
2113193391Srwatson	lomac_copy_single(&source, dest);
2114193391Srwatson	SOCK_UNLOCK(newso);
2115173138Srwatson}
2116173138Srwatson
2117173138Srwatsonstatic void
2118173138Srwatsonlomac_syncache_create(struct label *label, struct inpcb *inp)
2119173138Srwatson{
2120173138Srwatson	struct mac_lomac *source, *dest;
2121173138Srwatson
2122173138Srwatson	source = SLOT(inp->inp_label);
2123173138Srwatson	dest = SLOT(label);
2124173138Srwatson	lomac_copy(source, dest);
2125173138Srwatson}
2126173138Srwatson
2127173138Srwatsonstatic void
2128173138Srwatsonlomac_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2129173138Srwatson    struct label *mlabel)
2130173138Srwatson{
2131173138Srwatson	struct mac_lomac *source, *dest;
2132173138Srwatson
2133173138Srwatson	source = SLOT(sc_label);
2134173138Srwatson	dest = SLOT(mlabel);
2135173138Srwatson	lomac_copy(source, dest);
2136173138Srwatson}
2137173138Srwatson
2138173138Srwatsonstatic int
2139172955Srwatsonlomac_system_check_acct(struct ucred *cred, struct vnode *vp,
2140168976Srwatson    struct label *vplabel)
2141168933Srwatson{
2142168933Srwatson	struct mac_lomac *subj, *obj;
2143168933Srwatson
2144172955Srwatson	if (!lomac_enabled)
2145168933Srwatson		return (0);
2146168933Srwatson
2147168933Srwatson	subj = SLOT(cred->cr_label);
2148168976Srwatson	obj = SLOT(vplabel);
2149168933Srwatson
2150172955Srwatson	if (lomac_subject_privileged(subj))
2151168933Srwatson		return (EPERM);
2152168933Srwatson
2153172955Srwatson	if (!lomac_high_single(obj))
2154168933Srwatson		return (EACCES);
2155168933Srwatson
2156168933Srwatson	return (0);
2157168933Srwatson}
2158168933Srwatson
2159168933Srwatsonstatic int
2160172955Srwatsonlomac_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2161168976Srwatson    struct label *vplabel)
2162168933Srwatson{
2163168933Srwatson	struct mac_lomac *subj, *obj;
2164168933Srwatson
2165172955Srwatson	if (!lomac_enabled)
2166168933Srwatson		return (0);
2167168933Srwatson
2168168933Srwatson	subj = SLOT(cred->cr_label);
2169168976Srwatson	obj = SLOT(vplabel);
2170168933Srwatson
2171172955Srwatson	if (lomac_subject_privileged(subj))
2172168933Srwatson		return (EPERM);
2173168933Srwatson
2174172955Srwatson	if (!lomac_high_single(obj))
2175168933Srwatson		return (EACCES);
2176168933Srwatson
2177168933Srwatson	return (0);
2178168933Srwatson}
2179168933Srwatson
2180168933Srwatsonstatic int
2181172955Srwatsonlomac_system_check_swapoff(struct ucred *cred, struct vnode *vp,
2182168976Srwatson    struct label *vplabel)
2183168933Srwatson{
2184168933Srwatson	struct mac_lomac *subj;
2185168933Srwatson
2186172955Srwatson	if (!lomac_enabled)
2187168933Srwatson		return (0);
2188168933Srwatson
2189168933Srwatson	subj = SLOT(cred->cr_label);
2190168933Srwatson
2191172955Srwatson	if (lomac_subject_privileged(subj))
2192168933Srwatson		return (EPERM);
2193168933Srwatson
2194168933Srwatson	return (0);
2195168933Srwatson}
2196168933Srwatson
2197168933Srwatsonstatic int
2198172955Srwatsonlomac_system_check_swapon(struct ucred *cred, struct vnode *vp,
2199168976Srwatson    struct label *vplabel)
2200107273Srwatson{
2201107273Srwatson	struct mac_lomac *subj, *obj;
2202107273Srwatson
2203172955Srwatson	if (!lomac_enabled)
2204107273Srwatson		return (0);
2205107273Srwatson
2206122524Srwatson	subj = SLOT(cred->cr_label);
2207168976Srwatson	obj = SLOT(vplabel);
2208107273Srwatson
2209172955Srwatson	if (lomac_subject_privileged(subj))
2210107273Srwatson		return (EPERM);
2211107273Srwatson
2212172955Srwatson	if (!lomac_high_single(obj))
2213107273Srwatson		return (EACCES);
2214107273Srwatson
2215107273Srwatson	return (0);
2216107273Srwatson}
2217107273Srwatson
2218107273Srwatsonstatic int
2219172955Srwatsonlomac_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2220126121Spjd    void *arg1, int arg2, struct sysctl_req *req)
2221107273Srwatson{
2222107273Srwatson	struct mac_lomac *subj;
2223107273Srwatson
2224172955Srwatson	if (!lomac_enabled)
2225107273Srwatson		return (0);
2226107273Srwatson
2227122524Srwatson	subj = SLOT(cred->cr_label);
2228107273Srwatson
2229107273Srwatson	/*
2230172955Srwatson	 * Treat sysctl variables without CTLFLAG_ANYBODY flag as lomac/high,
2231172955Srwatson	 * but also require privilege to change them.
2232107273Srwatson	 */
2233126121Spjd	if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2234107273Srwatson#ifdef notdef
2235172955Srwatson		if (!lomac_subject_dominate_high(subj))
2236107273Srwatson			return (EACCES);
2237107273Srwatson#endif
2238107273Srwatson
2239172955Srwatson		if (lomac_subject_privileged(subj))
2240107273Srwatson			return (EPERM);
2241107273Srwatson	}
2242107273Srwatson
2243107273Srwatson	return (0);
2244107273Srwatson}
2245107273Srwatson
2246173138Srwatsonstatic void
2247173138Srwatsonlomac_thread_userret(struct thread *td)
2248173138Srwatson{
2249173138Srwatson	struct proc *p = td->td_proc;
2250173138Srwatson	struct mac_lomac_proc *subj = PSLOT(p->p_label);
2251173138Srwatson	struct ucred *newcred, *oldcred;
2252173138Srwatson	int dodrop;
2253173138Srwatson
2254173138Srwatson	mtx_lock(&subj->mtx);
2255173138Srwatson	if (subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) {
2256173138Srwatson		dodrop = 0;
2257173138Srwatson		mtx_unlock(&subj->mtx);
2258173138Srwatson		newcred = crget();
2259173138Srwatson		/*
2260184412Srwatson		 * Prevent a lock order reversal in mac_proc_vm_revoke;
2261184412Srwatson		 * ideally, the other user of subj->mtx wouldn't be holding
2262184412Srwatson		 * Giant.
2263173138Srwatson		 */
2264173138Srwatson		mtx_lock(&Giant);
2265173138Srwatson		PROC_LOCK(p);
2266173138Srwatson		mtx_lock(&subj->mtx);
2267173138Srwatson		/*
2268173138Srwatson		 * Check if we lost the race while allocating the cred.
2269173138Srwatson		 */
2270173138Srwatson		if ((subj->mac_lomac.ml_flags & MAC_LOMAC_FLAG_UPDATE) == 0) {
2271173138Srwatson			crfree(newcred);
2272173138Srwatson			goto out;
2273173138Srwatson		}
2274173138Srwatson		oldcred = p->p_ucred;
2275173138Srwatson		crcopy(newcred, oldcred);
2276173138Srwatson		crhold(newcred);
2277173138Srwatson		lomac_copy(&subj->mac_lomac, SLOT(newcred->cr_label));
2278173138Srwatson		p->p_ucred = newcred;
2279173138Srwatson		crfree(oldcred);
2280173138Srwatson		dodrop = 1;
2281173138Srwatson	out:
2282173138Srwatson		mtx_unlock(&subj->mtx);
2283173138Srwatson		PROC_UNLOCK(p);
2284173138Srwatson		if (dodrop)
2285184412Srwatson			mac_proc_vm_revoke(curthread);
2286173138Srwatson		mtx_unlock(&Giant);
2287173138Srwatson	} else {
2288173138Srwatson		mtx_unlock(&subj->mtx);
2289173138Srwatson	}
2290173138Srwatson}
2291173138Srwatson
2292107273Srwatsonstatic int
2293173138Srwatsonlomac_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2294173138Srwatson    struct vnode *vp, struct label *vplabel)
2295173138Srwatson{
2296173138Srwatson	struct mac_lomac ml_temp, *source, *dest;
2297173138Srwatson	int buflen, error;
2298173138Srwatson
2299173138Srwatson	source = SLOT(mplabel);
2300173138Srwatson	dest = SLOT(vplabel);
2301173138Srwatson
2302173138Srwatson	buflen = sizeof(ml_temp);
2303173138Srwatson	bzero(&ml_temp, buflen);
2304173138Srwatson
2305173138Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2306173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, &buflen, (char *)&ml_temp, curthread);
2307173138Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
2308173138Srwatson		/* Fall back to the mntlabel. */
2309173138Srwatson		lomac_copy_single(source, dest);
2310173138Srwatson		return (0);
2311173138Srwatson	} else if (error)
2312173138Srwatson		return (error);
2313173138Srwatson
2314173138Srwatson	if (buflen != sizeof(ml_temp)) {
2315173138Srwatson		if (buflen != sizeof(ml_temp) - sizeof(ml_temp.ml_auxsingle)) {
2316173138Srwatson			printf("lomac_vnode_associate_extattr: bad size %d\n",
2317173138Srwatson			    buflen);
2318173138Srwatson			return (EPERM);
2319173138Srwatson		}
2320173138Srwatson		bzero(&ml_temp.ml_auxsingle, sizeof(ml_temp.ml_auxsingle));
2321173138Srwatson		buflen = sizeof(ml_temp);
2322173138Srwatson		(void)vn_extattr_set(vp, IO_NODELOCKED,
2323173138Srwatson		    MAC_LOMAC_EXTATTR_NAMESPACE, MAC_LOMAC_EXTATTR_NAME,
2324173138Srwatson		    buflen, (char *)&ml_temp, curthread);
2325173138Srwatson	}
2326173138Srwatson	if (lomac_valid(&ml_temp) != 0) {
2327173138Srwatson		printf("lomac_vnode_associate_extattr: invalid\n");
2328173138Srwatson		return (EPERM);
2329173138Srwatson	}
2330173138Srwatson	if ((ml_temp.ml_flags & MAC_LOMAC_FLAGS_BOTH) !=
2331173138Srwatson	    MAC_LOMAC_FLAG_SINGLE) {
2332173138Srwatson		printf("lomac_vnode_associate_extattr: not single\n");
2333173138Srwatson		return (EPERM);
2334173138Srwatson	}
2335173138Srwatson
2336173138Srwatson	lomac_copy_single(&ml_temp, dest);
2337173138Srwatson	return (0);
2338173138Srwatson}
2339173138Srwatson
2340173138Srwatsonstatic void
2341173138Srwatsonlomac_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2342173138Srwatson    struct vnode *vp, struct label *vplabel)
2343173138Srwatson{
2344173138Srwatson	struct mac_lomac *source, *dest;
2345173138Srwatson
2346173138Srwatson	source = SLOT(mplabel);
2347173138Srwatson	dest = SLOT(vplabel);
2348173138Srwatson
2349173138Srwatson	lomac_copy_single(source, dest);
2350173138Srwatson}
2351173138Srwatson
2352173138Srwatsonstatic int
2353172955Srwatsonlomac_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2354168976Srwatson    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2355107273Srwatson{
2356107273Srwatson	struct mac_lomac *subj, *obj;
2357107273Srwatson
2358172955Srwatson	if (!lomac_enabled)
2359107273Srwatson		return (0);
2360107273Srwatson
2361122524Srwatson	subj = SLOT(cred->cr_label);
2362168976Srwatson	obj = SLOT(dvplabel);
2363107273Srwatson
2364172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2365107273Srwatson		return (EACCES);
2366107273Srwatson	if (obj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2367172955Srwatson	    !lomac_dominate_element(&subj->ml_single, &obj->ml_auxsingle))
2368107273Srwatson		return (EACCES);
2369107273Srwatson
2370107273Srwatson	return (0);
2371107273Srwatson}
2372107273Srwatson
2373107273Srwatsonstatic int
2374172955Srwatsonlomac_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2375168976Srwatson    struct label *vplabel, acl_type_t type)
2376107273Srwatson{
2377107273Srwatson	struct mac_lomac *subj, *obj;
2378107273Srwatson
2379172955Srwatson	if (!lomac_enabled)
2380107273Srwatson		return (0);
2381107273Srwatson
2382122524Srwatson	subj = SLOT(cred->cr_label);
2383168976Srwatson	obj = SLOT(vplabel);
2384107273Srwatson
2385172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2386107273Srwatson		return (EACCES);
2387107273Srwatson
2388107273Srwatson	return (0);
2389107273Srwatson}
2390107273Srwatson
2391107273Srwatsonstatic int
2392172955Srwatsonlomac_vnode_check_link(struct ucred *cred, struct vnode *dvp,
2393168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2394107273Srwatson    struct componentname *cnp)
2395107273Srwatson{
2396107273Srwatson	struct mac_lomac *subj, *obj;
2397107273Srwatson
2398172955Srwatson	if (!lomac_enabled)
2399107273Srwatson		return (0);
2400107273Srwatson
2401122524Srwatson	subj = SLOT(cred->cr_label);
2402168976Srwatson	obj = SLOT(dvplabel);
2403107273Srwatson
2404172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2405107273Srwatson		return (EACCES);
2406107273Srwatson
2407168976Srwatson	obj = SLOT(vplabel);
2408107273Srwatson
2409172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2410107273Srwatson		return (EACCES);
2411107273Srwatson
2412107273Srwatson	return (0);
2413107273Srwatson}
2414107273Srwatson
2415107273Srwatsonstatic int
2416172955Srwatsonlomac_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
2417168976Srwatson    struct label *vplabel, int prot, int flags)
2418107273Srwatson{
2419107273Srwatson	struct mac_lomac *subj, *obj;
2420107273Srwatson
2421107273Srwatson	/*
2422107273Srwatson	 * Rely on the use of open()-time protections to handle
2423107273Srwatson	 * non-revocation cases.
2424107273Srwatson	 */
2425172955Srwatson	if (!lomac_enabled)
2426107273Srwatson		return (0);
2427107273Srwatson
2428122524Srwatson	subj = SLOT(cred->cr_label);
2429168976Srwatson	obj = SLOT(vplabel);
2430107273Srwatson
2431145076Scsjp	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2432172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2433107273Srwatson			return (EACCES);
2434107273Srwatson	}
2435107273Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2436172955Srwatson		if (!lomac_dominate_single(obj, subj))
2437107273Srwatson			return (maybe_demote(subj, obj, "mapping", "file", vp));
2438107273Srwatson	}
2439107273Srwatson
2440107273Srwatson	return (0);
2441107273Srwatson}
2442107273Srwatson
2443107273Srwatsonstatic void
2444172955Srwatsonlomac_vnode_check_mmap_downgrade(struct ucred *cred, struct vnode *vp,
2445168976Srwatson    struct label *vplabel, /* XXX vm_prot_t */ int *prot)
2446107273Srwatson{
2447107273Srwatson	struct mac_lomac *subj, *obj;
2448107273Srwatson
2449107273Srwatson	/*
2450107273Srwatson	 * Rely on the use of open()-time protections to handle
2451107273Srwatson	 * non-revocation cases.
2452107273Srwatson	 */
2453172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2454107273Srwatson		return;
2455107273Srwatson
2456122524Srwatson	subj = SLOT(cred->cr_label);
2457168976Srwatson	obj = SLOT(vplabel);
2458107273Srwatson
2459172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2460107273Srwatson		*prot &= ~VM_PROT_WRITE;
2461107273Srwatson}
2462107273Srwatson
2463107273Srwatsonstatic int
2464172955Srwatsonlomac_vnode_check_open(struct ucred *cred, struct vnode *vp,
2465184413Strasz    struct label *vplabel, accmode_t accmode)
2466107273Srwatson{
2467107273Srwatson	struct mac_lomac *subj, *obj;
2468107273Srwatson
2469172955Srwatson	if (!lomac_enabled)
2470107273Srwatson		return (0);
2471107273Srwatson
2472122524Srwatson	subj = SLOT(cred->cr_label);
2473168976Srwatson	obj = SLOT(vplabel);
2474107273Srwatson
2475107273Srwatson	/* XXX privilege override for admin? */
2476201438Strasz	if (accmode & VMODIFY_PERMS) {
2477172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2478107273Srwatson			return (EACCES);
2479107273Srwatson	}
2480107273Srwatson
2481107273Srwatson	return (0);
2482107273Srwatson}
2483107273Srwatson
2484107273Srwatsonstatic int
2485172955Srwatsonlomac_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
2486168976Srwatson    struct vnode *vp, struct label *vplabel)
2487107273Srwatson{
2488107273Srwatson	struct mac_lomac *subj, *obj;
2489107273Srwatson
2490172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2491107273Srwatson		return (0);
2492107273Srwatson
2493122524Srwatson	subj = SLOT(active_cred->cr_label);
2494168976Srwatson	obj = SLOT(vplabel);
2495107273Srwatson
2496172955Srwatson	if (!lomac_dominate_single(obj, subj))
2497107273Srwatson		return (maybe_demote(subj, obj, "reading", "file", vp));
2498107273Srwatson
2499107273Srwatson	return (0);
2500107273Srwatson}
2501107273Srwatson
2502107273Srwatsonstatic int
2503172955Srwatsonlomac_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
2504168976Srwatson    struct label *vplabel, struct label *newlabel)
2505107273Srwatson{
2506107273Srwatson	struct mac_lomac *old, *new, *subj;
2507107273Srwatson	int error;
2508107273Srwatson
2509168976Srwatson	old = SLOT(vplabel);
2510107273Srwatson	new = SLOT(newlabel);
2511122524Srwatson	subj = SLOT(cred->cr_label);
2512107273Srwatson
2513107273Srwatson	/*
2514107273Srwatson	 * If there is a LOMAC label update for the vnode, it must be a
2515107273Srwatson	 * single label, with an optional explicit auxiliary single.
2516107273Srwatson	 */
2517107273Srwatson	error = lomac_atmostflags(new,
2518107273Srwatson	    MAC_LOMAC_FLAG_SINGLE | MAC_LOMAC_FLAG_AUX);
2519107273Srwatson	if (error)
2520107273Srwatson		return (error);
2521107273Srwatson
2522107273Srwatson	/*
2523107273Srwatson	 * To perform a relabel of the vnode (LOMAC label or not), LOMAC must
2524107273Srwatson	 * authorize the relabel.
2525107273Srwatson	 */
2526172955Srwatson	if (!lomac_single_in_range(old, subj))
2527107273Srwatson		return (EPERM);
2528107273Srwatson
2529107273Srwatson	/*
2530107273Srwatson	 * If the LOMAC label is to be changed, authorize as appropriate.
2531107273Srwatson	 */
2532107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_SINGLE) {
2533107273Srwatson		/*
2534107273Srwatson		 * To change the LOMAC label on a vnode, the new vnode label
2535107273Srwatson		 * must be in the subject range.
2536107273Srwatson		 */
2537172955Srwatson		if (!lomac_single_in_range(new, subj))
2538107273Srwatson			return (EPERM);
2539107273Srwatson
2540107273Srwatson		/*
2541172955Srwatson		 * To change the LOMAC label on the vnode to be EQUAL, the
2542172955Srwatson		 * subject must have appropriate privilege.
2543107273Srwatson		 */
2544172955Srwatson		if (lomac_contains_equal(new)) {
2545172955Srwatson			error = lomac_subject_privileged(subj);
2546107273Srwatson			if (error)
2547107273Srwatson				return (error);
2548107273Srwatson		}
2549107273Srwatson	}
2550107273Srwatson	if (new->ml_flags & MAC_LOMAC_FLAG_AUX) {
2551107273Srwatson		/*
2552119242Srwatson		 * Fill in the missing parts from the previous label.
2553119242Srwatson		 */
2554119242Srwatson		if ((new->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2555172955Srwatson			lomac_copy_single(subj, new);
2556119242Srwatson
2557119242Srwatson		/*
2558107273Srwatson		 * To change the auxiliary LOMAC label on a vnode, the new
2559107273Srwatson		 * vnode label must be in the subject range.
2560107273Srwatson		 */
2561172955Srwatson		if (!lomac_auxsingle_in_range(new, subj))
2562107273Srwatson			return (EPERM);
2563107273Srwatson
2564107273Srwatson		/*
2565107273Srwatson		 * To change the auxiliary LOMAC label on the vnode to be
2566107273Srwatson		 * EQUAL, the subject must have appropriate privilege.
2567107273Srwatson		 */
2568172955Srwatson		if (lomac_contains_equal(new)) {
2569172955Srwatson			error = lomac_subject_privileged(subj);
2570107273Srwatson			if (error)
2571107273Srwatson				return (error);
2572107273Srwatson		}
2573107273Srwatson	}
2574107273Srwatson
2575107273Srwatson	return (0);
2576107273Srwatson}
2577107273Srwatson
2578107273Srwatsonstatic int
2579172955Srwatsonlomac_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
2580168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2581107273Srwatson    struct componentname *cnp)
2582107273Srwatson{
2583107273Srwatson	struct mac_lomac *subj, *obj;
2584107273Srwatson
2585172955Srwatson	if (!lomac_enabled)
2586107273Srwatson		return (0);
2587107273Srwatson
2588122524Srwatson	subj = SLOT(cred->cr_label);
2589168976Srwatson	obj = SLOT(dvplabel);
2590107273Srwatson
2591172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2592107273Srwatson		return (EACCES);
2593107273Srwatson
2594168976Srwatson	obj = SLOT(vplabel);
2595107273Srwatson
2596172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2597107273Srwatson		return (EACCES);
2598107273Srwatson
2599107273Srwatson	return (0);
2600107273Srwatson}
2601107273Srwatson
2602107273Srwatsonstatic int
2603172955Srwatsonlomac_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
2604168976Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2605168976Srwatson    int samedir, struct componentname *cnp)
2606107273Srwatson{
2607107273Srwatson	struct mac_lomac *subj, *obj;
2608107273Srwatson
2609172955Srwatson	if (!lomac_enabled)
2610107273Srwatson		return (0);
2611107273Srwatson
2612122524Srwatson	subj = SLOT(cred->cr_label);
2613168976Srwatson	obj = SLOT(dvplabel);
2614107273Srwatson
2615172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2616107273Srwatson		return (EACCES);
2617107273Srwatson
2618107273Srwatson	if (vp != NULL) {
2619168976Srwatson		obj = SLOT(vplabel);
2620107273Srwatson
2621172955Srwatson		if (!lomac_subject_dominate(subj, obj))
2622107273Srwatson			return (EACCES);
2623107273Srwatson	}
2624107273Srwatson
2625107273Srwatson	return (0);
2626107273Srwatson}
2627107273Srwatson
2628107273Srwatsonstatic int
2629172955Srwatsonlomac_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
2630168976Srwatson    struct label *vplabel)
2631107273Srwatson{
2632107273Srwatson	struct mac_lomac *subj, *obj;
2633107273Srwatson
2634172955Srwatson	if (!lomac_enabled)
2635107273Srwatson		return (0);
2636107273Srwatson
2637122524Srwatson	subj = SLOT(cred->cr_label);
2638168976Srwatson	obj = SLOT(vplabel);
2639107273Srwatson
2640172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2641107273Srwatson		return (EACCES);
2642107273Srwatson
2643107273Srwatson	return (0);
2644107273Srwatson}
2645107273Srwatson
2646107273Srwatsonstatic int
2647172955Srwatsonlomac_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
2648168976Srwatson    struct label *vplabel, acl_type_t type, struct acl *acl)
2649107273Srwatson{
2650107273Srwatson	struct mac_lomac *subj, *obj;
2651107273Srwatson
2652172955Srwatson	if (!lomac_enabled)
2653107273Srwatson		return (0);
2654107273Srwatson
2655122524Srwatson	subj = SLOT(cred->cr_label);
2656168976Srwatson	obj = SLOT(vplabel);
2657107273Srwatson
2658172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2659107273Srwatson		return (EACCES);
2660107273Srwatson
2661107273Srwatson	return (0);
2662107273Srwatson}
2663107273Srwatson
2664107273Srwatsonstatic int
2665172955Srwatsonlomac_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
2666189533Srwatson    struct label *vplabel, int attrnamespace, const char *name)
2667107273Srwatson{
2668107273Srwatson	struct mac_lomac *subj, *obj;
2669107273Srwatson
2670172955Srwatson	if (!lomac_enabled)
2671107273Srwatson		return (0);
2672107273Srwatson
2673122524Srwatson	subj = SLOT(cred->cr_label);
2674168976Srwatson	obj = SLOT(vplabel);
2675107273Srwatson
2676172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2677107273Srwatson		return (EACCES);
2678107273Srwatson
2679107273Srwatson	/* XXX: protect the MAC EA in a special way? */
2680107273Srwatson
2681107273Srwatson	return (0);
2682107273Srwatson}
2683107273Srwatson
2684107273Srwatsonstatic int
2685172955Srwatsonlomac_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
2686168976Srwatson    struct label *vplabel, u_long flags)
2687107273Srwatson{
2688107273Srwatson	struct mac_lomac *subj, *obj;
2689107273Srwatson
2690172955Srwatson	if (!lomac_enabled)
2691107273Srwatson		return (0);
2692107273Srwatson
2693122524Srwatson	subj = SLOT(cred->cr_label);
2694168976Srwatson	obj = SLOT(vplabel);
2695107273Srwatson
2696172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2697107273Srwatson		return (EACCES);
2698107273Srwatson
2699107273Srwatson	return (0);
2700107273Srwatson}
2701107273Srwatson
2702107273Srwatsonstatic int
2703172955Srwatsonlomac_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
2704168976Srwatson    struct label *vplabel, mode_t mode)
2705107273Srwatson{
2706107273Srwatson	struct mac_lomac *subj, *obj;
2707107273Srwatson
2708172955Srwatson	if (!lomac_enabled)
2709107273Srwatson		return (0);
2710107273Srwatson
2711122524Srwatson	subj = SLOT(cred->cr_label);
2712168976Srwatson	obj = SLOT(vplabel);
2713107273Srwatson
2714172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2715107273Srwatson		return (EACCES);
2716107273Srwatson
2717107273Srwatson	return (0);
2718107273Srwatson}
2719107273Srwatson
2720107273Srwatsonstatic int
2721172955Srwatsonlomac_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
2722168976Srwatson    struct label *vplabel, uid_t uid, gid_t gid)
2723107273Srwatson{
2724107273Srwatson	struct mac_lomac *subj, *obj;
2725107273Srwatson
2726172955Srwatson	if (!lomac_enabled)
2727107273Srwatson		return (0);
2728107273Srwatson
2729122524Srwatson	subj = SLOT(cred->cr_label);
2730168976Srwatson	obj = SLOT(vplabel);
2731107273Srwatson
2732172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2733107273Srwatson		return (EACCES);
2734107273Srwatson
2735107273Srwatson	return (0);
2736107273Srwatson}
2737107273Srwatson
2738107273Srwatsonstatic int
2739172955Srwatsonlomac_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
2740168976Srwatson    struct label *vplabel, struct timespec atime, struct timespec mtime)
2741107273Srwatson{
2742107273Srwatson	struct mac_lomac *subj, *obj;
2743107273Srwatson
2744172955Srwatson	if (!lomac_enabled)
2745107273Srwatson		return (0);
2746107273Srwatson
2747122524Srwatson	subj = SLOT(cred->cr_label);
2748168976Srwatson	obj = SLOT(vplabel);
2749107273Srwatson
2750172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2751107273Srwatson		return (EACCES);
2752107273Srwatson
2753107273Srwatson	return (0);
2754107273Srwatson}
2755107273Srwatson
2756107273Srwatsonstatic int
2757172955Srwatsonlomac_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
2758172107Srwatson    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
2759172107Srwatson    struct componentname *cnp)
2760172107Srwatson{
2761172107Srwatson	struct mac_lomac *subj, *obj;
2762172107Srwatson
2763172955Srwatson	if (!lomac_enabled)
2764172107Srwatson		return (0);
2765172107Srwatson
2766172107Srwatson	subj = SLOT(cred->cr_label);
2767172107Srwatson	obj = SLOT(dvplabel);
2768172107Srwatson
2769172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2770172107Srwatson		return (EACCES);
2771172107Srwatson
2772172107Srwatson	obj = SLOT(vplabel);
2773172107Srwatson
2774172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2775172107Srwatson		return (EACCES);
2776172107Srwatson
2777172107Srwatson	return (0);
2778172107Srwatson}
2779172107Srwatson
2780172107Srwatsonstatic int
2781172955Srwatsonlomac_vnode_check_write(struct ucred *active_cred,
2782168976Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
2783107273Srwatson{
2784107273Srwatson	struct mac_lomac *subj, *obj;
2785107273Srwatson
2786172955Srwatson	if (!lomac_enabled || !revocation_enabled)
2787107273Srwatson		return (0);
2788107273Srwatson
2789122524Srwatson	subj = SLOT(active_cred->cr_label);
2790168976Srwatson	obj = SLOT(vplabel);
2791107273Srwatson
2792172955Srwatson	if (!lomac_subject_dominate(subj, obj))
2793107273Srwatson		return (EACCES);
2794107273Srwatson
2795107273Srwatson	return (0);
2796107273Srwatson}
2797107273Srwatson
2798173138Srwatsonstatic int
2799173138Srwatsonlomac_vnode_create_extattr(struct ucred *cred, struct mount *mp,
2800173138Srwatson    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
2801173138Srwatson    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
2802107273Srwatson{
2803173138Srwatson	struct mac_lomac *source, *dest, *dir, temp;
2804173138Srwatson	size_t buflen;
2805173138Srwatson	int error;
2806107273Srwatson
2807173138Srwatson	buflen = sizeof(temp);
2808173138Srwatson	bzero(&temp, buflen);
2809173138Srwatson
2810173138Srwatson	source = SLOT(cred->cr_label);
2811173138Srwatson	dest = SLOT(vplabel);
2812173138Srwatson	dir = SLOT(dvplabel);
2813173138Srwatson	if (dir->ml_flags & MAC_LOMAC_FLAG_AUX) {
2814173138Srwatson		lomac_copy_auxsingle(dir, &temp);
2815173138Srwatson		lomac_set_single(&temp, dir->ml_auxsingle.mle_type,
2816173138Srwatson		    dir->ml_auxsingle.mle_grade);
2817107273Srwatson	} else {
2818173138Srwatson		lomac_copy_single(source, &temp);
2819107273Srwatson	}
2820173138Srwatson
2821173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2822173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2823173138Srwatson	if (error == 0)
2824173138Srwatson		lomac_copy(&temp, dest);
2825173138Srwatson	return (error);
2826107273Srwatson}
2827107273Srwatson
2828173138Srwatsonstatic void
2829173138Srwatsonlomac_vnode_execve_transition(struct ucred *old, struct ucred *new,
2830173138Srwatson    struct vnode *vp, struct label *vplabel, struct label *interpvplabel,
2831173138Srwatson    struct image_params *imgp, struct label *execlabel)
2832173138Srwatson{
2833173138Srwatson	struct mac_lomac *source, *dest, *obj, *robj;
2834173138Srwatson
2835173138Srwatson	source = SLOT(old->cr_label);
2836173138Srwatson	dest = SLOT(new->cr_label);
2837173138Srwatson	obj = SLOT(vplabel);
2838173138Srwatson	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2839173138Srwatson
2840173138Srwatson	lomac_copy(source, dest);
2841173138Srwatson	/*
2842173138Srwatson	 * If there's an auxiliary label on the real object, respect it and
2843173138Srwatson	 * assume that this level should be assumed immediately if a higher
2844173138Srwatson	 * level is currently in place.
2845173138Srwatson	 */
2846173138Srwatson	if (robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2847173138Srwatson	    !lomac_dominate_element(&robj->ml_auxsingle, &dest->ml_single)
2848173138Srwatson	    && lomac_auxsingle_in_range(robj, dest))
2849173138Srwatson		lomac_set_single(dest, robj->ml_auxsingle.mle_type,
2850173138Srwatson		    robj->ml_auxsingle.mle_grade);
2851173138Srwatson	/*
2852173138Srwatson	 * Restructuring to use the execve transitioning mechanism instead of
2853173138Srwatson	 * the normal demotion mechanism here would be difficult, so just
2854173138Srwatson	 * copy the label over and perform standard demotion.  This is also
2855173138Srwatson	 * non-optimal because it will result in the intermediate label "new"
2856173138Srwatson	 * being created and immediately recycled.
2857173138Srwatson	 */
2858173138Srwatson	if (lomac_enabled && revocation_enabled &&
2859173138Srwatson	    !lomac_dominate_single(obj, source))
2860173138Srwatson		(void)maybe_demote(source, obj, "executing", "file", vp);
2861173138Srwatson}
2862173138Srwatson
2863173138Srwatsonstatic int
2864173138Srwatsonlomac_vnode_execve_will_transition(struct ucred *old, struct vnode *vp,
2865173138Srwatson    struct label *vplabel, struct label *interpvplabel,
2866173138Srwatson    struct image_params *imgp, struct label *execlabel)
2867173138Srwatson{
2868173138Srwatson	struct mac_lomac *subj, *obj, *robj;
2869173138Srwatson
2870173138Srwatson	if (!lomac_enabled || !revocation_enabled)
2871173138Srwatson		return (0);
2872173138Srwatson
2873173138Srwatson	subj = SLOT(old->cr_label);
2874173138Srwatson	obj = SLOT(vplabel);
2875173138Srwatson	robj = interpvplabel != NULL ? SLOT(interpvplabel) : obj;
2876173138Srwatson
2877173138Srwatson	return ((robj->ml_flags & MAC_LOMAC_FLAG_AUX &&
2878173138Srwatson	    !lomac_dominate_element(&robj->ml_auxsingle, &subj->ml_single)
2879173138Srwatson	    && lomac_auxsingle_in_range(robj, subj)) ||
2880173138Srwatson	    !lomac_dominate_single(obj, subj));
2881173138Srwatson}
2882173138Srwatson
2883173138Srwatsonstatic void
2884173138Srwatsonlomac_vnode_relabel(struct ucred *cred, struct vnode *vp,
2885173138Srwatson    struct label *vplabel, struct label *newlabel)
2886173138Srwatson{
2887173138Srwatson	struct mac_lomac *source, *dest;
2888173138Srwatson
2889173138Srwatson	source = SLOT(newlabel);
2890173138Srwatson	dest = SLOT(vplabel);
2891173138Srwatson
2892173138Srwatson	try_relabel(source, dest);
2893173138Srwatson}
2894173138Srwatson
2895173138Srwatsonstatic int
2896173138Srwatsonlomac_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
2897173138Srwatson    struct label *vplabel, struct label *intlabel)
2898173138Srwatson{
2899173138Srwatson	struct mac_lomac *source, temp;
2900173138Srwatson	size_t buflen;
2901173138Srwatson	int error;
2902173138Srwatson
2903173138Srwatson	buflen = sizeof(temp);
2904173138Srwatson	bzero(&temp, buflen);
2905173138Srwatson
2906173138Srwatson	source = SLOT(intlabel);
2907173138Srwatson	if ((source->ml_flags & MAC_LOMAC_FLAG_SINGLE) == 0)
2908173138Srwatson		return (0);
2909173138Srwatson
2910173138Srwatson	lomac_copy_single(source, &temp);
2911173138Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_LOMAC_EXTATTR_NAMESPACE,
2912173138Srwatson	    MAC_LOMAC_EXTATTR_NAME, buflen, (char *)&temp, curthread);
2913173138Srwatson	return (error);
2914173138Srwatson}
2915173138Srwatson
2916172955Srwatsonstatic struct mac_policy_ops lomac_ops =
2917107273Srwatson{
2918172955Srwatson	.mpo_init = lomac_init,
2919173138Srwatson
2920173138Srwatson	.mpo_bpfdesc_check_receive = lomac_bpfdesc_check_receive,
2921173138Srwatson	.mpo_bpfdesc_create = lomac_bpfdesc_create,
2922173138Srwatson	.mpo_bpfdesc_create_mbuf = lomac_bpfdesc_create_mbuf,
2923173138Srwatson	.mpo_bpfdesc_destroy_label = lomac_destroy_label,
2924172955Srwatson	.mpo_bpfdesc_init_label = lomac_init_label,
2925173138Srwatson
2926173138Srwatson	.mpo_cred_check_relabel = lomac_cred_check_relabel,
2927173138Srwatson	.mpo_cred_check_visible = lomac_cred_check_visible,
2928173138Srwatson	.mpo_cred_copy_label = lomac_copy_label,
2929184407Srwatson	.mpo_cred_create_swapper = lomac_cred_create_swapper,
2930184407Srwatson	.mpo_cred_create_init = lomac_cred_create_init,
2931172955Srwatson	.mpo_cred_destroy_label = lomac_destroy_label,
2932172955Srwatson	.mpo_cred_externalize_label = lomac_externalize_label,
2933173138Srwatson	.mpo_cred_init_label = lomac_init_label,
2934172955Srwatson	.mpo_cred_internalize_label = lomac_internalize_label,
2935173138Srwatson	.mpo_cred_relabel = lomac_cred_relabel,
2936173138Srwatson
2937172955Srwatson	.mpo_devfs_create_device = lomac_devfs_create_device,
2938172955Srwatson	.mpo_devfs_create_directory = lomac_devfs_create_directory,
2939172955Srwatson	.mpo_devfs_create_symlink = lomac_devfs_create_symlink,
2940173138Srwatson	.mpo_devfs_destroy_label = lomac_destroy_label,
2941173138Srwatson	.mpo_devfs_init_label = lomac_init_label,
2942172955Srwatson	.mpo_devfs_update = lomac_devfs_update,
2943172955Srwatson	.mpo_devfs_vnode_associate = lomac_devfs_vnode_associate,
2944173138Srwatson
2945173138Srwatson	.mpo_ifnet_check_relabel = lomac_ifnet_check_relabel,
2946173138Srwatson	.mpo_ifnet_check_transmit = lomac_ifnet_check_transmit,
2947173138Srwatson	.mpo_ifnet_copy_label = lomac_copy_label,
2948172955Srwatson	.mpo_ifnet_create = lomac_ifnet_create,
2949173138Srwatson	.mpo_ifnet_create_mbuf = lomac_ifnet_create_mbuf,
2950173138Srwatson	.mpo_ifnet_destroy_label = lomac_destroy_label,
2951173138Srwatson	.mpo_ifnet_externalize_label = lomac_externalize_label,
2952173138Srwatson	.mpo_ifnet_init_label = lomac_init_label,
2953173138Srwatson	.mpo_ifnet_internalize_label = lomac_internalize_label,
2954173138Srwatson	.mpo_ifnet_relabel = lomac_ifnet_relabel,
2955173138Srwatson
2956173138Srwatson	.mpo_syncache_create = lomac_syncache_create,
2957173138Srwatson	.mpo_syncache_destroy_label = lomac_destroy_label,
2958173138Srwatson	.mpo_syncache_init_label = lomac_init_label_waitcheck,
2959173138Srwatson
2960173138Srwatson	.mpo_inpcb_check_deliver = lomac_inpcb_check_deliver,
2961183980Sbz	.mpo_inpcb_check_visible = lomac_inpcb_check_visible,
2962172955Srwatson	.mpo_inpcb_create = lomac_inpcb_create,
2963173138Srwatson	.mpo_inpcb_create_mbuf = lomac_inpcb_create_mbuf,
2964173138Srwatson	.mpo_inpcb_destroy_label = lomac_destroy_label,
2965173138Srwatson	.mpo_inpcb_init_label = lomac_init_label_waitcheck,
2966173138Srwatson	.mpo_inpcb_sosetlabel = lomac_inpcb_sosetlabel,
2967173138Srwatson
2968184308Srwatson	.mpo_ip6q_create = lomac_ip6q_create,
2969184308Srwatson	.mpo_ip6q_destroy_label = lomac_destroy_label,
2970184308Srwatson	.mpo_ip6q_init_label = lomac_init_label_waitcheck,
2971184308Srwatson	.mpo_ip6q_match = lomac_ip6q_match,
2972184308Srwatson	.mpo_ip6q_reassemble = lomac_ip6q_reassemble,
2973184308Srwatson	.mpo_ip6q_update = lomac_ip6q_update,
2974184308Srwatson
2975172955Srwatson	.mpo_ipq_create = lomac_ipq_create,
2976173138Srwatson	.mpo_ipq_destroy_label = lomac_destroy_label,
2977173138Srwatson	.mpo_ipq_init_label = lomac_init_label_waitcheck,
2978172955Srwatson	.mpo_ipq_match = lomac_ipq_match,
2979173138Srwatson	.mpo_ipq_reassemble = lomac_ipq_reassemble,
2980172955Srwatson	.mpo_ipq_update = lomac_ipq_update,
2981173138Srwatson
2982172955Srwatson	.mpo_kld_check_load = lomac_kld_check_load,
2983173138Srwatson
2984173138Srwatson	.mpo_mbuf_copy_label = lomac_copy_label,
2985173138Srwatson	.mpo_mbuf_destroy_label = lomac_destroy_label,
2986173138Srwatson	.mpo_mbuf_init_label = lomac_init_label_waitcheck,
2987173138Srwatson
2988173138Srwatson	.mpo_mount_create = lomac_mount_create,
2989173138Srwatson	.mpo_mount_destroy_label = lomac_destroy_label,
2990173138Srwatson	.mpo_mount_init_label = lomac_init_label,
2991173138Srwatson
2992173138Srwatson	.mpo_netatalk_aarp_send = lomac_netatalk_aarp_send,
2993173138Srwatson
2994173138Srwatson	.mpo_netinet_arp_send = lomac_netinet_arp_send,
2995173138Srwatson	.mpo_netinet_firewall_reply = lomac_netinet_firewall_reply,
2996173138Srwatson	.mpo_netinet_firewall_send = lomac_netinet_firewall_send,
2997173138Srwatson	.mpo_netinet_fragment = lomac_netinet_fragment,
2998173138Srwatson	.mpo_netinet_icmp_reply = lomac_netinet_icmp_reply,
2999173138Srwatson	.mpo_netinet_igmp_send = lomac_netinet_igmp_send,
3000173138Srwatson
3001173138Srwatson	.mpo_netinet6_nd6_send = lomac_netinet6_nd6_send,
3002173138Srwatson
3003172955Srwatson	.mpo_pipe_check_ioctl = lomac_pipe_check_ioctl,
3004172955Srwatson	.mpo_pipe_check_read = lomac_pipe_check_read,
3005172955Srwatson	.mpo_pipe_check_relabel = lomac_pipe_check_relabel,
3006172955Srwatson	.mpo_pipe_check_write = lomac_pipe_check_write,
3007173138Srwatson	.mpo_pipe_copy_label = lomac_copy_label,
3008173138Srwatson	.mpo_pipe_create = lomac_pipe_create,
3009173138Srwatson	.mpo_pipe_destroy_label = lomac_destroy_label,
3010173138Srwatson	.mpo_pipe_externalize_label = lomac_externalize_label,
3011173138Srwatson	.mpo_pipe_init_label = lomac_init_label,
3012173138Srwatson	.mpo_pipe_internalize_label = lomac_internalize_label,
3013173138Srwatson	.mpo_pipe_relabel = lomac_pipe_relabel,
3014173138Srwatson
3015173138Srwatson	.mpo_priv_check = lomac_priv_check,
3016173138Srwatson
3017172955Srwatson	.mpo_proc_check_debug = lomac_proc_check_debug,
3018172955Srwatson	.mpo_proc_check_sched = lomac_proc_check_sched,
3019172955Srwatson	.mpo_proc_check_signal = lomac_proc_check_signal,
3020173138Srwatson	.mpo_proc_destroy_label = lomac_proc_destroy_label,
3021173138Srwatson	.mpo_proc_init_label = lomac_proc_init_label,
3022173138Srwatson
3023172955Srwatson	.mpo_socket_check_deliver = lomac_socket_check_deliver,
3024172955Srwatson	.mpo_socket_check_relabel = lomac_socket_check_relabel,
3025172955Srwatson	.mpo_socket_check_visible = lomac_socket_check_visible,
3026173138Srwatson	.mpo_socket_copy_label = lomac_copy_label,
3027173138Srwatson	.mpo_socket_create = lomac_socket_create,
3028173138Srwatson	.mpo_socket_create_mbuf = lomac_socket_create_mbuf,
3029173138Srwatson	.mpo_socket_destroy_label = lomac_destroy_label,
3030173138Srwatson	.mpo_socket_externalize_label = lomac_externalize_label,
3031173138Srwatson	.mpo_socket_init_label = lomac_init_label_waitcheck,
3032173138Srwatson	.mpo_socket_internalize_label = lomac_internalize_label,
3033173138Srwatson	.mpo_socket_newconn = lomac_socket_newconn,
3034173138Srwatson	.mpo_socket_relabel = lomac_socket_relabel,
3035173138Srwatson
3036173138Srwatson	.mpo_socketpeer_destroy_label = lomac_destroy_label,
3037173138Srwatson	.mpo_socketpeer_externalize_label = lomac_externalize_label,
3038173138Srwatson	.mpo_socketpeer_init_label = lomac_init_label_waitcheck,
3039173138Srwatson	.mpo_socketpeer_set_from_mbuf = lomac_socketpeer_set_from_mbuf,
3040173138Srwatson	.mpo_socketpeer_set_from_socket = lomac_socketpeer_set_from_socket,
3041173138Srwatson
3042173138Srwatson	.mpo_syncache_create_mbuf = lomac_syncache_create_mbuf,
3043173138Srwatson
3044172955Srwatson	.mpo_system_check_acct = lomac_system_check_acct,
3045172955Srwatson	.mpo_system_check_auditctl = lomac_system_check_auditctl,
3046172955Srwatson	.mpo_system_check_swapoff = lomac_system_check_swapoff,
3047172955Srwatson	.mpo_system_check_swapon = lomac_system_check_swapon,
3048172955Srwatson	.mpo_system_check_sysctl = lomac_system_check_sysctl,
3049173138Srwatson
3050173138Srwatson	.mpo_thread_userret = lomac_thread_userret,
3051173138Srwatson
3052173138Srwatson	.mpo_vnode_associate_extattr = lomac_vnode_associate_extattr,
3053173138Srwatson	.mpo_vnode_associate_singlelabel = lomac_vnode_associate_singlelabel,
3054172955Srwatson	.mpo_vnode_check_access = lomac_vnode_check_open,
3055172955Srwatson	.mpo_vnode_check_create = lomac_vnode_check_create,
3056172955Srwatson	.mpo_vnode_check_deleteacl = lomac_vnode_check_deleteacl,
3057172955Srwatson	.mpo_vnode_check_link = lomac_vnode_check_link,
3058172955Srwatson	.mpo_vnode_check_mmap = lomac_vnode_check_mmap,
3059172955Srwatson	.mpo_vnode_check_mmap_downgrade = lomac_vnode_check_mmap_downgrade,
3060172955Srwatson	.mpo_vnode_check_open = lomac_vnode_check_open,
3061172955Srwatson	.mpo_vnode_check_read = lomac_vnode_check_read,
3062172955Srwatson	.mpo_vnode_check_relabel = lomac_vnode_check_relabel,
3063172955Srwatson	.mpo_vnode_check_rename_from = lomac_vnode_check_rename_from,
3064172955Srwatson	.mpo_vnode_check_rename_to = lomac_vnode_check_rename_to,
3065172955Srwatson	.mpo_vnode_check_revoke = lomac_vnode_check_revoke,
3066172955Srwatson	.mpo_vnode_check_setacl = lomac_vnode_check_setacl,
3067172955Srwatson	.mpo_vnode_check_setextattr = lomac_vnode_check_setextattr,
3068172955Srwatson	.mpo_vnode_check_setflags = lomac_vnode_check_setflags,
3069172955Srwatson	.mpo_vnode_check_setmode = lomac_vnode_check_setmode,
3070172955Srwatson	.mpo_vnode_check_setowner = lomac_vnode_check_setowner,
3071172955Srwatson	.mpo_vnode_check_setutimes = lomac_vnode_check_setutimes,
3072172955Srwatson	.mpo_vnode_check_unlink = lomac_vnode_check_unlink,
3073172955Srwatson	.mpo_vnode_check_write = lomac_vnode_check_write,
3074173138Srwatson	.mpo_vnode_copy_label = lomac_copy_label,
3075173138Srwatson	.mpo_vnode_create_extattr = lomac_vnode_create_extattr,
3076173138Srwatson	.mpo_vnode_destroy_label = lomac_destroy_label,
3077173138Srwatson	.mpo_vnode_execve_transition = lomac_vnode_execve_transition,
3078173138Srwatson	.mpo_vnode_execve_will_transition = lomac_vnode_execve_will_transition,
3079173138Srwatson	.mpo_vnode_externalize_label = lomac_externalize_label,
3080173138Srwatson	.mpo_vnode_init_label = lomac_init_label,
3081173138Srwatson	.mpo_vnode_internalize_label = lomac_internalize_label,
3082173138Srwatson	.mpo_vnode_relabel = lomac_vnode_relabel,
3083173138Srwatson	.mpo_vnode_setlabel_extattr = lomac_vnode_setlabel_extattr,
3084107273Srwatson};
3085107273Srwatson
3086172955SrwatsonMAC_POLICY_SET(&lomac_ops, mac_lomac, "TrustedBSD MAC/LOMAC",
3087187016Srwatson    MPC_LOADTIME_FLAG_NOTLATE, &lomac_slot);
3088