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