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