tools/testing/selftests/x86/test_vsyscall.c

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

File Facts

System
Linux kernel
Corpus path
tools/testing/selftests/x86/test_vsyscall.c
Extension
.c
Size
14005 bytes
Lines
536
Domain
Support Tooling And Documentation
Bucket
tools
Inferred role
Support Tooling And Documentation: syscall or user/kernel boundary
Status
core 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 (ret_vdso) {
			ksft_test_result_fail("vDSO getcpu() failed\n");
		} else {
			if (!have_node) {
				have_node = true;
				node = node_vdso;
			}

			if (cpu_vdso != cpu || node_vdso != node) {
				if (cpu_vdso != cpu)
					ksft_print_msg("vDSO reported CPU %u but should be %d\n",
						       cpu_vdso, cpu);
				if (node_vdso != node)
					ksft_print_msg("vDSO reported node %u but should be %u\n",
						       node_vdso, node);
				ksft_test_result_fail("Wrong values\n");
			} else {
				ksft_test_result_pass("vDSO reported correct CPU and node\n");
			}
		}
	} else {
		ksft_test_result_skip("vdso_getcpu isn't set\n");
	}

	if (vsyscall_map_x) {
		if (ret_vsys) {
			ksft_test_result_fail("vsyscall getcpu() failed\n");
		} else {
			if (!have_node) {
				have_node = true;
				node = node_vsys;
			}

			if (cpu_vsys != cpu || node_vsys != node) {
				if (cpu_vsys != cpu)
					ksft_print_msg("vsyscall reported CPU %u but should be %d\n",
						       cpu_vsys, cpu);
				if (node_vsys != node)
					ksft_print_msg("vsyscall reported node %u but should be %u\n",
						       node_vsys, node);
				ksft_test_result_fail("Wrong values\n");
			} else {
				ksft_test_result_pass("vsyscall reported correct CPU and node\n");
			}
		}
	} else {
		ksft_test_result_skip("vsyscall_map_x isn't set\n");
	}
}

#ifdef __x86_64__

static jmp_buf jmpbuf;
static volatile unsigned long segv_err, segv_trapno;

static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
{
	ucontext_t *ctx = (ucontext_t *)ctx_void;

	segv_trapno = ctx->uc_mcontext.gregs[REG_TRAPNO];
	segv_err =  ctx->uc_mcontext.gregs[REG_ERR];
	siglongjmp(jmpbuf, 1);
}

static void test_vsys_r(void)
{
	ksft_print_msg("Checking read access to the vsyscall page\n");
	bool can_read;
	if (sigsetjmp(jmpbuf, 1) == 0) {
		*(volatile int *)0xffffffffff600000;
		can_read = true;
	} else {
		can_read = false;
	}

	if (can_read && !vsyscall_map_r)
		ksft_test_result_fail("We have read access, but we shouldn't\n");
	else if (!can_read && vsyscall_map_r)
		ksft_test_result_fail("We don't have read access, but we should\n");
	else if (can_read)
		ksft_test_result_pass("We have read access\n");
	else
		ksft_test_result_pass("We do not have read access (trap=%ld, error=0x%lx)\n",
				      segv_trapno, segv_err);
}

static void test_vsys_x(void)
{
	if (vsyscall_map_x) {
		/* We already tested this adequately. */

Annotation

Implementation Notes