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