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