Add the new internal ptrace flags, PT_SINGLE_STEP and PT_SINGLE_BLOCK.

Like PT_SYSCALL_TRACE, this is needed to avoid the unnecessary ptrace
reports when TIF_SINGLESTEP was set by another engine, not by ptrace.
Also, we need these bits to coordinate the user_*_single_step() calls
from ptrace and utrace.

TODO: update the !x86 ptrace code which does user_disable_single_step().

Signed-off-by: Oleg Nesterov <o...@redhat.com>
---
 arch/x86/kernel/ptrace.c  |    1 +
 include/linux/ptrace.h    |    5 ++++-
 include/linux/tracehook.h |    7 +++++--
 kernel/ptrace.c           |    3 +++
 4 files changed, 13 insertions(+), 3 deletions(-)

diff --git a/arch/x86/kernel/ptrace.c b/arch/x86/kernel/ptrace.c
index 807c2a2..7ab475f 100644
--- a/arch/x86/kernel/ptrace.c
+++ b/arch/x86/kernel/ptrace.c
@@ -807,6 +807,7 @@ static int ioperm_get(struct task_struct *target,
  */
 void ptrace_disable(struct task_struct *child)
 {
+       child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK);
        user_disable_single_step(child);
 #ifdef TIF_SYSCALL_EMU
        clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 98d995d..65b1e4f 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -91,6 +91,8 @@
 #define PT_TRACE_MASK  0x000003f4
 
 #define PT_SYSCALL_TRACE       0x00010000
+#define PT_SINGLE_STEP         0x00020000
+#define PT_SINGLE_BLOCK                0x00040000
 
 /* single stepping state bits (used on ARM and PA-RISC) */
 #define PT_SINGLESTEP_BIT      31
@@ -189,7 +191,8 @@ static inline void ptrace_init_task(struct task_struct 
*child, bool ptrace)
        child->ptrace = 0;
        if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) {
                child->ptrace = current->ptrace;
-               child->ptrace &= ~PT_SYSCALL_TRACE;
+               child->ptrace &=
+                       ~(PT_SYSCALL_TRACE | PT_SINGLE_STEP | PT_SINGLE_BLOCK);
                __ptrace_link(child, current->parent);
        }
 
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 6ce7a37..06edb52 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -121,6 +121,9 @@ static inline __must_check int 
tracehook_report_syscall_entry(
        return 0;
 }
 
+#define ptrace_wants_step()    \
+       (current->ptrace & (PT_SINGLE_STEP | PT_SINGLE_BLOCK))
+
 /**
  * tracehook_report_syscall_exit - task has just finished a system call
  * @regs:              user register state of current task
@@ -143,7 +146,7 @@ static inline void tracehook_report_syscall_exit(struct 
pt_regs *regs, int step)
        if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT))
                utrace_report_syscall_exit(regs);
 
-       if (step) {
+       if (step && ptrace_wants_step()) {
                siginfo_t info;
                user_single_step_siginfo(current, regs, &info);
                force_sig_info(SIGTRAP, &info, current);
@@ -436,7 +439,7 @@ static inline void tracehook_signal_handler(int sig, 
siginfo_t *info,
 {
        if (task_utrace_flags(current))
                utrace_signal_handler(current, stepping);
-       if (stepping)
+       if (stepping && ptrace_wants_step())
                ptrace_notify(SIGTRAP);
 }
 
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 209ea2d..44908d0 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -575,13 +575,16 @@ static int ptrace_resume(struct task_struct *child, long 
request,
                clear_tsk_thread_flag(child, TIF_SYSCALL_EMU);
 #endif
 
+       child->ptrace &= ~(PT_SINGLE_STEP | PT_SINGLE_BLOCK);
        if (is_singleblock(request)) {
                if (unlikely(!arch_has_block_step()))
                        return -EIO;
+               child->ptrace |= PT_SINGLE_BLOCK;
                user_enable_block_step(child);
        } else if (is_singlestep(request) || is_sysemu_singlestep(request)) {
                if (unlikely(!arch_has_single_step()))
                        return -EIO;
+               child->ptrace |= PT_SINGLE_STEP;
                user_enable_single_step(child);
        } else {
                user_disable_single_step(child);
-- 
1.5.5.1


Reply via email to