[PATCH 38] make sure PTRACE_CONT "disables" SYSCALL_EXIT report
Oleg Nesterov
oleg at redhat.com
Tue Sep 15 18:49:01 UTC 2009
I am a bit surprised there is nothing in ptrace-tests to check
CONT/SYSCALL behaviour. I had to write this one:
#define WEVENT(s) ((s & 0xFF0000) >> 16)
int main(void)
{
int pid, stat;
pid = fork();
if (!pid) {
assert(0 == ptrace(PTRACE_TRACEME, 0,0,0));
kill(getpid(), SIGSTOP);
execl("/bin/false", "true", NULL);
assert(0);
}
assert(wait(&stat) == pid);
assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP);
assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACEEXEC));
for (;;) {
assert(0 == ptrace(PTRACE_SYSCALL, pid, 0, 0));
assert(waitpid(pid, &stat, __WALL) == pid);
if (WEVENT(stat) == PTRACE_EVENT_EXEC)
break;
}
kill(pid, SIGINT);
assert(0 == ptrace(PTRACE_CONT, pid, 0, 0));
assert(waitpid(pid, &stat, __WALL) == pid);
// we must see SIGINT, not SYSCALL_EXIT
assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGINT);
return 0;
}
If the tracee reports PTRACE_EVENT_EXEC, then it must not report
SYSCALL_EXIT if the traces resumes it via PTRACE_CONT.
The previous patch introduced ptrace_event->ev_options to filter out
unwanted events. But since there is no option for syscall tracing,
we add the "fake" PTRACE_O_TRACE_SYSCALL. It is not visible to user
space, and this bit is not used outside of ptrace_resume() path.
---
kernel/ptrace.c | 14 ++++++++++++--
1 file changed, 12 insertions(+), 2 deletions(-)
--- PU/kernel/ptrace.c~38_FIX_EXEC_CONT 2009-09-15 18:06:53.000000000 +0200
+++ PU/kernel/ptrace.c 2009-09-15 18:36:40.000000000 +0200
@@ -303,10 +303,15 @@ static void ptrace_resume_syscall(struct
}
}
+#define PTRACE_O_TRACE_SYSCALL 0x100
+
static void push_syscall_event(struct ptrace_context *context)
{
struct ptrace_event *ev = ev_push(context);
+ BUILD_BUG_ON(PTRACE_O_TRACE_SYSCALL & PTRACE_O_MASK);
+
+ ev->ev_options = PTRACE_O_TRACE_SYSCALL;
ev->ev_resume = ptrace_resume_syscall;
ev->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
(SIGTRAP | 0x80) : SIGTRAP;
@@ -998,10 +1003,15 @@ static void ptrace_wake_up(struct utrace
static void do_ptrace_resume(struct utrace_engine *engine,
struct task_struct *tracee,
- long data)
+ long request, long data)
{
struct ptrace_context *context = ptrace_context(engine);
+ if (request == PTRACE_SYSCALL)
+ context->options |= PTRACE_O_TRACE_SYSCALL;
+ else
+ context->options &= ~PTRACE_O_TRACE_SYSCALL;
+
if (!ev_empty(context)) {
struct ptrace_event *ev = ev_pop(context);
@@ -1072,7 +1082,7 @@ static int ptrace_resume(struct task_str
int event;
if (!ev_empty(context)) {
- do_ptrace_resume(engine, child, data);
+ do_ptrace_resume(engine, child, request, data);
utrace_engine_put(engine);
return 0;
}
More information about the utrace-devel
mailing list