[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