tools/testing/selftests/riscv/cfi/shadowstack.c

Source file repositories/reference/linux-study-clean/tools/testing/selftests/riscv/cfi/shadowstack.c

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/riscv/cfi/shadowstack.c
Extension
.c
Size
8993 bytes
Lines
386
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

WEXITSTATUS(child_status) != CHILD_EXIT_CODE_SSWRITE) {
		ksft_print_msg("Shadow stack WPT failed: child wasn't signaled for write\n");
		return false;
	}

	ret = munmap(write_addr, SHADOW_STACK_ALLOC_SIZE);
	if (ret) {
		ksft_print_msg("Shadow stack WPT failed: munmap failed, error code %d\n",
			       ret);
		return false;
	}

	return true;
}

#define SS_MAGIC_WRITE_VAL 0xbeefdead

int gup_tests(int mem_fd, unsigned long *shdw_addr)
{
	unsigned long val = 0;

	lseek(mem_fd, (unsigned long)shdw_addr, SEEK_SET);
	if (read(mem_fd, &val, sizeof(val)) < 0) {
		ksft_print_msg("Reading shadow stack mem via gup failed\n");
		return 1;
	}

	val = SS_MAGIC_WRITE_VAL;
	lseek(mem_fd, (unsigned long)shdw_addr, SEEK_SET);
	if (write(mem_fd, &val, sizeof(val)) < 0) {
		ksft_print_msg("Writing shadow stack mem via gup failed\n");
		return 1;
	}

	if (*shdw_addr != SS_MAGIC_WRITE_VAL) {
		ksft_print_msg("GUP write to shadow stack memory failed\n");
		return 1;
	}

	return 0;
}

bool shadow_stack_gup_tests(unsigned long test_num, void *ctx)
{
	unsigned long shdw_addr = 0;
	unsigned long *write_addr = NULL;
	int fd = 0;
	bool ret = false;

	ksft_print_msg("Exercising shadow stack gup tests\n");
	shdw_addr = my_syscall3(__NR_map_shadow_stack, NULL, SHADOW_STACK_ALLOC_SIZE, 0);

	if (((long)shdw_addr) <= 0) {
		ksft_print_msg("map_shadow_stack failed with error code %d\n", (int)shdw_addr);
		return false;
	}

	write_addr = (unsigned long *)shdw_addr;

	fd = open("/proc/self/mem", O_RDWR);
	if (fd == -1)
		return false;

	if (gup_tests(fd, write_addr)) {
		ksft_print_msg("gup tests failed\n");
		goto out;
	}

	ret = true;
out:
	if (shdw_addr && munmap(write_addr, SHADOW_STACK_ALLOC_SIZE)) {
		ksft_print_msg("munmap failed with error code %d\n", ret);
		ret = false;
	}

	return ret;
}

volatile bool break_loop;

void sigusr1_handler(int signo)
{
	break_loop = true;
}

bool sigusr1_signal_test(void)
{
	struct sigaction sa = {};

	sa.sa_handler = sigusr1_handler;

Annotation

Implementation Notes