mac_biba.c revision 112675
120253Sjoerg/*-
220302Sjoerg * Copyright (c) 1999, 2000, 2001, 2002 Robert N. M. Watson
320302Sjoerg * Copyright (c) 2001, 2002 Networks Associates Technology, Inc.
420253Sjoerg * All rights reserved.
520253Sjoerg *
620253Sjoerg * This software was developed by Robert Watson for the TrustedBSD Project.
720253Sjoerg *
820253Sjoerg * This software was developed for the FreeBSD Project in part by Network
920302Sjoerg * Associates Laboratories, the Security Research Division of Network
1020253Sjoerg * Associates, Inc. under DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"),
1120253Sjoerg * as part of the DARPA CHATS research program.
1220253Sjoerg *
1320253Sjoerg * Redistribution and use in source and binary forms, with or without
1420302Sjoerg * modification, are permitted provided that the following conditions
1520253Sjoerg * are met:
1620253Sjoerg * 1. Redistributions of source code must retain the above copyright
1720302Sjoerg *    notice, this list of conditions and the following disclaimer.
1820253Sjoerg * 2. Redistributions in binary form must reproduce the above copyright
1920253Sjoerg *    notice, this list of conditions and the following disclaimer in the
2020253Sjoerg *    documentation and/or other materials provided with the distribution.
2120253Sjoerg *
2220253Sjoerg * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2320253Sjoerg * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2420253Sjoerg * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2544229Sdavidn * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2620253Sjoerg * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2720253Sjoerg * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2830259Scharnier * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2930259Scharnier * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3050479Speter * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3130259Scharnier * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3230259Scharnier * SUCH DAMAGE.
3330259Scharnier *
3430259Scharnier * $FreeBSD: head/sys/security/mac_biba/mac_biba.c 112675 2003-03-26 15:12:03Z rwatson $
3520253Sjoerg */
3620253Sjoerg
3720253Sjoerg/*
3830259Scharnier * Developed by the TrustedBSD Project.
3920253Sjoerg * Biba fixed label mandatory integrity policy.
4020555Sdavidn */
4120555Sdavidn
4220555Sdavidn#include <sys/types.h>
4330259Scharnier#include <sys/param.h>
4464918Sgreen#include <sys/acl.h>
4520253Sjoerg#include <sys/conf.h>
4620253Sjoerg#include <sys/extattr.h>
4720253Sjoerg#include <sys/kernel.h>
4823318Sache#include <sys/mac.h>
4922394Sdavidn#include <sys/malloc.h>
5052512Sdavidn#include <sys/mount.h>
5124214Sache#include <sys/proc.h>
5244386Sdavidn#include <sys/systm.h>
5320253Sjoerg#include <sys/sysproto.h>
5420253Sjoerg#include <sys/sysent.h>
5520253Sjoerg#include <sys/systm.h>
5620253Sjoerg#include <sys/vnode.h>
5720253Sjoerg#include <sys/file.h>
5820253Sjoerg#include <sys/socket.h>
5920253Sjoerg#include <sys/socketvar.h>
6020253Sjoerg#include <sys/pipe.h>
6120253Sjoerg#include <sys/sysctl.h>
6285145Sache
6320253Sjoerg#include <fs/devfs/devfs.h>
6420253Sjoerg
6520253Sjoerg#include <net/bpfdesc.h>
6620253Sjoerg#include <net/if.h>
6720253Sjoerg#include <net/if_types.h>
6820253Sjoerg#include <net/if_var.h>
6920253Sjoerg
7020253Sjoerg#include <netinet/in.h>
7120253Sjoerg#include <netinet/ip_var.h>
7220253Sjoerg
7320253Sjoerg#include <vm/vm.h>
7420253Sjoerg
7520253Sjoerg#include <sys/mac_policy.h>
7620253Sjoerg
7720253Sjoerg#include <security/mac_biba/mac_biba.h>
7820253Sjoerg
7920253SjoergSYSCTL_DECL(_security_mac);
8020253Sjoerg
81124382SiedowseSYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
8220253Sjoerg    "TrustedBSD mac_biba policy controls");
8320253Sjoerg
8420253Sjoergstatic int	mac_biba_label_size = sizeof(struct mac_biba);
8520253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
8620253Sjoerg    &mac_biba_label_size, 0, "Size of struct mac_biba");
8720253Sjoerg
8820253Sjoergstatic int	mac_biba_enabled = 1;
8920253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW,
9020253Sjoerg    &mac_biba_enabled, 0, "Enforce MAC/Biba policy");
9120253SjoergTUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled);
9220253Sjoerg
9320253Sjoergstatic int	destroyed_not_inited;
9420253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
9520253Sjoerg    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
9620253Sjoerg
9720253Sjoergstatic int	trust_all_interfaces = 0;
9820253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
9952527Sdavidn    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
10020253SjoergTUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces);
10152512Sdavidn
10220253Sjoergstatic char	trusted_interfaces[128];
10320253SjoergSYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
10420253Sjoerg    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
10520253SjoergTUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces,
10620253Sjoerg    sizeof(trusted_interfaces));
10720253Sjoerg
10820747Sdavidnstatic int	max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
10982868SddSYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
110167919Sle    &max_compartments, 0, "Maximum supported compartments");
111167919Sle
11220253Sjoergstatic int	ptys_equal = 0;
11320253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW,
11420253Sjoerg    &ptys_equal, 0, "Label pty devices as biba/equal on create");
11520253SjoergTUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal);
11620253Sjoerg
11720253Sjoergstatic int	revocation_enabled = 0;
11820253SjoergSYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW,
11920253Sjoerg    &revocation_enabled, 0, "Revoke access to objects on relabel");
12020253SjoergTUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled);
12120253Sjoerg
12256000Sdavidnstatic int	mac_biba_slot;
12320253Sjoerg#define	SLOT(l)	((struct mac_biba *)LABEL_TO_SLOT((l), mac_biba_slot).l_ptr)
12420253Sjoerg
12556000SdavidnMALLOC_DEFINE(M_MACBIBA, "biba label", "MAC/Biba labels");
12656000Sdavidn
12756000Sdavidnstatic __inline int
12820253Sjoergbiba_bit_set_empty(u_char *set) {
12920253Sjoerg	int i;
13052512Sdavidn
13120253Sjoerg	for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
13220267Sjoerg		if (set[i] != 0)
13320267Sjoerg			return (0);
13420267Sjoerg	return (1);
13520267Sjoerg}
13620267Sjoerg
13720267Sjoergstatic struct mac_biba *
13820267Sjoergbiba_alloc(int flag)
13920267Sjoerg{
14020267Sjoerg	struct mac_biba *mac_biba;
14120267Sjoerg
14220267Sjoerg	mac_biba = malloc(sizeof(struct mac_biba), M_MACBIBA, M_ZERO | flag);
14320267Sjoerg
14420267Sjoerg	return (mac_biba);
14520267Sjoerg}
14620253Sjoerg
14720253Sjoergstatic void
14820253Sjoergbiba_free(struct mac_biba *mac_biba)
14920253Sjoerg{
15020267Sjoerg
15120253Sjoerg	if (mac_biba != NULL)
15221052Sdavidn		free(mac_biba, M_MACBIBA);
153167919Sle	else
154167919Sle		atomic_add_int(&destroyed_not_inited, 1);
155167919Sle}
156167919Sle
157167919Slestatic int
158219408Sjkimbiba_atmostflags(struct mac_biba *mac_biba, int flags)
159167919Sle{
160168044Sle
161167919Sle	if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags)
16221052Sdavidn		return (EINVAL);
16321052Sdavidn	return (0);
16421052Sdavidn}
16521052Sdavidn
166224535Sdelphijstatic int
16721052Sdavidnmac_biba_dominate_element(struct mac_biba_element *a,
16821052Sdavidn    struct mac_biba_element *b)
16921052Sdavidn{
17021052Sdavidn	int bit;
17121052Sdavidn
17221052Sdavidn	switch (a->mbe_type) {
17330259Scharnier	case MAC_BIBA_TYPE_EQUAL:
17421052Sdavidn	case MAC_BIBA_TYPE_HIGH:
17521052Sdavidn		return (1);
17621052Sdavidn
17721052Sdavidn	case MAC_BIBA_TYPE_LOW:
17821242Sdavidn		switch (b->mbe_type) {
17921242Sdavidn		case MAC_BIBA_TYPE_GRADE:
18021242Sdavidn		case MAC_BIBA_TYPE_HIGH:
18121242Sdavidn			return (0);
18221242Sdavidn
18321242Sdavidn		case MAC_BIBA_TYPE_EQUAL:
18421242Sdavidn		case MAC_BIBA_TYPE_LOW:
18521242Sdavidn			return (1);
18621242Sdavidn
187219408Sjkim		default:
18821242Sdavidn			panic("mac_biba_dominate_element: b->mbe_type invalid");
189148584Spjd		}
190148584Spjd
191148584Spjd	case MAC_BIBA_TYPE_GRADE:
192148584Spjd		switch (b->mbe_type) {
193148584Spjd		case MAC_BIBA_TYPE_EQUAL:
19421242Sdavidn		case MAC_BIBA_TYPE_LOW:
19521242Sdavidn			return (1);
19621242Sdavidn
197130633Srobert		case MAC_BIBA_TYPE_HIGH:
198130633Srobert			return (0);
19921242Sdavidn
20021242Sdavidn		case MAC_BIBA_TYPE_GRADE:
20121242Sdavidn			for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
20221242Sdavidn				if (!MAC_BIBA_BIT_TEST(bit,
203219408Sjkim				    a->mbe_compartments) &&
20421242Sdavidn				    MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
20521242Sdavidn					return (0);
20621242Sdavidn			return (a->mbe_grade >= b->mbe_grade);
20730259Scharnier
20821242Sdavidn		default:
20921242Sdavidn			panic("mac_biba_dominate_element: b->mbe_type invalid");
21021052Sdavidn		}
21121242Sdavidn
212219408Sjkim	default:
21330259Scharnier		panic("mac_biba_dominate_element: a->mbe_type invalid");
21421052Sdavidn	}
21521052Sdavidn
21621052Sdavidn	return (0);
21721052Sdavidn}
21830259Scharnier
21921052Sdavidnstatic int
22021052Sdavidnmac_biba_subject_dominate_high(struct mac_biba *mac_biba)
22120253Sjoerg{
22220253Sjoerg	struct mac_biba_element *element;
22320253Sjoerg
22421330Sdavidn	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
22521330Sdavidn	    ("mac_biba_single_in_range: mac_biba not single"));
22621330Sdavidn	element = &mac_biba->mb_single;
22720253Sjoerg
22820253Sjoerg	return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
22920253Sjoerg	    element->mbe_type == MAC_BIBA_TYPE_HIGH);
23020253Sjoerg}
23163596Sdavidn
23263596Sdavidnstatic int
23363596Sdavidnmac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
23463596Sdavidn{
23563596Sdavidn
23663596Sdavidn	return (mac_biba_dominate_element(&rangeb->mb_rangehigh,
23763596Sdavidn	    &rangea->mb_rangehigh) &&
23863596Sdavidn	    mac_biba_dominate_element(&rangea->mb_rangelow,
23920253Sjoerg	    &rangeb->mb_rangelow));
24020253Sjoerg}
24120253Sjoerg
24220679Sdavidnstatic int
24320253Sjoergmac_biba_single_in_range(struct mac_biba *single, struct mac_biba *range)
24420253Sjoerg{
24552527Sdavidn
24620253Sjoerg	KASSERT((single->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
24720747Sdavidn	    ("mac_biba_single_in_range: a not single"));
24844229Sdavidn	KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
24961957Sache	    ("mac_biba_single_in_range: b not range"));
25030259Scharnier
25120253Sjoerg	return (mac_biba_dominate_element(&range->mb_rangehigh,
25220747Sdavidn	    &single->mb_single) &&
25320747Sdavidn	    mac_biba_dominate_element(&single->mb_single,
25420253Sjoerg	    &range->mb_rangelow));
25520747Sdavidn
25620253Sjoerg	return (1);
25720253Sjoerg}
25852527Sdavidn
25920253Sjoergstatic int
26026088Sdavidnmac_biba_dominate_single(struct mac_biba *a, struct mac_biba *b)
26130259Scharnier{
26220253Sjoerg	KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
26352527Sdavidn	    ("mac_biba_dominate_single: a not single"));
26420253Sjoerg	KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
26520253Sjoerg	    ("mac_biba_dominate_single: b not single"));
26620253Sjoerg
26763600Sdavidn	return (mac_biba_dominate_element(&a->mb_single, &b->mb_single));
26863600Sdavidn}
26920253Sjoerg
27020253Sjoergstatic int
27130259Scharniermac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
27220253Sjoerg{
27320253Sjoerg
27420253Sjoerg	if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
27520253Sjoerg	    b->mbe_type == MAC_BIBA_TYPE_EQUAL)
27620253Sjoerg		return (1);
27720253Sjoerg
27820253Sjoerg	return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
27920253Sjoerg}
28020253Sjoerg
28120253Sjoergstatic int
28220253Sjoergmac_biba_equal_single(struct mac_biba *a, struct mac_biba *b)
28320253Sjoerg{
28420253Sjoerg
28520253Sjoerg	KASSERT((a->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
28620253Sjoerg	    ("mac_biba_equal_single: a not single"));
28720267Sjoerg	KASSERT((b->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
28830259Scharnier	    ("mac_biba_equal_single: b not single"));
28920267Sjoerg
29020253Sjoerg	return (mac_biba_equal_element(&a->mb_single, &b->mb_single));
29152527Sdavidn}
29220253Sjoerg
29320267Sjoergstatic int
29444386Sdavidnmac_biba_contains_equal(struct mac_biba *mac_biba)
29520253Sjoerg{
29644229Sdavidn
29744229Sdavidn	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE)
29844386Sdavidn		if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL)
29944229Sdavidn			return (1);
30020267Sjoerg
30120253Sjoerg	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
30252527Sdavidn		if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
30320253Sjoerg			return (1);
30444229Sdavidn		if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
30520253Sjoerg			return (1);
30620253Sjoerg	}
30720253Sjoerg
30820253Sjoerg	return (0);
30930259Scharnier}
31020253Sjoerg
31120253Sjoergstatic int
31220253Sjoergmac_biba_subject_privileged(struct mac_biba *mac_biba)
31320253Sjoerg{
31420253Sjoerg
31520253Sjoerg	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
31643780Sdes	    MAC_BIBA_FLAGS_BOTH,
31743780Sdes	    ("mac_biba_subject_privileged: subject doesn't have both labels"));
318242916Sbapt
31920253Sjoerg	/* If the single is EQUAL, it's ok. */
32020253Sjoerg	if (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_EQUAL)
32120253Sjoerg		return (0);
32220253Sjoerg
32352527Sdavidn	/* If either range endpoint is EQUAL, it's ok. */
32420253Sjoerg	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
32520253Sjoerg	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
32620253Sjoerg		return (0);
32752512Sdavidn
32852512Sdavidn	/* If the range is low-high, it's ok. */
32952527Sdavidn	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
33020253Sjoerg	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
33144229Sdavidn		return (0);
33220253Sjoerg
33320253Sjoerg	/* It's not ok. */
33420253Sjoerg	return (EPERM);
33520253Sjoerg}
33620253Sjoerg
33744386Sdavidnstatic int
33844386Sdavidnmac_biba_high_single(struct mac_biba *mac_biba)
33944386Sdavidn{
34020253Sjoerg
34120253Sjoerg	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
34230259Scharnier	    ("mac_biba_equal_single: mac_biba not single"));
34330259Scharnier
34420253Sjoerg	return (mac_biba->mb_single.mbe_type == MAC_BIBA_TYPE_HIGH);
34552527Sdavidn}
34620253Sjoerg
34720253Sjoergstatic int
34820253Sjoergmac_biba_valid(struct mac_biba *mac_biba)
34920253Sjoerg{
35052512Sdavidn
35152512Sdavidn	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) {
35252512Sdavidn		switch (mac_biba->mb_single.mbe_type) {
35352512Sdavidn		case MAC_BIBA_TYPE_GRADE:
35452512Sdavidn			break;
35552512Sdavidn
35652512Sdavidn		case MAC_BIBA_TYPE_EQUAL:
35752512Sdavidn		case MAC_BIBA_TYPE_HIGH:
35852512Sdavidn		case MAC_BIBA_TYPE_LOW:
35952512Sdavidn			if (mac_biba->mb_single.mbe_grade != 0 ||
36052512Sdavidn			    !MAC_BIBA_BIT_SET_EMPTY(
36152512Sdavidn			    mac_biba->mb_single.mbe_compartments))
36252512Sdavidn				return (EINVAL);
36352512Sdavidn			break;
36452512Sdavidn
36552512Sdavidn		default:
36652512Sdavidn			return (EINVAL);
36752512Sdavidn		}
36852527Sdavidn	} else {
36952512Sdavidn		if (mac_biba->mb_single.mbe_type != MAC_BIBA_TYPE_UNDEF)
37052512Sdavidn			return (EINVAL);
37152512Sdavidn	}
37252512Sdavidn
37352527Sdavidn	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
37452527Sdavidn		switch (mac_biba->mb_rangelow.mbe_type) {
37552527Sdavidn		case MAC_BIBA_TYPE_GRADE:
37652527Sdavidn			break;
37752527Sdavidn
37820253Sjoerg		case MAC_BIBA_TYPE_EQUAL:
37920253Sjoerg		case MAC_BIBA_TYPE_HIGH:
38020253Sjoerg		case MAC_BIBA_TYPE_LOW:
38120253Sjoerg			if (mac_biba->mb_rangelow.mbe_grade != 0 ||
38220253Sjoerg			    !MAC_BIBA_BIT_SET_EMPTY(
38330259Scharnier			    mac_biba->mb_rangelow.mbe_compartments))
38420253Sjoerg				return (EINVAL);
38544229Sdavidn			break;
38644229Sdavidn
38785145Sache		default:
38844229Sdavidn			return (EINVAL);
38920747Sdavidn		}
39085145Sache
39120747Sdavidn		switch (mac_biba->mb_rangehigh.mbe_type) {
39244229Sdavidn		case MAC_BIBA_TYPE_GRADE:
39344229Sdavidn			break;
39444229Sdavidn
39544229Sdavidn		case MAC_BIBA_TYPE_EQUAL:
39644229Sdavidn		case MAC_BIBA_TYPE_HIGH:
39744229Sdavidn		case MAC_BIBA_TYPE_LOW:
39844229Sdavidn			if (mac_biba->mb_rangehigh.mbe_grade != 0 ||
39944229Sdavidn			    !MAC_BIBA_BIT_SET_EMPTY(
40020253Sjoerg			    mac_biba->mb_rangehigh.mbe_compartments))
40120253Sjoerg				return (EINVAL);
40220253Sjoerg			break;
40320253Sjoerg
40420253Sjoerg		default:
40520253Sjoerg			return (EINVAL);
406130633Srobert		}
40720253Sjoerg		if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh,
40852502Sdavidn		    &mac_biba->mb_rangelow))
40952502Sdavidn			return (EINVAL);
41052502Sdavidn	} else {
41152502Sdavidn		if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
41256000Sdavidn		    mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
41352502Sdavidn			return (EINVAL);
41452502Sdavidn	}
41521330Sdavidn
41652502Sdavidn	return (0);
41752502Sdavidn}
41852502Sdavidn
41952502Sdavidnstatic void
42052502Sdavidnmac_biba_set_range(struct mac_biba *mac_biba, u_short typelow,
42156000Sdavidn    u_short gradelow, u_char *compartmentslow, u_short typehigh,
42252502Sdavidn    u_short gradehigh, u_char *compartmentshigh)
42352502Sdavidn{
42452502Sdavidn
42520253Sjoerg	mac_biba->mb_rangelow.mbe_type = typelow;
42620253Sjoerg	mac_biba->mb_rangelow.mbe_grade = gradelow;
42720253Sjoerg	if (compartmentslow != NULL)
42820253Sjoerg		memcpy(mac_biba->mb_rangelow.mbe_compartments,
42944229Sdavidn		    compartmentslow,
43044229Sdavidn		    sizeof(mac_biba->mb_rangelow.mbe_compartments));
43144229Sdavidn	mac_biba->mb_rangehigh.mbe_type = typehigh;
43244229Sdavidn	mac_biba->mb_rangehigh.mbe_grade = gradehigh;
43344229Sdavidn	if (compartmentshigh != NULL)
43420253Sjoerg		memcpy(mac_biba->mb_rangehigh.mbe_compartments,
43544229Sdavidn		    compartmentshigh,
43644229Sdavidn		    sizeof(mac_biba->mb_rangehigh.mbe_compartments));
43744229Sdavidn	mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
43844229Sdavidn}
43944229Sdavidn
44020253Sjoergstatic void
44144229Sdavidnmac_biba_set_single(struct mac_biba *mac_biba, u_short type, u_short grade,
44244229Sdavidn    u_char *compartments)
44344229Sdavidn{
44444229Sdavidn
44544229Sdavidn	mac_biba->mb_single.mbe_type = type;
44644229Sdavidn	mac_biba->mb_single.mbe_grade = grade;
44744229Sdavidn	if (compartments != NULL)
44844229Sdavidn		memcpy(mac_biba->mb_single.mbe_compartments, compartments,
44944229Sdavidn		    sizeof(mac_biba->mb_single.mbe_compartments));
45044229Sdavidn	mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE;
45120253Sjoerg}
45220253Sjoerg
45320267Sjoergstatic void
45420253Sjoergmac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
45544386Sdavidn{
45644386Sdavidn
45744386Sdavidn	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
45820253Sjoerg	    ("mac_biba_copy_range: labelfrom not range"));
45920253Sjoerg
46020253Sjoerg	labelto->mb_rangelow = labelfrom->mb_rangelow;
46120253Sjoerg	labelto->mb_rangehigh = labelfrom->mb_rangehigh;
46220253Sjoerg	labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
46320253Sjoerg}
46430259Scharnier
46520679Sdavidnstatic void
46652527Sdavidnmac_biba_copy_single(struct mac_biba *labelfrom, struct mac_biba *labelto)
46720253Sjoerg{
46852527Sdavidn
46961957Sache	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_SINGLE) != 0,
47020253Sjoerg	    ("mac_biba_copy_single: labelfrom not single"));
47152527Sdavidn
47220253Sjoerg	labelto->mb_single = labelfrom->mb_single;
47330259Scharnier	labelto->mb_flags |= MAC_BIBA_FLAG_SINGLE;
47420253Sjoerg}
47530259Scharnier
47620253Sjoergstatic void
47720253Sjoergmac_biba_copy(struct mac_biba *source, struct mac_biba *dest)
47852527Sdavidn{
47952527Sdavidn
48052527Sdavidn	if (source->mb_flags & MAC_BIBA_FLAG_SINGLE)
48152527Sdavidn		mac_biba_copy_single(source, dest);
48261762Sdavidn	if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
48352527Sdavidn		mac_biba_copy_range(source, dest);
48452527Sdavidn}
48552527Sdavidn
48620253Sjoerg/*
48752527Sdavidn * Policy module operations.
48852527Sdavidn */
48952527Sdavidnstatic void
49052527Sdavidnmac_biba_destroy(struct mac_policy_conf *conf)
49152527Sdavidn{
49252527Sdavidn
49320253Sjoerg}
49420253Sjoerg
49520253Sjoergstatic void
49620253Sjoergmac_biba_init(struct mac_policy_conf *conf)
49752527Sdavidn{
49852527Sdavidn
49952527Sdavidn}
50052527Sdavidn
50120253Sjoerg/*
50220253Sjoerg * Label operations.
50352527Sdavidn */
50420267Sjoergstatic void
50552527Sdavidnmac_biba_init_label(struct label *label)
50652527Sdavidn{
50752527Sdavidn
50852527Sdavidn	SLOT(label) = biba_alloc(M_WAITOK);
50952527Sdavidn}
51052527Sdavidn
51120253Sjoergstatic int
51220253Sjoergmac_biba_init_label_waitcheck(struct label *label, int flag)
51320253Sjoerg{
51420253Sjoerg
51552527Sdavidn	SLOT(label) = biba_alloc(flag);
51652527Sdavidn	if (SLOT(label) == NULL)
51752527Sdavidn		return (ENOMEM);
51852527Sdavidn
51920253Sjoerg	return (0);
52020253Sjoerg}
52120253Sjoerg
52252527Sdavidnstatic void
52352527Sdavidnmac_biba_destroy_label(struct label *label)
52452527Sdavidn{
52552527Sdavidn
52652527Sdavidn	biba_free(SLOT(label));
52752527Sdavidn	SLOT(label) = NULL;
52852527Sdavidn}
52952527Sdavidn
53052527Sdavidn/*
53120253Sjoerg * mac_biba_element_to_string() is basically an snprintf wrapper with
53252527Sdavidn * the same properties as snprintf().  It returns the length it would
53352527Sdavidn * have added to the string in the event the string is too short.
53452527Sdavidn */
53552527Sdavidnstatic size_t
53652527Sdavidnmac_biba_element_to_string(char *string, size_t size,
53752527Sdavidn    struct mac_biba_element *element)
53852527Sdavidn{
53952527Sdavidn	int pos, bit = 1;
54052527Sdavidn
54120747Sdavidn	switch (element->mbe_type) {
542130629Srobert	case MAC_BIBA_TYPE_HIGH:
543130629Srobert		return (snprintf(string, size, "high"));
54420747Sdavidn
54520747Sdavidn	case MAC_BIBA_TYPE_LOW:
54630259Scharnier		return (snprintf(string, size, "low"));
54720747Sdavidn
54830259Scharnier	case MAC_BIBA_TYPE_EQUAL:
54920747Sdavidn		return (snprintf(string, size, "equal"));
55020747Sdavidn
551124382Siedowse	case MAC_BIBA_TYPE_GRADE:
552124382Siedowse		pos = snprintf(string, size, "%d:", element->mbe_grade);
55364918Sgreen		for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++) {
55464918Sgreen			if (MAC_BIBA_BIT_TEST(bit, element->mbe_compartments))
55564918Sgreen				pos += snprintf(string + pos, size - pos,
55664918Sgreen				    "%d+", bit);
557253157Sdes		}
55864918Sgreen		if (string[pos - 1] == '+' || string[pos - 1] == ':')
55964918Sgreen			string[--pos] = '\0';
56020267Sjoerg		return (pos);
56152527Sdavidn
56252527Sdavidn	default:
56320267Sjoerg		panic("mac_biba_element_to_string: invalid type (%d)",
56420253Sjoerg		    element->mbe_type);
56564918Sgreen	}
56652527Sdavidn}
56752527Sdavidn
56852527Sdavidnstatic int
56952527Sdavidnmac_biba_to_string(char *string, size_t size, size_t *caller_len,
57052527Sdavidn    struct mac_biba *mac_biba)
57120253Sjoerg{
57230259Scharnier	size_t left, len;
57344229Sdavidn	char *curptr;
57430259Scharnier
57520253Sjoerg	bzero(string, size);
57620253Sjoerg	curptr = string;
57720253Sjoerg	left = size;
57820253Sjoerg
57920253Sjoerg	if (mac_biba->mb_flags & MAC_BIBA_FLAG_SINGLE) {
58020253Sjoerg		len = mac_biba_element_to_string(curptr, left,
58120253Sjoerg		    &mac_biba->mb_single);
58220253Sjoerg		if (len >= left)
58320253Sjoerg			return (EINVAL);
58420253Sjoerg		left -= len;
58520253Sjoerg		curptr += len;
58620253Sjoerg	}
58720253Sjoerg
58864918Sgreen	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
58964918Sgreen		len = snprintf(curptr, left, "(");
59064918Sgreen		if (len >= left)
59164918Sgreen			return (EINVAL);
59264918Sgreen		left -= len;
59352527Sdavidn		curptr += len;
59420253Sjoerg
59520253Sjoerg		len = mac_biba_element_to_string(curptr, left,
59630259Scharnier		    &mac_biba->mb_rangelow);
59720253Sjoerg		if (len >= left)
59820253Sjoerg			return (EINVAL);
59920253Sjoerg		left -= len;
60020253Sjoerg		curptr += len;
60120253Sjoerg
60252527Sdavidn		len = snprintf(curptr, left, "-");
60352527Sdavidn		if (len >= left)
60452527Sdavidn			return (EINVAL);
60552527Sdavidn		left -= len;
60652527Sdavidn		curptr += len;
60752527Sdavidn
60852527Sdavidn		len = mac_biba_element_to_string(curptr, left,
60920253Sjoerg		    &mac_biba->mb_rangehigh);
610124382Siedowse		if (len >= left)
611124382Siedowse			return (EINVAL);
61263572Sdavidn		left -= len;
61363572Sdavidn		curptr += len;
61463572Sdavidn
61563572Sdavidn		len = snprintf(curptr, left, ")");
61663572Sdavidn		if (len >= left)
61763572Sdavidn			return (EINVAL);
61820253Sjoerg		left -= len;
619124382Siedowse		curptr += len;
62020253Sjoerg	}
62120253Sjoerg
62220253Sjoerg	*caller_len = strlen(string);
62364918Sgreen	return (0);
62420253Sjoerg}
62520253Sjoerg
62620253Sjoergstatic int
62720253Sjoergmac_biba_externalize_label(struct label *label, char *element_name,
62820253Sjoerg    char *element_data, size_t size, size_t *len, int *claimed)
62920253Sjoerg{
63020253Sjoerg	struct mac_biba *mac_biba;
63120253Sjoerg	int error;
63220253Sjoerg
63320253Sjoerg	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
634124382Siedowse		return (0);
635124382Siedowse
636124382Siedowse	(*claimed)++;
637124382Siedowse
63820253Sjoerg	mac_biba = SLOT(label);
63920253Sjoerg	error = mac_biba_to_string(element_data, size, len, mac_biba);
64020253Sjoerg	if (error)
64120253Sjoerg		return (error);
64220253Sjoerg
64320253Sjoerg	*len = strlen(element_data);
64420253Sjoerg	return (0);
64520253Sjoerg}
64620253Sjoerg
64720253Sjoergstatic int
648124382Siedowsemac_biba_parse_element(struct mac_biba_element *element, char *string)
649124382Siedowse{
65020267Sjoerg
65120253Sjoerg	if (strcmp(string, "high") == 0 ||
65220253Sjoerg	    strcmp(string, "hi") == 0) {
653168045Sle		element->mbe_type = MAC_BIBA_TYPE_HIGH;
65420253Sjoerg		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
65520253Sjoerg	} else if (strcmp(string, "low") == 0 ||
65630259Scharnier	    strcmp(string, "lo") == 0) {
657124382Siedowse		element->mbe_type = MAC_BIBA_TYPE_LOW;
658124382Siedowse		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
659124382Siedowse	} else if (strcmp(string, "equal") == 0 ||
660124382Siedowse	    strcmp(string, "eq") == 0) {
661124382Siedowse		element->mbe_type = MAC_BIBA_TYPE_EQUAL;
662124382Siedowse		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
663124382Siedowse	} else {
664124382Siedowse		char *p0, *p1;
665124382Siedowse		int d;
666124382Siedowse
667124382Siedowse		p0 = string;
668124382Siedowse		d = strtol(p0, &p1, 10);
66952527Sdavidn
67020253Sjoerg		if (d < 0 || d > 65535)
67120253Sjoerg			return (EINVAL);
67220267Sjoerg		element->mbe_type = MAC_BIBA_TYPE_GRADE;
67320267Sjoerg		element->mbe_grade = d;
67420267Sjoerg
67520267Sjoerg		if (*p1 != ':')  {
67620267Sjoerg			if (p1 == p0 || *p1 != '\0')
67744386Sdavidn				return (EINVAL);
67844386Sdavidn			else
67944386Sdavidn				return (0);
68020267Sjoerg		}
68121330Sdavidn		else
68252527Sdavidn			if (*(p1 + 1) == '\0')
68352502Sdavidn				return (0);
68452502Sdavidn
68552502Sdavidn		while ((p0 = ++p1)) {
68652502Sdavidn			d = strtol(p0, &p1, 10);
68752502Sdavidn			if (d < 1 || d > MAC_BIBA_MAX_COMPARTMENTS)
68856000Sdavidn				return (EINVAL);
68952502Sdavidn
69052502Sdavidn			MAC_BIBA_BIT_SET(d, element->mbe_compartments);
69152502Sdavidn
69252502Sdavidn			if (*p1 == '\0')
69352502Sdavidn				break;
69452502Sdavidn			if (p1 == p0 || *p1 != '+')
69552502Sdavidn				return (EINVAL);
69656000Sdavidn		}
69752502Sdavidn	}
69852502Sdavidn
69952512Sdavidn	return (0);
70052527Sdavidn}
70152527Sdavidn
70252527Sdavidn/*
70352527Sdavidn * Note: destructively consumes the string, make a local copy before
70452527Sdavidn * calling if that's a problem.
70552527Sdavidn */
70656000Sdavidnstatic int
70752527Sdavidnmac_biba_parse(struct mac_biba *mac_biba, char *string)
70852527Sdavidn{
70952527Sdavidn	char *range, *rangeend, *rangehigh, *rangelow, *single;
71052527Sdavidn	int error;
71152527Sdavidn
71252527Sdavidn	/* Do we have a range? */
71352527Sdavidn	single = string;
71456000Sdavidn	range = index(string, '(');
71552527Sdavidn	if (range == single)
71652527Sdavidn		single = NULL;
71752502Sdavidn	rangelow = rangehigh = NULL;
71821330Sdavidn	if (range != NULL) {
71921330Sdavidn		/* Nul terminate the end of the single string. */
72020253Sjoerg		*range = '\0';
72120253Sjoerg		range++;
72220253Sjoerg		rangelow = range;
72320253Sjoerg		rangehigh = index(rangelow, '-');
72420253Sjoerg		if (rangehigh == NULL)
72520253Sjoerg			return (EINVAL);
72620253Sjoerg		rangehigh++;
72761759Sdavidn		if (*rangelow == '\0' || *rangehigh == '\0')
72861759Sdavidn			return (EINVAL);
72961759Sdavidn		rangeend = index(rangehigh, ')');
73061759Sdavidn		if (rangeend == NULL)
73161759Sdavidn			return (EINVAL);
73261759Sdavidn		if (*(rangeend + 1) != '\0')
73361759Sdavidn			return (EINVAL);
73461759Sdavidn		/* Nul terminate the ends of the ranges. */
73561759Sdavidn		*(rangehigh - 1) = '\0';
73661759Sdavidn		*rangeend = '\0';
73730259Scharnier	}
73820253Sjoerg	KASSERT((rangelow != NULL && rangehigh != NULL) ||
73944229Sdavidn	    (rangelow == NULL && rangehigh == NULL),
74098744Sdwmalone	    ("mac_biba_internalize_label: range mismatch"));
74120253Sjoerg
74220253Sjoerg	bzero(mac_biba, sizeof(*mac_biba));
74320253Sjoerg	if (single != NULL) {
74420253Sjoerg		error = mac_biba_parse_element(&mac_biba->mb_single, single);
74520253Sjoerg		if (error)
74620253Sjoerg			return (error);
74720253Sjoerg		mac_biba->mb_flags |= MAC_BIBA_FLAG_SINGLE;
74820253Sjoerg	}
74920253Sjoerg
75020253Sjoerg	if (rangelow != NULL) {
75144229Sdavidn		error = mac_biba_parse_element(&mac_biba->mb_rangelow,
75244229Sdavidn		    rangelow);
75344229Sdavidn		if (error)
75444229Sdavidn			return (error);
75544229Sdavidn		error = mac_biba_parse_element(&mac_biba->mb_rangehigh,
75620253Sjoerg		    rangehigh);
75720253Sjoerg		if (error)
75852527Sdavidn			return (error);
75920253Sjoerg		mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
76082868Sdd	}
76120253Sjoerg
76220253Sjoerg	error = mac_biba_valid(mac_biba);
76320253Sjoerg	if (error)
76444229Sdavidn		return (error);
765168044Sle
76620253Sjoerg	return (0);
76720253Sjoerg}
76820253Sjoerg
76952527Sdavidnstatic int
77082868Sddmac_biba_internalize_label(struct label *label, char *element_name,
77182868Sdd    char *element_data, int *claimed)
77282868Sdd{
77382868Sdd	struct mac_biba *mac_biba, mac_biba_temp;
77482868Sdd	int error;
77582868Sdd
77682868Sdd	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
77782868Sdd		return (0);
77882868Sdd
77982868Sdd	(*claimed)++;
78082868Sdd
78182868Sdd	error = mac_biba_parse(&mac_biba_temp, element_data);
78282868Sdd	if (error)
78382868Sdd		return (error);
78482868Sdd
78582868Sdd	mac_biba = SLOT(label);
78682868Sdd	*mac_biba = mac_biba_temp;
78782868Sdd
78882868Sdd	return (0);
78982868Sdd}
79082868Sdd
79182868Sddstatic void
79220267Sjoergmac_biba_copy_label(struct label *src, struct label *dest)
79320253Sjoerg{
79420253Sjoerg
79520253Sjoerg	*SLOT(dest) = *SLOT(src);
79620253Sjoerg}
79720253Sjoerg
79820253Sjoerg/*
79920253Sjoerg * Labeling event operations: file system objects, and things that look
80020253Sjoerg * a lot like file system objects.
80120253Sjoerg */
80220253Sjoergstatic void
80320253Sjoergmac_biba_create_devfs_device(struct mount *mp, dev_t dev,
80420253Sjoerg    struct devfs_dirent *devfs_dirent, struct label *label)
80520253Sjoerg{
80620253Sjoerg	struct mac_biba *mac_biba;
80720253Sjoerg	int biba_type;
80820253Sjoerg
80944229Sdavidn	mac_biba = SLOT(label);
81030259Scharnier	if (strcmp(dev->si_name, "null") == 0 ||
81120253Sjoerg	    strcmp(dev->si_name, "zero") == 0 ||
81220253Sjoerg	    strcmp(dev->si_name, "random") == 0 ||
81320253Sjoerg	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
81420253Sjoerg		biba_type = MAC_BIBA_TYPE_EQUAL;
81520253Sjoerg	else if (ptys_equal &&
81620253Sjoerg	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
81720253Sjoerg	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
81820253Sjoerg		biba_type = MAC_BIBA_TYPE_EQUAL;
81920253Sjoerg	else
82020253Sjoerg		biba_type = MAC_BIBA_TYPE_HIGH;
82120253Sjoerg	mac_biba_set_single(mac_biba, biba_type, 0, NULL);
82220253Sjoerg}
82320253Sjoerg
82420253Sjoergstatic void
82520253Sjoergmac_biba_create_devfs_directory(struct mount *mp, char *dirname,
82620253Sjoerg    int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
82720253Sjoerg{
82820253Sjoerg	struct mac_biba *mac_biba;
82944229Sdavidn
83044229Sdavidn	mac_biba = SLOT(label);
83144229Sdavidn	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
83220253Sjoerg}
83344229Sdavidn
83420253Sjoergstatic void
83520253Sjoergmac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp,
83620253Sjoerg    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
83720253Sjoerg    struct label *delabel)
83820253Sjoerg{
83920253Sjoerg	struct mac_biba *source, *dest;
84020253Sjoerg
84120253Sjoerg	source = SLOT(&cred->cr_label);
84220253Sjoerg	dest = SLOT(delabel);
84320253Sjoerg
84420253Sjoerg	mac_biba_copy_single(source, dest);
84530259Scharnier}
84620253Sjoerg
84720253Sjoergstatic void
84820253Sjoergmac_biba_create_mount(struct ucred *cred, struct mount *mp,
84920253Sjoerg    struct label *mntlabel, struct label *fslabel)
85020253Sjoerg{
85120253Sjoerg	struct mac_biba *source, *dest;
85220253Sjoerg
85320253Sjoerg	source = SLOT(&cred->cr_label);
85420253Sjoerg	dest = SLOT(mntlabel);
85520253Sjoerg	mac_biba_copy_single(source, dest);
85620253Sjoerg	dest = SLOT(fslabel);
85720253Sjoerg	mac_biba_copy_single(source, dest);
85820253Sjoerg}
85920253Sjoerg
86020253Sjoergstatic void
86120253Sjoergmac_biba_create_root_mount(struct ucred *cred, struct mount *mp,
86220253Sjoerg    struct label *mntlabel, struct label *fslabel)
86320253Sjoerg{
86420253Sjoerg	struct mac_biba *mac_biba;
86520253Sjoerg
86620253Sjoerg	/* Always mount root as high integrity. */
86720253Sjoerg	mac_biba = SLOT(fslabel);
86844229Sdavidn	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
86920253Sjoerg	mac_biba = SLOT(mntlabel);
87044229Sdavidn	mac_biba_set_single(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
87120253Sjoerg}
87261957Sache
87330259Scharnierstatic void
87420253Sjoergmac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp,
87520253Sjoerg    struct label *vnodelabel, struct label *label)
87644229Sdavidn{
87720267Sjoerg	struct mac_biba *source, *dest;
87820253Sjoerg
87920253Sjoerg	source = SLOT(label);
88020253Sjoerg	dest = SLOT(vnodelabel);
88120253Sjoerg
88220253Sjoerg	mac_biba_copy(source, dest);
88320253Sjoerg}
88420253Sjoerg
88520253Sjoergstatic void
88620253Sjoergmac_biba_update_devfsdirent(struct mount *mp,
88720253Sjoerg    struct devfs_dirent *devfs_dirent, struct label *direntlabel,
88820253Sjoerg    struct vnode *vp, struct label *vnodelabel)
88920253Sjoerg{
89020253Sjoerg	struct mac_biba *source, *dest;
89120253Sjoerg
89220253Sjoerg	source = SLOT(vnodelabel);
89320253Sjoerg	dest = SLOT(direntlabel);
89444229Sdavidn
89520253Sjoerg	mac_biba_copy(source, dest);
89620253Sjoerg}
89720253Sjoerg
89820267Sjoergstatic void
89920267Sjoergmac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
90020267Sjoerg    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
90120267Sjoerg    struct label *vlabel)
90220267Sjoerg{
90320267Sjoerg	struct mac_biba *source, *dest;
90420267Sjoerg
90520267Sjoerg	source = SLOT(delabel);
90620267Sjoerg	dest = SLOT(vlabel);
90744229Sdavidn
90820267Sjoerg	mac_biba_copy_single(source, dest);
90920267Sjoerg}
91070486Sben
91120253Sjoergstatic int
91270486Sbenmac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
91320253Sjoerg    struct vnode *vp, struct label *vlabel)
91420253Sjoerg{
91520253Sjoerg	struct mac_biba temp, *source, *dest;
91620253Sjoerg	int buflen, error;
91744229Sdavidn
91820253Sjoerg	source = SLOT(fslabel);
91920253Sjoerg	dest = SLOT(vlabel);
92020253Sjoerg
92120253Sjoerg	buflen = sizeof(temp);
92220253Sjoerg	bzero(&temp, buflen);
92320253Sjoerg
92420253Sjoerg	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
92520253Sjoerg	    MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
92620253Sjoerg	if (error == ENOATTR || error == EOPNOTSUPP) {
92727831Sdavidn		/* Fall back to the fslabel. */
92820253Sjoerg		mac_biba_copy_single(source, dest);
92920253Sjoerg		return (0);
93020253Sjoerg	} else if (error)
93130259Scharnier		return (error);
93220253Sjoerg
93320253Sjoerg	if (buflen != sizeof(temp)) {
93420253Sjoerg		printf("mac_biba_associate_vnode_extattr: bad size %d\n",
93520253Sjoerg		    buflen);
93620253Sjoerg		return (EPERM);
93720253Sjoerg	}
93820253Sjoerg	if (mac_biba_valid(&temp) != 0) {
93920253Sjoerg		printf("mac_biba_associate_vnode_extattr: invalid\n");
94020253Sjoerg		return (EPERM);
94120253Sjoerg	}
94220253Sjoerg	if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_SINGLE) {
94320253Sjoerg		printf("mac_biba_associate_vnode_extattr: not single\n");
94420253Sjoerg		return (EPERM);
94520253Sjoerg	}
94620253Sjoerg
94730259Scharnier	mac_biba_copy_single(&temp, dest);
94820253Sjoerg	return (0);
94920253Sjoerg}
95020253Sjoerg
95120253Sjoergstatic void
95220253Sjoergmac_biba_associate_vnode_singlelabel(struct mount *mp,
95320253Sjoerg    struct label *fslabel, struct vnode *vp, struct label *vlabel)
95420253Sjoerg{
95520253Sjoerg	struct mac_biba *source, *dest;
95620253Sjoerg
95720253Sjoerg	source = SLOT(fslabel);
95820253Sjoerg	dest = SLOT(vlabel);
95920253Sjoerg
96020253Sjoerg	mac_biba_copy_single(source, dest);
96120253Sjoerg}
96220253Sjoerg
96320253Sjoergstatic int
96420253Sjoergmac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp,
96530259Scharnier    struct label *fslabel, struct vnode *dvp, struct label *dlabel,
96620253Sjoerg    struct vnode *vp, struct label *vlabel, struct componentname *cnp)
96720253Sjoerg{
96820253Sjoerg	struct mac_biba *source, *dest, temp;
96920253Sjoerg	size_t buflen;
97020253Sjoerg	int error;
97120253Sjoerg
97220253Sjoerg	buflen = sizeof(temp);
97320253Sjoerg	bzero(&temp, buflen);
97420253Sjoerg
97520253Sjoerg	source = SLOT(&cred->cr_label);
97620253Sjoerg	dest = SLOT(vlabel);
97720253Sjoerg	mac_biba_copy_single(source, &temp);
97820253Sjoerg
97920253Sjoerg	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
98020253Sjoerg	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
98120253Sjoerg	if (error == 0)
98220253Sjoerg		mac_biba_copy_single(source, dest);
983130633Srobert	return (error);
98420253Sjoerg}
98520253Sjoerg
98620253Sjoergstatic int
98720253Sjoergmac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
98820253Sjoerg    struct label *vlabel, struct label *intlabel)
98920253Sjoerg{
99020253Sjoerg	struct mac_biba *source, temp;
99120253Sjoerg	size_t buflen;
99220253Sjoerg	int error;
99320253Sjoerg
99420253Sjoerg	buflen = sizeof(temp);
99520253Sjoerg	bzero(&temp, buflen);
99620253Sjoerg
99720253Sjoerg	source = SLOT(intlabel);
99820253Sjoerg	if ((source->mb_flags & MAC_BIBA_FLAG_SINGLE) == 0)
99920253Sjoerg		return (0);
100030259Scharnier
100130259Scharnier	mac_biba_copy_single(source, &temp);
100220253Sjoerg
100320253Sjoerg	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
100420253Sjoerg	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
100520253Sjoerg	return (error);
100620253Sjoerg}
100720253Sjoerg
100820253Sjoerg/*
100920253Sjoerg * Labeling event operations: IPC object.
101020253Sjoerg */
101120253Sjoergstatic void
101220253Sjoergmac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
101320253Sjoerg    struct mbuf *m, struct label *mbuflabel)
101420253Sjoerg{
101520253Sjoerg	struct mac_biba *source, *dest;
101620253Sjoerg
101720253Sjoerg	source = SLOT(socketlabel);
1018179365Santoine	dest = SLOT(mbuflabel);
101920253Sjoerg
1020179365Santoine	mac_biba_copy_single(source, dest);
1021179365Santoine}
102220253Sjoerg
102320253Sjoergstatic void
102420253Sjoergmac_biba_create_socket(struct ucred *cred, struct socket *socket,
102520253Sjoerg    struct label *socketlabel)
1026179365Santoine{
102720253Sjoerg	struct mac_biba *source, *dest;
102820253Sjoerg
102920253Sjoerg	source = SLOT(&cred->cr_label);
103020253Sjoerg	dest = SLOT(socketlabel);
103120253Sjoerg
103220253Sjoerg	mac_biba_copy_single(source, dest);
1033179365Santoine}
1034181785Sache
1035179365Santoinestatic void
103620253Sjoergmac_biba_create_pipe(struct ucred *cred, struct pipe *pipe,
103720253Sjoerg    struct label *pipelabel)
103820253Sjoerg{
103920253Sjoerg	struct mac_biba *source, *dest;
104020590Sdavidn
104120253Sjoerg	source = SLOT(&cred->cr_label);
104220253Sjoerg	dest = SLOT(pipelabel);
104320253Sjoerg
104420253Sjoerg	mac_biba_copy_single(source, dest);
104520253Sjoerg}
104620253Sjoerg
104720253Sjoergstatic void
104820253Sjoergmac_biba_create_socket_from_socket(struct socket *oldsocket,
104973563Skris    struct label *oldsocketlabel, struct socket *newsocket,
105020253Sjoerg    struct label *newsocketlabel)
1051181785Sache{
105220253Sjoerg	struct mac_biba *source, *dest;
105320253Sjoerg
105420253Sjoerg	source = SLOT(oldsocketlabel);
105520253Sjoerg	dest = SLOT(newsocketlabel);
105620253Sjoerg
1057124382Siedowse	mac_biba_copy_single(source, dest);
1058124382Siedowse}
105961957Sache
106020712Sdavidnstatic void
106120253Sjoergmac_biba_relabel_socket(struct ucred *cred, struct socket *socket,
106220253Sjoerg    struct label *socketlabel, struct label *newlabel)
106320253Sjoerg{
106420253Sjoerg	struct mac_biba *source, *dest;
106520253Sjoerg
106620253Sjoerg	source = SLOT(newlabel);
106720253Sjoerg	dest = SLOT(socketlabel);
106820253Sjoerg
106920253Sjoerg	mac_biba_copy(source, dest);
107020253Sjoerg}
107120253Sjoerg
107220253Sjoergstatic void
107320253Sjoergmac_biba_relabel_pipe(struct ucred *cred, struct pipe *pipe,
1074130633Srobert    struct label *pipelabel, struct label *newlabel)
107520253Sjoerg{
107620253Sjoerg	struct mac_biba *source, *dest;
107720253Sjoerg
107820253Sjoerg	source = SLOT(newlabel);
107920253Sjoerg	dest = SLOT(pipelabel);
108020253Sjoerg
108120253Sjoerg	mac_biba_copy(source, dest);
108244386Sdavidn}
108320253Sjoerg
108420253Sjoergstatic void
108520253Sjoergmac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
108620253Sjoerg    struct socket *socket, struct label *socketpeerlabel)
108744386Sdavidn{
108820253Sjoerg	struct mac_biba *source, *dest;
108920253Sjoerg
109020267Sjoerg	source = SLOT(mbuflabel);
109120253Sjoerg	dest = SLOT(socketpeerlabel);
109244229Sdavidn
109320253Sjoerg	mac_biba_copy_single(source, dest);
109420253Sjoerg}
109520590Sdavidn
109620590Sdavidn/*
109720253Sjoerg * Labeling event operations: network objects.
109820253Sjoerg */
1099130633Srobertstatic void
110020253Sjoergmac_biba_set_socket_peer_from_socket(struct socket *oldsocket,
1101130633Srobert    struct label *oldsocketlabel, struct socket *newsocket,
110220253Sjoerg    struct label *newsocketpeerlabel)
1103130633Srobert{
110420253Sjoerg	struct mac_biba *source, *dest;
1105130633Srobert
1106130633Srobert	source = SLOT(oldsocketlabel);
110720253Sjoerg	dest = SLOT(newsocketpeerlabel);
110820253Sjoerg
110920253Sjoerg	mac_biba_copy_single(source, dest);
111020253Sjoerg}
111120253Sjoerg
111220253Sjoergstatic void
111320253Sjoergmac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
111420253Sjoerg    struct label *bpflabel)
111520253Sjoerg{
111620253Sjoerg	struct mac_biba *source, *dest;
111720253Sjoerg
111820253Sjoerg	source = SLOT(&cred->cr_label);
111920253Sjoerg	dest = SLOT(bpflabel);
112061957Sache
112120253Sjoerg	mac_biba_copy_single(source, dest);
112220590Sdavidn}
112374569Sache
112461957Sachestatic void
112574569Sachemac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
112622394Sdavidn{
112720747Sdavidn	char tifname[IFNAMSIZ], ifname[IFNAMSIZ], *p, *q;
112820747Sdavidn	char tiflist[sizeof(trusted_interfaces)];
112920747Sdavidn	struct mac_biba *dest;
113020747Sdavidn	int len, type;
113120747Sdavidn
113220253Sjoerg	dest = SLOT(ifnetlabel);
113320253Sjoerg
113420253Sjoerg	if (ifnet->if_type == IFT_LOOP) {
113520590Sdavidn		type = MAC_BIBA_TYPE_EQUAL;
113620590Sdavidn		goto set;
113744229Sdavidn	}
113820267Sjoerg
113944229Sdavidn	if (trust_all_interfaces) {
114020267Sjoerg		type = MAC_BIBA_TYPE_HIGH;
114120267Sjoerg		goto set;
114220747Sdavidn	}
114320267Sjoerg
114420267Sjoerg	type = MAC_BIBA_TYPE_LOW;
114520267Sjoerg
114620747Sdavidn	if (trusted_interfaces[0] == '\0' ||
114720267Sjoerg	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
114820267Sjoerg		goto set;
114920267Sjoerg
115020267Sjoerg	bzero(tiflist, sizeof(tiflist));
115120267Sjoerg	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
115244229Sdavidn		if(*p != ' ' && *p != '\t')
115361957Sache			*q = *p;
115420253Sjoerg
115520267Sjoerg	snprintf(ifname, IFNAMSIZ, "%s%d", ifnet->if_name, ifnet->if_unit);
115620253Sjoerg
115720253Sjoerg	for (p = q = tiflist;; p++) {
115820679Sdavidn		if (*p == ',' || *p == '\0') {
115920679Sdavidn			len = p - q;
116020253Sjoerg			if (len < IFNAMSIZ) {
1161109961Sgad				bzero(tifname, sizeof(tifname));
1162109961Sgad				bcopy(q, tifname, len);
1163109961Sgad				if (strcmp(tifname, ifname) == 0) {
116420253Sjoerg					type = MAC_BIBA_TYPE_HIGH;
1165109961Sgad					break;
1166109961Sgad				}
1167109961Sgad			} else {
1168109961Sgad				*p = '\0';
1169109961Sgad				printf("mac_biba warning: interface name "
1170109961Sgad				    "\"%s\" is too long (must be < %d)\n",
1171109961Sgad				    q, IFNAMSIZ);
1172109961Sgad			}
1173109961Sgad			if (*p == '\0')
1174109961Sgad				break;
1175109961Sgad			q = p + 1;
1176109961Sgad		}
1177109961Sgad	}
117820253Sjoergset:
1179109961Sgad	mac_biba_set_single(dest, type, 0, NULL);
1180109961Sgad	mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1181109961Sgad}
1182109961Sgad
1183109961Sgadstatic void
1184109961Sgadmac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1185109961Sgad    struct ipq *ipq, struct label *ipqlabel)
1186109961Sgad{
1187109961Sgad	struct mac_biba *source, *dest;
1188109961Sgad
1189109961Sgad	source = SLOT(fragmentlabel);
1190109961Sgad	dest = SLOT(ipqlabel);
1191109961Sgad
1192109961Sgad	mac_biba_copy_single(source, dest);
1193109961Sgad}
1194109961Sgad
1195109961Sgadstatic void
1196109961Sgadmac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1197109961Sgad    struct mbuf *datagram, struct label *datagramlabel)
1198109961Sgad{
1199109961Sgad	struct mac_biba *source, *dest;
1200109961Sgad
1201109961Sgad	source = SLOT(ipqlabel);
1202109961Sgad	dest = SLOT(datagramlabel);
1203109961Sgad
1204109961Sgad	/* Just use the head, since we require them all to match. */
1205109961Sgad	mac_biba_copy_single(source, dest);
1206109961Sgad}
1207229237Sdim
1208109961Sgadstatic void
1209109961Sgadmac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1210109961Sgad    struct mbuf *fragment, struct label *fragmentlabel)
1211109961Sgad{
1212109961Sgad	struct mac_biba *source, *dest;
121320679Sdavidn
121420253Sjoerg	source = SLOT(datagramlabel);
121520253Sjoerg	dest = SLOT(fragmentlabel);
121620253Sjoerg
121720253Sjoerg	mac_biba_copy_single(source, dest);
121820253Sjoerg}
121920253Sjoerg
122020253Sjoergstatic void
122120253Sjoergmac_biba_create_mbuf_from_mbuf(struct mbuf *oldmbuf,
122220253Sjoerg    struct label *oldmbuflabel, struct mbuf *newmbuf,
122320253Sjoerg    struct label *newmbuflabel)
122420253Sjoerg{
122520253Sjoerg	struct mac_biba *source, *dest;
122620253Sjoerg
122720253Sjoerg	source = SLOT(oldmbuflabel);
122820253Sjoerg	dest = SLOT(newmbuflabel);
122920253Sjoerg
123020253Sjoerg	/*
123120253Sjoerg	 * Because the source mbuf may not yet have been "created",
123220253Sjoerg	 * just initialized, we do a conditional copy.  Since we don't
123320253Sjoerg	 * allow mbufs to have ranges, do a KASSERT to make sure that
123420253Sjoerg	 * doesn't happen.
123520253Sjoerg	 */
123620253Sjoerg	KASSERT((source->mb_flags & MAC_BIBA_FLAG_RANGE) == 0,
123720253Sjoerg	    ("mac_biba_create_mbuf_from_mbuf: source mbuf has range"));
123820253Sjoerg	mac_biba_copy(source, dest);
123920253Sjoerg}
124020253Sjoerg
124120747Sdavidnstatic void
124220747Sdavidnmac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
124385145Sache    struct mbuf *mbuf, struct label *mbuflabel)
124420747Sdavidn{
124585145Sache	struct mac_biba *dest;
124685145Sache
124720747Sdavidn	dest = SLOT(mbuflabel);
124821052Sdavidn
124921052Sdavidn	mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
125021052Sdavidn}
125121052Sdavidn
125220747Sdavidnstatic void
125321052Sdavidnmac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
125421052Sdavidn    struct mbuf *mbuf, struct label *mbuflabel)
125521052Sdavidn{
125621052Sdavidn	struct mac_biba *source, *dest;
125721052Sdavidn
125821052Sdavidn	source = SLOT(bpflabel);
125920747Sdavidn	dest = SLOT(mbuflabel);
126021052Sdavidn
126120747Sdavidn	mac_biba_copy_single(source, dest);
126221052Sdavidn}
126321052Sdavidn
126421052Sdavidnstatic void
126521052Sdavidnmac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
126620747Sdavidn    struct mbuf *m, struct label *mbuflabel)
126720747Sdavidn{
126820747Sdavidn	struct mac_biba *source, *dest;
1269
1270	source = SLOT(ifnetlabel);
1271	dest = SLOT(mbuflabel);
1272
1273	mac_biba_copy_single(source, dest);
1274}
1275
1276static void
1277mac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1278    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1279    struct mbuf *newmbuf, struct label *newmbuflabel)
1280{
1281	struct mac_biba *source, *dest;
1282
1283	source = SLOT(oldmbuflabel);
1284	dest = SLOT(newmbuflabel);
1285
1286	mac_biba_copy_single(source, dest);
1287}
1288
1289static void
1290mac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1291    struct mbuf *newmbuf, struct label *newmbuflabel)
1292{
1293	struct mac_biba *source, *dest;
1294
1295	source = SLOT(oldmbuflabel);
1296	dest = SLOT(newmbuflabel);
1297
1298	mac_biba_copy_single(source, dest);
1299}
1300
1301static int
1302mac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1303    struct ipq *ipq, struct label *ipqlabel)
1304{
1305	struct mac_biba *a, *b;
1306
1307	a = SLOT(ipqlabel);
1308	b = SLOT(fragmentlabel);
1309
1310	return (mac_biba_equal_single(a, b));
1311}
1312
1313static void
1314mac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1315    struct label *ifnetlabel, struct label *newlabel)
1316{
1317	struct mac_biba *source, *dest;
1318
1319	source = SLOT(newlabel);
1320	dest = SLOT(ifnetlabel);
1321
1322	mac_biba_copy(source, dest);
1323}
1324
1325static void
1326mac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1327    struct ipq *ipq, struct label *ipqlabel)
1328{
1329
1330	/* NOOP: we only accept matching labels, so no need to update */
1331}
1332
1333/*
1334 * Labeling event operations: processes.
1335 */
1336static void
1337mac_biba_create_cred(struct ucred *cred_parent, struct ucred *cred_child)
1338{
1339	struct mac_biba *source, *dest;
1340
1341	source = SLOT(&cred_parent->cr_label);
1342	dest = SLOT(&cred_child->cr_label);
1343
1344	mac_biba_copy_single(source, dest);
1345	mac_biba_copy_range(source, dest);
1346}
1347
1348static void
1349mac_biba_create_proc0(struct ucred *cred)
1350{
1351	struct mac_biba *dest;
1352
1353	dest = SLOT(&cred->cr_label);
1354
1355	mac_biba_set_single(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1356	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1357	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1358}
1359
1360static void
1361mac_biba_create_proc1(struct ucred *cred)
1362{
1363	struct mac_biba *dest;
1364
1365	dest = SLOT(&cred->cr_label);
1366
1367	mac_biba_set_single(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
1368	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1369	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1370}
1371
1372static void
1373mac_biba_relabel_cred(struct ucred *cred, struct label *newlabel)
1374{
1375	struct mac_biba *source, *dest;
1376
1377	source = SLOT(newlabel);
1378	dest = SLOT(&cred->cr_label);
1379
1380	mac_biba_copy(source, dest);
1381}
1382
1383/*
1384 * Access control checks.
1385 */
1386static int
1387mac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1388    struct ifnet *ifnet, struct label *ifnetlabel)
1389{
1390	struct mac_biba *a, *b;
1391
1392	if (!mac_biba_enabled)
1393		return (0);
1394
1395	a = SLOT(bpflabel);
1396	b = SLOT(ifnetlabel);
1397
1398	if (mac_biba_equal_single(a, b))
1399		return (0);
1400	return (EACCES);
1401}
1402
1403static int
1404mac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1405{
1406	struct mac_biba *subj, *new;
1407	int error;
1408
1409	subj = SLOT(&cred->cr_label);
1410	new = SLOT(newlabel);
1411
1412	/*
1413	 * If there is a Biba label update for the credential, it may
1414	 * be an update of the single, range, or both.
1415	 */
1416	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1417	if (error)
1418		return (error);
1419
1420	/*
1421	 * If the Biba label is to be changed, authorize as appropriate.
1422	 */
1423	if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1424		/*
1425		 * If the change request modifies both the Biba label
1426		 * single and range, check that the new single will be
1427		 * in the new range.
1428		 */
1429		if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
1430		    MAC_BIBA_FLAGS_BOTH &&
1431		    !mac_biba_single_in_range(new, new))
1432			return (EINVAL);
1433
1434		/*
1435		 * To change the Biba single label on a credential, the
1436		 * new single label must be in the current range.
1437		 */
1438		if (new->mb_flags & MAC_BIBA_FLAG_SINGLE &&
1439		    !mac_biba_single_in_range(new, subj))
1440			return (EPERM);
1441
1442		/*
1443		 * To change the Biba range on a credential, the new
1444		 * range label must be in the current range.
1445		 */
1446		if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
1447		    !mac_biba_range_in_range(new, subj))
1448			return (EPERM);
1449
1450		/*
1451		 * To have EQUAL in any component of the new credential
1452		 * Biba label, the subject must already have EQUAL in
1453		 * their label.
1454		 */
1455		if (mac_biba_contains_equal(new)) {
1456			error = mac_biba_subject_privileged(subj);
1457			if (error)
1458				return (error);
1459		}
1460	}
1461
1462	return (0);
1463}
1464
1465static int
1466mac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2)
1467{
1468	struct mac_biba *subj, *obj;
1469
1470	if (!mac_biba_enabled)
1471		return (0);
1472
1473	subj = SLOT(&u1->cr_label);
1474	obj = SLOT(&u2->cr_label);
1475
1476	/* XXX: range */
1477	if (!mac_biba_dominate_single(obj, subj))
1478		return (ESRCH);
1479
1480	return (0);
1481}
1482
1483static int
1484mac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1485    struct label *ifnetlabel, struct label *newlabel)
1486{
1487	struct mac_biba *subj, *new;
1488	int error;
1489
1490	subj = SLOT(&cred->cr_label);
1491	new = SLOT(newlabel);
1492
1493	/*
1494	 * If there is a Biba label update for the interface, it may
1495	 * be an update of the single, range, or both.
1496	 */
1497	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1498	if (error)
1499		return (error);
1500
1501	/*
1502	 * Relabling network interfaces requires Biba privilege.
1503	 */
1504	error = mac_biba_subject_privileged(subj);
1505	if (error)
1506		return (error);
1507
1508	/*
1509	 * If the Biba label is to be changed, authorize as appropriate.
1510	 */
1511	if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1512		/*
1513		 * Rely on the traditional superuser status for the Biba
1514		 * interface relabel requirements.  XXXMAC: This will go
1515		 * away.
1516		 */
1517		error = suser_cred(cred, 0);
1518		if (error)
1519			return (EPERM);
1520
1521		/*
1522		 * XXXMAC: Additional consistency tests regarding the single
1523		 * and the range of the new label might be performed here.
1524		 */
1525	}
1526
1527	return (0);
1528}
1529
1530static int
1531mac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1532    struct mbuf *m, struct label *mbuflabel)
1533{
1534	struct mac_biba *p, *i;
1535
1536	if (!mac_biba_enabled)
1537		return (0);
1538
1539	p = SLOT(mbuflabel);
1540	i = SLOT(ifnetlabel);
1541
1542	return (mac_biba_single_in_range(p, i) ? 0 : EACCES);
1543}
1544
1545static int
1546mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp,
1547    struct label *label)
1548{
1549	struct mac_biba *subj, *obj;
1550	int error;
1551
1552	if (!mac_biba_enabled)
1553		return (0);
1554
1555	subj = SLOT(&cred->cr_label);
1556
1557	error = mac_biba_subject_privileged(subj);
1558	if (error)
1559		return (error);
1560
1561	obj = SLOT(label);
1562	if (!mac_biba_high_single(obj))
1563		return (EACCES);
1564
1565	return (0);
1566}
1567
1568
1569static int
1570mac_biba_check_kld_unload(struct ucred *cred)
1571{
1572	struct mac_biba *subj;
1573
1574	if (!mac_biba_enabled)
1575		return (0);
1576
1577	subj = SLOT(&cred->cr_label);
1578
1579	return (mac_biba_subject_privileged(subj));
1580}
1581
1582static int
1583mac_biba_check_mount_stat(struct ucred *cred, struct mount *mp,
1584    struct label *mntlabel)
1585{
1586	struct mac_biba *subj, *obj;
1587
1588	if (!mac_biba_enabled)
1589		return (0);
1590
1591	subj = SLOT(&cred->cr_label);
1592	obj = SLOT(mntlabel);
1593
1594	if (!mac_biba_dominate_single(obj, subj))
1595		return (EACCES);
1596
1597	return (0);
1598}
1599
1600static int
1601mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipe *pipe,
1602    struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1603{
1604
1605	if(!mac_biba_enabled)
1606		return (0);
1607
1608	/* XXX: This will be implemented soon... */
1609
1610	return (0);
1611}
1612
1613static int
1614mac_biba_check_pipe_poll(struct ucred *cred, struct pipe *pipe,
1615    struct label *pipelabel)
1616{
1617	struct mac_biba *subj, *obj;
1618
1619	if (!mac_biba_enabled)
1620		return (0);
1621
1622	subj = SLOT(&cred->cr_label);
1623	obj = SLOT((pipelabel));
1624
1625	if (!mac_biba_dominate_single(obj, subj))
1626		return (EACCES);
1627
1628	return (0);
1629}
1630
1631static int
1632mac_biba_check_pipe_read(struct ucred *cred, struct pipe *pipe,
1633    struct label *pipelabel)
1634{
1635	struct mac_biba *subj, *obj;
1636
1637	if (!mac_biba_enabled)
1638		return (0);
1639
1640	subj = SLOT(&cred->cr_label);
1641	obj = SLOT((pipelabel));
1642
1643	if (!mac_biba_dominate_single(obj, subj))
1644		return (EACCES);
1645
1646	return (0);
1647}
1648
1649static int
1650mac_biba_check_pipe_relabel(struct ucred *cred, struct pipe *pipe,
1651    struct label *pipelabel, struct label *newlabel)
1652{
1653	struct mac_biba *subj, *obj, *new;
1654	int error;
1655
1656	new = SLOT(newlabel);
1657	subj = SLOT(&cred->cr_label);
1658	obj = SLOT(pipelabel);
1659
1660	/*
1661	 * If there is a Biba label update for a pipe, it must be a
1662	 * single update.
1663	 */
1664	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
1665	if (error)
1666		return (error);
1667
1668	/*
1669	 * To perform a relabel of a pipe (Biba label or not), Biba must
1670	 * authorize the relabel.
1671	 */
1672	if (!mac_biba_single_in_range(obj, subj))
1673		return (EPERM);
1674
1675	/*
1676	 * If the Biba label is to be changed, authorize as appropriate.
1677	 */
1678	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
1679		/*
1680		 * To change the Biba label on a pipe, the new pipe label
1681		 * must be in the subject range.
1682		 */
1683		if (!mac_biba_single_in_range(new, subj))
1684			return (EPERM);
1685
1686		/*
1687		 * To change the Biba label on a pipe to be EQUAL, the
1688		 * subject must have appropriate privilege.
1689		 */
1690		if (mac_biba_contains_equal(new)) {
1691			error = mac_biba_subject_privileged(subj);
1692			if (error)
1693				return (error);
1694		}
1695	}
1696
1697	return (0);
1698}
1699
1700static int
1701mac_biba_check_pipe_stat(struct ucred *cred, struct pipe *pipe,
1702    struct label *pipelabel)
1703{
1704	struct mac_biba *subj, *obj;
1705
1706	if (!mac_biba_enabled)
1707		return (0);
1708
1709	subj = SLOT(&cred->cr_label);
1710	obj = SLOT((pipelabel));
1711
1712	if (!mac_biba_dominate_single(obj, subj))
1713		return (EACCES);
1714
1715	return (0);
1716}
1717
1718static int
1719mac_biba_check_pipe_write(struct ucred *cred, struct pipe *pipe,
1720    struct label *pipelabel)
1721{
1722	struct mac_biba *subj, *obj;
1723
1724	if (!mac_biba_enabled)
1725		return (0);
1726
1727	subj = SLOT(&cred->cr_label);
1728	obj = SLOT((pipelabel));
1729
1730	if (!mac_biba_dominate_single(subj, obj))
1731		return (EACCES);
1732
1733	return (0);
1734}
1735
1736static int
1737mac_biba_check_proc_debug(struct ucred *cred, struct proc *proc)
1738{
1739	struct mac_biba *subj, *obj;
1740
1741	if (!mac_biba_enabled)
1742		return (0);
1743
1744	subj = SLOT(&cred->cr_label);
1745	obj = SLOT(&proc->p_ucred->cr_label);
1746
1747	/* XXX: range checks */
1748	if (!mac_biba_dominate_single(obj, subj))
1749		return (ESRCH);
1750	if (!mac_biba_dominate_single(subj, obj))
1751		return (EACCES);
1752
1753	return (0);
1754}
1755
1756static int
1757mac_biba_check_proc_sched(struct ucred *cred, struct proc *proc)
1758{
1759	struct mac_biba *subj, *obj;
1760
1761	if (!mac_biba_enabled)
1762		return (0);
1763
1764	subj = SLOT(&cred->cr_label);
1765	obj = SLOT(&proc->p_ucred->cr_label);
1766
1767	/* XXX: range checks */
1768	if (!mac_biba_dominate_single(obj, subj))
1769		return (ESRCH);
1770	if (!mac_biba_dominate_single(subj, obj))
1771		return (EACCES);
1772
1773	return (0);
1774}
1775
1776static int
1777mac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
1778{
1779	struct mac_biba *subj, *obj;
1780
1781	if (!mac_biba_enabled)
1782		return (0);
1783
1784	subj = SLOT(&cred->cr_label);
1785	obj = SLOT(&proc->p_ucred->cr_label);
1786
1787	/* XXX: range checks */
1788	if (!mac_biba_dominate_single(obj, subj))
1789		return (ESRCH);
1790	if (!mac_biba_dominate_single(subj, obj))
1791		return (EACCES);
1792
1793	return (0);
1794}
1795
1796static int
1797mac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel,
1798    struct mbuf *m, struct label *mbuflabel)
1799{
1800	struct mac_biba *p, *s;
1801
1802	if (!mac_biba_enabled)
1803		return (0);
1804
1805	p = SLOT(mbuflabel);
1806	s = SLOT(socketlabel);
1807
1808	return (mac_biba_equal_single(p, s) ? 0 : EACCES);
1809}
1810
1811static int
1812mac_biba_check_socket_relabel(struct ucred *cred, struct socket *so,
1813    struct label *socketlabel, struct label *newlabel)
1814{
1815	struct mac_biba *subj, *obj, *new;
1816	int error;
1817
1818	new = SLOT(newlabel);
1819	subj = SLOT(&cred->cr_label);
1820	obj = SLOT(socketlabel);
1821
1822	/*
1823	 * If there is a Biba label update for the socket, it may be
1824	 * an update of single.
1825	 */
1826	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
1827	if (error)
1828		return (error);
1829
1830	/*
1831	 * To relabel a socket, the old socket single must be in the subject
1832	 * range.
1833	 */
1834	if (!mac_biba_single_in_range(obj, subj))
1835		return (EPERM);
1836
1837	/*
1838	 * If the Biba label is to be changed, authorize as appropriate.
1839	 */
1840	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
1841		/*
1842		 * To relabel a socket, the new socket single must be in
1843		 * the subject range.
1844		 */
1845		if (!mac_biba_single_in_range(new, subj))
1846			return (EPERM);
1847
1848		/*
1849		 * To change the Biba label on the socket to contain EQUAL,
1850		 * the subject must have appropriate privilege.
1851		 */
1852		if (mac_biba_contains_equal(new)) {
1853			error = mac_biba_subject_privileged(subj);
1854			if (error)
1855				return (error);
1856		}
1857	}
1858
1859	return (0);
1860}
1861
1862static int
1863mac_biba_check_socket_visible(struct ucred *cred, struct socket *socket,
1864    struct label *socketlabel)
1865{
1866	struct mac_biba *subj, *obj;
1867
1868	if (!mac_biba_enabled)
1869		return (0);
1870
1871	subj = SLOT(&cred->cr_label);
1872	obj = SLOT(socketlabel);
1873
1874	if (!mac_biba_dominate_single(obj, subj))
1875		return (ENOENT);
1876
1877	return (0);
1878}
1879
1880static int
1881mac_biba_check_sysarch_ioperm(struct ucred *cred)
1882{
1883	struct mac_biba *subj;
1884	int error;
1885
1886	if (!mac_biba_enabled)
1887		return (0);
1888
1889	subj = SLOT(&cred->cr_label);
1890
1891	error = mac_biba_subject_privileged(subj);
1892	if (error)
1893		return (error);
1894
1895	return (0);
1896}
1897
1898static int
1899mac_biba_check_system_acct(struct ucred *cred, struct vnode *vp,
1900    struct label *label)
1901{
1902	struct mac_biba *subj, *obj;
1903	int error;
1904
1905	if (!mac_biba_enabled)
1906		return (0);
1907
1908	subj = SLOT(&cred->cr_label);
1909
1910	error = mac_biba_subject_privileged(subj);
1911	if (error)
1912		return (error);
1913
1914	if (label == NULL)
1915		return (0);
1916
1917	obj = SLOT(label);
1918	if (!mac_biba_high_single(obj))
1919		return (EACCES);
1920
1921	return (0);
1922}
1923
1924static int
1925mac_biba_check_system_settime(struct ucred *cred)
1926{
1927	struct mac_biba *subj;
1928	int error;
1929
1930	if (!mac_biba_enabled)
1931		return (0);
1932
1933	subj = SLOT(&cred->cr_label);
1934
1935	error = mac_biba_subject_privileged(subj);
1936	if (error)
1937		return (error);
1938
1939	return (0);
1940}
1941
1942static int
1943mac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp,
1944    struct label *label)
1945{
1946	struct mac_biba *subj, *obj;
1947	int error;
1948
1949	if (!mac_biba_enabled)
1950		return (0);
1951
1952	subj = SLOT(&cred->cr_label);
1953	obj = SLOT(label);
1954
1955	error = mac_biba_subject_privileged(subj);
1956	if (error)
1957		return (error);
1958
1959	if (!mac_biba_high_single(obj))
1960		return (EACCES);
1961
1962	return (0);
1963}
1964
1965static int
1966mac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp,
1967    struct label *label)
1968{
1969	struct mac_biba *subj, *obj;
1970	int error;
1971
1972	if (!mac_biba_enabled)
1973		return (0);
1974
1975	subj = SLOT(&cred->cr_label);
1976	obj = SLOT(label);
1977
1978	error = mac_biba_subject_privileged(subj);
1979	if (error)
1980		return (error);
1981
1982	return (0);
1983}
1984
1985static int
1986mac_biba_check_system_sysctl(struct ucred *cred, int *name, u_int namelen,
1987    void *old, size_t *oldlenp, int inkernel, void *new, size_t newlen)
1988{
1989	struct mac_biba *subj;
1990	int error;
1991
1992	if (!mac_biba_enabled)
1993		return (0);
1994
1995	subj = SLOT(&cred->cr_label);
1996
1997	/*
1998	 * In general, treat sysctl variables as biba/high, but also
1999	 * require privilege to change them, since they are a
2000	 * communications channel between grades.  Exempt MIB
2001	 * queries from this due to undocmented sysctl magic.
2002	 * XXXMAC: This probably requires some more review.
2003	 */
2004	if (new != NULL) {
2005		if (namelen > 0 && name[0] == 0)
2006			return (0);
2007
2008		if (!mac_biba_subject_dominate_high(subj))
2009			return (EACCES);
2010
2011		error = mac_biba_subject_privileged(subj);
2012		if (error)
2013			return (error);
2014	}
2015
2016	return (0);
2017}
2018
2019static int
2020mac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2021    struct label *dlabel)
2022{
2023	struct mac_biba *subj, *obj;
2024
2025	if (!mac_biba_enabled)
2026		return (0);
2027
2028	subj = SLOT(&cred->cr_label);
2029	obj = SLOT(dlabel);
2030
2031	if (!mac_biba_dominate_single(obj, subj))
2032		return (EACCES);
2033
2034	return (0);
2035}
2036
2037static int
2038mac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2039    struct label *dlabel)
2040{
2041	struct mac_biba *subj, *obj;
2042
2043	if (!mac_biba_enabled)
2044		return (0);
2045
2046	subj = SLOT(&cred->cr_label);
2047	obj = SLOT(dlabel);
2048
2049	if (!mac_biba_dominate_single(obj, subj))
2050		return (EACCES);
2051
2052	return (0);
2053}
2054
2055static int
2056mac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2057    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2058{
2059	struct mac_biba *subj, *obj;
2060
2061	if (!mac_biba_enabled)
2062		return (0);
2063
2064	subj = SLOT(&cred->cr_label);
2065	obj = SLOT(dlabel);
2066
2067	if (!mac_biba_dominate_single(subj, obj))
2068		return (EACCES);
2069
2070	return (0);
2071}
2072
2073static int
2074mac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2075    struct label *dlabel, struct vnode *vp, struct label *label,
2076    struct componentname *cnp)
2077{
2078	struct mac_biba *subj, *obj;
2079
2080	if (!mac_biba_enabled)
2081		return (0);
2082
2083	subj = SLOT(&cred->cr_label);
2084	obj = SLOT(dlabel);
2085
2086	if (!mac_biba_dominate_single(subj, obj))
2087		return (EACCES);
2088
2089	obj = SLOT(label);
2090
2091	if (!mac_biba_dominate_single(subj, obj))
2092		return (EACCES);
2093
2094	return (0);
2095}
2096
2097static int
2098mac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2099    struct label *label, acl_type_t type)
2100{
2101	struct mac_biba *subj, *obj;
2102
2103	if (!mac_biba_enabled)
2104		return (0);
2105
2106	subj = SLOT(&cred->cr_label);
2107	obj = SLOT(label);
2108
2109	if (!mac_biba_dominate_single(subj, obj))
2110		return (EACCES);
2111
2112	return (0);
2113}
2114
2115static int
2116mac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2117    struct label *label, struct image_params *imgp,
2118    struct label *execlabel)
2119{
2120	struct mac_biba *subj, *obj, *exec;
2121	int error;
2122
2123	if (execlabel != NULL) {
2124		/*
2125		 * We currently don't permit labels to be changed at
2126		 * exec-time as part of Biba, so disallow non-NULL
2127		 * Biba label elements in the execlabel.
2128		 */
2129		exec = SLOT(execlabel);
2130		error = biba_atmostflags(exec, 0);
2131		if (error)
2132			return (error);
2133	}
2134
2135	if (!mac_biba_enabled)
2136		return (0);
2137
2138	subj = SLOT(&cred->cr_label);
2139	obj = SLOT(label);
2140
2141	if (!mac_biba_dominate_single(obj, subj))
2142		return (EACCES);
2143
2144	return (0);
2145}
2146
2147static int
2148mac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2149    struct label *label, acl_type_t type)
2150{
2151	struct mac_biba *subj, *obj;
2152
2153	if (!mac_biba_enabled)
2154		return (0);
2155
2156	subj = SLOT(&cred->cr_label);
2157	obj = SLOT(label);
2158
2159	if (!mac_biba_dominate_single(obj, subj))
2160		return (EACCES);
2161
2162	return (0);
2163}
2164
2165static int
2166mac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2167    struct label *label, int attrnamespace, const char *name, struct uio *uio)
2168{
2169	struct mac_biba *subj, *obj;
2170
2171	if (!mac_biba_enabled)
2172		return (0);
2173
2174	subj = SLOT(&cred->cr_label);
2175	obj = SLOT(label);
2176
2177	if (!mac_biba_dominate_single(obj, subj))
2178		return (EACCES);
2179
2180	return (0);
2181}
2182
2183static int
2184mac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2185    struct label *dlabel, struct vnode *vp, struct label *label,
2186    struct componentname *cnp)
2187{
2188	struct mac_biba *subj, *obj;
2189
2190	if (!mac_biba_enabled)
2191		return (0);
2192
2193	subj = SLOT(&cred->cr_label);
2194	obj = SLOT(dlabel);
2195
2196	if (!mac_biba_dominate_single(subj, obj))
2197		return (EACCES);
2198
2199	obj = SLOT(label);
2200
2201	if (!mac_biba_dominate_single(subj, obj))
2202		return (EACCES);
2203
2204	return (0);
2205}
2206
2207static int
2208mac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2209    struct label *dlabel, struct componentname *cnp)
2210{
2211	struct mac_biba *subj, *obj;
2212
2213	if (!mac_biba_enabled)
2214		return (0);
2215
2216	subj = SLOT(&cred->cr_label);
2217	obj = SLOT(dlabel);
2218
2219	if (!mac_biba_dominate_single(obj, subj))
2220		return (EACCES);
2221
2222	return (0);
2223}
2224
2225static int
2226mac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2227    struct label *label, int prot)
2228{
2229	struct mac_biba *subj, *obj;
2230
2231	/*
2232	 * Rely on the use of open()-time protections to handle
2233	 * non-revocation cases.
2234	 */
2235	if (!mac_biba_enabled || !revocation_enabled)
2236		return (0);
2237
2238	subj = SLOT(&cred->cr_label);
2239	obj = SLOT(label);
2240
2241	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2242		if (!mac_biba_dominate_single(obj, subj))
2243			return (EACCES);
2244	}
2245	if (prot & VM_PROT_WRITE) {
2246		if (!mac_biba_dominate_single(subj, obj))
2247			return (EACCES);
2248	}
2249
2250	return (0);
2251}
2252
2253static int
2254mac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp,
2255    struct label *vnodelabel, int acc_mode)
2256{
2257	struct mac_biba *subj, *obj;
2258
2259	if (!mac_biba_enabled)
2260		return (0);
2261
2262	subj = SLOT(&cred->cr_label);
2263	obj = SLOT(vnodelabel);
2264
2265	/* XXX privilege override for admin? */
2266	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2267		if (!mac_biba_dominate_single(obj, subj))
2268			return (EACCES);
2269	}
2270	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2271		if (!mac_biba_dominate_single(subj, obj))
2272			return (EACCES);
2273	}
2274
2275	return (0);
2276}
2277
2278static int
2279mac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2280    struct vnode *vp, struct label *label)
2281{
2282	struct mac_biba *subj, *obj;
2283
2284	if (!mac_biba_enabled || !revocation_enabled)
2285		return (0);
2286
2287	subj = SLOT(&active_cred->cr_label);
2288	obj = SLOT(label);
2289
2290	if (!mac_biba_dominate_single(obj, subj))
2291		return (EACCES);
2292
2293	return (0);
2294}
2295
2296static int
2297mac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2298    struct vnode *vp, struct label *label)
2299{
2300	struct mac_biba *subj, *obj;
2301
2302	if (!mac_biba_enabled || !revocation_enabled)
2303		return (0);
2304
2305	subj = SLOT(&active_cred->cr_label);
2306	obj = SLOT(label);
2307
2308	if (!mac_biba_dominate_single(obj, subj))
2309		return (EACCES);
2310
2311	return (0);
2312}
2313
2314static int
2315mac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2316    struct label *dlabel)
2317{
2318	struct mac_biba *subj, *obj;
2319
2320	if (!mac_biba_enabled)
2321		return (0);
2322
2323	subj = SLOT(&cred->cr_label);
2324	obj = SLOT(dlabel);
2325
2326	if (!mac_biba_dominate_single(obj, subj))
2327		return (EACCES);
2328
2329	return (0);
2330}
2331
2332static int
2333mac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2334    struct label *label)
2335{
2336	struct mac_biba *subj, *obj;
2337
2338	if (!mac_biba_enabled)
2339		return (0);
2340
2341	subj = SLOT(&cred->cr_label);
2342	obj = SLOT(label);
2343
2344	if (!mac_biba_dominate_single(obj, subj))
2345		return (EACCES);
2346
2347	return (0);
2348}
2349
2350static int
2351mac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2352    struct label *vnodelabel, struct label *newlabel)
2353{
2354	struct mac_biba *old, *new, *subj;
2355	int error;
2356
2357	old = SLOT(vnodelabel);
2358	new = SLOT(newlabel);
2359	subj = SLOT(&cred->cr_label);
2360
2361	/*
2362	 * If there is a Biba label update for the vnode, it must be a
2363	 * single label.
2364	 */
2365	error = biba_atmostflags(new, MAC_BIBA_FLAG_SINGLE);
2366	if (error)
2367		return (error);
2368
2369	/*
2370	 * To perform a relabel of the vnode (Biba label or not), Biba must
2371	 * authorize the relabel.
2372	 */
2373	if (!mac_biba_single_in_range(old, subj))
2374		return (EPERM);
2375
2376	/*
2377	 * If the Biba label is to be changed, authorize as appropriate.
2378	 */
2379	if (new->mb_flags & MAC_BIBA_FLAG_SINGLE) {
2380		/*
2381		 * To change the Biba label on a vnode, the new vnode label
2382		 * must be in the subject range.
2383		 */
2384		if (!mac_biba_single_in_range(new, subj))
2385			return (EPERM);
2386
2387		/*
2388		 * To change the Biba label on the vnode to be EQUAL,
2389		 * the subject must have appropriate privilege.
2390		 */
2391		if (mac_biba_contains_equal(new)) {
2392			error = mac_biba_subject_privileged(subj);
2393			if (error)
2394				return (error);
2395		}
2396	}
2397
2398	return (0);
2399}
2400
2401static int
2402mac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2403    struct label *dlabel, struct vnode *vp, struct label *label,
2404    struct componentname *cnp)
2405{
2406	struct mac_biba *subj, *obj;
2407
2408	if (!mac_biba_enabled)
2409		return (0);
2410
2411	subj = SLOT(&cred->cr_label);
2412	obj = SLOT(dlabel);
2413
2414	if (!mac_biba_dominate_single(subj, obj))
2415		return (EACCES);
2416
2417	obj = SLOT(label);
2418
2419	if (!mac_biba_dominate_single(subj, obj))
2420		return (EACCES);
2421
2422	return (0);
2423}
2424
2425static int
2426mac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2427    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2428    struct componentname *cnp)
2429{
2430	struct mac_biba *subj, *obj;
2431
2432	if (!mac_biba_enabled)
2433		return (0);
2434
2435	subj = SLOT(&cred->cr_label);
2436	obj = SLOT(dlabel);
2437
2438	if (!mac_biba_dominate_single(subj, obj))
2439		return (EACCES);
2440
2441	if (vp != NULL) {
2442		obj = SLOT(label);
2443
2444		if (!mac_biba_dominate_single(subj, obj))
2445			return (EACCES);
2446	}
2447
2448	return (0);
2449}
2450
2451static int
2452mac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2453    struct label *label)
2454{
2455	struct mac_biba *subj, *obj;
2456
2457	if (!mac_biba_enabled)
2458		return (0);
2459
2460	subj = SLOT(&cred->cr_label);
2461	obj = SLOT(label);
2462
2463	if (!mac_biba_dominate_single(subj, obj))
2464		return (EACCES);
2465
2466	return (0);
2467}
2468
2469static int
2470mac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2471    struct label *label, acl_type_t type, struct acl *acl)
2472{
2473	struct mac_biba *subj, *obj;
2474
2475	if (!mac_biba_enabled)
2476		return (0);
2477
2478	subj = SLOT(&cred->cr_label);
2479	obj = SLOT(label);
2480
2481	if (!mac_biba_dominate_single(subj, obj))
2482		return (EACCES);
2483
2484	return (0);
2485}
2486
2487static int
2488mac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2489    struct label *vnodelabel, int attrnamespace, const char *name,
2490    struct uio *uio)
2491{
2492	struct mac_biba *subj, *obj;
2493
2494	if (!mac_biba_enabled)
2495		return (0);
2496
2497	subj = SLOT(&cred->cr_label);
2498	obj = SLOT(vnodelabel);
2499
2500	if (!mac_biba_dominate_single(subj, obj))
2501		return (EACCES);
2502
2503	/* XXX: protect the MAC EA in a special way? */
2504
2505	return (0);
2506}
2507
2508static int
2509mac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2510    struct label *vnodelabel, u_long flags)
2511{
2512	struct mac_biba *subj, *obj;
2513
2514	if (!mac_biba_enabled)
2515		return (0);
2516
2517	subj = SLOT(&cred->cr_label);
2518	obj = SLOT(vnodelabel);
2519
2520	if (!mac_biba_dominate_single(subj, obj))
2521		return (EACCES);
2522
2523	return (0);
2524}
2525
2526static int
2527mac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2528    struct label *vnodelabel, mode_t mode)
2529{
2530	struct mac_biba *subj, *obj;
2531
2532	if (!mac_biba_enabled)
2533		return (0);
2534
2535	subj = SLOT(&cred->cr_label);
2536	obj = SLOT(vnodelabel);
2537
2538	if (!mac_biba_dominate_single(subj, obj))
2539		return (EACCES);
2540
2541	return (0);
2542}
2543
2544static int
2545mac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2546    struct label *vnodelabel, uid_t uid, gid_t gid)
2547{
2548	struct mac_biba *subj, *obj;
2549
2550	if (!mac_biba_enabled)
2551		return (0);
2552
2553	subj = SLOT(&cred->cr_label);
2554	obj = SLOT(vnodelabel);
2555
2556	if (!mac_biba_dominate_single(subj, obj))
2557		return (EACCES);
2558
2559	return (0);
2560}
2561
2562static int
2563mac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2564    struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2565{
2566	struct mac_biba *subj, *obj;
2567
2568	if (!mac_biba_enabled)
2569		return (0);
2570
2571	subj = SLOT(&cred->cr_label);
2572	obj = SLOT(vnodelabel);
2573
2574	if (!mac_biba_dominate_single(subj, obj))
2575		return (EACCES);
2576
2577	return (0);
2578}
2579
2580static int
2581mac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2582    struct vnode *vp, struct label *vnodelabel)
2583{
2584	struct mac_biba *subj, *obj;
2585
2586	if (!mac_biba_enabled)
2587		return (0);
2588
2589	subj = SLOT(&active_cred->cr_label);
2590	obj = SLOT(vnodelabel);
2591
2592	if (!mac_biba_dominate_single(obj, subj))
2593		return (EACCES);
2594
2595	return (0);
2596}
2597
2598static int
2599mac_biba_check_vnode_write(struct ucred *active_cred,
2600    struct ucred *file_cred, struct vnode *vp, struct label *label)
2601{
2602	struct mac_biba *subj, *obj;
2603
2604	if (!mac_biba_enabled || !revocation_enabled)
2605		return (0);
2606
2607	subj = SLOT(&active_cred->cr_label);
2608	obj = SLOT(label);
2609
2610	if (!mac_biba_dominate_single(subj, obj))
2611		return (EACCES);
2612
2613	return (0);
2614}
2615
2616static struct mac_policy_ops mac_biba_ops =
2617{
2618	.mpo_destroy = mac_biba_destroy,
2619	.mpo_init = mac_biba_init,
2620	.mpo_init_bpfdesc_label = mac_biba_init_label,
2621	.mpo_init_cred_label = mac_biba_init_label,
2622	.mpo_init_devfsdirent_label = mac_biba_init_label,
2623	.mpo_init_ifnet_label = mac_biba_init_label,
2624	.mpo_init_ipq_label = mac_biba_init_label_waitcheck,
2625	.mpo_init_mbuf_label = mac_biba_init_label_waitcheck,
2626	.mpo_init_mount_label = mac_biba_init_label,
2627	.mpo_init_mount_fs_label = mac_biba_init_label,
2628	.mpo_init_pipe_label = mac_biba_init_label,
2629	.mpo_init_socket_label = mac_biba_init_label_waitcheck,
2630	.mpo_init_socket_peer_label = mac_biba_init_label_waitcheck,
2631	.mpo_init_vnode_label = mac_biba_init_label,
2632	.mpo_destroy_bpfdesc_label = mac_biba_destroy_label,
2633	.mpo_destroy_cred_label = mac_biba_destroy_label,
2634	.mpo_destroy_devfsdirent_label = mac_biba_destroy_label,
2635	.mpo_destroy_ifnet_label = mac_biba_destroy_label,
2636	.mpo_destroy_ipq_label = mac_biba_destroy_label,
2637	.mpo_destroy_mbuf_label = mac_biba_destroy_label,
2638	.mpo_destroy_mount_label = mac_biba_destroy_label,
2639	.mpo_destroy_mount_fs_label = mac_biba_destroy_label,
2640	.mpo_destroy_pipe_label = mac_biba_destroy_label,
2641	.mpo_destroy_socket_label = mac_biba_destroy_label,
2642	.mpo_destroy_socket_peer_label = mac_biba_destroy_label,
2643	.mpo_destroy_vnode_label = mac_biba_destroy_label,
2644	.mpo_copy_pipe_label = mac_biba_copy_label,
2645	.mpo_copy_vnode_label = mac_biba_copy_label,
2646	.mpo_externalize_cred_label = mac_biba_externalize_label,
2647	.mpo_externalize_ifnet_label = mac_biba_externalize_label,
2648	.mpo_externalize_pipe_label = mac_biba_externalize_label,
2649	.mpo_externalize_socket_label = mac_biba_externalize_label,
2650	.mpo_externalize_socket_peer_label = mac_biba_externalize_label,
2651	.mpo_externalize_vnode_label = mac_biba_externalize_label,
2652	.mpo_internalize_cred_label = mac_biba_internalize_label,
2653	.mpo_internalize_ifnet_label = mac_biba_internalize_label,
2654	.mpo_internalize_pipe_label = mac_biba_internalize_label,
2655	.mpo_internalize_socket_label = mac_biba_internalize_label,
2656	.mpo_internalize_vnode_label = mac_biba_internalize_label,
2657	.mpo_create_devfs_device = mac_biba_create_devfs_device,
2658	.mpo_create_devfs_directory = mac_biba_create_devfs_directory,
2659	.mpo_create_devfs_symlink = mac_biba_create_devfs_symlink,
2660	.mpo_create_mount = mac_biba_create_mount,
2661	.mpo_create_root_mount = mac_biba_create_root_mount,
2662	.mpo_relabel_vnode = mac_biba_relabel_vnode,
2663	.mpo_update_devfsdirent = mac_biba_update_devfsdirent,
2664	.mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs,
2665	.mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr,
2666	.mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel,
2667	.mpo_create_vnode_extattr = mac_biba_create_vnode_extattr,
2668	.mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr,
2669	.mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket,
2670	.mpo_create_pipe = mac_biba_create_pipe,
2671	.mpo_create_socket = mac_biba_create_socket,
2672	.mpo_create_socket_from_socket = mac_biba_create_socket_from_socket,
2673	.mpo_relabel_pipe = mac_biba_relabel_pipe,
2674	.mpo_relabel_socket = mac_biba_relabel_socket,
2675	.mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf,
2676	.mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket,
2677	.mpo_create_bpfdesc = mac_biba_create_bpfdesc,
2678	.mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq,
2679	.mpo_create_fragment = mac_biba_create_fragment,
2680	.mpo_create_ifnet = mac_biba_create_ifnet,
2681	.mpo_create_ipq = mac_biba_create_ipq,
2682	.mpo_create_mbuf_from_mbuf = mac_biba_create_mbuf_from_mbuf,
2683	.mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer,
2684	.mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc,
2685	.mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet,
2686	.mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap,
2687	.mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer,
2688	.mpo_fragment_match = mac_biba_fragment_match,
2689	.mpo_relabel_ifnet = mac_biba_relabel_ifnet,
2690	.mpo_update_ipq = mac_biba_update_ipq,
2691	.mpo_create_cred = mac_biba_create_cred,
2692	.mpo_create_proc0 = mac_biba_create_proc0,
2693	.mpo_create_proc1 = mac_biba_create_proc1,
2694	.mpo_relabel_cred = mac_biba_relabel_cred,
2695	.mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive,
2696	.mpo_check_cred_relabel = mac_biba_check_cred_relabel,
2697	.mpo_check_cred_visible = mac_biba_check_cred_visible,
2698	.mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel,
2699	.mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit,
2700	.mpo_check_kld_load = mac_biba_check_kld_load,
2701	.mpo_check_kld_unload = mac_biba_check_kld_unload,
2702	.mpo_check_mount_stat = mac_biba_check_mount_stat,
2703	.mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl,
2704	.mpo_check_pipe_poll = mac_biba_check_pipe_poll,
2705	.mpo_check_pipe_read = mac_biba_check_pipe_read,
2706	.mpo_check_pipe_relabel = mac_biba_check_pipe_relabel,
2707	.mpo_check_pipe_stat = mac_biba_check_pipe_stat,
2708	.mpo_check_pipe_write = mac_biba_check_pipe_write,
2709	.mpo_check_proc_debug = mac_biba_check_proc_debug,
2710	.mpo_check_proc_sched = mac_biba_check_proc_sched,
2711	.mpo_check_proc_signal = mac_biba_check_proc_signal,
2712	.mpo_check_socket_deliver = mac_biba_check_socket_deliver,
2713	.mpo_check_socket_relabel = mac_biba_check_socket_relabel,
2714	.mpo_check_socket_visible = mac_biba_check_socket_visible,
2715	.mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm,
2716	.mpo_check_system_acct = mac_biba_check_system_acct,
2717	.mpo_check_system_settime = mac_biba_check_system_settime,
2718	.mpo_check_system_swapon = mac_biba_check_system_swapon,
2719	.mpo_check_system_swapoff = mac_biba_check_system_swapoff,
2720	.mpo_check_system_sysctl = mac_biba_check_system_sysctl,
2721	.mpo_check_vnode_access = mac_biba_check_vnode_open,
2722	.mpo_check_vnode_chdir = mac_biba_check_vnode_chdir,
2723	.mpo_check_vnode_chroot = mac_biba_check_vnode_chroot,
2724	.mpo_check_vnode_create = mac_biba_check_vnode_create,
2725	.mpo_check_vnode_delete = mac_biba_check_vnode_delete,
2726	.mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl,
2727	.mpo_check_vnode_exec = mac_biba_check_vnode_exec,
2728	.mpo_check_vnode_getacl = mac_biba_check_vnode_getacl,
2729	.mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr,
2730	.mpo_check_vnode_link = mac_biba_check_vnode_link,
2731	.mpo_check_vnode_lookup = mac_biba_check_vnode_lookup,
2732	.mpo_check_vnode_mmap = mac_biba_check_vnode_mmap,
2733	.mpo_check_vnode_mprotect = mac_biba_check_vnode_mmap,
2734	.mpo_check_vnode_open = mac_biba_check_vnode_open,
2735	.mpo_check_vnode_poll = mac_biba_check_vnode_poll,
2736	.mpo_check_vnode_read = mac_biba_check_vnode_read,
2737	.mpo_check_vnode_readdir = mac_biba_check_vnode_readdir,
2738	.mpo_check_vnode_readlink = mac_biba_check_vnode_readlink,
2739	.mpo_check_vnode_relabel = mac_biba_check_vnode_relabel,
2740	.mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from,
2741	.mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to,
2742	.mpo_check_vnode_revoke = mac_biba_check_vnode_revoke,
2743	.mpo_check_vnode_setacl = mac_biba_check_vnode_setacl,
2744	.mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr,
2745	.mpo_check_vnode_setflags = mac_biba_check_vnode_setflags,
2746	.mpo_check_vnode_setmode = mac_biba_check_vnode_setmode,
2747	.mpo_check_vnode_setowner = mac_biba_check_vnode_setowner,
2748	.mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes,
2749	.mpo_check_vnode_stat = mac_biba_check_vnode_stat,
2750	.mpo_check_vnode_write = mac_biba_check_vnode_write,
2751};
2752
2753MAC_POLICY_SET(&mac_biba_ops, trustedbsd_mac_biba, "TrustedBSD MAC/Biba",
2754    MPC_LOADTIME_FLAG_NOTLATE, &mac_biba_slot);
2755