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