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