Restartable sequences: x86 32/64 architecture support
[deliverable/linux.git] / arch / x86 / kernel / signal.c
index 99f285b512dbbeef0756ef22e0832714375432f5..d7252b5dad5ccc8d9011ad76ac1c2d9e9b85986c 100644 (file)
@@ -683,6 +683,12 @@ setup_rt_frame(struct ksignal *ksig, struct pt_regs *regs)
        sigset_t *set = sigmask_to_save();
        compat_sigset_t *cset = (compat_sigset_t *) set;
 
+       /*
+        * Increment event counter and perform fixup for the pre-signal
+        * frame.
+        */
+       rseq_signal_deliver(regs);
+
        /* Set up the stack frame */
        if (is_ia32_frame()) {
                if (ksig->ka.sa.sa_flags & SA_SIGINFO)
@@ -760,8 +766,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 (in_ia32_syscall())
+       /*
+        * 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.025094 seconds and 5 git commands to generate.