Move send_sigtrap() logic from ptrace_resume() to ptrace_report_signal().
ptrace_resume() sets ctx->signr = SIGTRAP and returns UTRACE_INTERRUPT.
ptrace_report_signal() notices SIGTRAP, fills *info and reports the signal.

fill_sigtrap_info() mimics x86-specific send_sigtrap(), therefore:

        - it sets task->thread.trap_no/error_code under CONFIG_X86,
          what should it do in the #else case?

        - it sets info->si_addr = KSTK_EIP() which doesn't check
          user_mode_vm(). Hopefully this is OK?

        - with or without this patch utrace-ptrace assumes that
          PTRACE_SINGLESTEP after PTRACE_EVENT_SYSCALL_EXIT needs
          fill_sigtrap_info()'ed signal, this may break or fix !x86
          machines, and I don't know how to check. Perhaps
          ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) needs ifdef's.

User-visible changes:

        - unlike send_sigtrap()->force_sig_info() we don't unblock
          SIGTRAP or reset the handler

        - UTRACE_SIGNAL_REPORT synthesizes the "extra" SIGTRAP even
          if this signal is already penging

these changes looks good (but see the next patch). However, any
user-visible change is dangerous.

For example, suppose a tracee reports SYSCALL_EXIT and the tracer does
ptrace(PTRACE_SINGLESTEP, SIGTRAP). Before this change (or with upstream
kernel) send_sigtrap() is "lost", because ptrace_report_syscall() does
send_sig(SIGTRAP, current) first. With this patch we report TRAP_BRKPT
and then the normal SIGTRAP.

Also, we don't depend on dequeue_signal() which can dequeue another
signr before SIGTRAP. Again, looks like a fix actually, but may break
some test-case or stupid app.

---

 kernel/ptrace.c |   35 +++++++++++++++++++++++++++--------
 1 file changed, 27 insertions(+), 8 deletions(-)

--- PU/kernel/ptrace.c~127_OFFLOAD_SEND_SIGTRAP_TO_REPORT_SIGNAL        
2009-11-02 00:31:30.000000000 +0100
+++ PU/kernel/ptrace.c  2009-11-02 05:31:46.000000000 +0100
@@ -439,6 +439,18 @@ static u32 ptrace_report_exec(enum utrac
        return UTRACE_STOP;
 }
 
+static void fill_sigtrap_info(struct task_struct *task, siginfo_t *info)
+{
+#ifdef CONFIG_X86
+       task->thread.trap_no = 1;
+       task->thread.error_code = 0;
+#endif
+       memset(info, 0, sizeof(*info));
+       info->si_signo = SIGTRAP;
+       info->si_code  = TRAP_BRKPT;
+       info->si_addr  = (void __user*)KSTK_EIP(task);
+}
+
 static enum utrace_signal_action resume_signal(struct task_struct *task,
                                                struct ptrace_context *ctx,
                                                struct k_sigaction *return_ka)
@@ -506,8 +518,15 @@ static u32 ptrace_report_signal(u32 acti
                }
 
        case UTRACE_SIGNAL_REPORT:
-               if (!ctx->siginfo)
-                       return resume | UTRACE_SIGNAL_IGN;
+               if (!ctx->siginfo) {
+                       if (!ctx->signr)
+                               return resume | UTRACE_SIGNAL_IGN;
+
+                       WARN_ON(ctx->signr != SIGTRAP);
+                       /* set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) */
+                       fill_sigtrap_info(task, info);
+                       break;
+               }
 
                if (WARN_ON(ctx->siginfo != info))
                        return resume | UTRACE_SIGNAL_IGN;
@@ -911,12 +930,12 @@ static int ptrace_resume(struct task_str
 
        case PTRACE_EVENT_SYSCALL_EXIT:
                if (action != UTRACE_RESUME) {
-                       read_lock(&tasklist_lock);
-                       if (tracee->sighand)
-                               send_sigtrap(tracee, task_pt_regs(tracee),
-                                               0, TRAP_BRKPT);
-                       read_unlock(&tasklist_lock);
-                       action = UTRACE_RESUME;
+                       /*
+                        * single-stepping. UTRACE_SIGNAL_REPORT will
+                        * synthesize a trap to follow the syscall insn.
+                        */
+                       ctx->signr = SIGTRAP;
+                       action = UTRACE_INTERRUPT;
                }
                /* fallthrough */
 

Reply via email to