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