summaryrefslogtreecommitdiff
path: root/drivers/lguest/x86/core.c
diff options
context:
space:
mode:
authorOleg Nesterov <oleg@redhat.com>2014-09-02 19:57:13 +0200
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>2014-11-14 08:47:54 -0800
commitfb5b6e7ecfefa65efd7280f4824741ac76e10c4b (patch)
tree6402c662cca9ba1c76e7a4af980d69e3b016c29a /drivers/lguest/x86/core.c
parentb888e3d442069e3107d9b4a43c1321e4d555b6cd (diff)
downloadlwn-fb5b6e7ecfefa65efd7280f4824741ac76e10c4b.tar.gz
lwn-fb5b6e7ecfefa65efd7280f4824741ac76e10c4b.zip
x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal()
commit 66463db4fc5605d51c7bb81d009d5bf30a783a2c upstream. save_xstate_sig()->drop_init_fpu() doesn't look right. setup_rt_frame() can fail after that, in this case the next setup_rt_frame() triggered by SIGSEGV won't save fpu simply because the old state was lost. This obviously mean that fpu won't be restored after sys_rt_sigreturn() from SIGSEGV handler. Shift drop_init_fpu() into !failed branch in handle_signal(). Test-case (needs -O2): #include <stdio.h> #include <signal.h> #include <unistd.h> #include <sys/syscall.h> #include <sys/mman.h> #include <pthread.h> #include <assert.h> volatile double D; void test(double d) { int pid = getpid(); for (D = d; D == d; ) { /* sys_tkill(pid, SIGHUP); asm to avoid save/reload * fp regs around "C" call */ asm ("" : : "a"(200), "D"(pid), "S"(1)); asm ("syscall" : : : "ax"); } printf("ERR!!\n"); } void sigh(int sig) { } char altstack[4096 * 10] __attribute__((aligned(4096))); void *tfunc(void *arg) { for (;;) { mprotect(altstack, sizeof(altstack), PROT_READ); mprotect(altstack, sizeof(altstack), PROT_READ|PROT_WRITE); } } int main(void) { stack_t st = { .ss_sp = altstack, .ss_size = sizeof(altstack), .ss_flags = SS_ONSTACK, }; struct sigaction sa = { .sa_handler = sigh, }; pthread_t pt; sigaction(SIGSEGV, &sa, NULL); sigaltstack(&st, NULL); sa.sa_flags = SA_ONSTACK; sigaction(SIGHUP, &sa, NULL); pthread_create(&pt, NULL, tfunc, NULL); test(123.456); return 0; } Reported-by: Bean Anderson <bean@azulsystems.com> Signed-off-by: Oleg Nesterov <oleg@redhat.com> Link: http://lkml.kernel.org/r/20140902175713.GA21646@redhat.com Signed-off-by: H. Peter Anvin <hpa@linux.intel.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Diffstat (limited to 'drivers/lguest/x86/core.c')
0 files changed, 0 insertions, 0 deletions