tools/testing/selftests/x86/test_mremap_vdso.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/test_mremap_vdso.c
Extension
.c
Size
3318 bytes
Lines
150
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 (errno == EINVAL) {
			ksft_print_msg("vDSO partial move failed, will try with bigger size\n");
			return -1; /* Retry with larger */
		}
		ksft_print_msg("[FAIL]\tmremap failed (%d): %m\n", errno);
		return 1;
	}

	return 0;

}

#define VDSO_NAME "[vdso]"
#define VMFLAGS "VmFlags:"
#define MSEAL_FLAGS "sl"
#define MAX_LINE_LEN 512

bool vdso_sealed(FILE *maps)
{
	char line[MAX_LINE_LEN];
	bool has_vdso = false;

	while (fgets(line, sizeof(line), maps)) {
		if (strstr(line, VDSO_NAME))
			has_vdso = true;

		if (has_vdso && !strncmp(line, VMFLAGS, strlen(VMFLAGS))) {
			if (strstr(line, MSEAL_FLAGS))
				return true;

			return false;
		}
	}

	return false;
}

int main(int argc, char **argv, char **envp)
{
	pid_t child;
	FILE *maps;

	ksft_print_header();
	ksft_set_plan(1);

	maps = fopen("/proc/self/smaps", "r");
	if (!maps) {
		ksft_test_result_skip(
			"Could not open /proc/self/smaps, errno=%d\n",
			 errno);

		return 0;
	}

	if (vdso_sealed(maps)) {
		ksft_test_result_skip("vdso is sealed\n");
		return 0;
	}

	fclose(maps);

	child = fork();
	if (child == -1)
		ksft_exit_fail_msg("failed to fork (%d): %m\n", errno);

	if (child == 0) {
		unsigned long vdso_size = PAGE_SIZE;
		unsigned long auxval;
		int ret = -1;

		auxval = getauxval(AT_SYSINFO_EHDR);
		ksft_print_msg("AT_SYSINFO_EHDR is %#lx\n", auxval);
		if (!auxval || auxval == -ENOENT) {
			ksft_print_msg("WARN: getauxval failed\n");
			return 0;
		}

		/* Simpler than parsing ELF header */
		while (ret < 0) {
			ret = try_to_remap((void *)auxval, vdso_size);
			vdso_size += PAGE_SIZE;
		}

#ifdef __i386__
		/* Glibc is likely to explode now - exit with raw syscall */
		asm volatile ("int $0x80" : : "a" (__NR_exit), "b" (!!ret));
#else /* __x86_64__ */
		syscall(SYS_exit, ret);
#endif
	} else {

Annotation

Implementation Notes