mac_biba.c revision 122879
1101099Srwatson/*-
2101099Srwatson * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
3115497Srwatson * Copyright (c) 2001, 2002, 2003 Networks Associates Technology, Inc.
4101099Srwatson * All rights reserved.
5101099Srwatson *
6101099Srwatson * This software was developed by Robert Watson for the TrustedBSD Project.
7101099Srwatson *
8106393Srwatson * This software was developed for the FreeBSD Project in part by Network
9106393Srwatson * Associates Laboratories, the Security Research Division of Network
10106393Srwatson * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
11106393Srwatson * as part of the DARPA CHATS research program.
12101099Srwatson *
13101099Srwatson * Redistribution and use in source and binary forms, with or without
14101099Srwatson * modification, are permitted provided that the following conditions
15101099Srwatson * are met:
16101099Srwatson * 1. Redistributions of source code must retain the above copyright
17101099Srwatson *    notice, this list of conditions and the following disclaimer.
18101099Srwatson * 2. Redistributions in binary form must reproduce the above copyright
19101099Srwatson *    notice, this list of conditions and the following disclaimer in the
20101099Srwatson *    documentation and/or other materials provided with the distribution.
21101099Srwatson *
22101099Srwatson * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
23101099Srwatson * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
24101099Srwatson * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
25101099Srwatson * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
26101099Srwatson * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
27101099Srwatson * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
28101099Srwatson * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
29101099Srwatson * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
30101099Srwatson * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
31101099Srwatson * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
32101099Srwatson * SUCH DAMAGE.
33101099Srwatson *
34101099Srwatson * $FreeBSD: head/sys/security/mac_biba/mac_biba.c 122879 2003-11-18 04:11:52Z rwatson $
35101099Srwatson */
36101099Srwatson
37101099Srwatson/*
38101099Srwatson * Developed by the TrustedBSD Project.
39101099Srwatson * Biba fixed label mandatory integrity policy.
40101099Srwatson */
41101099Srwatson
42101099Srwatson#include <sys/types.h>
43101099Srwatson#include <sys/param.h>
44101099Srwatson#include <sys/acl.h>
45101099Srwatson#include <sys/conf.h>
46105988Srwatson#include <sys/extattr.h>
47101099Srwatson#include <sys/kernel.h>
48101099Srwatson#include <sys/mac.h>
49103183Sbde#include <sys/malloc.h>
50101099Srwatson#include <sys/mount.h>
51101099Srwatson#include <sys/proc.h>
52115497Srwatson#include <sys/sbuf.h>
53101099Srwatson#include <sys/systm.h>
54101099Srwatson#include <sys/sysproto.h>
55101099Srwatson#include <sys/sysent.h>
56105696Srwatson#include <sys/systm.h>
57101099Srwatson#include <sys/vnode.h>
58101099Srwatson#include <sys/file.h>
59101099Srwatson#include <sys/socket.h>
60101099Srwatson#include <sys/socketvar.h>
61101099Srwatson#include <sys/pipe.h>
62101099Srwatson#include <sys/sysctl.h>
63101099Srwatson
64101099Srwatson#include <fs/devfs/devfs.h>
65101099Srwatson
66101099Srwatson#include <net/bpfdesc.h>
67101099Srwatson#include <net/if.h>
68101099Srwatson#include <net/if_types.h>
69101099Srwatson#include <net/if_var.h>
70101099Srwatson
71101099Srwatson#include <netinet/in.h>
72122875Srwatson#include <netinet/in_pcb.h>
73101099Srwatson#include <netinet/ip_var.h>
74101099Srwatson
75122879Srwatson#include <vm/uma.h>
76101099Srwatson#include <vm/vm.h>
77101099Srwatson
78101099Srwatson#include <sys/mac_policy.h>
79101099Srwatson
80101099Srwatson#include <security/mac_biba/mac_biba.h>
81101099Srwatson
82101099SrwatsonSYSCTL_DECL(_security_mac);
83101099Srwatson
84101099SrwatsonSYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
85101099Srwatson    "TrustedBSD mac_biba policy controls");
86101099Srwatson
87105988Srwatsonstatic int	mac_biba_label_size = sizeof(struct mac_biba);
88105988SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
89105988Srwatson    &mac_biba_label_size, 0, "Size of struct mac_biba");
90105988Srwatson
91107731Srwatsonstatic int	mac_biba_enabled = 1;
92101099SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW,
93101099Srwatson    &mac_biba_enabled, 0, "Enforce MAC/Biba policy");
94102980SrwatsonTUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled);
95101099Srwatson
96101099Srwatsonstatic int	destroyed_not_inited;
97101099SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
98101099Srwatson    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
99101099Srwatson
100101099Srwatsonstatic int	trust_all_interfaces = 0;
101101099SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
102101099Srwatson    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
103101099SrwatsonTUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces);
104101099Srwatson
105101099Srwatsonstatic char	trusted_interfaces[128];
106101099SrwatsonSYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
107101099Srwatson    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
108101099SrwatsonTUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces,
109101099Srwatson    sizeof(trusted_interfaces));
110101099Srwatson
111105643Srwatsonstatic int	max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
112105643SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
113105643Srwatson    &max_compartments, 0, "Maximum supported compartments");
114105643Srwatson
115105606Srwatsonstatic int	ptys_equal = 0;
116105606SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW,
117105606Srwatson    &ptys_equal, 0, "Label pty devices as biba/equal on create");
118105606SrwatsonTUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal);
119105606Srwatson
120105637Srwatsonstatic int	revocation_enabled = 0;
121101099SrwatsonSYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW,
122105637Srwatson    &revocation_enabled, 0, "Revoke access to objects on relabel");
123105637SrwatsonTUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled);
124101099Srwatson
125101099Srwatsonstatic int	mac_biba_slot;
126101099Srwatson#define	SLOT(l)	((struct mac_biba *)LABEL_TO_SLOT((l), mac_biba_slot).l_ptr)
127101099Srwatson
128122879Srwatsonstatic uma_zone_t	zone_biba;
129101099Srwatson
130105643Srwatsonstatic __inline int
131105643Srwatsonbiba_bit_set_empty(u_char *set) {
132105643Srwatson	int i;
133105643Srwatson
134105643Srwatson	for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
135105643Srwatson		if (set[i] != 0)
136105643Srwatson			return (0);
137105643Srwatson	return (1);
138105643Srwatson}
139105643Srwatson
140101099Srwatsonstatic struct mac_biba *
141104514Srwatsonbiba_alloc(int flag)
142101099Srwatson{
143101099Srwatson
144122879Srwatson	return (uma_zalloc(zone_biba, flag | M_ZERO));
145101099Srwatson}
146101099Srwatson
147101099Srwatsonstatic void
148101099Srwatsonbiba_free(struct mac_biba *mac_biba)
149101099Srwatson{
150101099Srwatson
151101099Srwatson	if (mac_biba != NULL)
152122879Srwatson		uma_zfree(zone_biba, mac_biba);
153101099Srwatson	else
154101099Srwatson		atomic_add_int(&destroyed_not_inited, 1);
155101099Srwatson}
156101099Srwatson
157101099Srwatsonstatic int
158105634Srwatsonbiba_atmostflags(struct mac_biba *mac_biba, int flags)
159105634Srwatson{
160105634Srwatson
161105634Srwatson	if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags)
162105634Srwatson		return (EINVAL);
163105634Srwatson	return (0);
164105634Srwatson}
165105634Srwatson
166105634Srwatsonstatic int
167101099Srwatsonmac_biba_dominate_element(struct mac_biba_element *a,
168101099Srwatson    struct mac_biba_element *b)
169101099Srwatson{
170105643Srwatson	int bit;
171101099Srwatson
172105736Srwatson	switch (a->mbe_type) {
173101099Srwatson	case MAC_BIBA_TYPE_EQUAL:
174101099Srwatson	case MAC_BIBA_TYPE_HIGH:
175101099Srwatson		return (1);
176101099Srwatson
177101099Srwatson	case MAC_BIBA_TYPE_LOW:
178101099Srwatson		switch (b->mbe_type) {
179101099Srwatson		case MAC_BIBA_TYPE_GRADE:
180101099Srwatson		case MAC_BIBA_TYPE_HIGH:
181101099Srwatson			return (0);
182101099Srwatson
183101099Srwatson		case MAC_BIBA_TYPE_EQUAL:
184101099Srwatson		case MAC_BIBA_TYPE_LOW:
185101099Srwatson			return (1);
186101099Srwatson
187101099Srwatson		default:
188101099Srwatson			panic("mac_biba_dominate_element: b->mbe_type invalid");
189101099Srwatson		}
190101099Srwatson
191101099Srwatson	case MAC_BIBA_TYPE_GRADE:
192101099Srwatson		switch (b->mbe_type) {
193101099Srwatson		case MAC_BIBA_TYPE_EQUAL:
194101099Srwatson		case MAC_BIBA_TYPE_LOW:
195101099Srwatson			return (1);
196101099Srwatson
197101099Srwatson		case MAC_BIBA_TYPE_HIGH:
198101099Srwatson			return (0);
199101099Srwatson
200101099Srwatson		case MAC_BIBA_TYPE_GRADE:
201105643Srwatson			for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
202105643Srwatson				if (!MAC_BIBA_BIT_TEST(bit,
203105643Srwatson				    a->mbe_compartments) &&
204105643Srwatson				    MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
205105643Srwatson					return (0);
206101099Srwatson			return (a->mbe_grade >= b->mbe_grade);
207101099Srwatson
208101099Srwatson		default:
209101099Srwatson			panic("mac_biba_dominate_element: b->mbe_type invalid");
210101099Srwatson		}
211101099Srwatson
212101099Srwatson	default:
213101099Srwatson		panic("mac_biba_dominate_element: a->mbe_type invalid");
214101099Srwatson	}
215101099Srwatson
216101099Srwatson	return (0);
217101099Srwatson}
218101099Srwatson
219101099Srwatsonstatic int
220105988Srwatsonmac_biba_subject_dominate_high(struct mac_biba *mac_biba)
221105988Srwatson{
222105988Srwatson	struct mac_biba_element *element;
223105988Srwatson
224106174Srwatson	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
225105988Srwatson	    ("mac_biba_single_in_range: mac_biba not single"));
226105988Srwatson	element = &mac_biba->mb_single;
227105988Srwatson
228105988Srwatson	return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
229105988Srwatson	    element->mbe_type == MAC_BIBA_TYPE_HIGH);
230105988Srwatson}
231105988Srwatson
232105988Srwatsonstatic int
233101099Srwatsonmac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
234101099Srwatson{
235101099Srwatson
236101099Srwatson	return (mac_biba_dominate_element(&rangeb->mb_rangehigh,
237101099Srwatson	    &rangea->mb_rangehigh) &&
238101099Srwatson	    mac_biba_dominate_element(&rangea->mb_rangelow,
239101099Srwatson	    &rangeb->mb_rangelow));
240101099Srwatson}
241101099Srwatson
242101099Srwatsonstatic int
243101099Srwatsonmac_biba_single_in_range(struct mac_biba *single, struct mac_biba *range)
244101099Srwatson{
245101099Srwatson
246103750Srwatson	KASSERT((single->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
247101099Srwatson	    ("mac_biba_single_in_range: a not single"));
248103750Srwatson	KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
249101099Srwatson	    ("mac_biba_single_in_range: b not range"));
250101099Srwatson
251101099Srwatson	return (mac_biba_dominate_element(&range->mb_rangehigh,
252101099Srwatson	    &single->mb_single) &&
253101099Srwatson	    mac_biba_dominate_element(&single->mb_single,
254101099Srwatson	    &range->mb_rangelow));
255101099Srwatson
256101099Srwatson	return (1);
257101099Srwatson}
258101099Srwatson
259101099Srwatsonstatic int
260101099Srwatsonmac_biba_dominate_single(struct mac_biba *a, struct mac_biba *b)
261101099Srwatson{
262101099Srwatson	KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
263101099Srwatson	    ("mac_biba_dominate_single: a not single"));
264101099Srwatson	KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
265101099Srwatson	    ("mac_biba_dominate_single: b not single"));
266101099Srwatson
267101099Srwatson	return (mac_biba_dominate_element(&a->mb_single, &b->mb_single));
268101099Srwatson}
269101099Srwatson
270101099Srwatsonstatic int
271101099Srwatsonmac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
272101099Srwatson{
273101099Srwatson
274101099Srwatson	if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
275101099Srwatson	    b->mbe_type == MAC_BIBA_TYPE_EQUAL)
276101099Srwatson		return (1);
277101099Srwatson
278101099Srwatson	return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
279101099Srwatson}
280101099Srwatson
281101099Srwatsonstatic int
282101099Srwatsonmac_biba_equal_single(struct mac_biba *a, struct mac_biba *b)
283101099Srwatson{
284101099Srwatson
285101099Srwatson	KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
286101099Srwatson	    ("mac_biba_equal_single: a not single"));
287101099Srwatson	KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
288101099Srwatson	    ("mac_biba_equal_single: b not single"));
289101099Srwatson
290101099Srwatson	return (mac_biba_equal_element(&a->mb_single, &b->mb_single));
291101099Srwatson}
292101099Srwatson
293101099Srwatsonstatic int
294105634Srwatsonmac_biba_contains_equal(struct mac_biba *mac_biba)
295105634Srwatson{
296105634Srwatson
297105634Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE)
298105634Srwatson		if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL)
299105634Srwatson			return (1);
300105634Srwatson
301105634Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
302105634Srwatson		if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
303105634Srwatson			return (1);
304105634Srwatson		if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
305105637Srwatson			return (1);
306105634Srwatson	}
307105634Srwatson
308105634Srwatson	return (0);
309105634Srwatson}
310105634Srwatson
311105634Srwatsonstatic int
312106090Srwatsonmac_biba_subject_privileged(struct mac_biba *mac_biba)
313105634Srwatson{
314105634Srwatson
315105634Srwatson	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
316105634Srwatson	    MAC_BIBA_FLAGS_BOTH,
317106090Srwatson	    ("mac_biba_subject_privileged: subject doesn't have both labels"));
318105634Srwatson
319105634Srwatson	/* If the single is EQUAL, it's ok. */
320105634Srwatson	if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL)
321105634Srwatson		return (0);
322105634Srwatson
323105634Srwatson	/* If either range endpoint is EQUAL, it's ok. */
324105634Srwatson	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
325105634Srwatson	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
326105634Srwatson		return (0);
327105634Srwatson
328105634Srwatson	/* If the range is low-high, it's ok. */
329105634Srwatson	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
330105634Srwatson	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
331105634Srwatson		return (0);
332105634Srwatson
333105634Srwatson	/* It's not ok. */
334105634Srwatson	return (EPERM);
335105634Srwatson}
336105634Srwatson
337106091Srwatsonstatic int
338105988Srwatsonmac_biba_high_single(struct mac_biba *mac_biba)
339105988Srwatson{
340105988Srwatson
341105988Srwatson	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
342105988Srwatson	    ("mac_biba_equal_single: mac_biba not single"));
343105988Srwatson
344105988Srwatson	return (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_HIGH);
345105988Srwatson}
346105988Srwatson
347105634Srwatsonstatic int
348101099Srwatsonmac_biba_valid(struct mac_biba *mac_biba)
349101099Srwatson{
350101099Srwatson
351101099Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) {
352101099Srwatson		switch (mac_biba->mb_single.mbe_type) {
353101099Srwatson		case MAC_BIBA_TYPE_GRADE:
354101099Srwatson			break;
355101099Srwatson
356101099Srwatson		case MAC_BIBA_TYPE_EQUAL:
357101099Srwatson		case MAC_BIBA_TYPE_HIGH:
358101099Srwatson		case MAC_BIBA_TYPE_LOW:
359105643Srwatson			if (mac_biba->mb_single.mbe_grade != 0 ||
360105643Srwatson			    !MAC_BIBA_BIT_SET_EMPTY(
361105643Srwatson			    mac_biba->mb_single.mbe_compartments))
362101099Srwatson				return (EINVAL);
363101099Srwatson			break;
364101099Srwatson
365101099Srwatson		default:
366101099Srwatson			return (EINVAL);
367101099Srwatson		}
368101099Srwatson	} else {
369101099Srwatson		if (mac_biba->mb_single.mbe_type != MAC_BIBA_TYPE_UNDEF)
370101099Srwatson			return (EINVAL);
371101099Srwatson	}
372101099Srwatson
373101099Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
374101099Srwatson		switch (mac_biba->mb_rangelow.mbe_type) {
375101099Srwatson		case MAC_BIBA_TYPE_GRADE:
376101099Srwatson			break;
377101099Srwatson
378101099Srwatson		case MAC_BIBA_TYPE_EQUAL:
379101099Srwatson		case MAC_BIBA_TYPE_HIGH:
380101099Srwatson		case MAC_BIBA_TYPE_LOW:
381105643Srwatson			if (mac_biba->mb_rangelow.mbe_grade != 0 ||
382105643Srwatson			    !MAC_BIBA_BIT_SET_EMPTY(
383105643Srwatson			    mac_biba->mb_rangelow.mbe_compartments))
384101099Srwatson				return (EINVAL);
385101099Srwatson			break;
386101099Srwatson
387101099Srwatson		default:
388101099Srwatson			return (EINVAL);
389101099Srwatson		}
390101099Srwatson
391101099Srwatson		switch (mac_biba->mb_rangehigh.mbe_type) {
392101099Srwatson		case MAC_BIBA_TYPE_GRADE:
393101099Srwatson			break;
394101099Srwatson
395101099Srwatson		case MAC_BIBA_TYPE_EQUAL:
396101099Srwatson		case MAC_BIBA_TYPE_HIGH:
397101099Srwatson		case MAC_BIBA_TYPE_LOW:
398105643Srwatson			if (mac_biba->mb_rangehigh.mbe_grade != 0 ||
399105643Srwatson			    !MAC_BIBA_BIT_SET_EMPTY(
400105643Srwatson			    mac_biba->mb_rangehigh.mbe_compartments))
401101099Srwatson				return (EINVAL);
402101099Srwatson			break;
403101099Srwatson
404101099Srwatson		default:
405101099Srwatson			return (EINVAL);
406101099Srwatson		}
407101099Srwatson		if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh,
408101099Srwatson		    &mac_biba->mb_rangelow))
409101099Srwatson			return (EINVAL);
410101099Srwatson	} else {
411101099Srwatson		if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
412101099Srwatson		    mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
413101099Srwatson			return (EINVAL);
414101099Srwatson	}
415101099Srwatson
416101099Srwatson	return (0);
417101099Srwatson}
418101099Srwatson
419101099Srwatsonstatic void
420101099Srwatsonmac_biba_set_range(struct mac_biba *mac_biba, u_short typelow,
421105643Srwatson    u_short gradelow, u_char *compartmentslow, u_short typehigh,
422105643Srwatson    u_short gradehigh, u_char *compartmentshigh)
423101099Srwatson{
424101099Srwatson
425101099Srwatson	mac_biba->mb_rangelow.mbe_type = typelow;
426101099Srwatson	mac_biba->mb_rangelow.mbe_grade = gradelow;
427105643Srwatson	if (compartmentslow != NULL)
428105643Srwatson		memcpy(mac_biba->mb_rangelow.mbe_compartments,
429105643Srwatson		    compartmentslow,
430105643Srwatson		    sizeof(mac_biba->mb_rangelow.mbe_compartments));
431101099Srwatson	mac_biba->mb_rangehigh.mbe_type = typehigh;
432101099Srwatson	mac_biba->mb_rangehigh.mbe_grade = gradehigh;
433105643Srwatson	if (compartmentshigh != NULL)
434105643Srwatson		memcpy(mac_biba->mb_rangehigh.mbe_compartments,
435105643Srwatson		    compartmentshigh,
436105643Srwatson		    sizeof(mac_biba->mb_rangehigh.mbe_compartments));
437101099Srwatson	mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
438101099Srwatson}
439101099Srwatson
440101099Srwatsonstatic void
441105643Srwatsonmac_biba_set_single(struct mac_biba *mac_biba, u_short type, u_short grade,
442105643Srwatson    u_char *compartments)
443101099Srwatson{
444101099Srwatson
445101099Srwatson	mac_biba->mb_single.mbe_type = type;
446101099Srwatson	mac_biba->mb_single.mbe_grade = grade;
447105643Srwatson	if (compartments != NULL)
448105643Srwatson		memcpy(mac_biba->mb_single.mbe_compartments, compartments,
449105643Srwatson		    sizeof(mac_biba->mb_single.mbe_compartments));
450101099Srwatson	mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE;
451101099Srwatson}
452101099Srwatson
453101099Srwatsonstatic void
454101099Srwatsonmac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
455101099Srwatson{
456105643Srwatson
457101099Srwatson	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
458101099Srwatson	    ("mac_biba_copy_range: labelfrom not range"));
459101099Srwatson
460101099Srwatson	labelto->mb_rangelow = labelfrom->mb_rangelow;
461101099Srwatson	labelto->mb_rangehigh = labelfrom->mb_rangehigh;
462101099Srwatson	labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
463101099Srwatson}
464101099Srwatson
465101099Srwatsonstatic void
466101099Srwatsonmac_biba_copy_single(struct mac_biba *labelfrom, struct mac_biba *labelto)
467101099Srwatson{
468101099Srwatson
469101099Srwatson	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
470101099Srwatson	    ("mac_biba_copy_single: labelfrom not single"));
471101099Srwatson
472101099Srwatson	labelto->mb_single = labelfrom->mb_single;
473101099Srwatson	labelto->mb_flags |= MAC_BIBA_FLAG_SINGLE;
474101099Srwatson}
475101099Srwatson
476105656Srwatsonstatic void
477105656Srwatsonmac_biba_copy(struct mac_biba *source, struct mac_biba *dest)
478105656Srwatson{
479105656Srwatson
480105656Srwatson	if (source->mb_flags & MAC_BIBA_FLAG_SINGLE)
481105656Srwatson		mac_biba_copy_single(source, dest);
482105656Srwatson	if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
483105656Srwatson		mac_biba_copy_range(source, dest);
484105656Srwatson}
485105656Srwatson
486101099Srwatson/*
487101099Srwatson * Policy module operations.
488101099Srwatson */
489101099Srwatsonstatic void
490101099Srwatsonmac_biba_init(struct mac_policy_conf *conf)
491101099Srwatson{
492101099Srwatson
493122879Srwatson	zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL,
494122879Srwatson	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
495101099Srwatson}
496101099Srwatson
497101099Srwatson/*
498101099Srwatson * Label operations.
499101099Srwatson */
500101099Srwatsonstatic void
501104514Srwatsonmac_biba_init_label(struct label *label)
502101099Srwatson{
503101099Srwatson
504111119Simp	SLOT(label) = biba_alloc(M_WAITOK);
505101099Srwatson}
506101099Srwatson
507101099Srwatsonstatic int
508104514Srwatsonmac_biba_init_label_waitcheck(struct label *label, int flag)
509101099Srwatson{
510101099Srwatson
511104514Srwatson	SLOT(label) = biba_alloc(flag);
512101099Srwatson	if (SLOT(label) == NULL)
513101099Srwatson		return (ENOMEM);
514101099Srwatson
515101099Srwatson	return (0);
516101099Srwatson}
517101099Srwatson
518101099Srwatsonstatic void
519104514Srwatsonmac_biba_destroy_label(struct label *label)
520101099Srwatson{
521101099Srwatson
522101099Srwatson	biba_free(SLOT(label));
523101099Srwatson	SLOT(label) = NULL;
524101099Srwatson}
525101099Srwatson
526105696Srwatson/*
527115497Srwatson * mac_biba_element_to_string() accepts an sbuf and Biba element.  It
528115497Srwatson * converts the Biba element to a string and stores the result in the
529115497Srwatson * sbuf; if there isn't space in the sbuf, -1 is returned.
530105696Srwatson */
531115497Srwatsonstatic int
532115497Srwatsonmac_biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element)
533105696Srwatson{
534115497Srwatson	int i, first;
535105696Srwatson
536105696Srwatson	switch (element->mbe_type) {
537105696Srwatson	case MAC_BIBA_TYPE_HIGH:
538115497Srwatson		return (sbuf_printf(sb, "high"));
539105696Srwatson
540105696Srwatson	case MAC_BIBA_TYPE_LOW:
541115497Srwatson		return (sbuf_printf(sb, "low"));
542105696Srwatson
543105696Srwatson	case MAC_BIBA_TYPE_EQUAL:
544115497Srwatson		return (sbuf_printf(sb, "equal"));
545105696Srwatson
546105696Srwatson	case MAC_BIBA_TYPE_GRADE:
547115497Srwatson		if (sbuf_printf(sb, "%d", element->mbe_grade) == -1)
548115497Srwatson			return (-1);
549115497Srwatson
550115497Srwatson		first = 1;
551115497Srwatson		for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) {
552115497Srwatson			if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) {
553115497Srwatson				if (first) {
554115497Srwatson					if (sbuf_putc(sb, ':') == -1)
555115497Srwatson						return (-1);
556115497Srwatson					if (sbuf_printf(sb, "%d", i) == -1)
557115497Srwatson						return (-1);
558115497Srwatson					first = 0;
559115497Srwatson				} else {
560115497Srwatson					if (sbuf_printf(sb, "+%d", i) == -1)
561115497Srwatson						return (-1);
562115497Srwatson				}
563115497Srwatson			}
564105696Srwatson		}
565115497Srwatson		return (0);
566105696Srwatson
567105696Srwatson	default:
568105696Srwatson		panic("mac_biba_element_to_string: invalid type (%d)",
569105696Srwatson		    element->mbe_type);
570105696Srwatson	}
571105696Srwatson}
572105696Srwatson
573115497Srwatson/*
574116701Srwatson * mac_biba_to_string() converts a Biba label to a string, and places
575116701Srwatson * the results in the passed sbuf.  It returns 0 on success, or EINVAL
576116701Srwatson * if there isn't room in the sbuf.  Note: the sbuf will be modified
577116701Srwatson * even in a failure case, so the caller may need to revert the sbuf
578116701Srwatson * by restoring the offset if that's undesired.
579115497Srwatson */
580101099Srwatsonstatic int
581116701Srwatsonmac_biba_to_string(struct sbuf *sb, struct mac_biba *mac_biba)
582101099Srwatson{
583105696Srwatson
584105696Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) {
585116701Srwatson		if (mac_biba_element_to_string(sb, &mac_biba->mb_single)
586115497Srwatson		    == -1)
587105696Srwatson			return (EINVAL);
588105696Srwatson	}
589105696Srwatson
590105696Srwatson	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
591116701Srwatson		if (sbuf_putc(sb, '(') == -1)
592105696Srwatson			return (EINVAL);
593105696Srwatson
594116701Srwatson		if (mac_biba_element_to_string(sb, &mac_biba->mb_rangelow)
595115497Srwatson		    == -1)
596105696Srwatson			return (EINVAL);
597105696Srwatson
598116701Srwatson		if (sbuf_putc(sb, '-') == -1)
599105696Srwatson			return (EINVAL);
600105696Srwatson
601116701Srwatson		if (mac_biba_element_to_string(sb, &mac_biba->mb_rangehigh)
602115497Srwatson		    == -1)
603105696Srwatson			return (EINVAL);
604105696Srwatson
605116701Srwatson		if (sbuf_putc(sb, ')') == -1)
606105696Srwatson			return (EINVAL);
607105696Srwatson	}
608105696Srwatson
609105696Srwatson	return (0);
610105696Srwatson}
611105696Srwatson
612105696Srwatsonstatic int
613105696Srwatsonmac_biba_externalize_label(struct label *label, char *element_name,
614116701Srwatson    struct sbuf *sb, int *claimed)
615105696Srwatson{
616101099Srwatson	struct mac_biba *mac_biba;
617101099Srwatson
618105696Srwatson	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
619105696Srwatson		return (0);
620105696Srwatson
621105696Srwatson	(*claimed)++;
622105696Srwatson
623101099Srwatson	mac_biba = SLOT(label);
624116701Srwatson	return (mac_biba_to_string(sb, mac_biba));
625105696Srwatson}
626105696Srwatson
627105696Srwatsonstatic int
628105696Srwatsonmac_biba_parse_element(struct mac_biba_element *element, char *string)
629101099Srwatson{
630115395Srwatson	char *compartment, *end, *grade;
631115395Srwatson	int value;
632105696Srwatson
633105696Srwatson	if (strcmp(string, "high") == 0 ||
634105696Srwatson	    strcmp(string, "hi") == 0) {
635105696Srwatson		element->mbe_type = MAC_BIBA_TYPE_HIGH;
636105696Srwatson		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
637105696Srwatson	} else if (strcmp(string, "low") == 0 ||
638105696Srwatson	    strcmp(string, "lo") == 0) {
639105696Srwatson		element->mbe_type = MAC_BIBA_TYPE_LOW;
640105696Srwatson		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
641105696Srwatson	} else if (strcmp(string, "equal") == 0 ||
642105696Srwatson	    strcmp(string, "eq") == 0) {
643105696Srwatson		element->mbe_type = MAC_BIBA_TYPE_EQUAL;
644105696Srwatson		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
645105696Srwatson	} else {
646115395Srwatson		element->mbe_type = MAC_BIBA_TYPE_GRADE;
647105696Srwatson
648115395Srwatson		/*
649115395Srwatson		 * Numeric grade piece of the element.
650115395Srwatson		 */
651115395Srwatson		grade = strsep(&string, ":");
652115395Srwatson		value = strtol(grade, &end, 10);
653115395Srwatson		if (end == grade || *end != '\0')
654105696Srwatson			return (EINVAL);
655115395Srwatson		if (value < 0 || value > 65535)
656115395Srwatson			return (EINVAL);
657115395Srwatson		element->mbe_grade = value;
658105696Srwatson
659115395Srwatson		/*
660115395Srwatson		 * Optional compartment piece of the element.  If none
661115395Srwatson		 * are included, we assume that the label has no
662115395Srwatson		 * compartments.
663115395Srwatson		 */
664115395Srwatson		if (string == NULL)
665115395Srwatson			return (0);
666115395Srwatson		if (*string == '\0')
667115395Srwatson			return (0);
668105696Srwatson
669115395Srwatson		while ((compartment = strsep(&string, "+")) != NULL) {
670115395Srwatson			value = strtol(compartment, &end, 10);
671115395Srwatson			if (compartment == end || *end != '\0')
672105696Srwatson				return (EINVAL);
673115395Srwatson			if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS)
674105696Srwatson				return (EINVAL);
675115395Srwatson			MAC_BIBA_BIT_SET(value, element->mbe_compartments);
676105696Srwatson		}
677105696Srwatson	}
678105696Srwatson
679105696Srwatson	return (0);
680105696Srwatson}
681105696Srwatson
682105696Srwatson/*
683105696Srwatson * Note: destructively consumes the string, make a local copy before
684105696Srwatson * calling if that's a problem.
685105696Srwatson */
686105696Srwatsonstatic int
687105696Srwatsonmac_biba_parse(struct mac_biba *mac_biba, char *string)
688105696Srwatson{
689115395Srwatson	char *rangehigh, *rangelow, *single;
690101099Srwatson	int error;
691101099Srwatson
692115395Srwatson	single = strsep(&string, "(");
693115395Srwatson	if (*single == '\0')
694105696Srwatson		single = NULL;
695115395Srwatson
696115395Srwatson	if (string != NULL) {
697115395Srwatson		rangelow = strsep(&string, "-");
698115395Srwatson		if (string == NULL)
699105696Srwatson			return (EINVAL);
700115395Srwatson		rangehigh = strsep(&string, ")");
701115395Srwatson		if (string == NULL)
702105696Srwatson			return (EINVAL);
703115395Srwatson		if (*string != '\0')
704105696Srwatson			return (EINVAL);
705115395Srwatson	} else {
706115395Srwatson		rangelow = NULL;
707115395Srwatson		rangehigh = NULL;
708105696Srwatson	}
709115395Srwatson
710105696Srwatson	KASSERT((rangelow != NULL && rangehigh != NULL) ||
711105696Srwatson	    (rangelow == NULL && rangehigh == NULL),
712115395Srwatson	    ("mac_biba_parse: range mismatch"));
713101099Srwatson
714105696Srwatson	bzero(mac_biba, sizeof(*mac_biba));
715105696Srwatson	if (single != NULL) {
716105696Srwatson		error = mac_biba_parse_element(&mac_biba->mb_single, single);
717105696Srwatson		if (error)
718105696Srwatson			return (error);
719105696Srwatson		mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE;
720105696Srwatson	}
721105696Srwatson
722105696Srwatson	if (rangelow != NULL) {
723105696Srwatson		error = mac_biba_parse_element(&mac_biba->mb_rangelow,
724105696Srwatson		    rangelow);
725105696Srwatson		if (error)
726105696Srwatson			return (error);
727105696Srwatson		error = mac_biba_parse_element(&mac_biba->mb_rangehigh,
728105696Srwatson		    rangehigh);
729105696Srwatson		if (error)
730105696Srwatson			return (error);
731105696Srwatson		mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
732105696Srwatson	}
733105696Srwatson
734101099Srwatson	error = mac_biba_valid(mac_biba);
735101099Srwatson	if (error)
736101099Srwatson		return (error);
737101099Srwatson
738105696Srwatson	return (0);
739105696Srwatson}
740101099Srwatson
741105696Srwatsonstatic int
742105696Srwatsonmac_biba_internalize_label(struct label *label, char *element_name,
743105696Srwatson    char *element_data, int *claimed)
744105696Srwatson{
745105696Srwatson	struct mac_biba *mac_biba, mac_biba_temp;
746105696Srwatson	int error;
747105696Srwatson
748105696Srwatson	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
749105696Srwatson		return (0);
750105696Srwatson
751105696Srwatson	(*claimed)++;
752105696Srwatson
753105696Srwatson	error = mac_biba_parse(&mac_biba_temp, element_data);
754105696Srwatson	if (error)
755105696Srwatson		return (error);
756105696Srwatson
757105696Srwatson	mac_biba = SLOT(label);
758105696Srwatson	*mac_biba = mac_biba_temp;
759105696Srwatson
760101099Srwatson	return (0);
761101099Srwatson}
762101099Srwatson
763105696Srwatsonstatic void
764105696Srwatsonmac_biba_copy_label(struct label *src, struct label *dest)
765105696Srwatson{
766105696Srwatson
767105696Srwatson	*SLOT(dest) = *SLOT(src);
768105696Srwatson}
769105696Srwatson
770101099Srwatson/*
771101099Srwatson * Labeling event operations: file system objects, and things that look
772101099Srwatson * a lot like file system objects.
773101099Srwatson */
774101099Srwatsonstatic void
775107698Srwatsonmac_biba_create_devfs_device(struct mount *mp, dev_t dev,
776107698Srwatson    struct devfs_dirent *devfs_dirent, struct label *label)
777101099Srwatson{
778101099Srwatson	struct mac_biba *mac_biba;
779101099Srwatson	int biba_type;
780101099Srwatson
781101099Srwatson	mac_biba = SLOT(label);
782101099Srwatson	if (strcmp(dev->si_name, "null") == 0 ||
783101099Srwatson	    strcmp(dev->si_name, "zero") == 0 ||
784101099Srwatson	    strcmp(dev->si_name, "random") == 0 ||
785101099Srwatson	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
786101099Srwatson		biba_type = MAC_BIBA_TYPE_EQUAL;
787105606Srwatson	else if (ptys_equal &&
788105606Srwatson	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
789105606Srwatson	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
790105606Srwatson		biba_type = MAC_BIBA_TYPE_EQUAL;
791101099Srwatson	else
792101099Srwatson		biba_type = MAC_BIBA_TYPE_HIGH;
793105643Srwatson	mac_biba_set_single(mac_biba, biba_type, 0, NULL);
794101099Srwatson}
795101099Srwatson
796101099Srwatsonstatic void
797107698Srwatsonmac_biba_create_devfs_directory(struct mount *mp, char *dirname,
798107698Srwatson    int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
799101099Srwatson{
800101099Srwatson	struct mac_biba *mac_biba;
801101099Srwatson
802101099Srwatson	mac_biba = SLOT(label);
803105643Srwatson	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
804101099Srwatson}
805101099Srwatson
806101099Srwatsonstatic void
807107698Srwatsonmac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp,
808107698Srwatson    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
809122563Srwatson    struct label *delabel)
810104535Srwatson{
811104535Srwatson	struct mac_biba *source, *dest;
812104535Srwatson
813122524Srwatson	source = SLOT(cred->cr_label);
814104535Srwatson	dest = SLOT(delabel);
815104535Srwatson
816104535Srwatson	mac_biba_copy_single(source, dest);
817104535Srwatson}
818104535Srwatson
819104535Srwatsonstatic void
820101099Srwatsonmac_biba_create_mount(struct ucred *cred, struct mount *mp,
821101099Srwatson    struct label *mntlabel, struct label *fslabel)
822101099Srwatson{
823101099Srwatson	struct mac_biba *source, *dest;
824101099Srwatson
825122524Srwatson	source = SLOT(cred->cr_label);
826101099Srwatson	dest = SLOT(mntlabel);
827101099Srwatson	mac_biba_copy_single(source, dest);
828101099Srwatson	dest = SLOT(fslabel);
829101099Srwatson	mac_biba_copy_single(source, dest);
830101099Srwatson}
831101099Srwatson
832101099Srwatsonstatic void
833101099Srwatsonmac_biba_create_root_mount(struct ucred *cred, struct mount *mp,
834101099Srwatson    struct label *mntlabel, struct label *fslabel)
835101099Srwatson{
836101099Srwatson	struct mac_biba *mac_biba;
837101099Srwatson
838101099Srwatson	/* Always mount root as high integrity. */
839101099Srwatson	mac_biba = SLOT(fslabel);
840105643Srwatson	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
841101099Srwatson	mac_biba = SLOT(mntlabel);
842105643Srwatson	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
843101099Srwatson}
844101099Srwatson
845101099Srwatsonstatic void
846101099Srwatsonmac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp,
847101099Srwatson    struct label *vnodelabel, struct label *label)
848101099Srwatson{
849101099Srwatson	struct mac_biba *source, *dest;
850101099Srwatson
851101099Srwatson	source = SLOT(label);
852101099Srwatson	dest = SLOT(vnodelabel);
853101099Srwatson
854105656Srwatson	mac_biba_copy(source, dest);
855101099Srwatson}
856101099Srwatson
857101099Srwatsonstatic void
858107698Srwatsonmac_biba_update_devfsdirent(struct mount *mp,
859107698Srwatson    struct devfs_dirent *devfs_dirent, struct label *direntlabel,
860107698Srwatson    struct vnode *vp, struct label *vnodelabel)
861101099Srwatson{
862101099Srwatson	struct mac_biba *source, *dest;
863101099Srwatson
864101099Srwatson	source = SLOT(vnodelabel);
865101099Srwatson	dest = SLOT(direntlabel);
866101099Srwatson
867105656Srwatson	mac_biba_copy(source, dest);
868101099Srwatson}
869101099Srwatson
870101099Srwatsonstatic void
871105988Srwatsonmac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
872105988Srwatson    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
873105988Srwatson    struct label *vlabel)
874101099Srwatson{
875101099Srwatson	struct mac_biba *source, *dest;
876101099Srwatson
877105988Srwatson	source = SLOT(delabel);
878105988Srwatson	dest = SLOT(vlabel);
879101099Srwatson
880101099Srwatson	mac_biba_copy_single(source, dest);
881101099Srwatson}
882101099Srwatson
883101099Srwatsonstatic int
884105988Srwatsonmac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
885105988Srwatson    struct vnode *vp, struct label *vlabel)
886101099Srwatson{
887105988Srwatson	struct mac_biba temp, *source, *dest;
888106354Smux	int buflen, error;
889101099Srwatson
890105988Srwatson	source = SLOT(fslabel);
891105988Srwatson	dest = SLOT(vlabel);
892101099Srwatson
893105988Srwatson	buflen = sizeof(temp);
894105988Srwatson	bzero(&temp, buflen);
895105988Srwatson
896105988Srwatson	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
897105988Srwatson	    MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
898105988Srwatson	if (error == ENOATTR || error == EOPNOTSUPP) {
899105988Srwatson		/* Fall back to the fslabel. */
900105988Srwatson		mac_biba_copy_single(source, dest);
901105988Srwatson		return (0);
902105988Srwatson	} else if (error)
903101099Srwatson		return (error);
904101099Srwatson
905105988Srwatson	if (buflen != sizeof(temp)) {
906105988Srwatson		printf("mac_biba_associate_vnode_extattr: bad size %d\n",
907105988Srwatson		    buflen);
908105988Srwatson		return (EPERM);
909105988Srwatson	}
910105988Srwatson	if (mac_biba_valid(&temp) != 0) {
911105988Srwatson		printf("mac_biba_associate_vnode_extattr: invalid\n");
912105988Srwatson		return (EPERM);
913105988Srwatson	}
914105988Srwatson	if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_SINGLE) {
915105988Srwatson		printf("mac_biba_associate_vnode_extattr: not single\n");
916105988Srwatson		return (EPERM);
917105988Srwatson	}
918101099Srwatson
919105988Srwatson	mac_biba_copy_single(&temp, dest);
920101099Srwatson	return (0);
921101099Srwatson}
922101099Srwatson
923101099Srwatsonstatic void
924105988Srwatsonmac_biba_associate_vnode_singlelabel(struct mount *mp,
925105988Srwatson    struct label *fslabel, struct vnode *vp, struct label *vlabel)
926101099Srwatson{
927101099Srwatson	struct mac_biba *source, *dest;
928101099Srwatson
929101099Srwatson	source = SLOT(fslabel);
930105988Srwatson	dest = SLOT(vlabel);
931101099Srwatson
932101099Srwatson	mac_biba_copy_single(source, dest);
933101099Srwatson}
934101099Srwatson
935105988Srwatsonstatic int
936105988Srwatsonmac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp,
937105988Srwatson    struct label *fslabel, struct vnode *dvp, struct label *dlabel,
938105988Srwatson    struct vnode *vp, struct label *vlabel, struct componentname *cnp)
939105988Srwatson{
940105988Srwatson	struct mac_biba *source, *dest, temp;
941105988Srwatson	size_t buflen;
942105988Srwatson	int error;
943105988Srwatson
944105988Srwatson	buflen = sizeof(temp);
945105988Srwatson	bzero(&temp, buflen);
946105988Srwatson
947122524Srwatson	source = SLOT(cred->cr_label);
948105988Srwatson	dest = SLOT(vlabel);
949105988Srwatson	mac_biba_copy_single(source, &temp);
950105988Srwatson
951105988Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
952105988Srwatson	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
953105988Srwatson	if (error == 0)
954105988Srwatson		mac_biba_copy_single(source, dest);
955105988Srwatson	return (error);
956105988Srwatson}
957105988Srwatson
958105988Srwatsonstatic int
959105988Srwatsonmac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
960105988Srwatson    struct label *vlabel, struct label *intlabel)
961105988Srwatson{
962105988Srwatson	struct mac_biba *source, temp;
963105988Srwatson	size_t buflen;
964105988Srwatson	int error;
965105988Srwatson
966105988Srwatson	buflen = sizeof(temp);
967105988Srwatson	bzero(&temp, buflen);
968105988Srwatson
969105988Srwatson	source = SLOT(intlabel);
970105988Srwatson	if ((source->mb_flags & MAC_BIBA_FLAG_SINGLE) == 0)
971105988Srwatson		return (0);
972105988Srwatson
973105988Srwatson	mac_biba_copy_single(source, &temp);
974105988Srwatson
975105988Srwatson	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
976105988Srwatson	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
977105988Srwatson	return (error);
978105988Srwatson}
979105988Srwatson
980101099Srwatson/*
981101099Srwatson * Labeling event operations: IPC object.
982101099Srwatson */
983101099Srwatsonstatic void
984122875Srwatsonmac_biba_create_inpcb_from_socket(struct socket *so, struct label *solabel,
985122875Srwatson    struct inpcb *inp, struct label *inplabel)
986122875Srwatson{
987122875Srwatson	struct mac_biba *source, *dest;
988122875Srwatson
989122875Srwatson	source = SLOT(solabel);
990122875Srwatson	dest = SLOT(inplabel);
991122875Srwatson
992122875Srwatson	mac_biba_copy_single(source, dest);
993122875Srwatson}
994122875Srwatson
995122875Srwatsonstatic void
996101099Srwatsonmac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
997101099Srwatson    struct mbuf *m, struct label *mbuflabel)
998101099Srwatson{
999101099Srwatson	struct mac_biba *source, *dest;
1000101099Srwatson
1001101099Srwatson	source = SLOT(socketlabel);
1002101099Srwatson	dest = SLOT(mbuflabel);
1003101099Srwatson
1004101099Srwatson	mac_biba_copy_single(source, dest);
1005101099Srwatson}
1006101099Srwatson
1007101099Srwatsonstatic void
1008101099Srwatsonmac_biba_create_socket(struct ucred *cred, struct socket *socket,
1009101099Srwatson    struct label *socketlabel)
1010101099Srwatson{
1011101099Srwatson	struct mac_biba *source, *dest;
1012101099Srwatson
1013122524Srwatson	source = SLOT(cred->cr_label);
1014101099Srwatson	dest = SLOT(socketlabel);
1015101099Srwatson
1016101099Srwatson	mac_biba_copy_single(source, dest);
1017101099Srwatson}
1018101099Srwatson
1019101099Srwatsonstatic void
1020101099Srwatsonmac_biba_create_pipe(struct ucred *cred, struct pipe *pipe,
1021101099Srwatson    struct label *pipelabel)
1022101099Srwatson{
1023101099Srwatson	struct mac_biba *source, *dest;
1024101099Srwatson
1025122524Srwatson	source = SLOT(cred->cr_label);
1026101099Srwatson	dest = SLOT(pipelabel);
1027101099Srwatson
1028101099Srwatson	mac_biba_copy_single(source, dest);
1029101099Srwatson}
1030101099Srwatson
1031101099Srwatsonstatic void
1032101099Srwatsonmac_biba_create_socket_from_socket(struct socket *oldsocket,
1033101099Srwatson    struct label *oldsocketlabel, struct socket *newsocket,
1034101099Srwatson    struct label *newsocketlabel)
1035101099Srwatson{
1036101099Srwatson	struct mac_biba *source, *dest;
1037101099Srwatson
1038101099Srwatson	source = SLOT(oldsocketlabel);
1039101099Srwatson	dest = SLOT(newsocketlabel);
1040101099Srwatson
1041101099Srwatson	mac_biba_copy_single(source, dest);
1042101099Srwatson}
1043101099Srwatson
1044101099Srwatsonstatic void
1045101099Srwatsonmac_biba_relabel_socket(struct ucred *cred, struct socket *socket,
1046101099Srwatson    struct label *socketlabel, struct label *newlabel)
1047101099Srwatson{
1048101099Srwatson	struct mac_biba *source, *dest;
1049101099Srwatson
1050101099Srwatson	source = SLOT(newlabel);
1051101099Srwatson	dest = SLOT(socketlabel);
1052101099Srwatson
1053105656Srwatson	mac_biba_copy(source, dest);
1054101099Srwatson}
1055101099Srwatson
1056101099Srwatsonstatic void
1057101099Srwatsonmac_biba_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1058101099Srwatson    struct label *pipelabel, struct label *newlabel)
1059101099Srwatson{
1060101099Srwatson	struct mac_biba *source, *dest;
1061101099Srwatson
1062101099Srwatson	source = SLOT(newlabel);
1063101099Srwatson	dest = SLOT(pipelabel);
1064101099Srwatson
1065105656Srwatson	mac_biba_copy(source, dest);
1066101099Srwatson}
1067101099Srwatson
1068101099Srwatsonstatic void
1069101099Srwatsonmac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1070101099Srwatson    struct socket *socket, struct label *socketpeerlabel)
1071101099Srwatson{
1072101099Srwatson	struct mac_biba *source, *dest;
1073101099Srwatson
1074101099Srwatson	source = SLOT(mbuflabel);
1075101099Srwatson	dest = SLOT(socketpeerlabel);
1076101099Srwatson
1077101099Srwatson	mac_biba_copy_single(source, dest);
1078101099Srwatson}
1079101099Srwatson
1080101099Srwatson/*
1081101099Srwatson * Labeling event operations: network objects.
1082101099Srwatson */
1083101099Srwatsonstatic void
1084101099Srwatsonmac_biba_set_socket_peer_from_socket(struct socket *oldsocket,
1085101099Srwatson    struct label *oldsocketlabel, struct socket *newsocket,
1086101099Srwatson    struct label *newsocketpeerlabel)
1087101099Srwatson{
1088101099Srwatson	struct mac_biba *source, *dest;
1089101099Srwatson
1090101099Srwatson	source = SLOT(oldsocketlabel);
1091101099Srwatson	dest = SLOT(newsocketpeerlabel);
1092101099Srwatson
1093101099Srwatson	mac_biba_copy_single(source, dest);
1094101099Srwatson}
1095101099Srwatson
1096101099Srwatsonstatic void
1097101099Srwatsonmac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1098101099Srwatson    struct label *bpflabel)
1099101099Srwatson{
1100101099Srwatson	struct mac_biba *source, *dest;
1101101099Srwatson
1102122524Srwatson	source = SLOT(cred->cr_label);
1103101099Srwatson	dest = SLOT(bpflabel);
1104101099Srwatson
1105101099Srwatson	mac_biba_copy_single(source, dest);
1106101099Srwatson}
1107101099Srwatson
1108101099Srwatsonstatic void
1109101099Srwatsonmac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1110101099Srwatson{
1111121816Sbrooks	char tifname[IFNAMSIZ], *p, *q;
1112101099Srwatson	char tiflist[sizeof(trusted_interfaces)];
1113101099Srwatson	struct mac_biba *dest;
1114110350Srwatson	int len, type;
1115101099Srwatson
1116101099Srwatson	dest = SLOT(ifnetlabel);
1117101099Srwatson
1118101099Srwatson	if (ifnet->if_type == IFT_LOOP) {
1119110350Srwatson		type = MAC_BIBA_TYPE_EQUAL;
1120101099Srwatson		goto set;
1121101099Srwatson	}
1122101099Srwatson
1123101099Srwatson	if (trust_all_interfaces) {
1124110350Srwatson		type = MAC_BIBA_TYPE_HIGH;
1125101099Srwatson		goto set;
1126101099Srwatson	}
1127101099Srwatson
1128110350Srwatson	type = MAC_BIBA_TYPE_LOW;
1129101099Srwatson
1130101099Srwatson	if (trusted_interfaces[0] == '\0' ||
1131101099Srwatson	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1132101099Srwatson		goto set;
1133101099Srwatson
1134106089Srwatson	bzero(tiflist, sizeof(tiflist));
1135101099Srwatson	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1136101099Srwatson		if(*p != ' ' && *p != '\t')
1137101099Srwatson			*q = *p;
1138101099Srwatson
1139101099Srwatson	for (p = q = tiflist;; p++) {
1140101099Srwatson		if (*p == ',' || *p == '\0') {
1141101099Srwatson			len = p - q;
1142101099Srwatson			if (len < IFNAMSIZ) {
1143101099Srwatson				bzero(tifname, sizeof(tifname));
1144101099Srwatson				bcopy(q, tifname, len);
1145121816Sbrooks				if (strcmp(tifname, ifnet->if_xname) == 0) {
1146110350Srwatson					type = MAC_BIBA_TYPE_HIGH;
1147101099Srwatson					break;
1148101099Srwatson				}
1149106089Srwatson			} else {
1150106089Srwatson				*p = '\0';
1151106089Srwatson				printf("mac_biba warning: interface name "
1152106089Srwatson				    "\"%s\" is too long (must be < %d)\n",
1153106089Srwatson				    q, IFNAMSIZ);
1154101099Srwatson			}
1155101099Srwatson			if (*p == '\0')
1156101099Srwatson				break;
1157101099Srwatson			q = p + 1;
1158101099Srwatson		}
1159101099Srwatson	}
1160101099Srwatsonset:
1161110350Srwatson	mac_biba_set_single(dest, type, 0, NULL);
1162110350Srwatson	mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1163101099Srwatson}
1164101099Srwatson
1165101099Srwatsonstatic void
1166101099Srwatsonmac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1167101099Srwatson    struct ipq *ipq, struct label *ipqlabel)
1168101099Srwatson{
1169101099Srwatson	struct mac_biba *source, *dest;
1170101099Srwatson
1171101099Srwatson	source = SLOT(fragmentlabel);
1172101099Srwatson	dest = SLOT(ipqlabel);
1173101099Srwatson
1174101099Srwatson	mac_biba_copy_single(source, dest);
1175101099Srwatson}
1176101099Srwatson
1177101099Srwatsonstatic void
1178101099Srwatsonmac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1179101099Srwatson    struct mbuf *datagram, struct label *datagramlabel)
1180101099Srwatson{
1181101099Srwatson	struct mac_biba *source, *dest;
1182101099Srwatson
1183101099Srwatson	source = SLOT(ipqlabel);
1184101099Srwatson	dest = SLOT(datagramlabel);
1185101099Srwatson
1186101099Srwatson	/* Just use the head, since we require them all to match. */
1187101099Srwatson	mac_biba_copy_single(source, dest);
1188101099Srwatson}
1189101099Srwatson
1190101099Srwatsonstatic void
1191101099Srwatsonmac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1192101099Srwatson    struct mbuf *fragment, struct label *fragmentlabel)
1193101099Srwatson{
1194101099Srwatson	struct mac_biba *source, *dest;
1195101099Srwatson
1196101099Srwatson	source = SLOT(datagramlabel);
1197101099Srwatson	dest = SLOT(fragmentlabel);
1198101099Srwatson
1199101099Srwatson	mac_biba_copy_single(source, dest);
1200101099Srwatson}
1201101099Srwatson
1202101099Srwatsonstatic void
1203101099Srwatsonmac_biba_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
1204101099Srwatson    struct label *oldmbuflabel, struct mbuf *newmbuf,
1205101099Srwatson    struct label *newmbuflabel)
1206101099Srwatson{
1207101099Srwatson	struct mac_biba *source, *dest;
1208101099Srwatson
1209101099Srwatson	source = SLOT(oldmbuflabel);
1210101099Srwatson	dest = SLOT(newmbuflabel);
1211101099Srwatson
1212105656Srwatson	/*
1213105656Srwatson	 * Because the source mbuf may not yet have been "created",
1214105696Srwatson	 * just initialized, we do a conditional copy.  Since we don't
1215105656Srwatson	 * allow mbufs to have ranges, do a KASSERT to make sure that
1216105656Srwatson	 * doesn't happen.
1217105656Srwatson	 */
1218105656Srwatson	KASSERT((source->mb_flags & MAC_BIBA_FLAG_RANGE) == 0,
1219105656Srwatson	    ("mac_biba_create_mbuf_from_mbuf: source mbuf has range"));
1220105656Srwatson	mac_biba_copy(source, dest);
1221101099Srwatson}
1222101099Srwatson
1223101099Srwatsonstatic void
1224101099Srwatsonmac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1225101099Srwatson    struct mbuf *mbuf, struct label *mbuflabel)
1226101099Srwatson{
1227101099Srwatson	struct mac_biba *dest;
1228101099Srwatson
1229101099Srwatson	dest = SLOT(mbuflabel);
1230101099Srwatson
1231105643Srwatson	mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1232101099Srwatson}
1233101099Srwatson
1234101099Srwatsonstatic void
1235101099Srwatsonmac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1236101099Srwatson    struct mbuf *mbuf, struct label *mbuflabel)
1237101099Srwatson{
1238101099Srwatson	struct mac_biba *source, *dest;
1239101099Srwatson
1240101099Srwatson	source = SLOT(bpflabel);
1241101099Srwatson	dest = SLOT(mbuflabel);
1242101099Srwatson
1243101099Srwatson	mac_biba_copy_single(source, dest);
1244101099Srwatson}
1245101099Srwatson
1246101099Srwatsonstatic void
1247101099Srwatsonmac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1248101099Srwatson    struct mbuf *m, struct label *mbuflabel)
1249101099Srwatson{
1250101099Srwatson	struct mac_biba *source, *dest;
1251101099Srwatson
1252101099Srwatson	source = SLOT(ifnetlabel);
1253101099Srwatson	dest = SLOT(mbuflabel);
1254101099Srwatson
1255101099Srwatson	mac_biba_copy_single(source, dest);
1256101099Srwatson}
1257101099Srwatson
1258101099Srwatsonstatic void
1259101099Srwatsonmac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1260101099Srwatson    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1261101099Srwatson    struct mbuf *newmbuf, struct label *newmbuflabel)
1262101099Srwatson{
1263101099Srwatson	struct mac_biba *source, *dest;
1264101099Srwatson
1265101099Srwatson	source = SLOT(oldmbuflabel);
1266101099Srwatson	dest = SLOT(newmbuflabel);
1267101099Srwatson
1268101099Srwatson	mac_biba_copy_single(source, dest);
1269101099Srwatson}
1270101099Srwatson
1271101099Srwatsonstatic void
1272101099Srwatsonmac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1273101099Srwatson    struct mbuf *newmbuf, struct label *newmbuflabel)
1274101099Srwatson{
1275101099Srwatson	struct mac_biba *source, *dest;
1276101099Srwatson
1277101099Srwatson	source = SLOT(oldmbuflabel);
1278101099Srwatson	dest = SLOT(newmbuflabel);
1279101099Srwatson
1280101099Srwatson	mac_biba_copy_single(source, dest);
1281101099Srwatson}
1282101099Srwatson
1283101099Srwatsonstatic int
1284101099Srwatsonmac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1285101099Srwatson    struct ipq *ipq, struct label *ipqlabel)
1286101099Srwatson{
1287101099Srwatson	struct mac_biba *a, *b;
1288101099Srwatson
1289101099Srwatson	a = SLOT(ipqlabel);
1290101099Srwatson	b = SLOT(fragmentlabel);
1291101099Srwatson
1292101099Srwatson	return (mac_biba_equal_single(a, b));
1293101099Srwatson}
1294101099Srwatson
1295101099Srwatsonstatic void
1296101099Srwatsonmac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1297101099Srwatson    struct label *ifnetlabel, struct label *newlabel)
1298101099Srwatson{
1299101099Srwatson	struct mac_biba *source, *dest;
1300101099Srwatson
1301101099Srwatson	source = SLOT(newlabel);
1302101099Srwatson	dest = SLOT(ifnetlabel);
1303101099Srwatson
1304105656Srwatson	mac_biba_copy(source, dest);
1305101099Srwatson}
1306101099Srwatson
1307101099Srwatsonstatic void
1308101099Srwatsonmac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1309101099Srwatson    struct ipq *ipq, struct label *ipqlabel)
1310101099Srwatson{
1311101099Srwatson
1312101099Srwatson	/* NOOP: we only accept matching labels, so no need to update */
1313101099Srwatson}
1314101099Srwatson
1315122875Srwatsonstatic void
1316122875Srwatsonmac_biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1317122875Srwatson    struct inpcb *inp, struct label *inplabel)
1318122875Srwatson{
1319122875Srwatson	struct mac_biba *source, *dest;
1320122875Srwatson
1321122875Srwatson	source = SLOT(solabel);
1322122875Srwatson	dest = SLOT(inplabel);
1323122875Srwatson
1324122875Srwatson	mac_biba_copy(source, dest);
1325122875Srwatson}
1326122875Srwatson
1327101099Srwatson/*
1328101099Srwatson * Labeling event operations: processes.
1329101099Srwatson */
1330101099Srwatsonstatic void
1331101099Srwatsonmac_biba_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1332101099Srwatson{
1333101099Srwatson	struct mac_biba *source, *dest;
1334101099Srwatson
1335122524Srwatson	source = SLOT(cred_parent->cr_label);
1336122524Srwatson	dest = SLOT(cred_child->cr_label);
1337101099Srwatson
1338101099Srwatson	mac_biba_copy_single(source, dest);
1339101099Srwatson	mac_biba_copy_range(source, dest);
1340101099Srwatson}
1341101099Srwatson
1342101099Srwatsonstatic void
1343101099Srwatsonmac_biba_create_proc0(struct ucred *cred)
1344101099Srwatson{
1345101099Srwatson	struct mac_biba *dest;
1346101099Srwatson
1347122524Srwatson	dest = SLOT(cred->cr_label);
1348101099Srwatson
1349105643Srwatson	mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1350105643Srwatson	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1351105643Srwatson	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1352101099Srwatson}
1353101099Srwatson
1354101099Srwatsonstatic void
1355101099Srwatsonmac_biba_create_proc1(struct ucred *cred)
1356101099Srwatson{
1357101099Srwatson	struct mac_biba *dest;
1358101099Srwatson
1359122524Srwatson	dest = SLOT(cred->cr_label);
1360101099Srwatson
1361105643Srwatson	mac_biba_set_single(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
1362105643Srwatson	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1363105643Srwatson	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1364101099Srwatson}
1365101099Srwatson
1366101099Srwatsonstatic void
1367101099Srwatsonmac_biba_relabel_cred(struct ucred *cred, struct label *newlabel)
1368101099Srwatson{
1369101099Srwatson	struct mac_biba *source, *dest;
1370101099Srwatson
1371101099Srwatson	source = SLOT(newlabel);
1372122524Srwatson	dest = SLOT(cred->cr_label);
1373101099Srwatson
1374105656Srwatson	mac_biba_copy(source, dest);
1375101099Srwatson}
1376101099Srwatson
1377101099Srwatson/*
1378101099Srwatson * Access control checks.
1379101099Srwatson */
1380101099Srwatsonstatic int
1381101099Srwatsonmac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1382101099Srwatson    struct ifnet *ifnet, struct label *ifnetlabel)
1383101099Srwatson{
1384101099Srwatson	struct mac_biba *a, *b;
1385101099Srwatson
1386101099Srwatson	if (!mac_biba_enabled)
1387101099Srwatson		return (0);
1388101099Srwatson
1389101099Srwatson	a = SLOT(bpflabel);
1390101099Srwatson	b = SLOT(ifnetlabel);
1391101099Srwatson
1392101099Srwatson	if (mac_biba_equal_single(a, b))
1393101099Srwatson		return (0);
1394101099Srwatson	return (EACCES);
1395101099Srwatson}
1396101099Srwatson
1397101099Srwatsonstatic int
1398101099Srwatsonmac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1399101099Srwatson{
1400101099Srwatson	struct mac_biba *subj, *new;
1401105634Srwatson	int error;
1402101099Srwatson
1403122524Srwatson	subj = SLOT(cred->cr_label);
1404101099Srwatson	new = SLOT(newlabel);
1405101099Srwatson
1406101099Srwatson	/*
1407105634Srwatson	 * If there is a Biba label update for the credential, it may
1408105634Srwatson	 * be an update of the single, range, or both.
1409101099Srwatson	 */
1410105634Srwatson	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1411105634Srwatson	if (error)
1412105634Srwatson		return (error);
1413101099Srwatson
1414101099Srwatson	/*
1415105634Srwatson	 * If the Biba label is to be changed, authorize as appropriate.
1416101099Srwatson	 */
1417105634Srwatson	if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1418105634Srwatson		/*
1419110351Srwatson		 * If the change request modifies both the Biba label
1420110351Srwatson		 * single and range, check that the new single will be
1421110351Srwatson		 * in the new range.
1422110351Srwatson		 */
1423110351Srwatson		if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
1424110351Srwatson		    MAC_BIBA_FLAGS_BOTH &&
1425110351Srwatson		    !mac_biba_single_in_range(new, new))
1426110351Srwatson			return (EINVAL);
1427110351Srwatson
1428110351Srwatson		/*
1429105634Srwatson		 * To change the Biba single label on a credential, the
1430105634Srwatson		 * new single label must be in the current range.
1431105634Srwatson		 */
1432105634Srwatson		if (new->mb_flags & MAC_BIBA_FLAG_SINGLE &&
1433105634Srwatson		    !mac_biba_single_in_range(new, subj))
1434105634Srwatson			return (EPERM);
1435101099Srwatson
1436105634Srwatson		/*
1437105634Srwatson		 * To change the Biba range on a credential, the new
1438105634Srwatson		 * range label must be in the current range.
1439105634Srwatson		 */
1440105634Srwatson		if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
1441105634Srwatson		    !mac_biba_range_in_range(new, subj))
1442105634Srwatson			return (EPERM);
1443101099Srwatson
1444105634Srwatson		/*
1445105634Srwatson		 * To have EQUAL in any component of the new credential
1446105634Srwatson		 * Biba label, the subject must already have EQUAL in
1447105634Srwatson		 * their label.
1448105634Srwatson		 */
1449105634Srwatson		if (mac_biba_contains_equal(new)) {
1450106090Srwatson			error = mac_biba_subject_privileged(subj);
1451105634Srwatson			if (error)
1452105634Srwatson				return (error);
1453105634Srwatson		}
1454105634Srwatson	}
1455105634Srwatson
1456101099Srwatson	return (0);
1457101099Srwatson}
1458101099Srwatson
1459101099Srwatsonstatic int
1460101099Srwatsonmac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2)
1461101099Srwatson{
1462101099Srwatson	struct mac_biba *subj, *obj;
1463101099Srwatson
1464101099Srwatson	if (!mac_biba_enabled)
1465101099Srwatson		return (0);
1466101099Srwatson
1467122524Srwatson	subj = SLOT(u1->cr_label);
1468122524Srwatson	obj = SLOT(u2->cr_label);
1469101099Srwatson
1470101099Srwatson	/* XXX: range */
1471101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1472101099Srwatson		return (ESRCH);
1473101099Srwatson
1474101099Srwatson	return (0);
1475101099Srwatson}
1476101099Srwatson
1477101099Srwatsonstatic int
1478101099Srwatsonmac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1479101099Srwatson    struct label *ifnetlabel, struct label *newlabel)
1480101099Srwatson{
1481101099Srwatson	struct mac_biba *subj, *new;
1482105634Srwatson	int error;
1483101099Srwatson
1484122524Srwatson	subj = SLOT(cred->cr_label);
1485101099Srwatson	new = SLOT(newlabel);
1486101099Srwatson
1487105634Srwatson	/*
1488105634Srwatson	 * If there is a Biba label update for the interface, it may
1489105634Srwatson	 * be an update of the single, range, or both.
1490105634Srwatson	 */
1491105634Srwatson	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1492105634Srwatson	if (error)
1493105634Srwatson		return (error);
1494101099Srwatson
1495105634Srwatson	/*
1496106160Srwatson	 * Relabling network interfaces requires Biba privilege.
1497106160Srwatson	 */
1498106160Srwatson	error = mac_biba_subject_privileged(subj);
1499106160Srwatson	if (error)
1500106160Srwatson		return (error);
1501106160Srwatson
1502105634Srwatson	return (0);
1503101099Srwatson}
1504101099Srwatson
1505103759Srwatsonstatic int
1506101099Srwatsonmac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1507101099Srwatson    struct mbuf *m, struct label *mbuflabel)
1508101099Srwatson{
1509101099Srwatson	struct mac_biba *p, *i;
1510103761Srwatson
1511101099Srwatson	if (!mac_biba_enabled)
1512101099Srwatson		return (0);
1513101099Srwatson
1514101099Srwatson	p = SLOT(mbuflabel);
1515101099Srwatson	i = SLOT(ifnetlabel);
1516103759Srwatson
1517101099Srwatson	return (mac_biba_single_in_range(p, i) ? 0 : EACCES);
1518101099Srwatson}
1519101099Srwatson
1520101099Srwatsonstatic int
1521122875Srwatsonmac_biba_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1522122875Srwatson    struct mbuf *m, struct label *mlabel)
1523122875Srwatson{
1524122875Srwatson	struct mac_biba *p, *i;
1525122875Srwatson
1526122875Srwatson	if (!mac_biba_enabled)
1527122875Srwatson		return (0);
1528122875Srwatson
1529122875Srwatson	p = SLOT(mlabel);
1530122875Srwatson	i = SLOT(inplabel);
1531122875Srwatson
1532122875Srwatson	return (mac_biba_equal_single(p, i) ? 0 : EACCES);
1533122875Srwatson}
1534122875Srwatson
1535122875Srwatsonstatic int
1536110354Srwatsonmac_biba_check_kld_load(struct ucred *cred, struct vnode *vp,
1537110354Srwatson    struct label *label)
1538110354Srwatson{
1539110354Srwatson	struct mac_biba *subj, *obj;
1540110354Srwatson	int error;
1541110354Srwatson
1542110354Srwatson	if (!mac_biba_enabled)
1543110354Srwatson		return (0);
1544110354Srwatson
1545122524Srwatson	subj = SLOT(cred->cr_label);
1546110354Srwatson
1547110354Srwatson	error = mac_biba_subject_privileged(subj);
1548110354Srwatson	if (error)
1549110354Srwatson		return (error);
1550110354Srwatson
1551110354Srwatson	obj = SLOT(label);
1552110354Srwatson	if (!mac_biba_high_single(obj))
1553110354Srwatson		return (EACCES);
1554110354Srwatson
1555110354Srwatson	return (0);
1556110354Srwatson}
1557110354Srwatson
1558110354Srwatson
1559110354Srwatsonstatic int
1560110354Srwatsonmac_biba_check_kld_unload(struct ucred *cred)
1561110354Srwatson{
1562110354Srwatson	struct mac_biba *subj;
1563110354Srwatson
1564110354Srwatson	if (!mac_biba_enabled)
1565110354Srwatson		return (0);
1566110354Srwatson
1567122524Srwatson	subj = SLOT(cred->cr_label);
1568110354Srwatson
1569110354Srwatson	return (mac_biba_subject_privileged(subj));
1570110354Srwatson}
1571110354Srwatson
1572110354Srwatsonstatic int
1573101099Srwatsonmac_biba_check_mount_stat(struct ucred *cred, struct mount *mp,
1574101099Srwatson    struct label *mntlabel)
1575101099Srwatson{
1576101099Srwatson	struct mac_biba *subj, *obj;
1577101099Srwatson
1578101099Srwatson	if (!mac_biba_enabled)
1579101099Srwatson		return (0);
1580101099Srwatson
1581122524Srwatson	subj = SLOT(cred->cr_label);
1582101099Srwatson	obj = SLOT(mntlabel);
1583101099Srwatson
1584101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1585101099Srwatson		return (EACCES);
1586101099Srwatson
1587101099Srwatson	return (0);
1588101099Srwatson}
1589101099Srwatson
1590101099Srwatsonstatic int
1591101099Srwatsonmac_biba_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1592101099Srwatson    struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1593101099Srwatson{
1594103759Srwatson
1595101099Srwatson	if(!mac_biba_enabled)
1596101099Srwatson		return (0);
1597101099Srwatson
1598101099Srwatson	/* XXX: This will be implemented soon... */
1599101099Srwatson
1600101099Srwatson	return (0);
1601101099Srwatson}
1602101099Srwatson
1603101099Srwatsonstatic int
1604102115Srwatsonmac_biba_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1605102115Srwatson    struct label *pipelabel)
1606101099Srwatson{
1607101099Srwatson	struct mac_biba *subj, *obj;
1608101099Srwatson
1609101099Srwatson	if (!mac_biba_enabled)
1610101099Srwatson		return (0);
1611101099Srwatson
1612122524Srwatson	subj = SLOT(cred->cr_label);
1613101099Srwatson	obj = SLOT((pipelabel));
1614101099Srwatson
1615102115Srwatson	if (!mac_biba_dominate_single(obj, subj))
1616102115Srwatson		return (EACCES);
1617101099Srwatson
1618101099Srwatson	return (0);
1619101099Srwatson}
1620101099Srwatson
1621101099Srwatsonstatic int
1622102115Srwatsonmac_biba_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1623102115Srwatson    struct label *pipelabel)
1624102115Srwatson{
1625102115Srwatson	struct mac_biba *subj, *obj;
1626102115Srwatson
1627102115Srwatson	if (!mac_biba_enabled)
1628102115Srwatson		return (0);
1629102115Srwatson
1630122524Srwatson	subj = SLOT(cred->cr_label);
1631102115Srwatson	obj = SLOT((pipelabel));
1632102115Srwatson
1633102115Srwatson	if (!mac_biba_dominate_single(obj, subj))
1634102115Srwatson		return (EACCES);
1635102115Srwatson
1636102115Srwatson	return (0);
1637102115Srwatson}
1638102115Srwatson
1639102115Srwatsonstatic int
1640101099Srwatsonmac_biba_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1641101099Srwatson    struct label *pipelabel, struct label *newlabel)
1642101099Srwatson{
1643101099Srwatson	struct mac_biba *subj, *obj, *new;
1644105634Srwatson	int error;
1645101099Srwatson
1646101099Srwatson	new = SLOT(newlabel);
1647122524Srwatson	subj = SLOT(cred->cr_label);
1648101099Srwatson	obj = SLOT(pipelabel);
1649101099Srwatson
1650101099Srwatson	/*
1651105634Srwatson	 * If there is a Biba label update for a pipe, it must be a
1652105634Srwatson	 * single update.
1653101099Srwatson	 */
1654105634Srwatson	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
1655105634Srwatson	if (error)
1656105634Srwatson		return (error);
1657101099Srwatson
1658101099Srwatson	/*
1659105634Srwatson	 * To perform a relabel of a pipe (Biba label or not), Biba must
1660105634Srwatson	 * authorize the relabel.
1661101099Srwatson	 */
1662105634Srwatson	if (!mac_biba_single_in_range(obj, subj))
1663101099Srwatson		return (EPERM);
1664101099Srwatson
1665101099Srwatson	/*
1666105634Srwatson	 * If the Biba label is to be changed, authorize as appropriate.
1667101099Srwatson	 */
1668105634Srwatson	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
1669105634Srwatson		/*
1670105634Srwatson		 * To change the Biba label on a pipe, the new pipe label
1671105634Srwatson		 * must be in the subject range.
1672105634Srwatson		 */
1673105634Srwatson		if (!mac_biba_single_in_range(new, subj))
1674105634Srwatson			return (EPERM);
1675101099Srwatson
1676105634Srwatson		/*
1677105634Srwatson		 * To change the Biba label on a pipe to be EQUAL, the
1678105634Srwatson		 * subject must have appropriate privilege.
1679105634Srwatson		 */
1680105634Srwatson		if (mac_biba_contains_equal(new)) {
1681106090Srwatson			error = mac_biba_subject_privileged(subj);
1682105634Srwatson			if (error)
1683105634Srwatson				return (error);
1684105634Srwatson		}
1685105634Srwatson	}
1686105634Srwatson
1687101099Srwatson	return (0);
1688101099Srwatson}
1689101099Srwatson
1690101099Srwatsonstatic int
1691102115Srwatsonmac_biba_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1692102115Srwatson    struct label *pipelabel)
1693102115Srwatson{
1694102115Srwatson	struct mac_biba *subj, *obj;
1695102115Srwatson
1696102115Srwatson	if (!mac_biba_enabled)
1697102115Srwatson		return (0);
1698102115Srwatson
1699122524Srwatson	subj = SLOT(cred->cr_label);
1700102115Srwatson	obj = SLOT((pipelabel));
1701102115Srwatson
1702102115Srwatson	if (!mac_biba_dominate_single(obj, subj))
1703102115Srwatson		return (EACCES);
1704102115Srwatson
1705102115Srwatson	return (0);
1706102115Srwatson}
1707102115Srwatson
1708102115Srwatsonstatic int
1709102115Srwatsonmac_biba_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1710102115Srwatson    struct label *pipelabel)
1711102115Srwatson{
1712102115Srwatson	struct mac_biba *subj, *obj;
1713102115Srwatson
1714102115Srwatson	if (!mac_biba_enabled)
1715102115Srwatson		return (0);
1716102115Srwatson
1717122524Srwatson	subj = SLOT(cred->cr_label);
1718102115Srwatson	obj = SLOT((pipelabel));
1719102115Srwatson
1720102115Srwatson	if (!mac_biba_dominate_single(subj, obj))
1721102115Srwatson		return (EACCES);
1722102115Srwatson
1723102115Srwatson	return (0);
1724102115Srwatson}
1725102115Srwatson
1726102115Srwatsonstatic int
1727101099Srwatsonmac_biba_check_proc_debug(struct ucred *cred, struct proc *proc)
1728101099Srwatson{
1729101099Srwatson	struct mac_biba *subj, *obj;
1730101099Srwatson
1731101099Srwatson	if (!mac_biba_enabled)
1732101099Srwatson		return (0);
1733101099Srwatson
1734122524Srwatson	subj = SLOT(cred->cr_label);
1735122524Srwatson	obj = SLOT(proc->p_ucred->cr_label);
1736101099Srwatson
1737101099Srwatson	/* XXX: range checks */
1738101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1739101099Srwatson		return (ESRCH);
1740101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
1741101099Srwatson		return (EACCES);
1742101099Srwatson
1743101099Srwatson	return (0);
1744101099Srwatson}
1745101099Srwatson
1746101099Srwatsonstatic int
1747101099Srwatsonmac_biba_check_proc_sched(struct ucred *cred, struct proc *proc)
1748101099Srwatson{
1749101099Srwatson	struct mac_biba *subj, *obj;
1750103759Srwatson
1751101099Srwatson	if (!mac_biba_enabled)
1752101099Srwatson		return (0);
1753101099Srwatson
1754122524Srwatson	subj = SLOT(cred->cr_label);
1755122524Srwatson	obj = SLOT(proc->p_ucred->cr_label);
1756103759Srwatson
1757101099Srwatson	/* XXX: range checks */
1758101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1759101099Srwatson		return (ESRCH);
1760101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
1761101099Srwatson		return (EACCES);
1762101099Srwatson
1763101099Srwatson	return (0);
1764101099Srwatson}
1765101099Srwatson
1766101099Srwatsonstatic int
1767101099Srwatsonmac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1768101099Srwatson{
1769101099Srwatson	struct mac_biba *subj, *obj;
1770103759Srwatson
1771101099Srwatson	if (!mac_biba_enabled)
1772101099Srwatson		return (0);
1773101099Srwatson
1774122524Srwatson	subj = SLOT(cred->cr_label);
1775122524Srwatson	obj = SLOT(proc->p_ucred->cr_label);
1776103759Srwatson
1777101099Srwatson	/* XXX: range checks */
1778101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1779101099Srwatson		return (ESRCH);
1780101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
1781101099Srwatson		return (EACCES);
1782101099Srwatson
1783101099Srwatson	return (0);
1784101099Srwatson}
1785101099Srwatson
1786101099Srwatsonstatic int
1787101934Srwatsonmac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel,
1788101099Srwatson    struct mbuf *m, struct label *mbuflabel)
1789101099Srwatson{
1790101099Srwatson	struct mac_biba *p, *s;
1791101099Srwatson
1792101099Srwatson	if (!mac_biba_enabled)
1793101099Srwatson		return (0);
1794101099Srwatson
1795101099Srwatson	p = SLOT(mbuflabel);
1796101099Srwatson	s = SLOT(socketlabel);
1797101099Srwatson
1798101099Srwatson	return (mac_biba_equal_single(p, s) ? 0 : EACCES);
1799101099Srwatson}
1800101099Srwatson
1801101099Srwatsonstatic int
1802106214Srwatsonmac_biba_check_socket_relabel(struct ucred *cred, struct socket *so,
1803101099Srwatson    struct label *socketlabel, struct label *newlabel)
1804101099Srwatson{
1805101099Srwatson	struct mac_biba *subj, *obj, *new;
1806105634Srwatson	int error;
1807101099Srwatson
1808101099Srwatson	new = SLOT(newlabel);
1809122524Srwatson	subj = SLOT(cred->cr_label);
1810101099Srwatson	obj = SLOT(socketlabel);
1811101099Srwatson
1812101099Srwatson	/*
1813105634Srwatson	 * If there is a Biba label update for the socket, it may be
1814105634Srwatson	 * an update of single.
1815101099Srwatson	 */
1816105634Srwatson	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
1817105634Srwatson	if (error)
1818105634Srwatson		return (error);
1819101099Srwatson
1820101099Srwatson	/*
1821105634Srwatson	 * To relabel a socket, the old socket single must be in the subject
1822101099Srwatson	 * range.
1823101099Srwatson	 */
1824105634Srwatson	if (!mac_biba_single_in_range(obj, subj))
1825101099Srwatson		return (EPERM);
1826101099Srwatson
1827101099Srwatson	/*
1828105634Srwatson	 * If the Biba label is to be changed, authorize as appropriate.
1829101099Srwatson	 */
1830105634Srwatson	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
1831105634Srwatson		/*
1832105634Srwatson		 * To relabel a socket, the new socket single must be in
1833105634Srwatson		 * the subject range.
1834105634Srwatson		 */
1835105634Srwatson		if (!mac_biba_single_in_range(new, subj))
1836105634Srwatson			return (EPERM);
1837101099Srwatson
1838105634Srwatson		/*
1839105634Srwatson		 * To change the Biba label on the socket to contain EQUAL,
1840105634Srwatson		 * the subject must have appropriate privilege.
1841105634Srwatson		 */
1842105634Srwatson		if (mac_biba_contains_equal(new)) {
1843106090Srwatson			error = mac_biba_subject_privileged(subj);
1844105634Srwatson			if (error)
1845105634Srwatson				return (error);
1846105634Srwatson		}
1847105634Srwatson	}
1848105634Srwatson
1849101099Srwatson	return (0);
1850101099Srwatson}
1851101099Srwatson
1852101099Srwatsonstatic int
1853101099Srwatsonmac_biba_check_socket_visible(struct ucred *cred, struct socket *socket,
1854101099Srwatson    struct label *socketlabel)
1855101099Srwatson{
1856101099Srwatson	struct mac_biba *subj, *obj;
1857101099Srwatson
1858105722Srwatson	if (!mac_biba_enabled)
1859105722Srwatson		return (0);
1860105722Srwatson
1861122524Srwatson	subj = SLOT(cred->cr_label);
1862101099Srwatson	obj = SLOT(socketlabel);
1863101099Srwatson
1864101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
1865101099Srwatson		return (ENOENT);
1866101099Srwatson
1867101099Srwatson	return (0);
1868101099Srwatson}
1869101099Srwatson
1870101099Srwatsonstatic int
1871112574Srwatsonmac_biba_check_sysarch_ioperm(struct ucred *cred)
1872112574Srwatson{
1873112574Srwatson	struct mac_biba *subj;
1874112574Srwatson	int error;
1875112574Srwatson
1876112574Srwatson	if (!mac_biba_enabled)
1877112574Srwatson		return (0);
1878112574Srwatson
1879122524Srwatson	subj = SLOT(cred->cr_label);
1880112574Srwatson
1881112574Srwatson	error = mac_biba_subject_privileged(subj);
1882112574Srwatson	if (error)
1883112574Srwatson		return (error);
1884112574Srwatson
1885112574Srwatson	return (0);
1886112574Srwatson}
1887112574Srwatson
1888112574Srwatsonstatic int
1889106418Srwatsonmac_biba_check_system_acct(struct ucred *cred, struct vnode *vp,
1890106418Srwatson    struct label *label)
1891106418Srwatson{
1892106418Srwatson	struct mac_biba *subj, *obj;
1893106418Srwatson	int error;
1894106418Srwatson
1895106418Srwatson	if (!mac_biba_enabled)
1896106418Srwatson		return (0);
1897106418Srwatson
1898122524Srwatson	subj = SLOT(cred->cr_label);
1899106418Srwatson
1900106418Srwatson	error = mac_biba_subject_privileged(subj);
1901106418Srwatson	if (error)
1902106418Srwatson		return (error);
1903106418Srwatson
1904106418Srwatson	if (label == NULL)
1905106418Srwatson		return (0);
1906106418Srwatson
1907106418Srwatson	obj = SLOT(label);
1908106418Srwatson	if (!mac_biba_high_single(obj))
1909106418Srwatson		return (EACCES);
1910106418Srwatson
1911106418Srwatson	return (0);
1912106418Srwatson}
1913106418Srwatson
1914106418Srwatsonstatic int
1915106418Srwatsonmac_biba_check_system_settime(struct ucred *cred)
1916106418Srwatson{
1917106418Srwatson	struct mac_biba *subj;
1918106418Srwatson	int error;
1919106418Srwatson
1920106418Srwatson	if (!mac_biba_enabled)
1921106418Srwatson		return (0);
1922106418Srwatson
1923122524Srwatson	subj = SLOT(cred->cr_label);
1924106418Srwatson
1925106418Srwatson	error = mac_biba_subject_privileged(subj);
1926106418Srwatson	if (error)
1927106418Srwatson		return (error);
1928106418Srwatson
1929106418Srwatson	return (0);
1930106418Srwatson}
1931106418Srwatson
1932106418Srwatsonstatic int
1933106161Srwatsonmac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp,
1934106161Srwatson    struct label *label)
1935106161Srwatson{
1936106161Srwatson	struct mac_biba *subj, *obj;
1937106416Srwatson	int error;
1938106161Srwatson
1939106161Srwatson	if (!mac_biba_enabled)
1940106161Srwatson		return (0);
1941106161Srwatson
1942122524Srwatson	subj = SLOT(cred->cr_label);
1943106161Srwatson	obj = SLOT(label);
1944106161Srwatson
1945106416Srwatson	error = mac_biba_subject_privileged(subj);
1946106416Srwatson	if (error)
1947106416Srwatson		return (error);
1948106161Srwatson
1949106161Srwatson	if (!mac_biba_high_single(obj))
1950106161Srwatson		return (EACCES);
1951106161Srwatson
1952106161Srwatson	return (0);
1953106161Srwatson}
1954106161Srwatson
1955106161Srwatsonstatic int
1956112574Srwatsonmac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp,
1957112574Srwatson    struct label *label)
1958112574Srwatson{
1959112574Srwatson	struct mac_biba *subj, *obj;
1960112574Srwatson	int error;
1961112574Srwatson
1962112574Srwatson	if (!mac_biba_enabled)
1963112574Srwatson		return (0);
1964112574Srwatson
1965122524Srwatson	subj = SLOT(cred->cr_label);
1966112574Srwatson	obj = SLOT(label);
1967112574Srwatson
1968112574Srwatson	error = mac_biba_subject_privileged(subj);
1969112574Srwatson	if (error)
1970112574Srwatson		return (error);
1971112574Srwatson
1972112574Srwatson	return (0);
1973112574Srwatson}
1974112574Srwatson
1975112574Srwatsonstatic int
1976106161Srwatsonmac_biba_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
1977106161Srwatson    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
1978106161Srwatson{
1979106161Srwatson	struct mac_biba *subj;
1980106161Srwatson	int error;
1981106161Srwatson
1982106161Srwatson	if (!mac_biba_enabled)
1983106161Srwatson		return (0);
1984106161Srwatson
1985122524Srwatson	subj = SLOT(cred->cr_label);
1986106161Srwatson
1987106161Srwatson	/*
1988106161Srwatson	 * In general, treat sysctl variables as biba/high, but also
1989106161Srwatson	 * require privilege to change them, since they are a
1990106161Srwatson	 * communications channel between grades.  Exempt MIB
1991106161Srwatson	 * queries from this due to undocmented sysctl magic.
1992106161Srwatson	 * XXXMAC: This probably requires some more review.
1993106161Srwatson	 */
1994106161Srwatson	if (new != NULL) {
1995106161Srwatson		if (namelen > 0 && name[0] == 0)
1996106161Srwatson			return (0);
1997106161Srwatson
1998106161Srwatson		if (!mac_biba_subject_dominate_high(subj))
1999106161Srwatson			return (EACCES);
2000106161Srwatson
2001106161Srwatson		error = mac_biba_subject_privileged(subj);
2002106161Srwatson		if (error)
2003106161Srwatson			return (error);
2004106161Srwatson	}
2005106161Srwatson
2006106161Srwatson	return (0);
2007106161Srwatson}
2008106161Srwatson
2009106161Srwatsonstatic int
2010101099Srwatsonmac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2011101099Srwatson    struct label *dlabel)
2012101099Srwatson{
2013101099Srwatson	struct mac_biba *subj, *obj;
2014101099Srwatson
2015101099Srwatson	if (!mac_biba_enabled)
2016101099Srwatson		return (0);
2017101099Srwatson
2018122524Srwatson	subj = SLOT(cred->cr_label);
2019101099Srwatson	obj = SLOT(dlabel);
2020101099Srwatson
2021101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2022101099Srwatson		return (EACCES);
2023101099Srwatson
2024101099Srwatson	return (0);
2025101099Srwatson}
2026101099Srwatson
2027101099Srwatsonstatic int
2028101099Srwatsonmac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2029101099Srwatson    struct label *dlabel)
2030101099Srwatson{
2031101099Srwatson	struct mac_biba *subj, *obj;
2032101099Srwatson
2033101099Srwatson	if (!mac_biba_enabled)
2034101099Srwatson		return (0);
2035101099Srwatson
2036122524Srwatson	subj = SLOT(cred->cr_label);
2037101099Srwatson	obj = SLOT(dlabel);
2038101099Srwatson
2039101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2040101099Srwatson		return (EACCES);
2041101099Srwatson
2042101099Srwatson	return (0);
2043101099Srwatson}
2044101099Srwatson
2045101099Srwatsonstatic int
2046101099Srwatsonmac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2047101099Srwatson    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2048101099Srwatson{
2049101099Srwatson	struct mac_biba *subj, *obj;
2050101099Srwatson
2051101099Srwatson	if (!mac_biba_enabled)
2052101099Srwatson		return (0);
2053101099Srwatson
2054122524Srwatson	subj = SLOT(cred->cr_label);
2055101099Srwatson	obj = SLOT(dlabel);
2056101099Srwatson
2057101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2058101099Srwatson		return (EACCES);
2059101099Srwatson
2060101099Srwatson	return (0);
2061101099Srwatson}
2062101099Srwatson
2063101099Srwatsonstatic int
2064101099Srwatsonmac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2065101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
2066101099Srwatson    struct componentname *cnp)
2067101099Srwatson{
2068101099Srwatson	struct mac_biba *subj, *obj;
2069101099Srwatson
2070101099Srwatson	if (!mac_biba_enabled)
2071101099Srwatson		return (0);
2072101099Srwatson
2073122524Srwatson	subj = SLOT(cred->cr_label);
2074101099Srwatson	obj = SLOT(dlabel);
2075101099Srwatson
2076101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2077101099Srwatson		return (EACCES);
2078101099Srwatson
2079101099Srwatson	obj = SLOT(label);
2080101099Srwatson
2081101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2082101099Srwatson		return (EACCES);
2083101099Srwatson
2084101099Srwatson	return (0);
2085101099Srwatson}
2086101099Srwatson
2087101099Srwatsonstatic int
2088101099Srwatsonmac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2089101099Srwatson    struct label *label, acl_type_t type)
2090101099Srwatson{
2091101099Srwatson	struct mac_biba *subj, *obj;
2092101099Srwatson
2093101099Srwatson	if (!mac_biba_enabled)
2094101099Srwatson		return (0);
2095101099Srwatson
2096122524Srwatson	subj = SLOT(cred->cr_label);
2097101099Srwatson	obj = SLOT(label);
2098101099Srwatson
2099101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2100101099Srwatson		return (EACCES);
2101101099Srwatson
2102101099Srwatson	return (0);
2103101099Srwatson}
2104101099Srwatson
2105101099Srwatsonstatic int
2106119202Srwatsonmac_biba_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2107119202Srwatson    struct label *label, int attrnamespace, const char *name)
2108119202Srwatson{
2109119202Srwatson	struct mac_biba *subj, *obj;
2110119202Srwatson
2111119202Srwatson	if (!mac_biba_enabled)
2112119202Srwatson		return (0);
2113119202Srwatson
2114122524Srwatson	subj = SLOT(cred->cr_label);
2115119202Srwatson	obj = SLOT(label);
2116119202Srwatson
2117119202Srwatson	if (!mac_biba_dominate_single(subj, obj))
2118119202Srwatson		return (EACCES);
2119119202Srwatson
2120119202Srwatson	return (0);
2121119202Srwatson}
2122119202Srwatson
2123119202Srwatsonstatic int
2124101099Srwatsonmac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2125106648Srwatson    struct label *label, struct image_params *imgp,
2126106648Srwatson    struct label *execlabel)
2127101099Srwatson{
2128106648Srwatson	struct mac_biba *subj, *obj, *exec;
2129106648Srwatson	int error;
2130101099Srwatson
2131106648Srwatson	if (execlabel != NULL) {
2132106648Srwatson		/*
2133106648Srwatson		 * We currently don't permit labels to be changed at
2134106648Srwatson		 * exec-time as part of Biba, so disallow non-NULL
2135106648Srwatson		 * Biba label elements in the execlabel.
2136106648Srwatson		 */
2137106648Srwatson		exec = SLOT(execlabel);
2138106648Srwatson		error = biba_atmostflags(exec, 0);
2139106648Srwatson		if (error)
2140106648Srwatson			return (error);
2141106648Srwatson	}
2142106648Srwatson
2143101099Srwatson	if (!mac_biba_enabled)
2144101099Srwatson		return (0);
2145101099Srwatson
2146122524Srwatson	subj = SLOT(cred->cr_label);
2147101099Srwatson	obj = SLOT(label);
2148101099Srwatson
2149101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2150101099Srwatson		return (EACCES);
2151101099Srwatson
2152101099Srwatson	return (0);
2153101099Srwatson}
2154101099Srwatson
2155101099Srwatsonstatic int
2156101099Srwatsonmac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2157101099Srwatson    struct label *label, acl_type_t type)
2158101099Srwatson{
2159101099Srwatson	struct mac_biba *subj, *obj;
2160101099Srwatson
2161101099Srwatson	if (!mac_biba_enabled)
2162101099Srwatson		return (0);
2163101099Srwatson
2164122524Srwatson	subj = SLOT(cred->cr_label);
2165101099Srwatson	obj = SLOT(label);
2166101099Srwatson
2167101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2168101099Srwatson		return (EACCES);
2169101099Srwatson
2170101099Srwatson	return (0);
2171101099Srwatson}
2172101099Srwatson
2173101099Srwatsonstatic int
2174101099Srwatsonmac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2175101099Srwatson    struct label *label, int attrnamespace, const char *name, struct uio *uio)
2176101099Srwatson{
2177101099Srwatson	struct mac_biba *subj, *obj;
2178101099Srwatson
2179101099Srwatson	if (!mac_biba_enabled)
2180101099Srwatson		return (0);
2181101099Srwatson
2182122524Srwatson	subj = SLOT(cred->cr_label);
2183101099Srwatson	obj = SLOT(label);
2184101099Srwatson
2185101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2186101099Srwatson		return (EACCES);
2187101099Srwatson
2188101099Srwatson	return (0);
2189101099Srwatson}
2190101099Srwatson
2191101099Srwatsonstatic int
2192104530Srwatsonmac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2193104530Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
2194104530Srwatson    struct componentname *cnp)
2195104530Srwatson{
2196104530Srwatson	struct mac_biba *subj, *obj;
2197104530Srwatson
2198104530Srwatson	if (!mac_biba_enabled)
2199104530Srwatson		return (0);
2200104530Srwatson
2201122524Srwatson	subj = SLOT(cred->cr_label);
2202104530Srwatson	obj = SLOT(dlabel);
2203104530Srwatson
2204104530Srwatson	if (!mac_biba_dominate_single(subj, obj))
2205104530Srwatson		return (EACCES);
2206104530Srwatson
2207104530Srwatson	obj = SLOT(label);
2208104530Srwatson
2209104530Srwatson	if (!mac_biba_dominate_single(subj, obj))
2210104530Srwatson		return (EACCES);
2211104530Srwatson
2212104530Srwatson	return (0);
2213104530Srwatson}
2214104530Srwatson
2215104530Srwatsonstatic int
2216119202Srwatsonmac_biba_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2217119202Srwatson    struct label *label, int attrnamespace)
2218119202Srwatson{
2219119202Srwatson	struct mac_biba *subj, *obj;
2220119202Srwatson
2221119202Srwatson	if (!mac_biba_enabled)
2222119202Srwatson		return (0);
2223119202Srwatson
2224122524Srwatson	subj = SLOT(cred->cr_label);
2225119202Srwatson	obj = SLOT(label);
2226119202Srwatson
2227119202Srwatson	if (!mac_biba_dominate_single(obj, subj))
2228119202Srwatson		return (EACCES);
2229119202Srwatson
2230119202Srwatson	return (0);
2231119202Srwatson}
2232119202Srwatson
2233119202Srwatsonstatic int
2234103759Srwatsonmac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2235101099Srwatson    struct label *dlabel, struct componentname *cnp)
2236101099Srwatson{
2237101099Srwatson	struct mac_biba *subj, *obj;
2238103759Srwatson
2239101099Srwatson	if (!mac_biba_enabled)
2240101099Srwatson		return (0);
2241103759Srwatson
2242122524Srwatson	subj = SLOT(cred->cr_label);
2243101099Srwatson	obj = SLOT(dlabel);
2244103759Srwatson
2245101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2246101099Srwatson		return (EACCES);
2247101099Srwatson
2248103759Srwatson	return (0);
2249101099Srwatson}
2250101099Srwatson
2251101099Srwatsonstatic int
2252104546Srwatsonmac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2253104546Srwatson    struct label *label, int prot)
2254104546Srwatson{
2255104546Srwatson	struct mac_biba *subj, *obj;
2256104546Srwatson
2257104546Srwatson	/*
2258104546Srwatson	 * Rely on the use of open()-time protections to handle
2259104546Srwatson	 * non-revocation cases.
2260104546Srwatson	 */
2261105637Srwatson	if (!mac_biba_enabled || !revocation_enabled)
2262104546Srwatson		return (0);
2263104546Srwatson
2264122524Srwatson	subj = SLOT(cred->cr_label);
2265104546Srwatson	obj = SLOT(label);
2266104546Srwatson
2267104546Srwatson	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2268104546Srwatson		if (!mac_biba_dominate_single(obj, subj))
2269104546Srwatson			return (EACCES);
2270104546Srwatson	}
2271104546Srwatson	if (prot & VM_PROT_WRITE) {
2272104546Srwatson		if (!mac_biba_dominate_single(subj, obj))
2273104546Srwatson			return (EACCES);
2274104546Srwatson	}
2275104546Srwatson
2276104569Srwatson	return (0);
2277104546Srwatson}
2278104546Srwatson
2279104546Srwatsonstatic int
2280101099Srwatsonmac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp,
2281106212Srwatson    struct label *vnodelabel, int acc_mode)
2282101099Srwatson{
2283101099Srwatson	struct mac_biba *subj, *obj;
2284101099Srwatson
2285101099Srwatson	if (!mac_biba_enabled)
2286101099Srwatson		return (0);
2287101099Srwatson
2288122524Srwatson	subj = SLOT(cred->cr_label);
2289101099Srwatson	obj = SLOT(vnodelabel);
2290101099Srwatson
2291101099Srwatson	/* XXX privilege override for admin? */
2292101099Srwatson	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2293101099Srwatson		if (!mac_biba_dominate_single(obj, subj))
2294101099Srwatson			return (EACCES);
2295101099Srwatson	}
2296101099Srwatson	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2297101099Srwatson		if (!mac_biba_dominate_single(subj, obj))
2298101099Srwatson			return (EACCES);
2299101099Srwatson	}
2300101099Srwatson
2301101099Srwatson	return (0);
2302101099Srwatson}
2303101099Srwatson
2304101099Srwatsonstatic int
2305102129Srwatsonmac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2306102129Srwatson    struct vnode *vp, struct label *label)
2307102112Srwatson{
2308102112Srwatson	struct mac_biba *subj, *obj;
2309102112Srwatson
2310105637Srwatson	if (!mac_biba_enabled || !revocation_enabled)
2311102112Srwatson		return (0);
2312102112Srwatson
2313122524Srwatson	subj = SLOT(active_cred->cr_label);
2314102112Srwatson	obj = SLOT(label);
2315102112Srwatson
2316102112Srwatson	if (!mac_biba_dominate_single(obj, subj))
2317102112Srwatson		return (EACCES);
2318102112Srwatson
2319102112Srwatson	return (0);
2320102112Srwatson}
2321102112Srwatson
2322102112Srwatsonstatic int
2323102129Srwatsonmac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2324102129Srwatson    struct vnode *vp, struct label *label)
2325102112Srwatson{
2326102112Srwatson	struct mac_biba *subj, *obj;
2327102112Srwatson
2328105637Srwatson	if (!mac_biba_enabled || !revocation_enabled)
2329102112Srwatson		return (0);
2330102112Srwatson
2331122524Srwatson	subj = SLOT(active_cred->cr_label);
2332102112Srwatson	obj = SLOT(label);
2333102112Srwatson
2334102112Srwatson	if (!mac_biba_dominate_single(obj, subj))
2335102112Srwatson		return (EACCES);
2336102112Srwatson
2337102112Srwatson	return (0);
2338102112Srwatson}
2339102112Srwatson
2340102112Srwatsonstatic int
2341101099Srwatsonmac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2342101099Srwatson    struct label *dlabel)
2343101099Srwatson{
2344101099Srwatson	struct mac_biba *subj, *obj;
2345101099Srwatson
2346101099Srwatson	if (!mac_biba_enabled)
2347101099Srwatson		return (0);
2348101099Srwatson
2349122524Srwatson	subj = SLOT(cred->cr_label);
2350101099Srwatson	obj = SLOT(dlabel);
2351101099Srwatson
2352101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2353101099Srwatson		return (EACCES);
2354101099Srwatson
2355101099Srwatson	return (0);
2356101099Srwatson}
2357101099Srwatson
2358101099Srwatsonstatic int
2359101099Srwatsonmac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2360101099Srwatson    struct label *label)
2361101099Srwatson{
2362101099Srwatson	struct mac_biba *subj, *obj;
2363101099Srwatson
2364101099Srwatson	if (!mac_biba_enabled)
2365101099Srwatson		return (0);
2366101099Srwatson
2367122524Srwatson	subj = SLOT(cred->cr_label);
2368101099Srwatson	obj = SLOT(label);
2369101099Srwatson
2370101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2371101099Srwatson		return (EACCES);
2372101099Srwatson
2373101099Srwatson	return (0);
2374101099Srwatson}
2375101099Srwatson
2376101099Srwatsonstatic int
2377101099Srwatsonmac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2378101099Srwatson    struct label *vnodelabel, struct label *newlabel)
2379101099Srwatson{
2380101099Srwatson	struct mac_biba *old, *new, *subj;
2381105634Srwatson	int error;
2382101099Srwatson
2383101099Srwatson	old = SLOT(vnodelabel);
2384101099Srwatson	new = SLOT(newlabel);
2385122524Srwatson	subj = SLOT(cred->cr_label);
2386101099Srwatson
2387101099Srwatson	/*
2388105634Srwatson	 * If there is a Biba label update for the vnode, it must be a
2389105634Srwatson	 * single label.
2390101099Srwatson	 */
2391105634Srwatson	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
2392105634Srwatson	if (error)
2393105634Srwatson		return (error);
2394101099Srwatson
2395101099Srwatson	/*
2396105634Srwatson	 * To perform a relabel of the vnode (Biba label or not), Biba must
2397105634Srwatson	 * authorize the relabel.
2398101099Srwatson	 */
2399105634Srwatson	if (!mac_biba_single_in_range(old, subj))
2400101099Srwatson		return (EPERM);
2401101099Srwatson
2402101099Srwatson	/*
2403105634Srwatson	 * If the Biba label is to be changed, authorize as appropriate.
2404101099Srwatson	 */
2405105634Srwatson	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
2406105634Srwatson		/*
2407105634Srwatson		 * To change the Biba label on a vnode, the new vnode label
2408105634Srwatson		 * must be in the subject range.
2409105634Srwatson		 */
2410105634Srwatson		if (!mac_biba_single_in_range(new, subj))
2411105634Srwatson			return (EPERM);
2412101099Srwatson
2413105634Srwatson		/*
2414105634Srwatson		 * To change the Biba label on the vnode to be EQUAL,
2415105634Srwatson		 * the subject must have appropriate privilege.
2416105634Srwatson		 */
2417105634Srwatson		if (mac_biba_contains_equal(new)) {
2418106090Srwatson			error = mac_biba_subject_privileged(subj);
2419105634Srwatson			if (error)
2420105634Srwatson				return (error);
2421105634Srwatson		}
2422105634Srwatson	}
2423105634Srwatson
2424105634Srwatson	return (0);
2425101099Srwatson}
2426101099Srwatson
2427101099Srwatsonstatic int
2428101099Srwatsonmac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2429101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label,
2430101099Srwatson    struct componentname *cnp)
2431101099Srwatson{
2432101099Srwatson	struct mac_biba *subj, *obj;
2433101099Srwatson
2434101099Srwatson	if (!mac_biba_enabled)
2435101099Srwatson		return (0);
2436101099Srwatson
2437122524Srwatson	subj = SLOT(cred->cr_label);
2438101099Srwatson	obj = SLOT(dlabel);
2439101099Srwatson
2440101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2441101099Srwatson		return (EACCES);
2442101099Srwatson
2443101099Srwatson	obj = SLOT(label);
2444101099Srwatson
2445101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2446101099Srwatson		return (EACCES);
2447101099Srwatson
2448101099Srwatson	return (0);
2449101099Srwatson}
2450101099Srwatson
2451101099Srwatsonstatic int
2452101099Srwatsonmac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2453101099Srwatson    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2454101099Srwatson    struct componentname *cnp)
2455101099Srwatson{
2456101099Srwatson	struct mac_biba *subj, *obj;
2457101099Srwatson
2458101099Srwatson	if (!mac_biba_enabled)
2459101099Srwatson		return (0);
2460101099Srwatson
2461122524Srwatson	subj = SLOT(cred->cr_label);
2462101099Srwatson	obj = SLOT(dlabel);
2463101099Srwatson
2464101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2465101099Srwatson		return (EACCES);
2466101099Srwatson
2467101099Srwatson	if (vp != NULL) {
2468101099Srwatson		obj = SLOT(label);
2469101099Srwatson
2470101099Srwatson		if (!mac_biba_dominate_single(subj, obj))
2471101099Srwatson			return (EACCES);
2472101099Srwatson	}
2473101099Srwatson
2474101099Srwatson	return (0);
2475101099Srwatson}
2476101099Srwatson
2477101099Srwatsonstatic int
2478101099Srwatsonmac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2479101099Srwatson    struct label *label)
2480101099Srwatson{
2481101099Srwatson	struct mac_biba *subj, *obj;
2482101099Srwatson
2483101099Srwatson	if (!mac_biba_enabled)
2484101099Srwatson		return (0);
2485101099Srwatson
2486122524Srwatson	subj = SLOT(cred->cr_label);
2487101099Srwatson	obj = SLOT(label);
2488101099Srwatson
2489101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2490101099Srwatson		return (EACCES);
2491101099Srwatson
2492101099Srwatson	return (0);
2493101099Srwatson}
2494101099Srwatson
2495101099Srwatsonstatic int
2496101099Srwatsonmac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2497101099Srwatson    struct label *label, acl_type_t type, struct acl *acl)
2498101099Srwatson{
2499101099Srwatson	struct mac_biba *subj, *obj;
2500101099Srwatson
2501101099Srwatson	if (!mac_biba_enabled)
2502101099Srwatson		return (0);
2503101099Srwatson
2504122524Srwatson	subj = SLOT(cred->cr_label);
2505101099Srwatson	obj = SLOT(label);
2506101099Srwatson
2507101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2508101099Srwatson		return (EACCES);
2509101099Srwatson
2510101099Srwatson	return (0);
2511101099Srwatson}
2512101099Srwatson
2513101099Srwatsonstatic int
2514101099Srwatsonmac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2515101099Srwatson    struct label *vnodelabel, int attrnamespace, const char *name,
2516101099Srwatson    struct uio *uio)
2517101099Srwatson{
2518101099Srwatson	struct mac_biba *subj, *obj;
2519101099Srwatson
2520101099Srwatson	if (!mac_biba_enabled)
2521101099Srwatson		return (0);
2522101099Srwatson
2523122524Srwatson	subj = SLOT(cred->cr_label);
2524101099Srwatson	obj = SLOT(vnodelabel);
2525101099Srwatson
2526101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2527101099Srwatson		return (EACCES);
2528101099Srwatson
2529101099Srwatson	/* XXX: protect the MAC EA in a special way? */
2530101099Srwatson
2531101099Srwatson	return (0);
2532101099Srwatson}
2533101099Srwatson
2534101099Srwatsonstatic int
2535101099Srwatsonmac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2536101099Srwatson    struct label *vnodelabel, u_long flags)
2537101099Srwatson{
2538101099Srwatson	struct mac_biba *subj, *obj;
2539101099Srwatson
2540101099Srwatson	if (!mac_biba_enabled)
2541101099Srwatson		return (0);
2542101099Srwatson
2543122524Srwatson	subj = SLOT(cred->cr_label);
2544101099Srwatson	obj = SLOT(vnodelabel);
2545101099Srwatson
2546101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2547101099Srwatson		return (EACCES);
2548101099Srwatson
2549101099Srwatson	return (0);
2550101099Srwatson}
2551101099Srwatson
2552101099Srwatsonstatic int
2553101099Srwatsonmac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2554101099Srwatson    struct label *vnodelabel, mode_t mode)
2555101099Srwatson{
2556101099Srwatson	struct mac_biba *subj, *obj;
2557101099Srwatson
2558101099Srwatson	if (!mac_biba_enabled)
2559101099Srwatson		return (0);
2560101099Srwatson
2561122524Srwatson	subj = SLOT(cred->cr_label);
2562101099Srwatson	obj = SLOT(vnodelabel);
2563101099Srwatson
2564101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2565101099Srwatson		return (EACCES);
2566101099Srwatson
2567101099Srwatson	return (0);
2568101099Srwatson}
2569101099Srwatson
2570101099Srwatsonstatic int
2571101099Srwatsonmac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2572101099Srwatson    struct label *vnodelabel, uid_t uid, gid_t gid)
2573101099Srwatson{
2574101099Srwatson	struct mac_biba *subj, *obj;
2575101099Srwatson
2576101099Srwatson	if (!mac_biba_enabled)
2577101099Srwatson		return (0);
2578101099Srwatson
2579122524Srwatson	subj = SLOT(cred->cr_label);
2580101099Srwatson	obj = SLOT(vnodelabel);
2581101099Srwatson
2582101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2583101099Srwatson		return (EACCES);
2584101099Srwatson
2585101099Srwatson	return (0);
2586101099Srwatson}
2587101099Srwatson
2588101099Srwatsonstatic int
2589101099Srwatsonmac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2590101099Srwatson    struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2591101099Srwatson{
2592101099Srwatson	struct mac_biba *subj, *obj;
2593101099Srwatson
2594101099Srwatson	if (!mac_biba_enabled)
2595101099Srwatson		return (0);
2596101099Srwatson
2597122524Srwatson	subj = SLOT(cred->cr_label);
2598101099Srwatson	obj = SLOT(vnodelabel);
2599101099Srwatson
2600101099Srwatson	if (!mac_biba_dominate_single(subj, obj))
2601101099Srwatson		return (EACCES);
2602101099Srwatson
2603101099Srwatson	return (0);
2604101099Srwatson}
2605101099Srwatson
2606101099Srwatsonstatic int
2607102129Srwatsonmac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2608102129Srwatson    struct vnode *vp, struct label *vnodelabel)
2609101099Srwatson{
2610101099Srwatson	struct mac_biba *subj, *obj;
2611101099Srwatson
2612101099Srwatson	if (!mac_biba_enabled)
2613101099Srwatson		return (0);
2614101099Srwatson
2615122524Srwatson	subj = SLOT(active_cred->cr_label);
2616101099Srwatson	obj = SLOT(vnodelabel);
2617101099Srwatson
2618101099Srwatson	if (!mac_biba_dominate_single(obj, subj))
2619101099Srwatson		return (EACCES);
2620101099Srwatson
2621101099Srwatson	return (0);
2622101099Srwatson}
2623101099Srwatson
2624102112Srwatsonstatic int
2625102129Srwatsonmac_biba_check_vnode_write(struct ucred *active_cred,
2626102129Srwatson    struct ucred *file_cred, struct vnode *vp, struct label *label)
2627102112Srwatson{
2628102112Srwatson	struct mac_biba *subj, *obj;
2629102112Srwatson
2630105637Srwatson	if (!mac_biba_enabled || !revocation_enabled)
2631102112Srwatson		return (0);
2632102112Srwatson
2633122524Srwatson	subj = SLOT(active_cred->cr_label);
2634102112Srwatson	obj = SLOT(label);
2635102112Srwatson
2636102112Srwatson	if (!mac_biba_dominate_single(subj, obj))
2637102112Srwatson		return (EACCES);
2638102112Srwatson
2639102112Srwatson	return (0);
2640102112Srwatson}
2641102112Srwatson
2642106217Srwatsonstatic struct mac_policy_ops mac_biba_ops =
2643101099Srwatson{
2644106217Srwatson	.mpo_init = mac_biba_init,
2645106217Srwatson	.mpo_init_bpfdesc_label = mac_biba_init_label,
2646106217Srwatson	.mpo_init_cred_label = mac_biba_init_label,
2647106217Srwatson	.mpo_init_devfsdirent_label = mac_biba_init_label,
2648106217Srwatson	.mpo_init_ifnet_label = mac_biba_init_label,
2649122875Srwatson	.mpo_init_inpcb_label = mac_biba_init_label_waitcheck,
2650112675Srwatson	.mpo_init_ipq_label = mac_biba_init_label_waitcheck,
2651106217Srwatson	.mpo_init_mbuf_label = mac_biba_init_label_waitcheck,
2652106217Srwatson	.mpo_init_mount_label = mac_biba_init_label,
2653106217Srwatson	.mpo_init_mount_fs_label = mac_biba_init_label,
2654106217Srwatson	.mpo_init_pipe_label = mac_biba_init_label,
2655106217Srwatson	.mpo_init_socket_label = mac_biba_init_label_waitcheck,
2656106217Srwatson	.mpo_init_socket_peer_label = mac_biba_init_label_waitcheck,
2657106217Srwatson	.mpo_init_vnode_label = mac_biba_init_label,
2658106217Srwatson	.mpo_destroy_bpfdesc_label = mac_biba_destroy_label,
2659106217Srwatson	.mpo_destroy_cred_label = mac_biba_destroy_label,
2660106217Srwatson	.mpo_destroy_devfsdirent_label = mac_biba_destroy_label,
2661106217Srwatson	.mpo_destroy_ifnet_label = mac_biba_destroy_label,
2662122875Srwatson	.mpo_destroy_inpcb_label = mac_biba_destroy_label,
2663106217Srwatson	.mpo_destroy_ipq_label = mac_biba_destroy_label,
2664106217Srwatson	.mpo_destroy_mbuf_label = mac_biba_destroy_label,
2665106217Srwatson	.mpo_destroy_mount_label = mac_biba_destroy_label,
2666106217Srwatson	.mpo_destroy_mount_fs_label = mac_biba_destroy_label,
2667106217Srwatson	.mpo_destroy_pipe_label = mac_biba_destroy_label,
2668106217Srwatson	.mpo_destroy_socket_label = mac_biba_destroy_label,
2669106217Srwatson	.mpo_destroy_socket_peer_label = mac_biba_destroy_label,
2670106217Srwatson	.mpo_destroy_vnode_label = mac_biba_destroy_label,
2671115707Srwatson	.mpo_copy_mbuf_label = mac_biba_copy_label,
2672106217Srwatson	.mpo_copy_pipe_label = mac_biba_copy_label,
2673122820Srwatson	.mpo_copy_socket_label = mac_biba_copy_label,
2674106217Srwatson	.mpo_copy_vnode_label = mac_biba_copy_label,
2675106217Srwatson	.mpo_externalize_cred_label = mac_biba_externalize_label,
2676106217Srwatson	.mpo_externalize_ifnet_label = mac_biba_externalize_label,
2677106217Srwatson	.mpo_externalize_pipe_label = mac_biba_externalize_label,
2678106217Srwatson	.mpo_externalize_socket_label = mac_biba_externalize_label,
2679106217Srwatson	.mpo_externalize_socket_peer_label = mac_biba_externalize_label,
2680106217Srwatson	.mpo_externalize_vnode_label = mac_biba_externalize_label,
2681106217Srwatson	.mpo_internalize_cred_label = mac_biba_internalize_label,
2682106217Srwatson	.mpo_internalize_ifnet_label = mac_biba_internalize_label,
2683106217Srwatson	.mpo_internalize_pipe_label = mac_biba_internalize_label,
2684106217Srwatson	.mpo_internalize_socket_label = mac_biba_internalize_label,
2685106217Srwatson	.mpo_internalize_vnode_label = mac_biba_internalize_label,
2686106217Srwatson	.mpo_create_devfs_device = mac_biba_create_devfs_device,
2687106217Srwatson	.mpo_create_devfs_directory = mac_biba_create_devfs_directory,
2688106217Srwatson	.mpo_create_devfs_symlink = mac_biba_create_devfs_symlink,
2689106217Srwatson	.mpo_create_mount = mac_biba_create_mount,
2690106217Srwatson	.mpo_create_root_mount = mac_biba_create_root_mount,
2691106217Srwatson	.mpo_relabel_vnode = mac_biba_relabel_vnode,
2692106217Srwatson	.mpo_update_devfsdirent = mac_biba_update_devfsdirent,
2693106217Srwatson	.mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs,
2694106217Srwatson	.mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr,
2695106217Srwatson	.mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel,
2696106217Srwatson	.mpo_create_vnode_extattr = mac_biba_create_vnode_extattr,
2697106217Srwatson	.mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr,
2698106217Srwatson	.mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket,
2699106217Srwatson	.mpo_create_pipe = mac_biba_create_pipe,
2700106217Srwatson	.mpo_create_socket = mac_biba_create_socket,
2701106217Srwatson	.mpo_create_socket_from_socket = mac_biba_create_socket_from_socket,
2702106217Srwatson	.mpo_relabel_pipe = mac_biba_relabel_pipe,
2703106217Srwatson	.mpo_relabel_socket = mac_biba_relabel_socket,
2704106217Srwatson	.mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf,
2705106217Srwatson	.mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket,
2706106217Srwatson	.mpo_create_bpfdesc = mac_biba_create_bpfdesc,
2707106217Srwatson	.mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq,
2708106217Srwatson	.mpo_create_fragment = mac_biba_create_fragment,
2709106217Srwatson	.mpo_create_ifnet = mac_biba_create_ifnet,
2710122875Srwatson	.mpo_create_inpcb_from_socket = mac_biba_create_inpcb_from_socket,
2711106217Srwatson	.mpo_create_ipq = mac_biba_create_ipq,
2712106217Srwatson	.mpo_create_mbuf_from_mbuf = mac_biba_create_mbuf_from_mbuf,
2713106217Srwatson	.mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer,
2714106217Srwatson	.mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc,
2715106217Srwatson	.mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet,
2716106217Srwatson	.mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap,
2717106217Srwatson	.mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer,
2718106217Srwatson	.mpo_fragment_match = mac_biba_fragment_match,
2719106217Srwatson	.mpo_relabel_ifnet = mac_biba_relabel_ifnet,
2720106217Srwatson	.mpo_update_ipq = mac_biba_update_ipq,
2721122875Srwatson	.mpo_inpcb_sosetlabel = mac_biba_inpcb_sosetlabel,
2722106217Srwatson	.mpo_create_cred = mac_biba_create_cred,
2723106217Srwatson	.mpo_create_proc0 = mac_biba_create_proc0,
2724106217Srwatson	.mpo_create_proc1 = mac_biba_create_proc1,
2725106217Srwatson	.mpo_relabel_cred = mac_biba_relabel_cred,
2726106217Srwatson	.mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive,
2727106217Srwatson	.mpo_check_cred_relabel = mac_biba_check_cred_relabel,
2728106217Srwatson	.mpo_check_cred_visible = mac_biba_check_cred_visible,
2729106217Srwatson	.mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel,
2730106217Srwatson	.mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit,
2731122875Srwatson	.mpo_check_inpcb_deliver = mac_biba_check_inpcb_deliver,
2732110354Srwatson	.mpo_check_kld_load = mac_biba_check_kld_load,
2733110354Srwatson	.mpo_check_kld_unload = mac_biba_check_kld_unload,
2734106217Srwatson	.mpo_check_mount_stat = mac_biba_check_mount_stat,
2735106217Srwatson	.mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl,
2736106217Srwatson	.mpo_check_pipe_poll = mac_biba_check_pipe_poll,
2737106217Srwatson	.mpo_check_pipe_read = mac_biba_check_pipe_read,
2738106217Srwatson	.mpo_check_pipe_relabel = mac_biba_check_pipe_relabel,
2739106217Srwatson	.mpo_check_pipe_stat = mac_biba_check_pipe_stat,
2740106217Srwatson	.mpo_check_pipe_write = mac_biba_check_pipe_write,
2741106217Srwatson	.mpo_check_proc_debug = mac_biba_check_proc_debug,
2742106217Srwatson	.mpo_check_proc_sched = mac_biba_check_proc_sched,
2743106217Srwatson	.mpo_check_proc_signal = mac_biba_check_proc_signal,
2744106217Srwatson	.mpo_check_socket_deliver = mac_biba_check_socket_deliver,
2745106217Srwatson	.mpo_check_socket_relabel = mac_biba_check_socket_relabel,
2746106217Srwatson	.mpo_check_socket_visible = mac_biba_check_socket_visible,
2747112574Srwatson	.mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm,
2748106418Srwatson	.mpo_check_system_acct = mac_biba_check_system_acct,
2749106418Srwatson	.mpo_check_system_settime = mac_biba_check_system_settime,
2750106217Srwatson	.mpo_check_system_swapon = mac_biba_check_system_swapon,
2751112574Srwatson	.mpo_check_system_swapoff = mac_biba_check_system_swapoff,
2752106217Srwatson	.mpo_check_system_sysctl = mac_biba_check_system_sysctl,
2753106217Srwatson	.mpo_check_vnode_access = mac_biba_check_vnode_open,
2754106217Srwatson	.mpo_check_vnode_chdir = mac_biba_check_vnode_chdir,
2755106217Srwatson	.mpo_check_vnode_chroot = mac_biba_check_vnode_chroot,
2756106217Srwatson	.mpo_check_vnode_create = mac_biba_check_vnode_create,
2757106217Srwatson	.mpo_check_vnode_delete = mac_biba_check_vnode_delete,
2758106217Srwatson	.mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl,
2759119202Srwatson	.mpo_check_vnode_deleteextattr = mac_biba_check_vnode_deleteextattr,
2760106217Srwatson	.mpo_check_vnode_exec = mac_biba_check_vnode_exec,
2761106217Srwatson	.mpo_check_vnode_getacl = mac_biba_check_vnode_getacl,
2762106217Srwatson	.mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr,
2763106217Srwatson	.mpo_check_vnode_link = mac_biba_check_vnode_link,
2764119202Srwatson	.mpo_check_vnode_listextattr = mac_biba_check_vnode_listextattr,
2765106217Srwatson	.mpo_check_vnode_lookup = mac_biba_check_vnode_lookup,
2766106217Srwatson	.mpo_check_vnode_mmap = mac_biba_check_vnode_mmap,
2767106217Srwatson	.mpo_check_vnode_mprotect = mac_biba_check_vnode_mmap,
2768106217Srwatson	.mpo_check_vnode_open = mac_biba_check_vnode_open,
2769106217Srwatson	.mpo_check_vnode_poll = mac_biba_check_vnode_poll,
2770106217Srwatson	.mpo_check_vnode_read = mac_biba_check_vnode_read,
2771106217Srwatson	.mpo_check_vnode_readdir = mac_biba_check_vnode_readdir,
2772106217Srwatson	.mpo_check_vnode_readlink = mac_biba_check_vnode_readlink,
2773106217Srwatson	.mpo_check_vnode_relabel = mac_biba_check_vnode_relabel,
2774106217Srwatson	.mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from,
2775106217Srwatson	.mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to,
2776106217Srwatson	.mpo_check_vnode_revoke = mac_biba_check_vnode_revoke,
2777106217Srwatson	.mpo_check_vnode_setacl = mac_biba_check_vnode_setacl,
2778106217Srwatson	.mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr,
2779106217Srwatson	.mpo_check_vnode_setflags = mac_biba_check_vnode_setflags,
2780106217Srwatson	.mpo_check_vnode_setmode = mac_biba_check_vnode_setmode,
2781106217Srwatson	.mpo_check_vnode_setowner = mac_biba_check_vnode_setowner,
2782106217Srwatson	.mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes,
2783106217Srwatson	.mpo_check_vnode_stat = mac_biba_check_vnode_stat,
2784106217Srwatson	.mpo_check_vnode_write = mac_biba_check_vnode_write,
2785101099Srwatson};
2786101099Srwatson
2787112717SrwatsonMAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
2788113531Srwatson    MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_biba_slot);
2789