Currently tracehooks assume that if the ptraced task has
TIF_SYSCALL_TRACE set, the tracee should report the syscall.
This is not true, this thread flag can be set by utrace.
Add the new internal ptrace flag, PT_SYSCALL_TRACE. Change
ptrace_set_syscall_trace() to set/clear this bit along with
TIF_SYSCALL_TRACE, change ptrace_report_syscall() to check
this flag instead of PT_PTRACED.
Signed-off-by: Oleg Nesterov <oleg(a)redhat.com>
---
include/linux/ptrace.h | 3 +++
include/linux/tracehook.h | 2 +-
kernel/ptrace.c | 7 +++++--
3 files changed, 9 insertions(+), 3 deletions(-)
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 9178d5c..98d995d 100644
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -90,6 +90,8 @@
#define PT_TRACE_MASK 0x000003f4
+#define PT_SYSCALL_TRACE 0x00010000
+
/* single stepping state bits (used on ARM and PA-RISC) */
#define PT_SINGLESTEP_BIT 31
#define PT_SINGLESTEP (1<<PT_SINGLESTEP_BIT)
@@ -187,6 +189,7 @@ 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;
__ptrace_link(child, current->parent);
}
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 3c7b6b3..6ce7a37 100644
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -76,7 +76,7 @@ static inline void ptrace_report_syscall(struct pt_regs *regs)
{
int ptrace = task_ptrace(current);
- if (!(ptrace & PT_PTRACED))
+ if (!(ptrace & PT_SYSCALL_TRACE))
return;
ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0));
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index b6fd922..0825a01 100644
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -39,10 +39,13 @@ static void ptrace_signal_wake_up(struct task_struct *p, int
quiescent)
static void ptrace_set_syscall_trace(struct task_struct *p, bool on)
{
- if (on)
+ if (on) {
+ p->ptrace |= PT_SYSCALL_TRACE;
set_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
- else
+ } else {
+ p->ptrace &= ~PT_SYSCALL_TRACE;
clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE);
+ }
}
/*
--
1.5.5.1