Introduce ptrace_set_options(). It will replace ptrace_setoptions() but we can't kill the old helper yet. The new one sets ptrace_context->options, but we should convert the code which checks ->ptrace for PT_XXX first.
Currently PTRACE_SETOPTIONS calls both helpers. --- kernel/ptrace.c | 38 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 38 insertions(+) --- PU/kernel/ptrace.c~18_SET_OPTIONS 2009-09-02 19:53:06.000000000 +0200 +++ PU/kernel/ptrace.c 2009-09-02 20:17:34.000000000 +0200 @@ -871,6 +871,7 @@ int ptrace_writedata(struct task_struct return copied; } +/* will die soon ... */ static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -901,6 +902,42 @@ static int ptrace_setoptions(struct task return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } +static int ptrace_set_options(struct task_struct *child, long data) +{ + struct utrace_engine *engine; + int options = 0; + + if (data & PTRACE_O_TRACESYSGOOD) + options |= PT_TRACESYSGOOD; + + if (data & PTRACE_O_TRACEFORK) + options |= PT_TRACE_FORK; + + if (data & PTRACE_O_TRACEVFORK) + options |= PT_TRACE_VFORK; + + if (data & PTRACE_O_TRACECLONE) + options |= PT_TRACE_CLONE; + + if (data & PTRACE_O_TRACEEXEC) + options |= PT_TRACE_EXEC; + + if (data & PTRACE_O_TRACEVFORKDONE) + options |= PT_TRACE_VFORK_DONE; + + if (data & PTRACE_O_TRACEEXIT) + options |= PT_TRACE_EXIT; + + engine = utrace_attach_task(child, UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, NULL); + if (likely(!IS_ERR(engine))) { + __ptrace_set_options(child, engine, options); + utrace_engine_put(engine); + } + + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) { unsigned long flags; @@ -1139,6 +1176,7 @@ int ptrace_request(struct task_struct *c #endif case PTRACE_SETOPTIONS: ret = ptrace_setoptions(child, data); + ret = ptrace_set_options(child, data); break; case PTRACE_GETEVENTMSG: ret = put_user(child->ptrace_message, (unsigned long __user *) data);