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