[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