Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 198ee8e1 authored by Dominik Brodowski's avatar Dominik Brodowski Committed by Ingo Molnar
Browse files

selftests/x86: Fix vDSO selftest segfault for vsyscall=none



The vDSO selftest tries to execute a vsyscall unconditionally, even if it
is not present on the test system (e.g. if booted with vsyscall=none or
with CONFIG_LEGACY_VSYSCALL_NONE=y set. Fix this by copying (and tweaking)
the vsyscall check from test_vsyscall.c

Signed-off-by: default avatarDominik Brodowski <linux@dominikbrodowski.net>
Cc: Andrew Lutomirski <luto@kernel.org>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: linux-kselftest@vger.kernel.org
Cc: shuah@kernel.org
Link: http://lkml.kernel.org/r/20180211111013.16888-3-linux@dominikbrodowski.net


Signed-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent b498c261
Loading
Loading
Loading
Loading
+43 −7
Original line number Original line Diff line number Diff line
@@ -28,18 +28,52 @@


int nerrs = 0;
int nerrs = 0;


typedef long (*getcpu_t)(unsigned *, unsigned *, void *);

getcpu_t vgetcpu;
getcpu_t vdso_getcpu;

static void *vsyscall_getcpu(void)
{
#ifdef __x86_64__
#ifdef __x86_64__
# define VSYS(x) (x)
	FILE *maps;
	char line[128];
	bool found = false;

	maps = fopen("/proc/self/maps", "r");
	if (!maps) /* might still be present, but ignore it here, as we test vDSO not vsyscall */
		return NULL;

	while (fgets(line, sizeof(line), maps)) {
		char r, x;
		void *start, *end;
		char name[128];
		if (sscanf(line, "%p-%p %c-%cp %*x %*x:%*x %*u %s",
			   &start, &end, &r, &x, name) != 5)
			continue;

		if (strcmp(name, "[vsyscall]"))
			continue;

		/* assume entries are OK, as we test vDSO here not vsyscall */
		found = true;
		break;
	}

	fclose(maps);

	if (!found) {
		printf("Warning: failed to find vsyscall getcpu\n");
		return NULL;
	}
	return (void *) (0xffffffffff600800);
#else
#else
# define VSYS(x) 0
	return NULL;
#endif
#endif
}


typedef long (*getcpu_t)(unsigned *, unsigned *, void *);

const getcpu_t vgetcpu = (getcpu_t)VSYS(0xffffffffff600800);
getcpu_t vdso_getcpu;


void fill_function_pointers()
static void fill_function_pointers()
{
{
	void *vdso = dlopen("linux-vdso.so.1",
	void *vdso = dlopen("linux-vdso.so.1",
			    RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
			    RTLD_LAZY | RTLD_LOCAL | RTLD_NOLOAD);
@@ -54,6 +88,8 @@ void fill_function_pointers()
	vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
	vdso_getcpu = (getcpu_t)dlsym(vdso, "__vdso_getcpu");
	if (!vdso_getcpu)
	if (!vdso_getcpu)
		printf("Warning: failed to find getcpu in vDSO\n");
		printf("Warning: failed to find getcpu in vDSO\n");

	vgetcpu = (getcpu_t) vsyscall_getcpu();
}
}


static long sys_getcpu(unsigned * cpu, unsigned * node,
static long sys_getcpu(unsigned * cpu, unsigned * node,