diff options
author | Tejun Heo <tj@kernel.org> | 2011-06-17 10:50:35 -0400 |
---|---|---|
committer | Oleg Nesterov <oleg@redhat.com> | 2011-06-22 13:26:28 -0400 |
commit | 643ad8388e189dfd14ef76972cf7dc394b3cbebd (patch) | |
tree | 82d4787ddc09cf5a6fc9fc1345839973ab7763f5 /include | |
parent | d21142ece414ce1088cfcae760689aa60d6fee80 (diff) |
ptrace: introduce ptrace_event_enabled() and simplify ptrace_event() and tracehook_prepare_clone()
This patch implements ptrace_event_enabled() which tests whether a
given PTRACE_EVENT_* is enabled and use it to simplify ptrace_event()
and tracehook_prepare_clone().
PT_EVENT_FLAG() macro is added which calculates PT_TRACE_* flag from
PTRACE_EVENT_*. This is used to define PT_TRACE_* flags and by
ptrace_event_enabled() to find the matching flag.
This is used to make ptrace_event() and tracehook_prepare_clone()
simpler.
* ptrace_event() callers were responsible for providing mask to test
whether the event was enabled. This patch implements
ptrace_event_enabled() and make ptrace_event() drop @mask and
determine whether the event is enabled from @event. Note that
@event is constant and this conversion doesn't add runtime overhead.
All conversions except tracehook_report_clone_complete() are
trivial. tracehook_report_clone_complete() used to use 0 for @mask
(always enabled) but now tests whether the specified event is
enabled. This doesn't cause any behavior difference as it's
guaranteed that the event specified by @trace is enabled.
* tracehook_prepare_clone() now only determines which event is
applicable and use ptrace_event_enabled() for enable test.
This doesn't introduce any behavior change.
Signed-off-by: Tejun Heo <tj@kernel.org>
Signed-off-by: Oleg Nesterov <oleg@redhat.com>
Diffstat (limited to 'include')
-rw-r--r-- | include/linux/ptrace.h | 46 | ||||
-rw-r--r-- | include/linux/tracehook.h | 26 |
2 files changed, 45 insertions, 27 deletions
diff --git a/include/linux/ptrace.h b/include/linux/ptrace.h index 3ff20b322598..18feac6f441e 100644 --- a/include/linux/ptrace.h +++ b/include/linux/ptrace.h | |||
@@ -90,12 +90,17 @@ | |||
90 | #define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ | 90 | #define PT_DTRACE 0x00000002 /* delayed trace (used on m68k, i386) */ |
91 | #define PT_TRACESYSGOOD 0x00000004 | 91 | #define PT_TRACESYSGOOD 0x00000004 |
92 | #define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ | 92 | #define PT_PTRACE_CAP 0x00000008 /* ptracer can follow suid-exec */ |
93 | #define PT_TRACE_FORK 0x00000010 | 93 | |
94 | #define PT_TRACE_VFORK 0x00000020 | 94 | /* PT_TRACE_* event enable flags */ |
95 | #define PT_TRACE_CLONE 0x00000040 | 95 | #define PT_EVENT_FLAG_SHIFT 4 |
96 | #define PT_TRACE_EXEC 0x00000080 | 96 | #define PT_EVENT_FLAG(event) (1 << (PT_EVENT_FLAG_SHIFT + (event) - 1)) |
97 | #define PT_TRACE_VFORK_DONE 0x00000100 | 97 | |
98 | #define PT_TRACE_EXIT 0x00000200 | 98 | #define PT_TRACE_FORK PT_EVENT_FLAG(PTRACE_EVENT_FORK) |
99 | #define PT_TRACE_VFORK PT_EVENT_FLAG(PTRACE_EVENT_VFORK) | ||
100 | #define PT_TRACE_CLONE PT_EVENT_FLAG(PTRACE_EVENT_CLONE) | ||
101 | #define PT_TRACE_EXEC PT_EVENT_FLAG(PTRACE_EVENT_EXEC) | ||
102 | #define PT_TRACE_VFORK_DONE PT_EVENT_FLAG(PTRACE_EVENT_VFORK_DONE) | ||
103 | #define PT_TRACE_EXIT PT_EVENT_FLAG(PTRACE_EVENT_EXIT) | ||
99 | 104 | ||
100 | #define PT_TRACE_MASK 0x000003f4 | 105 | #define PT_TRACE_MASK 0x000003f4 |
101 | 106 | ||
@@ -146,25 +151,38 @@ int generic_ptrace_pokedata(struct task_struct *tsk, unsigned long addr, | |||
146 | unsigned long data); | 151 | unsigned long data); |
147 | 152 | ||
148 | /** | 153 | /** |
154 | * ptrace_event_enabled - test whether a ptrace event is enabled | ||
155 | * @task: ptracee of interest | ||
156 | * @event: %PTRACE_EVENT_* to test | ||
157 | * | ||
158 | * Test whether @event is enabled for ptracee @task. | ||
159 | * | ||
160 | * Returns %true if @event is enabled, %false otherwise. | ||
161 | */ | ||
162 | static inline bool ptrace_event_enabled(struct task_struct *task, int event) | ||
163 | { | ||
164 | return task->ptrace & PT_EVENT_FLAG(event); | ||
165 | } | ||
166 | |||
167 | /** | ||
149 | * ptrace_event - possibly stop for a ptrace event notification | 168 | * ptrace_event - possibly stop for a ptrace event notification |
150 | * @mask: %PT_* bit to check in @current->ptrace | 169 | * @event: %PTRACE_EVENT_* value to report |
151 | * @event: %PTRACE_EVENT_* value to report if @mask is set | ||
152 | * @message: value for %PTRACE_GETEVENTMSG to return | 170 | * @message: value for %PTRACE_GETEVENTMSG to return |
153 | * | 171 | * |
154 | * This checks the @mask bit to see if ptrace wants stops for this event. | 172 | * Check whether @event is enabled and, if so, report @event and @message |
155 | * If so we stop, reporting @event and @message to the ptrace parent. | 173 | * to the ptrace parent. |
156 | * | 174 | * |
157 | * Returns nonzero if we did a ptrace notification, zero if not. | 175 | * Returns nonzero if we did a ptrace notification, zero if not. |
158 | * | 176 | * |
159 | * Called without locks. | 177 | * Called without locks. |
160 | */ | 178 | */ |
161 | static inline int ptrace_event(int mask, int event, unsigned long message) | 179 | static inline int ptrace_event(int event, unsigned long message) |
162 | { | 180 | { |
163 | if (mask && likely(!(current->ptrace & mask))) | 181 | if (likely(!ptrace_event_enabled(current, event))) |
164 | return 0; | 182 | return false; |
165 | current->ptrace_message = message; | 183 | current->ptrace_message = message; |
166 | ptrace_notify((event << 8) | SIGTRAP); | 184 | ptrace_notify((event << 8) | SIGTRAP); |
167 | return 1; | 185 | return true; |
168 | } | 186 | } |
169 | 187 | ||
170 | /** | 188 | /** |
diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index a3e838784f43..7d38571b0c05 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h | |||
@@ -201,7 +201,7 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, | |||
201 | struct linux_binprm *bprm, | 201 | struct linux_binprm *bprm, |
202 | struct pt_regs *regs) | 202 | struct pt_regs *regs) |
203 | { | 203 | { |
204 | if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && | 204 | if (!ptrace_event(PTRACE_EVENT_EXEC, 0) && |
205 | unlikely(current->ptrace & PT_PTRACED)) | 205 | unlikely(current->ptrace & PT_PTRACED)) |
206 | send_sig(SIGTRAP, current, 0); | 206 | send_sig(SIGTRAP, current, 0); |
207 | } | 207 | } |
@@ -218,7 +218,7 @@ static inline void tracehook_report_exec(struct linux_binfmt *fmt, | |||
218 | */ | 218 | */ |
219 | static inline void tracehook_report_exit(long *exit_code) | 219 | static inline void tracehook_report_exit(long *exit_code) |
220 | { | 220 | { |
221 | ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); | 221 | ptrace_event(PTRACE_EVENT_EXIT, *exit_code); |
222 | } | 222 | } |
223 | 223 | ||
224 | /** | 224 | /** |
@@ -232,19 +232,19 @@ static inline void tracehook_report_exit(long *exit_code) | |||
232 | */ | 232 | */ |
233 | static inline int tracehook_prepare_clone(unsigned clone_flags) | 233 | static inline int tracehook_prepare_clone(unsigned clone_flags) |
234 | { | 234 | { |
235 | int event = 0; | ||
236 | |||
235 | if (clone_flags & CLONE_UNTRACED) | 237 | if (clone_flags & CLONE_UNTRACED) |
236 | return 0; | 238 | return 0; |
237 | 239 | ||
238 | if (clone_flags & CLONE_VFORK) { | 240 | if (clone_flags & CLONE_VFORK) |
239 | if (current->ptrace & PT_TRACE_VFORK) | 241 | event = PTRACE_EVENT_VFORK; |
240 | return PTRACE_EVENT_VFORK; | 242 | else if ((clone_flags & CSIGNAL) != SIGCHLD) |
241 | } else if ((clone_flags & CSIGNAL) != SIGCHLD) { | 243 | event = PTRACE_EVENT_CLONE; |
242 | if (current->ptrace & PT_TRACE_CLONE) | 244 | else |
243 | return PTRACE_EVENT_CLONE; | 245 | event = PTRACE_EVENT_FORK; |
244 | } else if (current->ptrace & PT_TRACE_FORK) | ||
245 | return PTRACE_EVENT_FORK; | ||
246 | 246 | ||
247 | return 0; | 247 | return ptrace_event_enabled(current, event) ? event : 0; |
248 | } | 248 | } |
249 | 249 | ||
250 | /** | 250 | /** |
@@ -318,7 +318,7 @@ static inline void tracehook_report_clone_complete(int trace, | |||
318 | struct task_struct *child) | 318 | struct task_struct *child) |
319 | { | 319 | { |
320 | if (unlikely(trace)) | 320 | if (unlikely(trace)) |
321 | ptrace_event(0, trace, pid); | 321 | ptrace_event(trace, pid); |
322 | } | 322 | } |
323 | 323 | ||
324 | /** | 324 | /** |
@@ -336,7 +336,7 @@ static inline void tracehook_report_clone_complete(int trace, | |||
336 | static inline void tracehook_report_vfork_done(struct task_struct *child, | 336 | static inline void tracehook_report_vfork_done(struct task_struct *child, |
337 | pid_t pid) | 337 | pid_t pid) |
338 | { | 338 | { |
339 | ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid); | 339 | ptrace_event(PTRACE_EVENT_VFORK_DONE, pid); |
340 | } | 340 | } |
341 | 341 | ||
342 | /** | 342 | /** |