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