-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
selftests/x86: Test __kernel_sigreturn and __kernel_rt_sigreturn
The vdso-based sigreturn mechanism is fragile and isn't used by modern glibc so, if we break it, we'll only notice when someone tests an unusual libc. Add an explicit selftest. [ I wrote this while debugging a Bionic breakage -- my first guess was that I had somehow messed up sigreturn. I've caused problems in that code before, and it's really easy to fail to notice it because there's nothing on a modern distro that needs vdso-based sigreturn. ] Signed-off-by: Andy Lutomirski <luto@kernel.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Borislav Petkov <bp@alien8.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Shuah Khan <shuahkh@osg.samsung.com> Cc: Thomas Gleixner <tglx@linutronix.de> Link: http://lkml.kernel.org/r/32946d714156879cd8e5d8eab044cd07557ed558.1452628504.git.luto@kernel.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
- Loading branch information
Andy Lutomirski
authored and
Ingo Molnar
committed
Jan 13, 2016
1 parent
2f0c0b2
commit 65cacec
Showing
2 changed files
with
90 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,88 @@ | ||
/* | ||
* vdso_restorer.c - tests vDSO-based signal restore | ||
* Copyright (c) 2015 Andrew Lutomirski | ||
* | ||
* This program is free software; you can redistribute it and/or modify | ||
* it under the terms and conditions of the GNU General Public License, | ||
* version 2, as published by the Free Software Foundation. | ||
* | ||
* This program is distributed in the hope it will be useful, but | ||
* WITHOUT ANY WARRANTY; without even the implied warranty of | ||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU | ||
* General Public License for more details. | ||
* | ||
* This makes sure that sa_restorer == NULL keeps working on 32-bit | ||
* configurations. Modern glibc doesn't use it under any circumstances, | ||
* so it's easy to overlook breakage. | ||
* | ||
* 64-bit userspace has never supported sa_restorer == NULL, so this is | ||
* 32-bit only. | ||
*/ | ||
|
||
#define _GNU_SOURCE | ||
|
||
#include <err.h> | ||
#include <stdio.h> | ||
#include <string.h> | ||
#include <signal.h> | ||
#include <unistd.h> | ||
#include <syscall.h> | ||
#include <sys/syscall.h> | ||
|
||
/* Open-code this -- the headers are too messy to easily use them. */ | ||
struct real_sigaction { | ||
void *handler; | ||
unsigned long flags; | ||
void *restorer; | ||
unsigned int mask[2]; | ||
}; | ||
|
||
static volatile sig_atomic_t handler_called; | ||
|
||
static void handler_with_siginfo(int sig, siginfo_t *info, void *ctx_void) | ||
{ | ||
handler_called = 1; | ||
} | ||
|
||
static void handler_without_siginfo(int sig) | ||
{ | ||
handler_called = 1; | ||
} | ||
|
||
int main() | ||
{ | ||
int nerrs = 0; | ||
struct real_sigaction sa; | ||
|
||
memset(&sa, 0, sizeof(sa)); | ||
sa.handler = handler_with_siginfo; | ||
sa.flags = SA_SIGINFO; | ||
sa.restorer = NULL; /* request kernel-provided restorer */ | ||
|
||
if (syscall(SYS_rt_sigaction, SIGUSR1, &sa, NULL, 8) != 0) | ||
err(1, "raw rt_sigaction syscall"); | ||
|
||
raise(SIGUSR1); | ||
|
||
if (handler_called) { | ||
printf("[OK]\tSA_SIGINFO handler returned successfully\n"); | ||
} else { | ||
printf("[FAIL]\tSA_SIGINFO handler was not called\n"); | ||
nerrs++; | ||
} | ||
|
||
sa.flags = 0; | ||
sa.handler = handler_without_siginfo; | ||
if (syscall(SYS_sigaction, SIGUSR1, &sa, 0) != 0) | ||
err(1, "raw sigaction syscall"); | ||
handler_called = 0; | ||
|
||
raise(SIGUSR1); | ||
|
||
if (handler_called) { | ||
printf("[OK]\t!SA_SIGINFO handler returned successfully\n"); | ||
} else { | ||
printf("[FAIL]\t!SA_SIGINFO handler was not called\n"); | ||
nerrs++; | ||
} | ||
} |