security/landlock/domain.c

Source file repositories/reference/linux-study-clean/security/landlock/domain.c

File Facts

System
Linux kernel
Corpus path
security/landlock/domain.c
Extension
.c
Size
8758 bytes
Lines
310
Domain
Core OS
Bucket
Security And Isolation
Inferred role
Core OS: implementation source
Status
source implementation candidate

Why This File Exists

Core operating-system implementation surface: boot, tasks, memory, VFS, syscall-facing interfaces, synchronization, credentials, and isolation.

Dependency Surface

Detected Declarations

Annotated Snippet

BITS_PER_TYPE(access_mask_t)) {
		const u8 layer =
			(deny_masks >> (access_index *
					HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1))) &
			(LANDLOCK_MAX_NUM_LAYERS - 1);

		if (masks->layers[layer].quiet)
			quiet_optional_accesses |= BIT(access_index);
		access_index++;
	}
	return quiet_optional_accesses;
}

#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST

static void test_get_layer_deny_mask(struct kunit *const test)
{
	const unsigned long truncate = BIT_INDEX(LANDLOCK_ACCESS_FS_TRUNCATE);
	const unsigned long ioctl_dev = BIT_INDEX(LANDLOCK_ACCESS_FS_IOCTL_DEV);

	KUNIT_EXPECT_EQ(test, 0,
			get_layer_deny_mask(_LANDLOCK_ACCESS_FS_OPTIONAL,
					    truncate, 0));
	KUNIT_EXPECT_EQ(test, 0x3,
			get_layer_deny_mask(_LANDLOCK_ACCESS_FS_OPTIONAL,
					    truncate, 3));

	KUNIT_EXPECT_EQ(test, 0,
			get_layer_deny_mask(_LANDLOCK_ACCESS_FS_OPTIONAL,
					    ioctl_dev, 0));
	KUNIT_EXPECT_EQ(test, 0xf0,
			get_layer_deny_mask(_LANDLOCK_ACCESS_FS_OPTIONAL,
					    ioctl_dev, 15));
}

#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */

deny_masks_t
landlock_get_deny_masks(const access_mask_t all_existing_optional_access,
			const access_mask_t optional_access,
			const struct layer_masks *const masks)
{
	const unsigned long access_opt = optional_access;
	unsigned long access_bit;
	deny_masks_t deny_masks = 0;
	access_mask_t all_denied = 0;

	/* This may require change with new object types. */
	WARN_ON_ONCE(!access_mask_subset(optional_access,
					 all_existing_optional_access));

	if (WARN_ON_ONCE(!masks))
		return 0;

	if (WARN_ON_ONCE(!access_opt))
		return 0;

	for (ssize_t i = ARRAY_SIZE(masks->layers) - 1; i >= 0; i--) {
		const access_mask_t denied = masks->layers[i].access &
					     optional_access;
		const unsigned long newly_denied = denied & ~all_denied;

		if (!newly_denied)
			continue;

		for_each_set_bit(access_bit, &newly_denied,
				 8 * sizeof(access_mask_t)) {
			deny_masks |= get_layer_deny_mask(
				all_existing_optional_access, access_bit, i);
		}
		all_denied |= denied;
	}
	return deny_masks;
}

#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST

static void test_landlock_get_deny_masks(struct kunit *const test)
{
	const struct layer_masks layers1 = {
		.layers[0].access = LANDLOCK_ACCESS_FS_EXECUTE |
				    LANDLOCK_ACCESS_FS_IOCTL_DEV,
		.layers[1].access = LANDLOCK_ACCESS_FS_TRUNCATE,
		.layers[2].access = LANDLOCK_ACCESS_FS_IOCTL_DEV,
		.layers[9].access = LANDLOCK_ACCESS_FS_EXECUTE,
	};

	KUNIT_EXPECT_EQ(test, 0x1,
			landlock_get_deny_masks(_LANDLOCK_ACCESS_FS_OPTIONAL,
						LANDLOCK_ACCESS_FS_TRUNCATE,

Annotation

Implementation Notes