Relocate some code in ptrace.c to avoid forward declarations. Just move some functions up/down, no code changes.
--- kernel/ptrace.c | 332 +++++++++++++++++++++++++++----------------------------- 1 file changed, 163 insertions(+), 169 deletions(-) --- PU/kernel/ptrace.c~119_RELOCATE 2009-10-26 02:11:29.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-26 02:48:49.000000000 +0100 @@ -25,6 +25,36 @@ #include <linux/uaccess.h> #include "ptrace-common.h" +/* + * ptrace a task: make the debugger its new parent and + * move it to the ptrace list. + * + * Must be called with the tasklist lock write-held. + */ +void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) +{ + BUG_ON(!list_empty(&child->ptrace_entry)); + list_add(&child->ptrace_entry, &new_parent->ptraced); + child->parent = new_parent; +} + +/* + * unptrace a task: move it back to its original parent and + * remove it from the ptrace list. + * + * Must be called with the tasklist lock write-held. + */ +void __ptrace_unlink(struct task_struct *child) +{ + BUG_ON(!child->ptrace); + + child->ptrace = 0; + child->parent = child->real_parent; + list_del_init(&child->ptrace_entry); + + arch_ptrace_untrace(child); +} + struct ptrace_context { int options; @@ -69,31 +99,146 @@ ptrace_context(struct utrace_engine *eng return engine->data; } +static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ + +static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) +{ + return utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); +} + +static struct utrace_engine * +ptrace_reuse_engine(struct task_struct *tracee) +{ + struct utrace_engine *engine; + struct ptrace_context *context; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + context = ptrace_context(engine); + if (unlikely(context->resume == UTRACE_DETACH)) { + /* + * Try to reuse this self-detaching engine. + * The only caller which can hit this case is ptrace_attach(), + * it holds ->cred_guard_mutex. + */ + context->options = 0; + context->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + context->resume = UTRACE_RESUME; + /* synchronize with ptrace_report_signal() */ + err = utrace_barrier(tracee, engine); + } + WARN_ON(!err != (engine->ops == &ptrace_utrace_ops)); + + if (!err) + return engine; + } + + utrace_engine_put(engine); + return ERR_PTR(err); +} + +static struct utrace_engine * +ptrace_attach_engine(struct task_struct *tracee) +{ + struct utrace_engine *engine; + struct ptrace_context *context; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + context = kzalloc(sizeof(*context), GFP_KERNEL); + if (unlikely(!context)) + return ERR_PTR(-ENOMEM); + + context->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, context); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(context); + } + + return engine; +} + +static inline int __ptrace_set_options(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *context = ptrace_context(engine); + /* + * We need QUIESCE for resume handling, CLONE to check + * for CLONE_PTRACE, other events are always reported. + */ + unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; + + context->options = options; + if (options & PTRACE_O_TRACEEXIT) + events |= UTRACE_EVENT(EXIT); + + return utrace_set_events(target, engine, events); +} + /* - * ptrace a task: make the debugger its new parent and - * move it to the ptrace list. - * - * Must be called with the tasklist lock write-held. + * Attach a utrace engine for ptrace and set up its event mask. + * Returns error code or 0 on success. */ -void __ptrace_link(struct task_struct *child, struct task_struct *new_parent) +static int ptrace_attach_task(struct task_struct *tracee, int options) { - BUG_ON(!list_empty(&child->ptrace_entry)); - list_add(&child->ptrace_entry, &new_parent->ptraced); - child->parent = new_parent; + struct utrace_engine *engine; + int err; + + engine = ptrace_attach_engine(tracee); + if (IS_ERR(engine)) + return PTR_ERR(engine); + /* + * It can fail only if the tracee is dead, the caller + * must notice this before setting PT_UTRACED. + */ + err = __ptrace_set_options(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; } -static const struct utrace_engine_ops ptrace_utrace_ops; /* forward decl */ -static int ptrace_attach_task(struct task_struct *tracee, int options); -static void ptrace_abort_attach(struct task_struct *tracee); static void ptrace_wake_up(struct task_struct *tracee, struct utrace_engine *engine, enum utrace_resume_action action, - bool force_wakeup); - -static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) + bool force_wakeup) { - return utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, NULL); + if (force_wakeup) { + unsigned long flags; + /* + * Preserve the compatibility bug. Historically ptrace + * wakes up the tracee even if it should not. Clear + * SIGNAL_STOP_STOPPED for utrace_wakeup(). + */ + if (lock_task_sighand(tracee, &flags)) { + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + unlock_task_sighand(tracee, &flags); + } + } + + if (action != UTRACE_REPORT) + ptrace_context(engine)->stop_code = 0; + utrace_control(tracee, engine, action); } static void ptrace_detach_task(struct task_struct *tracee, int sig) @@ -128,21 +273,9 @@ static void ptrace_detach_task(struct ta utrace_engine_put(engine); } -/* - * unptrace a task: move it back to its original parent and - * remove it from the ptrace list. - * - * Must be called with the tasklist lock write-held. - */ -void __ptrace_unlink(struct task_struct *child) +static void ptrace_abort_attach(struct task_struct *tracee) { - BUG_ON(!child->ptrace); - - child->ptrace = 0; - child->parent = child->real_parent; - list_del_init(&child->ptrace_entry); - - arch_ptrace_untrace(child); + ptrace_detach_task(tracee, 0); } static u32 ptrace_report_exit(enum utrace_resume_action action, @@ -418,122 +551,6 @@ static const struct utrace_engine_ops pt .release = ptrace_release, }; -static struct utrace_engine * -ptrace_reuse_engine(struct task_struct *tracee) -{ - struct utrace_engine *engine; - struct ptrace_context *context; - int err = -EPERM; - - engine = ptrace_lookup_engine(tracee); - if (IS_ERR(engine)) - return engine; - - context = ptrace_context(engine); - if (unlikely(context->resume == UTRACE_DETACH)) { - /* - * Try to reuse this self-detaching engine. - * The only caller which can hit this case is ptrace_attach(), - * it holds ->cred_guard_mutex. - */ - context->options = 0; - context->eventmsg = 0; - - /* make sure we don't get unwanted reports */ - err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); - if (!err || err == -EINPROGRESS) { - context->resume = UTRACE_RESUME; - /* synchronize with ptrace_report_signal() */ - err = utrace_barrier(tracee, engine); - } - WARN_ON(!err != (engine->ops == &ptrace_utrace_ops)); - - if (!err) - return engine; - } - - utrace_engine_put(engine); - return ERR_PTR(err); -} - -static struct utrace_engine * -ptrace_attach_engine(struct task_struct *tracee) -{ - struct utrace_engine *engine; - struct ptrace_context *context; - - if (unlikely(task_utrace_flags(tracee))) { - engine = ptrace_reuse_engine(tracee); - if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) - return engine; - } - - context = kzalloc(sizeof(*context), GFP_KERNEL); - if (unlikely(!context)) - return ERR_PTR(-ENOMEM); - - context->resume = UTRACE_RESUME; - - engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE | - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, context); - if (unlikely(IS_ERR(engine))) { - if (engine != ERR_PTR(-ESRCH) && - engine != ERR_PTR(-ERESTARTNOINTR)) - engine = ERR_PTR(-EPERM); - kfree(context); - } - - return engine; -} - -static inline int __ptrace_set_options(struct task_struct *target, - struct utrace_engine *engine, - unsigned long options) -{ - struct ptrace_context *context = ptrace_context(engine); - /* - * We need QUIESCE for resume handling, CLONE to check - * for CLONE_PTRACE, other events are always reported. - */ - unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | - UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - - context->options = options; - if (options & PTRACE_O_TRACEEXIT) - events |= UTRACE_EVENT(EXIT); - - return utrace_set_events(target, engine, events); -} - -/* - * Attach a utrace engine for ptrace and set up its event mask. - * Returns error code or 0 on success. - */ -static int ptrace_attach_task(struct task_struct *tracee, int options) -{ - struct utrace_engine *engine; - int err; - - engine = ptrace_attach_engine(tracee); - if (IS_ERR(engine)) - return PTR_ERR(engine); - /* - * It can fail only if the tracee is dead, the caller - * must notice this before setting PT_UTRACED. - */ - err = __ptrace_set_options(tracee, engine, options); - WARN_ON(err && !tracee->exit_state); - utrace_engine_put(engine); - return 0; -} - -static void ptrace_abort_attach(struct task_struct *tracee) -{ - ptrace_detach_task(tracee, 0); -} - int ptrace_check_attach(struct task_struct *child, int kill) { struct utrace_engine *engine; @@ -796,29 +813,6 @@ void ptrace_notify_stop(struct task_stru utrace_engine_put(engine); } -static void ptrace_wake_up(struct task_struct *tracee, - struct utrace_engine *engine, - enum utrace_resume_action action, - bool force_wakeup) -{ - if (force_wakeup) { - unsigned long flags; - /* - * Preserve the compatibility bug. Historically ptrace - * wakes up the tracee even if it should not. Clear - * SIGNAL_STOP_STOPPED for utrace_wakeup(). - */ - if (lock_task_sighand(tracee, &flags)) { - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - unlock_task_sighand(tracee, &flags); - } - } - - if (action != UTRACE_REPORT) - ptrace_context(engine)->stop_code = 0; - utrace_control(tracee, engine, action); -} - static int ptrace_resume_action(struct task_struct *tracee, struct utrace_engine *engine, long request) {