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