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