Skip to content
  • Oleg Nesterov's avatar
    x86, fpu: shift drop_init_fpu() from save_xstate_sig() to handle_signal() · fb5b6e7e
    Oleg Nesterov authored
    
    
    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: default avatarBean Anderson <bean@azulsystems.com>
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Link: http://lkml.kernel.org/r/20140902175713.GA21646@redhat.com
    
    
    Signed-off-by: default avatarH. Peter Anvin <hpa@linux.intel.com>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
    fb5b6e7e