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