security/landlock/audit.c

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

File Facts

System
Linux kernel
Corpus path
security/landlock/audit.c
Extension
.c
Size
22488 bytes
Lines
735
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

if (masks->layers[i].access & *access_request) {
			*access_request &= masks->layers[i].access;
			return i;
		}
	}

	/* Not found - fall back to default values */
	*access_request = 0;
	return domain->num_layers - 1;
}

#ifdef CONFIG_SECURITY_LANDLOCK_KUNIT_TEST

static void test_get_denied_layer(struct kunit *const test)
{
	const struct landlock_ruleset dom = {
		.num_layers = 5,
	};
	const struct layer_masks masks = {
		.layers[0].access = LANDLOCK_ACCESS_FS_EXECUTE |
				    LANDLOCK_ACCESS_FS_READ_DIR,
		.layers[1].access = LANDLOCK_ACCESS_FS_READ_FILE |
				    LANDLOCK_ACCESS_FS_READ_DIR,
		.layers[2].access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
	};
	access_mask_t access;

	access = LANDLOCK_ACCESS_FS_EXECUTE;
	KUNIT_EXPECT_EQ(test, 0, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_EXECUTE);

	access = LANDLOCK_ACCESS_FS_READ_FILE;
	KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_FILE);

	access = LANDLOCK_ACCESS_FS_READ_DIR;
	KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_DIR);

	access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR;
	KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access,
			LANDLOCK_ACCESS_FS_READ_FILE |
				LANDLOCK_ACCESS_FS_READ_DIR);

	access = LANDLOCK_ACCESS_FS_EXECUTE | LANDLOCK_ACCESS_FS_READ_DIR;
	KUNIT_EXPECT_EQ(test, 1, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access, LANDLOCK_ACCESS_FS_READ_DIR);

	access = LANDLOCK_ACCESS_FS_WRITE_FILE;
	KUNIT_EXPECT_EQ(test, 4, get_denied_layer(&dom, &access, &masks));
	KUNIT_EXPECT_EQ(test, access, 0);
}

#endif /* CONFIG_SECURITY_LANDLOCK_KUNIT_TEST */

static size_t
get_layer_from_deny_masks(access_mask_t *const access_request,
			  const access_mask_t all_existing_optional_access,
			  const deny_masks_t deny_masks,
			  optional_access_t quiet_optional_accesses,
			  bool *quiet)
{
	const unsigned long access_opt = all_existing_optional_access;
	const unsigned long access_req = *access_request;
	access_mask_t missing = 0;
	size_t youngest_layer = 0;
	size_t access_index = 0;
	unsigned long access_bit;
	bool should_quiet = false;

	/* This will require change with new object types. */
	WARN_ON_ONCE(access_opt != _LANDLOCK_ACCESS_FS_OPTIONAL);

	for_each_set_bit(access_bit, &access_opt,
			 BITS_PER_TYPE(access_mask_t)) {
		if (access_req & BIT(access_bit)) {
			const size_t layer =
				(deny_masks >>
				 (access_index *
				  HWEIGHT(LANDLOCK_MAX_NUM_LAYERS - 1))) &
				(LANDLOCK_MAX_NUM_LAYERS - 1);
			const bool layer_has_quiet =
				!!(quiet_optional_accesses & BIT(access_index));

			if (layer > youngest_layer) {
				youngest_layer = layer;
				missing = BIT(access_bit);
				should_quiet = layer_has_quiet;
			} else if (layer == youngest_layer) {

Annotation

Implementation Notes