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