tools/testing/selftests/mm/guard-regions.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/mm/guard-regions.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/mm/guard-regions.c
Extension
.c
Size
62812 bytes
Lines
2331
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: implementation source
Status
source implementation candidate

Why This File Exists

Repository support layer: documentation, build tooling, samples, user-space helper tools, generated initramfs support, licenses, and validation utilities.

Dependency Surface

Detected Declarations

Annotated Snippet

if (i % 2 == 0) {
			ASSERT_FALSE(result);
		} else {
			ASSERT_TRUE(result);
			switch (variant->backing) {
			case ANON_BACKED:
				/* If anon, then we get a zero page. */
				ASSERT_EQ(*curr, '\0');
				break;
			default:
				/* Otherwise, we get the file data. */
				ASSERT_EQ(*curr, 'y');
				break;
			}
		}

		/* Now write... */
		result = try_write_buf(&ptr[i * page_size]);

		/* ...and make sure same result. */
		ASSERT_TRUE(i % 2 != 0 ? result : !result);
	}

	/* Cleanup. */
	ASSERT_EQ(munmap(ptr, 10 * page_size), 0);
}

/* Assert that mlock()'ed pages work correctly with guard markers. */
TEST_F(guard_regions, mlock)
{
	const unsigned long page_size = self->page_size;
	char *ptr;
	int i;

	ptr = mmap_(self, variant, NULL, 10 * page_size,
		    PROT_READ | PROT_WRITE, 0, 0);
	ASSERT_NE(ptr, MAP_FAILED);

	/* Populate. */
	for (i = 0; i < 10; i++) {
		char *curr = &ptr[i * page_size];

		*curr = 'y';
	}

	/* Lock. */
	ASSERT_EQ(mlock(ptr, 10 * page_size), 0);

	/* Now try to guard, should fail with EINVAL. */
	ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_INSTALL), -1);
	ASSERT_EQ(errno, EINVAL);

	/* OK unlock. */
	ASSERT_EQ(munlock(ptr, 10 * page_size), 0);

	/* Guard first half of range, should now succeed. */
	ASSERT_EQ(madvise(ptr, 5 * page_size, MADV_GUARD_INSTALL), 0);

	/* Make sure guard works. */
	for (i = 0; i < 10; i++) {
		char *curr = &ptr[i * page_size];
		bool result = try_read_write_buf(curr);

		if (i < 5) {
			ASSERT_FALSE(result);
		} else {
			ASSERT_TRUE(result);
			ASSERT_EQ(*curr, 'x');
		}
	}

	/*
	 * Now lock the latter part of the range. We can't lock the guard pages,
	 * as this would result in the pages being populated and the guarding
	 * would cause this to error out.
	 */
	ASSERT_EQ(mlock(&ptr[5 * page_size], 5 * page_size), 0);

	/*
	 * Now remove guard pages, we permit mlock()'d ranges to have guard
	 * pages removed as it is a non-destructive operation.
	 */
	ASSERT_EQ(madvise(ptr, 10 * page_size, MADV_GUARD_REMOVE), 0);

	/* Now check that no guard pages remain. */
	for (i = 0; i < 10; i++) {
		char *curr = &ptr[i * page_size];

		ASSERT_TRUE(try_read_write_buf(curr));
	}

Annotation

Implementation Notes