[PATCH 53] kill context->ev_array[]

Oleg Nesterov oleg at redhat.com
Thu Oct 1 22:45:25 UTC 2009


Kill context->ev_array[].

Add the new members to struct ptrace_context:

	->ev_mesg: for task_struct->ptrace_message

	->ev_code: for task_struct->exit_code

	->ev_name: this is unique identifier for ptrace_resume().

	   We don't actually need both ev_code and ev_name, but
	   ev_name makes things a bit clearer, at least for now.
	   In particular, we can detect jctl stops because every
	   other stop event has ev_name != 0.

	   So, if a callback wants to stop it does

	   	context->ev_name = PTRACE_EVENT_XXX;
	   	context->ev_code = (PTRACE_EVENT_XXX << 8) | SIGTRAP;

	   we need a helper, and we can move "(... << 8) | SIGTRAP"
	   into ptrace_notify_stop().

	   The patch also adds 3 new events which are not visible to
	   the user-mode:

	   	PTRACE_EVENT_SYSCALL
	   	PTRACE_EVENT_SIGTRAP
	   	PTRACE_EVENT_SIGNAL

	   The last 2 are not strictly needed, just for consistency.

Add the new helper, ev_pending(context) which just checks ->ev_name != 0,
ptrace_resume() sets context->ev_name == 0.

With this patch ptrace_resume(data) ignores "data" and doesn't implement
the stacked events, see the next patches.

---

 kernel/ptrace.c |  181 ++++++++++++++++----------------------------------------
 1 file changed, 54 insertions(+), 127 deletions(-)

--- PU/kernel/ptrace.c~53_KILL_EV_ARRAY	2009-10-01 19:35:49.000000000 +0200
+++ PU/kernel/ptrace.c	2009-10-01 21:53:01.000000000 +0200
@@ -24,57 +24,25 @@
 #include <linux/syscalls.h>
 #include <linux/uaccess.h>
 
-typedef void (*resume_func_t)(struct utrace_engine *,
-				struct task_struct*, long);
-
-struct ptrace_event {
-	int		ev_code;
-	unsigned long	ev_message;
-	resume_func_t	ev_resume;
-
-	int		ev_options;
-};
-
 struct ptrace_context {
 	int options;
 
 	siginfo_t *siginfo;
 
-	struct ptrace_event ev_array[2];
-	unsigned int ev_first, ev_last;
+	int		ev_name;
+	int		ev_code;
+	unsigned long	ev_mesg;
 
 	enum utrace_resume_action resume;
 };
 
-static inline bool ev_empty(struct ptrace_context *context)
-{
-	return context->ev_first == context->ev_last;
-}
-
-static inline struct ptrace_event *__ev_at(struct ptrace_context *context,
-						unsigned int idx)
-{
-	return context->ev_array + (idx % ARRAY_SIZE(context->ev_array));
-}
-
-static inline struct ptrace_event *ev_current(struct ptrace_context *context)
-{
-	WARN_ON(ev_empty(context));
-	return __ev_at(context, context->ev_first);
-}
-
-static inline struct ptrace_event *ev_pop(struct ptrace_context *context)
-{
-	WARN_ON(ev_empty(context));
-	return __ev_at(context, context->ev_first++);
-}
+#define PTRACE_EVENT_SYSCALL	100
+#define PTRACE_EVENT_SIGTRAP	101
+#define PTRACE_EVENT_SIGNAL	102
 
-static inline struct ptrace_event *ev_push(struct ptrace_context *context)
+static inline bool ev_pending(struct ptrace_context *context)
 {
-	struct ptrace_event *ev = __ev_at(context, context->ev_last++);
-	WARN_ON(context->ev_last - context->ev_first > ARRAY_SIZE(context->ev_array));
-	memset(ev, 0, sizeof(*ev));
-	return ev;
+	return context->ev_name != 0;
 }
 
 static inline struct ptrace_context *
@@ -144,11 +112,12 @@ static u32 ptrace_report_exit(enum utrac
 			      long orig_code, long *code)
 {
 	struct ptrace_context *context = ptrace_context(engine);
-	struct ptrace_event *ev;
 
-	ev = ev_push(context);
-	ev->ev_message = *code;
-	ev->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP;
+	WARN_ON(ev_pending(context));
+
+	context->ev_name = PTRACE_EVENT_EXIT;
+	context->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP;
+	context->ev_mesg = *code;
 
 	return UTRACE_STOP;
 }
@@ -193,7 +162,7 @@ static u32 ptrace_report_clone(enum utra
 	struct ptrace_context *context = ptrace_context(engine);
 	int event, ret = UTRACE_RESUME;
 
-	WARN_ON(!ev_empty(context));
+	WARN_ON(ev_pending(context));
 
 	// XXX: WRONG!!!
 	if (clone_flags & CLONE_UNTRACED)
@@ -219,21 +188,16 @@ static u32 ptrace_report_clone(enum utra
 
 	// XXX: child->pid is wrong! use tracer's pid_ns
 	if (event) {
-		struct ptrace_event *ev = ev_push(context);
-
-		ev->ev_message = child->pid;
-		ev->ev_code = (event << 8) | SIGTRAP;
+		context->ev_name = event;
+		context->ev_code = (event << 8) | SIGTRAP;
+		context->ev_mesg = child->pid;
 
 		ret = UTRACE_STOP;
-	}
-
-	if ((clone_flags & CLONE_VFORK) &&
-	    (context->options & PTRACE_O_TRACEVFORKDONE)) {
-		struct ptrace_event *ev = ev_push(context);
-
-		ev->ev_message = child->pid;
-		ev->ev_options = PTRACE_O_TRACEVFORKDONE;
-		ev->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP;
+	} else if ((clone_flags & CLONE_VFORK) &&
+			(context->options & PTRACE_O_TRACEVFORKDONE)) {
+		context->ev_name = PTRACE_EVENT_VFORK_DONE;
+		context->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP;
+		context->ev_mesg = child->pid;
 
 		ret = UTRACE_STOP;
 	}
@@ -253,26 +217,18 @@ 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;
-}
-
 static u32 ptrace_report_syscall_entry(u32 action,
 				       struct utrace_engine *engine,
 				       struct task_struct *task,
 				       struct pt_regs *regs)
 {
-	push_syscall_event(ptrace_context(engine));
+	struct ptrace_context *context = ptrace_context(engine);
+
+	WARN_ON(ev_pending(context));
+
+	context->ev_name = PTRACE_EVENT_SYSCALL;
+	context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
+				(SIGTRAP | 0x80) : SIGTRAP;
 	return UTRACE_SYSCALL_RUN | UTRACE_STOP;
 }
 
@@ -281,19 +237,15 @@ static u32 ptrace_report_syscall_exit(en
 				      struct task_struct *task,
 				      struct pt_regs *regs)
 {
-	push_syscall_event(ptrace_context(engine));
-	return UTRACE_STOP;
-}
-
-static void ptrace_resume_ck_syscall(struct utrace_engine *engine,
-				struct task_struct *tracee, long data)
-{
 	struct ptrace_context *context = ptrace_context(engine);
 
-	if (context->options & PTRACE_O_TRACE_SYSCALL) {
-		if (ev_empty(context))
-			push_syscall_event(context);
-	}
+	if (ev_pending(context))
+		return UTRACE_STOP;
+
+	context->ev_name = PTRACE_EVENT_SYSCALL;
+	context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ?
+				(SIGTRAP | 0x80) : SIGTRAP;
+	return UTRACE_STOP;
 }
 
 static u32 ptrace_report_exec(enum utrace_resume_action action,
@@ -304,7 +256,8 @@ static u32 ptrace_report_exec(enum utrac
 			      struct pt_regs *regs)
 {
 	struct ptrace_context *context = ptrace_context(engine);
-	struct ptrace_event *ev;
+
+	WARN_ON(ev_pending(context));
 
 	if (!(context->options & PTRACE_O_TRACEEXEC)) {
 		/*
@@ -314,9 +267,8 @@ static u32 ptrace_report_exec(enum utrac
 		return UTRACE_RESUME;
 	}
 
-	ev = ev_push(context);
-	ev->ev_resume = ptrace_resume_ck_syscall;
-	ev->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP;
+	context->ev_name = PTRACE_EVENT_EXEC;
+	context->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP;
 
 	return UTRACE_STOP;
 }
@@ -351,10 +303,9 @@ static u32 ptrace_report_signal(u32 acti
 {
 	struct ptrace_context *context = ptrace_context(engine);
 	enum utrace_resume_action resume = context->resume;
-	struct ptrace_event *ev;
 
-	if (!ev_empty(context)) {
-		WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task));
+	if (ev_pending(context)) {
+		WARN_ON(!context->ev_code && !fatal_signal_pending(task));
 		action = utrace_signal_action(action);
 		WARN_ON(action != UTRACE_SIGNAL_REPORT);
 		return action | UTRACE_STOP;
@@ -366,8 +317,8 @@ static u32 ptrace_report_signal(u32 acti
 			if (WARN_ON(context->siginfo))
 				context->siginfo = NULL;
 
-			ev = ev_push(context);
-			ev->ev_code = SIGTRAP;
+			context->ev_name = PTRACE_EVENT_SIGTRAP;
+			context->ev_code = SIGTRAP;
 
 			return UTRACE_STOP | UTRACE_SIGNAL_IGN;
 		}
@@ -403,9 +354,8 @@ static u32 ptrace_report_signal(u32 acti
 		// will clear context->siginfo
 		utrace_control(task, engine, UTRACE_INTERRUPT);
 
-		ev = ev_push(context);
-		ev->ev_resume = ptrace_resume_signal;
-		ev->ev_code = info->si_signo;
+		context->ev_name = PTRACE_EVENT_SIGNAL;
+		context->ev_code = info->si_signo;
 
 		return UTRACE_STOP | UTRACE_SIGNAL_IGN;
 	}
@@ -418,8 +368,8 @@ static u32 ptrace_report_quiesce(u32 act
 {
 	struct ptrace_context *context = ptrace_context(engine);
 
-	if (!ev_empty(context)) {
-		WARN_ON(!ev_current(context)->ev_code && !fatal_signal_pending(task) && !(task->flags & PF_EXITING));
+	if (ev_pending(context)) {
+		WARN_ON(!context->ev_code && !fatal_signal_pending(task) && !(task->flags & PF_EXITING));
 		return UTRACE_STOP;
 	}
 
@@ -886,14 +836,12 @@ static int ptrace_setsiginfo(struct utra
 static void do_ptrace_notify_stop(struct ptrace_context *context,
 					struct task_struct *tracee)
 {
-	struct ptrace_event *ev = ev_current(context);
-
-	tracee->ptrace_message = ev->ev_message;
-	tracee->exit_code = ev->ev_code;
+	tracee->ptrace_message = context->ev_mesg;
+	tracee->exit_code = context->ev_code;
 
 	// XXX: for debug only
-	WARN_ON(ev->ev_code == 0);
-	ev->ev_code = 0;
+	WARN_ON(!context->ev_code);
+	context->ev_code = 0;
 
 	// XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!!
 	read_lock(&tasklist_lock);
@@ -913,7 +861,7 @@ void ptrace_notify_stop(struct task_stru
 	}
 
 	context = ptrace_context(engine);
-	if (WARN_ON(ev_empty(context)))
+	if (WARN_ON(!ev_pending(context)))
 		return;
 	do_ptrace_notify_stop(context, tracee);
 }
@@ -943,28 +891,7 @@ static void do_ptrace_resume(struct utra
 {
 	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);
-
-		WARN_ON(ev->ev_code); // XXX: debug
-		if (ev->ev_resume)
-			ev->ev_resume(engine, tracee, data);
-
-		while (!ev_empty(context)) {
-			int ev_o = ev_current(context)->ev_options;
-			if (!ev_o || (ev_o & context->options)) {
-				do_ptrace_notify_stop(context, tracee);
-				return;
-			}
-			ev_pop(context);
-		}
-	}
-
+	context->ev_name = 0;
 	context->resume = action;
 	ptrace_wake_up(engine, tracee, action);
 }




More information about the utrace-devel mailing list