summaryrefslogtreecommitdiffstats
path: root/linux-2.6-tracehook.patch
blob: 027c6d5338aa901d3de9327a975c83d1c37730b2 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
From: Oleg Nesterov <oleg@redhat.com>

[PATCH] signals: check ->group_stop_count after tracehook_get_signal()

Move the call to do_signal_stop() down, after tracehook call.
This makes ->group_stop_count condition visible to tracers before
do_signal_stop() will participate in this group-stop.

Currently the patch has no effect, tracehook_get_signal() always
returns 0.

Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Signed-off-by: Roland McGrath <roland@redhat.com>
---
 include/linux/ptrace.h    |    1 +
 include/linux/sched.h     |    1 +
 include/linux/tracehook.h |   10 +++++-----
 kernel/ptrace.c           |    2 +-
 kernel/signal.c           |    4 ++--
 5 files changed, 10 insertions(+), 8 deletions(-)

diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h
index 092a04f..619cdf0 100644  
--- a/include/linux/ptrace.h
+++ b/include/linux/ptrace.h
@@ -106,6 +106,7 @@ extern int ptrace_traceme(void);
 extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len);
 extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len);
 extern int ptrace_attach(struct task_struct *tsk);
+extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee);
 extern int ptrace_detach(struct task_struct *, unsigned int);
 extern void ptrace_disable(struct task_struct *);
 extern int ptrace_check_attach(struct task_struct *task, int kill);
diff --git a/include/linux/sched.h b/include/linux/sched.h
index 2238745..09f26df 100644  
--- a/include/linux/sched.h
+++ b/include/linux/sched.h
@@ -2061,6 +2061,7 @@ extern int kill_pgrp(struct pid *pid, in
 extern int kill_pid(struct pid *pid, int sig, int priv);
 extern int kill_proc_info(int, struct siginfo *, pid_t);
 extern int do_notify_parent(struct task_struct *, int);
+extern void do_notify_parent_cldstop(struct task_struct *, int);
 extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent);
 extern void force_sig(int, struct task_struct *);
 extern int send_sig(int, struct task_struct *, int);
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h
index 3a2e66d..98917e9 100644  
--- a/include/linux/tracehook.h
+++ b/include/linux/tracehook.h
@@ -134,7 +134,7 @@ static inline __must_check int tracehook
  */
 static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step)
 {
-	if (step) {
+	if (step && (task_ptrace(current) & PT_PTRACED)) {
 		siginfo_t info;
 		user_single_step_siginfo(current, regs, &info);
 		force_sig_info(SIGTRAP, &info, current);
@@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec(
 {
 	int unsafe = 0;
 	int ptrace = task_ptrace(task);
-	if (ptrace & PT_PTRACED) {
+	if (ptrace) {
 		if (ptrace & PT_PTRACE_CAP)
 			unsafe |= LSM_UNSAFE_PTRACE_CAP;
 		else
@@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec(
  */
 static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk)
 {
-	if (task_ptrace(tsk) & PT_PTRACED)
+	if (task_ptrace(tsk))
 		return rcu_dereference(tsk->parent);
 	return NULL;
 }
@@ -386,7 +386,7 @@ static inline void tracehook_signal_hand
 					    const struct k_sigaction *ka,
 					    struct pt_regs *regs, int stepping)
 {
-	if (stepping)
+	if (stepping && (task_ptrace(current) & PT_PTRACED))
 		ptrace_notify(SIGTRAP);
 }
 
@@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s
  */
 static inline int tracehook_notify_jctl(int notify, int why)
 {
-	return notify ?: (current->ptrace & PT_PTRACED) ? why : 0;
+	return notify ?: task_ptrace(current) ? why : 0;
 }
 
 /**
diff --git a/kernel/ptrace.c b/kernel/ptrace.c
index 99bbaa3..84d9f8f 100644  
--- a/kernel/ptrace.c
+++ b/kernel/ptrace.c
@@ -270,7 +270,7 @@ static int ignoring_children(struct sigh
  * reap it now, in that case we must also wake up sub-threads sleeping in
  * do_wait().
  */
-static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
+bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p)
 {
 	__ptrace_unlink(p);
 
diff --git a/kernel/signal.c b/kernel/signal.c
index 4e3cff1..b74324d 100644  
--- a/kernel/signal.c
+++ b/kernel/signal.c
@@ -1522,7 +1522,7 @@ int do_notify_parent(struct task_struct 
 	return ret;
 }
 
-static void do_notify_parent_cldstop(struct task_struct *tsk, int why)
+void do_notify_parent_cldstop(struct task_struct *tsk, int why)
 {
 	struct siginfo info;
 	unsigned long flags;
@@ -1794,7 +1794,7 @@ static int do_signal_stop(int signr)
 static int ptrace_signal(int signr, siginfo_t *info,
 			 struct pt_regs *regs, void *cookie)
 {
-	if (!task_ptrace(current))
+	if (!(task_ptrace(current) & PT_PTRACED))
 		return signr;
 
 	ptrace_signal_deliver(regs, cookie);