1/*-
2 * Copyright (c) 1999-2002, 2007-2011 Robert N. M. Watson
3 * Copyright (c) 2001-2005 McAfee, Inc.
4 * Copyright (c) 2006 SPARTA, Inc.
5 * All rights reserved.
6 *
7 * This software was developed by Robert Watson for the TrustedBSD Project.
8 *
9 * This software was developed for the FreeBSD Project in part by McAfee
10 * Research, the Security Research Division of McAfee, Inc. under
11 * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
12 * CHATS research program.
13 *
14 * This software was enhanced by SPARTA ISSO under SPAWAR contract
15 * N66001-04-C-6019 ("SEFOS").
16 *
17 * This software was developed at the University of Cambridge Computer
18 * Laboratory with support from a grant from Google, Inc.
19 *
20 * Redistribution and use in source and binary forms, with or without
21 * modification, are permitted provided that the following conditions
22 * are met:
23 * 1. Redistributions of source code must retain the above copyright
24 *    notice, this list of conditions and the following disclaimer.
25 * 2. Redistributions in binary form must reproduce the above copyright
26 *    notice, this list of conditions and the following disclaimer in the
27 *    documentation and/or other materials provided with the distribution.
28 *
29 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
32 * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
39 * SUCH DAMAGE.
40 *
41 * $FreeBSD$
42 */
43
44/*
45 * Developed by the TrustedBSD Project.
46 *
47 * Biba fixed label mandatory integrity policy.
48 */
49
50#include <sys/param.h>
51#include <sys/conf.h>
52#include <sys/extattr.h>
53#include <sys/kernel.h>
54#include <sys/ksem.h>
55#include <sys/malloc.h>
56#include <sys/mman.h>
57#include <sys/mount.h>
58#include <sys/priv.h>
59#include <sys/proc.h>
60#include <sys/sbuf.h>
61#include <sys/systm.h>
62#include <sys/sysproto.h>
63#include <sys/sysent.h>
64#include <sys/systm.h>
65#include <sys/vnode.h>
66#include <sys/file.h>
67#include <sys/socket.h>
68#include <sys/socketvar.h>
69#include <sys/pipe.h>
70#include <sys/sx.h>
71#include <sys/sysctl.h>
72#include <sys/msg.h>
73#include <sys/sem.h>
74#include <sys/shm.h>
75
76#include <fs/devfs/devfs.h>
77
78#include <net/bpfdesc.h>
79#include <net/if.h>
80#include <net/if_types.h>
81#include <net/if_var.h>
82
83#include <netinet/in.h>
84#include <netinet/in_pcb.h>
85#include <netinet/ip_var.h>
86
87#include <vm/uma.h>
88#include <vm/vm.h>
89
90#include <security/mac/mac_policy.h>
91#include <security/mac_biba/mac_biba.h>
92
93SYSCTL_DECL(_security_mac);
94
95static SYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
96    "TrustedBSD mac_biba policy controls");
97
98static int	biba_label_size = sizeof(struct mac_biba);
99SYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
100    &biba_label_size, 0, "Size of struct mac_biba");
101
102static int	biba_enabled = 1;
103SYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RWTUN, &biba_enabled,
104    0, "Enforce MAC/Biba policy");
105
106static int	destroyed_not_inited;
107SYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
108    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
109
110static int	trust_all_interfaces = 0;
111SYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RDTUN,
112    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
113
114static char	trusted_interfaces[128];
115SYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RDTUN,
116    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
117
118static int	max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
119SYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
120    &max_compartments, 0, "Maximum supported compartments");
121
122static int	ptys_equal = 0;
123SYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RWTUN, &ptys_equal,
124    0, "Label pty devices as biba/equal on create");
125
126static int	interfaces_equal = 1;
127SYSCTL_INT(_security_mac_biba, OID_AUTO, interfaces_equal, CTLFLAG_RWTUN,
128    &interfaces_equal, 0, "Label network interfaces as biba/equal on create");
129
130static int	revocation_enabled = 0;
131SYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RWTUN,
132    &revocation_enabled, 0, "Revoke access to objects on relabel");
133
134static int	biba_slot;
135#define	SLOT(l)	((struct mac_biba *)mac_label_get((l), biba_slot))
136#define	SLOT_SET(l, val) mac_label_set((l), biba_slot, (uintptr_t)(val))
137
138static uma_zone_t	zone_biba;
139
140static __inline int
141biba_bit_set_empty(u_char *set) {
142	int i;
143
144	for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
145		if (set[i] != 0)
146			return (0);
147	return (1);
148}
149
150static struct mac_biba *
151biba_alloc(int flag)
152{
153
154	return (uma_zalloc(zone_biba, flag | M_ZERO));
155}
156
157static void
158biba_free(struct mac_biba *mb)
159{
160
161	if (mb != NULL)
162		uma_zfree(zone_biba, mb);
163	else
164		atomic_add_int(&destroyed_not_inited, 1);
165}
166
167static int
168biba_atmostflags(struct mac_biba *mb, int flags)
169{
170
171	if ((mb->mb_flags & flags) != mb->mb_flags)
172		return (EINVAL);
173	return (0);
174}
175
176static int
177biba_dominate_element(struct mac_biba_element *a, struct mac_biba_element *b)
178{
179	int bit;
180
181	switch (a->mbe_type) {
182	case MAC_BIBA_TYPE_EQUAL:
183	case MAC_BIBA_TYPE_HIGH:
184		return (1);
185
186	case MAC_BIBA_TYPE_LOW:
187		switch (b->mbe_type) {
188		case MAC_BIBA_TYPE_GRADE:
189		case MAC_BIBA_TYPE_HIGH:
190			return (0);
191
192		case MAC_BIBA_TYPE_EQUAL:
193		case MAC_BIBA_TYPE_LOW:
194			return (1);
195
196		default:
197			panic("biba_dominate_element: b->mbe_type invalid");
198		}
199
200	case MAC_BIBA_TYPE_GRADE:
201		switch (b->mbe_type) {
202		case MAC_BIBA_TYPE_EQUAL:
203		case MAC_BIBA_TYPE_LOW:
204			return (1);
205
206		case MAC_BIBA_TYPE_HIGH:
207			return (0);
208
209		case MAC_BIBA_TYPE_GRADE:
210			for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
211				if (!MAC_BIBA_BIT_TEST(bit,
212				    a->mbe_compartments) &&
213				    MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
214					return (0);
215			return (a->mbe_grade >= b->mbe_grade);
216
217		default:
218			panic("biba_dominate_element: b->mbe_type invalid");
219		}
220
221	default:
222		panic("biba_dominate_element: a->mbe_type invalid");
223	}
224
225	return (0);
226}
227
228static int
229biba_subject_dominate_high(struct mac_biba *mb)
230{
231	struct mac_biba_element *element;
232
233	KASSERT((mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
234	    ("biba_effective_in_range: mb not effective"));
235	element = &mb->mb_effective;
236
237	return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
238	    element->mbe_type == MAC_BIBA_TYPE_HIGH);
239}
240
241static int
242biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
243{
244
245	return (biba_dominate_element(&rangeb->mb_rangehigh,
246	    &rangea->mb_rangehigh) &&
247	    biba_dominate_element(&rangea->mb_rangelow,
248	    &rangeb->mb_rangelow));
249}
250
251static int
252biba_effective_in_range(struct mac_biba *effective, struct mac_biba *range)
253{
254
255	KASSERT((effective->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
256	    ("biba_effective_in_range: a not effective"));
257	KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
258	    ("biba_effective_in_range: b not range"));
259
260	return (biba_dominate_element(&range->mb_rangehigh,
261	    &effective->mb_effective) &&
262	    biba_dominate_element(&effective->mb_effective,
263	    &range->mb_rangelow));
264
265	return (1);
266}
267
268static int
269biba_dominate_effective(struct mac_biba *a, struct mac_biba *b)
270{
271	KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
272	    ("biba_dominate_effective: a not effective"));
273	KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
274	    ("biba_dominate_effective: b not effective"));
275
276	return (biba_dominate_element(&a->mb_effective, &b->mb_effective));
277}
278
279static int
280biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
281{
282
283	if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
284	    b->mbe_type == MAC_BIBA_TYPE_EQUAL)
285		return (1);
286
287	return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
288}
289
290static int
291biba_equal_effective(struct mac_biba *a, struct mac_biba *b)
292{
293
294	KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
295	    ("biba_equal_effective: a not effective"));
296	KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
297	    ("biba_equal_effective: b not effective"));
298
299	return (biba_equal_element(&a->mb_effective, &b->mb_effective));
300}
301
302static int
303biba_contains_equal(struct mac_biba *mb)
304{
305
306	if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
307		if (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
308			return (1);
309	}
310
311	if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
312		if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
313			return (1);
314		if (mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
315			return (1);
316	}
317
318	return (0);
319}
320
321static int
322biba_subject_privileged(struct mac_biba *mb)
323{
324
325	KASSERT((mb->mb_flags & MAC_BIBA_FLAGS_BOTH) == MAC_BIBA_FLAGS_BOTH,
326	    ("biba_subject_privileged: subject doesn't have both labels"));
327
328	/* If the effective is EQUAL, it's ok. */
329	if (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
330		return (0);
331
332	/* If either range endpoint is EQUAL, it's ok. */
333	if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
334	    mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
335		return (0);
336
337	/* If the range is low-high, it's ok. */
338	if (mb->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
339	    mb->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
340		return (0);
341
342	/* It's not ok. */
343	return (EPERM);
344}
345
346static int
347biba_high_effective(struct mac_biba *mb)
348{
349
350	KASSERT((mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
351	    ("biba_equal_effective: mb not effective"));
352
353	return (mb->mb_effective.mbe_type == MAC_BIBA_TYPE_HIGH);
354}
355
356static int
357biba_valid(struct mac_biba *mb)
358{
359
360	if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
361		switch (mb->mb_effective.mbe_type) {
362		case MAC_BIBA_TYPE_GRADE:
363			break;
364
365		case MAC_BIBA_TYPE_EQUAL:
366		case MAC_BIBA_TYPE_HIGH:
367		case MAC_BIBA_TYPE_LOW:
368			if (mb->mb_effective.mbe_grade != 0 ||
369			    !MAC_BIBA_BIT_SET_EMPTY(
370			    mb->mb_effective.mbe_compartments))
371				return (EINVAL);
372			break;
373
374		default:
375			return (EINVAL);
376		}
377	} else {
378		if (mb->mb_effective.mbe_type != MAC_BIBA_TYPE_UNDEF)
379			return (EINVAL);
380	}
381
382	if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
383		switch (mb->mb_rangelow.mbe_type) {
384		case MAC_BIBA_TYPE_GRADE:
385			break;
386
387		case MAC_BIBA_TYPE_EQUAL:
388		case MAC_BIBA_TYPE_HIGH:
389		case MAC_BIBA_TYPE_LOW:
390			if (mb->mb_rangelow.mbe_grade != 0 ||
391			    !MAC_BIBA_BIT_SET_EMPTY(
392			    mb->mb_rangelow.mbe_compartments))
393				return (EINVAL);
394			break;
395
396		default:
397			return (EINVAL);
398		}
399
400		switch (mb->mb_rangehigh.mbe_type) {
401		case MAC_BIBA_TYPE_GRADE:
402			break;
403
404		case MAC_BIBA_TYPE_EQUAL:
405		case MAC_BIBA_TYPE_HIGH:
406		case MAC_BIBA_TYPE_LOW:
407			if (mb->mb_rangehigh.mbe_grade != 0 ||
408			    !MAC_BIBA_BIT_SET_EMPTY(
409			    mb->mb_rangehigh.mbe_compartments))
410				return (EINVAL);
411			break;
412
413		default:
414			return (EINVAL);
415		}
416		if (!biba_dominate_element(&mb->mb_rangehigh,
417		    &mb->mb_rangelow))
418			return (EINVAL);
419	} else {
420		if (mb->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
421		    mb->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
422			return (EINVAL);
423	}
424
425	return (0);
426}
427
428static void
429biba_set_range(struct mac_biba *mb, u_short typelow, u_short gradelow,
430    u_char *compartmentslow, u_short typehigh, u_short gradehigh,
431    u_char *compartmentshigh)
432{
433
434	mb->mb_rangelow.mbe_type = typelow;
435	mb->mb_rangelow.mbe_grade = gradelow;
436	if (compartmentslow != NULL)
437		memcpy(mb->mb_rangelow.mbe_compartments, compartmentslow,
438		    sizeof(mb->mb_rangelow.mbe_compartments));
439	mb->mb_rangehigh.mbe_type = typehigh;
440	mb->mb_rangehigh.mbe_grade = gradehigh;
441	if (compartmentshigh != NULL)
442		memcpy(mb->mb_rangehigh.mbe_compartments, compartmentshigh,
443		    sizeof(mb->mb_rangehigh.mbe_compartments));
444	mb->mb_flags |= MAC_BIBA_FLAG_RANGE;
445}
446
447static void
448biba_set_effective(struct mac_biba *mb, u_short type, u_short grade,
449    u_char *compartments)
450{
451
452	mb->mb_effective.mbe_type = type;
453	mb->mb_effective.mbe_grade = grade;
454	if (compartments != NULL)
455		memcpy(mb->mb_effective.mbe_compartments, compartments,
456		    sizeof(mb->mb_effective.mbe_compartments));
457	mb->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
458}
459
460static void
461biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
462{
463
464	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
465	    ("biba_copy_range: labelfrom not range"));
466
467	labelto->mb_rangelow = labelfrom->mb_rangelow;
468	labelto->mb_rangehigh = labelfrom->mb_rangehigh;
469	labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
470}
471
472static void
473biba_copy_effective(struct mac_biba *labelfrom, struct mac_biba *labelto)
474{
475
476	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
477	    ("biba_copy_effective: labelfrom not effective"));
478
479	labelto->mb_effective = labelfrom->mb_effective;
480	labelto->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
481}
482
483static void
484biba_copy(struct mac_biba *source, struct mac_biba *dest)
485{
486
487	if (source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
488		biba_copy_effective(source, dest);
489	if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
490		biba_copy_range(source, dest);
491}
492
493/*
494 * Policy module operations.
495 */
496static void
497biba_init(struct mac_policy_conf *conf)
498{
499
500	zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL,
501	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
502}
503
504/*
505 * Label operations.
506 */
507static void
508biba_init_label(struct label *label)
509{
510
511	SLOT_SET(label, biba_alloc(M_WAITOK));
512}
513
514static int
515biba_init_label_waitcheck(struct label *label, int flag)
516{
517
518	SLOT_SET(label, biba_alloc(flag));
519	if (SLOT(label) == NULL)
520		return (ENOMEM);
521
522	return (0);
523}
524
525static void
526biba_destroy_label(struct label *label)
527{
528
529	biba_free(SLOT(label));
530	SLOT_SET(label, NULL);
531}
532
533/*
534 * biba_element_to_string() accepts an sbuf and Biba element.  It converts
535 * the Biba element to a string and stores the result in the sbuf; if there
536 * isn't space in the sbuf, -1 is returned.
537 */
538static int
539biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element)
540{
541	int i, first;
542
543	switch (element->mbe_type) {
544	case MAC_BIBA_TYPE_HIGH:
545		return (sbuf_printf(sb, "high"));
546
547	case MAC_BIBA_TYPE_LOW:
548		return (sbuf_printf(sb, "low"));
549
550	case MAC_BIBA_TYPE_EQUAL:
551		return (sbuf_printf(sb, "equal"));
552
553	case MAC_BIBA_TYPE_GRADE:
554		if (sbuf_printf(sb, "%d", element->mbe_grade) == -1)
555			return (-1);
556
557		first = 1;
558		for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) {
559			if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) {
560				if (first) {
561					if (sbuf_putc(sb, ':') == -1)
562						return (-1);
563					if (sbuf_printf(sb, "%d", i) == -1)
564						return (-1);
565					first = 0;
566				} else {
567					if (sbuf_printf(sb, "+%d", i) == -1)
568						return (-1);
569				}
570			}
571		}
572		return (0);
573
574	default:
575		panic("biba_element_to_string: invalid type (%d)",
576		    element->mbe_type);
577	}
578}
579
580/*
581 * biba_to_string() converts a Biba label to a string, and places the results
582 * in the passed sbuf.  It returns 0 on success, or EINVAL if there isn't
583 * room in the sbuf.  Note: the sbuf will be modified even in a failure case,
584 * so the caller may need to revert the sbuf by restoring the offset if
585 * that's undesired.
586 */
587static int
588biba_to_string(struct sbuf *sb, struct mac_biba *mb)
589{
590
591	if (mb->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
592		if (biba_element_to_string(sb, &mb->mb_effective) == -1)
593			return (EINVAL);
594	}
595
596	if (mb->mb_flags & MAC_BIBA_FLAG_RANGE) {
597		if (sbuf_putc(sb, '(') == -1)
598			return (EINVAL);
599
600		if (biba_element_to_string(sb, &mb->mb_rangelow) == -1)
601			return (EINVAL);
602
603		if (sbuf_putc(sb, '-') == -1)
604			return (EINVAL);
605
606		if (biba_element_to_string(sb, &mb->mb_rangehigh) == -1)
607			return (EINVAL);
608
609		if (sbuf_putc(sb, ')') == -1)
610			return (EINVAL);
611	}
612
613	return (0);
614}
615
616static int
617biba_externalize_label(struct label *label, char *element_name,
618    struct sbuf *sb, int *claimed)
619{
620	struct mac_biba *mb;
621
622	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
623		return (0);
624
625	(*claimed)++;
626
627	mb = SLOT(label);
628	return (biba_to_string(sb, mb));
629}
630
631static int
632biba_parse_element(struct mac_biba_element *element, char *string)
633{
634	char *compartment, *end, *grade;
635	int value;
636
637	if (strcmp(string, "high") == 0 || strcmp(string, "hi") == 0) {
638		element->mbe_type = MAC_BIBA_TYPE_HIGH;
639		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
640	} else if (strcmp(string, "low") == 0 || strcmp(string, "lo") == 0) {
641		element->mbe_type = MAC_BIBA_TYPE_LOW;
642		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
643	} else if (strcmp(string, "equal") == 0 ||
644	    strcmp(string, "eq") == 0) {
645		element->mbe_type = MAC_BIBA_TYPE_EQUAL;
646		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
647	} else {
648		element->mbe_type = MAC_BIBA_TYPE_GRADE;
649
650		/*
651		 * Numeric grade piece of the element.
652		 */
653		grade = strsep(&string, ":");
654		value = strtol(grade, &end, 10);
655		if (end == grade || *end != '\0')
656			return (EINVAL);
657		if (value < 0 || value > 65535)
658			return (EINVAL);
659		element->mbe_grade = value;
660
661		/*
662		 * Optional compartment piece of the element.  If none are
663		 * included, we assume that the label has no compartments.
664		 */
665		if (string == NULL)
666			return (0);
667		if (*string == '\0')
668			return (0);
669
670		while ((compartment = strsep(&string, "+")) != NULL) {
671			value = strtol(compartment, &end, 10);
672			if (compartment == end || *end != '\0')
673				return (EINVAL);
674			if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS)
675				return (EINVAL);
676			MAC_BIBA_BIT_SET(value, element->mbe_compartments);
677		}
678	}
679
680	return (0);
681}
682
683/*
684 * Note: destructively consumes the string, make a local copy before calling
685 * if that's a problem.
686 */
687static int
688biba_parse(struct mac_biba *mb, char *string)
689{
690	char *rangehigh, *rangelow, *effective;
691	int error;
692
693	effective = strsep(&string, "(");
694	if (*effective == '\0')
695		effective = NULL;
696
697	if (string != NULL) {
698		rangelow = strsep(&string, "-");
699		if (string == NULL)
700			return (EINVAL);
701		rangehigh = strsep(&string, ")");
702		if (string == NULL)
703			return (EINVAL);
704		if (*string != '\0')
705			return (EINVAL);
706	} else {
707		rangelow = NULL;
708		rangehigh = NULL;
709	}
710
711	KASSERT((rangelow != NULL && rangehigh != NULL) ||
712	    (rangelow == NULL && rangehigh == NULL),
713	    ("biba_parse: range mismatch"));
714
715	bzero(mb, sizeof(*mb));
716	if (effective != NULL) {
717		error = biba_parse_element(&mb->mb_effective, effective);
718		if (error)
719			return (error);
720		mb->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
721	}
722
723	if (rangelow != NULL) {
724		error = biba_parse_element(&mb->mb_rangelow, rangelow);
725		if (error)
726			return (error);
727		error = biba_parse_element(&mb->mb_rangehigh, rangehigh);
728		if (error)
729			return (error);
730		mb->mb_flags |= MAC_BIBA_FLAG_RANGE;
731	}
732
733	error = biba_valid(mb);
734	if (error)
735		return (error);
736
737	return (0);
738}
739
740static int
741biba_internalize_label(struct label *label, char *element_name,
742    char *element_data, int *claimed)
743{
744	struct mac_biba *mb, mb_temp;
745	int error;
746
747	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
748		return (0);
749
750	(*claimed)++;
751
752	error = biba_parse(&mb_temp, element_data);
753	if (error)
754		return (error);
755
756	mb = SLOT(label);
757	*mb = mb_temp;
758
759	return (0);
760}
761
762static void
763biba_copy_label(struct label *src, struct label *dest)
764{
765
766	*SLOT(dest) = *SLOT(src);
767}
768
769/*
770 * Object-specific entry point implementations are sorted alphabetically by
771 * object type name and then by operation.
772 */
773static int
774biba_bpfdesc_check_receive(struct bpf_d *d, struct label *dlabel,
775    struct ifnet *ifp, struct label *ifplabel)
776{
777	struct mac_biba *a, *b;
778
779	if (!biba_enabled)
780		return (0);
781
782	a = SLOT(dlabel);
783	b = SLOT(ifplabel);
784
785	if (biba_equal_effective(a, b))
786		return (0);
787	return (EACCES);
788}
789
790static void
791biba_bpfdesc_create(struct ucred *cred, struct bpf_d *d,
792    struct label *dlabel)
793{
794	struct mac_biba *source, *dest;
795
796	source = SLOT(cred->cr_label);
797	dest = SLOT(dlabel);
798
799	biba_copy_effective(source, dest);
800}
801
802static void
803biba_bpfdesc_create_mbuf(struct bpf_d *d, struct label *dlabel,
804    struct mbuf *m, struct label *mlabel)
805{
806	struct mac_biba *source, *dest;
807
808	source = SLOT(dlabel);
809	dest = SLOT(mlabel);
810
811	biba_copy_effective(source, dest);
812}
813
814static void
815biba_cred_associate_nfsd(struct ucred *cred)
816{
817	struct mac_biba *label;
818
819	label = SLOT(cred->cr_label);
820	biba_set_effective(label, MAC_BIBA_TYPE_LOW, 0, NULL);
821	biba_set_range(label, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
822	    0, NULL);
823}
824
825static int
826biba_cred_check_relabel(struct ucred *cred, struct label *newlabel)
827{
828	struct mac_biba *subj, *new;
829	int error;
830
831	subj = SLOT(cred->cr_label);
832	new = SLOT(newlabel);
833
834	/*
835	 * If there is a Biba label update for the credential, it may
836	 * be an update of the effective, range, or both.
837	 */
838	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
839	if (error)
840		return (error);
841
842	/*
843	 * If the Biba label is to be changed, authorize as appropriate.
844	 */
845	if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
846		/*
847		 * If the change request modifies both the Biba label
848		 * effective and range, check that the new effective will be
849		 * in the new range.
850		 */
851		if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
852		    MAC_BIBA_FLAGS_BOTH &&
853		    !biba_effective_in_range(new, new))
854			return (EINVAL);
855
856		/*
857		 * To change the Biba effective label on a credential, the
858		 * new effective label must be in the current range.
859		 */
860		if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE &&
861		    !biba_effective_in_range(new, subj))
862			return (EPERM);
863
864		/*
865		 * To change the Biba range on a credential, the new range
866		 * label must be in the current range.
867		 */
868		if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
869		    !biba_range_in_range(new, subj))
870			return (EPERM);
871
872		/*
873		 * To have EQUAL in any component of the new credential Biba
874		 * label, the subject must already have EQUAL in their label.
875		 */
876		if (biba_contains_equal(new)) {
877			error = biba_subject_privileged(subj);
878			if (error)
879				return (error);
880		}
881	}
882
883	return (0);
884}
885
886static int
887biba_cred_check_visible(struct ucred *u1, struct ucred *u2)
888{
889	struct mac_biba *subj, *obj;
890
891	if (!biba_enabled)
892		return (0);
893
894	subj = SLOT(u1->cr_label);
895	obj = SLOT(u2->cr_label);
896
897	/* XXX: range */
898	if (!biba_dominate_effective(obj, subj))
899		return (ESRCH);
900
901	return (0);
902}
903
904static void
905biba_cred_create_init(struct ucred *cred)
906{
907	struct mac_biba *dest;
908
909	dest = SLOT(cred->cr_label);
910
911	biba_set_effective(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
912	biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
913	    0, NULL);
914}
915
916static void
917biba_cred_create_swapper(struct ucred *cred)
918{
919	struct mac_biba *dest;
920
921	dest = SLOT(cred->cr_label);
922
923	biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
924	biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL, MAC_BIBA_TYPE_HIGH,
925	    0, NULL);
926}
927
928static void
929biba_cred_relabel(struct ucred *cred, struct label *newlabel)
930{
931	struct mac_biba *source, *dest;
932
933	source = SLOT(newlabel);
934	dest = SLOT(cred->cr_label);
935
936	biba_copy(source, dest);
937}
938
939static void
940biba_devfs_create_device(struct ucred *cred, struct mount *mp,
941    struct cdev *dev, struct devfs_dirent *de, struct label *delabel)
942{
943	struct mac_biba *mb;
944	const char *dn;
945	int biba_type;
946
947	mb = SLOT(delabel);
948	dn = devtoname(dev);
949	if (strcmp(dn, "null") == 0 ||
950	    strcmp(dn, "zero") == 0 ||
951	    strcmp(dn, "random") == 0 ||
952	    strncmp(dn, "fd/", strlen("fd/")) == 0)
953		biba_type = MAC_BIBA_TYPE_EQUAL;
954	else if (ptys_equal &&
955	    (strncmp(dn, "ttyp", strlen("ttyp")) == 0 ||
956	    strncmp(dn, "pts/", strlen("pts/")) == 0 ||
957	    strncmp(dn, "ptyp", strlen("ptyp")) == 0))
958		biba_type = MAC_BIBA_TYPE_EQUAL;
959	else
960		biba_type = MAC_BIBA_TYPE_HIGH;
961	biba_set_effective(mb, biba_type, 0, NULL);
962}
963
964static void
965biba_devfs_create_directory(struct mount *mp, char *dirname, int dirnamelen,
966    struct devfs_dirent *de, struct label *delabel)
967{
968	struct mac_biba *mb;
969
970	mb = SLOT(delabel);
971
972	biba_set_effective(mb, MAC_BIBA_TYPE_HIGH, 0, NULL);
973}
974
975static void
976biba_devfs_create_symlink(struct ucred *cred, struct mount *mp,
977    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
978    struct label *delabel)
979{
980	struct mac_biba *source, *dest;
981
982	source = SLOT(cred->cr_label);
983	dest = SLOT(delabel);
984
985	biba_copy_effective(source, dest);
986}
987
988static void
989biba_devfs_update(struct mount *mp, struct devfs_dirent *de,
990    struct label *delabel, struct vnode *vp, struct label *vplabel)
991{
992	struct mac_biba *source, *dest;
993
994	source = SLOT(vplabel);
995	dest = SLOT(delabel);
996
997	biba_copy(source, dest);
998}
999
1000static void
1001biba_devfs_vnode_associate(struct mount *mp, struct label *mntlabel,
1002    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
1003    struct label *vplabel)
1004{
1005	struct mac_biba *source, *dest;
1006
1007	source = SLOT(delabel);
1008	dest = SLOT(vplabel);
1009
1010	biba_copy_effective(source, dest);
1011}
1012
1013static int
1014biba_ifnet_check_relabel(struct ucred *cred, struct ifnet *ifp,
1015    struct label *ifplabel, struct label *newlabel)
1016{
1017	struct mac_biba *subj, *new;
1018	int error;
1019
1020	subj = SLOT(cred->cr_label);
1021	new = SLOT(newlabel);
1022
1023	/*
1024	 * If there is a Biba label update for the interface, it may be an
1025	 * update of the effective, range, or both.
1026	 */
1027	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1028	if (error)
1029		return (error);
1030
1031	/*
1032	 * Relabling network interfaces requires Biba privilege.
1033	 */
1034	error = biba_subject_privileged(subj);
1035	if (error)
1036		return (error);
1037
1038	return (0);
1039}
1040
1041static int
1042biba_ifnet_check_transmit(struct ifnet *ifp, struct label *ifplabel,
1043    struct mbuf *m, struct label *mlabel)
1044{
1045	struct mac_biba *p, *i;
1046
1047	if (!biba_enabled)
1048		return (0);
1049
1050	p = SLOT(mlabel);
1051	i = SLOT(ifplabel);
1052
1053	return (biba_effective_in_range(p, i) ? 0 : EACCES);
1054}
1055
1056static void
1057biba_ifnet_create(struct ifnet *ifp, struct label *ifplabel)
1058{
1059	char tifname[IFNAMSIZ], *p, *q;
1060	char tiflist[sizeof(trusted_interfaces)];
1061	struct mac_biba *dest;
1062	int len, type;
1063
1064	dest = SLOT(ifplabel);
1065
1066	if (ifp->if_type == IFT_LOOP || interfaces_equal != 0) {
1067		type = MAC_BIBA_TYPE_EQUAL;
1068		goto set;
1069	}
1070
1071	if (trust_all_interfaces) {
1072		type = MAC_BIBA_TYPE_HIGH;
1073		goto set;
1074	}
1075
1076	type = MAC_BIBA_TYPE_LOW;
1077
1078	if (trusted_interfaces[0] == '\0' ||
1079	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1080		goto set;
1081
1082	bzero(tiflist, sizeof(tiflist));
1083	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1084		if(*p != ' ' && *p != '\t')
1085			*q = *p;
1086
1087	for (p = q = tiflist;; p++) {
1088		if (*p == ',' || *p == '\0') {
1089			len = p - q;
1090			if (len < IFNAMSIZ) {
1091				bzero(tifname, sizeof(tifname));
1092				bcopy(q, tifname, len);
1093				if (strcmp(tifname, ifp->if_xname) == 0) {
1094					type = MAC_BIBA_TYPE_HIGH;
1095					break;
1096				}
1097			} else {
1098				*p = '\0';
1099				printf("mac_biba warning: interface name "
1100				    "\"%s\" is too long (must be < %d)\n",
1101				    q, IFNAMSIZ);
1102			}
1103			if (*p == '\0')
1104				break;
1105			q = p + 1;
1106		}
1107	}
1108set:
1109	biba_set_effective(dest, type, 0, NULL);
1110	biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1111}
1112
1113static void
1114biba_ifnet_create_mbuf(struct ifnet *ifp, struct label *ifplabel,
1115    struct mbuf *m, struct label *mlabel)
1116{
1117	struct mac_biba *source, *dest;
1118
1119	source = SLOT(ifplabel);
1120	dest = SLOT(mlabel);
1121
1122	biba_copy_effective(source, dest);
1123}
1124
1125static void
1126biba_ifnet_relabel(struct ucred *cred, struct ifnet *ifp,
1127    struct label *ifplabel, struct label *newlabel)
1128{
1129	struct mac_biba *source, *dest;
1130
1131	source = SLOT(newlabel);
1132	dest = SLOT(ifplabel);
1133
1134	biba_copy(source, dest);
1135}
1136
1137static int
1138biba_inpcb_check_deliver(struct inpcb *inp, struct label *inplabel,
1139    struct mbuf *m, struct label *mlabel)
1140{
1141	struct mac_biba *p, *i;
1142
1143	if (!biba_enabled)
1144		return (0);
1145
1146	p = SLOT(mlabel);
1147	i = SLOT(inplabel);
1148
1149	return (biba_equal_effective(p, i) ? 0 : EACCES);
1150}
1151
1152static int
1153biba_inpcb_check_visible(struct ucred *cred, struct inpcb *inp,
1154    struct label *inplabel)
1155{
1156	struct mac_biba *subj, *obj;
1157
1158	if (!biba_enabled)
1159		return (0);
1160
1161	subj = SLOT(cred->cr_label);
1162	obj = SLOT(inplabel);
1163
1164	if (!biba_dominate_effective(obj, subj))
1165		return (ENOENT);
1166
1167	return (0);
1168}
1169
1170static void
1171biba_inpcb_create(struct socket *so, struct label *solabel,
1172    struct inpcb *inp, struct label *inplabel)
1173{
1174	struct mac_biba *source, *dest;
1175
1176	source = SLOT(solabel);
1177	dest = SLOT(inplabel);
1178
1179	SOCK_LOCK(so);
1180	biba_copy_effective(source, dest);
1181	SOCK_UNLOCK(so);
1182}
1183
1184static void
1185biba_inpcb_create_mbuf(struct inpcb *inp, struct label *inplabel,
1186    struct mbuf *m, struct label *mlabel)
1187{
1188	struct mac_biba *source, *dest;
1189
1190	source = SLOT(inplabel);
1191	dest = SLOT(mlabel);
1192
1193	biba_copy_effective(source, dest);
1194}
1195
1196static void
1197biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1198    struct inpcb *inp, struct label *inplabel)
1199{
1200	struct mac_biba *source, *dest;
1201
1202	SOCK_LOCK_ASSERT(so);
1203
1204	source = SLOT(solabel);
1205	dest = SLOT(inplabel);
1206
1207	biba_copy(source, dest);
1208}
1209
1210static void
1211biba_ip6q_create(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1212    struct label *q6label)
1213{
1214	struct mac_biba *source, *dest;
1215
1216	source = SLOT(mlabel);
1217	dest = SLOT(q6label);
1218
1219	biba_copy_effective(source, dest);
1220}
1221
1222static int
1223biba_ip6q_match(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1224    struct label *q6label)
1225{
1226	struct mac_biba *a, *b;
1227
1228	a = SLOT(q6label);
1229	b = SLOT(mlabel);
1230
1231	return (biba_equal_effective(a, b));
1232}
1233
1234static void
1235biba_ip6q_reassemble(struct ip6q *q6, struct label *q6label, struct mbuf *m,
1236    struct label *mlabel)
1237{
1238	struct mac_biba *source, *dest;
1239
1240	source = SLOT(q6label);
1241	dest = SLOT(mlabel);
1242
1243	/* Just use the head, since we require them all to match. */
1244	biba_copy_effective(source, dest);
1245}
1246
1247static void
1248biba_ip6q_update(struct mbuf *m, struct label *mlabel, struct ip6q *q6,
1249    struct label *q6label)
1250{
1251
1252	/* NOOP: we only accept matching labels, so no need to update */
1253}
1254
1255static void
1256biba_ipq_create(struct mbuf *m, struct label *mlabel, struct ipq *q,
1257    struct label *qlabel)
1258{
1259	struct mac_biba *source, *dest;
1260
1261	source = SLOT(mlabel);
1262	dest = SLOT(qlabel);
1263
1264	biba_copy_effective(source, dest);
1265}
1266
1267static int
1268biba_ipq_match(struct mbuf *m, struct label *mlabel, struct ipq *q,
1269    struct label *qlabel)
1270{
1271	struct mac_biba *a, *b;
1272
1273	a = SLOT(qlabel);
1274	b = SLOT(mlabel);
1275
1276	return (biba_equal_effective(a, b));
1277}
1278
1279static void
1280biba_ipq_reassemble(struct ipq *q, struct label *qlabel, struct mbuf *m,
1281    struct label *mlabel)
1282{
1283	struct mac_biba *source, *dest;
1284
1285	source = SLOT(qlabel);
1286	dest = SLOT(mlabel);
1287
1288	/* Just use the head, since we require them all to match. */
1289	biba_copy_effective(source, dest);
1290}
1291
1292static void
1293biba_ipq_update(struct mbuf *m, struct label *mlabel, struct ipq *q,
1294    struct label *qlabel)
1295{
1296
1297	/* NOOP: we only accept matching labels, so no need to update */
1298}
1299
1300static int
1301biba_kld_check_load(struct ucred *cred, struct vnode *vp,
1302    struct label *vplabel)
1303{
1304	struct mac_biba *subj, *obj;
1305	int error;
1306
1307	if (!biba_enabled)
1308		return (0);
1309
1310	subj = SLOT(cred->cr_label);
1311
1312	error = biba_subject_privileged(subj);
1313	if (error)
1314		return (error);
1315
1316	obj = SLOT(vplabel);
1317	if (!biba_high_effective(obj))
1318		return (EACCES);
1319
1320	return (0);
1321}
1322
1323static int
1324biba_mount_check_stat(struct ucred *cred, struct mount *mp,
1325    struct label *mplabel)
1326{
1327	struct mac_biba *subj, *obj;
1328
1329	if (!biba_enabled)
1330		return (0);
1331
1332	subj = SLOT(cred->cr_label);
1333	obj = SLOT(mplabel);
1334
1335	if (!biba_dominate_effective(obj, subj))
1336		return (EACCES);
1337
1338	return (0);
1339}
1340
1341static void
1342biba_mount_create(struct ucred *cred, struct mount *mp,
1343    struct label *mplabel)
1344{
1345	struct mac_biba *source, *dest;
1346
1347	source = SLOT(cred->cr_label);
1348	dest = SLOT(mplabel);
1349
1350	biba_copy_effective(source, dest);
1351}
1352
1353static void
1354biba_netinet_arp_send(struct ifnet *ifp, struct label *ifplabel,
1355    struct mbuf *m, struct label *mlabel)
1356{
1357	struct mac_biba *dest;
1358
1359	dest = SLOT(mlabel);
1360
1361	biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1362}
1363
1364static void
1365biba_netinet_firewall_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1366    struct mbuf *msend, struct label *msendlabel)
1367{
1368	struct mac_biba *source, *dest;
1369
1370	source = SLOT(mrecvlabel);
1371	dest = SLOT(msendlabel);
1372
1373	biba_copy_effective(source, dest);
1374}
1375
1376static void
1377biba_netinet_firewall_send(struct mbuf *m, struct label *mlabel)
1378{
1379	struct mac_biba *dest;
1380
1381	dest = SLOT(mlabel);
1382
1383	/* XXX: where is the label for the firewall really coming from? */
1384	biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1385}
1386
1387static void
1388biba_netinet_fragment(struct mbuf *m, struct label *mlabel,
1389    struct mbuf *frag, struct label *fraglabel)
1390{
1391	struct mac_biba *source, *dest;
1392
1393	source = SLOT(mlabel);
1394	dest = SLOT(fraglabel);
1395
1396	biba_copy_effective(source, dest);
1397}
1398
1399static void
1400biba_netinet_icmp_reply(struct mbuf *mrecv, struct label *mrecvlabel,
1401    struct mbuf *msend, struct label *msendlabel)
1402{
1403	struct mac_biba *source, *dest;
1404
1405	source = SLOT(mrecvlabel);
1406	dest = SLOT(msendlabel);
1407
1408	biba_copy_effective(source, dest);
1409}
1410
1411static void
1412biba_netinet_igmp_send(struct ifnet *ifp, struct label *ifplabel,
1413    struct mbuf *m, struct label *mlabel)
1414{
1415	struct mac_biba *dest;
1416
1417	dest = SLOT(mlabel);
1418
1419	biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1420}
1421
1422static void
1423biba_netinet6_nd6_send(struct ifnet *ifp, struct label *ifplabel,
1424    struct mbuf *m, struct label *mlabel)
1425{
1426	struct mac_biba *dest;
1427
1428	dest = SLOT(mlabel);
1429
1430	biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1431}
1432
1433static int
1434biba_pipe_check_ioctl(struct ucred *cred, struct pipepair *pp,
1435    struct label *pplabel, unsigned long cmd, void /* caddr_t */ *data)
1436{
1437
1438	if(!biba_enabled)
1439		return (0);
1440
1441	/* XXX: This will be implemented soon... */
1442
1443	return (0);
1444}
1445
1446static int
1447biba_pipe_check_poll(struct ucred *cred, struct pipepair *pp,
1448    struct label *pplabel)
1449{
1450	struct mac_biba *subj, *obj;
1451
1452	if (!biba_enabled)
1453		return (0);
1454
1455	subj = SLOT(cred->cr_label);
1456	obj = SLOT(pplabel);
1457
1458	if (!biba_dominate_effective(obj, subj))
1459		return (EACCES);
1460
1461	return (0);
1462}
1463
1464static int
1465biba_pipe_check_read(struct ucred *cred, struct pipepair *pp,
1466    struct label *pplabel)
1467{
1468	struct mac_biba *subj, *obj;
1469
1470	if (!biba_enabled)
1471		return (0);
1472
1473	subj = SLOT(cred->cr_label);
1474	obj = SLOT(pplabel);
1475
1476	if (!biba_dominate_effective(obj, subj))
1477		return (EACCES);
1478
1479	return (0);
1480}
1481
1482static int
1483biba_pipe_check_relabel(struct ucred *cred, struct pipepair *pp,
1484    struct label *pplabel, struct label *newlabel)
1485{
1486	struct mac_biba *subj, *obj, *new;
1487	int error;
1488
1489	new = SLOT(newlabel);
1490	subj = SLOT(cred->cr_label);
1491	obj = SLOT(pplabel);
1492
1493	/*
1494	 * If there is a Biba label update for a pipe, it must be a effective
1495	 * update.
1496	 */
1497	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
1498	if (error)
1499		return (error);
1500
1501	/*
1502	 * To perform a relabel of a pipe (Biba label or not), Biba must
1503	 * authorize the relabel.
1504	 */
1505	if (!biba_effective_in_range(obj, subj))
1506		return (EPERM);
1507
1508	/*
1509	 * If the Biba label is to be changed, authorize as appropriate.
1510	 */
1511	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
1512		/*
1513		 * To change the Biba label on a pipe, the new pipe label
1514		 * must be in the subject range.
1515		 */
1516		if (!biba_effective_in_range(new, subj))
1517			return (EPERM);
1518
1519		/*
1520		 * To change the Biba label on a pipe to be EQUAL, the
1521		 * subject must have appropriate privilege.
1522		 */
1523		if (biba_contains_equal(new)) {
1524			error = biba_subject_privileged(subj);
1525			if (error)
1526				return (error);
1527		}
1528	}
1529
1530	return (0);
1531}
1532
1533static int
1534biba_pipe_check_stat(struct ucred *cred, struct pipepair *pp,
1535    struct label *pplabel)
1536{
1537	struct mac_biba *subj, *obj;
1538
1539	if (!biba_enabled)
1540		return (0);
1541
1542	subj = SLOT(cred->cr_label);
1543	obj = SLOT(pplabel);
1544
1545	if (!biba_dominate_effective(obj, subj))
1546		return (EACCES);
1547
1548	return (0);
1549}
1550
1551static int
1552biba_pipe_check_write(struct ucred *cred, struct pipepair *pp,
1553    struct label *pplabel)
1554{
1555	struct mac_biba *subj, *obj;
1556
1557	if (!biba_enabled)
1558		return (0);
1559
1560	subj = SLOT(cred->cr_label);
1561	obj = SLOT(pplabel);
1562
1563	if (!biba_dominate_effective(subj, obj))
1564		return (EACCES);
1565
1566	return (0);
1567}
1568
1569static void
1570biba_pipe_create(struct ucred *cred, struct pipepair *pp,
1571    struct label *pplabel)
1572{
1573	struct mac_biba *source, *dest;
1574
1575	source = SLOT(cred->cr_label);
1576	dest = SLOT(pplabel);
1577
1578	biba_copy_effective(source, dest);
1579}
1580
1581static void
1582biba_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1583    struct label *pplabel, struct label *newlabel)
1584{
1585	struct mac_biba *source, *dest;
1586
1587	source = SLOT(newlabel);
1588	dest = SLOT(pplabel);
1589
1590	biba_copy(source, dest);
1591}
1592
1593static int
1594biba_posixsem_check_openunlink(struct ucred *cred, struct ksem *ks,
1595    struct label *kslabel)
1596{
1597	struct mac_biba *subj, *obj;
1598
1599	if (!biba_enabled)
1600		return (0);
1601
1602	subj = SLOT(cred->cr_label);
1603	obj = SLOT(kslabel);
1604
1605	if (!biba_dominate_effective(subj, obj))
1606		return (EACCES);
1607
1608	return (0);
1609}
1610
1611static int
1612biba_posixsem_check_setmode(struct ucred *cred, struct ksem *ks,
1613    struct label *kslabel, mode_t mode)
1614{
1615	struct mac_biba *subj, *obj;
1616
1617	if (!biba_enabled)
1618		return (0);
1619
1620	subj = SLOT(cred->cr_label);
1621	obj = SLOT(kslabel);
1622
1623	if (!biba_dominate_effective(subj, obj))
1624		return (EACCES);
1625
1626	return (0);
1627}
1628
1629static int
1630biba_posixsem_check_setowner(struct ucred *cred, struct ksem *ks,
1631    struct label *kslabel, uid_t uid, gid_t gid)
1632{
1633	struct mac_biba *subj, *obj;
1634
1635	if (!biba_enabled)
1636		return (0);
1637
1638	subj = SLOT(cred->cr_label);
1639	obj = SLOT(kslabel);
1640
1641	if (!biba_dominate_effective(subj, obj))
1642		return (EACCES);
1643
1644	return (0);
1645}
1646
1647static int
1648biba_posixsem_check_write(struct ucred *active_cred, struct ucred *file_cred,
1649    struct ksem *ks, struct label *kslabel)
1650{
1651	struct mac_biba *subj, *obj;
1652
1653	if (!biba_enabled)
1654		return (0);
1655
1656	subj = SLOT(active_cred->cr_label);
1657	obj = SLOT(kslabel);
1658
1659	if (!biba_dominate_effective(subj, obj))
1660		return (EACCES);
1661
1662	return (0);
1663}
1664
1665static int
1666biba_posixsem_check_rdonly(struct ucred *active_cred, struct ucred *file_cred,
1667    struct ksem *ks, struct label *kslabel)
1668{
1669	struct mac_biba *subj, *obj;
1670
1671	if (!biba_enabled)
1672		return (0);
1673
1674	subj = SLOT(active_cred->cr_label);
1675	obj = SLOT(kslabel);
1676
1677	if (!biba_dominate_effective(obj, subj))
1678		return (EACCES);
1679
1680	return (0);
1681}
1682
1683static void
1684biba_posixsem_create(struct ucred *cred, struct ksem *ks,
1685    struct label *kslabel)
1686{
1687	struct mac_biba *source, *dest;
1688
1689	source = SLOT(cred->cr_label);
1690	dest = SLOT(kslabel);
1691
1692	biba_copy_effective(source, dest);
1693}
1694
1695static int
1696biba_posixshm_check_mmap(struct ucred *cred, struct shmfd *shmfd,
1697    struct label *shmlabel, int prot, int flags)
1698{
1699	struct mac_biba *subj, *obj;
1700
1701	if (!biba_enabled || !revocation_enabled)
1702		return (0);
1703
1704	subj = SLOT(cred->cr_label);
1705	obj = SLOT(shmlabel);
1706
1707	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
1708		if (!biba_dominate_effective(obj, subj))
1709			return (EACCES);
1710	}
1711	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
1712		if (!biba_dominate_effective(subj, obj))
1713			return (EACCES);
1714	}
1715
1716	return (0);
1717}
1718
1719static int
1720biba_posixshm_check_open(struct ucred *cred, struct shmfd *shmfd,
1721    struct label *shmlabel, accmode_t accmode)
1722{
1723	struct mac_biba *subj, *obj;
1724
1725	if (!biba_enabled)
1726		return (0);
1727
1728	subj = SLOT(cred->cr_label);
1729	obj = SLOT(shmlabel);
1730
1731	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
1732		if (!biba_dominate_effective(obj, subj))
1733			return (EACCES);
1734	}
1735	if (accmode & VMODIFY_PERMS) {
1736		if (!biba_dominate_effective(subj, obj))
1737			return (EACCES);
1738	}
1739
1740	return (0);
1741}
1742
1743static int
1744biba_posixshm_check_read(struct ucred *active_cred, struct ucred *file_cred,
1745    struct shmfd *vp, struct label *shmlabel)
1746{
1747	struct mac_biba *subj, *obj;
1748
1749	if (!biba_enabled || !revocation_enabled)
1750		return (0);
1751
1752	subj = SLOT(active_cred->cr_label);
1753	obj = SLOT(shmlabel);
1754
1755	if (!biba_dominate_effective(obj, subj))
1756		return (EACCES);
1757
1758	return (0);
1759}
1760
1761static int
1762biba_posixshm_check_setmode(struct ucred *cred, struct shmfd *shmfd,
1763    struct label *shmlabel, mode_t mode)
1764{
1765	struct mac_biba *subj, *obj;
1766
1767	if (!biba_enabled)
1768		return (0);
1769
1770	subj = SLOT(cred->cr_label);
1771	obj = SLOT(shmlabel);
1772
1773	if (!biba_dominate_effective(subj, obj))
1774		return (EACCES);
1775
1776	return (0);
1777}
1778
1779static int
1780biba_posixshm_check_setowner(struct ucred *cred, struct shmfd *shmfd,
1781    struct label *shmlabel, uid_t uid, gid_t gid)
1782{
1783	struct mac_biba *subj, *obj;
1784
1785	if (!biba_enabled)
1786		return (0);
1787
1788	subj = SLOT(cred->cr_label);
1789	obj = SLOT(shmlabel);
1790
1791	if (!biba_dominate_effective(subj, obj))
1792		return (EACCES);
1793
1794	return (0);
1795}
1796
1797static int
1798biba_posixshm_check_stat(struct ucred *active_cred, struct ucred *file_cred,
1799    struct shmfd *shmfd, struct label *shmlabel)
1800{
1801	struct mac_biba *subj, *obj;
1802
1803	if (!biba_enabled)
1804		return (0);
1805
1806	subj = SLOT(active_cred->cr_label);
1807	obj = SLOT(shmlabel);
1808
1809	if (!biba_dominate_effective(obj, subj))
1810		return (EACCES);
1811
1812	return (0);
1813}
1814
1815static int
1816biba_posixshm_check_truncate(struct ucred *active_cred,
1817    struct ucred *file_cred, struct shmfd *shmfd, struct label *shmlabel)
1818{
1819	struct mac_biba *subj, *obj;
1820
1821	if (!biba_enabled)
1822		return (0);
1823
1824	subj = SLOT(active_cred->cr_label);
1825	obj = SLOT(shmlabel);
1826
1827	if (!biba_dominate_effective(subj, obj))
1828		return (EACCES);
1829
1830	return (0);
1831}
1832
1833static int
1834biba_posixshm_check_unlink(struct ucred *cred, struct shmfd *shmfd,
1835    struct label *shmlabel)
1836{
1837	struct mac_biba *subj, *obj;
1838
1839	if (!biba_enabled)
1840		return (0);
1841
1842	subj = SLOT(cred->cr_label);
1843	obj = SLOT(shmlabel);
1844
1845	if (!biba_dominate_effective(subj, obj))
1846		return (EACCES);
1847
1848	return (0);
1849}
1850
1851static int
1852biba_posixshm_check_write(struct ucred *active_cred, struct ucred *file_cred,
1853    struct shmfd *vp, struct label *shmlabel)
1854{
1855	struct mac_biba *subj, *obj;
1856
1857	if (!biba_enabled || !revocation_enabled)
1858		return (0);
1859
1860	subj = SLOT(active_cred->cr_label);
1861	obj = SLOT(shmlabel);
1862
1863	if (!biba_dominate_effective(obj, subj))
1864		return (EACCES);
1865
1866	return (0);
1867}
1868
1869static void
1870biba_posixshm_create(struct ucred *cred, struct shmfd *shmfd,
1871    struct label *shmlabel)
1872{
1873	struct mac_biba *source, *dest;
1874
1875	source = SLOT(cred->cr_label);
1876	dest = SLOT(shmlabel);
1877
1878	biba_copy_effective(source, dest);
1879}
1880
1881/*
1882 * Some system privileges are allowed regardless of integrity grade; others
1883 * are allowed only when running with privilege with respect to the Biba
1884 * policy as they might otherwise allow bypassing of the integrity policy.
1885 */
1886static int
1887biba_priv_check(struct ucred *cred, int priv)
1888{
1889	struct mac_biba *subj;
1890	int error;
1891
1892	if (!biba_enabled)
1893		return (0);
1894
1895	/*
1896	 * Exempt only specific privileges from the Biba integrity policy.
1897	 */
1898	switch (priv) {
1899	case PRIV_KTRACE:
1900	case PRIV_MSGBUF:
1901
1902	/*
1903	 * Allow processes to manipulate basic process audit properties, and
1904	 * to submit audit records.
1905	 */
1906	case PRIV_AUDIT_GETAUDIT:
1907	case PRIV_AUDIT_SETAUDIT:
1908	case PRIV_AUDIT_SUBMIT:
1909
1910	/*
1911	 * Allow processes to manipulate their regular UNIX credentials.
1912	 */
1913	case PRIV_CRED_SETUID:
1914	case PRIV_CRED_SETEUID:
1915	case PRIV_CRED_SETGID:
1916	case PRIV_CRED_SETEGID:
1917	case PRIV_CRED_SETGROUPS:
1918	case PRIV_CRED_SETREUID:
1919	case PRIV_CRED_SETREGID:
1920	case PRIV_CRED_SETRESUID:
1921	case PRIV_CRED_SETRESGID:
1922
1923	/*
1924	 * Allow processes to perform system monitoring.
1925	 */
1926	case PRIV_SEEOTHERGIDS:
1927	case PRIV_SEEOTHERUIDS:
1928		break;
1929
1930	/*
1931	 * Allow access to general process debugging facilities.  We
1932	 * separately control debugging based on MAC label.
1933	 */
1934	case PRIV_DEBUG_DIFFCRED:
1935	case PRIV_DEBUG_SUGID:
1936	case PRIV_DEBUG_UNPRIV:
1937
1938	/*
1939	 * Allow manipulating jails.
1940	 */
1941	case PRIV_JAIL_ATTACH:
1942
1943	/*
1944	 * Allow privilege with respect to the Partition policy, but not the
1945	 * Privs policy.
1946	 */
1947	case PRIV_MAC_PARTITION:
1948
1949	/*
1950	 * Allow privilege with respect to process resource limits and login
1951	 * context.
1952	 */
1953	case PRIV_PROC_LIMIT:
1954	case PRIV_PROC_SETLOGIN:
1955	case PRIV_PROC_SETRLIMIT:
1956
1957	/*
1958	 * Allow System V and POSIX IPC privileges.
1959	 */
1960	case PRIV_IPC_READ:
1961	case PRIV_IPC_WRITE:
1962	case PRIV_IPC_ADMIN:
1963	case PRIV_IPC_MSGSIZE:
1964	case PRIV_MQ_ADMIN:
1965
1966	/*
1967	 * Allow certain scheduler manipulations -- possibly this should be
1968	 * controlled by more fine-grained policy, as potentially low
1969	 * integrity processes can deny CPU to higher integrity ones.
1970	 */
1971	case PRIV_SCHED_DIFFCRED:
1972	case PRIV_SCHED_SETPRIORITY:
1973	case PRIV_SCHED_RTPRIO:
1974	case PRIV_SCHED_SETPOLICY:
1975	case PRIV_SCHED_SET:
1976	case PRIV_SCHED_SETPARAM:
1977
1978	/*
1979	 * More IPC privileges.
1980	 */
1981	case PRIV_SEM_WRITE:
1982
1983	/*
1984	 * Allow signaling privileges subject to integrity policy.
1985	 */
1986	case PRIV_SIGNAL_DIFFCRED:
1987	case PRIV_SIGNAL_SUGID:
1988
1989	/*
1990	 * Allow access to only limited sysctls from lower integrity levels;
1991	 * piggy-back on the Jail definition.
1992	 */
1993	case PRIV_SYSCTL_WRITEJAIL:
1994
1995	/*
1996	 * Allow TTY-based privileges, subject to general device access using
1997	 * labels on TTY device nodes, but not console privilege.
1998	 */
1999	case PRIV_TTY_DRAINWAIT:
2000	case PRIV_TTY_DTRWAIT:
2001	case PRIV_TTY_EXCLUSIVE:
2002	case PRIV_TTY_STI:
2003	case PRIV_TTY_SETA:
2004
2005	/*
2006	 * Grant most VFS privileges, as almost all are in practice bounded
2007	 * by more specific checks using labels.
2008	 */
2009	case PRIV_VFS_READ:
2010	case PRIV_VFS_WRITE:
2011	case PRIV_VFS_ADMIN:
2012	case PRIV_VFS_EXEC:
2013	case PRIV_VFS_LOOKUP:
2014	case PRIV_VFS_CHFLAGS_DEV:
2015	case PRIV_VFS_CHOWN:
2016	case PRIV_VFS_CHROOT:
2017	case PRIV_VFS_RETAINSUGID:
2018	case PRIV_VFS_EXCEEDQUOTA:
2019	case PRIV_VFS_FCHROOT:
2020	case PRIV_VFS_FHOPEN:
2021	case PRIV_VFS_FHSTATFS:
2022	case PRIV_VFS_GENERATION:
2023	case PRIV_VFS_GETFH:
2024	case PRIV_VFS_GETQUOTA:
2025	case PRIV_VFS_LINK:
2026	case PRIV_VFS_MOUNT:
2027	case PRIV_VFS_MOUNT_OWNER:
2028	case PRIV_VFS_MOUNT_PERM:
2029	case PRIV_VFS_MOUNT_SUIDDIR:
2030	case PRIV_VFS_MOUNT_NONUSER:
2031	case PRIV_VFS_SETGID:
2032	case PRIV_VFS_STICKYFILE:
2033	case PRIV_VFS_SYSFLAGS:
2034	case PRIV_VFS_UNMOUNT:
2035
2036	/*
2037	 * Allow VM privileges; it would be nice if these were subject to
2038	 * resource limits.
2039	 */
2040	case PRIV_VM_MADV_PROTECT:
2041	case PRIV_VM_MLOCK:
2042	case PRIV_VM_MUNLOCK:
2043	case PRIV_VM_SWAP_NOQUOTA:
2044	case PRIV_VM_SWAP_NORLIMIT:
2045
2046	/*
2047	 * Allow some but not all network privileges.  In general, dont allow
2048	 * reconfiguring the network stack, just normal use.
2049	 */
2050	case PRIV_NETINET_RESERVEDPORT:
2051	case PRIV_NETINET_RAW:
2052	case PRIV_NETINET_REUSEPORT:
2053		break;
2054
2055	/*
2056	 * All remaining system privileges are allow only if the process
2057	 * holds privilege with respect to the Biba policy.
2058	 */
2059	default:
2060		subj = SLOT(cred->cr_label);
2061		error = biba_subject_privileged(subj);
2062		if (error)
2063			return (error);
2064	}
2065	return (0);
2066}
2067
2068static int
2069biba_proc_check_debug(struct ucred *cred, struct proc *p)
2070{
2071	struct mac_biba *subj, *obj;
2072
2073	if (!biba_enabled)
2074		return (0);
2075
2076	subj = SLOT(cred->cr_label);
2077	obj = SLOT(p->p_ucred->cr_label);
2078
2079	/* XXX: range checks */
2080	if (!biba_dominate_effective(obj, subj))
2081		return (ESRCH);
2082	if (!biba_dominate_effective(subj, obj))
2083		return (EACCES);
2084
2085	return (0);
2086}
2087
2088static int
2089biba_proc_check_sched(struct ucred *cred, struct proc *p)
2090{
2091	struct mac_biba *subj, *obj;
2092
2093	if (!biba_enabled)
2094		return (0);
2095
2096	subj = SLOT(cred->cr_label);
2097	obj = SLOT(p->p_ucred->cr_label);
2098
2099	/* XXX: range checks */
2100	if (!biba_dominate_effective(obj, subj))
2101		return (ESRCH);
2102	if (!biba_dominate_effective(subj, obj))
2103		return (EACCES);
2104
2105	return (0);
2106}
2107
2108static int
2109biba_proc_check_signal(struct ucred *cred, struct proc *p, int signum)
2110{
2111	struct mac_biba *subj, *obj;
2112
2113	if (!biba_enabled)
2114		return (0);
2115
2116	subj = SLOT(cred->cr_label);
2117	obj = SLOT(p->p_ucred->cr_label);
2118
2119	/* XXX: range checks */
2120	if (!biba_dominate_effective(obj, subj))
2121		return (ESRCH);
2122	if (!biba_dominate_effective(subj, obj))
2123		return (EACCES);
2124
2125	return (0);
2126}
2127
2128static int
2129biba_socket_check_deliver(struct socket *so, struct label *solabel,
2130    struct mbuf *m, struct label *mlabel)
2131{
2132	struct mac_biba *p, *s;
2133	int error;
2134
2135	if (!biba_enabled)
2136		return (0);
2137
2138	p = SLOT(mlabel);
2139	s = SLOT(solabel);
2140
2141	SOCK_LOCK(so);
2142	error = biba_equal_effective(p, s) ? 0 : EACCES;
2143	SOCK_UNLOCK(so);
2144	return (error);
2145}
2146
2147static int
2148biba_socket_check_relabel(struct ucred *cred, struct socket *so,
2149    struct label *solabel, struct label *newlabel)
2150{
2151	struct mac_biba *subj, *obj, *new;
2152	int error;
2153
2154	SOCK_LOCK_ASSERT(so);
2155
2156	new = SLOT(newlabel);
2157	subj = SLOT(cred->cr_label);
2158	obj = SLOT(solabel);
2159
2160	/*
2161	 * If there is a Biba label update for the socket, it may be an
2162	 * update of effective.
2163	 */
2164	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2165	if (error)
2166		return (error);
2167
2168	/*
2169	 * To relabel a socket, the old socket effective must be in the
2170	 * subject range.
2171	 */
2172	if (!biba_effective_in_range(obj, subj))
2173		return (EPERM);
2174
2175	/*
2176	 * If the Biba label is to be changed, authorize as appropriate.
2177	 */
2178	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2179		/*
2180		 * To relabel a socket, the new socket effective must be in
2181		 * the subject range.
2182		 */
2183		if (!biba_effective_in_range(new, subj))
2184			return (EPERM);
2185
2186		/*
2187		 * To change the Biba label on the socket to contain EQUAL,
2188		 * the subject must have appropriate privilege.
2189		 */
2190		if (biba_contains_equal(new)) {
2191			error = biba_subject_privileged(subj);
2192			if (error)
2193				return (error);
2194		}
2195	}
2196
2197	return (0);
2198}
2199
2200static int
2201biba_socket_check_visible(struct ucred *cred, struct socket *so,
2202    struct label *solabel)
2203{
2204	struct mac_biba *subj, *obj;
2205
2206	if (!biba_enabled)
2207		return (0);
2208
2209	subj = SLOT(cred->cr_label);
2210	obj = SLOT(solabel);
2211
2212	SOCK_LOCK(so);
2213	if (!biba_dominate_effective(obj, subj)) {
2214		SOCK_UNLOCK(so);
2215		return (ENOENT);
2216	}
2217	SOCK_UNLOCK(so);
2218
2219	return (0);
2220}
2221
2222static void
2223biba_socket_create(struct ucred *cred, struct socket *so,
2224    struct label *solabel)
2225{
2226	struct mac_biba *source, *dest;
2227
2228	source = SLOT(cred->cr_label);
2229	dest = SLOT(solabel);
2230
2231	biba_copy_effective(source, dest);
2232}
2233
2234static void
2235biba_socket_create_mbuf(struct socket *so, struct label *solabel,
2236    struct mbuf *m, struct label *mlabel)
2237{
2238	struct mac_biba *source, *dest;
2239
2240	source = SLOT(solabel);
2241	dest = SLOT(mlabel);
2242
2243	SOCK_LOCK(so);
2244	biba_copy_effective(source, dest);
2245	SOCK_UNLOCK(so);
2246}
2247
2248static void
2249biba_socket_newconn(struct socket *oldso, struct label *oldsolabel,
2250    struct socket *newso, struct label *newsolabel)
2251{
2252	struct mac_biba source, *dest;
2253
2254	SOCK_LOCK(oldso);
2255	source = *SLOT(oldsolabel);
2256	SOCK_UNLOCK(oldso);
2257
2258	dest = SLOT(newsolabel);
2259
2260	SOCK_LOCK(newso);
2261	biba_copy_effective(&source, dest);
2262	SOCK_UNLOCK(newso);
2263}
2264
2265static void
2266biba_socket_relabel(struct ucred *cred, struct socket *so,
2267    struct label *solabel, struct label *newlabel)
2268{
2269	struct mac_biba *source, *dest;
2270
2271	SOCK_LOCK_ASSERT(so);
2272
2273	source = SLOT(newlabel);
2274	dest = SLOT(solabel);
2275
2276	biba_copy(source, dest);
2277}
2278
2279static void
2280biba_socketpeer_set_from_mbuf(struct mbuf *m, struct label *mlabel,
2281    struct socket *so, struct label *sopeerlabel)
2282{
2283	struct mac_biba *source, *dest;
2284
2285	source = SLOT(mlabel);
2286	dest = SLOT(sopeerlabel);
2287
2288	SOCK_LOCK(so);
2289	biba_copy_effective(source, dest);
2290	SOCK_UNLOCK(so);
2291}
2292
2293static void
2294biba_socketpeer_set_from_socket(struct socket *oldso,
2295    struct label *oldsolabel, struct socket *newso,
2296    struct label *newsopeerlabel)
2297{
2298	struct mac_biba source, *dest;
2299
2300	SOCK_LOCK(oldso);
2301	source = *SLOT(oldsolabel);
2302	SOCK_UNLOCK(oldso);
2303	dest = SLOT(newsopeerlabel);
2304
2305	SOCK_LOCK(newso);
2306	biba_copy_effective(&source, dest);
2307	SOCK_UNLOCK(newso);
2308}
2309
2310static void
2311biba_syncache_create(struct label *label, struct inpcb *inp)
2312{
2313	struct mac_biba *source, *dest;
2314
2315	source = SLOT(inp->inp_label);
2316	dest = SLOT(label);
2317	biba_copy_effective(source, dest);
2318}
2319
2320static void
2321biba_syncache_create_mbuf(struct label *sc_label, struct mbuf *m,
2322    struct label *mlabel)
2323{
2324	struct mac_biba *source, *dest;
2325
2326	source = SLOT(sc_label);
2327	dest = SLOT(mlabel);
2328	biba_copy_effective(source, dest);
2329}
2330
2331static int
2332biba_system_check_acct(struct ucred *cred, struct vnode *vp,
2333    struct label *vplabel)
2334{
2335	struct mac_biba *subj, *obj;
2336	int error;
2337
2338	if (!biba_enabled)
2339		return (0);
2340
2341	subj = SLOT(cred->cr_label);
2342
2343	error = biba_subject_privileged(subj);
2344	if (error)
2345		return (error);
2346
2347	if (vplabel == NULL)
2348		return (0);
2349
2350	obj = SLOT(vplabel);
2351	if (!biba_high_effective(obj))
2352		return (EACCES);
2353
2354	return (0);
2355}
2356
2357static int
2358biba_system_check_auditctl(struct ucred *cred, struct vnode *vp,
2359    struct label *vplabel)
2360{
2361	struct mac_biba *subj, *obj;
2362	int error;
2363
2364	if (!biba_enabled)
2365		return (0);
2366
2367	subj = SLOT(cred->cr_label);
2368
2369	error = biba_subject_privileged(subj);
2370	if (error)
2371		return (error);
2372
2373	if (vplabel == NULL)
2374		return (0);
2375
2376	obj = SLOT(vplabel);
2377	if (!biba_high_effective(obj))
2378		return (EACCES);
2379
2380	return (0);
2381}
2382
2383static int
2384biba_system_check_auditon(struct ucred *cred, int cmd)
2385{
2386	struct mac_biba *subj;
2387	int error;
2388
2389	if (!biba_enabled)
2390		return (0);
2391
2392	subj = SLOT(cred->cr_label);
2393
2394	error = biba_subject_privileged(subj);
2395	if (error)
2396		return (error);
2397
2398	return (0);
2399}
2400
2401static int
2402biba_system_check_swapoff(struct ucred *cred, struct vnode *vp,
2403    struct label *label)
2404{
2405	struct mac_biba *subj;
2406	int error;
2407
2408	if (!biba_enabled)
2409		return (0);
2410
2411	subj = SLOT(cred->cr_label);
2412
2413	error = biba_subject_privileged(subj);
2414	if (error)
2415		return (error);
2416
2417	return (0);
2418}
2419
2420static int
2421biba_system_check_swapon(struct ucred *cred, struct vnode *vp,
2422    struct label *vplabel)
2423{
2424	struct mac_biba *subj, *obj;
2425	int error;
2426
2427	if (!biba_enabled)
2428		return (0);
2429
2430	subj = SLOT(cred->cr_label);
2431	obj = SLOT(vplabel);
2432
2433	error = biba_subject_privileged(subj);
2434	if (error)
2435		return (error);
2436
2437	if (!biba_high_effective(obj))
2438		return (EACCES);
2439
2440	return (0);
2441}
2442
2443static int
2444biba_system_check_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2445    void *arg1, int arg2, struct sysctl_req *req)
2446{
2447	struct mac_biba *subj;
2448	int error;
2449
2450	if (!biba_enabled)
2451		return (0);
2452
2453	subj = SLOT(cred->cr_label);
2454
2455	/*
2456	 * Treat sysctl variables without CTLFLAG_ANYBODY flag as biba/high,
2457	 * but also require privilege to change them.
2458	 */
2459	if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2460		if (!biba_subject_dominate_high(subj))
2461			return (EACCES);
2462
2463		error = biba_subject_privileged(subj);
2464		if (error)
2465			return (error);
2466	}
2467
2468	return (0);
2469}
2470
2471static void
2472biba_sysvmsg_cleanup(struct label *msglabel)
2473{
2474
2475	bzero(SLOT(msglabel), sizeof(struct mac_biba));
2476}
2477
2478static void
2479biba_sysvmsg_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2480    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
2481{
2482	struct mac_biba *source, *dest;
2483
2484	/* Ignore the msgq label */
2485	source = SLOT(cred->cr_label);
2486	dest = SLOT(msglabel);
2487
2488	biba_copy_effective(source, dest);
2489}
2490
2491static int
2492biba_sysvmsq_check_msgrcv(struct ucred *cred, struct msg *msgptr,
2493    struct label *msglabel)
2494{
2495	struct mac_biba *subj, *obj;
2496
2497	if (!biba_enabled)
2498		return (0);
2499
2500	subj = SLOT(cred->cr_label);
2501	obj = SLOT(msglabel);
2502
2503	if (!biba_dominate_effective(obj, subj))
2504		return (EACCES);
2505
2506	return (0);
2507}
2508
2509static int
2510biba_sysvmsq_check_msgrmid(struct ucred *cred, struct msg *msgptr,
2511    struct label *msglabel)
2512{
2513	struct mac_biba *subj, *obj;
2514
2515	if (!biba_enabled)
2516		return (0);
2517
2518	subj = SLOT(cred->cr_label);
2519	obj = SLOT(msglabel);
2520
2521	if (!biba_dominate_effective(subj, obj))
2522		return (EACCES);
2523
2524	return (0);
2525}
2526
2527static int
2528biba_sysvmsq_check_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
2529    struct label *msqklabel)
2530{
2531	struct mac_biba *subj, *obj;
2532
2533	if (!biba_enabled)
2534		return (0);
2535
2536	subj = SLOT(cred->cr_label);
2537	obj = SLOT(msqklabel);
2538
2539	if (!biba_dominate_effective(obj, subj))
2540		return (EACCES);
2541
2542	return (0);
2543}
2544
2545static int
2546biba_sysvmsq_check_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
2547    struct label *msqklabel)
2548{
2549	struct mac_biba *subj, *obj;
2550
2551	if (!biba_enabled)
2552		return (0);
2553
2554	subj = SLOT(cred->cr_label);
2555	obj = SLOT(msqklabel);
2556
2557	if (!biba_dominate_effective(subj, obj))
2558		return (EACCES);
2559
2560	return (0);
2561}
2562
2563static int
2564biba_sysvmsq_check_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
2565    struct label *msqklabel)
2566{
2567	struct mac_biba *subj, *obj;
2568
2569	if (!biba_enabled)
2570		return (0);
2571
2572	subj = SLOT(cred->cr_label);
2573	obj = SLOT(msqklabel);
2574
2575	if (!biba_dominate_effective(obj, subj))
2576		return (EACCES);
2577
2578	return (0);
2579}
2580
2581static int
2582biba_sysvmsq_check_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
2583    struct label *msqklabel, int cmd)
2584{
2585	struct mac_biba *subj, *obj;
2586
2587	if (!biba_enabled)
2588		return (0);
2589
2590	subj = SLOT(cred->cr_label);
2591	obj = SLOT(msqklabel);
2592
2593	switch(cmd) {
2594	case IPC_RMID:
2595	case IPC_SET:
2596		if (!biba_dominate_effective(subj, obj))
2597			return (EACCES);
2598		break;
2599
2600	case IPC_STAT:
2601		if (!biba_dominate_effective(obj, subj))
2602			return (EACCES);
2603		break;
2604
2605	default:
2606		return (EACCES);
2607	}
2608
2609	return (0);
2610}
2611
2612static void
2613biba_sysvmsq_cleanup(struct label *msqlabel)
2614{
2615
2616	bzero(SLOT(msqlabel), sizeof(struct mac_biba));
2617}
2618
2619static void
2620biba_sysvmsq_create(struct ucred *cred, struct msqid_kernel *msqkptr,
2621    struct label *msqlabel)
2622{
2623	struct mac_biba *source, *dest;
2624
2625	source = SLOT(cred->cr_label);
2626	dest = SLOT(msqlabel);
2627
2628	biba_copy_effective(source, dest);
2629}
2630
2631static int
2632biba_sysvsem_check_semctl(struct ucred *cred, struct semid_kernel *semakptr,
2633    struct label *semaklabel, int cmd)
2634{
2635	struct mac_biba *subj, *obj;
2636
2637	if (!biba_enabled)
2638		return (0);
2639
2640	subj = SLOT(cred->cr_label);
2641	obj = SLOT(semaklabel);
2642
2643	switch(cmd) {
2644	case IPC_RMID:
2645	case IPC_SET:
2646	case SETVAL:
2647	case SETALL:
2648		if (!biba_dominate_effective(subj, obj))
2649			return (EACCES);
2650		break;
2651
2652	case IPC_STAT:
2653	case GETVAL:
2654	case GETPID:
2655	case GETNCNT:
2656	case GETZCNT:
2657	case GETALL:
2658		if (!biba_dominate_effective(obj, subj))
2659			return (EACCES);
2660		break;
2661
2662	default:
2663		return (EACCES);
2664	}
2665
2666	return (0);
2667}
2668
2669static int
2670biba_sysvsem_check_semget(struct ucred *cred, struct semid_kernel *semakptr,
2671    struct label *semaklabel)
2672{
2673	struct mac_biba *subj, *obj;
2674
2675	if (!biba_enabled)
2676		return (0);
2677
2678	subj = SLOT(cred->cr_label);
2679	obj = SLOT(semaklabel);
2680
2681	if (!biba_dominate_effective(obj, subj))
2682		return (EACCES);
2683
2684	return (0);
2685}
2686
2687static int
2688biba_sysvsem_check_semop(struct ucred *cred, struct semid_kernel *semakptr,
2689    struct label *semaklabel, size_t accesstype)
2690{
2691	struct mac_biba *subj, *obj;
2692
2693	if (!biba_enabled)
2694		return (0);
2695
2696	subj = SLOT(cred->cr_label);
2697	obj = SLOT(semaklabel);
2698
2699	if (accesstype & SEM_R)
2700		if (!biba_dominate_effective(obj, subj))
2701			return (EACCES);
2702
2703	if (accesstype & SEM_A)
2704		if (!biba_dominate_effective(subj, obj))
2705			return (EACCES);
2706
2707	return (0);
2708}
2709
2710static void
2711biba_sysvsem_cleanup(struct label *semalabel)
2712{
2713
2714	bzero(SLOT(semalabel), sizeof(struct mac_biba));
2715}
2716
2717static void
2718biba_sysvsem_create(struct ucred *cred, struct semid_kernel *semakptr,
2719    struct label *semalabel)
2720{
2721	struct mac_biba *source, *dest;
2722
2723	source = SLOT(cred->cr_label);
2724	dest = SLOT(semalabel);
2725
2726	biba_copy_effective(source, dest);
2727}
2728
2729static int
2730biba_sysvshm_check_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
2731    struct label *shmseglabel, int shmflg)
2732{
2733	struct mac_biba *subj, *obj;
2734
2735	if (!biba_enabled)
2736		return (0);
2737
2738	subj = SLOT(cred->cr_label);
2739	obj = SLOT(shmseglabel);
2740
2741	if (!biba_dominate_effective(obj, subj))
2742		return (EACCES);
2743	if ((shmflg & SHM_RDONLY) == 0) {
2744		if (!biba_dominate_effective(subj, obj))
2745			return (EACCES);
2746	}
2747
2748	return (0);
2749}
2750
2751static int
2752biba_sysvshm_check_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
2753    struct label *shmseglabel, int cmd)
2754{
2755	struct mac_biba *subj, *obj;
2756
2757	if (!biba_enabled)
2758		return (0);
2759
2760	subj = SLOT(cred->cr_label);
2761	obj = SLOT(shmseglabel);
2762
2763	switch(cmd) {
2764	case IPC_RMID:
2765	case IPC_SET:
2766		if (!biba_dominate_effective(subj, obj))
2767			return (EACCES);
2768		break;
2769
2770	case IPC_STAT:
2771	case SHM_STAT:
2772		if (!biba_dominate_effective(obj, subj))
2773			return (EACCES);
2774		break;
2775
2776	default:
2777		return (EACCES);
2778	}
2779
2780	return (0);
2781}
2782
2783static int
2784biba_sysvshm_check_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
2785    struct label *shmseglabel, int shmflg)
2786{
2787	struct mac_biba *subj, *obj;
2788
2789	if (!biba_enabled)
2790		return (0);
2791
2792	subj = SLOT(cred->cr_label);
2793	obj = SLOT(shmseglabel);
2794
2795	if (!biba_dominate_effective(obj, subj))
2796		return (EACCES);
2797
2798	return (0);
2799}
2800
2801static void
2802biba_sysvshm_cleanup(struct label *shmlabel)
2803{
2804
2805	bzero(SLOT(shmlabel), sizeof(struct mac_biba));
2806}
2807
2808static void
2809biba_sysvshm_create(struct ucred *cred, struct shmid_kernel *shmsegptr,
2810    struct label *shmlabel)
2811{
2812	struct mac_biba *source, *dest;
2813
2814	source = SLOT(cred->cr_label);
2815	dest = SLOT(shmlabel);
2816
2817	biba_copy_effective(source, dest);
2818}
2819
2820static int
2821biba_vnode_associate_extattr(struct mount *mp, struct label *mplabel,
2822    struct vnode *vp, struct label *vplabel)
2823{
2824	struct mac_biba mb_temp, *source, *dest;
2825	int buflen, error;
2826
2827	source = SLOT(mplabel);
2828	dest = SLOT(vplabel);
2829
2830	buflen = sizeof(mb_temp);
2831	bzero(&mb_temp, buflen);
2832
2833	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
2834	    MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &mb_temp, curthread);
2835	if (error == ENOATTR || error == EOPNOTSUPP) {
2836		/* Fall back to the mntlabel. */
2837		biba_copy_effective(source, dest);
2838		return (0);
2839	} else if (error)
2840		return (error);
2841
2842	if (buflen != sizeof(mb_temp)) {
2843		printf("biba_vnode_associate_extattr: bad size %d\n",
2844		    buflen);
2845		return (EPERM);
2846	}
2847	if (biba_valid(&mb_temp) != 0) {
2848		printf("biba_vnode_associate_extattr: invalid\n");
2849		return (EPERM);
2850	}
2851	if ((mb_temp.mb_flags & MAC_BIBA_FLAGS_BOTH) !=
2852	    MAC_BIBA_FLAG_EFFECTIVE) {
2853		printf("biba_vnode_associate_extattr: not effective\n");
2854		return (EPERM);
2855	}
2856
2857	biba_copy_effective(&mb_temp, dest);
2858	return (0);
2859}
2860
2861static void
2862biba_vnode_associate_singlelabel(struct mount *mp, struct label *mplabel,
2863    struct vnode *vp, struct label *vplabel)
2864{
2865	struct mac_biba *source, *dest;
2866
2867	source = SLOT(mplabel);
2868	dest = SLOT(vplabel);
2869
2870	biba_copy_effective(source, dest);
2871}
2872
2873static int
2874biba_vnode_check_chdir(struct ucred *cred, struct vnode *dvp,
2875    struct label *dvplabel)
2876{
2877	struct mac_biba *subj, *obj;
2878
2879	if (!biba_enabled)
2880		return (0);
2881
2882	subj = SLOT(cred->cr_label);
2883	obj = SLOT(dvplabel);
2884
2885	if (!biba_dominate_effective(obj, subj))
2886		return (EACCES);
2887
2888	return (0);
2889}
2890
2891static int
2892biba_vnode_check_chroot(struct ucred *cred, struct vnode *dvp,
2893    struct label *dvplabel)
2894{
2895	struct mac_biba *subj, *obj;
2896
2897	if (!biba_enabled)
2898		return (0);
2899
2900	subj = SLOT(cred->cr_label);
2901	obj = SLOT(dvplabel);
2902
2903	if (!biba_dominate_effective(obj, subj))
2904		return (EACCES);
2905
2906	return (0);
2907}
2908
2909static int
2910biba_vnode_check_create(struct ucred *cred, struct vnode *dvp,
2911    struct label *dvplabel, struct componentname *cnp, struct vattr *vap)
2912{
2913	struct mac_biba *subj, *obj;
2914
2915	if (!biba_enabled)
2916		return (0);
2917
2918	subj = SLOT(cred->cr_label);
2919	obj = SLOT(dvplabel);
2920
2921	if (!biba_dominate_effective(subj, obj))
2922		return (EACCES);
2923
2924	return (0);
2925}
2926
2927static int
2928biba_vnode_check_deleteacl(struct ucred *cred, struct vnode *vp,
2929    struct label *vplabel, acl_type_t type)
2930{
2931	struct mac_biba *subj, *obj;
2932
2933	if (!biba_enabled)
2934		return (0);
2935
2936	subj = SLOT(cred->cr_label);
2937	obj = SLOT(vplabel);
2938
2939	if (!biba_dominate_effective(subj, obj))
2940		return (EACCES);
2941
2942	return (0);
2943}
2944
2945static int
2946biba_vnode_check_deleteextattr(struct ucred *cred, struct vnode *vp,
2947    struct label *vplabel, int attrnamespace, const char *name)
2948{
2949	struct mac_biba *subj, *obj;
2950
2951	if (!biba_enabled)
2952		return (0);
2953
2954	subj = SLOT(cred->cr_label);
2955	obj = SLOT(vplabel);
2956
2957	if (!biba_dominate_effective(subj, obj))
2958		return (EACCES);
2959
2960	return (0);
2961}
2962
2963static int
2964biba_vnode_check_exec(struct ucred *cred, struct vnode *vp,
2965    struct label *vplabel, struct image_params *imgp,
2966    struct label *execlabel)
2967{
2968	struct mac_biba *subj, *obj, *exec;
2969	int error;
2970
2971	if (execlabel != NULL) {
2972		/*
2973		 * We currently don't permit labels to be changed at
2974		 * exec-time as part of Biba, so disallow non-NULL Biba label
2975		 * elements in the execlabel.
2976		 */
2977		exec = SLOT(execlabel);
2978		error = biba_atmostflags(exec, 0);
2979		if (error)
2980			return (error);
2981	}
2982
2983	if (!biba_enabled)
2984		return (0);
2985
2986	subj = SLOT(cred->cr_label);
2987	obj = SLOT(vplabel);
2988
2989	if (!biba_dominate_effective(obj, subj))
2990		return (EACCES);
2991
2992	return (0);
2993}
2994
2995static int
2996biba_vnode_check_getacl(struct ucred *cred, struct vnode *vp,
2997    struct label *vplabel, acl_type_t type)
2998{
2999	struct mac_biba *subj, *obj;
3000
3001	if (!biba_enabled)
3002		return (0);
3003
3004	subj = SLOT(cred->cr_label);
3005	obj = SLOT(vplabel);
3006
3007	if (!biba_dominate_effective(obj, subj))
3008		return (EACCES);
3009
3010	return (0);
3011}
3012
3013static int
3014biba_vnode_check_getextattr(struct ucred *cred, struct vnode *vp,
3015    struct label *vplabel, int attrnamespace, const char *name)
3016{
3017	struct mac_biba *subj, *obj;
3018
3019	if (!biba_enabled)
3020		return (0);
3021
3022	subj = SLOT(cred->cr_label);
3023	obj = SLOT(vplabel);
3024
3025	if (!biba_dominate_effective(obj, subj))
3026		return (EACCES);
3027
3028	return (0);
3029}
3030
3031static int
3032biba_vnode_check_link(struct ucred *cred, struct vnode *dvp,
3033    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3034    struct componentname *cnp)
3035{
3036	struct mac_biba *subj, *obj;
3037
3038	if (!biba_enabled)
3039		return (0);
3040
3041	subj = SLOT(cred->cr_label);
3042	obj = SLOT(dvplabel);
3043
3044	if (!biba_dominate_effective(subj, obj))
3045		return (EACCES);
3046
3047	obj = SLOT(vplabel);
3048
3049	if (!biba_dominate_effective(subj, obj))
3050		return (EACCES);
3051
3052	return (0);
3053}
3054
3055static int
3056biba_vnode_check_listextattr(struct ucred *cred, struct vnode *vp,
3057    struct label *vplabel, int attrnamespace)
3058{
3059	struct mac_biba *subj, *obj;
3060
3061	if (!biba_enabled)
3062		return (0);
3063
3064	subj = SLOT(cred->cr_label);
3065	obj = SLOT(vplabel);
3066
3067	if (!biba_dominate_effective(obj, subj))
3068		return (EACCES);
3069
3070	return (0);
3071}
3072
3073static int
3074biba_vnode_check_lookup(struct ucred *cred, struct vnode *dvp,
3075    struct label *dvplabel, struct componentname *cnp)
3076{
3077	struct mac_biba *subj, *obj;
3078
3079	if (!biba_enabled)
3080		return (0);
3081
3082	subj = SLOT(cred->cr_label);
3083	obj = SLOT(dvplabel);
3084
3085	if (!biba_dominate_effective(obj, subj))
3086		return (EACCES);
3087
3088	return (0);
3089}
3090
3091static int
3092biba_vnode_check_mmap(struct ucred *cred, struct vnode *vp,
3093    struct label *vplabel, int prot, int flags)
3094{
3095	struct mac_biba *subj, *obj;
3096
3097	/*
3098	 * Rely on the use of open()-time protections to handle
3099	 * non-revocation cases.
3100	 */
3101	if (!biba_enabled || !revocation_enabled)
3102		return (0);
3103
3104	subj = SLOT(cred->cr_label);
3105	obj = SLOT(vplabel);
3106
3107	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
3108		if (!biba_dominate_effective(obj, subj))
3109			return (EACCES);
3110	}
3111	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
3112		if (!biba_dominate_effective(subj, obj))
3113			return (EACCES);
3114	}
3115
3116	return (0);
3117}
3118
3119static int
3120biba_vnode_check_open(struct ucred *cred, struct vnode *vp,
3121    struct label *vplabel, accmode_t accmode)
3122{
3123	struct mac_biba *subj, *obj;
3124
3125	if (!biba_enabled)
3126		return (0);
3127
3128	subj = SLOT(cred->cr_label);
3129	obj = SLOT(vplabel);
3130
3131	/* XXX privilege override for admin? */
3132	if (accmode & (VREAD | VEXEC | VSTAT_PERMS)) {
3133		if (!biba_dominate_effective(obj, subj))
3134			return (EACCES);
3135	}
3136	if (accmode & VMODIFY_PERMS) {
3137		if (!biba_dominate_effective(subj, obj))
3138			return (EACCES);
3139	}
3140
3141	return (0);
3142}
3143
3144static int
3145biba_vnode_check_poll(struct ucred *active_cred, struct ucred *file_cred,
3146    struct vnode *vp, struct label *vplabel)
3147{
3148	struct mac_biba *subj, *obj;
3149
3150	if (!biba_enabled || !revocation_enabled)
3151		return (0);
3152
3153	subj = SLOT(active_cred->cr_label);
3154	obj = SLOT(vplabel);
3155
3156	if (!biba_dominate_effective(obj, subj))
3157		return (EACCES);
3158
3159	return (0);
3160}
3161
3162static int
3163biba_vnode_check_read(struct ucred *active_cred, struct ucred *file_cred,
3164    struct vnode *vp, struct label *vplabel)
3165{
3166	struct mac_biba *subj, *obj;
3167
3168	if (!biba_enabled || !revocation_enabled)
3169		return (0);
3170
3171	subj = SLOT(active_cred->cr_label);
3172	obj = SLOT(vplabel);
3173
3174	if (!biba_dominate_effective(obj, subj))
3175		return (EACCES);
3176
3177	return (0);
3178}
3179
3180static int
3181biba_vnode_check_readdir(struct ucred *cred, struct vnode *dvp,
3182    struct label *dvplabel)
3183{
3184	struct mac_biba *subj, *obj;
3185
3186	if (!biba_enabled)
3187		return (0);
3188
3189	subj = SLOT(cred->cr_label);
3190	obj = SLOT(dvplabel);
3191
3192	if (!biba_dominate_effective(obj, subj))
3193		return (EACCES);
3194
3195	return (0);
3196}
3197
3198static int
3199biba_vnode_check_readlink(struct ucred *cred, struct vnode *vp,
3200    struct label *vplabel)
3201{
3202	struct mac_biba *subj, *obj;
3203
3204	if (!biba_enabled)
3205		return (0);
3206
3207	subj = SLOT(cred->cr_label);
3208	obj = SLOT(vplabel);
3209
3210	if (!biba_dominate_effective(obj, subj))
3211		return (EACCES);
3212
3213	return (0);
3214}
3215
3216static int
3217biba_vnode_check_relabel(struct ucred *cred, struct vnode *vp,
3218    struct label *vplabel, struct label *newlabel)
3219{
3220	struct mac_biba *old, *new, *subj;
3221	int error;
3222
3223	old = SLOT(vplabel);
3224	new = SLOT(newlabel);
3225	subj = SLOT(cred->cr_label);
3226
3227	/*
3228	 * If there is a Biba label update for the vnode, it must be a
3229	 * effective label.
3230	 */
3231	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
3232	if (error)
3233		return (error);
3234
3235	/*
3236	 * To perform a relabel of the vnode (Biba label or not), Biba must
3237	 * authorize the relabel.
3238	 */
3239	if (!biba_effective_in_range(old, subj))
3240		return (EPERM);
3241
3242	/*
3243	 * If the Biba label is to be changed, authorize as appropriate.
3244	 */
3245	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
3246		/*
3247		 * To change the Biba label on a vnode, the new vnode label
3248		 * must be in the subject range.
3249		 */
3250		if (!biba_effective_in_range(new, subj))
3251			return (EPERM);
3252
3253		/*
3254		 * To change the Biba label on the vnode to be EQUAL, the
3255		 * subject must have appropriate privilege.
3256		 */
3257		if (biba_contains_equal(new)) {
3258			error = biba_subject_privileged(subj);
3259			if (error)
3260				return (error);
3261		}
3262	}
3263
3264	return (0);
3265}
3266
3267static int
3268biba_vnode_check_rename_from(struct ucred *cred, struct vnode *dvp,
3269    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3270    struct componentname *cnp)
3271{
3272	struct mac_biba *subj, *obj;
3273
3274	if (!biba_enabled)
3275		return (0);
3276
3277	subj = SLOT(cred->cr_label);
3278	obj = SLOT(dvplabel);
3279
3280	if (!biba_dominate_effective(subj, obj))
3281		return (EACCES);
3282
3283	obj = SLOT(vplabel);
3284
3285	if (!biba_dominate_effective(subj, obj))
3286		return (EACCES);
3287
3288	return (0);
3289}
3290
3291static int
3292biba_vnode_check_rename_to(struct ucred *cred, struct vnode *dvp,
3293    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3294    int samedir, struct componentname *cnp)
3295{
3296	struct mac_biba *subj, *obj;
3297
3298	if (!biba_enabled)
3299		return (0);
3300
3301	subj = SLOT(cred->cr_label);
3302	obj = SLOT(dvplabel);
3303
3304	if (!biba_dominate_effective(subj, obj))
3305		return (EACCES);
3306
3307	if (vp != NULL) {
3308		obj = SLOT(vplabel);
3309
3310		if (!biba_dominate_effective(subj, obj))
3311			return (EACCES);
3312	}
3313
3314	return (0);
3315}
3316
3317static int
3318biba_vnode_check_revoke(struct ucred *cred, struct vnode *vp,
3319    struct label *vplabel)
3320{
3321	struct mac_biba *subj, *obj;
3322
3323	if (!biba_enabled)
3324		return (0);
3325
3326	subj = SLOT(cred->cr_label);
3327	obj = SLOT(vplabel);
3328
3329	if (!biba_dominate_effective(subj, obj))
3330		return (EACCES);
3331
3332	return (0);
3333}
3334
3335static int
3336biba_vnode_check_setacl(struct ucred *cred, struct vnode *vp,
3337    struct label *vplabel, acl_type_t type, struct acl *acl)
3338{
3339	struct mac_biba *subj, *obj;
3340
3341	if (!biba_enabled)
3342		return (0);
3343
3344	subj = SLOT(cred->cr_label);
3345	obj = SLOT(vplabel);
3346
3347	if (!biba_dominate_effective(subj, obj))
3348		return (EACCES);
3349
3350	return (0);
3351}
3352
3353static int
3354biba_vnode_check_setextattr(struct ucred *cred, struct vnode *vp,
3355    struct label *vplabel, int attrnamespace, const char *name)
3356{
3357	struct mac_biba *subj, *obj;
3358
3359	if (!biba_enabled)
3360		return (0);
3361
3362	subj = SLOT(cred->cr_label);
3363	obj = SLOT(vplabel);
3364
3365	if (!biba_dominate_effective(subj, obj))
3366		return (EACCES);
3367
3368	/* XXX: protect the MAC EA in a special way? */
3369
3370	return (0);
3371}
3372
3373static int
3374biba_vnode_check_setflags(struct ucred *cred, struct vnode *vp,
3375    struct label *vplabel, u_long flags)
3376{
3377	struct mac_biba *subj, *obj;
3378
3379	if (!biba_enabled)
3380		return (0);
3381
3382	subj = SLOT(cred->cr_label);
3383	obj = SLOT(vplabel);
3384
3385	if (!biba_dominate_effective(subj, obj))
3386		return (EACCES);
3387
3388	return (0);
3389}
3390
3391static int
3392biba_vnode_check_setmode(struct ucred *cred, struct vnode *vp,
3393    struct label *vplabel, mode_t mode)
3394{
3395	struct mac_biba *subj, *obj;
3396
3397	if (!biba_enabled)
3398		return (0);
3399
3400	subj = SLOT(cred->cr_label);
3401	obj = SLOT(vplabel);
3402
3403	if (!biba_dominate_effective(subj, obj))
3404		return (EACCES);
3405
3406	return (0);
3407}
3408
3409static int
3410biba_vnode_check_setowner(struct ucred *cred, struct vnode *vp,
3411    struct label *vplabel, uid_t uid, gid_t gid)
3412{
3413	struct mac_biba *subj, *obj;
3414
3415	if (!biba_enabled)
3416		return (0);
3417
3418	subj = SLOT(cred->cr_label);
3419	obj = SLOT(vplabel);
3420
3421	if (!biba_dominate_effective(subj, obj))
3422		return (EACCES);
3423
3424	return (0);
3425}
3426
3427static int
3428biba_vnode_check_setutimes(struct ucred *cred, struct vnode *vp,
3429    struct label *vplabel, struct timespec atime, struct timespec mtime)
3430{
3431	struct mac_biba *subj, *obj;
3432
3433	if (!biba_enabled)
3434		return (0);
3435
3436	subj = SLOT(cred->cr_label);
3437	obj = SLOT(vplabel);
3438
3439	if (!biba_dominate_effective(subj, obj))
3440		return (EACCES);
3441
3442	return (0);
3443}
3444
3445static int
3446biba_vnode_check_stat(struct ucred *active_cred, struct ucred *file_cred,
3447    struct vnode *vp, struct label *vplabel)
3448{
3449	struct mac_biba *subj, *obj;
3450
3451	if (!biba_enabled)
3452		return (0);
3453
3454	subj = SLOT(active_cred->cr_label);
3455	obj = SLOT(vplabel);
3456
3457	if (!biba_dominate_effective(obj, subj))
3458		return (EACCES);
3459
3460	return (0);
3461}
3462
3463static int
3464biba_vnode_check_unlink(struct ucred *cred, struct vnode *dvp,
3465    struct label *dvplabel, struct vnode *vp, struct label *vplabel,
3466    struct componentname *cnp)
3467{
3468	struct mac_biba *subj, *obj;
3469
3470	if (!biba_enabled)
3471		return (0);
3472
3473	subj = SLOT(cred->cr_label);
3474	obj = SLOT(dvplabel);
3475
3476	if (!biba_dominate_effective(subj, obj))
3477		return (EACCES);
3478
3479	obj = SLOT(vplabel);
3480
3481	if (!biba_dominate_effective(subj, obj))
3482		return (EACCES);
3483
3484	return (0);
3485}
3486
3487static int
3488biba_vnode_check_write(struct ucred *active_cred,
3489    struct ucred *file_cred, struct vnode *vp, struct label *vplabel)
3490{
3491	struct mac_biba *subj, *obj;
3492
3493	if (!biba_enabled || !revocation_enabled)
3494		return (0);
3495
3496	subj = SLOT(active_cred->cr_label);
3497	obj = SLOT(vplabel);
3498
3499	if (!biba_dominate_effective(subj, obj))
3500		return (EACCES);
3501
3502	return (0);
3503}
3504
3505static int
3506biba_vnode_create_extattr(struct ucred *cred, struct mount *mp,
3507    struct label *mplabel, struct vnode *dvp, struct label *dvplabel,
3508    struct vnode *vp, struct label *vplabel, struct componentname *cnp)
3509{
3510	struct mac_biba *source, *dest, mb_temp;
3511	size_t buflen;
3512	int error;
3513
3514	buflen = sizeof(mb_temp);
3515	bzero(&mb_temp, buflen);
3516
3517	source = SLOT(cred->cr_label);
3518	dest = SLOT(vplabel);
3519	biba_copy_effective(source, &mb_temp);
3520
3521	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
3522	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &mb_temp, curthread);
3523	if (error == 0)
3524		biba_copy_effective(source, dest);
3525	return (error);
3526}
3527
3528static void
3529biba_vnode_relabel(struct ucred *cred, struct vnode *vp,
3530    struct label *vplabel, struct label *newlabel)
3531{
3532	struct mac_biba *source, *dest;
3533
3534	source = SLOT(newlabel);
3535	dest = SLOT(vplabel);
3536
3537	biba_copy(source, dest);
3538}
3539
3540static int
3541biba_vnode_setlabel_extattr(struct ucred *cred, struct vnode *vp,
3542    struct label *vplabel, struct label *intlabel)
3543{
3544	struct mac_biba *source, mb_temp;
3545	size_t buflen;
3546	int error;
3547
3548	buflen = sizeof(mb_temp);
3549	bzero(&mb_temp, buflen);
3550
3551	source = SLOT(intlabel);
3552	if ((source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) == 0)
3553		return (0);
3554
3555	biba_copy_effective(source, &mb_temp);
3556
3557	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
3558	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &mb_temp, curthread);
3559	return (error);
3560}
3561
3562static struct mac_policy_ops mac_biba_ops =
3563{
3564	.mpo_init = biba_init,
3565
3566	.mpo_bpfdesc_check_receive = biba_bpfdesc_check_receive,
3567	.mpo_bpfdesc_create = biba_bpfdesc_create,
3568	.mpo_bpfdesc_create_mbuf = biba_bpfdesc_create_mbuf,
3569	.mpo_bpfdesc_destroy_label = biba_destroy_label,
3570	.mpo_bpfdesc_init_label = biba_init_label,
3571
3572	.mpo_cred_associate_nfsd = biba_cred_associate_nfsd,
3573	.mpo_cred_check_relabel = biba_cred_check_relabel,
3574	.mpo_cred_check_visible = biba_cred_check_visible,
3575	.mpo_cred_copy_label = biba_copy_label,
3576	.mpo_cred_create_init = biba_cred_create_init,
3577	.mpo_cred_create_swapper = biba_cred_create_swapper,
3578	.mpo_cred_destroy_label = biba_destroy_label,
3579	.mpo_cred_externalize_label = biba_externalize_label,
3580	.mpo_cred_init_label = biba_init_label,
3581	.mpo_cred_internalize_label = biba_internalize_label,
3582	.mpo_cred_relabel = biba_cred_relabel,
3583
3584	.mpo_devfs_create_device = biba_devfs_create_device,
3585	.mpo_devfs_create_directory = biba_devfs_create_directory,
3586	.mpo_devfs_create_symlink = biba_devfs_create_symlink,
3587	.mpo_devfs_destroy_label = biba_destroy_label,
3588	.mpo_devfs_init_label = biba_init_label,
3589	.mpo_devfs_update = biba_devfs_update,
3590	.mpo_devfs_vnode_associate = biba_devfs_vnode_associate,
3591
3592	.mpo_ifnet_check_relabel = biba_ifnet_check_relabel,
3593	.mpo_ifnet_check_transmit = biba_ifnet_check_transmit,
3594	.mpo_ifnet_copy_label = biba_copy_label,
3595	.mpo_ifnet_create = biba_ifnet_create,
3596	.mpo_ifnet_create_mbuf = biba_ifnet_create_mbuf,
3597	.mpo_ifnet_destroy_label = biba_destroy_label,
3598	.mpo_ifnet_externalize_label = biba_externalize_label,
3599	.mpo_ifnet_init_label = biba_init_label,
3600	.mpo_ifnet_internalize_label = biba_internalize_label,
3601	.mpo_ifnet_relabel = biba_ifnet_relabel,
3602
3603	.mpo_inpcb_check_deliver = biba_inpcb_check_deliver,
3604	.mpo_inpcb_check_visible = biba_inpcb_check_visible,
3605	.mpo_inpcb_create = biba_inpcb_create,
3606	.mpo_inpcb_create_mbuf = biba_inpcb_create_mbuf,
3607	.mpo_inpcb_destroy_label = biba_destroy_label,
3608	.mpo_inpcb_init_label = biba_init_label_waitcheck,
3609	.mpo_inpcb_sosetlabel = biba_inpcb_sosetlabel,
3610
3611	.mpo_ip6q_create = biba_ip6q_create,
3612	.mpo_ip6q_destroy_label = biba_destroy_label,
3613	.mpo_ip6q_init_label = biba_init_label_waitcheck,
3614	.mpo_ip6q_match = biba_ip6q_match,
3615	.mpo_ip6q_reassemble = biba_ip6q_reassemble,
3616	.mpo_ip6q_update = biba_ip6q_update,
3617
3618	.mpo_ipq_create = biba_ipq_create,
3619	.mpo_ipq_destroy_label = biba_destroy_label,
3620	.mpo_ipq_init_label = biba_init_label_waitcheck,
3621	.mpo_ipq_match = biba_ipq_match,
3622	.mpo_ipq_reassemble = biba_ipq_reassemble,
3623	.mpo_ipq_update = biba_ipq_update,
3624
3625	.mpo_kld_check_load = biba_kld_check_load,
3626
3627	.mpo_mbuf_copy_label = biba_copy_label,
3628	.mpo_mbuf_destroy_label = biba_destroy_label,
3629	.mpo_mbuf_init_label = biba_init_label_waitcheck,
3630
3631	.mpo_mount_check_stat = biba_mount_check_stat,
3632	.mpo_mount_create = biba_mount_create,
3633	.mpo_mount_destroy_label = biba_destroy_label,
3634	.mpo_mount_init_label = biba_init_label,
3635
3636	.mpo_netinet_arp_send = biba_netinet_arp_send,
3637	.mpo_netinet_firewall_reply = biba_netinet_firewall_reply,
3638	.mpo_netinet_firewall_send = biba_netinet_firewall_send,
3639	.mpo_netinet_fragment = biba_netinet_fragment,
3640	.mpo_netinet_icmp_reply = biba_netinet_icmp_reply,
3641	.mpo_netinet_igmp_send = biba_netinet_igmp_send,
3642
3643	.mpo_netinet6_nd6_send = biba_netinet6_nd6_send,
3644
3645	.mpo_pipe_check_ioctl = biba_pipe_check_ioctl,
3646	.mpo_pipe_check_poll = biba_pipe_check_poll,
3647	.mpo_pipe_check_read = biba_pipe_check_read,
3648	.mpo_pipe_check_relabel = biba_pipe_check_relabel,
3649	.mpo_pipe_check_stat = biba_pipe_check_stat,
3650	.mpo_pipe_check_write = biba_pipe_check_write,
3651	.mpo_pipe_copy_label = biba_copy_label,
3652	.mpo_pipe_create = biba_pipe_create,
3653	.mpo_pipe_destroy_label = biba_destroy_label,
3654	.mpo_pipe_externalize_label = biba_externalize_label,
3655	.mpo_pipe_init_label = biba_init_label,
3656	.mpo_pipe_internalize_label = biba_internalize_label,
3657	.mpo_pipe_relabel = biba_pipe_relabel,
3658
3659	.mpo_posixsem_check_getvalue = biba_posixsem_check_rdonly,
3660	.mpo_posixsem_check_open = biba_posixsem_check_openunlink,
3661	.mpo_posixsem_check_post = biba_posixsem_check_write,
3662	.mpo_posixsem_check_setmode = biba_posixsem_check_setmode,
3663	.mpo_posixsem_check_setowner = biba_posixsem_check_setowner,
3664	.mpo_posixsem_check_stat = biba_posixsem_check_rdonly,
3665	.mpo_posixsem_check_unlink = biba_posixsem_check_openunlink,
3666	.mpo_posixsem_check_wait = biba_posixsem_check_write,
3667	.mpo_posixsem_create = biba_posixsem_create,
3668	.mpo_posixsem_destroy_label = biba_destroy_label,
3669	.mpo_posixsem_init_label = biba_init_label,
3670
3671	.mpo_posixshm_check_mmap = biba_posixshm_check_mmap,
3672	.mpo_posixshm_check_open = biba_posixshm_check_open,
3673	.mpo_posixshm_check_read = biba_posixshm_check_read,
3674	.mpo_posixshm_check_setmode = biba_posixshm_check_setmode,
3675	.mpo_posixshm_check_setowner = biba_posixshm_check_setowner,
3676	.mpo_posixshm_check_stat = biba_posixshm_check_stat,
3677	.mpo_posixshm_check_truncate = biba_posixshm_check_truncate,
3678	.mpo_posixshm_check_unlink = biba_posixshm_check_unlink,
3679	.mpo_posixshm_check_write = biba_posixshm_check_write,
3680	.mpo_posixshm_create = biba_posixshm_create,
3681	.mpo_posixshm_destroy_label = biba_destroy_label,
3682	.mpo_posixshm_init_label = biba_init_label,
3683
3684	.mpo_priv_check = biba_priv_check,
3685
3686	.mpo_proc_check_debug = biba_proc_check_debug,
3687	.mpo_proc_check_sched = biba_proc_check_sched,
3688	.mpo_proc_check_signal = biba_proc_check_signal,
3689
3690	.mpo_socket_check_deliver = biba_socket_check_deliver,
3691	.mpo_socket_check_relabel = biba_socket_check_relabel,
3692	.mpo_socket_check_visible = biba_socket_check_visible,
3693	.mpo_socket_copy_label = biba_copy_label,
3694	.mpo_socket_create = biba_socket_create,
3695	.mpo_socket_create_mbuf = biba_socket_create_mbuf,
3696	.mpo_socket_destroy_label = biba_destroy_label,
3697	.mpo_socket_externalize_label = biba_externalize_label,
3698	.mpo_socket_init_label = biba_init_label_waitcheck,
3699	.mpo_socket_internalize_label = biba_internalize_label,
3700	.mpo_socket_newconn = biba_socket_newconn,
3701	.mpo_socket_relabel = biba_socket_relabel,
3702
3703	.mpo_socketpeer_destroy_label = biba_destroy_label,
3704	.mpo_socketpeer_externalize_label = biba_externalize_label,
3705	.mpo_socketpeer_init_label = biba_init_label_waitcheck,
3706	.mpo_socketpeer_set_from_mbuf = biba_socketpeer_set_from_mbuf,
3707	.mpo_socketpeer_set_from_socket = biba_socketpeer_set_from_socket,
3708
3709	.mpo_syncache_create = biba_syncache_create,
3710	.mpo_syncache_create_mbuf = biba_syncache_create_mbuf,
3711	.mpo_syncache_destroy_label = biba_destroy_label,
3712	.mpo_syncache_init_label = biba_init_label_waitcheck,
3713
3714	.mpo_system_check_acct = biba_system_check_acct,
3715	.mpo_system_check_auditctl = biba_system_check_auditctl,
3716	.mpo_system_check_auditon = biba_system_check_auditon,
3717	.mpo_system_check_swapoff = biba_system_check_swapoff,
3718	.mpo_system_check_swapon = biba_system_check_swapon,
3719	.mpo_system_check_sysctl = biba_system_check_sysctl,
3720
3721	.mpo_sysvmsg_cleanup = biba_sysvmsg_cleanup,
3722	.mpo_sysvmsg_create = biba_sysvmsg_create,
3723	.mpo_sysvmsg_destroy_label = biba_destroy_label,
3724	.mpo_sysvmsg_init_label = biba_init_label,
3725
3726	.mpo_sysvmsq_check_msgrcv = biba_sysvmsq_check_msgrcv,
3727	.mpo_sysvmsq_check_msgrmid = biba_sysvmsq_check_msgrmid,
3728	.mpo_sysvmsq_check_msqget = biba_sysvmsq_check_msqget,
3729	.mpo_sysvmsq_check_msqsnd = biba_sysvmsq_check_msqsnd,
3730	.mpo_sysvmsq_check_msqrcv = biba_sysvmsq_check_msqrcv,
3731	.mpo_sysvmsq_check_msqctl = biba_sysvmsq_check_msqctl,
3732	.mpo_sysvmsq_cleanup = biba_sysvmsq_cleanup,
3733	.mpo_sysvmsq_create = biba_sysvmsq_create,
3734	.mpo_sysvmsq_destroy_label = biba_destroy_label,
3735	.mpo_sysvmsq_init_label = biba_init_label,
3736
3737	.mpo_sysvsem_check_semctl = biba_sysvsem_check_semctl,
3738	.mpo_sysvsem_check_semget = biba_sysvsem_check_semget,
3739	.mpo_sysvsem_check_semop = biba_sysvsem_check_semop,
3740	.mpo_sysvsem_cleanup = biba_sysvsem_cleanup,
3741	.mpo_sysvsem_create = biba_sysvsem_create,
3742	.mpo_sysvsem_destroy_label = biba_destroy_label,
3743	.mpo_sysvsem_init_label = biba_init_label,
3744
3745	.mpo_sysvshm_check_shmat = biba_sysvshm_check_shmat,
3746	.mpo_sysvshm_check_shmctl = biba_sysvshm_check_shmctl,
3747	.mpo_sysvshm_check_shmget = biba_sysvshm_check_shmget,
3748	.mpo_sysvshm_cleanup = biba_sysvshm_cleanup,
3749	.mpo_sysvshm_create = biba_sysvshm_create,
3750	.mpo_sysvshm_destroy_label = biba_destroy_label,
3751	.mpo_sysvshm_init_label = biba_init_label,
3752
3753	.mpo_vnode_associate_extattr = biba_vnode_associate_extattr,
3754	.mpo_vnode_associate_singlelabel = biba_vnode_associate_singlelabel,
3755	.mpo_vnode_check_access = biba_vnode_check_open,
3756	.mpo_vnode_check_chdir = biba_vnode_check_chdir,
3757	.mpo_vnode_check_chroot = biba_vnode_check_chroot,
3758	.mpo_vnode_check_create = biba_vnode_check_create,
3759	.mpo_vnode_check_deleteacl = biba_vnode_check_deleteacl,
3760	.mpo_vnode_check_deleteextattr = biba_vnode_check_deleteextattr,
3761	.mpo_vnode_check_exec = biba_vnode_check_exec,
3762	.mpo_vnode_check_getacl = biba_vnode_check_getacl,
3763	.mpo_vnode_check_getextattr = biba_vnode_check_getextattr,
3764	.mpo_vnode_check_link = biba_vnode_check_link,
3765	.mpo_vnode_check_listextattr = biba_vnode_check_listextattr,
3766	.mpo_vnode_check_lookup = biba_vnode_check_lookup,
3767	.mpo_vnode_check_mmap = biba_vnode_check_mmap,
3768	.mpo_vnode_check_open = biba_vnode_check_open,
3769	.mpo_vnode_check_poll = biba_vnode_check_poll,
3770	.mpo_vnode_check_read = biba_vnode_check_read,
3771	.mpo_vnode_check_readdir = biba_vnode_check_readdir,
3772	.mpo_vnode_check_readlink = biba_vnode_check_readlink,
3773	.mpo_vnode_check_relabel = biba_vnode_check_relabel,
3774	.mpo_vnode_check_rename_from = biba_vnode_check_rename_from,
3775	.mpo_vnode_check_rename_to = biba_vnode_check_rename_to,
3776	.mpo_vnode_check_revoke = biba_vnode_check_revoke,
3777	.mpo_vnode_check_setacl = biba_vnode_check_setacl,
3778	.mpo_vnode_check_setextattr = biba_vnode_check_setextattr,
3779	.mpo_vnode_check_setflags = biba_vnode_check_setflags,
3780	.mpo_vnode_check_setmode = biba_vnode_check_setmode,
3781	.mpo_vnode_check_setowner = biba_vnode_check_setowner,
3782	.mpo_vnode_check_setutimes = biba_vnode_check_setutimes,
3783	.mpo_vnode_check_stat = biba_vnode_check_stat,
3784	.mpo_vnode_check_unlink = biba_vnode_check_unlink,
3785	.mpo_vnode_check_write = biba_vnode_check_write,
3786	.mpo_vnode_create_extattr = biba_vnode_create_extattr,
3787	.mpo_vnode_copy_label = biba_copy_label,
3788	.mpo_vnode_destroy_label = biba_destroy_label,
3789	.mpo_vnode_externalize_label = biba_externalize_label,
3790	.mpo_vnode_init_label = biba_init_label,
3791	.mpo_vnode_internalize_label = biba_internalize_label,
3792	.mpo_vnode_relabel = biba_vnode_relabel,
3793	.mpo_vnode_setlabel_extattr = biba_vnode_setlabel_extattr,
3794};
3795
3796MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
3797    MPC_LOADTIME_FLAG_NOTLATE, &biba_slot);
3798