Merge branch 'x86-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[deliverable/linux.git] / arch / x86 / kernel / signal.c
index 548ddf7d6fd2085676328ffcde6375ce3e88b477..04cb3212db2d1d6e0e3263cef736121e6b0ad0d6 100644 (file)
@@ -146,7 +146,7 @@ static int restore_sigcontext(struct pt_regs *regs,
                buf = (void __user *)buf_val;
        } get_user_catch(err);
 
-       err |= fpu__restore_sig(buf, config_enabled(CONFIG_X86_32));
+       err |= fpu__restore_sig(buf, IS_ENABLED(CONFIG_X86_32));
 
        force_iret();
 
@@ -245,25 +245,24 @@ get_sigframe(struct k_sigaction *ka, struct pt_regs *regs, size_t frame_size,
        struct fpu *fpu = &current->thread.fpu;
 
        /* redzone */
-       if (config_enabled(CONFIG_X86_64))
+       if (IS_ENABLED(CONFIG_X86_64))
                sp -= 128;
 
-       if (!onsigstack) {
-               /* This is the X/Open sanctioned signal stack switching.  */
-               if (ka->sa.sa_flags & SA_ONSTACK) {
-                       if (current->sas_ss_size)
-                               sp = current->sas_ss_sp + current->sas_ss_size;
-               } else if (config_enabled(CONFIG_X86_32) &&
-                          (regs->ss & 0xffff) != __USER_DS &&
-                          !(ka->sa.sa_flags & SA_RESTORER) &&
-                          ka->sa.sa_restorer) {
-                               /* This is the legacy signal stack switching. */
-                               sp = (unsigned long) ka->sa.sa_restorer;
-               }
+       /* This is the X/Open sanctioned signal stack switching.  */
+       if (ka->sa.sa_flags & SA_ONSTACK) {
+               if (sas_ss_flags(sp) == 0)
+                       sp = current->sas_ss_sp + current->sas_ss_size;
+       } else if (IS_ENABLED(CONFIG_X86_32) &&
+                  !onsigstack &&
+                  (regs->ss & 0xffff) != __USER_DS &&
+                  !(ka->sa.sa_flags & SA_RESTORER) &&
+                  ka->sa.sa_restorer) {
+               /* This is the legacy signal stack switching. */
+               sp = (unsigned long) ka->sa.sa_restorer;
        }
 
        if (fpu->fpstate_active) {
-               sp = fpu__alloc_mathframe(sp, config_enabled(CONFIG_X86_32),
+               sp = fpu__alloc_mathframe(sp, IS_ENABLED(CONFIG_X86_32),
                                          &buf_fx, &math_size);
                *fpstate = (void __user *)sp;
        }
@@ -391,7 +390,7 @@ static int __setup_rt_frame(int sig, struct ksignal *ksig,
                put_user_ex(&frame->uc, &frame->puc);
 
                /* Create the ucontext.  */
-               if (cpu_has_xsave)
+               if (boot_cpu_has(X86_FEATURE_XSAVE))
                        put_user_ex(UC_FP_XSTATE, &frame->uc.uc_flags);
                else
                        put_user_ex(0, &frame->uc.uc_flags);
@@ -442,7 +441,7 @@ static unsigned long frame_uc_flags(struct pt_regs *regs)
 {
        unsigned long flags;
 
-       if (cpu_has_xsave)
+       if (boot_cpu_has(X86_FEATURE_XSAVE))
                flags = UC_FP_XSTATE | UC_SIGCONTEXT_SS;
        else
                flags = UC_SIGCONTEXT_SS;
@@ -663,18 +662,18 @@ badframe:
 
 static inline int is_ia32_compat_frame(void)
 {
-       return config_enabled(CONFIG_IA32_EMULATION) &&
+       return IS_ENABLED(CONFIG_IA32_EMULATION) &&
               test_thread_flag(TIF_IA32);
 }
 
 static inline int is_ia32_frame(void)
 {
-       return config_enabled(CONFIG_X86_32) || is_ia32_compat_frame();
+       return IS_ENABLED(CONFIG_X86_32) || is_ia32_compat_frame();
 }
 
 static inline int is_x32_frame(void)
 {
-       return config_enabled(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32);
+       return IS_ENABLED(CONFIG_X86_X32_ABI) && test_thread_flag(TIF_X32);
 }
 
 static int
@@ -761,8 +760,30 @@ handle_signal(struct ksignal *ksig, struct pt_regs *regs)
 
 static inline unsigned long get_nr_restart_syscall(const struct pt_regs *regs)
 {
-#ifdef CONFIG_X86_64
-       if (is_ia32_task())
+       /*
+        * This function is fundamentally broken as currently
+        * implemented.
+        *
+        * The idea is that we want to trigger a call to the
+        * restart_block() syscall and that we want in_ia32_syscall(),
+        * in_x32_syscall(), etc. to match whatever they were in the
+        * syscall being restarted.  We assume that the syscall
+        * instruction at (regs->ip - 2) matches whatever syscall
+        * instruction we used to enter in the first place.
+        *
+        * The problem is that we can get here when ptrace pokes
+        * syscall-like values into regs even if we're not in a syscall
+        * at all.
+        *
+        * For now, we maintain historical behavior and guess based on
+        * stored state.  We could do better by saving the actual
+        * syscall arch in restart_block or (with caveats on x32) by
+        * checking if regs->ip points to 'int $0x80'.  The current
+        * behavior is incorrect if a tracer has a different bitness
+        * than the tracee.
+        */
+#ifdef CONFIG_IA32_EMULATION
+       if (current_thread_info()->status & (TS_COMPAT|TS_I386_REGS_POKED))
                return __NR_ia32_restart_syscall;
 #endif
 #ifdef CONFIG_X86_X32_ABI
This page took 0.040596 seconds and 5 git commands to generate.