mac_biba.c revision 166617
138494Sobrien/*-
238494Sobrien * Copyright (c) 1999-2002, 2007 Robert N. M. Watson
338494Sobrien * Copyright (c) 2001-2005 McAfee, Inc.
438494Sobrien * All rights reserved.
538494Sobrien *
638494Sobrien * This software was developed by Robert Watson for the TrustedBSD Project.
738494Sobrien *
838494Sobrien * This software was developed for the FreeBSD Project in part by McAfee
938494Sobrien * Research, the Security Research Division of McAfee, Inc. under
1038494Sobrien * DARPA/SPAWAR contract N66001-01-C-8035 ("CBOSS"), as part of the DARPA
1138494Sobrien * CHATS research program.
1238494Sobrien *
1338494Sobrien * Redistribution and use in source and binary forms, with or without
1438494Sobrien * modification, are permitted provided that the following conditions
1538494Sobrien * are met:
1638494Sobrien * 1. Redistributions of source code must retain the above copyright
1738494Sobrien *    notice, this list of conditions and the following disclaimer.
1838494Sobrien * 2. Redistributions in binary form must reproduce the above copyright
1938494Sobrien *    notice, this list of conditions and the following disclaimer in the
2038494Sobrien *    documentation and/or other materials provided with the distribution.
2138494Sobrien *
2238494Sobrien * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
2338494Sobrien * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
2438494Sobrien * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
2538494Sobrien * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
2638494Sobrien * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
2738494Sobrien * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
2838494Sobrien * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
2938494Sobrien * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
3038494Sobrien * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
3138494Sobrien * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
3238494Sobrien * SUCH DAMAGE.
3338494Sobrien *
3438494Sobrien * $FreeBSD: head/sys/security/mac_biba/mac_biba.c 166617 2007-02-10 08:59:39Z rwatson $
3538494Sobrien */
3638494Sobrien
3738494Sobrien/*
3838494Sobrien * Developed by the TrustedBSD Project.
3938494Sobrien * Biba fixed label mandatory integrity policy.
4038494Sobrien */
4138494Sobrien
4238494Sobrien#include <sys/types.h>
4338494Sobrien#include <sys/param.h>
4438494Sobrien#include <sys/acl.h>
4538494Sobrien#include <sys/conf.h>
4638494Sobrien#include <sys/extattr.h>
4738494Sobrien#include <sys/kernel.h>
4838494Sobrien#include <sys/ksem.h>
4938494Sobrien#include <sys/malloc.h>
5038494Sobrien#include <sys/mman.h>
5138494Sobrien#include <sys/mount.h>
5238494Sobrien#include <sys/proc.h>
5338494Sobrien#include <sys/sbuf.h>
5438494Sobrien#include <sys/systm.h>
5538494Sobrien#include <sys/sysproto.h>
5638494Sobrien#include <sys/sysent.h>
5738494Sobrien#include <sys/systm.h>
5838494Sobrien#include <sys/vnode.h>
5938494Sobrien#include <sys/file.h>
6038494Sobrien#include <sys/socket.h>
6138494Sobrien#include <sys/socketvar.h>
6238494Sobrien#include <sys/pipe.h>
6338494Sobrien#include <sys/sx.h>
6438494Sobrien#include <sys/sysctl.h>
6538494Sobrien#include <sys/msg.h>
6638494Sobrien#include <sys/sem.h>
6738494Sobrien#include <sys/shm.h>
6838494Sobrien
6938494Sobrien#include <fs/devfs/devfs.h>
7038494Sobrien
7138494Sobrien#include <net/bpfdesc.h>
7238494Sobrien#include <net/if.h>
7338494Sobrien#include <net/if_types.h>
7438494Sobrien#include <net/if_var.h>
7538494Sobrien
7638494Sobrien#include <netinet/in.h>
7738494Sobrien#include <netinet/in_pcb.h>
7838494Sobrien#include <netinet/ip_var.h>
7938494Sobrien
8038494Sobrien#include <vm/uma.h>
8138494Sobrien#include <vm/vm.h>
8238494Sobrien
8338494Sobrien#include <security/mac/mac_policy.h>
8438494Sobrien#include <security/mac_biba/mac_biba.h>
8538494Sobrien
8638494SobrienSYSCTL_DECL(_security_mac);
8738494Sobrien
8838494SobrienSYSCTL_NODE(_security_mac, OID_AUTO, biba, CTLFLAG_RW, 0,
8938494Sobrien    "TrustedBSD mac_biba policy controls");
9038494Sobrien
9138494Sobrienstatic int	mac_biba_label_size = sizeof(struct mac_biba);
9238494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, label_size, CTLFLAG_RD,
9338494Sobrien    &mac_biba_label_size, 0, "Size of struct mac_biba");
9438494Sobrien
9538494Sobrienstatic int	mac_biba_enabled = 1;
9638494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, enabled, CTLFLAG_RW,
9738494Sobrien    &mac_biba_enabled, 0, "Enforce MAC/Biba policy");
9838494SobrienTUNABLE_INT("security.mac.biba.enabled", &mac_biba_enabled);
9938494Sobrien
10038494Sobrienstatic int	destroyed_not_inited;
10138494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, destroyed_not_inited, CTLFLAG_RD,
10238494Sobrien    &destroyed_not_inited, 0, "Count of labels destroyed but not inited");
10338494Sobrien
10438494Sobrienstatic int	trust_all_interfaces = 0;
10538494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, trust_all_interfaces, CTLFLAG_RD,
10638494Sobrien    &trust_all_interfaces, 0, "Consider all interfaces 'trusted' by MAC/Biba");
10738494SobrienTUNABLE_INT("security.mac.biba.trust_all_interfaces", &trust_all_interfaces);
10838494Sobrien
10938494Sobrienstatic char	trusted_interfaces[128];
11038494SobrienSYSCTL_STRING(_security_mac_biba, OID_AUTO, trusted_interfaces, CTLFLAG_RD,
11138494Sobrien    trusted_interfaces, 0, "Interfaces considered 'trusted' by MAC/Biba");
11238494SobrienTUNABLE_STR("security.mac.biba.trusted_interfaces", trusted_interfaces,
11338494Sobrien    sizeof(trusted_interfaces));
11438494Sobrien
11538494Sobrienstatic int	max_compartments = MAC_BIBA_MAX_COMPARTMENTS;
11638494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, max_compartments, CTLFLAG_RD,
11738494Sobrien    &max_compartments, 0, "Maximum supported compartments");
11838494Sobrien
11938494Sobrienstatic int	ptys_equal = 0;
12038494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, ptys_equal, CTLFLAG_RW,
12138494Sobrien    &ptys_equal, 0, "Label pty devices as biba/equal on create");
12238494SobrienTUNABLE_INT("security.mac.biba.ptys_equal", &ptys_equal);
12338494Sobrien
12438494Sobrienstatic int	interfaces_equal;
12538494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, interfaces_equal, CTLFLAG_RW,
12638494Sobrien    &interfaces_equal, 0, "Label network interfaces as biba/equal on create");
12738494SobrienTUNABLE_INT("security.mac.biba.interfaces_equal", &interfaces_equal);
12838494Sobrien
12938494Sobrienstatic int	revocation_enabled = 0;
13038494SobrienSYSCTL_INT(_security_mac_biba, OID_AUTO, revocation_enabled, CTLFLAG_RW,
13138494Sobrien    &revocation_enabled, 0, "Revoke access to objects on relabel");
13238494SobrienTUNABLE_INT("security.mac.biba.revocation_enabled", &revocation_enabled);
13338494Sobrien
13438494Sobrienstatic int	mac_biba_slot;
13538494Sobrien#define	SLOT(l)	((struct mac_biba *)mac_label_get((l), mac_biba_slot))
13638494Sobrien#define	SLOT_SET(l, val) mac_label_set((l), mac_biba_slot, (uintptr_t)(val))
13738494Sobrien
13838494Sobrienstatic uma_zone_t	zone_biba;
13938494Sobrien
14038494Sobrienstatic __inline int
14138494Sobrienbiba_bit_set_empty(u_char *set) {
14238494Sobrien	int i;
14338494Sobrien
14438494Sobrien	for (i = 0; i < MAC_BIBA_MAX_COMPARTMENTS >> 3; i++)
14538494Sobrien		if (set[i] != 0)
14638494Sobrien			return (0);
14738494Sobrien	return (1);
14838494Sobrien}
14938494Sobrien
15038494Sobrienstatic struct mac_biba *
15138494Sobrienbiba_alloc(int flag)
15238494Sobrien{
15338494Sobrien
15438494Sobrien	return (uma_zalloc(zone_biba, flag | M_ZERO));
15538494Sobrien}
15638494Sobrien
15738494Sobrienstatic void
15838494Sobrienbiba_free(struct mac_biba *mac_biba)
15938494Sobrien{
16038494Sobrien
16138494Sobrien	if (mac_biba != NULL)
16238494Sobrien		uma_zfree(zone_biba, mac_biba);
16338494Sobrien	else
16438494Sobrien		atomic_add_int(&destroyed_not_inited, 1);
16538494Sobrien}
16638494Sobrien
16738494Sobrienstatic int
16838494Sobrienbiba_atmostflags(struct mac_biba *mac_biba, int flags)
16938494Sobrien{
17038494Sobrien
17138494Sobrien	if ((mac_biba->mb_flags & flags) != mac_biba->mb_flags)
17238494Sobrien		return (EINVAL);
17338494Sobrien	return (0);
17438494Sobrien}
17538494Sobrien
17638494Sobrienstatic int
17738494Sobrienmac_biba_dominate_element(struct mac_biba_element *a,
17838494Sobrien    struct mac_biba_element *b)
17938494Sobrien{
18038494Sobrien	int bit;
18138494Sobrien
18238494Sobrien	switch (a->mbe_type) {
18338494Sobrien	case MAC_BIBA_TYPE_EQUAL:
18438494Sobrien	case MAC_BIBA_TYPE_HIGH:
18538494Sobrien		return (1);
18638494Sobrien
18738494Sobrien	case MAC_BIBA_TYPE_LOW:
18838494Sobrien		switch (b->mbe_type) {
18938494Sobrien		case MAC_BIBA_TYPE_GRADE:
19038494Sobrien		case MAC_BIBA_TYPE_HIGH:
19138494Sobrien			return (0);
19238494Sobrien
19338494Sobrien		case MAC_BIBA_TYPE_EQUAL:
19438494Sobrien		case MAC_BIBA_TYPE_LOW:
19538494Sobrien			return (1);
19638494Sobrien
19738494Sobrien		default:
19838494Sobrien			panic("mac_biba_dominate_element: b->mbe_type invalid");
19938494Sobrien		}
20038494Sobrien
20138494Sobrien	case MAC_BIBA_TYPE_GRADE:
20238494Sobrien		switch (b->mbe_type) {
20338494Sobrien		case MAC_BIBA_TYPE_EQUAL:
20438494Sobrien		case MAC_BIBA_TYPE_LOW:
20538494Sobrien			return (1);
20638494Sobrien
20738494Sobrien		case MAC_BIBA_TYPE_HIGH:
20838494Sobrien			return (0);
20938494Sobrien
21038494Sobrien		case MAC_BIBA_TYPE_GRADE:
21138494Sobrien			for (bit = 1; bit <= MAC_BIBA_MAX_COMPARTMENTS; bit++)
21238494Sobrien				if (!MAC_BIBA_BIT_TEST(bit,
21338494Sobrien				    a->mbe_compartments) &&
21438494Sobrien				    MAC_BIBA_BIT_TEST(bit, b->mbe_compartments))
21538494Sobrien					return (0);
21638494Sobrien			return (a->mbe_grade >= b->mbe_grade);
21738494Sobrien
21838494Sobrien		default:
21938494Sobrien			panic("mac_biba_dominate_element: b->mbe_type invalid");
22038494Sobrien		}
22138494Sobrien
22238494Sobrien	default:
22338494Sobrien		panic("mac_biba_dominate_element: a->mbe_type invalid");
22438494Sobrien	}
22538494Sobrien
22638494Sobrien	return (0);
22738494Sobrien}
22838494Sobrien
22938494Sobrienstatic int
23038494Sobrienmac_biba_subject_dominate_high(struct mac_biba *mac_biba)
23138494Sobrien{
23238494Sobrien	struct mac_biba_element *element;
23338494Sobrien
23438494Sobrien	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
23538494Sobrien	    ("mac_biba_effective_in_range: mac_biba not effective"));
23638494Sobrien	element = &mac_biba->mb_effective;
237
238	return (element->mbe_type == MAC_BIBA_TYPE_EQUAL ||
239	    element->mbe_type == MAC_BIBA_TYPE_HIGH);
240}
241
242static int
243mac_biba_range_in_range(struct mac_biba *rangea, struct mac_biba *rangeb)
244{
245
246	return (mac_biba_dominate_element(&rangeb->mb_rangehigh,
247	    &rangea->mb_rangehigh) &&
248	    mac_biba_dominate_element(&rangea->mb_rangelow,
249	    &rangeb->mb_rangelow));
250}
251
252static int
253mac_biba_effective_in_range(struct mac_biba *effective,
254    struct mac_biba *range)
255{
256
257	KASSERT((effective->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
258	    ("mac_biba_effective_in_range: a not effective"));
259	KASSERT((range->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
260	    ("mac_biba_effective_in_range: b not range"));
261
262	return (mac_biba_dominate_element(&range->mb_rangehigh,
263	    &effective->mb_effective) &&
264	    mac_biba_dominate_element(&effective->mb_effective,
265	    &range->mb_rangelow));
266
267	return (1);
268}
269
270static int
271mac_biba_dominate_effective(struct mac_biba *a, struct mac_biba *b)
272{
273	KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
274	    ("mac_biba_dominate_effective: a not effective"));
275	KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
276	    ("mac_biba_dominate_effective: b not effective"));
277
278	return (mac_biba_dominate_element(&a->mb_effective, &b->mb_effective));
279}
280
281static int
282mac_biba_equal_element(struct mac_biba_element *a, struct mac_biba_element *b)
283{
284
285	if (a->mbe_type == MAC_BIBA_TYPE_EQUAL ||
286	    b->mbe_type == MAC_BIBA_TYPE_EQUAL)
287		return (1);
288
289	return (a->mbe_type == b->mbe_type && a->mbe_grade == b->mbe_grade);
290}
291
292static int
293mac_biba_equal_effective(struct mac_biba *a, struct mac_biba *b)
294{
295
296	KASSERT((a->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
297	    ("mac_biba_equal_effective: a not effective"));
298	KASSERT((b->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
299	    ("mac_biba_equal_effective: b not effective"));
300
301	return (mac_biba_equal_element(&a->mb_effective, &b->mb_effective));
302}
303
304static int
305mac_biba_contains_equal(struct mac_biba *mac_biba)
306{
307
308	if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
309		if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
310			return (1);
311
312	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
313		if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL)
314			return (1);
315		if (mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
316			return (1);
317	}
318
319	return (0);
320}
321
322static int
323mac_biba_subject_privileged(struct mac_biba *mac_biba)
324{
325
326	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
327	    MAC_BIBA_FLAGS_BOTH,
328	    ("mac_biba_subject_privileged: subject doesn't have both labels"));
329
330	/* If the effective is EQUAL, it's ok. */
331	if (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_EQUAL)
332		return (0);
333
334	/* If either range endpoint is EQUAL, it's ok. */
335	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_EQUAL ||
336	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_EQUAL)
337		return (0);
338
339	/* If the range is low-high, it's ok. */
340	if (mac_biba->mb_rangelow.mbe_type == MAC_BIBA_TYPE_LOW &&
341	    mac_biba->mb_rangehigh.mbe_type == MAC_BIBA_TYPE_HIGH)
342		return (0);
343
344	/* It's not ok. */
345	return (EPERM);
346}
347
348static int
349mac_biba_high_effective(struct mac_biba *mac_biba)
350{
351
352	KASSERT((mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
353	    ("mac_biba_equal_effective: mac_biba not effective"));
354
355	return (mac_biba->mb_effective.mbe_type == MAC_BIBA_TYPE_HIGH);
356}
357
358static int
359mac_biba_valid(struct mac_biba *mac_biba)
360{
361
362	if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
363		switch (mac_biba->mb_effective.mbe_type) {
364		case MAC_BIBA_TYPE_GRADE:
365			break;
366
367		case MAC_BIBA_TYPE_EQUAL:
368		case MAC_BIBA_TYPE_HIGH:
369		case MAC_BIBA_TYPE_LOW:
370			if (mac_biba->mb_effective.mbe_grade != 0 ||
371			    !MAC_BIBA_BIT_SET_EMPTY(
372			    mac_biba->mb_effective.mbe_compartments))
373				return (EINVAL);
374			break;
375
376		default:
377			return (EINVAL);
378		}
379	} else {
380		if (mac_biba->mb_effective.mbe_type != MAC_BIBA_TYPE_UNDEF)
381			return (EINVAL);
382	}
383
384	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
385		switch (mac_biba->mb_rangelow.mbe_type) {
386		case MAC_BIBA_TYPE_GRADE:
387			break;
388
389		case MAC_BIBA_TYPE_EQUAL:
390		case MAC_BIBA_TYPE_HIGH:
391		case MAC_BIBA_TYPE_LOW:
392			if (mac_biba->mb_rangelow.mbe_grade != 0 ||
393			    !MAC_BIBA_BIT_SET_EMPTY(
394			    mac_biba->mb_rangelow.mbe_compartments))
395				return (EINVAL);
396			break;
397
398		default:
399			return (EINVAL);
400		}
401
402		switch (mac_biba->mb_rangehigh.mbe_type) {
403		case MAC_BIBA_TYPE_GRADE:
404			break;
405
406		case MAC_BIBA_TYPE_EQUAL:
407		case MAC_BIBA_TYPE_HIGH:
408		case MAC_BIBA_TYPE_LOW:
409			if (mac_biba->mb_rangehigh.mbe_grade != 0 ||
410			    !MAC_BIBA_BIT_SET_EMPTY(
411			    mac_biba->mb_rangehigh.mbe_compartments))
412				return (EINVAL);
413			break;
414
415		default:
416			return (EINVAL);
417		}
418		if (!mac_biba_dominate_element(&mac_biba->mb_rangehigh,
419		    &mac_biba->mb_rangelow))
420			return (EINVAL);
421	} else {
422		if (mac_biba->mb_rangelow.mbe_type != MAC_BIBA_TYPE_UNDEF ||
423		    mac_biba->mb_rangehigh.mbe_type != MAC_BIBA_TYPE_UNDEF)
424			return (EINVAL);
425	}
426
427	return (0);
428}
429
430static void
431mac_biba_set_range(struct mac_biba *mac_biba, u_short typelow,
432    u_short gradelow, u_char *compartmentslow, u_short typehigh,
433    u_short gradehigh, u_char *compartmentshigh)
434{
435
436	mac_biba->mb_rangelow.mbe_type = typelow;
437	mac_biba->mb_rangelow.mbe_grade = gradelow;
438	if (compartmentslow != NULL)
439		memcpy(mac_biba->mb_rangelow.mbe_compartments,
440		    compartmentslow,
441		    sizeof(mac_biba->mb_rangelow.mbe_compartments));
442	mac_biba->mb_rangehigh.mbe_type = typehigh;
443	mac_biba->mb_rangehigh.mbe_grade = gradehigh;
444	if (compartmentshigh != NULL)
445		memcpy(mac_biba->mb_rangehigh.mbe_compartments,
446		    compartmentshigh,
447		    sizeof(mac_biba->mb_rangehigh.mbe_compartments));
448	mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
449}
450
451static void
452mac_biba_set_effective(struct mac_biba *mac_biba, u_short type, u_short grade,
453    u_char *compartments)
454{
455
456	mac_biba->mb_effective.mbe_type = type;
457	mac_biba->mb_effective.mbe_grade = grade;
458	if (compartments != NULL)
459		memcpy(mac_biba->mb_effective.mbe_compartments, compartments,
460		    sizeof(mac_biba->mb_effective.mbe_compartments));
461	mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
462}
463
464static void
465mac_biba_copy_range(struct mac_biba *labelfrom, struct mac_biba *labelto)
466{
467
468	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_RANGE) != 0,
469	    ("mac_biba_copy_range: labelfrom not range"));
470
471	labelto->mb_rangelow = labelfrom->mb_rangelow;
472	labelto->mb_rangehigh = labelfrom->mb_rangehigh;
473	labelto->mb_flags |= MAC_BIBA_FLAG_RANGE;
474}
475
476static void
477mac_biba_copy_effective(struct mac_biba *labelfrom, struct mac_biba *labelto)
478{
479
480	KASSERT((labelfrom->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) != 0,
481	    ("mac_biba_copy_effective: labelfrom not effective"));
482
483	labelto->mb_effective = labelfrom->mb_effective;
484	labelto->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
485}
486
487static void
488mac_biba_copy(struct mac_biba *source, struct mac_biba *dest)
489{
490
491	if (source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE)
492		mac_biba_copy_effective(source, dest);
493	if (source->mb_flags & MAC_BIBA_FLAG_RANGE)
494		mac_biba_copy_range(source, dest);
495}
496
497/*
498 * Policy module operations.
499 */
500static void
501mac_biba_init(struct mac_policy_conf *conf)
502{
503
504	zone_biba = uma_zcreate("mac_biba", sizeof(struct mac_biba), NULL,
505	    NULL, NULL, NULL, UMA_ALIGN_PTR, 0);
506}
507
508/*
509 * Label operations.
510 */
511static void
512mac_biba_init_label(struct label *label)
513{
514
515	SLOT_SET(label, biba_alloc(M_WAITOK));
516}
517
518static int
519mac_biba_init_label_waitcheck(struct label *label, int flag)
520{
521
522	SLOT_SET(label, biba_alloc(flag));
523	if (SLOT(label) == NULL)
524		return (ENOMEM);
525
526	return (0);
527}
528
529static void
530mac_biba_destroy_label(struct label *label)
531{
532
533	biba_free(SLOT(label));
534	SLOT_SET(label, NULL);
535}
536
537/*
538 * mac_biba_element_to_string() accepts an sbuf and Biba element.  It
539 * converts the Biba element to a string and stores the result in the
540 * sbuf; if there isn't space in the sbuf, -1 is returned.
541 */
542static int
543mac_biba_element_to_string(struct sbuf *sb, struct mac_biba_element *element)
544{
545	int i, first;
546
547	switch (element->mbe_type) {
548	case MAC_BIBA_TYPE_HIGH:
549		return (sbuf_printf(sb, "high"));
550
551	case MAC_BIBA_TYPE_LOW:
552		return (sbuf_printf(sb, "low"));
553
554	case MAC_BIBA_TYPE_EQUAL:
555		return (sbuf_printf(sb, "equal"));
556
557	case MAC_BIBA_TYPE_GRADE:
558		if (sbuf_printf(sb, "%d", element->mbe_grade) == -1)
559			return (-1);
560
561		first = 1;
562		for (i = 1; i <= MAC_BIBA_MAX_COMPARTMENTS; i++) {
563			if (MAC_BIBA_BIT_TEST(i, element->mbe_compartments)) {
564				if (first) {
565					if (sbuf_putc(sb, ':') == -1)
566						return (-1);
567					if (sbuf_printf(sb, "%d", i) == -1)
568						return (-1);
569					first = 0;
570				} else {
571					if (sbuf_printf(sb, "+%d", i) == -1)
572						return (-1);
573				}
574			}
575		}
576		return (0);
577
578	default:
579		panic("mac_biba_element_to_string: invalid type (%d)",
580		    element->mbe_type);
581	}
582}
583
584/*
585 * mac_biba_to_string() converts a Biba label to a string, and places
586 * the results in the passed sbuf.  It returns 0 on success, or EINVAL
587 * if there isn't room in the sbuf.  Note: the sbuf will be modified
588 * even in a failure case, so the caller may need to revert the sbuf
589 * by restoring the offset if that's undesired.
590 */
591static int
592mac_biba_to_string(struct sbuf *sb, struct mac_biba *mac_biba)
593{
594
595	if (mac_biba->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
596		if (mac_biba_element_to_string(sb, &mac_biba->mb_effective)
597		    == -1)
598			return (EINVAL);
599	}
600
601	if (mac_biba->mb_flags & MAC_BIBA_FLAG_RANGE) {
602		if (sbuf_putc(sb, '(') == -1)
603			return (EINVAL);
604
605		if (mac_biba_element_to_string(sb, &mac_biba->mb_rangelow)
606		    == -1)
607			return (EINVAL);
608
609		if (sbuf_putc(sb, '-') == -1)
610			return (EINVAL);
611
612		if (mac_biba_element_to_string(sb, &mac_biba->mb_rangehigh)
613		    == -1)
614			return (EINVAL);
615
616		if (sbuf_putc(sb, ')') == -1)
617			return (EINVAL);
618	}
619
620	return (0);
621}
622
623static int
624mac_biba_externalize_label(struct label *label, char *element_name,
625    struct sbuf *sb, int *claimed)
626{
627	struct mac_biba *mac_biba;
628
629	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
630		return (0);
631
632	(*claimed)++;
633
634	mac_biba = SLOT(label);
635	return (mac_biba_to_string(sb, mac_biba));
636}
637
638static int
639mac_biba_parse_element(struct mac_biba_element *element, char *string)
640{
641	char *compartment, *end, *grade;
642	int value;
643
644	if (strcmp(string, "high") == 0 ||
645	    strcmp(string, "hi") == 0) {
646		element->mbe_type = MAC_BIBA_TYPE_HIGH;
647		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
648	} else if (strcmp(string, "low") == 0 ||
649	    strcmp(string, "lo") == 0) {
650		element->mbe_type = MAC_BIBA_TYPE_LOW;
651		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
652	} else if (strcmp(string, "equal") == 0 ||
653	    strcmp(string, "eq") == 0) {
654		element->mbe_type = MAC_BIBA_TYPE_EQUAL;
655		element->mbe_grade = MAC_BIBA_TYPE_UNDEF;
656	} else {
657		element->mbe_type = MAC_BIBA_TYPE_GRADE;
658
659		/*
660		 * Numeric grade piece of the element.
661		 */
662		grade = strsep(&string, ":");
663		value = strtol(grade, &end, 10);
664		if (end == grade || *end != '\0')
665			return (EINVAL);
666		if (value < 0 || value > 65535)
667			return (EINVAL);
668		element->mbe_grade = value;
669
670		/*
671		 * Optional compartment piece of the element.  If none
672		 * are included, we assume that the label has no
673		 * compartments.
674		 */
675		if (string == NULL)
676			return (0);
677		if (*string == '\0')
678			return (0);
679
680		while ((compartment = strsep(&string, "+")) != NULL) {
681			value = strtol(compartment, &end, 10);
682			if (compartment == end || *end != '\0')
683				return (EINVAL);
684			if (value < 1 || value > MAC_BIBA_MAX_COMPARTMENTS)
685				return (EINVAL);
686			MAC_BIBA_BIT_SET(value, element->mbe_compartments);
687		}
688	}
689
690	return (0);
691}
692
693/*
694 * Note: destructively consumes the string, make a local copy before
695 * calling if that's a problem.
696 */
697static int
698mac_biba_parse(struct mac_biba *mac_biba, char *string)
699{
700	char *rangehigh, *rangelow, *effective;
701	int error;
702
703	effective = strsep(&string, "(");
704	if (*effective == '\0')
705		effective = NULL;
706
707	if (string != NULL) {
708		rangelow = strsep(&string, "-");
709		if (string == NULL)
710			return (EINVAL);
711		rangehigh = strsep(&string, ")");
712		if (string == NULL)
713			return (EINVAL);
714		if (*string != '\0')
715			return (EINVAL);
716	} else {
717		rangelow = NULL;
718		rangehigh = NULL;
719	}
720
721	KASSERT((rangelow != NULL && rangehigh != NULL) ||
722	    (rangelow == NULL && rangehigh == NULL),
723	    ("mac_biba_parse: range mismatch"));
724
725	bzero(mac_biba, sizeof(*mac_biba));
726	if (effective != NULL) {
727		error = mac_biba_parse_element(&mac_biba->mb_effective, effective);
728		if (error)
729			return (error);
730		mac_biba->mb_flags |= MAC_BIBA_FLAG_EFFECTIVE;
731	}
732
733	if (rangelow != NULL) {
734		error = mac_biba_parse_element(&mac_biba->mb_rangelow,
735		    rangelow);
736		if (error)
737			return (error);
738		error = mac_biba_parse_element(&mac_biba->mb_rangehigh,
739		    rangehigh);
740		if (error)
741			return (error);
742		mac_biba->mb_flags |= MAC_BIBA_FLAG_RANGE;
743	}
744
745	error = mac_biba_valid(mac_biba);
746	if (error)
747		return (error);
748
749	return (0);
750}
751
752static int
753mac_biba_internalize_label(struct label *label, char *element_name,
754    char *element_data, int *claimed)
755{
756	struct mac_biba *mac_biba, mac_biba_temp;
757	int error;
758
759	if (strcmp(MAC_BIBA_LABEL_NAME, element_name) != 0)
760		return (0);
761
762	(*claimed)++;
763
764	error = mac_biba_parse(&mac_biba_temp, element_data);
765	if (error)
766		return (error);
767
768	mac_biba = SLOT(label);
769	*mac_biba = mac_biba_temp;
770
771	return (0);
772}
773
774static void
775mac_biba_copy_label(struct label *src, struct label *dest)
776{
777
778	*SLOT(dest) = *SLOT(src);
779}
780
781/*
782 * Labeling event operations: file system objects, and things that look
783 * a lot like file system objects.
784 */
785static void
786mac_biba_create_devfs_device(struct ucred *cred, struct mount *mp,
787    struct cdev *dev, struct devfs_dirent *devfs_dirent, struct label *label)
788{
789	struct mac_biba *mac_biba;
790	int biba_type;
791
792	mac_biba = SLOT(label);
793	if (strcmp(dev->si_name, "null") == 0 ||
794	    strcmp(dev->si_name, "zero") == 0 ||
795	    strcmp(dev->si_name, "random") == 0 ||
796	    strncmp(dev->si_name, "fd/", strlen("fd/")) == 0)
797		biba_type = MAC_BIBA_TYPE_EQUAL;
798	else if (ptys_equal &&
799	    (strncmp(dev->si_name, "ttyp", strlen("ttyp")) == 0 ||
800	    strncmp(dev->si_name, "ptyp", strlen("ptyp")) == 0))
801		biba_type = MAC_BIBA_TYPE_EQUAL;
802	else
803		biba_type = MAC_BIBA_TYPE_HIGH;
804	mac_biba_set_effective(mac_biba, biba_type, 0, NULL);
805}
806
807static void
808mac_biba_create_devfs_directory(struct mount *mp, char *dirname,
809    int dirnamelen, struct devfs_dirent *devfs_dirent, struct label *label)
810{
811	struct mac_biba *mac_biba;
812
813	mac_biba = SLOT(label);
814	mac_biba_set_effective(mac_biba, MAC_BIBA_TYPE_HIGH, 0, NULL);
815}
816
817static void
818mac_biba_create_devfs_symlink(struct ucred *cred, struct mount *mp,
819    struct devfs_dirent *dd, struct label *ddlabel, struct devfs_dirent *de,
820    struct label *delabel)
821{
822	struct mac_biba *source, *dest;
823
824	source = SLOT(cred->cr_label);
825	dest = SLOT(delabel);
826
827	mac_biba_copy_effective(source, dest);
828}
829
830static void
831mac_biba_create_mount(struct ucred *cred, struct mount *mp,
832    struct label *mntlabel, struct label *fslabel)
833{
834	struct mac_biba *source, *dest;
835
836	source = SLOT(cred->cr_label);
837	dest = SLOT(mntlabel);
838	mac_biba_copy_effective(source, dest);
839	dest = SLOT(fslabel);
840	mac_biba_copy_effective(source, dest);
841}
842
843static void
844mac_biba_relabel_vnode(struct ucred *cred, struct vnode *vp,
845    struct label *vnodelabel, struct label *label)
846{
847	struct mac_biba *source, *dest;
848
849	source = SLOT(label);
850	dest = SLOT(vnodelabel);
851
852	mac_biba_copy(source, dest);
853}
854
855static void
856mac_biba_update_devfsdirent(struct mount *mp,
857    struct devfs_dirent *devfs_dirent, struct label *direntlabel,
858    struct vnode *vp, struct label *vnodelabel)
859{
860	struct mac_biba *source, *dest;
861
862	source = SLOT(vnodelabel);
863	dest = SLOT(direntlabel);
864
865	mac_biba_copy(source, dest);
866}
867
868static void
869mac_biba_associate_vnode_devfs(struct mount *mp, struct label *fslabel,
870    struct devfs_dirent *de, struct label *delabel, struct vnode *vp,
871    struct label *vlabel)
872{
873	struct mac_biba *source, *dest;
874
875	source = SLOT(delabel);
876	dest = SLOT(vlabel);
877
878	mac_biba_copy_effective(source, dest);
879}
880
881static int
882mac_biba_associate_vnode_extattr(struct mount *mp, struct label *fslabel,
883    struct vnode *vp, struct label *vlabel)
884{
885	struct mac_biba temp, *source, *dest;
886	int buflen, error;
887
888	source = SLOT(fslabel);
889	dest = SLOT(vlabel);
890
891	buflen = sizeof(temp);
892	bzero(&temp, buflen);
893
894	error = vn_extattr_get(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
895	    MAC_BIBA_EXTATTR_NAME, &buflen, (char *) &temp, curthread);
896	if (error == ENOATTR || error == EOPNOTSUPP) {
897		/* Fall back to the fslabel. */
898		mac_biba_copy_effective(source, dest);
899		return (0);
900	} else if (error)
901		return (error);
902
903	if (buflen != sizeof(temp)) {
904		printf("mac_biba_associate_vnode_extattr: bad size %d\n",
905		    buflen);
906		return (EPERM);
907	}
908	if (mac_biba_valid(&temp) != 0) {
909		printf("mac_biba_associate_vnode_extattr: invalid\n");
910		return (EPERM);
911	}
912	if ((temp.mb_flags & MAC_BIBA_FLAGS_BOTH) != MAC_BIBA_FLAG_EFFECTIVE) {
913		printf("mac_biba_associate_vnode_extattr: not effective\n");
914		return (EPERM);
915	}
916
917	mac_biba_copy_effective(&temp, dest);
918	return (0);
919}
920
921static void
922mac_biba_associate_vnode_singlelabel(struct mount *mp,
923    struct label *fslabel, struct vnode *vp, struct label *vlabel)
924{
925	struct mac_biba *source, *dest;
926
927	source = SLOT(fslabel);
928	dest = SLOT(vlabel);
929
930	mac_biba_copy_effective(source, dest);
931}
932
933static int
934mac_biba_create_vnode_extattr(struct ucred *cred, struct mount *mp,
935    struct label *fslabel, struct vnode *dvp, struct label *dlabel,
936    struct vnode *vp, struct label *vlabel, struct componentname *cnp)
937{
938	struct mac_biba *source, *dest, temp;
939	size_t buflen;
940	int error;
941
942	buflen = sizeof(temp);
943	bzero(&temp, buflen);
944
945	source = SLOT(cred->cr_label);
946	dest = SLOT(vlabel);
947	mac_biba_copy_effective(source, &temp);
948
949	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
950	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
951	if (error == 0)
952		mac_biba_copy_effective(source, dest);
953	return (error);
954}
955
956static int
957mac_biba_setlabel_vnode_extattr(struct ucred *cred, struct vnode *vp,
958    struct label *vlabel, struct label *intlabel)
959{
960	struct mac_biba *source, temp;
961	size_t buflen;
962	int error;
963
964	buflen = sizeof(temp);
965	bzero(&temp, buflen);
966
967	source = SLOT(intlabel);
968	if ((source->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) == 0)
969		return (0);
970
971	mac_biba_copy_effective(source, &temp);
972
973	error = vn_extattr_set(vp, IO_NODELOCKED, MAC_BIBA_EXTATTR_NAMESPACE,
974	    MAC_BIBA_EXTATTR_NAME, buflen, (char *) &temp, curthread);
975	return (error);
976}
977
978/*
979 * Labeling event operations: IPC object.
980 */
981static void
982mac_biba_create_inpcb_from_socket(struct socket *so, struct label *solabel,
983    struct inpcb *inp, struct label *inplabel)
984{
985	struct mac_biba *source, *dest;
986
987	source = SLOT(solabel);
988	dest = SLOT(inplabel);
989
990	mac_biba_copy_effective(source, dest);
991}
992
993static void
994mac_biba_create_mbuf_from_socket(struct socket *so, struct label *socketlabel,
995    struct mbuf *m, struct label *mbuflabel)
996{
997	struct mac_biba *source, *dest;
998
999	source = SLOT(socketlabel);
1000	dest = SLOT(mbuflabel);
1001
1002	mac_biba_copy_effective(source, dest);
1003}
1004
1005static void
1006mac_biba_create_socket(struct ucred *cred, struct socket *socket,
1007    struct label *socketlabel)
1008{
1009	struct mac_biba *source, *dest;
1010
1011	source = SLOT(cred->cr_label);
1012	dest = SLOT(socketlabel);
1013
1014	mac_biba_copy_effective(source, dest);
1015}
1016
1017static void
1018mac_biba_create_pipe(struct ucred *cred, struct pipepair *pp,
1019    struct label *pipelabel)
1020{
1021	struct mac_biba *source, *dest;
1022
1023	source = SLOT(cred->cr_label);
1024	dest = SLOT(pipelabel);
1025
1026	mac_biba_copy_effective(source, dest);
1027}
1028
1029static void
1030mac_biba_create_posix_sem(struct ucred *cred, struct ksem *ksemptr,
1031    struct label *ks_label)
1032{
1033	struct mac_biba *source, *dest;
1034
1035	source = SLOT(cred->cr_label);
1036	dest = SLOT(ks_label);
1037
1038	mac_biba_copy_effective(source, dest);
1039}
1040
1041static void
1042mac_biba_create_socket_from_socket(struct socket *oldsocket,
1043    struct label *oldsocketlabel, struct socket *newsocket,
1044    struct label *newsocketlabel)
1045{
1046	struct mac_biba *source, *dest;
1047
1048	source = SLOT(oldsocketlabel);
1049	dest = SLOT(newsocketlabel);
1050
1051	mac_biba_copy_effective(source, dest);
1052}
1053
1054static void
1055mac_biba_relabel_socket(struct ucred *cred, struct socket *socket,
1056    struct label *socketlabel, struct label *newlabel)
1057{
1058	struct mac_biba *source, *dest;
1059
1060	source = SLOT(newlabel);
1061	dest = SLOT(socketlabel);
1062
1063	mac_biba_copy(source, dest);
1064}
1065
1066static void
1067mac_biba_relabel_pipe(struct ucred *cred, struct pipepair *pp,
1068    struct label *pipelabel, struct label *newlabel)
1069{
1070	struct mac_biba *source, *dest;
1071
1072	source = SLOT(newlabel);
1073	dest = SLOT(pipelabel);
1074
1075	mac_biba_copy(source, dest);
1076}
1077
1078static void
1079mac_biba_set_socket_peer_from_mbuf(struct mbuf *mbuf, struct label *mbuflabel,
1080    struct socket *socket, struct label *socketpeerlabel)
1081{
1082	struct mac_biba *source, *dest;
1083
1084	source = SLOT(mbuflabel);
1085	dest = SLOT(socketpeerlabel);
1086
1087	mac_biba_copy_effective(source, dest);
1088}
1089
1090/*
1091 * Labeling event operations: System V IPC objects.
1092 */
1093
1094static void
1095mac_biba_create_sysv_msgmsg(struct ucred *cred, struct msqid_kernel *msqkptr,
1096    struct label *msqlabel, struct msg *msgptr, struct label *msglabel)
1097{
1098	struct mac_biba *source, *dest;
1099
1100	/* Ignore the msgq label */
1101	source = SLOT(cred->cr_label);
1102	dest = SLOT(msglabel);
1103
1104	mac_biba_copy_effective(source, dest);
1105}
1106
1107static void
1108mac_biba_create_sysv_msgqueue(struct ucred *cred,
1109    struct msqid_kernel *msqkptr, struct label *msqlabel)
1110{
1111	struct mac_biba *source, *dest;
1112
1113	source = SLOT(cred->cr_label);
1114	dest = SLOT(msqlabel);
1115
1116	mac_biba_copy_effective(source, dest);
1117}
1118
1119static void
1120mac_biba_create_sysv_sem(struct ucred *cred, struct semid_kernel *semakptr,
1121    struct label *semalabel)
1122{
1123	struct mac_biba *source, *dest;
1124
1125	source = SLOT(cred->cr_label);
1126	dest = SLOT(semalabel);
1127
1128	mac_biba_copy_effective(source, dest);
1129}
1130
1131static void
1132mac_biba_create_sysv_shm(struct ucred *cred, struct shmid_kernel *shmsegptr,
1133    struct label *shmlabel)
1134{
1135	struct mac_biba *source, *dest;
1136
1137	source = SLOT(cred->cr_label);
1138	dest = SLOT(shmlabel);
1139
1140	mac_biba_copy_effective(source, dest);
1141}
1142
1143/*
1144 * Labeling event operations: network objects.
1145 */
1146static void
1147mac_biba_set_socket_peer_from_socket(struct socket *oldsocket,
1148    struct label *oldsocketlabel, struct socket *newsocket,
1149    struct label *newsocketpeerlabel)
1150{
1151	struct mac_biba *source, *dest;
1152
1153	source = SLOT(oldsocketlabel);
1154	dest = SLOT(newsocketpeerlabel);
1155
1156	mac_biba_copy_effective(source, dest);
1157}
1158
1159static void
1160mac_biba_create_bpfdesc(struct ucred *cred, struct bpf_d *bpf_d,
1161    struct label *bpflabel)
1162{
1163	struct mac_biba *source, *dest;
1164
1165	source = SLOT(cred->cr_label);
1166	dest = SLOT(bpflabel);
1167
1168	mac_biba_copy_effective(source, dest);
1169}
1170
1171static void
1172mac_biba_create_ifnet(struct ifnet *ifnet, struct label *ifnetlabel)
1173{
1174	char tifname[IFNAMSIZ], *p, *q;
1175	char tiflist[sizeof(trusted_interfaces)];
1176	struct mac_biba *dest;
1177	int len, type;
1178
1179	dest = SLOT(ifnetlabel);
1180
1181	if (ifnet->if_type == IFT_LOOP || interfaces_equal != 0) {
1182		type = MAC_BIBA_TYPE_EQUAL;
1183		goto set;
1184	}
1185
1186	if (trust_all_interfaces) {
1187		type = MAC_BIBA_TYPE_HIGH;
1188		goto set;
1189	}
1190
1191	type = MAC_BIBA_TYPE_LOW;
1192
1193	if (trusted_interfaces[0] == '\0' ||
1194	    !strvalid(trusted_interfaces, sizeof(trusted_interfaces)))
1195		goto set;
1196
1197	bzero(tiflist, sizeof(tiflist));
1198	for (p = trusted_interfaces, q = tiflist; *p != '\0'; p++, q++)
1199		if(*p != ' ' && *p != '\t')
1200			*q = *p;
1201
1202	for (p = q = tiflist;; p++) {
1203		if (*p == ',' || *p == '\0') {
1204			len = p - q;
1205			if (len < IFNAMSIZ) {
1206				bzero(tifname, sizeof(tifname));
1207				bcopy(q, tifname, len);
1208				if (strcmp(tifname, ifnet->if_xname) == 0) {
1209					type = MAC_BIBA_TYPE_HIGH;
1210					break;
1211				}
1212			} else {
1213				*p = '\0';
1214				printf("mac_biba warning: interface name "
1215				    "\"%s\" is too long (must be < %d)\n",
1216				    q, IFNAMSIZ);
1217			}
1218			if (*p == '\0')
1219				break;
1220			q = p + 1;
1221		}
1222	}
1223set:
1224	mac_biba_set_effective(dest, type, 0, NULL);
1225	mac_biba_set_range(dest, type, 0, NULL, type, 0, NULL);
1226}
1227
1228static void
1229mac_biba_create_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1230    struct ipq *ipq, struct label *ipqlabel)
1231{
1232	struct mac_biba *source, *dest;
1233
1234	source = SLOT(fragmentlabel);
1235	dest = SLOT(ipqlabel);
1236
1237	mac_biba_copy_effective(source, dest);
1238}
1239
1240static void
1241mac_biba_create_datagram_from_ipq(struct ipq *ipq, struct label *ipqlabel,
1242    struct mbuf *datagram, struct label *datagramlabel)
1243{
1244	struct mac_biba *source, *dest;
1245
1246	source = SLOT(ipqlabel);
1247	dest = SLOT(datagramlabel);
1248
1249	/* Just use the head, since we require them all to match. */
1250	mac_biba_copy_effective(source, dest);
1251}
1252
1253static void
1254mac_biba_create_fragment(struct mbuf *datagram, struct label *datagramlabel,
1255    struct mbuf *fragment, struct label *fragmentlabel)
1256{
1257	struct mac_biba *source, *dest;
1258
1259	source = SLOT(datagramlabel);
1260	dest = SLOT(fragmentlabel);
1261
1262	mac_biba_copy_effective(source, dest);
1263}
1264
1265static void
1266mac_biba_create_mbuf_from_inpcb(struct inpcb *inp, struct label *inplabel,
1267    struct mbuf *m, struct label *mlabel)
1268{
1269	struct mac_biba *source, *dest;
1270
1271	source = SLOT(inplabel);
1272	dest = SLOT(mlabel);
1273
1274	mac_biba_copy_effective(source, dest);
1275}
1276
1277static void
1278mac_biba_create_mbuf_linklayer(struct ifnet *ifnet, struct label *ifnetlabel,
1279    struct mbuf *mbuf, struct label *mbuflabel)
1280{
1281	struct mac_biba *dest;
1282
1283	dest = SLOT(mbuflabel);
1284
1285	mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1286}
1287
1288static void
1289mac_biba_create_mbuf_from_bpfdesc(struct bpf_d *bpf_d, struct label *bpflabel,
1290    struct mbuf *mbuf, struct label *mbuflabel)
1291{
1292	struct mac_biba *source, *dest;
1293
1294	source = SLOT(bpflabel);
1295	dest = SLOT(mbuflabel);
1296
1297	mac_biba_copy_effective(source, dest);
1298}
1299
1300static void
1301mac_biba_create_mbuf_from_ifnet(struct ifnet *ifnet, struct label *ifnetlabel,
1302    struct mbuf *m, struct label *mbuflabel)
1303{
1304	struct mac_biba *source, *dest;
1305
1306	source = SLOT(ifnetlabel);
1307	dest = SLOT(mbuflabel);
1308
1309	mac_biba_copy_effective(source, dest);
1310}
1311
1312static void
1313mac_biba_create_mbuf_multicast_encap(struct mbuf *oldmbuf,
1314    struct label *oldmbuflabel, struct ifnet *ifnet, struct label *ifnetlabel,
1315    struct mbuf *newmbuf, struct label *newmbuflabel)
1316{
1317	struct mac_biba *source, *dest;
1318
1319	source = SLOT(oldmbuflabel);
1320	dest = SLOT(newmbuflabel);
1321
1322	mac_biba_copy_effective(source, dest);
1323}
1324
1325static void
1326mac_biba_create_mbuf_netlayer(struct mbuf *oldmbuf, struct label *oldmbuflabel,
1327    struct mbuf *newmbuf, struct label *newmbuflabel)
1328{
1329	struct mac_biba *source, *dest;
1330
1331	source = SLOT(oldmbuflabel);
1332	dest = SLOT(newmbuflabel);
1333
1334	mac_biba_copy_effective(source, dest);
1335}
1336
1337static int
1338mac_biba_fragment_match(struct mbuf *fragment, struct label *fragmentlabel,
1339    struct ipq *ipq, struct label *ipqlabel)
1340{
1341	struct mac_biba *a, *b;
1342
1343	a = SLOT(ipqlabel);
1344	b = SLOT(fragmentlabel);
1345
1346	return (mac_biba_equal_effective(a, b));
1347}
1348
1349static void
1350mac_biba_relabel_ifnet(struct ucred *cred, struct ifnet *ifnet,
1351    struct label *ifnetlabel, struct label *newlabel)
1352{
1353	struct mac_biba *source, *dest;
1354
1355	source = SLOT(newlabel);
1356	dest = SLOT(ifnetlabel);
1357
1358	mac_biba_copy(source, dest);
1359}
1360
1361static void
1362mac_biba_update_ipq(struct mbuf *fragment, struct label *fragmentlabel,
1363    struct ipq *ipq, struct label *ipqlabel)
1364{
1365
1366	/* NOOP: we only accept matching labels, so no need to update */
1367}
1368
1369static void
1370mac_biba_inpcb_sosetlabel(struct socket *so, struct label *solabel,
1371    struct inpcb *inp, struct label *inplabel)
1372{
1373	struct mac_biba *source, *dest;
1374
1375	source = SLOT(solabel);
1376	dest = SLOT(inplabel);
1377
1378	mac_biba_copy(source, dest);
1379}
1380
1381static void
1382mac_biba_create_mbuf_from_firewall(struct mbuf *m, struct label *label)
1383{
1384	struct mac_biba *dest;
1385
1386	dest = SLOT(label);
1387
1388	/* XXX: where is the label for the firewall really comming from? */
1389	mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1390}
1391
1392/*
1393 * Labeling event operations: processes.
1394 */
1395static void
1396mac_biba_create_proc0(struct ucred *cred)
1397{
1398	struct mac_biba *dest;
1399
1400	dest = SLOT(cred->cr_label);
1401
1402	mac_biba_set_effective(dest, MAC_BIBA_TYPE_EQUAL, 0, NULL);
1403	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1404	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1405}
1406
1407static void
1408mac_biba_create_proc1(struct ucred *cred)
1409{
1410	struct mac_biba *dest;
1411
1412	dest = SLOT(cred->cr_label);
1413
1414	mac_biba_set_effective(dest, MAC_BIBA_TYPE_HIGH, 0, NULL);
1415	mac_biba_set_range(dest, MAC_BIBA_TYPE_LOW, 0, NULL,
1416	    MAC_BIBA_TYPE_HIGH, 0, NULL);
1417}
1418
1419static void
1420mac_biba_relabel_cred(struct ucred *cred, struct label *newlabel)
1421{
1422	struct mac_biba *source, *dest;
1423
1424	source = SLOT(newlabel);
1425	dest = SLOT(cred->cr_label);
1426
1427	mac_biba_copy(source, dest);
1428}
1429
1430/*
1431 * Label cleanup/flush operations
1432 */
1433static void
1434mac_biba_cleanup_sysv_msgmsg(struct label *msglabel)
1435{
1436
1437	bzero(SLOT(msglabel), sizeof(struct mac_biba));
1438}
1439
1440static void
1441mac_biba_cleanup_sysv_msgqueue(struct label *msqlabel)
1442{
1443
1444	bzero(SLOT(msqlabel), sizeof(struct mac_biba));
1445}
1446
1447static void
1448mac_biba_cleanup_sysv_sem(struct label *semalabel)
1449{
1450
1451	bzero(SLOT(semalabel), sizeof(struct mac_biba));
1452}
1453
1454static void
1455mac_biba_cleanup_sysv_shm(struct label *shmlabel)
1456{
1457	bzero(SLOT(shmlabel), sizeof(struct mac_biba));
1458}
1459
1460/*
1461 * Access control checks.
1462 */
1463static int
1464mac_biba_check_bpfdesc_receive(struct bpf_d *bpf_d, struct label *bpflabel,
1465    struct ifnet *ifnet, struct label *ifnetlabel)
1466{
1467	struct mac_biba *a, *b;
1468
1469	if (!mac_biba_enabled)
1470		return (0);
1471
1472	a = SLOT(bpflabel);
1473	b = SLOT(ifnetlabel);
1474
1475	if (mac_biba_equal_effective(a, b))
1476		return (0);
1477	return (EACCES);
1478}
1479
1480static int
1481mac_biba_check_cred_relabel(struct ucred *cred, struct label *newlabel)
1482{
1483	struct mac_biba *subj, *new;
1484	int error;
1485
1486	subj = SLOT(cred->cr_label);
1487	new = SLOT(newlabel);
1488
1489	/*
1490	 * If there is a Biba label update for the credential, it may
1491	 * be an update of the effective, range, or both.
1492	 */
1493	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1494	if (error)
1495		return (error);
1496
1497	/*
1498	 * If the Biba label is to be changed, authorize as appropriate.
1499	 */
1500	if (new->mb_flags & MAC_BIBA_FLAGS_BOTH) {
1501		/*
1502		 * If the change request modifies both the Biba label
1503		 * effective and range, check that the new effective will be
1504		 * in the new range.
1505		 */
1506		if ((new->mb_flags & MAC_BIBA_FLAGS_BOTH) ==
1507		    MAC_BIBA_FLAGS_BOTH &&
1508		    !mac_biba_effective_in_range(new, new))
1509			return (EINVAL);
1510
1511		/*
1512		 * To change the Biba effective label on a credential, the
1513		 * new effective label must be in the current range.
1514		 */
1515		if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE &&
1516		    !mac_biba_effective_in_range(new, subj))
1517			return (EPERM);
1518
1519		/*
1520		 * To change the Biba range on a credential, the new
1521		 * range label must be in the current range.
1522		 */
1523		if (new->mb_flags & MAC_BIBA_FLAG_RANGE &&
1524		    !mac_biba_range_in_range(new, subj))
1525			return (EPERM);
1526
1527		/*
1528		 * To have EQUAL in any component of the new credential
1529		 * Biba label, the subject must already have EQUAL in
1530		 * their label.
1531		 */
1532		if (mac_biba_contains_equal(new)) {
1533			error = mac_biba_subject_privileged(subj);
1534			if (error)
1535				return (error);
1536		}
1537	}
1538
1539	return (0);
1540}
1541
1542static int
1543mac_biba_check_cred_visible(struct ucred *u1, struct ucred *u2)
1544{
1545	struct mac_biba *subj, *obj;
1546
1547	if (!mac_biba_enabled)
1548		return (0);
1549
1550	subj = SLOT(u1->cr_label);
1551	obj = SLOT(u2->cr_label);
1552
1553	/* XXX: range */
1554	if (!mac_biba_dominate_effective(obj, subj))
1555		return (ESRCH);
1556
1557	return (0);
1558}
1559
1560static int
1561mac_biba_check_ifnet_relabel(struct ucred *cred, struct ifnet *ifnet,
1562    struct label *ifnetlabel, struct label *newlabel)
1563{
1564	struct mac_biba *subj, *new;
1565	int error;
1566
1567	subj = SLOT(cred->cr_label);
1568	new = SLOT(newlabel);
1569
1570	/*
1571	 * If there is a Biba label update for the interface, it may
1572	 * be an update of the effective, range, or both.
1573	 */
1574	error = biba_atmostflags(new, MAC_BIBA_FLAGS_BOTH);
1575	if (error)
1576		return (error);
1577
1578	/*
1579	 * Relabling network interfaces requires Biba privilege.
1580	 */
1581	error = mac_biba_subject_privileged(subj);
1582	if (error)
1583		return (error);
1584
1585	return (0);
1586}
1587
1588static int
1589mac_biba_check_ifnet_transmit(struct ifnet *ifnet, struct label *ifnetlabel,
1590    struct mbuf *m, struct label *mbuflabel)
1591{
1592	struct mac_biba *p, *i;
1593
1594	if (!mac_biba_enabled)
1595		return (0);
1596
1597	p = SLOT(mbuflabel);
1598	i = SLOT(ifnetlabel);
1599
1600	return (mac_biba_effective_in_range(p, i) ? 0 : EACCES);
1601}
1602
1603static int
1604mac_biba_check_inpcb_deliver(struct inpcb *inp, struct label *inplabel,
1605    struct mbuf *m, struct label *mlabel)
1606{
1607	struct mac_biba *p, *i;
1608
1609	if (!mac_biba_enabled)
1610		return (0);
1611
1612	p = SLOT(mlabel);
1613	i = SLOT(inplabel);
1614
1615	return (mac_biba_equal_effective(p, i) ? 0 : EACCES);
1616}
1617
1618static int
1619mac_biba_check_sysv_msgrcv(struct ucred *cred, struct msg *msgptr,
1620    struct label *msglabel)
1621{
1622	struct mac_biba *subj, *obj;
1623
1624	if (!mac_biba_enabled)
1625		return (0);
1626
1627	subj = SLOT(cred->cr_label);
1628	obj = SLOT(msglabel);
1629
1630	if (!mac_biba_dominate_effective(obj, subj))
1631		return (EACCES);
1632
1633	return (0);
1634}
1635
1636static int
1637mac_biba_check_sysv_msgrmid(struct ucred *cred, struct msg *msgptr,
1638    struct label *msglabel)
1639{
1640	struct mac_biba *subj, *obj;
1641
1642	if (!mac_biba_enabled)
1643		return (0);
1644
1645	subj = SLOT(cred->cr_label);
1646	obj = SLOT(msglabel);
1647
1648	if (!mac_biba_dominate_effective(subj, obj))
1649		return (EACCES);
1650
1651	return (0);
1652}
1653
1654static int
1655mac_biba_check_sysv_msqget(struct ucred *cred, struct msqid_kernel *msqkptr,
1656    struct label *msqklabel)
1657{
1658	struct mac_biba *subj, *obj;
1659
1660	if (!mac_biba_enabled)
1661		return (0);
1662
1663	subj = SLOT(cred->cr_label);
1664	obj = SLOT(msqklabel);
1665
1666	if (!mac_biba_dominate_effective(obj, subj))
1667		return (EACCES);
1668
1669	return (0);
1670}
1671
1672static int
1673mac_biba_check_sysv_msqsnd(struct ucred *cred, struct msqid_kernel *msqkptr,
1674    struct label *msqklabel)
1675{
1676	struct mac_biba *subj, *obj;
1677
1678	if (!mac_biba_enabled)
1679		return (0);
1680
1681	subj = SLOT(cred->cr_label);
1682	obj = SLOT(msqklabel);
1683
1684	if (!mac_biba_dominate_effective(subj, obj))
1685		return (EACCES);
1686
1687	return (0);
1688}
1689
1690static int
1691mac_biba_check_sysv_msqrcv(struct ucred *cred, struct msqid_kernel *msqkptr,
1692    struct label *msqklabel)
1693{
1694	struct mac_biba *subj, *obj;
1695
1696	if (!mac_biba_enabled)
1697		return (0);
1698
1699	subj = SLOT(cred->cr_label);
1700	obj = SLOT(msqklabel);
1701
1702	if (!mac_biba_dominate_effective(obj, subj))
1703		return (EACCES);
1704
1705	return (0);
1706}
1707
1708
1709static int
1710mac_biba_check_sysv_msqctl(struct ucred *cred, struct msqid_kernel *msqkptr,
1711    struct label *msqklabel, int cmd)
1712{
1713	struct mac_biba *subj, *obj;
1714
1715	if (!mac_biba_enabled)
1716		return (0);
1717
1718	subj = SLOT(cred->cr_label);
1719	obj = SLOT(msqklabel);
1720
1721	switch(cmd) {
1722	case IPC_RMID:
1723	case IPC_SET:
1724		if (!mac_biba_dominate_effective(subj, obj))
1725			return (EACCES);
1726		break;
1727
1728	case IPC_STAT:
1729		if (!mac_biba_dominate_effective(obj, subj))
1730			return (EACCES);
1731		break;
1732
1733	default:
1734		return (EACCES);
1735	}
1736
1737	return (0);
1738}
1739
1740static int
1741mac_biba_check_sysv_semctl(struct ucred *cred, struct semid_kernel *semakptr,
1742    struct label *semaklabel, int cmd)
1743{
1744	struct mac_biba *subj, *obj;
1745
1746	if (!mac_biba_enabled)
1747		return (0);
1748
1749	subj = SLOT(cred->cr_label);
1750	obj = SLOT(semaklabel);
1751
1752	switch(cmd) {
1753	case IPC_RMID:
1754	case IPC_SET:
1755	case SETVAL:
1756	case SETALL:
1757		if (!mac_biba_dominate_effective(subj, obj))
1758			return (EACCES);
1759		break;
1760
1761	case IPC_STAT:
1762	case GETVAL:
1763	case GETPID:
1764	case GETNCNT:
1765	case GETZCNT:
1766	case GETALL:
1767		if (!mac_biba_dominate_effective(obj, subj))
1768			return (EACCES);
1769		break;
1770
1771	default:
1772		return (EACCES);
1773	}
1774
1775	return (0);
1776}
1777
1778
1779static int
1780mac_biba_check_sysv_semget(struct ucred *cred, struct semid_kernel *semakptr,
1781    struct label *semaklabel)
1782{
1783	struct mac_biba *subj, *obj;
1784
1785	if (!mac_biba_enabled)
1786		return (0);
1787
1788	subj = SLOT(cred->cr_label);
1789	obj = SLOT(semaklabel);
1790
1791	if (!mac_biba_dominate_effective(obj, subj))
1792		return (EACCES);
1793
1794	return (0);
1795}
1796
1797
1798static int
1799mac_biba_check_sysv_semop(struct ucred *cred, struct semid_kernel *semakptr,
1800    struct label *semaklabel, size_t accesstype)
1801{
1802	struct mac_biba *subj, *obj;
1803
1804	if (!mac_biba_enabled)
1805		return (0);
1806
1807	subj = SLOT(cred->cr_label);
1808	obj = SLOT(semaklabel);
1809
1810	if (accesstype & SEM_R)
1811		if (!mac_biba_dominate_effective(obj, subj))
1812			return (EACCES);
1813
1814	if (accesstype & SEM_A)
1815		if (!mac_biba_dominate_effective(subj, obj))
1816			return (EACCES);
1817
1818	return (0);
1819}
1820
1821static int
1822mac_biba_check_sysv_shmat(struct ucred *cred, struct shmid_kernel *shmsegptr,
1823    struct label *shmseglabel, int shmflg)
1824{
1825	struct mac_biba *subj, *obj;
1826
1827	if (!mac_biba_enabled)
1828		return (0);
1829
1830	subj = SLOT(cred->cr_label);
1831	obj = SLOT(shmseglabel);
1832
1833	if (!mac_biba_dominate_effective(obj, subj))
1834		return (EACCES);
1835	if ((shmflg & SHM_RDONLY) == 0) {
1836		if (!mac_biba_dominate_effective(subj, obj))
1837			return (EACCES);
1838	}
1839
1840	return (0);
1841}
1842
1843static int
1844mac_biba_check_sysv_shmctl(struct ucred *cred, struct shmid_kernel *shmsegptr,
1845    struct label *shmseglabel, int cmd)
1846{
1847	struct mac_biba *subj, *obj;
1848
1849	if (!mac_biba_enabled)
1850		return (0);
1851
1852	subj = SLOT(cred->cr_label);
1853	obj = SLOT(shmseglabel);
1854
1855	switch(cmd) {
1856	case IPC_RMID:
1857	case IPC_SET:
1858		if (!mac_biba_dominate_effective(subj, obj))
1859			return (EACCES);
1860		break;
1861
1862	case IPC_STAT:
1863	case SHM_STAT:
1864		if (!mac_biba_dominate_effective(obj, subj))
1865			return (EACCES);
1866		break;
1867
1868	default:
1869		return (EACCES);
1870	}
1871
1872	return (0);
1873}
1874
1875static int
1876mac_biba_check_sysv_shmget(struct ucred *cred, struct shmid_kernel *shmsegptr,
1877    struct label *shmseglabel, int shmflg)
1878{
1879	struct mac_biba *subj, *obj;
1880
1881	if (!mac_biba_enabled)
1882		return (0);
1883
1884	subj = SLOT(cred->cr_label);
1885	obj = SLOT(shmseglabel);
1886
1887	if (!mac_biba_dominate_effective(obj, subj))
1888		return (EACCES);
1889
1890	return (0);
1891}
1892
1893static int
1894mac_biba_check_kld_load(struct ucred *cred, struct vnode *vp,
1895    struct label *label)
1896{
1897	struct mac_biba *subj, *obj;
1898	int error;
1899
1900	if (!mac_biba_enabled)
1901		return (0);
1902
1903	subj = SLOT(cred->cr_label);
1904
1905	error = mac_biba_subject_privileged(subj);
1906	if (error)
1907		return (error);
1908
1909	obj = SLOT(label);
1910	if (!mac_biba_high_effective(obj))
1911		return (EACCES);
1912
1913	return (0);
1914}
1915
1916
1917static int
1918mac_biba_check_kld_unload(struct ucred *cred)
1919{
1920	struct mac_biba *subj;
1921
1922	if (!mac_biba_enabled)
1923		return (0);
1924
1925	subj = SLOT(cred->cr_label);
1926
1927	return (mac_biba_subject_privileged(subj));
1928}
1929
1930static int
1931mac_biba_check_mount_stat(struct ucred *cred, struct mount *mp,
1932    struct label *mntlabel)
1933{
1934	struct mac_biba *subj, *obj;
1935
1936	if (!mac_biba_enabled)
1937		return (0);
1938
1939	subj = SLOT(cred->cr_label);
1940	obj = SLOT(mntlabel);
1941
1942	if (!mac_biba_dominate_effective(obj, subj))
1943		return (EACCES);
1944
1945	return (0);
1946}
1947
1948static int
1949mac_biba_check_pipe_ioctl(struct ucred *cred, struct pipepair *pp,
1950    struct label *pipelabel, unsigned long cmd, void /* caddr_t */ *data)
1951{
1952
1953	if(!mac_biba_enabled)
1954		return (0);
1955
1956	/* XXX: This will be implemented soon... */
1957
1958	return (0);
1959}
1960
1961static int
1962mac_biba_check_pipe_poll(struct ucred *cred, struct pipepair *pp,
1963    struct label *pipelabel)
1964{
1965	struct mac_biba *subj, *obj;
1966
1967	if (!mac_biba_enabled)
1968		return (0);
1969
1970	subj = SLOT(cred->cr_label);
1971	obj = SLOT((pipelabel));
1972
1973	if (!mac_biba_dominate_effective(obj, subj))
1974		return (EACCES);
1975
1976	return (0);
1977}
1978
1979static int
1980mac_biba_check_pipe_read(struct ucred *cred, struct pipepair *pp,
1981    struct label *pipelabel)
1982{
1983	struct mac_biba *subj, *obj;
1984
1985	if (!mac_biba_enabled)
1986		return (0);
1987
1988	subj = SLOT(cred->cr_label);
1989	obj = SLOT((pipelabel));
1990
1991	if (!mac_biba_dominate_effective(obj, subj))
1992		return (EACCES);
1993
1994	return (0);
1995}
1996
1997static int
1998mac_biba_check_pipe_relabel(struct ucred *cred, struct pipepair *pp,
1999    struct label *pipelabel, struct label *newlabel)
2000{
2001	struct mac_biba *subj, *obj, *new;
2002	int error;
2003
2004	new = SLOT(newlabel);
2005	subj = SLOT(cred->cr_label);
2006	obj = SLOT(pipelabel);
2007
2008	/*
2009	 * If there is a Biba label update for a pipe, it must be a
2010	 * effective update.
2011	 */
2012	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2013	if (error)
2014		return (error);
2015
2016	/*
2017	 * To perform a relabel of a pipe (Biba label or not), Biba must
2018	 * authorize the relabel.
2019	 */
2020	if (!mac_biba_effective_in_range(obj, subj))
2021		return (EPERM);
2022
2023	/*
2024	 * If the Biba label is to be changed, authorize as appropriate.
2025	 */
2026	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2027		/*
2028		 * To change the Biba label on a pipe, the new pipe label
2029		 * must be in the subject range.
2030		 */
2031		if (!mac_biba_effective_in_range(new, subj))
2032			return (EPERM);
2033
2034		/*
2035		 * To change the Biba label on a pipe to be EQUAL, the
2036		 * subject must have appropriate privilege.
2037		 */
2038		if (mac_biba_contains_equal(new)) {
2039			error = mac_biba_subject_privileged(subj);
2040			if (error)
2041				return (error);
2042		}
2043	}
2044
2045	return (0);
2046}
2047
2048static int
2049mac_biba_check_pipe_stat(struct ucred *cred, struct pipepair *pp,
2050    struct label *pipelabel)
2051{
2052	struct mac_biba *subj, *obj;
2053
2054	if (!mac_biba_enabled)
2055		return (0);
2056
2057	subj = SLOT(cred->cr_label);
2058	obj = SLOT((pipelabel));
2059
2060	if (!mac_biba_dominate_effective(obj, subj))
2061		return (EACCES);
2062
2063	return (0);
2064}
2065
2066static int
2067mac_biba_check_pipe_write(struct ucred *cred, struct pipepair *pp,
2068    struct label *pipelabel)
2069{
2070	struct mac_biba *subj, *obj;
2071
2072	if (!mac_biba_enabled)
2073		return (0);
2074
2075	subj = SLOT(cred->cr_label);
2076	obj = SLOT((pipelabel));
2077
2078	if (!mac_biba_dominate_effective(subj, obj))
2079		return (EACCES);
2080
2081	return (0);
2082}
2083
2084static int
2085mac_biba_check_posix_sem_write(struct ucred *cred, struct ksem *ksemptr,
2086    struct label *ks_label)
2087{
2088	struct mac_biba *subj, *obj;
2089
2090	if (!mac_biba_enabled)
2091		return (0);
2092
2093	subj = SLOT(cred->cr_label);
2094	obj = SLOT(ks_label);
2095
2096	if (!mac_biba_dominate_effective(subj, obj))
2097		return (EACCES);
2098
2099	return (0);
2100}
2101
2102static int
2103mac_biba_check_posix_sem_rdonly(struct ucred *cred, struct ksem *ksemptr,
2104    struct label *ks_label)
2105{
2106	struct mac_biba *subj, *obj;
2107
2108	if (!mac_biba_enabled)
2109		return (0);
2110
2111	subj = SLOT(cred->cr_label);
2112	obj = SLOT(ks_label);
2113
2114	if (!mac_biba_dominate_effective(obj, subj))
2115		return (EACCES);
2116
2117	return (0);
2118}
2119
2120static int
2121mac_biba_check_proc_debug(struct ucred *cred, struct proc *proc)
2122{
2123	struct mac_biba *subj, *obj;
2124
2125	if (!mac_biba_enabled)
2126		return (0);
2127
2128	subj = SLOT(cred->cr_label);
2129	obj = SLOT(proc->p_ucred->cr_label);
2130
2131	/* XXX: range checks */
2132	if (!mac_biba_dominate_effective(obj, subj))
2133		return (ESRCH);
2134	if (!mac_biba_dominate_effective(subj, obj))
2135		return (EACCES);
2136
2137	return (0);
2138}
2139
2140static int
2141mac_biba_check_proc_sched(struct ucred *cred, struct proc *proc)
2142{
2143	struct mac_biba *subj, *obj;
2144
2145	if (!mac_biba_enabled)
2146		return (0);
2147
2148	subj = SLOT(cred->cr_label);
2149	obj = SLOT(proc->p_ucred->cr_label);
2150
2151	/* XXX: range checks */
2152	if (!mac_biba_dominate_effective(obj, subj))
2153		return (ESRCH);
2154	if (!mac_biba_dominate_effective(subj, obj))
2155		return (EACCES);
2156
2157	return (0);
2158}
2159
2160static int
2161mac_biba_check_proc_signal(struct ucred *cred, struct proc *proc, int signum)
2162{
2163	struct mac_biba *subj, *obj;
2164
2165	if (!mac_biba_enabled)
2166		return (0);
2167
2168	subj = SLOT(cred->cr_label);
2169	obj = SLOT(proc->p_ucred->cr_label);
2170
2171	/* XXX: range checks */
2172	if (!mac_biba_dominate_effective(obj, subj))
2173		return (ESRCH);
2174	if (!mac_biba_dominate_effective(subj, obj))
2175		return (EACCES);
2176
2177	return (0);
2178}
2179
2180static int
2181mac_biba_check_socket_deliver(struct socket *so, struct label *socketlabel,
2182    struct mbuf *m, struct label *mbuflabel)
2183{
2184	struct mac_biba *p, *s;
2185
2186	if (!mac_biba_enabled)
2187		return (0);
2188
2189	p = SLOT(mbuflabel);
2190	s = SLOT(socketlabel);
2191
2192	return (mac_biba_equal_effective(p, s) ? 0 : EACCES);
2193}
2194
2195static int
2196mac_biba_check_socket_relabel(struct ucred *cred, struct socket *so,
2197    struct label *socketlabel, struct label *newlabel)
2198{
2199	struct mac_biba *subj, *obj, *new;
2200	int error;
2201
2202	new = SLOT(newlabel);
2203	subj = SLOT(cred->cr_label);
2204	obj = SLOT(socketlabel);
2205
2206	/*
2207	 * If there is a Biba label update for the socket, it may be
2208	 * an update of effective.
2209	 */
2210	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2211	if (error)
2212		return (error);
2213
2214	/*
2215	 * To relabel a socket, the old socket effective must be in the subject
2216	 * range.
2217	 */
2218	if (!mac_biba_effective_in_range(obj, subj))
2219		return (EPERM);
2220
2221	/*
2222	 * If the Biba label is to be changed, authorize as appropriate.
2223	 */
2224	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2225		/*
2226		 * To relabel a socket, the new socket effective must be in
2227		 * the subject range.
2228		 */
2229		if (!mac_biba_effective_in_range(new, subj))
2230			return (EPERM);
2231
2232		/*
2233		 * To change the Biba label on the socket to contain EQUAL,
2234		 * the subject must have appropriate privilege.
2235		 */
2236		if (mac_biba_contains_equal(new)) {
2237			error = mac_biba_subject_privileged(subj);
2238			if (error)
2239				return (error);
2240		}
2241	}
2242
2243	return (0);
2244}
2245
2246static int
2247mac_biba_check_socket_visible(struct ucred *cred, struct socket *socket,
2248    struct label *socketlabel)
2249{
2250	struct mac_biba *subj, *obj;
2251
2252	if (!mac_biba_enabled)
2253		return (0);
2254
2255	subj = SLOT(cred->cr_label);
2256	obj = SLOT(socketlabel);
2257
2258	if (!mac_biba_dominate_effective(obj, subj))
2259		return (ENOENT);
2260
2261	return (0);
2262}
2263
2264static int
2265mac_biba_check_sysarch_ioperm(struct ucred *cred)
2266{
2267	struct mac_biba *subj;
2268	int error;
2269
2270	if (!mac_biba_enabled)
2271		return (0);
2272
2273	subj = SLOT(cred->cr_label);
2274
2275	error = mac_biba_subject_privileged(subj);
2276	if (error)
2277		return (error);
2278
2279	return (0);
2280}
2281
2282static int
2283mac_biba_check_system_acct(struct ucred *cred, struct vnode *vp,
2284    struct label *label)
2285{
2286	struct mac_biba *subj, *obj;
2287	int error;
2288
2289	if (!mac_biba_enabled)
2290		return (0);
2291
2292	subj = SLOT(cred->cr_label);
2293
2294	error = mac_biba_subject_privileged(subj);
2295	if (error)
2296		return (error);
2297
2298	if (label == NULL)
2299		return (0);
2300
2301	obj = SLOT(label);
2302	if (!mac_biba_high_effective(obj))
2303		return (EACCES);
2304
2305	return (0);
2306}
2307
2308static int
2309mac_biba_check_system_settime(struct ucred *cred)
2310{
2311	struct mac_biba *subj;
2312	int error;
2313
2314	if (!mac_biba_enabled)
2315		return (0);
2316
2317	subj = SLOT(cred->cr_label);
2318
2319	error = mac_biba_subject_privileged(subj);
2320	if (error)
2321		return (error);
2322
2323	return (0);
2324}
2325
2326static int
2327mac_biba_check_system_swapon(struct ucred *cred, struct vnode *vp,
2328    struct label *label)
2329{
2330	struct mac_biba *subj, *obj;
2331	int error;
2332
2333	if (!mac_biba_enabled)
2334		return (0);
2335
2336	subj = SLOT(cred->cr_label);
2337	obj = SLOT(label);
2338
2339	error = mac_biba_subject_privileged(subj);
2340	if (error)
2341		return (error);
2342
2343	if (!mac_biba_high_effective(obj))
2344		return (EACCES);
2345
2346	return (0);
2347}
2348
2349static int
2350mac_biba_check_system_swapoff(struct ucred *cred, struct vnode *vp,
2351    struct label *label)
2352{
2353	struct mac_biba *subj;
2354	int error;
2355
2356	if (!mac_biba_enabled)
2357		return (0);
2358
2359	subj = SLOT(cred->cr_label);
2360
2361	error = mac_biba_subject_privileged(subj);
2362	if (error)
2363		return (error);
2364
2365	return (0);
2366}
2367
2368static int
2369mac_biba_check_system_sysctl(struct ucred *cred, struct sysctl_oid *oidp,
2370    void *arg1, int arg2, struct sysctl_req *req)
2371{
2372	struct mac_biba *subj;
2373	int error;
2374
2375	if (!mac_biba_enabled)
2376		return (0);
2377
2378	subj = SLOT(cred->cr_label);
2379
2380	/*
2381	 * Treat sysctl variables without CTLFLAG_ANYBODY flag as
2382	 * biba/high, but also require privilege to change them.
2383	 */
2384	if (req->newptr != NULL && (oidp->oid_kind & CTLFLAG_ANYBODY) == 0) {
2385		if (!mac_biba_subject_dominate_high(subj))
2386			return (EACCES);
2387
2388		error = mac_biba_subject_privileged(subj);
2389		if (error)
2390			return (error);
2391	}
2392
2393	return (0);
2394}
2395
2396static int
2397mac_biba_check_vnode_chdir(struct ucred *cred, struct vnode *dvp,
2398    struct label *dlabel)
2399{
2400	struct mac_biba *subj, *obj;
2401
2402	if (!mac_biba_enabled)
2403		return (0);
2404
2405	subj = SLOT(cred->cr_label);
2406	obj = SLOT(dlabel);
2407
2408	if (!mac_biba_dominate_effective(obj, subj))
2409		return (EACCES);
2410
2411	return (0);
2412}
2413
2414static int
2415mac_biba_check_vnode_chroot(struct ucred *cred, struct vnode *dvp,
2416    struct label *dlabel)
2417{
2418	struct mac_biba *subj, *obj;
2419
2420	if (!mac_biba_enabled)
2421		return (0);
2422
2423	subj = SLOT(cred->cr_label);
2424	obj = SLOT(dlabel);
2425
2426	if (!mac_biba_dominate_effective(obj, subj))
2427		return (EACCES);
2428
2429	return (0);
2430}
2431
2432static int
2433mac_biba_check_vnode_create(struct ucred *cred, struct vnode *dvp,
2434    struct label *dlabel, struct componentname *cnp, struct vattr *vap)
2435{
2436	struct mac_biba *subj, *obj;
2437
2438	if (!mac_biba_enabled)
2439		return (0);
2440
2441	subj = SLOT(cred->cr_label);
2442	obj = SLOT(dlabel);
2443
2444	if (!mac_biba_dominate_effective(subj, obj))
2445		return (EACCES);
2446
2447	return (0);
2448}
2449
2450static int
2451mac_biba_check_vnode_delete(struct ucred *cred, struct vnode *dvp,
2452    struct label *dlabel, struct vnode *vp, struct label *label,
2453    struct componentname *cnp)
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(dlabel);
2462
2463	if (!mac_biba_dominate_effective(subj, obj))
2464		return (EACCES);
2465
2466	obj = SLOT(label);
2467
2468	if (!mac_biba_dominate_effective(subj, obj))
2469		return (EACCES);
2470
2471	return (0);
2472}
2473
2474static int
2475mac_biba_check_vnode_deleteacl(struct ucred *cred, struct vnode *vp,
2476    struct label *label, acl_type_t type)
2477{
2478	struct mac_biba *subj, *obj;
2479
2480	if (!mac_biba_enabled)
2481		return (0);
2482
2483	subj = SLOT(cred->cr_label);
2484	obj = SLOT(label);
2485
2486	if (!mac_biba_dominate_effective(subj, obj))
2487		return (EACCES);
2488
2489	return (0);
2490}
2491
2492static int
2493mac_biba_check_vnode_deleteextattr(struct ucred *cred, struct vnode *vp,
2494    struct label *label, int attrnamespace, const char *name)
2495{
2496	struct mac_biba *subj, *obj;
2497
2498	if (!mac_biba_enabled)
2499		return (0);
2500
2501	subj = SLOT(cred->cr_label);
2502	obj = SLOT(label);
2503
2504	if (!mac_biba_dominate_effective(subj, obj))
2505		return (EACCES);
2506
2507	return (0);
2508}
2509
2510static int
2511mac_biba_check_vnode_exec(struct ucred *cred, struct vnode *vp,
2512    struct label *label, struct image_params *imgp,
2513    struct label *execlabel)
2514{
2515	struct mac_biba *subj, *obj, *exec;
2516	int error;
2517
2518	if (execlabel != NULL) {
2519		/*
2520		 * We currently don't permit labels to be changed at
2521		 * exec-time as part of Biba, so disallow non-NULL
2522		 * Biba label elements in the execlabel.
2523		 */
2524		exec = SLOT(execlabel);
2525		error = biba_atmostflags(exec, 0);
2526		if (error)
2527			return (error);
2528	}
2529
2530	if (!mac_biba_enabled)
2531		return (0);
2532
2533	subj = SLOT(cred->cr_label);
2534	obj = SLOT(label);
2535
2536	if (!mac_biba_dominate_effective(obj, subj))
2537		return (EACCES);
2538
2539	return (0);
2540}
2541
2542static int
2543mac_biba_check_vnode_getacl(struct ucred *cred, struct vnode *vp,
2544    struct label *label, acl_type_t type)
2545{
2546	struct mac_biba *subj, *obj;
2547
2548	if (!mac_biba_enabled)
2549		return (0);
2550
2551	subj = SLOT(cred->cr_label);
2552	obj = SLOT(label);
2553
2554	if (!mac_biba_dominate_effective(obj, subj))
2555		return (EACCES);
2556
2557	return (0);
2558}
2559
2560static int
2561mac_biba_check_vnode_getextattr(struct ucred *cred, struct vnode *vp,
2562    struct label *label, int attrnamespace, const char *name, struct uio *uio)
2563{
2564	struct mac_biba *subj, *obj;
2565
2566	if (!mac_biba_enabled)
2567		return (0);
2568
2569	subj = SLOT(cred->cr_label);
2570	obj = SLOT(label);
2571
2572	if (!mac_biba_dominate_effective(obj, subj))
2573		return (EACCES);
2574
2575	return (0);
2576}
2577
2578static int
2579mac_biba_check_vnode_link(struct ucred *cred, struct vnode *dvp,
2580    struct label *dlabel, struct vnode *vp, struct label *label,
2581    struct componentname *cnp)
2582{
2583	struct mac_biba *subj, *obj;
2584
2585	if (!mac_biba_enabled)
2586		return (0);
2587
2588	subj = SLOT(cred->cr_label);
2589	obj = SLOT(dlabel);
2590
2591	if (!mac_biba_dominate_effective(subj, obj))
2592		return (EACCES);
2593
2594	obj = SLOT(label);
2595
2596	if (!mac_biba_dominate_effective(subj, obj))
2597		return (EACCES);
2598
2599	return (0);
2600}
2601
2602static int
2603mac_biba_check_vnode_listextattr(struct ucred *cred, struct vnode *vp,
2604    struct label *label, int attrnamespace)
2605{
2606	struct mac_biba *subj, *obj;
2607
2608	if (!mac_biba_enabled)
2609		return (0);
2610
2611	subj = SLOT(cred->cr_label);
2612	obj = SLOT(label);
2613
2614	if (!mac_biba_dominate_effective(obj, subj))
2615		return (EACCES);
2616
2617	return (0);
2618}
2619
2620static int
2621mac_biba_check_vnode_lookup(struct ucred *cred, struct vnode *dvp,
2622    struct label *dlabel, struct componentname *cnp)
2623{
2624	struct mac_biba *subj, *obj;
2625
2626	if (!mac_biba_enabled)
2627		return (0);
2628
2629	subj = SLOT(cred->cr_label);
2630	obj = SLOT(dlabel);
2631
2632	if (!mac_biba_dominate_effective(obj, subj))
2633		return (EACCES);
2634
2635	return (0);
2636}
2637
2638static int
2639mac_biba_check_vnode_mmap(struct ucred *cred, struct vnode *vp,
2640    struct label *label, int prot, int flags)
2641{
2642	struct mac_biba *subj, *obj;
2643
2644	/*
2645	 * Rely on the use of open()-time protections to handle
2646	 * non-revocation cases.
2647	 */
2648	if (!mac_biba_enabled || !revocation_enabled)
2649		return (0);
2650
2651	subj = SLOT(cred->cr_label);
2652	obj = SLOT(label);
2653
2654	if (prot & (VM_PROT_READ | VM_PROT_EXECUTE)) {
2655		if (!mac_biba_dominate_effective(obj, subj))
2656			return (EACCES);
2657	}
2658	if (((prot & VM_PROT_WRITE) != 0) && ((flags & MAP_SHARED) != 0)) {
2659		if (!mac_biba_dominate_effective(subj, obj))
2660			return (EACCES);
2661	}
2662
2663	return (0);
2664}
2665
2666static int
2667mac_biba_check_vnode_open(struct ucred *cred, struct vnode *vp,
2668    struct label *vnodelabel, int acc_mode)
2669{
2670	struct mac_biba *subj, *obj;
2671
2672	if (!mac_biba_enabled)
2673		return (0);
2674
2675	subj = SLOT(cred->cr_label);
2676	obj = SLOT(vnodelabel);
2677
2678	/* XXX privilege override for admin? */
2679	if (acc_mode & (VREAD | VEXEC | VSTAT)) {
2680		if (!mac_biba_dominate_effective(obj, subj))
2681			return (EACCES);
2682	}
2683	if (acc_mode & (VWRITE | VAPPEND | VADMIN)) {
2684		if (!mac_biba_dominate_effective(subj, obj))
2685			return (EACCES);
2686	}
2687
2688	return (0);
2689}
2690
2691static int
2692mac_biba_check_vnode_poll(struct ucred *active_cred, struct ucred *file_cred,
2693    struct vnode *vp, struct label *label)
2694{
2695	struct mac_biba *subj, *obj;
2696
2697	if (!mac_biba_enabled || !revocation_enabled)
2698		return (0);
2699
2700	subj = SLOT(active_cred->cr_label);
2701	obj = SLOT(label);
2702
2703	if (!mac_biba_dominate_effective(obj, subj))
2704		return (EACCES);
2705
2706	return (0);
2707}
2708
2709static int
2710mac_biba_check_vnode_read(struct ucred *active_cred, struct ucred *file_cred,
2711    struct vnode *vp, struct label *label)
2712{
2713	struct mac_biba *subj, *obj;
2714
2715	if (!mac_biba_enabled || !revocation_enabled)
2716		return (0);
2717
2718	subj = SLOT(active_cred->cr_label);
2719	obj = SLOT(label);
2720
2721	if (!mac_biba_dominate_effective(obj, subj))
2722		return (EACCES);
2723
2724	return (0);
2725}
2726
2727static int
2728mac_biba_check_vnode_readdir(struct ucred *cred, struct vnode *dvp,
2729    struct label *dlabel)
2730{
2731	struct mac_biba *subj, *obj;
2732
2733	if (!mac_biba_enabled)
2734		return (0);
2735
2736	subj = SLOT(cred->cr_label);
2737	obj = SLOT(dlabel);
2738
2739	if (!mac_biba_dominate_effective(obj, subj))
2740		return (EACCES);
2741
2742	return (0);
2743}
2744
2745static int
2746mac_biba_check_vnode_readlink(struct ucred *cred, struct vnode *vp,
2747    struct label *label)
2748{
2749	struct mac_biba *subj, *obj;
2750
2751	if (!mac_biba_enabled)
2752		return (0);
2753
2754	subj = SLOT(cred->cr_label);
2755	obj = SLOT(label);
2756
2757	if (!mac_biba_dominate_effective(obj, subj))
2758		return (EACCES);
2759
2760	return (0);
2761}
2762
2763static int
2764mac_biba_check_vnode_relabel(struct ucred *cred, struct vnode *vp,
2765    struct label *vnodelabel, struct label *newlabel)
2766{
2767	struct mac_biba *old, *new, *subj;
2768	int error;
2769
2770	old = SLOT(vnodelabel);
2771	new = SLOT(newlabel);
2772	subj = SLOT(cred->cr_label);
2773
2774	/*
2775	 * If there is a Biba label update for the vnode, it must be a
2776	 * effective label.
2777	 */
2778	error = biba_atmostflags(new, MAC_BIBA_FLAG_EFFECTIVE);
2779	if (error)
2780		return (error);
2781
2782	/*
2783	 * To perform a relabel of the vnode (Biba label or not), Biba must
2784	 * authorize the relabel.
2785	 */
2786	if (!mac_biba_effective_in_range(old, subj))
2787		return (EPERM);
2788
2789	/*
2790	 * If the Biba label is to be changed, authorize as appropriate.
2791	 */
2792	if (new->mb_flags & MAC_BIBA_FLAG_EFFECTIVE) {
2793		/*
2794		 * To change the Biba label on a vnode, the new vnode label
2795		 * must be in the subject range.
2796		 */
2797		if (!mac_biba_effective_in_range(new, subj))
2798			return (EPERM);
2799
2800		/*
2801		 * To change the Biba label on the vnode to be EQUAL,
2802		 * the subject must have appropriate privilege.
2803		 */
2804		if (mac_biba_contains_equal(new)) {
2805			error = mac_biba_subject_privileged(subj);
2806			if (error)
2807				return (error);
2808		}
2809	}
2810
2811	return (0);
2812}
2813
2814static int
2815mac_biba_check_vnode_rename_from(struct ucred *cred, struct vnode *dvp,
2816    struct label *dlabel, struct vnode *vp, struct label *label,
2817    struct componentname *cnp)
2818{
2819	struct mac_biba *subj, *obj;
2820
2821	if (!mac_biba_enabled)
2822		return (0);
2823
2824	subj = SLOT(cred->cr_label);
2825	obj = SLOT(dlabel);
2826
2827	if (!mac_biba_dominate_effective(subj, obj))
2828		return (EACCES);
2829
2830	obj = SLOT(label);
2831
2832	if (!mac_biba_dominate_effective(subj, obj))
2833		return (EACCES);
2834
2835	return (0);
2836}
2837
2838static int
2839mac_biba_check_vnode_rename_to(struct ucred *cred, struct vnode *dvp,
2840    struct label *dlabel, struct vnode *vp, struct label *label, int samedir,
2841    struct componentname *cnp)
2842{
2843	struct mac_biba *subj, *obj;
2844
2845	if (!mac_biba_enabled)
2846		return (0);
2847
2848	subj = SLOT(cred->cr_label);
2849	obj = SLOT(dlabel);
2850
2851	if (!mac_biba_dominate_effective(subj, obj))
2852		return (EACCES);
2853
2854	if (vp != NULL) {
2855		obj = SLOT(label);
2856
2857		if (!mac_biba_dominate_effective(subj, obj))
2858			return (EACCES);
2859	}
2860
2861	return (0);
2862}
2863
2864static int
2865mac_biba_check_vnode_revoke(struct ucred *cred, struct vnode *vp,
2866    struct label *label)
2867{
2868	struct mac_biba *subj, *obj;
2869
2870	if (!mac_biba_enabled)
2871		return (0);
2872
2873	subj = SLOT(cred->cr_label);
2874	obj = SLOT(label);
2875
2876	if (!mac_biba_dominate_effective(subj, obj))
2877		return (EACCES);
2878
2879	return (0);
2880}
2881
2882static int
2883mac_biba_check_vnode_setacl(struct ucred *cred, struct vnode *vp,
2884    struct label *label, acl_type_t type, struct acl *acl)
2885{
2886	struct mac_biba *subj, *obj;
2887
2888	if (!mac_biba_enabled)
2889		return (0);
2890
2891	subj = SLOT(cred->cr_label);
2892	obj = SLOT(label);
2893
2894	if (!mac_biba_dominate_effective(subj, obj))
2895		return (EACCES);
2896
2897	return (0);
2898}
2899
2900static int
2901mac_biba_check_vnode_setextattr(struct ucred *cred, struct vnode *vp,
2902    struct label *vnodelabel, int attrnamespace, const char *name,
2903    struct uio *uio)
2904{
2905	struct mac_biba *subj, *obj;
2906
2907	if (!mac_biba_enabled)
2908		return (0);
2909
2910	subj = SLOT(cred->cr_label);
2911	obj = SLOT(vnodelabel);
2912
2913	if (!mac_biba_dominate_effective(subj, obj))
2914		return (EACCES);
2915
2916	/* XXX: protect the MAC EA in a special way? */
2917
2918	return (0);
2919}
2920
2921static int
2922mac_biba_check_vnode_setflags(struct ucred *cred, struct vnode *vp,
2923    struct label *vnodelabel, u_long flags)
2924{
2925	struct mac_biba *subj, *obj;
2926
2927	if (!mac_biba_enabled)
2928		return (0);
2929
2930	subj = SLOT(cred->cr_label);
2931	obj = SLOT(vnodelabel);
2932
2933	if (!mac_biba_dominate_effective(subj, obj))
2934		return (EACCES);
2935
2936	return (0);
2937}
2938
2939static int
2940mac_biba_check_vnode_setmode(struct ucred *cred, struct vnode *vp,
2941    struct label *vnodelabel, mode_t mode)
2942{
2943	struct mac_biba *subj, *obj;
2944
2945	if (!mac_biba_enabled)
2946		return (0);
2947
2948	subj = SLOT(cred->cr_label);
2949	obj = SLOT(vnodelabel);
2950
2951	if (!mac_biba_dominate_effective(subj, obj))
2952		return (EACCES);
2953
2954	return (0);
2955}
2956
2957static int
2958mac_biba_check_vnode_setowner(struct ucred *cred, struct vnode *vp,
2959    struct label *vnodelabel, uid_t uid, gid_t gid)
2960{
2961	struct mac_biba *subj, *obj;
2962
2963	if (!mac_biba_enabled)
2964		return (0);
2965
2966	subj = SLOT(cred->cr_label);
2967	obj = SLOT(vnodelabel);
2968
2969	if (!mac_biba_dominate_effective(subj, obj))
2970		return (EACCES);
2971
2972	return (0);
2973}
2974
2975static int
2976mac_biba_check_vnode_setutimes(struct ucred *cred, struct vnode *vp,
2977    struct label *vnodelabel, struct timespec atime, struct timespec mtime)
2978{
2979	struct mac_biba *subj, *obj;
2980
2981	if (!mac_biba_enabled)
2982		return (0);
2983
2984	subj = SLOT(cred->cr_label);
2985	obj = SLOT(vnodelabel);
2986
2987	if (!mac_biba_dominate_effective(subj, obj))
2988		return (EACCES);
2989
2990	return (0);
2991}
2992
2993static int
2994mac_biba_check_vnode_stat(struct ucred *active_cred, struct ucred *file_cred,
2995    struct vnode *vp, struct label *vnodelabel)
2996{
2997	struct mac_biba *subj, *obj;
2998
2999	if (!mac_biba_enabled)
3000		return (0);
3001
3002	subj = SLOT(active_cred->cr_label);
3003	obj = SLOT(vnodelabel);
3004
3005	if (!mac_biba_dominate_effective(obj, subj))
3006		return (EACCES);
3007
3008	return (0);
3009}
3010
3011static int
3012mac_biba_check_vnode_write(struct ucred *active_cred,
3013    struct ucred *file_cred, struct vnode *vp, struct label *label)
3014{
3015	struct mac_biba *subj, *obj;
3016
3017	if (!mac_biba_enabled || !revocation_enabled)
3018		return (0);
3019
3020	subj = SLOT(active_cred->cr_label);
3021	obj = SLOT(label);
3022
3023	if (!mac_biba_dominate_effective(subj, obj))
3024		return (EACCES);
3025
3026	return (0);
3027}
3028
3029static void
3030mac_biba_associate_nfsd_label(struct ucred *cred)
3031{
3032	struct mac_biba *label;
3033
3034	label = SLOT(cred->cr_label);
3035	mac_biba_set_effective(label, MAC_BIBA_TYPE_LOW, 0, NULL);
3036	mac_biba_set_range(label, MAC_BIBA_TYPE_LOW, 0, NULL,
3037	    MAC_BIBA_TYPE_HIGH, 0, NULL);
3038}
3039
3040static void
3041mac_biba_init_syncache_from_inpcb(struct label *label, struct inpcb *inp)
3042{
3043	struct mac_biba *source, *dest;
3044
3045	source = SLOT(inp->inp_label);
3046	dest = SLOT(label);
3047	mac_biba_copy_effective(source, dest);
3048}
3049
3050static void
3051mac_biba_create_mbuf_from_syncache(struct label *sc_label, struct mbuf *m,
3052    struct label *mbuf_label)
3053{
3054	struct mac_biba *source, *dest;
3055
3056	source = SLOT(sc_label);
3057	dest = SLOT(mbuf_label);
3058	mac_biba_copy_effective(source, dest);
3059}
3060
3061static struct mac_policy_ops mac_biba_ops =
3062{
3063	.mpo_init = mac_biba_init,
3064	.mpo_init_bpfdesc_label = mac_biba_init_label,
3065	.mpo_init_cred_label = mac_biba_init_label,
3066	.mpo_init_devfsdirent_label = mac_biba_init_label,
3067	.mpo_init_ifnet_label = mac_biba_init_label,
3068	.mpo_init_inpcb_label = mac_biba_init_label_waitcheck,
3069	.mpo_init_syncache_label = mac_biba_init_label_waitcheck,
3070	.mpo_init_sysv_msgmsg_label = mac_biba_init_label,
3071	.mpo_init_sysv_msgqueue_label = mac_biba_init_label,
3072	.mpo_init_sysv_sem_label = mac_biba_init_label,
3073	.mpo_init_sysv_shm_label = mac_biba_init_label,
3074	.mpo_init_ipq_label = mac_biba_init_label_waitcheck,
3075	.mpo_init_mbuf_label = mac_biba_init_label_waitcheck,
3076	.mpo_init_mount_label = mac_biba_init_label,
3077	.mpo_init_mount_fs_label = mac_biba_init_label,
3078	.mpo_init_pipe_label = mac_biba_init_label,
3079	.mpo_init_posix_sem_label = mac_biba_init_label,
3080	.mpo_init_socket_label = mac_biba_init_label_waitcheck,
3081	.mpo_init_socket_peer_label = mac_biba_init_label_waitcheck,
3082	.mpo_init_syncache_from_inpcb = mac_biba_init_syncache_from_inpcb,
3083	.mpo_init_vnode_label = mac_biba_init_label,
3084	.mpo_destroy_bpfdesc_label = mac_biba_destroy_label,
3085	.mpo_destroy_cred_label = mac_biba_destroy_label,
3086	.mpo_destroy_devfsdirent_label = mac_biba_destroy_label,
3087	.mpo_destroy_ifnet_label = mac_biba_destroy_label,
3088	.mpo_destroy_inpcb_label = mac_biba_destroy_label,
3089	.mpo_destroy_syncache_label = mac_biba_destroy_label,
3090	.mpo_destroy_sysv_msgmsg_label = mac_biba_destroy_label,
3091	.mpo_destroy_sysv_msgqueue_label = mac_biba_destroy_label,
3092	.mpo_destroy_sysv_sem_label = mac_biba_destroy_label,
3093	.mpo_destroy_sysv_shm_label = mac_biba_destroy_label,
3094	.mpo_destroy_ipq_label = mac_biba_destroy_label,
3095	.mpo_destroy_mbuf_label = mac_biba_destroy_label,
3096	.mpo_destroy_mount_label = mac_biba_destroy_label,
3097	.mpo_destroy_mount_fs_label = mac_biba_destroy_label,
3098	.mpo_destroy_pipe_label = mac_biba_destroy_label,
3099	.mpo_destroy_posix_sem_label = mac_biba_destroy_label,
3100	.mpo_destroy_socket_label = mac_biba_destroy_label,
3101	.mpo_destroy_socket_peer_label = mac_biba_destroy_label,
3102	.mpo_destroy_vnode_label = mac_biba_destroy_label,
3103	.mpo_copy_cred_label = mac_biba_copy_label,
3104	.mpo_copy_ifnet_label = mac_biba_copy_label,
3105	.mpo_copy_mbuf_label = mac_biba_copy_label,
3106	.mpo_copy_pipe_label = mac_biba_copy_label,
3107	.mpo_copy_socket_label = mac_biba_copy_label,
3108	.mpo_copy_vnode_label = mac_biba_copy_label,
3109	.mpo_externalize_cred_label = mac_biba_externalize_label,
3110	.mpo_externalize_ifnet_label = mac_biba_externalize_label,
3111	.mpo_externalize_pipe_label = mac_biba_externalize_label,
3112	.mpo_externalize_socket_label = mac_biba_externalize_label,
3113	.mpo_externalize_socket_peer_label = mac_biba_externalize_label,
3114	.mpo_externalize_vnode_label = mac_biba_externalize_label,
3115	.mpo_internalize_cred_label = mac_biba_internalize_label,
3116	.mpo_internalize_ifnet_label = mac_biba_internalize_label,
3117	.mpo_internalize_pipe_label = mac_biba_internalize_label,
3118	.mpo_internalize_socket_label = mac_biba_internalize_label,
3119	.mpo_internalize_vnode_label = mac_biba_internalize_label,
3120	.mpo_create_devfs_device = mac_biba_create_devfs_device,
3121	.mpo_create_devfs_directory = mac_biba_create_devfs_directory,
3122	.mpo_create_devfs_symlink = mac_biba_create_devfs_symlink,
3123	.mpo_create_mount = mac_biba_create_mount,
3124	.mpo_relabel_vnode = mac_biba_relabel_vnode,
3125	.mpo_update_devfsdirent = mac_biba_update_devfsdirent,
3126	.mpo_associate_vnode_devfs = mac_biba_associate_vnode_devfs,
3127	.mpo_associate_vnode_extattr = mac_biba_associate_vnode_extattr,
3128	.mpo_associate_vnode_singlelabel = mac_biba_associate_vnode_singlelabel,
3129	.mpo_create_vnode_extattr = mac_biba_create_vnode_extattr,
3130	.mpo_setlabel_vnode_extattr = mac_biba_setlabel_vnode_extattr,
3131	.mpo_create_mbuf_from_socket = mac_biba_create_mbuf_from_socket,
3132	.mpo_create_mbuf_from_syncache = mac_biba_create_mbuf_from_syncache,
3133	.mpo_create_pipe = mac_biba_create_pipe,
3134	.mpo_create_posix_sem = mac_biba_create_posix_sem,
3135	.mpo_create_socket = mac_biba_create_socket,
3136	.mpo_create_socket_from_socket = mac_biba_create_socket_from_socket,
3137	.mpo_relabel_pipe = mac_biba_relabel_pipe,
3138	.mpo_relabel_socket = mac_biba_relabel_socket,
3139	.mpo_set_socket_peer_from_mbuf = mac_biba_set_socket_peer_from_mbuf,
3140	.mpo_set_socket_peer_from_socket = mac_biba_set_socket_peer_from_socket,
3141	.mpo_create_bpfdesc = mac_biba_create_bpfdesc,
3142	.mpo_create_datagram_from_ipq = mac_biba_create_datagram_from_ipq,
3143	.mpo_create_fragment = mac_biba_create_fragment,
3144	.mpo_create_ifnet = mac_biba_create_ifnet,
3145	.mpo_create_inpcb_from_socket = mac_biba_create_inpcb_from_socket,
3146	.mpo_create_sysv_msgmsg = mac_biba_create_sysv_msgmsg,
3147	.mpo_create_sysv_msgqueue = mac_biba_create_sysv_msgqueue,
3148	.mpo_create_sysv_sem = mac_biba_create_sysv_sem,
3149	.mpo_create_sysv_shm = mac_biba_create_sysv_shm,
3150	.mpo_create_ipq = mac_biba_create_ipq,
3151	.mpo_create_mbuf_from_inpcb = mac_biba_create_mbuf_from_inpcb,
3152	.mpo_create_mbuf_linklayer = mac_biba_create_mbuf_linklayer,
3153	.mpo_create_mbuf_from_bpfdesc = mac_biba_create_mbuf_from_bpfdesc,
3154	.mpo_create_mbuf_from_ifnet = mac_biba_create_mbuf_from_ifnet,
3155	.mpo_create_mbuf_multicast_encap = mac_biba_create_mbuf_multicast_encap,
3156	.mpo_create_mbuf_netlayer = mac_biba_create_mbuf_netlayer,
3157	.mpo_fragment_match = mac_biba_fragment_match,
3158	.mpo_relabel_ifnet = mac_biba_relabel_ifnet,
3159	.mpo_update_ipq = mac_biba_update_ipq,
3160	.mpo_inpcb_sosetlabel = mac_biba_inpcb_sosetlabel,
3161	.mpo_create_proc0 = mac_biba_create_proc0,
3162	.mpo_create_proc1 = mac_biba_create_proc1,
3163	.mpo_relabel_cred = mac_biba_relabel_cred,
3164	.mpo_cleanup_sysv_msgmsg = mac_biba_cleanup_sysv_msgmsg,
3165	.mpo_cleanup_sysv_msgqueue = mac_biba_cleanup_sysv_msgqueue,
3166	.mpo_cleanup_sysv_sem = mac_biba_cleanup_sysv_sem,
3167	.mpo_cleanup_sysv_shm = mac_biba_cleanup_sysv_shm,
3168	.mpo_check_bpfdesc_receive = mac_biba_check_bpfdesc_receive,
3169	.mpo_check_cred_relabel = mac_biba_check_cred_relabel,
3170	.mpo_check_cred_visible = mac_biba_check_cred_visible,
3171	.mpo_check_ifnet_relabel = mac_biba_check_ifnet_relabel,
3172	.mpo_check_ifnet_transmit = mac_biba_check_ifnet_transmit,
3173	.mpo_check_inpcb_deliver = mac_biba_check_inpcb_deliver,
3174	.mpo_check_sysv_msgrcv = mac_biba_check_sysv_msgrcv,
3175	.mpo_check_sysv_msgrmid = mac_biba_check_sysv_msgrmid,
3176	.mpo_check_sysv_msqget = mac_biba_check_sysv_msqget,
3177	.mpo_check_sysv_msqsnd = mac_biba_check_sysv_msqsnd,
3178	.mpo_check_sysv_msqrcv = mac_biba_check_sysv_msqrcv,
3179	.mpo_check_sysv_msqctl = mac_biba_check_sysv_msqctl,
3180	.mpo_check_sysv_semctl = mac_biba_check_sysv_semctl,
3181	.mpo_check_sysv_semget = mac_biba_check_sysv_semget,
3182	.mpo_check_sysv_semop = mac_biba_check_sysv_semop,
3183	.mpo_check_sysv_shmat = mac_biba_check_sysv_shmat,
3184	.mpo_check_sysv_shmctl = mac_biba_check_sysv_shmctl,
3185	.mpo_check_sysv_shmget = mac_biba_check_sysv_shmget,
3186	.mpo_check_kld_load = mac_biba_check_kld_load,
3187	.mpo_check_kld_unload = mac_biba_check_kld_unload,
3188	.mpo_check_mount_stat = mac_biba_check_mount_stat,
3189	.mpo_check_pipe_ioctl = mac_biba_check_pipe_ioctl,
3190	.mpo_check_pipe_poll = mac_biba_check_pipe_poll,
3191	.mpo_check_pipe_read = mac_biba_check_pipe_read,
3192	.mpo_check_pipe_relabel = mac_biba_check_pipe_relabel,
3193	.mpo_check_pipe_stat = mac_biba_check_pipe_stat,
3194	.mpo_check_pipe_write = mac_biba_check_pipe_write,
3195	.mpo_check_posix_sem_destroy = mac_biba_check_posix_sem_write,
3196	.mpo_check_posix_sem_getvalue = mac_biba_check_posix_sem_rdonly,
3197	.mpo_check_posix_sem_open = mac_biba_check_posix_sem_write,
3198	.mpo_check_posix_sem_post = mac_biba_check_posix_sem_write,
3199	.mpo_check_posix_sem_unlink = mac_biba_check_posix_sem_write,
3200	.mpo_check_posix_sem_wait = mac_biba_check_posix_sem_write,
3201	.mpo_check_proc_debug = mac_biba_check_proc_debug,
3202	.mpo_check_proc_sched = mac_biba_check_proc_sched,
3203	.mpo_check_proc_signal = mac_biba_check_proc_signal,
3204	.mpo_check_socket_deliver = mac_biba_check_socket_deliver,
3205	.mpo_check_socket_relabel = mac_biba_check_socket_relabel,
3206	.mpo_check_socket_visible = mac_biba_check_socket_visible,
3207	.mpo_check_sysarch_ioperm = mac_biba_check_sysarch_ioperm,
3208	.mpo_check_system_acct = mac_biba_check_system_acct,
3209	.mpo_check_system_settime = mac_biba_check_system_settime,
3210	.mpo_check_system_swapon = mac_biba_check_system_swapon,
3211	.mpo_check_system_swapoff = mac_biba_check_system_swapoff,
3212	.mpo_check_system_sysctl = mac_biba_check_system_sysctl,
3213	.mpo_check_vnode_access = mac_biba_check_vnode_open,
3214	.mpo_check_vnode_chdir = mac_biba_check_vnode_chdir,
3215	.mpo_check_vnode_chroot = mac_biba_check_vnode_chroot,
3216	.mpo_check_vnode_create = mac_biba_check_vnode_create,
3217	.mpo_check_vnode_delete = mac_biba_check_vnode_delete,
3218	.mpo_check_vnode_deleteacl = mac_biba_check_vnode_deleteacl,
3219	.mpo_check_vnode_deleteextattr = mac_biba_check_vnode_deleteextattr,
3220	.mpo_check_vnode_exec = mac_biba_check_vnode_exec,
3221	.mpo_check_vnode_getacl = mac_biba_check_vnode_getacl,
3222	.mpo_check_vnode_getextattr = mac_biba_check_vnode_getextattr,
3223	.mpo_check_vnode_link = mac_biba_check_vnode_link,
3224	.mpo_check_vnode_listextattr = mac_biba_check_vnode_listextattr,
3225	.mpo_check_vnode_lookup = mac_biba_check_vnode_lookup,
3226	.mpo_check_vnode_mmap = mac_biba_check_vnode_mmap,
3227	.mpo_check_vnode_open = mac_biba_check_vnode_open,
3228	.mpo_check_vnode_poll = mac_biba_check_vnode_poll,
3229	.mpo_check_vnode_read = mac_biba_check_vnode_read,
3230	.mpo_check_vnode_readdir = mac_biba_check_vnode_readdir,
3231	.mpo_check_vnode_readlink = mac_biba_check_vnode_readlink,
3232	.mpo_check_vnode_relabel = mac_biba_check_vnode_relabel,
3233	.mpo_check_vnode_rename_from = mac_biba_check_vnode_rename_from,
3234	.mpo_check_vnode_rename_to = mac_biba_check_vnode_rename_to,
3235	.mpo_check_vnode_revoke = mac_biba_check_vnode_revoke,
3236	.mpo_check_vnode_setacl = mac_biba_check_vnode_setacl,
3237	.mpo_check_vnode_setextattr = mac_biba_check_vnode_setextattr,
3238	.mpo_check_vnode_setflags = mac_biba_check_vnode_setflags,
3239	.mpo_check_vnode_setmode = mac_biba_check_vnode_setmode,
3240	.mpo_check_vnode_setowner = mac_biba_check_vnode_setowner,
3241	.mpo_check_vnode_setutimes = mac_biba_check_vnode_setutimes,
3242	.mpo_check_vnode_stat = mac_biba_check_vnode_stat,
3243	.mpo_check_vnode_write = mac_biba_check_vnode_write,
3244	.mpo_associate_nfsd_label = mac_biba_associate_nfsd_label,
3245	.mpo_create_mbuf_from_firewall = mac_biba_create_mbuf_from_firewall,
3246};
3247
3248MAC_POLICY_SET(&mac_biba_ops, mac_biba, "TrustedBSD MAC/Biba",
3249    MPC_LOADTIME_FLAG_NOTLATE | MPC_LOADTIME_FLAG_LABELMBUFS, &mac_biba_slot);
3250