tools/testing/selftests/x86/test_shadow_stack.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/x86/test_shadow_stack.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/test_shadow_stack.c
Extension
.c
Size
23346 bytes
Lines
1089
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

struct node {
	struct node *next;
	void *mapping;
};

/*
 * This tests whether mmap will place other mappings in a shadow stack's guard
 * gap. The steps are:
 *   1. Finds an empty place by mapping and unmapping something.
 *   2. Map a shadow stack in the middle of the known empty area.
 *   3. Map a bunch of PAGE_SIZE mappings. These will use the search down
 *      direction, filling any gaps until it encounters the shadow stack's
 *      guard gap.
 *   4. When a mapping lands below the shadow stack from step 2, then all
 *      of the above gaps are filled. The search down algorithm will have
 *      looked at the shadow stack gaps.
 *   5. See if it landed in the gap.
 */
int test_guard_gap_other_gaps(void)
{
	void *free_area, *shstk, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
	struct node *head = NULL, *cur;

	free_area = mmap(0, SS_SIZE * 3, PROT_READ | PROT_WRITE,
			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	munmap(free_area, SS_SIZE * 3);

	shstk = create_shstk(free_area + SS_SIZE);
	if (shstk == MAP_FAILED)
		return 1;

	while (test_map > shstk) {
		test_map = mmap(0, PAGE_SIZE, PROT_READ | PROT_WRITE,
				MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
		if (test_map == MAP_FAILED)
			return 1;
		cur = malloc(sizeof(*cur));
		cur->mapping = test_map;

		cur->next = head;
		head = cur;
	}

	while (head) {
		cur = head;
		head = cur->next;
		munmap(cur->mapping, PAGE_SIZE);
		free(cur);
	}

	free_shstk(shstk);

	if (shstk - test_map - PAGE_SIZE != PAGE_SIZE)
		return 1;

	printf("[OK]\tGuard gap test, other mapping's gaps\n");

	return 0;
}

/* Tests respecting the guard gap of the mapping getting placed */
int test_guard_gap_new_mappings_gaps(void)
{
	void *free_area, *shstk_start, *test_map = (void *)0xFFFFFFFFFFFFFFFF;
	struct node *head = NULL, *cur;
	int ret = 0;

	free_area = mmap(0, PAGE_SIZE * 4, PROT_READ | PROT_WRITE,
			 MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	munmap(free_area, PAGE_SIZE * 4);

	/* Test letting map_shadow_stack find a free space */
	shstk_start = mmap(free_area, PAGE_SIZE, PROT_READ | PROT_WRITE,
			   MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
	if (shstk_start == MAP_FAILED || shstk_start != free_area)
		return 1;

	while (test_map > shstk_start) {
		test_map = (void *)syscall(__NR_map_shadow_stack, 0, PAGE_SIZE, 0);
		if (test_map == MAP_FAILED) {
			printf("[INFO]\tmap_shadow_stack MAP_FAILED\n");
			ret = 1;
			break;
		}

		cur = malloc(sizeof(*cur));
		cur->mapping = test_map;

		cur->next = head;
		head = cur;

Annotation

Implementation Notes