forked from Minki/linux
proc: save LOC in vsyscall test
Do one fork in vsyscall detection code and let SIGSEGV handler exit and carry information to the parent saving LOC. [adobriyan@gmail.com: redo original patch, delete unnecessary variables, minimise code changes] Link: https://lkml.kernel.org/r/YvoWzAn5dlhF75xa@localhost.localdomain Signed-off-by: Alexey Dobriyan <adobriyan@gmail.com> Signed-off-by: Brian Foster <bfoster@redhat.com> Reviewed-by: Brian Foster <bfoster@redhat.com> Tested-by: Brian Foster <bfoster@redhat.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
This commit is contained in:
parent
4f1d2a030d
commit
f4068af3a6
@ -213,22 +213,22 @@ static int make_exe(const uint8_t *payload, size_t len)
|
||||
|
||||
/*
|
||||
* 0: vsyscall VMA doesn't exist vsyscall=none
|
||||
* 1: vsyscall VMA is r-xp vsyscall=emulate
|
||||
* 2: vsyscall VMA is --xp vsyscall=xonly
|
||||
* 1: vsyscall VMA is --xp vsyscall=xonly
|
||||
* 2: vsyscall VMA is r-xp vsyscall=emulate
|
||||
*/
|
||||
static int g_vsyscall;
|
||||
static volatile int g_vsyscall;
|
||||
static const char *str_vsyscall;
|
||||
|
||||
static const char str_vsyscall_0[] = "";
|
||||
static const char str_vsyscall_1[] =
|
||||
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
|
||||
static const char str_vsyscall_2[] =
|
||||
"ffffffffff600000-ffffffffff601000 --xp 00000000 00:00 0 [vsyscall]\n";
|
||||
static const char str_vsyscall_2[] =
|
||||
"ffffffffff600000-ffffffffff601000 r-xp 00000000 00:00 0 [vsyscall]\n";
|
||||
|
||||
#ifdef __x86_64__
|
||||
static void sigaction_SIGSEGV(int _, siginfo_t *__, void *___)
|
||||
{
|
||||
_exit(1);
|
||||
_exit(g_vsyscall);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -255,6 +255,7 @@ static void vsyscall(void)
|
||||
act.sa_sigaction = sigaction_SIGSEGV;
|
||||
(void)sigaction(SIGSEGV, &act, NULL);
|
||||
|
||||
g_vsyscall = 0;
|
||||
/* gettimeofday(NULL, NULL); */
|
||||
asm volatile (
|
||||
"call %P0"
|
||||
@ -262,45 +263,20 @@ static void vsyscall(void)
|
||||
: "i" (0xffffffffff600000), "D" (NULL), "S" (NULL)
|
||||
: "rax", "rcx", "r11"
|
||||
);
|
||||
exit(0);
|
||||
|
||||
g_vsyscall = 1;
|
||||
*(volatile int *)0xffffffffff600000UL;
|
||||
|
||||
g_vsyscall = 2;
|
||||
exit(g_vsyscall);
|
||||
}
|
||||
waitpid(pid, &wstatus, 0);
|
||||
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) {
|
||||
/* vsyscall page exists and is executable. */
|
||||
if (WIFEXITED(wstatus)) {
|
||||
g_vsyscall = WEXITSTATUS(wstatus);
|
||||
} else {
|
||||
/* vsyscall page doesn't exist. */
|
||||
g_vsyscall = 0;
|
||||
return;
|
||||
}
|
||||
|
||||
pid = fork();
|
||||
if (pid < 0) {
|
||||
fprintf(stderr, "fork, errno %d\n", errno);
|
||||
fprintf(stderr, "error: wstatus %08x\n", wstatus);
|
||||
exit(1);
|
||||
}
|
||||
if (pid == 0) {
|
||||
struct rlimit rlim = {0, 0};
|
||||
(void)setrlimit(RLIMIT_CORE, &rlim);
|
||||
|
||||
/* Hide "segfault at ffffffffff600000" messages. */
|
||||
struct sigaction act;
|
||||
memset(&act, 0, sizeof(struct sigaction));
|
||||
act.sa_flags = SA_SIGINFO;
|
||||
act.sa_sigaction = sigaction_SIGSEGV;
|
||||
(void)sigaction(SIGSEGV, &act, NULL);
|
||||
|
||||
*(volatile int *)0xffffffffff600000UL;
|
||||
exit(0);
|
||||
}
|
||||
waitpid(pid, &wstatus, 0);
|
||||
if (WIFEXITED(wstatus) && WEXITSTATUS(wstatus) == 0) {
|
||||
/* vsyscall page is readable and executable. */
|
||||
g_vsyscall = 1;
|
||||
return;
|
||||
}
|
||||
|
||||
/* vsyscall page is executable but unreadable. */
|
||||
g_vsyscall = 2;
|
||||
}
|
||||
|
||||
int main(void)
|
||||
|
Loading…
Reference in New Issue
Block a user