From envoi at campaigns.media-sender.net Thu Oct 1 09:15:27 2009 From: envoi at campaigns.media-sender.net (Canal Direct) Date: Thu, 1 Oct 2009 11:15:27 +0200 (CEST) Subject: =?iso-8859-15?q?Livraison_sp=E9ciale_pour_votre_soci=E9t=E9=2E?= Message-ID: <1011303148415.1103468790.1254388527666@enginex4.emv2.com> An HTML attachment was scrubbed... URL: From envoi at campaigns.media-sender.net Thu Oct 1 15:29:01 2009 From: envoi at campaigns.media-sender.net (IC Telecom) Date: Thu, 1 Oct 2009 17:29:01 +0200 (CEST) Subject: =?iso-8859-15?q?Illimit=E9_=3A_Communications_-_Internet_-_t=E9l?= =?iso-8859-15?q?=E9phones?= Message-ID: <1011303148415.1103489395.1254410941193@enginex3.emv2.com> An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Thu Oct 1 20:17:25 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Thu, 1 Oct 2009 22:17:25 +0200 Subject: Stopped detach/attach status Message-ID: <20091001201725.GA2947@host0.dyn.jankratochvil.net> Hi Oleg, the ptrace-testsuite http://sourceware.org/systemtap/wiki/utrace/tests currently FAILs (also) on Fedora 12 kernel-2.6.31.1-48.fc12.x86_64 for: FAIL: detach-stopped FAIL: stopped-attach-transparency Do you agree with the testcases and is it planned to fix them for F12? Thanks, Jan From oleg at redhat.com Thu Oct 1 22:45:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 00:45:22 +0200 Subject: [PATCH 53-56] kill ->ev_array + fix stepping Message-ID: <20091001224522.GA15997@redhat.com> On top of 4492770dc8d2312da9518e8b85fb0e49dc3da510 in your utrace-ptrace branch. Oleg. From oleg at redhat.com Thu Oct 1 22:45:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 00:45:25 +0200 Subject: [PATCH 53] kill context->ev_array[] Message-ID: <20091001224525.GA16005@redhat.com> 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 #include -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); } From oleg at redhat.com Thu Oct 1 22:45:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 00:45:27 +0200 Subject: [PATCH 54] ptrace_resume: don't ignore "data" argument Message-ID: <20091001224527.GA16008@redhat.com> ptrace_resume(data) should process "data" in case of PTRACE_EVENT_SYSCALL and PTRACE_EVENT_SIGNAL events. --- kernel/ptrace.c | 30 +++++++++++++++--------------- 1 file changed, 15 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~54_RESUME_USE_DATA 2009-10-01 21:53:01.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-01 23:06:36.000000000 +0200 @@ -205,18 +205,6 @@ static u32 ptrace_report_clone(enum utra return ret; } -static void ptrace_resume_syscall(struct utrace_engine *engine, - struct task_struct *tracee, long data) -{ - if (data) { - // XXX: until do_send_sig_info() - read_lock(&tasklist_lock); - if (tracee->signal) - send_sig(data, tracee, 1); - read_unlock(&tasklist_lock); - } -} - static u32 ptrace_report_syscall_entry(u32 action, struct utrace_engine *engine, struct task_struct *task, @@ -276,10 +264,9 @@ static u32 ptrace_report_exec(enum utrac /* * XXX: This all is wrong/racy/crashable */ -static void ptrace_resume_signal(struct utrace_engine *engine, - struct task_struct *tracee, long data) +static void ptrace_resume_signal(struct ptrace_context* context, int data) { - siginfo_t *info = ptrace_context(engine)->siginfo; + siginfo_t *info = context->siginfo; if (WARN_ON(!info)) return; @@ -891,6 +878,19 @@ static void do_ptrace_resume(struct utra { struct ptrace_context *context = ptrace_context(engine); + switch (context->ev_name) { + case 0: + // XXX: JCTL stop + break; + case PTRACE_EVENT_SYSCALL: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + case PTRACE_EVENT_SIGNAL: + ptrace_resume_signal(context, data); + break; + } + context->ev_name = 0; context->resume = action; ptrace_wake_up(engine, tracee, action); From oleg at redhat.com Thu Oct 1 22:45:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 00:45:30 +0200 Subject: [PATCH 55] implement the stacked SYSCALL_EXIT event Message-ID: <20091001224530.GA16015@redhat.com> Change ptrace_resume() to report the artificial SYSCALL_EXIT stop when needed. This is trivial, but I am not sure yet what should we do with the stacked JCTL stops. ptrace_report_clone() is not exactly right too, will be fixed later. This and the next patches add another switch(->ev_name), I'll try to merge them into the single switch() later. --- kernel/ptrace.c | 14 ++++++++++++++ 1 file changed, 14 insertions(+) --- PU/kernel/ptrace.c~55_STACKED_EVENTS 2009-10-01 23:06:36.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-01 23:32:55.000000000 +0200 @@ -891,6 +891,20 @@ static void do_ptrace_resume(struct utra break; } + if (request == PTRACE_SYSCALL) { + switch (context->ev_name) { + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + context->ev_name = PTRACE_EVENT_SYSCALL; + context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? + (SIGTRAP | 0x80) : SIGTRAP; + do_ptrace_notify_stop(context, tracee); + return; + } + } + context->ev_name = 0; context->resume = action; ptrace_wake_up(engine, tracee, action); From oleg at redhat.com Thu Oct 1 22:45:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 00:45:32 +0200 Subject: [PATCH 56] fix the stepping over syscall Message-ID: <20091001224532.GA16018@redhat.com> utrace-ptrace can't rely on syscall_trace_leave()->send_sigtrap(), we should generate this trap by hand. To do this we have to split PTRACE_EVENT_SYSCALL into PTRACE_EVENT_SYSCALL_ENTRY and PTRACE_EVENT_SYSCALL_EXIT to identify the latter case which needs a trap. Note! I think we can avoid using send_sigtrap(). Instead we can rely on ptrace_report_sinal() which can report SIGTRAP. But this should be discussed beacuse of some ptrace oddities here. Now we pass all tests except these two attach-wait-on-stopped attach-into-signal which should fail. Plus the kernel passes this test-case: #include #include #include #include #include #include #include #include #include #include #include #define WEVENT(s) ((s & 0xFF0000) >> 16) static int verbose; #define d_printf(fmt, ...) do { if (verbose) printf(fmt, ##__VA_ARGS__); } while (0) static struct user_regs_struct regs; static void resume(int pid, int req, int ck_stat) { int stat; assert(0 == ptrace(req, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); //d_printf("===> %06X\n %06X\n", ck_stat, stat); assert(stat == ck_stat); assert(0 == ptrace(PTRACE_GETREGS, pid, NULL, ®s)); } int main(int argc, const char *argv[]) { int pid, child, stat; long rip, nxt_rip; if (getpid() == __NR_getppid) { printf("sorry, restart\n"); return 0; } verbose = argc > 1; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); // 1: SYSCALL + SYSCALL + STEP getppid(); // 2: SYSCALL + STEP getppid(); // 3: STEP getppid(); // 4: SYSCALL + STEP if (!fork()) exit(73); // STEPs only if (!fork()) exit(73); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK)); //----------------------------------------------------------------------------- d_printf("1: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); rip = regs.rip; d_printf("1: syscall leave\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("2: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("2: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("3: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //---------------------------------------------------------------------------------- d_printf("4: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == -ENOSYS); rip = regs.rip; child = waitpid (-1, &stat, WNOHANG); assert(child == 0); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("4: provoke SIGCHLD\n"); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGCHLD << 8)); assert(regs.rip == rip); d_printf("4: SIGTERM + STEP\n"); kill(pid, SIGTERM); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGTERM << 8)); assert(regs.rip == rip); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != rip); nxt_rip = regs.rip; //--------------------------------------------------------------------------- d_printf("5: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_clone); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip == nxt_rip); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("5: step\n"); resume(pid, PTRACE_CONT, 0x7F | (SIGCHLD << 8)); assert(regs.rip == nxt_rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != nxt_rip); //---------------------------------------------------------------------------- kill(pid, SIGKILL); return 0; } --- kernel/ptrace.c | 32 +++++++++++++++++++++++++------- 1 file changed, 25 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~56_SYSCALL_TRAP 2009-10-01 23:32:55.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-02 00:16:57.000000000 +0200 @@ -36,9 +36,10 @@ struct ptrace_context { enum utrace_resume_action resume; }; -#define PTRACE_EVENT_SYSCALL 100 -#define PTRACE_EVENT_SIGTRAP 101 -#define PTRACE_EVENT_SIGNAL 102 +#define PTRACE_EVENT_SYSCALL_ENTRY 100 +#define PTRACE_EVENT_SYSCALL_EXIT 101 +#define PTRACE_EVENT_SIGTRAP 102 +#define PTRACE_EVENT_SIGNAL 103 static inline bool ev_pending(struct ptrace_context *context) { @@ -214,7 +215,7 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ev_pending(context)); - context->ev_name = PTRACE_EVENT_SYSCALL; + context->ev_name = PTRACE_EVENT_SYSCALL_ENTRY; context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; return UTRACE_SYSCALL_RUN | UTRACE_STOP; @@ -230,7 +231,7 @@ static u32 ptrace_report_syscall_exit(en if (ev_pending(context)) return UTRACE_STOP; - context->ev_name = PTRACE_EVENT_SYSCALL; + context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; return UTRACE_STOP; @@ -882,7 +883,8 @@ static void do_ptrace_resume(struct utra case 0: // XXX: JCTL stop break; - case PTRACE_EVENT_SYSCALL: + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); break; @@ -897,7 +899,7 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: - context->ev_name = PTRACE_EVENT_SYSCALL; + context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? (SIGTRAP | 0x80) : SIGTRAP; do_ptrace_notify_stop(context, tracee); @@ -905,6 +907,22 @@ static void do_ptrace_resume(struct utra } } + if (action != UTRACE_RESUME) { + switch (context->ev_name) { + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_SYSCALL_EXIT: + read_lock(&tasklist_lock); + if (tracee->sighand) + send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); + read_unlock(&tasklist_lock); + + action = UTRACE_RESUME; + break; + } + } + context->ev_name = 0; context->resume = action; ptrace_wake_up(engine, tracee, action); From dolinsky at magma.net Thu Oct 1 23:45:41 2009 From: dolinsky at magma.net (Tommy Odom) Date: Fri, 2 Oct 2009 00:45:41 +0100 Subject: Let women excite you more Message-ID: <20091002004541.1070209@magma.net> Choose our huge company with absolute superb service. http://lq.kifdeisvavu.com/ From oleg at redhat.com Thu Oct 1 23:10:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 2 Oct 2009 01:10:53 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091001201725.GA2947@host0.dyn.jankratochvil.net> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> Message-ID: <20091001231053.GA16798@redhat.com> Hi Jan, On 10/01, Jan Kratochvil wrote: > > the ptrace-testsuite > http://sourceware.org/systemtap/wiki/utrace/tests > > currently FAILs (also) on Fedora 12 kernel-2.6.31.1-48.fc12.x86_64 for: > FAIL: detach-stopped Please recall our previous discussion about 95a3540da9c81a5987be810e1d9a83640a366bd5 which was then reverted ;) I do not know what I can do. In short, I think this wakeup is absolutely wrong (not only because of this test-case), but if we kill it we break another test-case: attach-wait-on-stopped I believe this test-case is wrong. I can send you mbox with the previous discussion. > FAIL: stopped-attach-transparency I'll try to take a look on Monday, thanks. Oleg. From hot-deals at clubvacationdeals.com Fri Oct 2 03:33:25 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Thu, 1 Oct 2009 23:33:25 -0400 Subject: Dare to be Tempted Message-ID: <0e324a1f17d766ded3bd109214b13922@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From marketing at prehospitalar.com.br Fri Oct 2 13:21:50 2009 From: marketing at prehospitalar.com.br (Grupo Anjos APH) Date: Fri, 2 Oct 2009 13:21:50 GMT Subject: APH TATICO com Medicos da SWAT de Dallas Message-ID: <200910021322.n92DMnFn007602@mx2.redhat.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Sat Oct 3 01:57:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:57:43 +0200 Subject: [PATCH 57-64] context->siginfo changes Message-ID: <20091003015741.GA14850@redhat.com> misc + context->siginfo changes Oleg. From oleg at redhat.com Sat Oct 3 01:57:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:57:47 +0200 Subject: [PATCH 57] do_ptrace_notify_stop: backport the "sync wakeup" logic Message-ID: <20091003015746.GA15039@redhat.com> Same as 53da1d9456fe7f87a920a78fdbdcf1225d197cb7 commit. The tracee can be preempted by tracer right after read_unlock(tasklist), in this case the tracer can spin wait_task_inactive(). I still can't understand why this patch makes the very noticeable difference. The test-case does something like for (1 .. 70) { ptrace(PTRACE_SINGLESTEP); waitpid(); ptrace(PTRACE_GETREGS); } without this ptach it takes near 0.3 seconds sometimes. --- kernel/ptrace.c | 6 ++++++ 1 file changed, 6 insertions(+) --- PU/kernel/ptrace.c~57_NOTIFY_SYNC_WAKEUP 2009-10-02 00:16:57.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-02 23:19:41.000000000 +0200 @@ -833,8 +833,14 @@ static void do_ptrace_notify_stop(struct // XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!! read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); do_notify_parent_cldstop(tracee, CLD_TRAPPED); read_unlock(&tasklist_lock); + preempt_enable_no_resched(); } void ptrace_notify_stop(struct task_struct *tracee) From oleg at redhat.com Sat Oct 3 01:57:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:57:49 +0200 Subject: [PATCH 58] do_ptrace_notify_stop: fix the race with SIGKILL Message-ID: <20091003015749.GA15042@redhat.com> do_ptrace_notify_stop()->do_notify_parent_cldstop() is not safe when called by tracer. By the time we take tasklist the tracee can be SIGKILL'ed and released by our sub-thread. In this case it is wrong to notify its ->real_parent. If ->real_parent has exited, then do_notify_parent_cldstop() can use the freed/unmapped/resused/ task_struct. Check task_ptrace(tracee) under tasklist_lock. --- kernel/ptrace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~58_NOTIFY_FIX_RACE 2009-10-02 23:19:41.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-02 23:34:57.000000000 +0200 @@ -831,14 +831,15 @@ static void do_ptrace_notify_stop(struct WARN_ON(!context->ev_code); context->ev_code = 0; - // XXX: !!!!!!!! UNSAFE when called by tracer !!!!!!!!!!!!! read_lock(&tasklist_lock); /* * Don't want to allow preemption here, because * sys_ptrace() needs this task to be inactive. */ preempt_disable(); - do_notify_parent_cldstop(tracee, CLD_TRAPPED); + /* It can be killed and then released by our subthread */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); read_unlock(&tasklist_lock); preempt_enable_no_resched(); } From oleg at redhat.com Sat Oct 3 01:57:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:57:53 +0200 Subject: [PATCH 59] don't use task_struct->ptrace_message Message-ID: <20091003015753.GA15049@redhat.com> task_struct->ptrace_message is no longer needed. I wonder why compat_ptrace_request() does "(compat_ulong_t)ptrace_message", put_user(x, ptr) uses __typeof__(*ptr). --- kernel/ptrace.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~59_NO_PTRACE_MESSAGE 2009-10-02 23:34:57.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-02 23:44:02.000000000 +0200 @@ -824,7 +824,6 @@ static int ptrace_setsiginfo(struct utra static void do_ptrace_notify_stop(struct ptrace_context *context, struct task_struct *tracee) { - tracee->ptrace_message = context->ev_mesg; tracee->exit_code = context->ev_code; // XXX: for debug only @@ -1006,7 +1005,8 @@ int ptrace_request(struct task_struct *c ret = ptrace_set_options(engine, child, data); break; case PTRACE_GETEVENTMSG: - ret = put_user(child->ptrace_message, (unsigned long __user *) data); + ret = put_user(ptrace_context(engine)->ev_mesg, + (unsigned long __user *) data); break; case PTRACE_GETSIGINFO: @@ -1174,7 +1174,8 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETEVENTMSG: - ret = put_user((compat_ulong_t) child->ptrace_message, datap); + ret = put_user((compat_ulong_t)ptrace_context(engine)->ev_mesg, + datap); break; case PTRACE_GETSIGINFO: From oleg at redhat.com Sat Oct 3 01:57:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:57:57 +0200 Subject: [PATCH 61] move "resume signal" logic into the tracee's context Message-ID: <20091003015757.GA15059@redhat.com> Add ptrace_context->signr. The tracer just sets context->signr = data and resumes the tracee, the tracee updates context->siginfo if needed. When the tracee reports the signal it sets context->signr = info->si_signo. This matches the current behaviour, but perhaps it would be bettter to set ->signr = 0. This only matters if the tracee is killed. --- kernel/ptrace.c | 66 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 34 insertions(+), 32 deletions(-) --- PU/kernel/ptrace.c~61_RESUME_SIGNAL_BY_TRACEE 2009-10-03 00:00:27.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 01:37:41.000000000 +0200 @@ -27,7 +27,8 @@ struct ptrace_context { int options; - siginfo_t *siginfo; + int signr; + siginfo_t *siginfo; int ev_name; int ev_code; @@ -262,23 +263,37 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } -/* - * XXX: This all is wrong/racy/crashable - */ -static void ptrace_resume_signal(struct ptrace_context* context, int data) +static enum utrace_signal_action resume_signal(struct task_struct *task, + int signr, siginfo_t *info, + struct k_sigaction *return_ka) { - siginfo_t *info = context->siginfo; - - if (WARN_ON(!info)) - return; - - if (info->si_signo != data) { - info->si_signo = data; - info->si_code = SI_USER; + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; info->si_errno = 0; - info->si_pid = task_pid_vnr(current); - info->si_uid = current_uid(); + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(&task->blocked, signr)) { + send_sig_info(signr, info, task); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[signr - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; } static u32 ptrace_report_signal(u32 action, @@ -319,22 +334,8 @@ static u32 ptrace_report_signal(u32 acti return resume | UTRACE_SIGNAL_IGN; context->siginfo = NULL; - if (!info->si_signo) // debugger cancelled sig - return resume | UTRACE_SIGNAL_IGN; - /* - * If the (new) signal is now blocked, requeue it. - */ - if (sigismember(&task->blocked, info->si_signo)) { - send_sig_info(info->si_signo, info, task); - return resume | UTRACE_SIGNAL_IGN; - } - - spin_lock_irq(&task->sighand->siglock); - *return_ka = task->sighand->action[info->si_signo - 1]; - spin_unlock_irq(&task->sighand->siglock); - - return resume | UTRACE_SIGNAL_DELIVER; - + return resume | resume_signal(task, context->signr, + info, return_ka); default: WARN_ON(context->siginfo); context->siginfo = info; @@ -344,6 +345,7 @@ static u32 ptrace_report_signal(u32 acti context->ev_name = PTRACE_EVENT_SIGNAL; context->ev_code = info->si_signo; + context->signr = info->si_signo; return UTRACE_STOP | UTRACE_SIGNAL_IGN; } @@ -895,7 +897,7 @@ static void do_ptrace_resume(struct utra send_sig_info(data, SEND_SIG_PRIV, tracee); break; case PTRACE_EVENT_SIGNAL: - ptrace_resume_signal(context, data); + context->signr = data; break; } From oleg at redhat.com Sat Oct 3 01:58:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:58:08 +0200 Subject: [PATCH 63] convert ptrace_getsiginfo() to use ptrace_rw_siginfo() Message-ID: <20091003015808.GA15073@redhat.com> - Change ptrace_getsiginfo() to use ptrace_rw_siginfo(). - Fix the semantics. We should return EINVAL only if the tracee was stopped. If it didn't report the signal, we fill siginfo like ptrace_notify() did. Note! Currently do_ptrace_notify_stop() clears context->ev_code for debugging purposes, this means info->si_code is not right currently. --- kernel/ptrace.c | 33 ++++++++++++++++++--------------- 1 file changed, 18 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~63_GET_SIGINFO 2009-10-03 02:49:42.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 03:19:47.000000000 +0200 @@ -801,22 +801,23 @@ static int ptrace_rw_siginfo(struct task return err; } -static int ptrace_getsiginfo(struct utrace_engine *engine, - struct task_struct *child, siginfo_t *info) +static int ptrace_getsiginfo(struct ptrace_context *context, + struct task_struct *tracee, siginfo_t *info) { - unsigned long flags; - int error = -ESRCH; + /* jctl stop ? */ + if (!ev_pending(context)) + return -EINVAL; - if (lock_task_sighand(child, &flags)) { - error = -EINVAL; - if (likely(ptrace_context(engine)->siginfo != NULL)) { - *info = *ptrace_context(engine)->siginfo; - error = 0; - } - unlock_task_sighand(child, &flags); - } + if (context->siginfo) + return ptrace_rw_siginfo(tracee, context, info, false); - return error; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = context->ev_code; // XXX: ev_code was already cleared!!! + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + + return 0; } static int ptrace_setsiginfo(struct utrace_engine *engine, @@ -1045,7 +1046,8 @@ int ptrace_request(struct task_struct *c break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(engine, child, &siginfo); + ret = ptrace_getsiginfo(ptrace_context(engine), + child, &siginfo); if (!ret) ret = copy_siginfo_to_user((siginfo_t __user *) data, &siginfo); @@ -1214,7 +1216,8 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(engine, child, &siginfo); + ret = ptrace_getsiginfo(ptrace_context(engine), + child, &siginfo); if (!ret) ret = copy_siginfo_to_user32( (struct compat_siginfo __user *) datap, From oleg at redhat.com Sat Oct 3 01:58:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 03:58:10 +0200 Subject: [PATCH 64] convert ptrace_setsiginfo() to use ptrace_rw_siginfo() Message-ID: <20091003015810.GA15076@redhat.com> Like the previous patch, but if the tracee didn't report a signal we do nothing but return success. Currently ptrace_notify() always sets ->last_siginfo != NULL which can be update via PTRACE_SETSIGINFO, but this info will be never used. We pretend siginfo was updated for compatibility but the stupid app can read it back, in this case we will have bug-reports. --- kernel/ptrace.c | 28 +++++++++++++--------------- 1 file changed, 13 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~64_PUT_SIGINFO 2009-10-03 03:19:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 03:44:56.000000000 +0200 @@ -820,22 +820,18 @@ static int ptrace_getsiginfo(struct ptra return 0; } -static int ptrace_setsiginfo(struct utrace_engine *engine, - struct task_struct *child, const siginfo_t *info) +static int ptrace_setsiginfo(struct ptrace_context *context, + struct task_struct *tracee, siginfo_t *info) { - unsigned long flags; - int error = -ESRCH; + /* jctl stop ? */ + if (!ev_pending(context)) + return -EINVAL; - if (lock_task_sighand(child, &flags)) { - error = -EINVAL; - if (likely(ptrace_context(engine)->siginfo != NULL)) { - *ptrace_context(engine)->siginfo = *info; - error = 0; - } - unlock_task_sighand(child, &flags); - } + if (context->siginfo) + return ptrace_rw_siginfo(tracee, context, info, true); - return error; + /* compatibility: pretend it was updated */ + return 0; } @@ -1058,7 +1054,8 @@ int ptrace_request(struct task_struct *c sizeof siginfo)) ret = -EFAULT; else - ret = ptrace_setsiginfo(engine, child, &siginfo); + ret = ptrace_setsiginfo(ptrace_context(engine), + child, &siginfo); break; case PTRACE_DETACH: /* detach a process that was attached. */ @@ -1230,7 +1227,8 @@ int compat_ptrace_request(struct task_st &siginfo, (struct compat_siginfo __user *) datap)) ret = -EFAULT; else - ret = ptrace_setsiginfo(engine, child, &siginfo); + ret = ptrace_setsiginfo(ptrace_context(engine), + child, &siginfo); break; default: From oleg at redhat.com Sat Oct 3 02:00:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 04:00:22 +0200 Subject: [PATCH 60] UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL Message-ID: <20091003020022.GA15200@redhat.com> ptrace_report_signal(UTRACE_SIGNAL_HANDLER) should be never called with a valid context->siginfo, move the corresponding WARN_ON() up. --- kernel/ptrace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~60_SIGNAL_HANDLER_WARN_ALWAYS 2009-10-02 23:44:02.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 00:00:27.000000000 +0200 @@ -301,10 +301,10 @@ static u32 ptrace_report_signal(u32 acti switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: - if (resume != UTRACE_RESUME) { - if (WARN_ON(context->siginfo)) - context->siginfo = NULL; + if (WARN_ON(context->siginfo)) + context->siginfo = NULL; + if (resume != UTRACE_RESUME) { context->ev_name = PTRACE_EVENT_SIGTRAP; context->ev_code = SIGTRAP; From oleg at redhat.com Sat Oct 3 02:00:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 3 Oct 2009 04:00:35 +0200 Subject: [PATCH 62] introduce ptrace_rw_siginfo() helper Message-ID: <20091003020035.GA15213@redhat.com> A separate patch to discuss the comments/naming. Introduce the new helper, ptrace_rw_siginfo(), to access context->siginfo. It assumes the tracee must have the valid ->siginfo != NULL unless we race with SIGKILL, see the next patches. --- kernel/ptrace.c | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~62_COPY_SIGINFO 2009-10-03 01:37:41.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-03 02:49:42.000000000 +0200 @@ -339,8 +339,11 @@ static u32 ptrace_report_signal(u32 acti default: WARN_ON(context->siginfo); context->siginfo = info; - // Make sure the next UTRACE_SIGNAL_REPORT - // will clear context->siginfo + /* + * context->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ utrace_control(task, engine, UTRACE_INTERRUPT); context->ev_name = PTRACE_EVENT_SIGNAL; @@ -768,6 +771,36 @@ static int ptrace_set_options(struct utr return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *context, + siginfo_t *info, bool write) +{ + unsigned long flags; + siginfo_t *context_info; + int err = -ESRCH; + + if (!lock_task_sighand(tracee, &flags)) + return err; + /* + * Make sure the compiler reads ->siginfo only once, if we race + * with SIGKILL ->siginfo can be cleared under us. But the memory + * it points to can't go away, and since we hold ->siglock we can't + * race with get_signal_to_deliver() pathes clobber this memory. + * See also the comment in ptrace_report_signal(). + */ + context_info = ACCESS_ONCE(context->siginfo); + if (context_info) { + if (write) + *context_info = *info; + else + *info = *context_info; + err = 0; + } + unlock_task_sighand(tracee, &flags); + + return err; +} + static int ptrace_getsiginfo(struct utrace_engine *engine, struct task_struct *child, siginfo_t *info) { From ryanezq at draxis.com Sat Oct 3 13:49:33 2009 From: ryanezq at draxis.com (Phil Mason) Date: Sat, 3 Oct 2009 14:49:33 +0100 Subject: Give her a taste of your long and hard malehood. Message-ID: <20091003144933.1010007@draxis.com> Science has created a blue-pill to better pleasure! http://loo.kuodvorteto.com/ From oleg at redhat.com Mon Oct 5 02:32:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 5 Oct 2009 04:32:08 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091001201725.GA2947@host0.dyn.jankratochvil.net> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> Message-ID: <20091005023208.GA23901@redhat.com> (add Roland) On 10/01, Jan Kratochvil wrote: > > the ptrace-testsuite > http://sourceware.org/systemtap/wiki/utrace/tests > > currently FAILs (also) on Fedora 12 kernel-2.6.31.1-48.fc12.x86_64 for: > FAIL: detach-stopped > FAIL: stopped-attach-transparency > > Do you agree with the testcases and is it planned to fix them for F12? I do not know. I'd leave this to Roland. I mean, if he thinks this should be fixed - I'll try to fix. But. This all looks unfixeable to me. In my opinion, the kernel is obviously wrong, and test-case are wrong too. And any fix in this area is user-visible and can break the current expectations. As for kernel, I lost any hope to understand what is the _supposed_ behaviour. As for user-space, I don't really understand the second test-case, this again means I don't understand the supposed behaviour. Firstly, I think we should un-revert edaba2c5334492f82d39ec35637c6dea5176a977. This unconditional wakeup is hopelessly wrong imho, and it is removed from utrace-ptrace code. But this breaks another test-case, attach-wait-on-stopped. I still think this test-case is wrong. We had a lengthy discussion about this. Now, this patch --- TTT_32/kernel/signal.c~PT_STOP 2009-10-04 04:08:36.000000000 +0200 +++ TTT_32/kernel/signal.c 2009-10-05 03:17:39.000000000 +0200 @@ -1708,7 +1708,7 @@ static int do_signal_stop(int signr) */ if (sig->group_stop_count) { if (!--sig->group_stop_count) - sig->flags = SIGNAL_STOP_STOPPED; + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; current->exit_code = sig->group_exit_code; __set_current_state(TASK_STOPPED); } fixes the tests above. Of course this change is not enough, I did it just to verify I really understand what happens. Except, stopped-attach-transparency prints Excessive waiting SIGSTOP after the second attach/detach afaics the test-case is not right here. attach_detach() leaves the traced threads in STOPPED state, why pid_notifying_sigstop() should fail? But as I said, I do not really understand what this test-case tries to do. What ptrace(PTRACE_DETACH, SIGSTOP) should mean? I think that ptrace(PTRACE_DETACH, signr) should mean the tracee should proceed with this signal, as if it was sent by, say, kill. In this case, I don't understand why stopped-attach-transparency "sends" SIGSTOP to every sub-thread. If the tracer wants to stop the thread group after detach, it can do ptrace(PTRACE_DETACH, anythread, SIGSTOP); for_each_other_thread(pid) ptrace(PTRACE_DETACH, anythread, 0); or just kill(SIGSTOP); for_each_thread(pid) ptrace(PTRACE_DETACH, anythread, 0); I do not say this will really work with the current implementaion, we have other bugs/races. I mean I'd expect this should be the right way to do detach+stop. And. Currently PTRACE_CONT/PTRACE_DETACH/etc wakes up the tracee even if the thread group is stopped. This is obviously not right, but utrace-ptrace does the same. I guess we can't fix this without breaking existing applications. In short: I don't know what to do ;) Oleg. From oleg at redhat.com Mon Oct 5 02:51:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 5 Oct 2009 04:51:32 +0200 Subject: utrace-ptrace && detach with signal semantics Message-ID: <20091005025132.GA25283@redhat.com> Jan, Roland, I have the question. Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) and then another/same tracer does ptrace(ATTACH, tracee) then SIGXXX will not be reported to the new tracer. Why? Should utrace-ptrace be 100% compatible here? It is not trivial to implement, and I don't understand why it is important to keep this behaviour. But we have the test case which checks this: attach-into-signal. Could you explain what can be breaked if SIGXXX will be reported to the next tracer (assuming the 2nd ATTACH is fast enough) ? I do not think there is a "real life" application that does ATTACH + DETACH and relies on fact it must not see this sig. Oleg. From envoi at campaigns.media-sender.net Mon Oct 5 11:02:50 2009 From: envoi at campaigns.media-sender.net (IC Telecom) Date: Mon, 5 Oct 2009 13:02:50 +0200 (CEST) Subject: =?iso-8859-15?q?Illimit=E9_=3A_Communications_-_Internet_-_t=E9l?= =?iso-8859-15?q?=E9phones?= Message-ID: <1011303148415.1103513324.1254740570734@enginex3.emv2.com> Si ce message n'est pas lisible, visualisez la version en ligne : http://campaigns.media-sender.net/HM?a=A9X7CkJQ0FqQsOZ73ORojRvhng VOTRE SOLUTION PRO TOUT EN UN Ma?triser votre budget, simplifiez votre t?l?phonie Une facture unique Une offre SIMPLE et ECONOMIQUE ICtelecom c'est : La t?l?phonie ILLIMITEE ( France m?tropolitaine fixe) + Standard t?l?phonique (Abonnement inclus) + Internet HAUT DEBIT + Postes t?l?phoniques (Cisco ou ?quivalent) Pour seulement 29? HT/mois La r?duction des co?ts g?n?raux est un enjeu crucial pour la comp?titivit? de votre entreprise. Avec plus de 10 ans d'exp?rience dans les t?l?communications, ICtelecom sp?cialiste de la voix sur IP, est l'inventeur du "guichet unique" pour les entreprises. Fort de sa ma?trise des technologies en t?l?communications et des r?seaux IP et b?n?ficiant d?une position sans concurrence de premier plan sur le march? de la convergence (t?l?phonie fixe, t?l?phonie mobile, internet), ICtelecom d?veloppe pour le march? professionel des offres tripe play packag?es (voix, data, mobile). ICtelecom fournit plus de 12000 utilisateurs ? travers plus de 2000 locaux install?s. Ce courriel est conforme ? la l?gislation en vigueur et aux d?lib?rations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier ?lectronique dans le cadre professionnel. Conform?ment ? l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative ? l'informatique, aux fichiers et aux libert?s, vous disposez d'un droit d'acc?s, de rectification des donn?es nominatives vous concernant. Si vous ne voulez plus recevoir de messages commerciaux de notre soci?t? par e-mail, D?sactiver votre souscription : http://campaigns.media-sender.net/HP?a=A9X7CkJQ0FqQsOZ73ORojRjhnw . Le pr?sent message est en parfait respect avec la d?ontologie et les bonnes pratiques de la communication par marketing direct ?lectronique. Conform?ment ? la l?gislation en vigueur et des diff?rents rectificatifs l?gaux, vous disposez d'un plein droit d'acc?s, de modifications ou de suppression des donn?es personnelles vous concernant. Vous pouvez ? tout moment exercer ce droit via le formulaire pr?vu ? cet effet. Conform?ment ? la loi Informatique et libert?s, vous pouvez d?sactiver votre souscription ? tout moment. Loi n? 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative ? l'informatique, aux fichiers et aux libert?s : Toute personne physique a le droit de s'opposer, pour des motifs l?gitimes, ? ce que des donn?es ? caract?re personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, ? ce que les donn?es la concernant soient utilis?es ? des fins de prospect par le responsable actuel du traitement ou celui d'un traitement ult?rieur. Les dispositions du premier alin?a ne s'appliquent pas lorsque le traitement r?pond ? une n?cessit? l?gale ou lorsque l'application de ces dispositions a ?t? ?cart?e par une disposition expresse de l'acte autorisant le traitement de la publicit? par voie ?lectronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs l?gitimes, ? ce que des donn?es ? caract?re personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, ? ce que les donn?es la concernant soient utilis?es ? des fins de prospection, par le responsable actuel du traitement ou celui d'un traitement ult?rieur. Les dispositions du premier alin?a ne s'appliquent pas lorsque le traitement r?pond ? une obligation l?gale ou lorsque l'application de ces dispositions a ?t? ?cart?e par une disposition expresse de l'acte autorisant le traitement. Si vous ne voulez plus recevoir de propositions de notre part, il vous suffit de remplir cette demande : http://campaigns.media-sender.net/HP?a=A9X7CkJQ0FqQsOZ73ORojRnhkA . -------------- next part -------------- An HTML attachment was scrubbed... URL: From envoi at campaigns.media-sender.net Mon Oct 5 11:59:39 2009 From: envoi at campaigns.media-sender.net (FaxReception) Date: Mon, 5 Oct 2009 13:59:39 +0200 (CEST) Subject: =?iso-8859-15?q?Vous_avez_re=E7u_un_Fax_?= Message-ID: <1011303148415.1103513008.1254743979249@enginex3.emv2.com> Si ce message ne s'affiche pas correctement, visualisez la version en ligne http://campaigns.media-sender.net/HM?a=A9X7CkJQ0FqQsOZ4gORr9E_i6w FAXR?CEPTION - RECEVEZ VOS FAX PAR E-MAIL (site : http://campaigns.media-sender.net/HS?a=A9X7CkJQ0FqQsOZ4gORrIszhJg ) Pourquoi ne pas recevoir vos fax par e-mail (6,50? / mois) ? D?monstration de notre service : http://campaigns.media-sender.net/HS?a=A9X7CkJQ0FqQsOZ4gORrIs3hJw Test de la r?ception de fax par email : http://campaigns.media-sender.net/HS?a=A9X7CkJQ0FqQsOZ4gORrIsLhWA ?CONOMIQUE Plus besoin de ligne t?l?phonique d?di?e, ni de t?l?copieur. Fini les probl?mes d'encre, de papier et de sonnerie. SIMPLICIT? En quelques minutes, vous choisissez votre nouveau num?ro de fax, et votre ligne est activ?e et op?rationnelle instantan?ment. CONFIDENTIALIT? Vous disposez d'un num?ro de fax personnel ainsi que d'un acc?s s?curis?. MOBILIT? Gr?ce ? l'acc?s web, vous pouvez consulter vos fax m?me lorsque vous ?tes en d?placement. COMPATIBLE PDA D?s souscription au service FaxReception, vous recevez aussi vos fax directement sur votre PDA. ?COLOGIQUE En utilisant FaxReception pour recevoir vos fax, vous r?duisez votre consommation de papier. Pour envoyer vos fax Envoyez directement vos Fax ? partir de votre PC : www.safefax.fr Ce courriel commercial est conforme ? la l?gislation en vigueur et aux d?lib?rations de la CNIL des 22 et 30 mars 2005 sur la prospection par courrier ?lectronique dans le cadre professionnel. Conform?ment ? l'article 34 de la loi 78-17 du 6 janvier mille neuf cent soixante dix huit, relative ? l'informatique, aux fichiers et aux libert?s, vous disposez d'un droit d'acc?s, de rectification des donn?es nominatives vous concernant. Si vous ne souhaitez plus recevoir de messages commerciaux de notre soci?t? par e-mail, D?sactiver votre souscription : http://campaigns.media-sender.net/HP?a=A9X7CkJQ0FqQsOZ4gORrZZbhIQ . Le pr?sent message est en parfait respect avec la d?ontologie et les bonnes pratiques de la communication par marketing direct ?lectronique. Conform?ment ? la l?gislation en vigueur et des diff?rents rectificatifs l?gaux, vous disposez d'un plein droit d'acc?s, de modifications ou de suppression des donn?es personnelles vous concernant. Vous pouvez ? tout moment exercer ce droit via le formulaire pr?vu ? cet effet. Conform?ment ? la loi Informatique et libert?s, vous pouvez d?sactiver votre souscription ? tout moment. Loi n? 78-17 du 6 Janvier mille neuf cent soixante dix huit, relative ? l'informatique, aux fichiers et aux libert?s : Toute personne physique a le droit de s'opposer, pour des motifs l?gitimes, ? ce que des donn?es ? caract?re personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, ? ce que les donn?es la concernant soient utilis?es ? des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ult?rieur. Les dispositions du premier alin?a ne s'appliquent pas lorsque le traitement r?pond ? une n?cessit? l?gale ou lorsque l'application de ces dispositions a ?t? ?cart?e par une disposition expresse de l'acte autorisant le traitement de la publicit? par voie ?lectronique. Art 38 : Toute personne physique a le droit de s'opposer, pour des motifs l?gitimes, ? ce que des donn?es ? caract?re personnel la concernant fassent l'objet d'un traitement. Elle a le droit de s'opposer, sans frais, ? ce que les donn?es la concernant soient utilis?es ? des fins de prospection, notamment commerciale, par le responsable actuel du traitement ou celui d'un traitement ult?rieur. Les dispositions du premier alin?a ne s'appliquent pas lorsque le traitement r?pond ? une obligation l?gale ou lorsque l'application de ces dispositions a ?t? ?cart?e par une disposition expresse de l'acte autorisant le traitement. Si vous ne souhaitez plus recevoir de propositions commerciales de notre part, il vous suffit de remplir cette demande : http://campaigns.media-sender.net/HP?a=A9X7CkJQ0FqQsOZ4gORrZZfhIg . -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Mon Oct 5 18:39:47 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 5 Oct 2009 20:39:47 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091005025132.GA25283@redhat.com> References: <20091005025132.GA25283@redhat.com> Message-ID: <20091005183947.GA22972@host0.dyn.jankratochvil.net> On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > and then another/same tracer does ptrace(ATTACH, tracee) > then SIGXXX will not be reported to the new tracer. > > Why? Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > It is not trivial to implement, and I don't understand why > it is important to keep this behaviour. But we have the test > case which checks this: attach-into-signal. This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the first one after PTRACE_ATTACH. It has specific handling of such cases. If it is the official goal we probably do not have a testcase for it. AI: Approved to modify attach-into-signal to check it does not happen? > Could you explain what can be breaked if SIGXXX will be reported > to the next tracer (assuming the 2nd ATTACH is fast enough) ? With a testcase looping in: void handler(int sig) { raise(sig); }: the latest official GDB release (6.8) will: Attaching to process 5412 linux-nat.c:988: internal-error: linux_nat_attach: Assertion `pid == GET_PID (inferior_ptid) && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP' failed. A problem internal to GDB has been detected, further debugging may prove unreliable. Quit this debugging session? (y or n) y If they do not assertion check they will at least lose the pending signal after the attach/detach pair. > I do not think there is a "real life" application that does > ATTACH + DETACH and relies on fact it must not see this sig. I think FSF GDB is enough, isn't it? Thanks, Jan From jan.kratochvil at redhat.com Mon Oct 5 18:47:45 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 5 Oct 2009 20:47:45 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091005023208.GA23901@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> Message-ID: <20091005184745.GB22972@host0.dyn.jankratochvil.net> On Mon, 05 Oct 2009 04:32:08 +0200, Oleg Nesterov wrote: > On 10/01, Jan Kratochvil wrote: > > > > the ptrace-testsuite > > http://sourceware.org/systemtap/wiki/utrace/tests > > > > currently FAILs (also) on Fedora 12 kernel-2.6.31.1-48.fc12.x86_64 for: > > FAIL: detach-stopped > > FAIL: stopped-attach-transparency [...] > As for user-space, I don't really understand the second test-case, > this again means I don't understand the supposed behaviour. The high level goal is described at its top. Users expect that if they run `gstack PID' or `gcore PID' the target PID will be absolutely in the same state as before gstack/gcore. That means it will keep both whether it was / was not stopped and also any possible existing / non-existing pending signal for a possible future waitpid() from its real (non-ptrace) parent PID. Another question whether technically what it does is right but this high level goal is hopefully valid. > Except, stopped-attach-transparency prints > > Excessive waiting SIGSTOP after the second attach/detach > > afaics the test-case is not right here. attach_detach() leaves the > traced threads in STOPPED state, why pid_notifying_sigstop() should > fail? [ Not replying this part, have not built a kernel with this patch now. ] > In this case, I don't understand why stopped-attach-transparency > "sends" SIGSTOP to every sub-thread. If the tracer wants to stop > the thread group after detach, it can do > > ptrace(PTRACE_DETACH, anythread, SIGSTOP); > for_each_other_thread(pid) > ptrace(PTRACE_DETACH, anythread, 0); > > or just > > kill(SIGSTOP); > for_each_thread(pid) > ptrace(PTRACE_DETACH, anythread, 0); OK, it this is the recommended way I can fix the testcase this way. The all-threads-being-sent-SIGSTOP way IIRC worked on linux-2.6.9 but I do not think this part of the compatibility must be kept. Thanks, Jan From oleg at redhat.com Mon Oct 5 19:00:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 5 Oct 2009 21:00:37 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091005183947.GA22972@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> Message-ID: <20091005190037.GA2103@redhat.com> On 10/05, Jan Kratochvil wrote: > > On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: > > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > > and then another/same tracer does ptrace(ATTACH, tracee) > > then SIGXXX will not be reported to the new tracer. > > > > Why? > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. They should not, this is just wrong. And I think the proposed change doesn't change the behaviour in this sense. > > It is not trivial to implement, and I don't understand why > > it is important to keep this behaviour. But we have the test > > case which checks this: attach-into-signal. > > This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the > first one after PTRACE_ATTACH. It has specific handling of such cases. This test-case also does: /* detach with SIGPIPE/attach. This should kill tracee */ ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); waitpid (child, &status, 0); assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what I can't understand. > > Could you explain what can be breaked if SIGXXX will be reported > > to the next tracer (assuming the 2nd ATTACH is fast enough) ? > > With a testcase looping in: void handler(int sig) { raise(sig); }: > the latest official GDB release (6.8) will: > > Attaching to process 5412 > linux-nat.c:988: internal-error: linux_nat_attach: Assertion `pid == GET_PID > (inferior_ptid) && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP' > failed. > A problem internal to GDB has been detected, > further debugging may prove unreliable. > Quit this debugging session? (y or n) y Hmm. Could you please explain what "testcase looping" above mean? Perhaps we don't understand each other... OK. Currently, ptrace(DETACH, SIGXXX) means: - untrace - the tracee will get this SIGXXX and handle this signal - BUT! if the new tracer attaches right now, before the tracee handles the signal, this signal will not be reported to the new tracer. With the current utrace-ptrace implementation: if the second attach happens before the tracee dequeues SIGXXX, this signal will be reported to the new tracer too. Oleg. From oleg at redhat.com Mon Oct 5 19:06:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 5 Oct 2009 21:06:49 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091005184745.GB22972@host0.dyn.jankratochvil.net> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091005184745.GB22972@host0.dyn.jankratochvil.net> Message-ID: <20091005190649.GA3201@redhat.com> On 10/05, Jan Kratochvil wrote: > > On Mon, 05 Oct 2009 04:32:08 +0200, Oleg Nesterov wrote: > [...] > > As for user-space, I don't really understand the second test-case, > > this again means I don't understand the supposed behaviour. > > The high level goal is described at its top. Users expect that if they run > `gstack PID' or `gcore PID' the target PID will be absolutely in the same > state as before gstack/gcore. > > That means it will keep both whether it was / was not stopped and also any > possible existing / non-existing pending signal for a possible future > waitpid() from its real (non-ptrace) parent PID. > > Another question whether technically what it does is right but this high level > goal is hopefully valid. Yes, agreed, this part is clear. Oleg. From oleg at redhat.com Tue Oct 6 00:11:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:34 +0200 Subject: [PATCH 65-69] kill context->ev_name Message-ID: <20091006001134.GA23862@redhat.com> Kill context->ev_name. Naming: as usual, I agree in advance with any suggestions. Oleg. From oleg at redhat.com Tue Oct 6 00:11:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:37 +0200 Subject: [PATCH 65] don't clear context->ev_code for debugging Message-ID: <20091006001137.GA23866@redhat.com> do_ptrace_notify_stop() clears ->ev_code for debugging purposes, remove this. We need the valid ->ev_code in ptrace_getsiginfo(). --- kernel/ptrace.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) --- PU/kernel/ptrace.c~65_DONT_CLEAR_EV_CODE 2009-10-06 00:47:13.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 00:50:01.000000000 +0200 @@ -308,7 +308,6 @@ static u32 ptrace_report_signal(u32 acti enum utrace_resume_action resume = context->resume; 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; @@ -361,10 +360,8 @@ static u32 ptrace_report_quiesce(u32 act { struct ptrace_context *context = ptrace_context(engine); - if (ev_pending(context)) { - WARN_ON(!context->ev_code && !fatal_signal_pending(task) && !(task->flags & PF_EXITING)); + if (ev_pending(context)) return UTRACE_STOP; - } return event ? UTRACE_RESUME : context->resume; } @@ -813,7 +810,7 @@ static int ptrace_getsiginfo(struct ptra memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; - info->si_code = context->ev_code; // XXX: ev_code was already cleared!!! + info->si_code = context->ev_code; info->si_pid = task_pid_vnr(tracee); info->si_uid = task_uid(tracee); @@ -858,10 +855,6 @@ static void do_ptrace_notify_stop(struct { tracee->exit_code = context->ev_code; - // XXX: for debug only - WARN_ON(!context->ev_code); - context->ev_code = 0; - read_lock(&tasklist_lock); /* * Don't want to allow preemption here, because From oleg at redhat.com Tue Oct 6 00:11:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:39 +0200 Subject: [PATCH 66] introduce syscall_code(context) helper Message-ID: <20091006001139.GA23873@redhat.com> Trivial, move the annoying PTRACE_O_TRACESYSGOOD check into the new helper, syscall_code(). --- kernel/ptrace.c | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) --- PU/kernel/ptrace.c~66_SYSGOOD_HELPER 2009-10-06 00:50:01.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 01:11:40.000000000 +0200 @@ -207,6 +207,12 @@ static u32 ptrace_report_clone(enum utra return ret; } +static inline int syscall_code(struct ptrace_context *context) +{ + return (context->options & PTRACE_O_TRACESYSGOOD) ? + (SIGTRAP | 0x80) : SIGTRAP; +} + static u32 ptrace_report_syscall_entry(u32 action, struct utrace_engine *engine, struct task_struct *task, @@ -217,8 +223,8 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ev_pending(context)); context->ev_name = PTRACE_EVENT_SYSCALL_ENTRY; - context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + context->ev_code = syscall_code(context); + return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -233,8 +239,8 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; - context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + context->ev_code = syscall_code(context); + return UTRACE_STOP; } @@ -931,8 +937,8 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; - context->ev_code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + context->ev_code = syscall_code(context); + do_ptrace_notify_stop(context, tracee); return; } From oleg at redhat.com Tue Oct 6 00:11:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:42 +0200 Subject: [PATCH 67] introduce get_stop_code(context) helper Message-ID: <20091006001142.GA23876@redhat.com> Trivial, to simplify the review of the next patches. ->ev_name is used as rvalue in ptrace_resume(), add the trivial helper to read this member. --- kernel/ptrace.c | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~67_GET_STOP_CODE_HELPER 2009-10-06 01:11:40.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 01:23:21.000000000 +0200 @@ -47,6 +47,11 @@ static inline bool ev_pending(struct ptr return context->ev_name != 0; } +static inline int get_stop_code(struct ptrace_context *context) +{ + return context->ev_name; +} + static inline struct ptrace_context * ptrace_context(struct utrace_engine *engine) { @@ -916,7 +921,7 @@ static void do_ptrace_resume(struct utra { struct ptrace_context *context = ptrace_context(engine); - switch (context->ev_name) { + switch (get_stop_code(context)) { case 0: // XXX: JCTL stop break; @@ -931,7 +936,7 @@ static void do_ptrace_resume(struct utra } if (request == PTRACE_SYSCALL) { - switch (context->ev_name) { + switch (get_stop_code(context)) { case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: @@ -945,7 +950,7 @@ static void do_ptrace_resume(struct utra } if (action != UTRACE_RESUME) { - switch (context->ev_name) { + switch (get_stop_code(context)) { case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: From oleg at redhat.com Tue Oct 6 00:11:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:44 +0200 Subject: [PATCH 68] encode internal stop events in ->ev_code too Message-ID: <20091006001144.GA23879@redhat.com> The events like PTRACE_EVENT_SYSCALL_ENTRY should not be reported to the tracer, that is why ptrace_report_syscall_entry() puts this code into ->ev_name only. And this is the only reason for ->ev_name. Introduce PTRACE_EVENT_MASK which can filter out internal codes and change their users to put this code into ->ev_code too. --- kernel/ptrace.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) --- PU/kernel/ptrace.c~68_PUT_EVENT_IN_CODE 2009-10-06 01:23:21.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 02:00:51.000000000 +0200 @@ -37,10 +37,12 @@ struct ptrace_context { enum utrace_resume_action resume; }; -#define PTRACE_EVENT_SYSCALL_ENTRY 100 -#define PTRACE_EVENT_SYSCALL_EXIT 101 -#define PTRACE_EVENT_SIGTRAP 102 -#define PTRACE_EVENT_SIGNAL 103 +#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) +#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) +#define PTRACE_EVENT_SIGTRAP (3 << 16) +#define PTRACE_EVENT_SIGNAL (4 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF static inline bool ev_pending(struct ptrace_context *context) { @@ -228,7 +230,8 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ev_pending(context)); context->ev_name = PTRACE_EVENT_SYSCALL_ENTRY; - context->ev_code = syscall_code(context); + context->ev_code = (PTRACE_EVENT_SYSCALL_ENTRY << 8) | + syscall_code(context); return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -244,7 +247,8 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_STOP; context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; - context->ev_code = syscall_code(context); + context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | + syscall_code(context); return UTRACE_STOP; } @@ -331,7 +335,7 @@ static u32 ptrace_report_signal(u32 acti if (resume != UTRACE_RESUME) { context->ev_name = PTRACE_EVENT_SIGTRAP; - context->ev_code = SIGTRAP; + context->ev_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; return UTRACE_STOP | UTRACE_SIGNAL_IGN; } @@ -357,7 +361,7 @@ static u32 ptrace_report_signal(u32 acti utrace_control(task, engine, UTRACE_INTERRUPT); context->ev_name = PTRACE_EVENT_SIGNAL; - context->ev_code = info->si_signo; + context->ev_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; context->signr = info->si_signo; return UTRACE_STOP | UTRACE_SIGNAL_IGN; @@ -821,7 +825,7 @@ static int ptrace_getsiginfo(struct ptra memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; - info->si_code = context->ev_code; + info->si_code = context->ev_code & PTRACE_EVENT_MASK; info->si_pid = task_pid_vnr(tracee); info->si_uid = task_uid(tracee); @@ -864,7 +868,7 @@ static int ptrace_setsiginfo(struct ptra static void do_ptrace_notify_stop(struct ptrace_context *context, struct task_struct *tracee) { - tracee->exit_code = context->ev_code; + tracee->exit_code = context->ev_code & PTRACE_EVENT_MASK; read_lock(&tasklist_lock); /* @@ -942,8 +946,8 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; - context->ev_code = syscall_code(context); - + context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | + syscall_code(context); do_ptrace_notify_stop(context, tracee); return; } From oleg at redhat.com Tue Oct 6 00:11:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:11:46 +0200 Subject: [PATCH 69] kill context->ev_name Message-ID: <20091006001146.GA23886@redhat.com> Kill context->ev_name, it is always eq to (ev_code >> 8) since the previous patch. I think it makes sense to add another helper for "(event << 8) | signr", but I failed to invent the name. We can also kill context->signr, we can use (ev_code & 0xFF) byte instead. --- kernel/ptrace.c | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) --- PU/kernel/ptrace.c~69_KILL_EV_NAME 2009-10-06 02:00:51.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 02:04:07.000000000 +0200 @@ -30,7 +30,6 @@ struct ptrace_context { int signr; siginfo_t *siginfo; - int ev_name; int ev_code; unsigned long ev_mesg; @@ -46,12 +45,12 @@ struct ptrace_context { static inline bool ev_pending(struct ptrace_context *context) { - return context->ev_name != 0; + return context->ev_code != 0; } static inline int get_stop_code(struct ptrace_context *context) { - return context->ev_name; + return context->ev_code >> 8; } static inline struct ptrace_context * @@ -124,7 +123,6 @@ static u32 ptrace_report_exit(enum utrac WARN_ON(ev_pending(context)); - context->ev_name = PTRACE_EVENT_EXIT; context->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP; context->ev_mesg = *code; @@ -197,14 +195,12 @@ static u32 ptrace_report_clone(enum utra // XXX: child->pid is wrong! use tracer's pid_ns if (event) { - context->ev_name = event; context->ev_code = (event << 8) | SIGTRAP; context->ev_mesg = child->pid; ret = UTRACE_STOP; } 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; @@ -229,7 +225,6 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ev_pending(context)); - context->ev_name = PTRACE_EVENT_SYSCALL_ENTRY; context->ev_code = (PTRACE_EVENT_SYSCALL_ENTRY << 8) | syscall_code(context); @@ -246,7 +241,6 @@ static u32 ptrace_report_syscall_exit(en if (ev_pending(context)) return UTRACE_STOP; - context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | syscall_code(context); @@ -272,7 +266,6 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } - context->ev_name = PTRACE_EVENT_EXEC; context->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; return UTRACE_STOP; @@ -334,7 +327,6 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - context->ev_name = PTRACE_EVENT_SIGTRAP; context->ev_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; return UTRACE_STOP | UTRACE_SIGNAL_IGN; @@ -360,7 +352,6 @@ static u32 ptrace_report_signal(u32 acti */ utrace_control(task, engine, UTRACE_INTERRUPT); - context->ev_name = PTRACE_EVENT_SIGNAL; context->ev_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; context->signr = info->si_signo; @@ -945,7 +936,6 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: - context->ev_name = PTRACE_EVENT_SYSCALL_EXIT; context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | syscall_code(context); do_ptrace_notify_stop(context, tracee); @@ -969,7 +959,7 @@ static void do_ptrace_resume(struct utra } } - context->ev_name = 0; + context->ev_code = 0; context->resume = action; ptrace_wake_up(engine, tracee, action); } From oleg at redhat.com Tue Oct 6 00:32:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:32:10 +0200 Subject: [PATCH 70] move "event << 8" into syscall_code() Message-ID: <20091006003210.GA26313@redhat.com> Forgot about this patch... Since we have syscall_code() anyway, make it a bit more useful. --- kernel/ptrace.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) --- PU/kernel/ptrace.c~70_TWEAK_SYSCALL_CODE 2009-10-06 02:24:36.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 02:25:02.000000000 +0200 @@ -210,10 +210,11 @@ static u32 ptrace_report_clone(enum utra return ret; } -static inline int syscall_code(struct ptrace_context *context) +static inline int syscall_code(struct ptrace_context *context, int event) { - return (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; + int code = (context->options & PTRACE_O_TRACESYSGOOD) ? + (SIGTRAP | 0x80) : SIGTRAP; + return (event << 8) | code; } static u32 ptrace_report_syscall_entry(u32 action, @@ -225,8 +226,7 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ev_pending(context)); - context->ev_code = (PTRACE_EVENT_SYSCALL_ENTRY << 8) | - syscall_code(context); + context->ev_code = syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -241,8 +241,7 @@ static u32 ptrace_report_syscall_exit(en if (ev_pending(context)) return UTRACE_STOP; - context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | - syscall_code(context); + context->ev_code = syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); return UTRACE_STOP; } @@ -936,8 +935,8 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: - context->ev_code = (PTRACE_EVENT_SYSCALL_EXIT << 8) | - syscall_code(context); + context->ev_code = syscall_code(context, + PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } @@ -951,7 +950,8 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_SYSCALL_EXIT: read_lock(&tasklist_lock); if (tracee->sighand) - send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); + send_sigtrap(tracee, task_pt_regs(tracee), + 0, TRAP_BRKPT); read_unlock(&tasklist_lock); action = UTRACE_RESUME; From oleg at redhat.com Tue Oct 6 00:39:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 02:39:02 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091005190037.GA2103@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> Message-ID: <20091006003902.GA26989@redhat.com> On 10/05, Oleg Nesterov wrote: > > On 10/05, Jan Kratochvil wrote: > > > > On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: > > > > It is not trivial to implement, and I don't understand why > > > it is important to keep this behaviour. But we have the test > > > case which checks this: attach-into-signal. > > > > This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the > > first one after PTRACE_ATTACH. It has specific handling of such cases. > > This test-case also does: > > /* detach with SIGPIPE/attach. This should kill tracee */ > ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); > > ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); > > waitpid (child, &status, 0); > assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); > > It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what > I can't understand. Just in case... If I change the test-case --- a/ptrace-tests/tests/attach-into-signal.c 2009-01-31 13:11:40.000000000 -0800 +++ b/ptrace-tests/tests/attach-into-signal.c 2009-09-20 13:32:30.000000000 -0700 @@ -225,9 +225,9 @@ static void reproduce (void) return; } assert (WIFSTOPPED (status)); - assert (WSTOPSIG (status) == SIGSTOP); + assert (WSTOPSIG (status) == SIGPIPE); /* let tracee run. it must be killed very soon by SIGPIPE */ - ptrace (PTRACE_CONT, child, (void *) 1, (void *) 0); + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); assert_perror (errno); pid = waitpid (child, &status, 0); assert (pid == child); then it doesn't fail. > OK. Currently, ptrace(DETACH, SIGXXX) means: > > - untrace > > - the tracee will get this SIGXXX and handle this signal > > - BUT! if the new tracer attaches right now, before the > tracee handles the signal, this signal will not be > reported to the new tracer. > > With the current utrace-ptrace implementation: if the second > attach happens before the tracee dequeues SIGXXX, this signal > will be reported to the new tracer too. So... Jan, do you think this behaviour change can break gdb? Oleg. From mldireto at tudoemoferta.com.br Mon Oct 5 18:09:55 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Mon, 5 Oct 2009 15:09:55 -0300 Subject: Brinquedoteca no TudoemOferta. Aqui o seu dia das criancas e mais feliz Message-ID: <40dceb4ea616635cf614730f001f631e@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Tue Oct 6 08:27:39 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 6 Oct 2009 10:27:39 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091005190037.GA2103@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> Message-ID: <20091006082739.GA12639@host0.dyn.jankratochvil.net> On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: > On 10/05, Jan Kratochvil wrote: > > > > On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: > > > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > > > and then another/same tracer does ptrace(ATTACH, tracee) > > > then SIGXXX will not be reported to the new tracer. > > > > > > Why? > > > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > > They should not, this is just wrong. That may be a right point but such programs are in use out there. Sure if it would be a real difficulty one can keep it as-is as GDB-7.0 soon to be released has it already fixed, strace works with it. Still ltrace crashes the inferior in such case. > And I think the proposed change doesn't change the behaviour > in this sense. We started to discuss two different changes: my asked for one: ptrace(DETACH, SIGSTOP) should leave the tracee stopped. a new one: First signal after PTRACE_ATTACH should be SIGSTOP. I find the latter as a lower priority, it just was brought in as a part of the discussion. I am not aware the latter would be any time filed as a real Bug. > > > It is not trivial to implement, and I don't understand why > > > it is important to keep this behaviour. But we have the test > > > case which checks this: attach-into-signal. > > > > This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the > > first one after PTRACE_ATTACH. It has specific handling of such cases. > > This test-case also does: > > /* detach with SIGPIPE/attach. This should kill tracee */ > ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); > > ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); > > waitpid (child, &status, 0); > assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); > > It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what > I can't understand. attach-info-signal from the ptrace-testsuite does not FAIL for me. Which kernel version does it FAIL on for you? > > > Could you explain what can be breaked if SIGXXX will be reported > > > to the next tracer (assuming the 2nd ATTACH is fast enough) ? > > > > With a testcase looping in: void handler(int sig) { raise(sig); }: > > the latest official GDB release (6.8) will: > > > > Attaching to process 5412 > > linux-nat.c:988: internal-error: linux_nat_attach: Assertion `pid == GET_PID > > (inferior_ptid) && WIFSTOPPED (status) && WSTOPSIG (status) == SIGSTOP' > > failed. > > A problem internal to GDB has been detected, > > further debugging may prove unreliable. > > Quit this debugging session? (y or n) y > > Hmm. Could you please explain what "testcase looping" above mean? Attached. > Perhaps we don't understand each other... > > OK. Currently, ptrace(DETACH, SIGXXX) means: > > - untrace > > - the tracee will get this SIGXXX and handle this signal > > - BUT! if the new tracer attaches right now, before the > tracee handles the signal, this signal will not be > reported to the new tracer. > > With the current utrace-ptrace implementation: if the second > attach happens before the tracee dequeues SIGXXX, this signal > will be reported to the new tracer too. I think you are discussing the latter Bug (first signal received by a tracer after PTRACE_ATTACH should be SIGSTOP) while I was asking about the former Bug (PTRACE_DETACH(SIGSTOP) should leave tracee stopped), do you agree? Thanks, Jan -------------- next part -------------- #include #include #include #include #define SIGNAL SIGALRM static void handler (int sig) { raise (sig); } int main (void) { struct sigaction act; int i; memset (&act, 0, sizeof (struct sigaction)); act.sa_handler = handler; act.sa_flags = SA_RESTART; i = sigaction (SIGNAL, &act, 0); assert (i == 0); i = raise (SIGNAL); assert (i == 0); assert (0); return 0; } From oleg at redhat.com Tue Oct 6 13:10:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 15:10:10 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006082739.GA12639@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> Message-ID: <20091006131010.GA5906@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: > > On 10/05, Jan Kratochvil wrote: > > > > > > On Mon, 05 Oct 2009 04:51:32 +0200, Oleg Nesterov wrote: > > > > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > > > > and then another/same tracer does ptrace(ATTACH, tracee) > > > > then SIGXXX will not be reported to the new tracer. > > > > > > > > Why? > > > > > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > > > > They should not, this is just wrong. > > That may be a right point but such programs are in use out there. Sure if it > would be a real difficulty one can keep it as-is as GDB-7.0 soon to be > released has it already fixed, strace works with it. Still ltrace crashes the > inferior in such case. Confused. Do you mean we should fix the kernel to match this expectation? This was never true. PTRACE_ATTACH sends SIGSTOP to the tracee, but this SIGSTOP is not magical, there is no any guarantee it will be dequeued before other pending signals. You attached the test-case which sends SIGALRM to itself in a loop. If the tracer attaches to this program, it is very possible that SIGALRM will be reported, not SIGSTOP. But! this has nothing to do with the question I asked ;) see below. > > And I think the proposed change doesn't change the behaviour > > in this sense. > > We started to discuss two different changes: We started to discuss 3 different things, not 2. Please see below, my question was quite different. > my asked for one: ptrace(DETACH, SIGSTOP) should leave the tracee stopped. Yes, > a new one: First signal after PTRACE_ATTACH should be SIGSTOP. This was never true, afaics. Of course, if nobody sends other signals to the tracee then SIGSTOP will be the first signal, but only because there are no other signals which could be dequeued/reported. > > > > It is not trivial to implement, and I don't understand why > > > > it is important to keep this behaviour. But we have the test > > > > case which checks this: attach-into-signal. > > > > > > This testcase is in fact PASSing even when non-SIGSTOP signal is sent as the > > > first one after PTRACE_ATTACH. It has specific handling of such cases. > > > > This test-case also does: > > > > /* detach with SIGPIPE/attach. This should kill tracee */ > > ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); > > > > ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); > > > > waitpid (child, &status, 0); > > assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); > > > > It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what > > I can't understand. > > attach-info-signal from the ptrace-testsuite does not FAIL for me. Which > kernel version does it FAIL on for you? It fails on ptrace-over-utrace. And I can't understand why this behaviour is important. I hope it is not. Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). Currently, if the next thacer attaches right after this detach it has no way to intercept SIGXXX, it will be never reported via ptrace_signal(). Is this really important? Do you know any application which can be broken if we change this behaviour? With the current utrace-ptrace implementation SIGXXX can be reported to the new tracer. OK, this relates to "the first signal should be SIGSTOP" but this is wrong anyway, and the case above is very unlikely. Oleg. From jan.kratochvil at redhat.com Tue Oct 6 14:39:11 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 6 Oct 2009 16:39:11 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006131010.GA5906@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> Message-ID: <20091006143911.GA7071@host0.dyn.jankratochvil.net> On Tue, 06 Oct 2009 15:10:10 +0200, Oleg Nesterov wrote: > On 10/06, Jan Kratochvil wrote: > > On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: > > > On 10/05, Jan Kratochvil wrote: > > > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > > > > > > They should not, this is just wrong. > > > > That may be a right point but such programs are in use out there. Sure if it > > would be a real difficulty one can keep it as-is as GDB-7.0 soon to be > > released has it already fixed, strace works with it. Still ltrace crashes the > > inferior in such case. > > Confused. Do you mean we should fix the kernel to match this > expectation? Yes, I was thinking it would be a good idea. > This was never true. I agree. > You attached the test-case which sends SIGALRM to itself in a loop. > If the tracer attaches to this program, it is very possible that > SIGALRM will be reported, not SIGSTOP. Yes. And the real world tracers do not expect so. > > > This test-case also does: > > > > > > /* detach with SIGPIPE/attach. This should kill tracee */ > > > ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); > > > > > > ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); > > > > > > waitpid (child, &status, 0); > > > assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); > > > > > > It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what > > > I can't understand. Second keyword "PTRACE_ATTACH" is on line 167. First keyword "SIGPIPE" is on line 199. Line 167 cannot see anything from line 199. Assuming you did mean "third PTRACE_ATTACH". Line 222: if (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE) Line 227: assert (WIFSTOPPED (status)); Line 228: assert (WSTOPSIG (status) == SIGSTOP); Yes, I agree with the current general behavior of ptrace there is missing: if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > It fails on ptrace-over-utrace. Attached, I do not have kernel.rpm with ptrace-over-utrace ready, please verify it and check it in (or ping me or so). > Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). > Currently, if the next thacer attaches right after this detach it has no > way to intercept SIGXXX, it will be never reported via ptrace_signal(). No matter if it gets reported to the new tracer still SIGXXX should never get lost. If it is not reported to the new tracer then it will be always processed by the tracee, is it right? > Is this really important? Do you know any application which can be > broken if we change this behaviour? With the current utrace-ptrace > implementation SIGXXX can be reported to the new tracer. I think there is no application which would handle non-SIGSTOP as the first signal after PTRACE_ATTACH while it would get confused by getting non-SIGSTOP signal as the first one after PTRACE_ATTACH after PTRACE_DETACH. > OK, this relates to "the first signal should be SIGSTOP" but this > is wrong anyway, and the case above is very unlikely. If "the first signal should be SIGSTOP" is not satisfied (current state) I think you can freely change this behavior whether SIGXXX will be reported to the new tracer and we should apply the attached ptrace-testsuite patch. If "the first signal should be SIGSTOP" gets fixed/satisfied (proposed state) I think it is clear SIGXXX from PTRACE_DETACH must not be lost and it must not be visible as the first signal after PTRACE_ATTACH. In such case the ptrace-testsuite testcase attach-into-signal should be simplified a lot to always just require SIGSTOP as the first signal after PTRACE_ATTACH and the attached change gets irrelevant in such case. Thanks, Jan -------------- next part -------------- --- attach-into-signal.c 31 Jan 2009 21:11:40 -0000 1.5 +++ attach-into-signal.c 6 Oct 2009 14:27:08 -0000 @@ -224,6 +224,18 @@ static void reproduce (void) child = 0; return; } + /* SIGPIPE was still pending and it has not been yet delivered. */ + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) + { + /* Deliver it and get the queued SIGSTOP. */ + errno = 0; + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); + assert_perror (errno); + + errno = 0; + pid = waitpid (child, &status, 0); + assert (pid == child); + } assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); /* let tracee run. it must be killed very soon by SIGPIPE */ From oleg at redhat.com Tue Oct 6 16:55:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 18:55:06 +0200 Subject: [PATCH 71] RFC, fix ptrace(PTRACE_DETACH, signr) logic Message-ID: <20091006165506.GA29043@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Tue, 06 Oct 2009 15:10:10 +0200, Oleg Nesterov wrote: > > Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). > > Currently, if the next thacer attaches right after this detach it has no > > way to intercept SIGXXX, it will be never reported via ptrace_signal(). >^ > No matter if it gets reported to the new tracer still SIGXXX should never get > lost. OK, great. Roland, do you agree? If yes, perhaps we can avoid ptrace_utrace_detached_ops logic? At least for the first version which can be sent to lkml. If the tracer does ptrace(DETACH, SIGNR) - just send this signal, that is all. If the tracer exits (valid_signal() == F), send the already reported signal. Otherwise, if the tracee didn't report a signal - do nothing. What do you think? --- kernel/ptrace.c | 36 +++++++++++++++++++++++++++++++----- 1 file changed, 31 insertions(+), 5 deletions(-) --- PU/kernel/ptrace.c~71_PARTLY_FIX_DETACH 2009-10-06 02:25:02.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-06 18:12:12.000000000 +0200 @@ -82,6 +82,33 @@ static struct utrace_engine *ptrace_look &ptrace_utrace_ops, NULL); } +static void detach_signal(struct task_struct *tracee, + struct ptrace_context *context, int sig) +{ + siginfo_t *info = NULL; + + switch (get_stop_code(context)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (valid_signal(sig)) + info = SEND_SIG_PRIV; + break; + + case PTRACE_EVENT_SIGNAL: + if (valid_signal(sig) && sig != context->signr) + info = SEND_SIG_NOINFO; + else + info = context->siginfo; + break; + } + + // XXX: if info == context->siginfo we can race with SIGKILL, + // but afaics this is harmless ? send_sig_info() uses *info + // under ->siglock, the worst case SIGKILL will be sent twice. + if (info) + send_sig_info(sig, info, tracee); +} + static void ptrace_detach_task(struct task_struct *child, int sig) { struct utrace_engine *engine = ptrace_lookup_engine(child); @@ -90,6 +117,9 @@ static void ptrace_detach_task(struct ta if (unlikely(IS_ERR(engine))) return; + if (sig) + detach_signal(child, ptrace_context(engine), sig); + ret = utrace_control(child, engine, UTRACE_DETACH); WARN_ON(ret && ret != -EINPROGRESS && ret != -ESRCH && ret != -EALREADY); @@ -668,12 +698,8 @@ static void ptrace_do_detach(struct task */ detach = tracee->ptrace != 0; release = false; - if (likely(detach)) { - // XXX: temporary hack - if (data && valid_signal(data)) - send_sig(data, tracee, 1); + if (likely(detach)) release = __ptrace_detach(current, tracee); - } write_unlock_irq(&tasklist_lock); if (unlikely(release)) From oleg at redhat.com Tue Oct 6 17:14:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 19:14:28 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006143911.GA7071@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> Message-ID: <20091006171428.GA29055@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Tue, 06 Oct 2009 15:10:10 +0200, Oleg Nesterov wrote: > > On 10/06, Jan Kratochvil wrote: > > > On Mon, 05 Oct 2009 21:00:37 +0200, Oleg Nesterov wrote: > > > > On 10/05, Jan Kratochvil wrote: > > > > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > > > > > > > > They should not, this is just wrong. > > > > > > That may be a right point but such programs are in use out there. Sure if it > > > would be a real difficulty one can keep it as-is as GDB-7.0 soon to be > > > released has it already fixed, strace works with it. Still ltrace crashes the > > > inferior in such case. > > > > Confused. Do you mean we should fix the kernel to match this > > expectation? > > Yes, I was thinking it would be a good idea. OK. Let's see what Roland thinks. Hmm. I guess with utrace it will be simple to do this change... Instead of sending SIGSTOP, PTRACE_ATACH can mark the new ptrace_context as "just attached" and trigger UTRACE_INTERRUPT, ptrace_report_signal() can synthesize SIGSTOP itself. But not in the first version. > > > > This test-case also does: > > > > > > > > /* detach with SIGPIPE/attach. This should kill tracee */ > > > > ptrace (PTRACE_DETACH, child, (void *) 1, (void *) SIGPIPE); > > > > > > > > ptrace (PTRACE_ATTACH, child, (void *) 0, (void *) 0); > > > > > > > > waitpid (child, &status, 0); > > > > assert (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE); > > > > > > > > It fails if the second PTRACE_ATTACH sees SIGPIPE. This is what > > > > I can't understand. > > Second keyword "PTRACE_ATTACH" is on line 167. > First keyword "SIGPIPE" is on line 199. > Line 167 cannot see anything from line 199. > > Assuming you did mean "third PTRACE_ATTACH". Yes, > Line 222: if (WIFSIGNALED (status) && WTERMSIG (status) == SIGPIPE) > Line 227: assert (WIFSTOPPED (status)); > Line 228: assert (WSTOPSIG (status) == SIGSTOP); > > Yes, I agree with the current general behavior of ptrace there is missing: > if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) Hmm, not sure, but I am almost sleeping ;) I mean, the test-case looks correct wrt current implemantation of ptrace. But see below. > > It fails on ptrace-over-utrace. > > Attached, I do not have kernel.rpm with ptrace-over-utrace ready, please > verify it and check it in (or ping me or so). ptrace-over-utrace is under development, not finished yet. > > Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). > > Currently, if the next thacer attaches right after this detach it has no > > way to intercept SIGXXX, it will be never reported via ptrace_signal(). > > No matter if it gets reported to the new tracer still SIGXXX should never get > lost. Great. > If it is not reported to the new tracer then it will be always > processed by the tracee, is it right? Yes, sure. (But, just in case... if the tracer does ptrace(DETACH, SIGNR), this signr only matters if the tracee was stopped after reporting syscall or signal, otherwise SIGNR is ignored). > > OK, this relates to "the first signal should be SIGSTOP" but this > > is wrong anyway, and the case above is very unlikely. > > If "the first signal should be SIGSTOP" is not satisfied (current state) > I think you can freely change this behavior whether SIGXXX will be reported to > the new tracer and we should apply the attached ptrace-testsuite patch. Good. > If "the first signal should be SIGSTOP" gets fixed/satisfied (proposed state) > I think it is clear SIGXXX from PTRACE_DETACH must not be lost and it must not > be visible as the first signal after PTRACE_ATTACH. Agreed. > --- attach-into-signal.c 31 Jan 2009 21:11:40 -0000 1.5 > +++ attach-into-signal.c 6 Oct 2009 14:27:08 -0000 > @@ -224,6 +224,18 @@ static void reproduce (void) > child = 0; > return; > } > + /* SIGPIPE was still pending and it has not been yet delivered. */ > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > + { > + /* Deliver it and get the queued SIGSTOP. */ > + errno = 0; > + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); > + assert_perror (errno); > + > + errno = 0; > + pid = waitpid (child, &status, 0); > + assert (pid == child); > + } Yes, I didn't verify this yet, but I think with this patch the test-case should succeed with utrace-ptrace kernel. Thanks Jan. Oleg. From oleg at redhat.com Tue Oct 6 17:29:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 19:29:57 +0200 Subject: [PATCH 71] RFC, fix ptrace(PTRACE_DETACH, signr) logic In-Reply-To: <20091006165506.GA29043@redhat.com> References: <20091006165506.GA29043@redhat.com> Message-ID: <20091006172957.GA30361@redhat.com> Forgot to mention... I didn't test this patch and it is in fact buggy, we should set sig = context->siginfo->si_signo when !valid_signal(sig). This is just RFC to know what do you think. On 10/06, Oleg Nesterov wrote: > > On 10/06, Jan Kratochvil wrote: > > > > On Tue, 06 Oct 2009 15:10:10 +0200, Oleg Nesterov wrote: > > > Once again. Suppose that the tracer does ptrace(PTRACE_DETACH, SIGXXX). > > > Currently, if the next thacer attaches right after this detach it has no > > > way to intercept SIGXXX, it will be never reported via ptrace_signal(). > >^ > > No matter if it gets reported to the new tracer still SIGXXX should never get > > lost. > > OK, great. Roland, do you agree? > > If yes, perhaps we can avoid ptrace_utrace_detached_ops logic? At least > for the first version which can be sent to lkml. > > If the tracer does ptrace(DETACH, SIGNR) - just send this signal, that > is all. > > If the tracer exits (valid_signal() == F), send the already reported > signal. Otherwise, if the tracee didn't report a signal - do nothing. > > What do you think? > > --- > > kernel/ptrace.c | 36 +++++++++++++++++++++++++++++++----- > 1 file changed, 31 insertions(+), 5 deletions(-) > > --- PU/kernel/ptrace.c~71_PARTLY_FIX_DETACH 2009-10-06 02:25:02.000000000 +0200 > +++ PU/kernel/ptrace.c 2009-10-06 18:12:12.000000000 +0200 > @@ -82,6 +82,33 @@ static struct utrace_engine *ptrace_look > &ptrace_utrace_ops, NULL); > } > > +static void detach_signal(struct task_struct *tracee, > + struct ptrace_context *context, int sig) > +{ > + siginfo_t *info = NULL; > + > + switch (get_stop_code(context)) { > + case PTRACE_EVENT_SYSCALL_ENTRY: > + case PTRACE_EVENT_SYSCALL_EXIT: > + if (valid_signal(sig)) > + info = SEND_SIG_PRIV; > + break; > + > + case PTRACE_EVENT_SIGNAL: > + if (valid_signal(sig) && sig != context->signr) > + info = SEND_SIG_NOINFO; > + else > + info = context->siginfo; > + break; > + } > + > + // XXX: if info == context->siginfo we can race with SIGKILL, > + // but afaics this is harmless ? send_sig_info() uses *info > + // under ->siglock, the worst case SIGKILL will be sent twice. > + if (info) > + send_sig_info(sig, info, tracee); > +} > + > static void ptrace_detach_task(struct task_struct *child, int sig) > { > struct utrace_engine *engine = ptrace_lookup_engine(child); > @@ -90,6 +117,9 @@ static void ptrace_detach_task(struct ta > if (unlikely(IS_ERR(engine))) > return; > > + if (sig) > + detach_signal(child, ptrace_context(engine), sig); > + > ret = utrace_control(child, engine, UTRACE_DETACH); > WARN_ON(ret && ret != -EINPROGRESS && > ret != -ESRCH && ret != -EALREADY); > @@ -668,12 +698,8 @@ static void ptrace_do_detach(struct task > */ > detach = tracee->ptrace != 0; > release = false; > - if (likely(detach)) { > - // XXX: temporary hack > - if (data && valid_signal(data)) > - send_sig(data, tracee, 1); > + if (likely(detach)) > release = __ptrace_detach(current, tracee); > - } > write_unlock_irq(&tasklist_lock); > > if (unlikely(release)) From oleg at redhat.com Tue Oct 6 17:46:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 19:46:07 +0200 Subject: [PATCH 71] RFC, fix ptrace(PTRACE_DETACH, signr) logic In-Reply-To: <20091006172957.GA30361@redhat.com> References: <20091006165506.GA29043@redhat.com> <20091006172957.GA30361@redhat.com> Message-ID: <20091006174607.GA3018@redhat.com> Damn, sorry for noise. On 10/06, Oleg Nesterov wrote: > > Forgot to mention... > > I didn't test this patch and it is in fact buggy, we should > set sig = context->siginfo->si_signo when !valid_signal(sig). Heh. And I just realized SEND_SIG_NOINFO == NULL, so this patch can't work. But I think it is clear what it should do. off-topic, but can't resist. Personally I don't like the fact SEND_SIG_NOINFO == NULL. Regardless of this patch, what do you think if we change these SEND_XXX defines so that no one can be confused with NULL ? Oleg. From jan.kratochvil at redhat.com Tue Oct 6 19:25:50 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 6 Oct 2009 21:25:50 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006171428.GA29055@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> Message-ID: <20091006192550.GA4784@host0.dyn.jankratochvil.net> On Tue, 06 Oct 2009 19:14:28 +0200, Oleg Nesterov wrote: > On 10/06, Jan Kratochvil wrote: [...] > > If it is not reported to the new tracer then it will be always > > processed by the tracee, is it right? > > Yes, sure. > > (But, just in case... if the tracer does ptrace(DETACH, SIGNR), this > signr only matters if the tracee was stopped after reporting syscall > or signal, otherwise SIGNR is ignored). In which specific cases SIGNR can get ignored? Whole PTRACE_DETACH will be ignored if the tracee is not stopped. It SIGNR will be proabably ignored if the tracee is now dead. Otherwise SIGNR should get delivered, shouldn't it? > > + /* SIGPIPE was still pending and it has not been yet delivered. */ > > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) [...] > Yes, I didn't verify this yet, but I think with this patch the > test-case should succeed with utrace-ptrace kernel. Checked-in. Thanks, Jan From jan.kratochvil at redhat.com Tue Oct 6 19:59:03 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 6 Oct 2009 21:59:03 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091005023208.GA23901@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> Message-ID: <20091006195903.GA19688@host0.dyn.jankratochvil.net> On Mon, 05 Oct 2009 04:32:08 +0200, Oleg Nesterov wrote: [...] > Firstly, I think we should un-revert edaba2c5334492f82d39ec35637c6dea5176a977. > This unconditional wakeup is hopelessly wrong imho, and it is removed > from utrace-ptrace code. But this breaks another test-case, > attach-wait-on-stopped. I still think this test-case is wrong. > We had a lengthy discussion about this. > > Now, this patch > > --- TTT_32/kernel/signal.c~PT_STOP 2009-10-04 04:08:36.000000000 +0200 > +++ TTT_32/kernel/signal.c 2009-10-05 03:17:39.000000000 +0200 > @@ -1708,7 +1708,7 @@ static int do_signal_stop(int signr) > */ > if (sig->group_stop_count) { > if (!--sig->group_stop_count) > - sig->flags = SIGNAL_STOP_STOPPED; > + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; > current->exit_code = sig->group_exit_code; > __set_current_state(TASK_STOPPED); > } > > fixes the tests above. Of course this change is not enough, I did > it just to verify I really understand what happens. > > Except, stopped-attach-transparency prints > > Excessive waiting SIGSTOP after the second attach/detach > > afaics the test-case is not right here. attach_detach() leaves the > traced threads in STOPPED state, why pid_notifying_sigstop() should > fail? Tried the patch above: http://koji.fedoraproject.org/scratch/jkratoch/task_1730038/ but it does not break stopped-attach-transparency for me. Should I also apply back edaba2c5334492f82d39ec35637c6dea5176a977? Not sure which combination are you interested in, please provide a patchset or a koji build if you have a suspection on buggy ptrace testcases. Thanks, Jan From oleg at redhat.com Tue Oct 6 20:05:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 6 Oct 2009 22:05:16 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006192550.GA4784@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> Message-ID: <20091006200516.GA3892@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Tue, 06 Oct 2009 19:14:28 +0200, Oleg Nesterov wrote: > > On 10/06, Jan Kratochvil wrote: > [...] > > > If it is not reported to the new tracer then it will be always > > > processed by the tracee, is it right? > > > > Yes, sure. > > > > (But, just in case... if the tracer does ptrace(DETACH, SIGNR), this > > signr only matters if the tracee was stopped after reporting syscall > > or signal, otherwise SIGNR is ignored). > > In which specific cases SIGNR can get ignored? > > Whole PTRACE_DETACH will be ignored if the tracee is not stopped. > It SIGNR will be proabably ignored if the tracee is now dead. > Otherwise SIGNR should get delivered, shouldn't it? No (afaics). For example, the tracee reports PTRACE_EVENT_EXEC and stops. In this case SIGNR has no effect after PTRACE_CONT/DETACH/etc. SIGNR does not ignored after the tracee reported syscall entry/exit or signal. If you think this should be changed, please tell. As always, I do not know if it was supposed or not. (and in fact I should re-check my understanding after sleep). > > > + /* SIGPIPE was still pending and it has not been yet delivered. */ > > > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > [...] > > Yes, I didn't verify this yet, but I think with this patch the > > test-case should succeed with utrace-ptrace kernel. > > Checked-in. Thanks! Oleg. From jan.kratochvil at redhat.com Tue Oct 6 20:17:01 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Tue, 6 Oct 2009 22:17:01 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006200516.GA3892@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> <20091006200516.GA3892@redhat.com> Message-ID: <20091006201701.GA8624@host0.dyn.jankratochvil.net> On Tue, 06 Oct 2009 22:05:16 +0200, Oleg Nesterov wrote: > For example, the tracee reports PTRACE_EVENT_EXEC and stops. In this > case SIGNR has no effect after PTRACE_CONT/DETACH/etc. > > SIGNR does not ignored after the tracee reported syscall entry/exit or > signal. OK, if only such exceptional cases as PTRACE_EVENT_EXEC that should not matter I think. It should work also for PTRACE_SINGLESTEP. Thanks, Jan From roland at redhat.com Wed Oct 7 06:34:33 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 6 Oct 2009 23:34:33 -0700 (PDT) Subject: [PATCH 59] make sure SINGLESTEP doesn't miss SYSCALL_EXIT In-Reply-To: Oleg Nesterov's message of Friday, 25 September 2009 02:49:32 +0200 <20090925004932.GA11247@redhat.com> References: <20090925004932.GA11247@redhat.com> Message-ID: <20091007063433.E869EF4A@magilla.sf.frob.com> Sorry I'm so long in following up on this. I know you've hacked a lot more since. > The vanilla kernel relies on syscall_trace_leave() which does > send_sigtrap(TRAP_BRKPT). But with utrace-ptrace the tracee sleeps > in do_notify_resume() path, syscall_trace_leave() won't be called. It's even weirder than this, in nonobvious ways. I'm not even sure I'm saying anything contrary to what you've coded for, but I want to be clear and explicit about everything. I'm concerned we might accidentally code to quirks of the x86 implementation details where we should instead make the arch tracehook calls' interface contracts more clear and make sure everything we do in generic utrace and ptrace layers jibes in theory and not just in observed x86 behavior. What happens today in the vanilla x86 kernel is this: 1. user_enable_single_step -> TIF_SINGLESTEP done to user state before a syscall insn makes sure (if nothing else) we'll hit syscall_trace_leave after sys_foo returns. 1b. If done to a thread state of "in the syscall" as in syscall-entry, clone, or exec report, that too makes sure we get there even if we hadn't been single-stepping into the syscall insn. 2. syscall_trace_leave -> tracehook_report_syscall_exit ->... ptrace_stop 3a. user_enable_single_step -> TIF_SINGLESTEP (was already and still is set) 3b. user_disable_single_step (PTRACE_CONT et al) -> clear TIF_SINGLESTEP 4. tracehook_report_syscall_exit returns to syscall_trace_leave -> 5a. (if 3a) test_thread_flag(TIF_SINGLESTEP)=>1 -> send_sigtrap 5b. (if 3b) test_thread_flag(TIF_SINGLESTEP)=>0 -> no signal, no stop 6. (if 5a) do_notify_resume -> dequeue SIGTRAP, ptrace_signal->ptrace_stop I found it nonobvious that what we really do is ptrace_stop inside tracehook_report_syscall_exit and then upon resumption look afresh at TIF_SINGLESTEP to determine whether we really send a SIGTRAP. Note that #6 could always be preceded e.g. by a dequeue of SIGHUP, ptrace_stop for that, handler setup for that with its own ptrace_notify() stop--not really a signal and so not touching the queued SIGTRAP--inside tracehook_signal_handler (if used PTRACE_SINGLESTEP,SIGHUP to enter the handler), etc., so the "stepped" state finally observed at the signal stop for that SIGTRAP could be wildly different from the post-syscall state. In comparison, on powerpc it is the same up to #2 and then do_syscall_trace_leave does: step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); And that's it. (x86 in #2 always calls it with step=0.) Vanilla tracehook_report_syscall_exit in fact ignores the step flag, though I thought at some point before it had a "ptrace_notify(SIGTRAP)" there. So on powerpc, PTRACE_SINGLESTEP done from the syscall-exit stop will not give an immediate (fake) single-step trap at the immediate post-syscall insn, but just single-step the next one insn (I think). I'm sure nobody intended this to be an arch difference, and I'm not sure how much we are really stuck with either choice in particular for application compatibility on one arch or the other. There is no particular reason for one arch to queue a SIGTRAP and another to use tracehook_report_syscall_exit for single-step cases, just the taste of each arch maintainer. IIRC there were even different opinions about whether PTRACE_SINGLESTEP producing a SYSGOOD-style SIGTRAP|0x80 when you happened to step over a syscall insn was a helpful feature giving one more bit of information or an unhelpful bug making PTRACE_SINGLESTEP behave inconsistently with one particular sort of user insn vs all others. I didn't want to keep arguing it out at the time. I included the step flag when formulating tracehook_report_syscall_exit with the hope that arch maintainers could be easily convinced to pass in that flag so at least future generic code (utrace, whatever) could have enough information for whatever behavior we wanted without more arch work. That much seems almost to have panned out (some arch's do pass in that flag). (Probably the biggest reason that x86 does what it does and others don't is just that it has the send_sigtrap() helper so it's a clean-looking one-line call.) As to the ptrace behavior, I don't think it much matters one way or the other about the two stops. If you just used PTRACE_SYSCALL (twice) and so are now at the syscall-exit stop, and then use PTRACE_SINGLESTEP, you really don't need an extra stop with exactly the same register state. The only thing that can happen is a signal, and ptrace is always going to give you an intervening stop for that anyway. OTOH, I never thought it was right to give a SYSGOOD status code in response to PTRACE_SINGLESTEP that happens to be over a syscall insn, so neither the x86 status quo nor the powerpc status quo really floats my boat. The tracehook and utrace layers have yet another set of considerations that never came up with ptrace. You can't use both PTRACE_SINGLESTEP and PTRACE_SYSCALL and simultaneously. But in utrace you can single-step and get syscall-exit callbacks, either both by one engine or some engines doing one and some doing the other. I don't have any conclusions or prescriptions about any of this right at the moment. It just seems important to cite that all this is kicking around to begin with before I threw in the new wrinkle of utrace not wanting to stop inside tracehook_report_syscall_exit but instead only later after its caller will have returned. > - perhaps it makes sense to change force_sig_info() to use > lock_task_sighand(), then we can avoid taking taskist around > send_sigtrap(). This feels like an indicator that it would be better to call send_sigtrap in the tracee instead. > > - I guess, we should also send SIGTRAP when SINGLESTEP resumes > > the tracee from SYSCALL_EXIT stop. This is trivial, but I need > > to write the test-case first. > > Yes, with this change the kernel passes all tests plus the test-case > below. I wrote it because I lost the hope to understand the required > behaviour ;) We should get a case for this into ptrace-tests and then look into (with Jan) what we want to do about consistency across arch's. > Note also the couple of "assert(regs.rax == -ENOSYS)" which were commented > out, here we differ from vanilla kernel and this can't be "fixed". But, > as you pointed out previously, we do not need to be bug-compatible here. Right. The test can assert(regs.rax == -ENOSYS || regs.rax == child_pid). We want those sites clearly commented to go along with the explanation to upstream about the intentional semantics change. Thanks, Roland From roland at redhat.com Wed Oct 7 06:45:47 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 6 Oct 2009 23:45:47 -0700 (PDT) Subject: [PATCH 53-56] kill ->ev_array + fix stepping In-Reply-To: Oleg Nesterov's message of Friday, 2 October 2009 00:45:22 +0200 <20091001224522.GA15997@redhat.com> References: <20091001224522.GA15997@redhat.com> Message-ID: <20091007064547.0A94FF4A@magilla.sf.frob.com> > On top of 4492770dc8d2312da9518e8b85fb0e49dc3da510 in your > utrace-ptrace branch. I had done an upstream merge since then and also merged some more of yours. So to get utrace-ptrace back to a state where 53-70 apply cleanly, I reverted these first: 6752625 introduce context_siginfo() helper d43a453 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL e4e48df ptrace_resume_signal() should use context->siginfo under ->siglock We could be nearing the point where it would be easier if you were using a GIT repository directly that I can pull from. But it was in fact no real problem to recover how to merge this time, so you still don't need to worry about that if you don't want to. Right now my trees fork from v2.6.32-rc3 and include 53-70: fbd4368 kill context->ev_array[] ba73824 ptrace_resume: don't ignore "data" argument a55d174 implement the stacked SYSCALL_EXIT event 08f4a21 fix the stepping over syscall d0ed18d do_ptrace_notify_stop: backport the "sync wakeup" logic 842684f do_ptrace_notify_stop: fix the race with SIGKILL e90cb71 don't use task_struct->ptrace_message 0768d89 UTRACE_SIGNAL_HANDLER should never see ->siginfo != NULL c625793 move "resume signal" logic into the tracee's context e7ac055 introduce ptrace_rw_siginfo() helper 53187be convert ptrace_getsiginfo() to use ptrace_rw_siginfo() 4e09fe3 convert ptrace_setsiginfo() to use ptrace_rw_siginfo() 47b5e2c don't clear context->ev_code for debugging 313bad1 introduce syscall_code(context) helper 3f48297 introduce get_stop_code(context) helper df7c8f2 encode internal stop events in ->ev_code too 4c99287 kill context->ev_name f83b2ca move "event << 8" into syscall_code() For whatever review comments I may have about these (to follow shortly), I'll just expect you to incorporate those issues into later cleanups. Thanks, Roland From roland at redhat.com Wed Oct 7 06:50:43 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 6 Oct 2009 23:50:43 -0700 (PDT) Subject: [PATCH 59] don't use task_struct->ptrace_message In-Reply-To: Oleg Nesterov's message of Saturday, 3 October 2009 03:57:53 +0200 <20091003015753.GA15049@redhat.com> References: <20091003015753.GA15049@redhat.com> Message-ID: <20091007065043.19D35F4A@magilla.sf.frob.com> > task_struct->ptrace_message is no longer needed. Woo! > I wonder why compat_ptrace_request() does "(compat_ulong_t)ptrace_message", > put_user(x, ptr) uses __typeof__(*ptr). I think it's just being explicit about the truncation to keep its intent clear to someone reading the code. Thanks, Roland From roland at redhat.com Wed Oct 7 07:06:10 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 00:06:10 -0700 (PDT) Subject: [PATCH 62] introduce ptrace_rw_siginfo() helper In-Reply-To: Oleg Nesterov's message of Saturday, 3 October 2009 04:00:35 +0200 <20091003020035.GA15213@redhat.com> References: <20091003020035.GA15213@redhat.com> Message-ID: <20091007070610.D046BF4A@magilla.sf.frob.com> > +static int ptrace_rw_siginfo(struct task_struct *tracee, > + struct ptrace_context *context, > + siginfo_t *info, bool write) > +{ > + unsigned long flags; > + siginfo_t *context_info; > + int err = -ESRCH; > + > + if (!lock_task_sighand(tracee, &flags)) > + return err; > + /* > + * Make sure the compiler reads ->siginfo only once, if we race > + * with SIGKILL ->siginfo can be cleared under us. But the memory > + * it points to can't go away, and since we hold ->siglock we can't > + * race with get_signal_to_deliver() pathes clobber this memory. s/pathes clobber/paths that clobber/ > + * See also the comment in ptrace_report_signal(). > + */ > + context_info = ACCESS_ONCE(context->siginfo); > + if (context_info) { > + if (write) > + *context_info = *info; > + else > + *info = *context_info; > + err = 0; > + } > + unlock_task_sighand(tracee, &flags); Couldn't we instead do: context_info = ACCESS_ONCE(context->siginfo); if (context_info) { *info = *context_info; smp_rmb(); if (ACCESS_ONCE(context->siginfo)) err = 0; } and never use the siglock for the reading case? If SIGKILL races, then we see the ptr cleared later and abandon our (maybe half garbage) copy. I guess it's not worth the bother, the old code uses the siglock anyway. Thanks, Roland From roland at redhat.com Wed Oct 7 07:18:16 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 00:18:16 -0700 (PDT) Subject: [PATCH 63] convert ptrace_getsiginfo() to use ptrace_rw_siginfo() In-Reply-To: Oleg Nesterov's message of Saturday, 3 October 2009 03:58:08 +0200 <20091003015808.GA15073@redhat.com> References: <20091003015808.GA15073@redhat.com> Message-ID: <20091007071816.63210F4A@magilla.sf.frob.com> > + if (context->siginfo) > + return ptrace_rw_siginfo(tracee, context, info, false); > > - return error; > + memset(info, 0, sizeof(*info)); > + info->si_signo = SIGTRAP; > + info->si_code = context->ev_code; // XXX: ev_code was already cleared!!! > + info->si_pid = task_pid_vnr(tracee); > + info->si_uid = task_uid(tracee); Put that logic inside ptrace_rw_siginfo and call it unconditionally. It's going to check context->siginfo anyway. The forged info is a wrong lie if it's actually clear because it was set and then there was a SIGKILL, but we can't tell the difference so a race could yield that bogon anyway. It probably doesn't really matter to anyone but my pedantic streak, but if we want to avoid that bogon then we need to leave some further indication for the SIGKILL case. Then PTRACE_GETSIGINFO could just return -ESRCH to appear "after" the death by SIGKILL. Where exactly does ->siginfo get cleared in that case? I only see it cleared in the UTRACE_SIGNAL_REPORT case. But SIGKILL should not do any signal reports, it bypasses them and you might get only the DEATH event. Since you don't request UTRACE_EVENT(DEATH), you'll only get ptrace_report_quiesce with event==UTRACE_EVENT(DEATH). I don't see the path. Thanks, Roland From roland at redhat.com Wed Oct 7 07:21:16 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 00:21:16 -0700 (PDT) Subject: [PATCH 64] convert ptrace_setsiginfo() to use ptrace_rw_siginfo() In-Reply-To: Oleg Nesterov's message of Saturday, 3 October 2009 03:58:10 +0200 <20091003015810.GA15076@redhat.com> References: <20091003015810.GA15076@redhat.com> Message-ID: <20091007072116.ED801F4A@magilla.sf.frob.com> > + if (context->siginfo) > + return ptrace_rw_siginfo(tracee, context, info, true); Superfluous test, just call it unconditionally as with the get case. Then both helpers have everything in common, and they are static anyway, so you might as well just call ptrace_rw_siginfo from ptrace_request. Thanks, Roland From roland at redhat.com Wed Oct 7 07:38:43 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 00:38:43 -0700 (PDT) Subject: [PATCH 65-69] kill context->ev_name In-Reply-To: Oleg Nesterov's message of Tuesday, 6 October 2009 02:11:34 +0200 <20091006001134.GA23862@redhat.com> References: <20091006001134.GA23862@redhat.com> Message-ID: <20091007073843.A47571F1@magilla.sf.frob.com> > Naming: as usual, I agree in advance with any suggestions. The ev_ prefix no longer refers to anything inherently obvious in the code. If you want a common prefix for the struct it should be on all its fields and it should be something evocative of "struct ptrace_context". (I'm not big on common prefixes for struct fields but I understand why you like them.) I'd use "eventmsg" for the thing whose purpose is for PTRACE_GETEVENTMSG to return it. I'd use either "exit_code" or "stop_code" for the thing that either is assigned to task_struct.exit_code (now) or just acts like it for purposes of ptrace_do_wait (hopefully future). s/ev_pending/ptrace_event_pending/ s/get_stop_code/get_stop_event/ (or maybe ptrace_ctx_event) Thanks, Roland From roland at redhat.com Wed Oct 7 07:47:35 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 00:47:35 -0700 (PDT) Subject: [PATCH 70] move "event << 8" into syscall_code() In-Reply-To: Oleg Nesterov's message of Tuesday, 6 October 2009 02:32:10 +0200 <20091006003210.GA26313@redhat.com> References: <20091006003210.GA26313@redhat.com> Message-ID: <20091007074735.51CF41F1@magilla.sf.frob.com> Make it something like: static inline void set_stop_code(struct ptrace_context *ctx, int event) { ctx->stop_code = (event << 8) | SIGTRAP | (event >= PTRACE_EVENT_SYSCALL_ENTRY && (ctx->options & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0); } and pick PTRACE_EVENT_* numbers so SYSCALL_{ENTRY,EXIT} are highest, or something along those lines. Thanks, Roland From info at soft-direct.net Wed Oct 7 05:14:17 2009 From: info at soft-direct.net (Ticket Restaurant par Soft Direct) Date: Wed, 7 Oct 2009 08:14:17 +0300 Subject: =?utf-8?q?Ticket_Restaurant_-_Donnons_au_d=C3=A9jeuner_l=27impor?= =?utf-8?q?tance_qu=27il_m=C3=A9rite?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Oct 7 12:05:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 14:05:27 +0200 Subject: [PATCH 65-69] kill context->ev_name In-Reply-To: <20091007073843.A47571F1@magilla.sf.frob.com> References: <20091006001134.GA23862@redhat.com> <20091007073843.A47571F1@magilla.sf.frob.com> Message-ID: <20091007120527.GA5482@redhat.com> On 10/07, Roland McGrath wrote: > > > Naming: as usual, I agree in advance with any suggestions. > > The ev_ prefix no longer refers to anything inherently obvious in the code. > If you want a common prefix for the struct it should be on all its fields > and it should be something evocative of "struct ptrace_context". (I'm not > big on common prefixes for struct fields but I understand why you like them.) > > I'd use "eventmsg" for the thing whose purpose is for PTRACE_GETEVENTMSG to > return it. > > I'd use either "exit_code" or "stop_code" for the thing that either is > assigned to task_struct.exit_code (now) or just acts like it for purposes > of ptrace_do_wait (hopefully future). > > s/ev_pending/ptrace_event_pending/ > s/get_stop_code/get_stop_event/ (or maybe ptrace_ctx_event) OK. Oleg. From oleg at redhat.com Wed Oct 7 12:12:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 14:12:18 +0200 Subject: [PATCH 70] move "event << 8" into syscall_code() In-Reply-To: <20091007074735.51CF41F1@magilla.sf.frob.com> References: <20091006003210.GA26313@redhat.com> <20091007074735.51CF41F1@magilla.sf.frob.com> Message-ID: <20091007121218.GB5482@redhat.com> On 10/07, Roland McGrath wrote: > > Make it something like: > > static inline void set_stop_code(struct ptrace_context *ctx, int event) > { > ctx->stop_code = (event << 8) | SIGTRAP | > (event >= PTRACE_EVENT_SYSCALL_ENTRY && > (ctx->options & PTRACE_O_TRACESYSGOOD) ? 0x80 : 0); > } > > and pick PTRACE_EVENT_* numbers so SYSCALL_{ENTRY,EXIT} are highest, > or something along those lines. Oh, I don't like this. This is unreadable, and ">= PTRACE_EVENT_" complicates the reading even more. How about void set_stop_code(struct ptrace_context *ctx, int event) { ctx->stop_code = (event << 8) | SIGTRAP; } void set_syscall_code(struct ptrace_context *ctx, int event) { set_stop_code(ctx, event); if (PTRACE_O_TRACESYSGOOD) ctx->stop_code |= 0x80; } Or, void __set_stop_code(struct ptrace_context *ctx, int event, int sig) { ctx->stop_code = (event << 8) | sig; } void set_syscall_code(struct ptrace_context *ctx, int event) { int sig = PTRACE_O_TRACESYSGOOD ? (0x80 | SIGTRAP) : SIGTRAP; __set_stop_code(event, sig); } void set_stop_code(struct ptrace_context *ctx, int event) { __set_stop_code(event, SIGTRAP); } This way ptrace_report_signal() can use __set_stop_code() too. But this is minor, if your prefer your version I'll send the patch. Oleg. From oleg at redhat.com Wed Oct 7 12:18:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 14:18:58 +0200 Subject: [PATCH 59] make sure SINGLESTEP doesn't miss SYSCALL_EXIT In-Reply-To: <20091007063433.E869EF4A@magilla.sf.frob.com> References: <20090925004932.GA11247@redhat.com> <20091007063433.E869EF4A@magilla.sf.frob.com> Message-ID: <20091007121858.GA5824@redhat.com> On 10/06, Roland McGrath wrote: > > [...snip a lot of useful info...] Thanks Roland. I need to read this carefully tomorrow. > > - perhaps it makes sense to change force_sig_info() to use > > lock_task_sighand(), then we can avoid taking taskist around > > send_sigtrap(). > > This feels like an indicator that it would be better to call send_sigtrap > in the tracee instead. Yes. Note the changelog for 08f4a21cd6d169942b3b6eb56cd10c5a8e84001b, I think we can move this into ptrace_report_siganl(). But hopefully this hack is OK for the first version. Oleg. From oleg at redhat.com Wed Oct 7 12:47:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 14:47:33 +0200 Subject: [PATCH 62] introduce ptrace_rw_siginfo() helper In-Reply-To: <20091007070610.D046BF4A@magilla.sf.frob.com> References: <20091003020035.GA15213@redhat.com> <20091007070610.D046BF4A@magilla.sf.frob.com> Message-ID: <20091007124733.GA6898@redhat.com> On 10/07, Roland McGrath wrote: > > > +static int ptrace_rw_siginfo(struct task_struct *tracee, > > + struct ptrace_context *context, > > + siginfo_t *info, bool write) > > +{ > > + unsigned long flags; > > + siginfo_t *context_info; > > + int err = -ESRCH; > > + > > + if (!lock_task_sighand(tracee, &flags)) > > + return err; > > + /* > > + * Make sure the compiler reads ->siginfo only once, if we race > > + * with SIGKILL ->siginfo can be cleared under us. But the memory > > + * it points to can't go away, and since we hold ->siglock we can't > > + * race with get_signal_to_deliver() pathes clobber this memory. > > s/pathes clobber/paths that clobber/ Thanks, > > + * See also the comment in ptrace_report_signal(). > > + */ > > + context_info = ACCESS_ONCE(context->siginfo); > > + if (context_info) { > > + if (write) > > + *context_info = *info; > > + else > > + *info = *context_info; > > + err = 0; > > + } > > + unlock_task_sighand(tracee, &flags); > > Couldn't we instead do: > > context_info = ACCESS_ONCE(context->siginfo); > if (context_info) { > *info = *context_info; > smp_rmb(); > if (ACCESS_ONCE(context->siginfo)) > err = 0; I don't think this can work. context->siginfo can be cleared and then set again in between. If we race with SIGKILL, utrace_get_signal() can dequeue another signal != SIGKILL and start the reporting loop. I thought about *info = *context_info; rmb(); if (fatal_ignal_pending(tracee)) return -ERR; But I think it is better to do theses cleanups after V1. See also my reply to next reviews. Oleg. From oleg at redhat.com Wed Oct 7 13:12:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 15:12:13 +0200 Subject: [PATCH 63] convert ptrace_getsiginfo() to use ptrace_rw_siginfo() In-Reply-To: <20091007071816.63210F4A@magilla.sf.frob.com> References: <20091003015808.GA15073@redhat.com> <20091007071816.63210F4A@magilla.sf.frob.com> Message-ID: <20091007131213.GB6898@redhat.com> On 10/07, Roland McGrath wrote: > > > + if (context->siginfo) > > + return ptrace_rw_siginfo(tracee, context, info, false); > > > > - return error; > > + memset(info, 0, sizeof(*info)); > > + info->si_signo = SIGTRAP; > > + info->si_code = context->ev_code; // XXX: ev_code was already cleared!!! > > + info->si_pid = task_pid_vnr(tracee); > > + info->si_uid = task_uid(tracee); > > Put that logic inside ptrace_rw_siginfo and call it unconditionally. (and from the next review of PATCH 64) > Then both helpers have everything in common, and they are static anyway, > so you might as well just call ptrace_rw_siginfo from ptrace_request. I mostly agree, but I'd like to keep this helper for now. I am not sure yet, but perhaps it will be needed if we change detach to play with ptrace_utrace_detached_ops. This was a reason why I added the separate helper. But let me repeat I am not sure it will be really needed. > It's > going to check context->siginfo anyway. The forged info is a wrong lie if > it's actually clear because it was set and then there was a SIGKILL, but we > can't tell the difference so a race could yield that bogon anyway. Yes. I swear, I was going to do if (get_stop_code() == PTRACE_EVENT_SIGNAL) return ptrace_rw_siginfo(); instead, not sure why I used ->siginfo != NULL. This way, when we call ptrace_rw_siginfo() we know that ->siginfo must be valid. But if we race with SIGKILL and ->siginfo was not cleared yet we can return the wrong info which was filled by the next dequeue_signal(). I'll recheck this, but looks like we have anotrher reason for fatal_signal_pending() in ptrace_rw_siginfo(). Or, we can change ptrace_report_signal() (or even utrace_get_signal()) to check __fatal_signal_pending(). > Where exactly does ->siginfo get cleared in that case? I only see it > cleared in the UTRACE_SIGNAL_REPORT case. But SIGKILL should not do any > signal reports, it bypasses them and you might get only the DEATH event. It does, or I missed something. Yes, if utrace_get_signal() dequeues SIGKILL it doesn't report and just returns. But, ptrace_report_signal() does: context->siginfo = info; /* * context->siginfo points to the caller's stack. * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->siginfo before return from get_signal_to_deliver(). */ utrace_control(task, engine, UTRACE_INTERRUPT); this means that, even if killed, the tracee will call utrace_get_signal() with utrace->interrupt == T. In this case UTRACE_SIGNAL_REPORT will be reported anyway. Right? Oleg. From oleg at redhat.com Wed Oct 7 13:23:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 15:23:07 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091006195903.GA19688@host0.dyn.jankratochvil.net> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091006195903.GA19688@host0.dyn.jankratochvil.net> Message-ID: <20091007132307.GA9721@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Mon, 05 Oct 2009 04:32:08 +0200, Oleg Nesterov wrote: > [...] > > Firstly, I think we should un-revert edaba2c5334492f82d39ec35637c6dea5176a977. > > This unconditional wakeup is hopelessly wrong imho, and it is removed > > from utrace-ptrace code. But this breaks another test-case, > > attach-wait-on-stopped. I still think this test-case is wrong. > > We had a lengthy discussion about this. > > > > Now, this patch > > > > --- TTT_32/kernel/signal.c~PT_STOP 2009-10-04 04:08:36.000000000 +0200 > > +++ TTT_32/kernel/signal.c 2009-10-05 03:17:39.000000000 +0200 > > @@ -1708,7 +1708,7 @@ static int do_signal_stop(int signr) > > */ > > if (sig->group_stop_count) { > > if (!--sig->group_stop_count) > > - sig->flags = SIGNAL_STOP_STOPPED; > > + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; > > current->exit_code = sig->group_exit_code; > > __set_current_state(TASK_STOPPED); > > } > > > > fixes the tests above. Of course this change is not enough, I did > > it just to verify I really understand what happens. > > > > Except, stopped-attach-transparency prints > > > > Excessive waiting SIGSTOP after the second attach/detach > > > > afaics the test-case is not right here. attach_detach() leaves the > > traced threads in STOPPED state, why pid_notifying_sigstop() should > > fail? > > Tried the patch above: > http://koji.fedoraproject.org/scratch/jkratoch/task_1730038/ > > but it does not break stopped-attach-transparency for me. You mean, it doesn't fix stopped-attach-transparency? Strange... I tested it, with this patch stopped-attach-transparency succeeds on my machine. But! please note "this change is not enough" above, the right fix is not simple. However I thought it should work in this case... > Should I also apply back edaba2c5334492f82d39ec35637c6dea5176a977? This revert should be unreverted anyway, imho. This wakeup is wrong in many ways, but note that the changelog says in particular: this wake_up_process() can break another assumption: PTRACE_DETACH with SIGSTOP should leave the tracee in TASK_STOPPED case. Because the untraced child can dequeue SIGSTOP and call do_signal_stop() before ptrace_detach() calls wake_up_process(). However, this race is unlikely, I don't think it can explain why stopped-attach-transparency fails with the patch above. Oleg. From oleg at redhat.com Wed Oct 7 13:33:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 15:33:49 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006201701.GA8624@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> <20091006200516.GA3892@redhat.com> <20091006201701.GA8624@host0.dyn.jankratochvil.net> Message-ID: <20091007133349.GB9721@redhat.com> On 10/06, Jan Kratochvil wrote: > > On Tue, 06 Oct 2009 22:05:16 +0200, Oleg Nesterov wrote: > > For example, the tracee reports PTRACE_EVENT_EXEC and stops. In this > > case SIGNR has no effect after PTRACE_CONT/DETACH/etc. > > > > SIGNR does not ignored after the tracee reported syscall entry/exit or > > signal. > > OK, if only such exceptional cases as PTRACE_EVENT_EXEC that should not matter > I think. Also PTRACE_EVENT_FORK and friends. > It should work also for PTRACE_SINGLESTEP. Heh. Yes, but with one exception. - the tracee has a hanlder for, say, SIGHUP - the tracee deques SIGHUP, reports to the tracer, and stops. - the tracer does ptrace(SINGLESTEP, SIGHUP) // it could use another signr, this works. // but the tracer must have a handler or // everething is OK. - the tracee delivers SIGHUP to itself, handle_signal() notices TIF_SINGLESTEP and calls ptrace_notify(). Now, the tracee reports SIGTRAP, but the next time the tracer does ptrace(WHATEVER, SIGNR) SIGNR will be ignored. Oleg. From jan.kratochvil at redhat.com Wed Oct 7 13:39:51 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 7 Oct 2009 15:39:51 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091007132307.GA9721@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091006195903.GA19688@host0.dyn.jankratochvil.net> <20091007132307.GA9721@redhat.com> Message-ID: <20091007133951.GA6748@host0.dyn.jankratochvil.net> On Wed, 07 Oct 2009 15:23:07 +0200, Oleg Nesterov wrote: > On 10/06, Jan Kratochvil wrote: > > but it does not break stopped-attach-transparency for me. > > You mean, it doesn't fix stopped-attach-transparency? Oh I may have been testing attach-into-signal instead, OK, forget about my bogus kernel test. Anyway stopped-attach-transparency makes no sense to test when detach-stopped is still FAILing. stopped-attach-transparency is much more complicated based on the fundamental functionality tested by detach-stopped. After you recommend a kernel/patch for PASSing detach-stopped we can start talking about stopped-attach-transparency. Thanks, Jan From jan.kratochvil at redhat.com Wed Oct 7 13:46:31 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 7 Oct 2009 15:46:31 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091007133349.GB9721@redhat.com> References: <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> <20091006200516.GA3892@redhat.com> <20091006201701.GA8624@host0.dyn.jankratochvil.net> <20091007133349.GB9721@redhat.com> Message-ID: <20091007134631.GB6748@host0.dyn.jankratochvil.net> On Wed, 07 Oct 2009 15:33:49 +0200, Oleg Nesterov wrote: > On 10/06, Jan Kratochvil wrote: > > It should work also for PTRACE_SINGLESTEP. > > Heh. Yes, but with one exception. > > - the tracee has a hanlder for, say, SIGHUP > > - the tracee deques SIGHUP, reports to the tracer, > and stops. > > - the tracer does ptrace(SINGLESTEP, SIGHUP) > > // it could use another signr, this works. > // but the tracer must have a handler or > // everething is OK. > > - the tracee delivers SIGHUP to itself, handle_signal() > notices TIF_SINGLESTEP and calls ptrace_notify(). > > Now, the tracee reports SIGTRAP, but the next time the tracer does > ptrace(WHATEVER, SIGNR) SIGNR will be ignored. OK, this is really a border case I did not mean. In such case the SIGHUP handler still is not fully execting and as the non-realtime signals do not nest (count) it is OK it gets activated only once. I did mean some more normal case of: ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP ptrace (PTRACE_SIGNALSTEP, 0) = 0 waitpid() = SIGTRAP PTRACE (PTRACE_DETACH, SIGSTOP) = 0 which I assume it will work. Thanks, Jan From oleg at redhat.com Wed Oct 7 14:48:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 7 Oct 2009 16:48:32 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091007134631.GB6748@host0.dyn.jankratochvil.net> References: <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> <20091006200516.GA3892@redhat.com> <20091006201701.GA8624@host0.dyn.jankratochvil.net> <20091007133349.GB9721@redhat.com> <20091007134631.GB6748@host0.dyn.jankratochvil.net> Message-ID: <20091007144832.GA13685@redhat.com> On 10/07, Jan Kratochvil wrote: > > OK, this is really a border case I did not mean. > > In such case the SIGHUP handler still is not fully execting and as the > non-realtime signals do not nest (count) it is OK it gets activated only once. > > > I did mean some more normal case of: > > ptrace (PTRACE_SIGNALSTEP, 0) = 0 > waitpid() = SIGTRAP > ptrace (PTRACE_SIGNALSTEP, 0) = 0 > waitpid() = SIGTRAP > PTRACE (PTRACE_DETACH, SIGSTOP) = 0 > > which I assume it will work. Yes, this should work. In this case the tracee really has the pending SIGTRAP which will be dequeued and reported. ptrace(WHATEVER, SIGNR) will change si_signo (or cancel the signal if SIGNR = 0), PTRACE_SETSIGINFO works too. Oleg. From roland at redhat.com Thu Oct 8 02:27:16 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 19:27:16 -0700 (PDT) Subject: [PATCH 70] move "event << 8" into syscall_code() In-Reply-To: Oleg Nesterov's message of Wednesday, 7 October 2009 14:12:18 +0200 <20091007121218.GB5482@redhat.com> References: <20091006003210.GA26313@redhat.com> <20091007074735.51CF41F1@magilla.sf.frob.com> <20091007121218.GB5482@redhat.com> Message-ID: <20091008022716.8D73BBF@magilla.sf.frob.com> > void set_stop_code(struct ptrace_context *ctx, int event) > { > ctx->stop_code = (event << 8) | SIGTRAP; > } > > void set_syscall_code(struct ptrace_context *ctx, int event) > { > set_stop_code(ctx, event); > if (PTRACE_O_TRACESYSGOOD) > ctx->stop_code |= 0x80; > } Very good (that's what I had in mind first, really). (statics, of course.) > Or, [...] > This way ptrace_report_signal() can use __set_stop_code() too. It sure feels cleaner just to use event=0 for the "signal" event so it just uses plain "ctx->stop_code = signr" there. > But this is minor, if your prefer your version I'll send the patch. Your preference, just something without << 8 duplicated a lot, and without __ names for static functions! Thanks, Roland From roland at redhat.com Thu Oct 8 02:33:30 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 19:33:30 -0700 (PDT) Subject: [PATCH 62] introduce ptrace_rw_siginfo() helper In-Reply-To: Oleg Nesterov's message of Wednesday, 7 October 2009 14:47:33 +0200 <20091007124733.GA6898@redhat.com> References: <20091003020035.GA15213@redhat.com> <20091007070610.D046BF4A@magilla.sf.frob.com> <20091007124733.GA6898@redhat.com> Message-ID: <20091008023330.9E4A6BF@magilla.sf.frob.com> > I don't think this can work. context->siginfo can be cleared and then > set again in between. If we race with SIGKILL, utrace_get_signal() > can dequeue another signal != SIGKILL and start the reporting loop. That's not supposed to be possible. See "sigset_t sigkill_only;" et al. I guess it is possible when it's an earlier utrace_stop() that is what's broken by SIGKILL. Then utrace_get_signal() is entered when SIGKILL is pending. It should have a fatal_signal_pending() check earlier then. We really want it to be ironclad that when UTRACE_STOP is broken the only meaningful thing that can happen is do_group_exit(SIGKILL). > I thought about > > *info = *context_info; > rmb(); > if (fatal_ignal_pending(tracee)) > return -ERR; > > But I think it is better to do theses cleanups after V1. Agreed. Thanks, Roland From roland at redhat.com Thu Oct 8 02:42:48 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 19:42:48 -0700 (PDT) Subject: [PATCH 63] convert ptrace_getsiginfo() to use ptrace_rw_siginfo() In-Reply-To: Oleg Nesterov's message of Wednesday, 7 October 2009 15:12:13 +0200 <20091007131213.GB6898@redhat.com> References: <20091003015808.GA15073@redhat.com> <20091007071816.63210F4A@magilla.sf.frob.com> <20091007131213.GB6898@redhat.com> Message-ID: <20091008024248.EF6D8BF@magilla.sf.frob.com> > I mostly agree, but I'd like to keep this helper for now. I am not sure > yet, but perhaps it will be needed if we change detach to play with > ptrace_utrace_detached_ops. This was a reason why I added the separate > helper. But let me repeat I am not sure it will be really needed. Ok. > Or, we can change ptrace_report_signal() (or even utrace_get_signal()) > to check __fatal_signal_pending(). See my last message, that's what we really want anyway. > Yes, if utrace_get_signal() dequeues SIGKILL it doesn't report and > just returns. Right. > But, ptrace_report_signal() does: > > context->siginfo = info; > /* > * context->siginfo points to the caller's stack. > * Make sure the subsequent UTRACE_SIGNAL_REPORT clears > * ->siginfo before return from get_signal_to_deliver(). > */ > utrace_control(task, engine, UTRACE_INTERRUPT); > > this means that, even if killed, the tracee will call utrace_get_signal() > with utrace->interrupt == T. In this case UTRACE_SIGNAL_REPORT will be > reported anyway. > > Right? Ah, yes, that is right. However, my feeling is that the really right thing for the utrace API is that the new fatal_signal_pending() check will be before even this. That is, the principle is that immediately upon SIGKILL it dies as quickly as possible and skips any stops or callbacks that aren't really required to prevent confusion. That logic says we could nix report_exit too and really only keep report_death, though I think it's probably better to guarantee report_exit always gets called--but a UTRACE_STOP from there should not be obeyed, it should finish dying fast. Thanks, Roland From roland at redhat.com Thu Oct 8 04:03:58 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 21:03:58 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Oleg Nesterov's message of Monday, 5 October 2009 04:51:32 +0200 <20091005025132.GA25283@redhat.com> References: <20091005025132.GA25283@redhat.com> Message-ID: <20091008040358.73BC88D@magilla.sf.frob.com> > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > and then another/same tracer does ptrace(ATTACH, tracee) > then SIGXXX will not be reported to the new tracer. Correct. > Why? Should utrace-ptrace be 100% compatible here? I think it should, yes. There is a rationale for it that makes sense to me, and it is most certainly consistent, observable behavior on which existing applications could very well depend subtly, so regardless of "right" I think this one is well within 100% bug-compatibility territory. The rationale I see is that the debugger observed the signal, decided it wanted the tracee to experience the normal effects of the signal and be done with it after that. If it's a termination signal, the debugger really expects that the tracee can do nothing but die. (Given the tortured historic logic of the ptrace code paths, this applies only to signal stops and only when it either passes back the same signal number or at least another one that is not blocked.) Now replace "debugger" with "monitor" or (dismal) "security-checking syscall tracing product", or just shudder while trying not to imagine what all inane things ptrace might already be in use for. It could be important to someone out there e.g. that some other process of the tracee's UID cannot race in there and rescue it from dying. > I do not think there is a "real life" application that does > ATTACH + DETACH and relies on fact it must not see this sig. We can hope, but we cannot assume. There are always better ways to achieve the same true ends than the corner case examples like the one I gave, but that doesn't mean people haven't written the stupid ones in applications already shipped long ago and never to be rethought again (until we get the blame for breaking them in the new kernel). Thanks, Roland From roland at redhat.com Thu Oct 8 04:07:36 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 21:07:36 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Oleg Nesterov's message of Monday, 5 October 2009 21:00:37 +0200 <20091005190037.GA2103@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> Message-ID: <20091008040736.6768A8D@magilla.sf.frob.com> > > Naive programs expect the first signal after PTRACE_ATTACH will be SIGSTOP. > > They should not, this is just wrong. > > And I think the proposed change doesn't change the behaviour > in this sense. It does not in the general sense. But it does change the behavior of certain 100% predictable patterns that could have been used before. Thanks, Roland From roland at redhat.com Thu Oct 8 04:13:43 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 21:13:43 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Oleg Nesterov's message of Tuesday, 6 October 2009 19:14:28 +0200 <20091006171428.GA29055@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> Message-ID: <20091008041343.E09D98D@magilla.sf.frob.com> > OK. Let's see what Roland thinks. I think the whole stoppedness vs detach et al discussion is a separate issue from the basic PTRACE_DETACH,signr behavior, and I think I want to discuss that in the other thread we have whose subject says it's about that. I think I've covered the (separate) basic parting-signal issue now. > Hmm. I guess with utrace it will be simple to do this change... You're supposed to say that before every patch! Didn't you get the memo? ;-) Thanks, Roland From roland at redhat.com Thu Oct 8 04:26:00 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 21:26:00 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Jan Kratochvil's message of Tuesday, 6 October 2009 21:25:50 +0200 <20091006192550.GA4784@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> Message-ID: <20091008042600.0F9EFD3@magilla.sf.frob.com> > In which specific cases SIGNR can get ignored? There are two fundamental kinds of ptrace stops: real signal stops, and "fake" (or "ptrace_notify()") stops. In the latter, you are not in the right place in the kernel for direct signal delivery, so it never works fully normally. All the optional event stops are in this latter category, i.e. everything not for a signal. The syscall entry and exit stops have an explicit queuing behavior (i.e. it's about the same as if you'd just called tgkill before PTRACE_CONT--any PTRACE_SETSIGINFO you've done has no effect on this new signal, but you will see it in a real signal stop soon when it's dequeued). The others do not have any such kludge, so they just drop the signr argument on the floor. Note that the default exec stop really is a signal (a plain SIGTRAP sent as if by "raise(SIGTRAP);" right after exec), but PTRACE_EVENT_EXEC is not. Some of the PTRACE_SINGLESTEP cases on some architectures use fake stops. When stepping over an average user instruction, it's always a real SIGTRAP. But e.g., stepping the syscall insn on powerpc and some others (perhaps all but x86) is not. As Oleg mentioned, when PTRACE_SINGLESTEP,signr stops immediately after handler setup, that is also a fake stop. These cases are something that we probably can and should fix and arch-harmonize upstream so that PTRACE_SINGLESTEP consistently produces a real SIGTRAP signal stop after which the full range of I don't think the behavior for the special event stops will change. Thanks, Roland From roland at redhat.com Thu Oct 8 04:29:08 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 21:29:08 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Roland McGrath's message of Wednesday, 7 October 2009 21:26:00 -0700 <20091008042600.0F9EFD3@magilla.sf.frob.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091006171428.GA29055@redhat.com> <20091006192550.GA4784@host0.dyn.jankratochvil.net> <20091008042600.0F9EFD3@magilla.sf.frob.com> Message-ID: <20091008042908.57B30D3@magilla.sf.frob.com> > after which the full range of [oops, left that thought unfinished!] ... signal control options works (immediate delivery, SETSIGIFNO obeyed) From roland at redhat.com Thu Oct 8 05:24:24 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 7 Oct 2009 22:24:24 -0700 (PDT) Subject: Stopped detach/attach status In-Reply-To: Oleg Nesterov's message of Monday, 5 October 2009 04:32:08 +0200 <20091005023208.GA23901@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> Message-ID: <20091008052424.29E15D3@magilla.sf.frob.com> > I do not know. I'd leave this to Roland. I mean, if he thinks this > should be fixed - I'll try to fix. > > But. This all looks unfixeable to me. In my opinion, the kernel is > obviously wrong, and test-case are wrong too. And any fix in this > area is user-visible and can break the current expectations. My view is that the handling of a tracee that was already job-stopped (left by ^Z, etc.) or of a tracee that you want to leave job-stopped for its natural parent to see on detach, has never really worked. In the past the kernel and GDB (let alone strace) have both been wrong and even internally inconsistent, and each changed incompatibly with itself (not to mention with each other) over the years. So for those cases as such, I don't think any particular compatibility matters so much as just settling on something acceptable now. I expect that there is no one behavior for this case that is actually compatible with the expectations of a significant range of tools/versions such that nearly any change at all wouldn't be a regression for some and an improvement for others. However, we unfortunately cannot say the same for all quirks that we would probably like to change. That is, the treatment of SIGSTOP and what wakeups get done and so forth is an intricate dependency of plain attach/detach logic in all manner of debuggeresque tools for numerous corner cases (many MT-related). So I think the main constraint on what we can come up with as "newly almost sane" semantics is that we really should not regress for any other corner of attach/detach et al logic in any current or past version of gdb, or strace, or anything else. > Firstly, I think we should un-revert edaba2c5334492f82d39ec35637c6dea5176a977. Yes. That unconditional wakeup was one of the very first things years ago that made me shake my head and marvel about what sucker they would ever get to maintain what all the purported ABI semantics corners of this ludicrous ptrace() implementation were supposed to be, glad that it was not my problem to touch that wormy can of flaming obvious wrong with a ten foot pole. At the time it was probably already obvious to most people other than me that I would be that very sucker for years to come. Hmm, perhaps I have not set this up very well now for asking you to think up all the details of matching the established semantics (that really sounds better than "purported", doesn't it?) of this insane implementation. :-) > We had a lengthy discussion about this. Yes. I only ever wanted that revert then because it was too late in the 2.6.30 cycle to hash this all out and get it really right. I meant that we should leave wrong enough alone in 2.6.30 but get it all worked out more properly in 2.6.31, but I forgot to follow up on it. If we can iron out the behavior now and the upstream version of implementing it is not big new hair, it might still be possible to get it fixed in 2.6.32. That piece of implementation is 100% wrong. But we have to figure out what the manifest semantics are today from the userland perspective and decide what exactly we want them to be before we implement those precise semantics in some sensible way. We may have to settle on something that, while more consistent than today's kernel, is still somewhat wrong in the abstract, when we need to preserve application compatibility. > - sig->flags = SIGNAL_STOP_STOPPED; > + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; Boy, do I not understand why that does anything about this at all! But I am barely awake tonight. Ok, I guess I do sort of if it goes along with some other patch to set SIGNAL_STOP_STOPPED. But since you've verified you really understand what happens, you can tell us! > But as I said, I do not really understand what this test-case tries > to do. What ptrace(PTRACE_DETACH, SIGSTOP) should mean? I think that > ptrace(PTRACE_DETACH, signr) should mean the tracee should proceed > with this signal, as if it was sent by, say, kill. Except for not being possibly intercepted again, roughly yes. But note that this really is only delivery, not generation (POSIX signal terms). (In the kludge cases for blocked signals and non-signal stops, sometimes it really is generation like kill, but here I mean resuming from real signal stops.) That means that magic generation-time effects, such as SIGSTOP clearing pending SIGCONT and vice versa, do not happen (if passing on the signal, they happened before at original generation). Internally, "dequeue-time" effects, i.e. SIGNAL_STOP_DEQUEUED and timer rearming, also don't happen (because they happened before). But since SIGNAL_STOP_DEQUEUED is pure internal bookkeeping, that is something we could change as an implementation detail for the semantics we want. > In this case, I don't understand why stopped-attach-transparency > "sends" SIGSTOP to every sub-thread. If the tracer wants to stop > the thread group after detach, it can do > > ptrace(PTRACE_DETACH, anythread, SIGSTOP); > for_each_other_thread(pid) > ptrace(PTRACE_DETACH, anythread, 0); That is racy. Each thread could resume and run a little before the first thread gets scheduled, processes the signal delivery, and interrupts all the other threads. That's always been the case. AFAIK this code pattern has been consistently reliable to leave the whole process stopped for a long time, so any existing debugger code that works this way will want to stay as it is for the foreseeable future so it works with a wide range of kernel vintages. Thanks, Roland From newsletter at rmcvisual.upmailer.com Wed Oct 7 04:58:14 2009 From: newsletter at rmcvisual.upmailer.com (RMC Visual) Date: Wed, 07 Oct 2009 00:58:14 -0400 Subject: Superando Obstaculos? Message-ID: Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://rmcvisual.upmailer.com/display.php?M=218845&C=0fd8d0aee637e524255c509639c873f5&S=4&L=4&N=3 Para parar de receber nossos e-mails:http://rmcvisual.upmailer.com/unsubscribe.php?M=218845&C=0fd8d0aee637e524255c509639c873f5&L=4&N=4 Desenvolvido por UpMailer -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at campaigns.canal-marketing.com Thu Oct 8 15:00:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Media_Mailing?=) Date: Thu, 08 Oct 2009 17:00:00 +0200 Subject: =?iso-8859-1?q?Communiquer_de_mani=E8re_efficace?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Oct 8 15:20:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 8 Oct 2009 17:20:39 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091008040358.73BC88D@magilla.sf.frob.com> References: <20091005025132.GA25283@redhat.com> <20091008040358.73BC88D@magilla.sf.frob.com> Message-ID: <20091008152039.GA15039@redhat.com> On 10/07, Roland McGrath wrote: > > > Currently, if a tracer does ptrace(DETACH, tracee, SIGXXX) > > and then another/same tracer does ptrace(ATTACH, tracee) > > then SIGXXX will not be reported to the new tracer. > > Correct. Well almost... What if the tracee reports a signal and stops, the tracer detaches but does not wake it up because of SIGNAL_STOP_STOPPED ? In this case this signal will be visible after the next attach. OK, currently ptrace_detach() unconditionally wakes up the tracee. But we seem to agree this wakeup should be killed, it completely breaks the group-stop logic and it has other problems. > > Why? Should utrace-ptrace be 100% compatible here? > > The rationale I see is that the debugger observed the signal, decided it > wanted the tracee to experience the normal effects of the signal and be > done with it after that. If it's a termination signal, the debugger really > expects that the tracee can do nothing but die. (Given the tortured > historic logic of the ptrace code paths, this applies only to signal stops > and only when it either passes back the same signal number or at least > another one that is not blocked.) Now replace "debugger" with "monitor" or > (dismal) "security-checking syscall tracing product", or just shudder while > trying not to imagine what all inane things ptrace might already be in use > for. It could be important to someone out there e.g. that some other > process of the tracee's UID cannot race in there and rescue it from dying. If "monitor" really wants to kill the tracee it should use SIGKILL ;) Any other fatal signal can be ignored by the tracee's sub-thread after detach but before the tracee returns from ptrace_signal(). This leads to another isssue I forgot to mention when I sent [PATCH 71] RFC, fix ptrace(PTRACE_DETACH, signr) logic https://www.redhat.com/archives/utrace-devel/2009-October/msg00043.html Since detach_signal() actually sends the signal, ptrace(DETACH, SIGKILL) really works: it wakes up SIGNAL_STOP_STOPPED tracee. > > I do not think there is a "real life" application that does > > ATTACH + DETACH and relies on fact it must not see this sig. > > We can hope, but we cannot assume. Oh, OK. Lets discuss how we can implement detach to be compatible... We already discussed detached_ops. So, we either change engine->ops (my choice) or add the new engine with ->ops = detached_ops and detach the ptrace engine. We need detached_report_signal() callback which fixups siginfo if signr != info->si_signo and returns UTRACE_DETACH | UTRACE_SIGNAL_DELIVER. How can detached_report_signal() set info->si_pid correctly? the tracer has gone away. This probably means this info should be prepared during detach, the tracer should fill context->siginfo. But the real problem, I can't see how can we teach ptrace_report_signal() to not play with parting signals. Do you have any idea? perhaps we can introduce UTRACE_SIGNAL_DELIVER_I_AM_DETACHED_ENGINE, but this is ugly. Oh, I'd like to avoid detached_ops. Perhaps the new attach can re-use the old engine/context? ptrace(DETACH, SIGNR) does: context->detached = true; // checked in ptrace_report_signal() return utrace_control(INTERRUPT); Now, how ptrace(ATTACH) can clear ->detached and re-use this engine without utrace->lock ? IOW, will you agree to abuse utrace->lock for this? OR. Perhaps we can introduce UTRACE_ATTACH_MATCH_FILTER_DATA ? static bool engine_matches(struct utrace_engine *engine, int flags, const struct utrace_engine_ops *ops, void *data) { if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) return false; if ((flags & UTRACE_ATTACH_MATCH_FILTER_DATA)) { bool (*filter)(void*) = data; if (!filter(engine->data)) return false; } if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) return false; return engine->ops && engine->ops != &utrace_detached_ops; } Now, PTRACE_ATTACH does: bool ptrace_filter(void *engine) { struct ptrace_context *context = ptrace_context(engine); if (!context->detached) return false; context->detached = false; // re-use return true; } ptrace_attach_task(...) { ... engine = utrace_attach_task(MATCH_OPS | MATCH_FILTER_DATA, ptrace_utrace_ops, ptrace_filter); if (!IS_ERR(engine)) { // We re-used the old engine, but perhaps it is // going to return UTRACE_DETACH ? utrace_barrier(engine); if (engine->ops == utrace_detached_ops) engine = -EANY; } if (IS_ERR(engine)) engine = utrace_attach_task(CREATE | EXCLUSIVE, ptrace_utrace_ops, context); ... } What do you think? In any case, I'd like to think more. Somehow I am so sleepy today, perhaps I can invent something else tomorrow... But actually I hope you can find a better solution ;) Oleg. From oleg at redhat.com Thu Oct 8 16:06:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 8 Oct 2009 18:06:58 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091008052424.29E15D3@magilla.sf.frob.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> Message-ID: <20091008160658.GA15768@redhat.com> Incomplete reply, just can't read/think/concentrate today... On 10/07, Roland McGrath wrote: > > > We had a lengthy discussion about this. > > Yes. I only ever wanted that revert then because it was too late in the > 2.6.30 cycle to hash this all out and get it really right. I meant that > we should leave wrong enough alone in 2.6.30 but get it all worked out > more properly in 2.6.31, but I forgot to follow up on it. If we can > iron out the behavior now and the upstream version of implementing it is > not big new hair, it might still be possible to get it fixed in 2.6.32. > > That piece of implementation is 100% wrong. But we have to figure out > what the manifest semantics are today from the userland perspective and > decide what exactly we want them to be before we implement those precise > semantics in some sensible way. Yes. In particular, ptrace(PTRACE_DETACH, SIGKILL) should cancel SIGNAL_STOP_STOPPED, yes? > > - sig->flags = SIGNAL_STOP_STOPPED; > > + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; > > Boy, do I not understand why that does anything about this at all! > But I am barely awake tonight. Ok, I guess I do sort of if it goes > along with some other patch to set SIGNAL_STOP_STOPPED. But since > you've verified you really understand what happens, you can tell us! Two threads T1 and T2, both ptraced by P, both TASK_TRACED, T2 sleeps in ptrace_signal(). P does: ptrace(DETACH, T1, SIGSTOP); ptrace(DETACH, T2, SIGSTOP); The first DETACH wakes up T1, it dequeues SIGSTOP, calls do_signal_stop(). T2 is still TASK_TRACED, this means T1 completes the group-stop and sets sig->flags = SIGNAL_STOP_STOPPED. The second detach wakes up T2, it returns from ptrace_signal() and calls do_signal_stop() which does nothing without SIGNAL_STOP_DEQUEUED. But please remember, the patch above is not complete of course and currently I do not see the good solution. I am starting to think we should forget about these bugs, merge utrace-ptrace, and then try to fix them. Even the first detach can fail to stop T1, because SIGNAL_STOP_DEQUEUED can be cleared before. I never knew what user-space actually does with ptrace, now I am really surprized gdb/etc assume it can trust ptrace(SIGSTOP). Sometime it works, but only by accident. Oleg. From oleg at redhat.com Thu Oct 8 16:27:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 8 Oct 2009 18:27:10 +0200 Subject: [PATCH 70] move "event << 8" into syscall_code() In-Reply-To: <20091008022716.8D73BBF@magilla.sf.frob.com> References: <20091006003210.GA26313@redhat.com> <20091007074735.51CF41F1@magilla.sf.frob.com> <20091007121218.GB5482@redhat.com> <20091008022716.8D73BBF@magilla.sf.frob.com> Message-ID: <20091008162710.GA17317@redhat.com> On 10/07, Roland McGrath wrote: > > > void set_stop_code(struct ptrace_context *ctx, int event) > > { > > ctx->stop_code = (event << 8) | SIGTRAP; > > } > > > > void set_syscall_code(struct ptrace_context *ctx, int event) > > { > > set_stop_code(ctx, event); > > if (PTRACE_O_TRACESYSGOOD) > > ctx->stop_code |= 0x80; > > } > > Very good (that's what I had in mind first, really). (statics, of course.) Great, will do. > > This way ptrace_report_signal() can use __set_stop_code() too. > > It sure feels cleaner just to use event=0 for the "signal" event > so it just uses plain "ctx->stop_code = signr" there. Cough. I am afraid you may be right again (yes yes yes, ev_array was really bad idea). But so far I disagree. I like the fact we can distinguish PTRACE_EVENT_SIGTRAP and PTRACE_EVENT_SIGNAL. And get_stop_event() logic becomes simpler. OK, at least these two events do not add a lot of uglification, it will be simple to kill them later. Oleg. From vendas at mardeb.com.br Thu Oct 8 17:55:14 2009 From: vendas at mardeb.com.br (Piero Jimenez) Date: Thu, 8 Oct 2009 17:55:14 GMT Subject: TINTA INDUSTRIAL ESMALTE SINTETICO E LACA Message-ID: <20091008145347.881121774A7@mhu18mtaz-tvt-spo.fly.com.br> An HTML attachment was scrubbed... URL: From dr at brillux.de Thu Oct 8 20:30:41 2009 From: dr at brillux.de (Rosabel Perez) Date: Thu, 8 Oct 2009 20:30:41 -0000 Subject: Make your pipe incredible Message-ID: <20091008203041.9010407@brillux.de> You need to be good in bed really fast? Choose us and get the speedy delivery! http://ef.planefruit.com/ From amoureux at netpromouter.net Thu Oct 8 16:20:44 2009 From: amoureux at netpromouter.net (Amoureux) Date: Thu, 08 Oct 2009 20:20:44 +0400 Subject: =?utf-8?q?Descubra_a_sua_cara_metade=2E_Inscri=C3=A7=C3=A3o_100?= =?utf-8?q?=25_Gratuita?= Message-ID: Descubra o encontro REALMENTE gratuito. Milhares de an?ncios novos cada dia perto de sua casa e por toda a parte no mundo. "? facil, s?rio, completo e gratuito". INSCRI??O Amoureux.com ? o site l?der de encontros gratuitos na Internet(Fonte de Nielsen/NetRating agosto 2007) Os servi?os de encontros de Amoureux.com s?o 100% Gr?tis e cumprido a inscri??o no site. Siga este link: http://netpromouter.net/iem/link.php?M=21794&N=2&L=1&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From reservaciones at laspalmasclub.com Thu Oct 8 00:46:54 2009 From: reservaciones at laspalmasclub.com (Las Palmas By The Sea) Date: Wed, 7 Oct 2009 20:46:54 -0400 Subject: Cristmas 209 in Puerto Vallarta Message-ID: <6f7c788c1e5af080d00806b24c3bfc84@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From mldireto at tudoemoferta.com.br Thu Oct 8 19:52:18 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 8 Oct 2009 16:52:18 -0300 Subject: Ainda da tempo. Brinquedoteca no TudoemOferta. Aqui o seu dia das Criancas e mais feliz Message-ID: <565b2d394265593616db52cc00183d4f@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From pctoday.allsolutions at gmail.com Fri Oct 9 07:47:51 2009 From: pctoday.allsolutions at gmail.com (PC today Laptop Repairs) Date: Fri, 09 Oct 2009 12:47:51 +0500 Subject: Gauranteed Laptop Repairing Message-ID: <72940d65100d784c8addcccd9da2f7cd@user> -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Flyer for PCToday1.JPG Type: image/jpeg Size: 71211 bytes Desc: not available URL: From oleg at redhat.com Fri Oct 9 14:24:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 16:24:33 +0200 Subject: [PATCH 71-72] renames, ->siginfo tweaks Message-ID: <20091009142433.GA6198@redhat.com> Rework get/set siginfo logic. We should never rely on ->siginfo != NULL checks. This is subtle, and if we implement the re-using of engine/context, this just can't work. Oleg. From oleg at redhat.com Fri Oct 9 14:24:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 16:24:35 +0200 Subject: [PATCH 71] cosmetic, misc renames Message-ID: <20091009142435.GA6206@redhat.com> Renames: ev_code => stop_code ev_mesg => eventmsg ev_pending => ptrace_event_pending get_stop_code => get_stop_event --- kernel/ptrace.c | 72 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 36 insertions(+), 36 deletions(-) --- PU/kernel/ptrace.c~71_RENAME_FIELDS 2009-10-09 13:18:32.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 14:18:55.000000000 +0200 @@ -30,8 +30,8 @@ struct ptrace_context { int signr; siginfo_t *siginfo; - int ev_code; - unsigned long ev_mesg; + int stop_code; + unsigned long eventmsg; enum utrace_resume_action resume; }; @@ -43,14 +43,14 @@ struct ptrace_context { /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF -static inline bool ev_pending(struct ptrace_context *context) +static inline bool ptrace_event_pending(struct ptrace_context *context) { - return context->ev_code != 0; + return context->stop_code != 0; } -static inline int get_stop_code(struct ptrace_context *context) +static inline int get_stop_event(struct ptrace_context *context) { - return context->ev_code >> 8; + return context->stop_code >> 8; } static inline struct ptrace_context * @@ -121,10 +121,10 @@ static u32 ptrace_report_exit(enum utrac { struct ptrace_context *context = ptrace_context(engine); - WARN_ON(ev_pending(context)); + WARN_ON(ptrace_event_pending(context)); - context->ev_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP; - context->ev_mesg = *code; + context->stop_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP; + context->eventmsg = *code; return UTRACE_STOP; } @@ -169,7 +169,7 @@ static u32 ptrace_report_clone(enum utra struct ptrace_context *context = ptrace_context(engine); int event, ret = UTRACE_RESUME; - WARN_ON(ev_pending(context)); + WARN_ON(ptrace_event_pending(context)); // XXX: WRONG!!! if (clone_flags & CLONE_UNTRACED) @@ -195,14 +195,14 @@ static u32 ptrace_report_clone(enum utra // XXX: child->pid is wrong! use tracer's pid_ns if (event) { - context->ev_code = (event << 8) | SIGTRAP; - context->ev_mesg = child->pid; + context->stop_code = (event << 8) | SIGTRAP; + context->eventmsg = child->pid; ret = UTRACE_STOP; } else if ((clone_flags & CLONE_VFORK) && (context->options & PTRACE_O_TRACEVFORKDONE)) { - context->ev_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; - context->ev_mesg = child->pid; + context->stop_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; + context->eventmsg = child->pid; ret = UTRACE_STOP; } @@ -224,9 +224,9 @@ static u32 ptrace_report_syscall_entry(u { struct ptrace_context *context = ptrace_context(engine); - WARN_ON(ev_pending(context)); + WARN_ON(ptrace_event_pending(context)); - context->ev_code = syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + context->stop_code = syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -238,10 +238,10 @@ static u32 ptrace_report_syscall_exit(en { struct ptrace_context *context = ptrace_context(engine); - if (ev_pending(context)) + if (ptrace_event_pending(context)) return UTRACE_STOP; - context->ev_code = syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + context->stop_code = syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); return UTRACE_STOP; } @@ -255,7 +255,7 @@ static u32 ptrace_report_exec(enum utrac { struct ptrace_context *context = ptrace_context(engine); - WARN_ON(ev_pending(context)); + WARN_ON(ptrace_event_pending(context)); if (!(context->options & PTRACE_O_TRACEEXEC)) { /* @@ -265,7 +265,7 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } - context->ev_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; + context->stop_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; return UTRACE_STOP; } @@ -314,7 +314,7 @@ static u32 ptrace_report_signal(u32 acti struct ptrace_context *context = ptrace_context(engine); enum utrace_resume_action resume = context->resume; - if (ev_pending(context)) { + if (ptrace_event_pending(context)) { action = utrace_signal_action(action); WARN_ON(action != UTRACE_SIGNAL_REPORT); return action | UTRACE_STOP; @@ -326,7 +326,7 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - context->ev_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; + context->stop_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; return UTRACE_STOP | UTRACE_SIGNAL_IGN; } @@ -351,7 +351,7 @@ static u32 ptrace_report_signal(u32 acti */ utrace_control(task, engine, UTRACE_INTERRUPT); - context->ev_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; + context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; context->signr = info->si_signo; return UTRACE_STOP | UTRACE_SIGNAL_IGN; @@ -365,7 +365,7 @@ static u32 ptrace_report_quiesce(u32 act { struct ptrace_context *context = ptrace_context(engine); - if (ev_pending(context)) + if (ptrace_event_pending(context)) return UTRACE_STOP; return event ? UTRACE_RESUME : context->resume; @@ -810,7 +810,7 @@ static int ptrace_getsiginfo(struct ptra struct task_struct *tracee, siginfo_t *info) { /* jctl stop ? */ - if (!ev_pending(context)) + if (!ptrace_event_pending(context)) return -EINVAL; if (context->siginfo) @@ -818,7 +818,7 @@ static int ptrace_getsiginfo(struct ptra memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; - info->si_code = context->ev_code & PTRACE_EVENT_MASK; + info->si_code = context->stop_code & PTRACE_EVENT_MASK; info->si_pid = task_pid_vnr(tracee); info->si_uid = task_uid(tracee); @@ -829,7 +829,7 @@ static int ptrace_setsiginfo(struct ptra struct task_struct *tracee, siginfo_t *info) { /* jctl stop ? */ - if (!ev_pending(context)) + if (!ptrace_event_pending(context)) return -EINVAL; if (context->siginfo) @@ -861,7 +861,7 @@ static int ptrace_setsiginfo(struct ptra static void do_ptrace_notify_stop(struct ptrace_context *context, struct task_struct *tracee) { - tracee->exit_code = context->ev_code & PTRACE_EVENT_MASK; + tracee->exit_code = context->stop_code & PTRACE_EVENT_MASK; read_lock(&tasklist_lock); /* @@ -888,7 +888,7 @@ void ptrace_notify_stop(struct task_stru } context = ptrace_context(engine); - if (WARN_ON(!ev_pending(context))) + if (WARN_ON(!ptrace_event_pending(context))) return; do_ptrace_notify_stop(context, tracee); } @@ -918,7 +918,7 @@ static void do_ptrace_resume(struct utra { struct ptrace_context *context = ptrace_context(engine); - switch (get_stop_code(context)) { + switch (get_stop_event(context)) { case 0: // XXX: JCTL stop break; @@ -933,12 +933,12 @@ static void do_ptrace_resume(struct utra } if (request == PTRACE_SYSCALL) { - switch (get_stop_code(context)) { + switch (get_stop_event(context)) { case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: - context->ev_code = syscall_code(context, + context->stop_code = syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; @@ -946,7 +946,7 @@ static void do_ptrace_resume(struct utra } if (action != UTRACE_RESUME) { - switch (get_stop_code(context)) { + switch (get_stop_event(context)) { case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: @@ -962,7 +962,7 @@ static void do_ptrace_resume(struct utra } } - context->ev_code = 0; + context->stop_code = 0; context->resume = action; ptrace_wake_up(engine, tracee, action); } @@ -1038,7 +1038,7 @@ int ptrace_request(struct task_struct *c ret = ptrace_set_options(engine, child, data); break; case PTRACE_GETEVENTMSG: - ret = put_user(ptrace_context(engine)->ev_mesg, + ret = put_user(ptrace_context(engine)->eventmsg, (unsigned long __user *) data); break; @@ -1209,7 +1209,7 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETEVENTMSG: - ret = put_user((compat_ulong_t)ptrace_context(engine)->ev_mesg, + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, datap); break; From oleg at redhat.com Fri Oct 9 14:24:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 16:24:38 +0200 Subject: [PATCH 72] introduce set_stop_code() helper Message-ID: <20091009142438.GA6210@redhat.com> Trivial, add set_stop_code() and turn syscall_code() into set_syscall_code(). --- kernel/ptrace.c | 28 ++++++++++++++++------------ 1 file changed, 16 insertions(+), 12 deletions(-) --- PU/kernel/ptrace.c~72_SET_CODE_HELPER 2009-10-09 14:18:55.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 14:34:38.000000000 +0200 @@ -53,6 +53,11 @@ static inline int get_stop_event(struct return context->stop_code >> 8; } +static inline void set_stop_code(struct ptrace_context *context, int event) +{ + context->stop_code = (event << 8) | SIGTRAP; +} + static inline struct ptrace_context * ptrace_context(struct utrace_engine *engine) { @@ -123,7 +128,7 @@ static u32 ptrace_report_exit(enum utrac WARN_ON(ptrace_event_pending(context)); - context->stop_code = (PTRACE_EVENT_EXIT << 8) | SIGTRAP; + set_stop_code(context, PTRACE_EVENT_EXIT); context->eventmsg = *code; return UTRACE_STOP; @@ -195,13 +200,13 @@ static u32 ptrace_report_clone(enum utra // XXX: child->pid is wrong! use tracer's pid_ns if (event) { - context->stop_code = (event << 8) | SIGTRAP; + set_stop_code(context, event); context->eventmsg = child->pid; ret = UTRACE_STOP; } else if ((clone_flags & CLONE_VFORK) && (context->options & PTRACE_O_TRACEVFORKDONE)) { - context->stop_code = (PTRACE_EVENT_VFORK_DONE << 8) | SIGTRAP; + set_stop_code(context, PTRACE_EVENT_VFORK_DONE); context->eventmsg = child->pid; ret = UTRACE_STOP; @@ -210,11 +215,11 @@ static u32 ptrace_report_clone(enum utra return ret; } -static inline int syscall_code(struct ptrace_context *context, int event) +static inline void set_syscall_code(struct ptrace_context *context, int event) { - int code = (context->options & PTRACE_O_TRACESYSGOOD) ? - (SIGTRAP | 0x80) : SIGTRAP; - return (event << 8) | code; + set_stop_code(context, event); + if (context->options & PTRACE_O_TRACESYSGOOD) + context->stop_code |= 0x80; } static u32 ptrace_report_syscall_entry(u32 action, @@ -226,7 +231,7 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ptrace_event_pending(context)); - context->stop_code = syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -241,7 +246,7 @@ static u32 ptrace_report_syscall_exit(en if (ptrace_event_pending(context)) return UTRACE_STOP; - context->stop_code = syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); return UTRACE_STOP; } @@ -265,7 +270,7 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } - context->stop_code = (PTRACE_EVENT_EXEC << 8) | SIGTRAP; + set_stop_code(context, PTRACE_EVENT_EXEC); return UTRACE_STOP; } @@ -938,8 +943,7 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: - context->stop_code = syscall_code(context, - PTRACE_EVENT_SYSCALL_EXIT); + set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } From oleg at redhat.com Fri Oct 9 14:24:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 16:24:41 +0200 Subject: [PATCH 73] rework access to context->siginfo Message-ID: <20091009142441.GA6213@redhat.com> To simplify the review: static int ptrace_rw_siginfo(struct task_struct *tracee, struct ptrace_context *context, siginfo_t *info, bool write) { unsigned long flags; int err; switch (get_stop_event(context)) { case 0: /* jctl stop */ return -EINVAL; case PTRACE_EVENT_SIGNAL: err = -ESRCH; if (lock_task_sighand(tracee, &flags)) { if (likely(task_is_traced(tracee))) { if (write) *context->siginfo = *info; else *info = *context->siginfo; err = 0; } unlock_task_sighand(tracee, &flags); } return err; default: if (!write) { memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; info->si_code = context->stop_code & PTRACE_EVENT_MASK; info->si_pid = task_pid_vnr(tracee); info->si_uid = task_uid(tracee); } return 0; } } ptrace_request() uses this helper directly. The logic is very simple, we never check ->siginfo != NULL. If PTRACE_EVENT_SIGNAL, then ->siginfo must be valid. To protect against the race with SIGKILL we simply check task_is_traced() under ->siglock. With this change we don't care about how/when ->siginfo is changed. ptrace_rw_siginfo() could read ->siginfo lockeless, but this will complicate the code. Let's do this later if needed, the curent code takes ->siglock too. --- kernel/ptrace.c | 93 ++++++++++++++++++++------------------------------------ 1 file changed, 34 insertions(+), 59 deletions(-) --- PU/kernel/ptrace.c~73_SIGINFO_TWEAKS 2009-10-09 14:34:38.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 16:00:11.000000000 +0200 @@ -786,65 +786,40 @@ static int ptrace_rw_siginfo(struct task siginfo_t *info, bool write) { unsigned long flags; - siginfo_t *context_info; - int err = -ESRCH; - - if (!lock_task_sighand(tracee, &flags)) - return err; - /* - * Make sure the compiler reads ->siginfo only once, if we race - * with SIGKILL ->siginfo can be cleared under us. But the memory - * it points to can't go away, and since we hold ->siglock we can't - * race with get_signal_to_deliver() pathes clobber this memory. - * See also the comment in ptrace_report_signal(). - */ - context_info = ACCESS_ONCE(context->siginfo); - if (context_info) { - if (write) - *context_info = *info; - else - *info = *context_info; - err = 0; - } - unlock_task_sighand(tracee, &flags); - - return err; -} + int err; -static int ptrace_getsiginfo(struct ptrace_context *context, - struct task_struct *tracee, siginfo_t *info) -{ - /* jctl stop ? */ - if (!ptrace_event_pending(context)) + switch (get_stop_event(context)) { + case 0: /* jctl stop */ return -EINVAL; - if (context->siginfo) - return ptrace_rw_siginfo(tracee, context, info, false); - - memset(info, 0, sizeof(*info)); - info->si_signo = SIGTRAP; - info->si_code = context->stop_code & PTRACE_EVENT_MASK; - info->si_pid = task_pid_vnr(tracee); - info->si_uid = task_uid(tracee); - - return 0; -} + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *context->siginfo = *info; + else + *info = *context->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } -static int ptrace_setsiginfo(struct ptrace_context *context, - struct task_struct *tracee, siginfo_t *info) -{ - /* jctl stop ? */ - if (!ptrace_event_pending(context)) - return -EINVAL; + return err; - if (context->siginfo) - return ptrace_rw_siginfo(tracee, context, info, true); + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = context->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } - /* compatibility: pretend it was updated */ - return 0; + return 0; + } } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -1047,8 +1022,8 @@ int ptrace_request(struct task_struct *c break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(ptrace_context(engine), - child, &siginfo); + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); if (!ret) ret = copy_siginfo_to_user((siginfo_t __user *) data, &siginfo); @@ -1059,8 +1034,8 @@ int ptrace_request(struct task_struct *c sizeof siginfo)) ret = -EFAULT; else - ret = ptrace_setsiginfo(ptrace_context(engine), - child, &siginfo); + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); break; case PTRACE_DETACH: /* detach a process that was attached. */ @@ -1218,8 +1193,8 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETSIGINFO: - ret = ptrace_getsiginfo(ptrace_context(engine), - child, &siginfo); + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); if (!ret) ret = copy_siginfo_to_user32( (struct compat_siginfo __user *) datap, @@ -1232,8 +1207,8 @@ int compat_ptrace_request(struct task_st &siginfo, (struct compat_siginfo __user *) datap)) ret = -EFAULT; else - ret = ptrace_setsiginfo(ptrace_context(engine), - child, &siginfo); + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); break; default: From oleg at redhat.com Fri Oct 9 17:09:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:05 +0200 Subject: [PATCH 74-78] implement the partly detached engines Message-ID: <20091009170905.GA3984@redhat.com> Untested. For review/discussion. Oleg. From oleg at redhat.com Fri Oct 9 17:09:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:07 +0200 Subject: [PATCH 74] implement the basic detach-with-signal logic Message-ID: <20091009170907.GA3992@redhat.com> Introduce detach_signal(sig) helper. It is called by ptrace_detach_task() instead of removed ptrace_do_detach()->send_sig(). !valid_signal(sig) means that the tracer exits and detaches implicitly. If sig == 0 - nothing to do, just detach and return. If the tracee reported the signal, it will be cancelled. If sig != 0, the tracee should process the reported signal. Currently we call send_sig_info(). Also, handle PTRACE_EVENT_SYSCALL_XXX case. --- kernel/ptrace.c | 28 +++++++++++++++++++++++----- 1 file changed, 23 insertions(+), 5 deletions(-) --- PU/kernel/ptrace.c~74_DETACH_SIGNAL 2009-10-09 16:48:40.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 16:49:32.000000000 +0200 @@ -87,6 +87,25 @@ static struct utrace_engine *ptrace_look &ptrace_utrace_ops, NULL); } +static void detach_signal(struct task_struct *tracee, + struct ptrace_context *context, int sig) +{ + switch (get_stop_event(context)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (valid_signal(sig)) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (!valid_signal(sig)) + sig = context->signr; + if (sig) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + } +} + static void ptrace_detach_task(struct task_struct *child, int sig) { struct utrace_engine *engine = ptrace_lookup_engine(child); @@ -95,6 +114,9 @@ static void ptrace_detach_task(struct ta if (unlikely(IS_ERR(engine))) return; + if (sig) + detach_signal(child, ptrace_context(engine), sig); + ret = utrace_control(child, engine, UTRACE_DETACH); WARN_ON(ret && ret != -EINPROGRESS && ret != -ESRCH && ret != -EALREADY); @@ -676,12 +698,8 @@ static void ptrace_do_detach(struct task */ detach = tracee->ptrace != 0; release = false; - if (likely(detach)) { - // XXX: temporary hack - if (data && valid_signal(data)) - send_sig(data, tracee, 1); + if (likely(detach)) release = __ptrace_detach(current, tracee); - } write_unlock_irq(&tasklist_lock); if (unlikely(release)) From oleg at redhat.com Fri Oct 9 17:09:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:10 +0200 Subject: [PATCH 75] don't detach the engine with the parting signal Message-ID: <20091009170910.GA3995@redhat.com> The parting signal must not be visible to the next attacher. Compatibility! Change ptrace_detach_task() to set context->resume = UTRACE_DETACH and do utrace_control(UTRACE_RESUME) in case the tracee should process the signal. If the tracee is killed we don't care what will happen. Otherwise it ptrace_report_signal(UTRACE_SIGNAL_REPORT) must be called, it will return UTRACE_DETACH and complete the detach. TODO: - re-check UTRACE_SIGNAL_HANDLER is not possible - info->si_pid will be wrong if sig != si_signo. how can we fix this? can't we ignore the problem? upstream is buggy too, I hope we can - the next attach is not possible until the tracee does ptrace_report_signal(). Fixed by the next patches. --- kernel/ptrace.c | 21 ++++++++++++++------- 1 file changed, 14 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~75_DETACHED_ENGINE 2009-10-09 16:49:32.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 17:14:30.000000000 +0200 @@ -87,9 +87,12 @@ static struct utrace_engine *ptrace_look &ptrace_utrace_ops, NULL); } -static void detach_signal(struct task_struct *tracee, +static enum utrace_resume_action +detach_signal(struct task_struct *tracee, struct ptrace_context *context, int sig) { + enum utrace_resume_action action = UTRACE_DETACH; + switch (get_stop_event(context)) { case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: @@ -98,26 +101,30 @@ static void detach_signal(struct task_st break; case PTRACE_EVENT_SIGNAL: - if (!valid_signal(sig)) - sig = context->signr; - if (sig) - send_sig_info(sig, SEND_SIG_PRIV, tracee); + if (valid_signal(sig)) + context->signr = sig; + context->stop_code = 0; + context->resume = UTRACE_DETACH; + action = UTRACE_RESUME; break; } + + return action; } static void ptrace_detach_task(struct task_struct *child, int sig) { struct utrace_engine *engine = ptrace_lookup_engine(child); + enum utrace_resume_action action = UTRACE_DETACH; int ret; if (unlikely(IS_ERR(engine))) return; if (sig) - detach_signal(child, ptrace_context(engine), sig); + action = detach_signal(child, ptrace_context(engine), sig); - ret = utrace_control(child, engine, UTRACE_DETACH); + ret = utrace_control(child, engine, action); WARN_ON(ret && ret != -EINPROGRESS && ret != -ESRCH && ret != -EALREADY); From oleg at redhat.com Fri Oct 9 17:09:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:12 +0200 Subject: [PATCH 76] fold detach_signal() into ptrace_detach_task() Message-ID: <20091009170912.GA4002@redhat.com> Hmm. Looks like this helper buys nothing but complicates the reading, move the code into ptrace_detach_task(). Also s/ret/err/ and s/child/tracee/. --- kernel/ptrace.c | 57 +++++++++++++++++++++++--------------------------------- 1 file changed, 24 insertions(+), 33 deletions(-) --- PU/kernel/ptrace.c~76_KILL_DETACH_SIGNAL 2009-10-09 17:14:30.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 18:51:56.000000000 +0200 @@ -87,46 +87,37 @@ static struct utrace_engine *ptrace_look &ptrace_utrace_ops, NULL); } -static enum utrace_resume_action -detach_signal(struct task_struct *tracee, - struct ptrace_context *context, int sig) -{ - enum utrace_resume_action action = UTRACE_DETACH; - - switch (get_stop_event(context)) { - case PTRACE_EVENT_SYSCALL_ENTRY: - case PTRACE_EVENT_SYSCALL_EXIT: - if (valid_signal(sig)) - send_sig_info(sig, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - if (valid_signal(sig)) - context->signr = sig; - context->stop_code = 0; - context->resume = UTRACE_DETACH; - action = UTRACE_RESUME; - break; - } - - return action; -} - -static void ptrace_detach_task(struct task_struct *child, int sig) +static void ptrace_detach_task(struct task_struct *tracee, int sig) { - struct utrace_engine *engine = ptrace_lookup_engine(child); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + struct ptrace_context *context = ptrace_context(engine); enum utrace_resume_action action = UTRACE_DETACH; - int ret; + int err; if (unlikely(IS_ERR(engine))) return; - if (sig) - action = detach_signal(child, ptrace_context(engine), sig); + if (sig) { + switch (get_stop_event(context)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (valid_signal(sig)) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; - ret = utrace_control(child, engine, action); - WARN_ON(ret && ret != -EINPROGRESS && - ret != -ESRCH && ret != -EALREADY); + case PTRACE_EVENT_SIGNAL: + if (valid_signal(sig)) + context->signr = sig; + context->stop_code = 0; + context->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + err = utrace_control(tracee, engine, action); + WARN_ON(err && err != -EINPROGRESS && + err != -ESRCH && err != -EALREADY); utrace_engine_put(engine); } From oleg at redhat.com Fri Oct 9 17:09:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:14 +0200 Subject: [PATCH 77] implement UTRACE_ATTACH_MATCH_CHECK Message-ID: <20091009170914.GA4005@redhat.com> Implement UTRACE_ATTACH_MATCH_CHECK. With this flag utrace_attach_task(data) "data" is the function pointer which checks engine->data instead of simple comparison. Todo: comment + rename. --- include/linux/utrace.h | 1 + kernel/utrace.c | 5 +++++ 2 files changed, 6 insertions(+) --- PU/include/linux/utrace.h~77_UTRACE_MATCH_FILTER 2009-10-09 18:51:56.000000000 +0200 +++ PU/include/linux/utrace.h 2009-10-09 19:02:34.000000000 +0200 @@ -303,6 +303,7 @@ static inline enum utrace_syscall_action #define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ #define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ #define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ +#define UTRACE_ATTACH_MATCH_CHECK 0x0004 /* Match engines on ????. */ #define UTRACE_ATTACH_MATCH_MASK 0x000f /** --- PU/kernel/utrace.c~77_UTRACE_MATCH_FILTER 2009-10-09 18:51:56.000000000 +0200 +++ PU/kernel/utrace.c 2009-10-09 19:04:05.000000000 +0200 @@ -92,6 +92,11 @@ static bool engine_matches(struct utrace return false; if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) return false; + if (flags & UTRACE_ATTACH_MATCH_CHECK) { + bool (*check)(void*) = data; + if (!check(engine->data)) + return false; + } return engine->ops && engine->ops != &utrace_detached_ops; } From oleg at redhat.com Fri Oct 9 17:09:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 9 Oct 2009 19:09:17 +0200 Subject: [PATCH 78] attach: try to re-use the self-detaching engine Message-ID: <20091009170917.GA4008@redhat.com> Change ptrace_attach_task() to re-use the self-detaching engine first, then do utrace_attach_task(UTRACE_ATTACH_CREATE). Todo: - re-check this all (and test) - rename check() - cleanups the mess in ptrace_attach_task() - ptrace_detach_task() should clear options/flags, if we re-use this engine then ptrace_attach_task()->utrace_set_events() happens a bit late. --- kernel/ptrace.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) --- PU/kernel/ptrace.c~78_REUSE_PARTING_ENGINE 2009-10-09 18:51:56.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-09 19:04:34.000000000 +0200 @@ -431,6 +431,15 @@ static inline int __ptrace_set_options(s return utrace_set_events(target, engine, events); } +static bool check(void *data) +{ + struct ptrace_context *context = data; + if (context->resume != UTRACE_DETACH) + return false; + context->resume = UTRACE_RESUME; + return true; +} + /* * Attach a utrace engine for ptrace and set up its event mask. * Returns error code or 0 on success. @@ -441,6 +450,20 @@ static int ptrace_attach_task(struct tas struct utrace_engine *engine; int err; + engine = utrace_attach_task(tracee, UTRACE_ATTACH_MATCH_OPS | + UTRACE_ATTACH_MATCH_CHECK, + &ptrace_utrace_ops, check); + if (!IS_ERR(engine)) { + /* + * Make sure we don't race with ptrace_report_signal() + */ + utrace_barrier(tracee, engine); + if (engine->ops != &ptrace_utrace_ops) + utrace_engine_put(engine); + else + goto finish; + } + context = kzalloc(sizeof(*context), GFP_KERNEL); if (unlikely(!context)) return -ENOMEM; @@ -458,6 +481,7 @@ static int ptrace_attach_task(struct tas kfree(context); return err; } +finish: /* * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED. From oleg at redhat.com Sat Oct 10 15:01:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 17:01:02 +0200 Subject: [PATCH 77] implement UTRACE_ATTACH_MATCH_CHECK In-Reply-To: <20091009170914.GA4005@redhat.com> References: <20091009170914.GA4005@redhat.com> Message-ID: <20091010150102.GA3857@redhat.com> Roland, please ignore this and the next patch. We can do the same without UTRACE_ATTACH_MATCH_CHECK. I don't like to rely on ->cred_guard_mutex, but MATCH_CHECK is not nice too. On 10/09, Oleg Nesterov wrote: > > Implement UTRACE_ATTACH_MATCH_CHECK. With this flag utrace_attach_task(data) > "data" is the function pointer which checks engine->data instead of simple > comparison. > > Todo: comment + rename. > > --- > > include/linux/utrace.h | 1 + > kernel/utrace.c | 5 +++++ > 2 files changed, 6 insertions(+) > > --- PU/include/linux/utrace.h~77_UTRACE_MATCH_FILTER 2009-10-09 18:51:56.000000000 +0200 > +++ PU/include/linux/utrace.h 2009-10-09 19:02:34.000000000 +0200 > @@ -303,6 +303,7 @@ static inline enum utrace_syscall_action > #define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ > #define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ > #define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ > +#define UTRACE_ATTACH_MATCH_CHECK 0x0004 /* Match engines on ????. */ > #define UTRACE_ATTACH_MATCH_MASK 0x000f > > /** > --- PU/kernel/utrace.c~77_UTRACE_MATCH_FILTER 2009-10-09 18:51:56.000000000 +0200 > +++ PU/kernel/utrace.c 2009-10-09 19:04:05.000000000 +0200 > @@ -92,6 +92,11 @@ static bool engine_matches(struct utrace > return false; > if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) > return false; > + if (flags & UTRACE_ATTACH_MATCH_CHECK) { > + bool (*check)(void*) = data; > + if (!check(engine->data)) > + return false; > + } > return engine->ops && engine->ops != &utrace_detached_ops; > } > From oleg at redhat.com Sat Oct 10 16:16:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:16:53 +0200 Subject: [PATCH 79-83] self-detaching fixes Message-ID: <20091010161653.GA12147@redhat.com> Please ignore [PATCH 77] implement UTRACE_ATTACH_MATCH_CHECK [PATCH 78] attach: try to re-use the self-detaching engine patches. Oleg. From oleg at redhat.com Sat Oct 10 16:16:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:16:56 +0200 Subject: [PATCH 79] ptrace_detach_task: don't use engine ptr before IS_ERR(engine) Message-ID: <20091010161656.GA12150@redhat.com> "[PATCH 76] fold detach_signal() into ptrace_detach_task()" was buggy, we read engine->date before checking IS_ERR(engine). --- kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~79_FIX_DETACH_ENGINE_DEREF 2009-10-10 17:06:11.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 17:09:34.000000000 +0200 @@ -90,7 +90,6 @@ static struct utrace_engine *ptrace_look static void ptrace_detach_task(struct task_struct *tracee, int sig) { struct utrace_engine *engine = ptrace_lookup_engine(tracee); - struct ptrace_context *context = ptrace_context(engine); enum utrace_resume_action action = UTRACE_DETACH; int err; @@ -98,6 +97,8 @@ static void ptrace_detach_task(struct ta return; if (sig) { + struct ptrace_context *context = ptrace_context(engine); + switch (get_stop_event(context)) { case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: From oleg at redhat.com Sat Oct 10 16:17:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:17:01 +0200 Subject: [PATCH 80] ptrace_notify_stop: fix engine leak Message-ID: <20091010161701.GA12157@redhat.com> ptrace_notify_stop() forgets to put engine. Also, move WARN_ON() into do_ptrace_notify_stop(). --- kernel/ptrace.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) --- PU/kernel/ptrace.c~80_FIX_ENGINE_LEAK 2009-10-10 17:09:34.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 17:10:07.000000000 +0200 @@ -859,6 +859,8 @@ static void do_ptrace_notify_stop(struct struct task_struct *tracee) { tracee->exit_code = context->stop_code & PTRACE_EVENT_MASK; + if (WARN_ON(!tracee->exit_code)) + return; read_lock(&tasklist_lock); /* @@ -876,7 +878,6 @@ static void do_ptrace_notify_stop(struct void ptrace_notify_stop(struct task_struct *tracee) { struct utrace_engine *engine = ptrace_lookup_engine(tracee); - struct ptrace_context *context; if (IS_ERR(engine)) { // XXX: temporary check, wrong with mutlitracing @@ -884,10 +885,8 @@ void ptrace_notify_stop(struct task_stru return; } - context = ptrace_context(engine); - if (WARN_ON(!ptrace_event_pending(context))) - return; - do_ptrace_notify_stop(context, tracee); + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); } static void ptrace_wake_up(struct utrace_engine *engine, From oleg at redhat.com Sat Oct 10 16:17:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:17:05 +0200 Subject: [PATCH 81] attach: try to re-use the self-detaching engine Message-ID: <20091010161705.GA12164@redhat.com> Change ptrace_attach_task() to re-use the self-detaching engine first, then do utrace_attach_task(UTRACE_ATTACH_CREATE). Unlike the previous version, ptrace_attach_task() just calls ptrace_lookup_engine() and changes context->resume. The only caller which can find the self-attaching engine is ptrace_atttach(), we can rely on ->cred_guard_mutex. Todo: re-check this all and cleanup the mess in ptrace_attach_task(). But first I'd like to know if you agree with this approach. --- kernel/ptrace.c | 17 +++++++++++++++++ 1 file changed, 17 insertions(+) --- PU/kernel/ptrace.c~81_REUSE_DETACHING_ENGINE 2009-10-10 17:10:07.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 17:13:37.000000000 +0200 @@ -442,6 +442,22 @@ static int ptrace_attach_task(struct tas struct utrace_engine *engine; int err; + engine = ptrace_lookup_engine(tracee); + if (!IS_ERR(engine)) { + context = ptrace_context(engine); + if (context->resume == UTRACE_DETACH) { + /* we rely on ->cred_guard_mutex */ + context->resume = UTRACE_RESUME; + /* + * Make sure we don't race with ptrace_report_signal() + */ + utrace_barrier(tracee, engine); + if (engine->ops == &ptrace_utrace_ops) + goto finish; + } + utrace_engine_put(engine); + } + context = kzalloc(sizeof(*context), GFP_KERNEL); if (unlikely(!context)) return -ENOMEM; @@ -459,6 +475,7 @@ static int ptrace_attach_task(struct tas kfree(context); return err; } +finish: /* * It can fail only if the tracee is dead, the caller * must notice this before setting PT_PTRACED. From oleg at redhat.com Sat Oct 10 16:17:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:17:09 +0200 Subject: [PATCH 82] detach should reset the context of self-detaching engine Message-ID: <20091010161709.GA12167@redhat.com> Make sure that the new debugger doesn't get the old values in ptrace_context or engine->flags if it re-uses the self-detaching engine. In particular, we should clear tracee->exit_code. The new debugger should not see it via do_wait() until the tracee stops again. This is racy, but ->exit_code changes were always racy in ptrace. Hopefully sooner or later ptrace will not use ->exit_code at all. Perhaps we should move this reinitialization into ptrace_attach_task(), we will see. Perhaps, instead of utrace_control() ptrace_detach_task() should use ptrace_wake_up() which clears SIGNAL_STOP_STOPPED. This is wrong, but more compatible with the current implementation. I dunno. --- kernel/ptrace.c | 9 +++++++++ 1 file changed, 9 insertions(+) --- PU/kernel/ptrace.c~82_RESET_CONTEXT_ON_DETACH 2009-10-10 17:13:37.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 17:43:28.000000000 +0200 @@ -109,7 +109,16 @@ static void ptrace_detach_task(struct ta case PTRACE_EVENT_SIGNAL: if (valid_signal(sig)) context->signr = sig; + context->options = 0; + context->eventmsg = 0; context->stop_code = 0; + /* make sure do_wait() can't succeed */ + tracee->exit_code = 0; + utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + /* + * once we set UTRACE_DETACH we don't own this engine, + * utrace_set_events() also acts as a memory barrier. + */ context->resume = UTRACE_DETACH; action = UTRACE_RESUME; break; From oleg at redhat.com Sat Oct 10 16:17:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:17:12 +0200 Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee Message-ID: <20091010161712.GA12175@redhat.com> Roland, Jan, what user-space expects ptrace(DETACH, SIGKILL) should do? My guess: this should really kill the tracee asap, hence this patch. --- kernel/ptrace.c | 5 +++++ 1 file changed, 5 insertions(+) --- PU/kernel/ptrace.c~83_DETACH_SIGKILL 2009-10-10 17:43:28.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-10 18:08:45.000000000 +0200 @@ -107,6 +107,11 @@ static void ptrace_detach_task(struct ta break; case PTRACE_EVENT_SIGNAL: + if (sig == SIGKILL) { + send_sig_info(sig, SEND_SIG_NOINFO, tracee); + break; + } + if (valid_signal(sig)) context->signr = sig; context->options = 0; From oleg at redhat.com Sat Oct 10 16:24:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:24:21 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091006143911.GA7071@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> Message-ID: <20091010162421.GA12281@redhat.com> On 10/06, Jan Kratochvil wrote: > > Yes, I agree with the current general behavior of ptrace there is missing: > if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > > [...snip...] > > --- attach-into-signal.c 31 Jan 2009 21:11:40 -0000 1.5 > +++ attach-into-signal.c 6 Oct 2009 14:27:08 -0000 > @@ -224,6 +224,18 @@ static void reproduce (void) > child = 0; > return; > } > + /* SIGPIPE was still pending and it has not been yet delivered. */ > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > + { > + /* Deliver it and get the queued SIGSTOP. */ > + errno = 0; > + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); > + assert_perror (errno); > + > + errno = 0; > + pid = waitpid (child, &status, 0); > + assert (pid == child); > + } > assert (WIFSTOPPED (status)); > assert (WSTOPSIG (status) == SIGSTOP); > /* let tracee run. it must be killed very soon by SIGPIPE */ Jan, please revert this change. Roland thinks we should keep this behaviour, this means attach-into-signal.c checks (in particular) exactly what we want: the new attach must not see SIGPIPE. With the recent patches utrace-ptrace passes this test-case too. Oleg. From oleg at redhat.com Sat Oct 10 16:40:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:40:18 +0200 Subject: utrace-ptrace && ptrace_check_attach() Message-ID: <20091010164018.GA13218@redhat.com> Issues with ptrace_check_attach(), - it does utrace_control(UTRACE_STOP). This is wrong, ptrace_check_attach() must be "passive", while utrace_control(UTRACE_STOP) can actualy stop the tracee. - even if it doesn't, this is wrong when we have multiple tracers. ptrace_check_attach() should not succeed if the tracee was stopped by another engine. - it ignores "int kill". Can we ignore these problems in V1 ? Or should we fix something? Oleg. From jan.kratochvil at redhat.com Sat Oct 10 16:48:26 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sat, 10 Oct 2009 18:48:26 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091010162421.GA12281@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091010162421.GA12281@redhat.com> Message-ID: <20091010164825.GA12387@host0.dyn.jankratochvil.net> On Sat, 10 Oct 2009 18:24:21 +0200, Oleg Nesterov wrote: > On 10/06, Jan Kratochvil wrote: > > > > Yes, I agree with the current general behavior of ptrace there is missing: > > if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > > > > [...snip...] > > > > --- attach-into-signal.c 31 Jan 2009 21:11:40 -0000 1.5 > > +++ attach-into-signal.c 6 Oct 2009 14:27:08 -0000 > > @@ -224,6 +224,18 @@ static void reproduce (void) > > child = 0; > > return; > > } > > + /* SIGPIPE was still pending and it has not been yet delivered. */ > > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > > + { > > + /* Deliver it and get the queued SIGSTOP. */ > > + errno = 0; > > + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); > > + assert_perror (errno); > > + > > + errno = 0; > > + pid = waitpid (child, &status, 0); > > + assert (pid == child); > > + } > > assert (WIFSTOPPED (status)); > > assert (WSTOPSIG (status) == SIGSTOP); > > /* let tracee run. it must be killed very soon by SIGPIPE */ > > Jan, please revert this change. Reverted (VERBOSE-caught with FAIL now). Jan From oleg at redhat.com Sat Oct 10 16:48:29 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 18:48:29 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091010164825.GA12387@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091010162421.GA12281@redhat.com> <20091010164825.GA12387@host0.dyn.jankratochvil.net> Message-ID: <20091010164829.GA13521@redhat.com> On 10/10, Jan Kratochvil wrote: > > On Sat, 10 Oct 2009 18:24:21 +0200, Oleg Nesterov wrote: > > On 10/06, Jan Kratochvil wrote: > > > > > > Yes, I agree with the current general behavior of ptrace there is missing: > > > if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > > > > > > [...snip...] > > > > > > --- attach-into-signal.c 31 Jan 2009 21:11:40 -0000 1.5 > > > +++ attach-into-signal.c 6 Oct 2009 14:27:08 -0000 > > > @@ -224,6 +224,18 @@ static void reproduce (void) > > > child = 0; > > > return; > > > } > > > + /* SIGPIPE was still pending and it has not been yet delivered. */ > > > + if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > > > + { > > > + /* Deliver it and get the queued SIGSTOP. */ > > > + errno = 0; > > > + ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); > > > + assert_perror (errno); > > > + > > > + errno = 0; > > > + pid = waitpid (child, &status, 0); > > > + assert (pid == child); > > > + } > > > assert (WIFSTOPPED (status)); > > > assert (WSTOPSIG (status) == SIGSTOP); > > > /* let tracee run. it must be killed very soon by SIGPIPE */ > > > > Jan, please revert this change. > > Reverted Thanks! > (VERBOSE-caught with FAIL now). Cough. please translate this to me ;) Oleg. From jan.kratochvil at redhat.com Sat Oct 10 17:16:28 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sat, 10 Oct 2009 19:16:28 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091010164829.GA13521@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091010162421.GA12281@redhat.com> <20091010164825.GA12387@host0.dyn.jankratochvil.net> <20091010164829.GA13521@redhat.com> Message-ID: <20091010171628.GA14763@host0.dyn.jankratochvil.net> On Sat, 10 Oct 2009 18:48:29 +0200, Oleg Nesterov wrote: > On 10/10, Jan Kratochvil wrote: > > (VERBOSE-caught with FAIL now). > > Cough. please translate this to me ;) (Cc of each such mail to Roland does not look OK to me but removing Ccs is also not OK) --- tests/attach-into-signal.c 6 Oct 2009 19:21:35 -0000 1.6 +++ tests/attach-into-signal.c 10 Oct 2009 16:47:46 -0000 1.7 @@ -227,14 +227,8 @@ static void reproduce (void) /* SIGPIPE was still pending and it has not been yet delivered. */ if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) { - /* Deliver it and get the queued SIGSTOP. */ - errno = 0; - ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); - assert_perror (errno); - - errno = 0; - pid = waitpid (child, &status, 0); - assert (pid == child); + VERBOSE ("Forbidden to catch pending signal from PTRACE_DETACH"); + exit (1); } assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGSTOP); From oleg at redhat.com Sat Oct 10 17:17:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 19:17:55 +0200 Subject: utrace-ptrace && detach with signal semantics In-Reply-To: <20091010171628.GA14763@host0.dyn.jankratochvil.net> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091010162421.GA12281@redhat.com> <20091010164825.GA12387@host0.dyn.jankratochvil.net> <20091010164829.GA13521@redhat.com> <20091010171628.GA14763@host0.dyn.jankratochvil.net> Message-ID: <20091010171755.GA14853@redhat.com> On 10/10, Jan Kratochvil wrote: > > On Sat, 10 Oct 2009 18:48:29 +0200, Oleg Nesterov wrote: > > On 10/10, Jan Kratochvil wrote: > > > (VERBOSE-caught with FAIL now). > > > > Cough. please translate this to me ;) > > (Cc of each such mail to Roland does not look OK to me but removing Ccs is > also not OK) I think always-reply-to-all is the best policy ;) > --- tests/attach-into-signal.c 6 Oct 2009 19:21:35 -0000 1.6 > +++ tests/attach-into-signal.c 10 Oct 2009 16:47:46 -0000 1.7 > @@ -227,14 +227,8 @@ static void reproduce (void) > /* SIGPIPE was still pending and it has not been yet delivered. */ > if (WIFSTOPPED (status) && WSTOPSIG (status) == SIGPIPE) > { > - /* Deliver it and get the queued SIGSTOP. */ > - errno = 0; > - ptrace (PTRACE_CONT, child, (void *) 1, (void *) SIGPIPE); > - assert_perror (errno); > - > - errno = 0; > - pid = waitpid (child, &status, 0); > - assert (pid == child); > + VERBOSE ("Forbidden to catch pending signal from PTRACE_DETACH"); > + exit (1); I see, thanks. Oleg. From jan.kratochvil at redhat.com Sat Oct 10 17:40:25 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sat, 10 Oct 2009 19:40:25 +0200 Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee In-Reply-To: <20091010161712.GA12175@redhat.com> References: <20091010161712.GA12175@redhat.com> Message-ID: <20091010174025.GA17728@host0.dyn.jankratochvil.net> On Sat, 10 Oct 2009 18:17:12 +0200, Oleg Nesterov wrote: > Roland, Jan, what user-space expects ptrace(DETACH, SIGKILL) should do? > > My guess: this should really kill the tracee asap, hence this patch. attached testcase works for me on both: kernel-2.6.31.1-48.fc12.x86_64 kernel-2.6.30.5-43.fc11.x86_64 does it FAIL for you to make it worth to the testsuite? Thanks, Jan -------------- next part -------------- /* Test case for (PTRACE_DETACH, SIGKILL) really does kill the tracee. This software is provided 'as-is', without any express or implied warranty. In no event will the authors be held liable for any damages arising from the use of this software. Permission is granted to anyone to use this software for any purpose, including commercial applications, and to alter it and redistribute it freely. */ #define _GNU_SOURCE 1 #include #include #include #include #include #include #include #include static pid_t child; static void cleanup (void) { if (child > 0) kill (child, SIGKILL); child = 0; } static void handler_fail (int signo) { cleanup (); signal (signo, SIG_DFL); raise (signo); } int main (void) { pid_t got_pid; int status; long l; atexit (cleanup); signal (SIGABRT, handler_fail); signal (SIGINT, handler_fail); child = fork (); switch (child) { case -1: assert_perror (errno); case 0: l = ptrace (PTRACE_TRACEME, 0, NULL, NULL); assert (l == 0); raise (SIGUSR1); _exit (42); default: break; } got_pid = waitpid (child, &status, 0); assert (got_pid == child); assert (WIFSTOPPED (status)); assert (WSTOPSIG (status) == SIGUSR1); errno = 0; l = ptrace (PTRACE_DETACH, child, NULL, (void *) (long) SIGKILL); assert_perror (errno); assert (l == 0); got_pid = waitpid (child, &status, 0); assert (got_pid == child); assert (WIFSIGNALED (status)); assert (WTERMSIG (status) == SIGKILL); return 0; } From oleg at redhat.com Sat Oct 10 17:58:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 10 Oct 2009 19:58:10 +0200 Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee In-Reply-To: <20091010174025.GA17728@host0.dyn.jankratochvil.net> References: <20091010161712.GA12175@redhat.com> <20091010174025.GA17728@host0.dyn.jankratochvil.net> Message-ID: <20091010175810.GA16460@redhat.com> On 10/10, Jan Kratochvil wrote: > > On Sat, 10 Oct 2009 18:17:12 +0200, Oleg Nesterov wrote: > > Roland, Jan, what user-space expects ptrace(DETACH, SIGKILL) should do? > > > > My guess: this should really kill the tracee asap, hence this patch. > > attached testcase works for me on both: > kernel-2.6.31.1-48.fc12.x86_64 > kernel-2.6.30.5-43.fc11.x86_64 > > does it FAIL for you to make it worth to the testsuite? The changelog is not very clear, sorry. Sure ptrace(DETACH, SIGKILL) works. Because currently detach always wakes up the tracee. This should be fixed later, detach shouldn't break the group-stop logic. So, the point of this patch is: even we the tracee should be leaved in TASK_STOPPED state, or we have another tracer which wants this tracee to be stopped, SIGKILL must work and kille the tracee. > child = fork (); > switch (child) > { > case -1: > assert_perror (errno); > > case 0: > l = ptrace (PTRACE_TRACEME, 0, NULL, NULL); > assert (l == 0); > > raise (SIGUSR1); > _exit (42); > > default: > break; > } > > got_pid = waitpid (child, &status, 0); > assert (got_pid == child); > assert (WIFSTOPPED (status)); > assert (WSTOPSIG (status) == SIGUSR1); > > errno = 0; > l = ptrace (PTRACE_DETACH, child, NULL, (void *) (long) SIGKILL); > assert_perror (errno); > assert (l == 0); > > got_pid = waitpid (child, &status, 0); > assert (got_pid == child); > assert (WIFSIGNALED (status)); > assert (WTERMSIG (status) == SIGKILL); I don't think this test-case is "interesting" in its current form. It can't prove SIGKILL does something special, and I think currently we can't test this. Oleg. From newsletter at rmcvisual.upmailer.com Fri Oct 9 04:25:22 2009 From: newsletter at rmcvisual.upmailer.com (RMC Visual) Date: Fri, 09 Oct 2009 00:25:22 -0400 Subject: Superando Obstaculos? Message-ID: Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://rmcvisual.upmailer.com/display.php?M=309182&C=fe48d7073cbf85b959d4a0955d861d03&S=5&L=5&N=4 Para parar de receber nossos e-mails:http://rmcvisual.upmailer.com/unsubscribe.php?M=309182&C=fe48d7073cbf85b959d4a0955d861d03&L=5&N=5 Desenvolvido por UpMailer -------------- next part -------------- An HTML attachment was scrubbed... URL: From noburin at sorabji.com Sun Oct 11 21:26:23 2009 From: noburin at sorabji.com (Liz Norwood) Date: Sun, 11 Oct 2009 16:26:23 -0500 Subject: 10 reasons to take enhancing medicaments. Message-ID: <001601ca4ab1$19a34e00$bc9b717f@shafintpc1sgn> Turn yourbedroom into paradise of pleasure. http://weole.noznicichef.com/ From roland at redhat.com Mon Oct 12 00:29:23 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 17:29:23 -0700 (PDT) Subject: Stopped detach/attach status In-Reply-To: Oleg Nesterov's message of Thursday, 8 October 2009 18:06:58 +0200 <20091008160658.GA15768@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> Message-ID: <20091012002924.019E6C8@magilla.sf.frob.com> > Yes. In particular, ptrace(PTRACE_DETACH, SIGKILL) should cancel > SIGNAL_STOP_STOPPED, yes? Yes. > > > - sig->flags = SIGNAL_STOP_STOPPED; > > > + sig->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED; > > > > Boy, do I not understand why that does anything about this at all! > > But I am barely awake tonight. Ok, I guess I do sort of if it goes > > along with some other patch to set SIGNAL_STOP_STOPPED. But since > > you've verified you really understand what happens, you can tell us! I actually thought of it right after I sent this, but I was too tired to follow up then. It's good that you've posted this particular concrete scenario to document it more fully. Here's the way I think about that: SIGNAL_STOP_DEQUEUED exists for one purpose. It's to ensure that SIGCONT and SIGKILL can clear it to make complete their required effect of clearing all pending stop signals. (It fills the hole when another thread has dequeued a stop signal and then dropped the siglock to make its call to is_current_pgrp_orphaned()--so that half-delivered signal is still considered "pending" and thus must be cancelled by SIGCONT or SIGKILL.) In the debugger case, there is a far larger hole possible, where a thread has dequeued a stop signal and then dropped the siglock to block for an arbitrary period while the debugger contemplates the signal. But to me this is really the same case as far as the signal semantics are concerned. When the debugger decides to send the signal on, it then picks up in the same "half-delivered" situation and goes the rest of the way. What I've just described is a simple "race" with an external SIGCONT or SIGKILL. This maps exactly to the is_current_pgrp_orphaned() window--it's just a window that can easily be far larger, and can be kept open forever and so to the debugger user with global perspective can be observed as a "non-racey" hole (hit SIGTSTP in the debugger, send SIGCONT from another terminal, continue in the debugger). Now, the case we are considering really is different from that race. But I think the same essential logic applies: you have a half-delivered stop signal "in flight", so either there has been a SIGCONT or SIGKILL to cancel it, or there hasn't. Since there hasn't, nothing should prevent the normal operation of that stop signal's final delivery. It's a bug that something does. Another way to put it is to say that the "exists for one purpose" statement above implies that only an actual SIGCONT or SIGKILL should ever clear SIGNAL_STOP_DEQUEUED. In fact, only one place clears the flag explicitly, but six others do so implicitly. The one explicit place and one of the implicit places is the one that clearly should: the SIGCONT case in prepare_signal(). Three implicit places are the ->flags = SIGNAL_GROUP_EXIT cases (zap_process, do_group_exit, complete_signal). These are harmless because they are already effectively mutually exclusive, since the one check of SIGNAL_STOP_DEQUEUED is: if (!likely(sig->flags & SIGNAL_STOP_DEQUEUED) || unlikely(signal_group_exit(sig))) return 0; The remaining two places are the ->flags = SIGNAL_STOP_STOPPED cases in do_signal_stop and exit_signals. Since SIGNAL_STOP_DEQUEUED must always have been set before if you can get to those situations, it is harmless to use "->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED" instead of: sig->flags &= SIGNAL_STOP_DEQUEUED; sig->flags |= SIGNAL_STOP_STOPPED; or anything like that. It's probably cleanest to consolidate those two cases to call a single subroutine that does the tracehook_notify_jctl logic, unlock and do_notify_parent_cldstop. It can take a caller flag or just check PF_EXITING to omit the ->exit_code + ->state change of the do_signal_stop version of the code. That one subroutine can have a clear comment about the nonobvious flag usage. > But please remember, the patch above is not complete of course and currently > I do not see the good solution. What's incomplete aside from handling the exit_signals case the same way? > I am starting to think we should forget > about these bugs, merge utrace-ptrace, and then try to fix them. If we can have utrace-ptrace code whose corner behavior matches the old code and is itself clean, then I don't care about the order of the changes going in. But it's not really clear to me that we can even describe the old behavior in terms clean enough to make an exact work-alike implementation that could possibly be clean. Thanks, Roland From roland at redhat.com Mon Oct 12 00:48:59 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 17:48:59 -0700 (PDT) Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee In-Reply-To: Oleg Nesterov's message of Saturday, 10 October 2009 18:17:12 +0200 <20091010161712.GA12175@redhat.com> References: <20091010161712.GA12175@redhat.com> Message-ID: <20091012004859.755F1C8@magilla.sf.frob.com> > Roland, Jan, what user-space expects ptrace(DETACH, SIGKILL) should do? > > My guess: this should really kill the tracee asap, hence this patch. As far as killing, it is no more reliable than PTRACE_CONT,SIGKILL. i.e., will fail if it's not stopped, will be dropped on the floor if stopped at PTRACE_EVENT_EXEC et al. So I would not especially try to make it any more reliable than that, especially if it takes a special case kludge like that. For "make it die now", I have been advising people for years to just use plain kill(,SIGKILL). That is the one thing we have worked the longest and most consistently to keep reliable in making things really die really soon. The one thing that anyone using PTRACE_DETACH,SIGKILL does perhaps expect is that the detaching and killing are atomic. That is, it's not possible for another thread in the tracer's process to get the WIFEXITED wait result for the tracee. Conversely, that race is possible if the tracer does: kill(pid, SIGKILL); ptrace(PTRACE_DETACH, pid, anything); (And a tracer doesn't want to do them in the other order if it wants to be sure to go from stopped->dead with no chance of running more user code.) So IMHO that is the only special wrinkle of PTRACE_DETACH,SIGKILL we need to worry about for compatibility. In other senses it needs to work no better or different from PTRACE_CONT,SIGKILL. Thanks, Roland From roland at redhat.com Mon Oct 12 01:39:02 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 18:39:02 -0700 (PDT) Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Saturday, 10 October 2009 18:40:18 +0200 <20091010164018.GA13218@redhat.com> References: <20091010164018.GA13218@redhat.com> Message-ID: <20091012013902.C8AD31D2@magilla.sf.frob.com> > Issues with ptrace_check_attach(), > > - it does utrace_control(UTRACE_STOP). > > This is wrong, ptrace_check_attach() must be "passive", > while utrace_control(UTRACE_STOP) can actualy stop the > tracee. This is not inherently problematic on its own. I'd say it's OK if you have to actually be the tracer task to get that far, and of course if you call utrace_control(UTRACE_RESUME) to reverse it in the failure case. The UTRACE_STOP itself does not have any effect that the tracee can observe except as scheduling flutter. (I'm not really counting it cooperating with another process that does "ps" and sees "T"--we can live with that too.) If the actual tracer making stupid use of ptrace calls that will wind up failing with ESRCH has the side effect of lousing up the scheduling of the tracee it's failing to otherwise molest, so be it. It's a security issue if you can do UTRACE_STOP on a task that you would not be allowed to ptrace, even for an instant. It's at least quite undesireable if you ever do that on a task other than one you do actually have attached for ptrace. If we can avoid those, don't worry about the rest. For the tracer itself, any UTRACE_STOP is "passive enough" if compensated with a UTRACE_RESUME. Just stay away from UTRACE_INTERRUPT and you are being "passive" by my lights. > - even if it doesn't, this is wrong when we have multiple > tracers. ptrace_check_attach() should not succeed if the > tracee was stopped by another engine. Yes. UTRACE_STOP state is necessary for ptrace to consider the tracee to be "in ptrace stop", but it's not sufficient. Ensuring UTRACE_STOP is the mechanism for the underlying material effect that "in ptrace stop" means, i.e. in (or on the way into) TASK_TRACED until SIGKILL. Since we use UTRACE_STOP in report returns to implement ptrace stops, this is normally already the case in almost all the situations where ptrace_check_attach should succeed. The only reason we have to use utrace_control to ensure that's the case is for a tracee in TASK_STOPPED (job control stop), which we have to convert into being a guaranteed ptrace stop SIGCONT won't wake (i.e. UTRACE_STOP, i.e. TASK_TRACED). So, we use the UTRACE_STOP interlock for that purpose. But it's not what we should use for "are we in a ptrace stop?" bookkeeping, which previously was implied directly by task_is_traced(). What might make sense as the indicator of "in ptrace stop" is "ctx->stop_code != 0" or "ctx->resume == UTRACE_STOP". > - it ignores "int kill". That's for PTRACE_KILL. This is a story similar to your question about PTRACE_DETACH,SIGKILL. That is, it's actually pretty useless but we still don't want to break some arcane assumptions. In actual utility and reliability (and implementation), PTRACE_KILL is exactly the same as PTRACE_CONT, SIGKILL. There is just no point to it at all. But, people over the years have been understandably confused by ptrace, not to mention even buggier states during its checkered past, and have used whatever seemed to work at the time, and we get to bend over pretty far to avoid breaking those people's expectations now. The manifest reality of PTRACE_KILL is that it doesn't check for stoppedness, only attachedness, and so returns "success" (while doing absolutely nothing useful!) on an attached task that is not stopped or is already dead. The former is extremely useless, but the latter is actually harmless and probably behaves predictably today. I will bet that there is some code somewhere doing: if (kill(pid, SIGKILL)) fail_loudly(); usleep(100); if (ptrace(PTRACE_KILL, pid)) fail_loudly(); or equivalent stupid things. Today this will succeed every time and the ptrace call will never do anything at all. By the time ptrace is called, the task is already dead, and so there is nothing to do, but PTRACE_KILL succeeds anyway because of the ptrace_check_attach flag. So I think you've got to keep doing that. I don't think it should be particularly difficult. The first part of the ptrace_check_attach work is to ensure that it's attached and you're the tracer. The second part is to ensure that it's stopped (including converting a job control stop into a ptrace stop). With the kill flag, you just omit the second part. > Can we ignore these problems in V1 ? Or should we fix something? It doesn't seem like it should be very hard to get this right from the start. I don't think we can submit something upstream that has any known regressions even in stupid cases, except the explicit intended "improvements" that we will document. Thanks, Roland From cisse at cisse2009.org Mon Oct 12 01:57:50 2009 From: cisse at cisse2009.org (CISSE 2009) Date: Sun, 11 Oct 2009 18:57:50 -0700 Subject: CISSE 2009 - Paper Submission Deadline Extended to October 26, 2009. Message-ID: <200910120158.n9C1vYWr020805@mx1.redhat.com> Dear Colleagues, Due to numerous deadline extension requests from potential CISSE 2009 authors, the CISSE organizing committee has decided to extend the paper submission deadline to 10/26/2009. Please note that this is a hard deadline, so that the technical committees can perform their paper reviewing duties in a timely manner. If you received this email in error, please forward it to the appropriate department at your institution. If you wish to unsubscribe please follow the unsubscribe link at bottom of the email. Please do not reply to this message. If you need to contact us please email us at info at cisse2009.org ********************************************************************* * The Fifth International Joint Conferences on Computer, * * Information, and Systems Sciences, and Engineering (CISSE 2009) * * * * * * * * http://www.cisse2009.org * * * * * * * ********************************************************************* December 4-12, 2009 Sponsored by the University of Bridgeport Technically co-sponsored by the IEEE Computer Society, Communications Society and Education Society (Connecticut Section) --------------------------------------------------------------------- CONFERENCE OVERVIEW --------------------------------------------------------------------- CISSE 2009 provides a virtual forum for presentation and discussion of the state-of the-art research on computers, information and systems sciences and engineering. CISSE 2009 is the fifth conference of the CISSE series of e-conferences. CISSE is the World's first Engineering/Computing and Systems Research E-Conference. CISSE 2005 was the first high-caliber Research Conference in the world to be completely conducted online in real-time via the internet. CISSE 2005 received 255 research paper submissions and the final program included 140 accepted papers, from more than 45 countries. CISSE 2006 received 691 research paper submissions and the final program included 390 accepted papers, from more than 70 countries. CISSE 2007 received 750 research paper submissions and the final program included 406 accepted papers. A total of 948 paper submissions were received for CISSE 2008 and the final program included 382 accepted papers, from more than 80 countries. The virtual conference will be conducted through the Internet using web-conferencing tools, made available by the conference. Authors will be presenting their PowerPoint, audio or video presentations using web-conferencing tools without the need for travel. Conference sessions will be broadcast to all the conference participants, where session participants can interact with the presenter during the presentation and (or) during the Q&A slot that follows the presentation. This international conference will be held entirely on-line. The accepted and presented papers will be made available and sent to the authors after the conference both on a DVD (including all papers, powerpoint presentations and audio presentations) and as a book publication. Springer, the official publisher for CISSE, published the 2005 proceedings in 2 books and the CISSE 2006, CISSE 2007 and CISSE 2008 proceedings in four books each. Conference participants - authors, presenters and attendees - only need an internet connection and sound available on their computers in order to be able to contribute and participate in this international ground-breaking conference. The on-line structure of this high-quality event will allow academic professionals and industry participants to contribute their work and attend world-class technical presentations based on rigorously refereed submissions, live, without the need for investing significant travel funds or time out of the office. The concept and format of CISSE is ground-breaking. The PowerPoint presentations, final paper manuscripts and time schedule for live presentations over the web are available for two weeks prior to the start of the conference for all registrants, so that the participants can choose the presentations they want to attend and think about questions that they might want to ask. The live audio presentations were also recorded and are part of the permanent CISSE on-line archive - accessible to all registrants- which also includes all the papers, PowerPoint and audio presentations. Potential non-author conference attendees who cannot make the on-line conference dates are encouraged to register, as the entire joint conferences will be archived for future viewing. The CISSE conference audio room provides superb audio even over low speed internet connections, the ability to display PowerPoint presentations, and cross-platform compatibility (the conferencing software runs on Windows, Mac, and any other operating system that supports Java). In addition, the conferencing system allows for an unlimited number of participants, which in turn granted us the opportunity to allow all CISSE participants to attend all presentations, as opposed to limiting the number of available seats for each session. Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at http://www.cisse2009.org. Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, please visit http://www.cisse2009.org CISSE 2009 is composed of the following four conferences: International Conference on Systems, Computing Sciences and Software Engineering (SCSS 09) Topics: Grid Computing, Internet-based Computing Models, Resource Discovery, Programming Models and tools, e-Science and Virtual Instrumentation, Biometric Authentication, Computers for People of Special Needs, Human Computer Interaction, Information and Knowledge Engineering, Algorithms, Parallel and Distributed processing, Modeling and Simulation, Services and Applications, Embedded Systems and Applications, Databases, Programming Languages, Signal Processing Theory and Methods, Signal Processing for Communication, Signal Processing Architectures and Implementation, Information Processing, Geographical Information Systems, Object Based Software Engineering, Parallel and Distributed Computing, Real Time Systems, Multiprocessing, File Systems and I/O, Kernel and OS Structures. International Conference on Telecommunications and Networking (TeNe 09) Topics: Optical Networks and Switching, Computer Networks, Network architectures and Equipment, Access Technologies, Telecommunication Technology, Coding and Modulation technique, Modeling and Simulation, Spread Spectrum and CDMA Systems, OFDM technology, Space-time Coding, Ultra Wideband Communications, Medium Access Control, Spread Spectrum, Wireless LAN: IEEE 802.11, HIPERLAN, Bluetooth, Cellular Wireless Networks, Cordless Systems and Wireless Local Loop, Mobile Network Layer, Mobile Transport Layer, Support for Mobility, Conventional Encryption and Message Confidentiality, Block Ciphers Design Principles, Block Ciphers Modes of Operation, Public-Key Cryptography and Message Authentication, Authentication Application, Stenography, Electronic Mail Security, Web Security, IP Security, Firewalls, Computer Forensics. International Conference on Engineering Education, Instructional Technology, Assessment, and E-learning (EIAE 09) Topics: Instructional Design, Accreditation, Curriculum Design, Educational Tools, 2-2-2 Platforms, Teaching Capstone Design, Teaching Design at the Lower Levels, Design and Development of e-Learning tools, Assessment Methods in Engineering, Development and Implementation of E-learning tools, Ethics in Education, Economical and Social Impacts of E-learning. International Conference on Industrial Electronics, Technology & Automation (IETA 09) Topics: Advanced and Distributed Control Systems, Intelligent Control Systems (NN, FL, GA, .etc), Expert Systems, Man Machine Interaction, Data Fusion, Factory Automation, Robotics, Motion Control, Machine Vision, MEMS Sensors and Actuators, Sensors Fusion, Power Electronics, High Frequency Converters, Motors and Drives, Power Converters, Power Devices and Components, Electric Vehicles and Intelligent Transportation, Process Automation, Factory Communication, Manufacturing Information System Advances in Manufacturing Systems, Industrial Applications of Multi Media, Intelligent Systems Instrumentation, Industrial Instrumentation, Modeling and Simulation, Signal Processing, Image and Data Processing, VR and Parallel systems.. Paper Submission ================= Prospective authors are invited to submit full papers electronically in Microsoft Word or Adobe PDF format through the website of the conference at http://www.cisse2009.org. Accepted papers must be presented in the virtual conference by one of the authors. To submit your paper, visit http://www.cisse2009.org New Paper submission Deadline: October 26th, 2009 Notification of Acceptance: November 12th, 2009 Final Manuscript and Registration: November 26th, 2009 ------------------------------------------------------------------------ S. Patel CISSE 2009 Support Team University of Bridgeport e-mail: info at cisse2009.org Bridgeport, CT 06604, U.S.A. http://www.cisse2009.org ------------------------------------------------------------------------ Click here on http://server1.streamsend.com/streamsend/unsubscribe.php?cd=3326&md=362&ud=1578d90540422ad4d9542fe697f9d246 to update your profile or Unsubscribe From roland at redhat.com Mon Oct 12 02:30:01 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 19:30:01 -0700 (PDT) Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: Oleg Nesterov's message of Friday, 9 October 2009 19:09:05 +0200 <20091009170905.GA3984@redhat.com> References: <20091009170905.GA3984@redhat.com> Message-ID: <20091012023001.5603AC8@magilla.sf.frob.com> I took it from the lack of Signed-off-by: lines that you probably didn't want me to merge these. Instead I applied them all to a new branch utrace-ptrace-reuse-engine: magilla 135 % git l utrace-ptrace..utrace-ptrace-reuse-engine 85f8b3a detach should reset the context of self-detaching engine a27233a attach: try to re-use the self-detaching engine 8667615 ptrace_notify_stop: fix engine leak 3d5d053 ptrace_detach_task: don't use engine ptr before IS_ERR(engine) 01875c7 fold detach_signal() into ptrace_detach_task() 464c2b7 don't detach the engine with the parting signal 97b345c implement the basic detach-with-signal logic I found it far easier to read utrace-ptrace..utrace-ptrace-reuse-engine as a single diff. Some miscellaneous comments: + if (valid_signal(sig)) + context->signr = sig; + context->options = 0; + context->eventmsg = 0; + context->stop_code = 0; + /* make sure do_wait() can't succeed */ + tracee->exit_code = 0; Since you allocate struct ptrace_context with kzalloc, it would seem cleanest here to use memset to clear it all first. The only thing you don't clear explicitly here is siginfo. You need it preserved for the resume_signal logic to use. But IMHO it's cleaner to make that explicit in some comments and extract and restore it around the memset. That should be the one difference in the data structures between fully detaching and then doing a separate full attach, right? Also it feels like there should be a way to consolidate that switch somehow with the first one in do_ptrace_resume, so e.g. the syscall->send_sig logic is all in one place. + if (context->resume == UTRACE_DETACH) { + /* we rely on ->cred_guard_mutex */ + context->resume = UTRACE_RESUME; Ok, so this means that when ->resume == UTRACE_DETACH then the only other thing that could change ->resume is another thread in the same code path. That path olds cred_guard_mutex, so it excludes other threads. Right? + /* + * Make sure we don't race with ptrace_report_signal() + */ + utrace_barrier(tracee, engine); + if (engine->ops == &ptrace_utrace_ops) + goto finish; I really don't understand this part. Firstly, what's the race? Secondly, what is that ->ops check about?? That is clearly not something that the ptrace layer ought to be fiddling with. If what you mean to detect here is that the tracee died or was detached while we waited for things to calm down, then you should just check the return value from utrace_barrier. (That will handily avoid the new __must_check warning you should be seeing for calling utrace_barrier without checking its return value, too!) I know we went around on this idea before, and we don't need to rehash the idea if you still don't like it. But the hair like clearing out the data structure for this approach makes me think the "second special engine" approach really might look better. That is, detaching with a signal attaches a new engine with a different ops vector and then detaches the real ptrace engine. Then on successful attach, you do the look-up for any ptrace_detached_ops engine, transfer over its ctx->signr and ->siginfo to your fresh ptrace_context, detach it and free the old context. It has more data structures live momentarily than you really need, but it seems cleaner. Thanks, Roland From sender at promoportugal.com Sat Oct 10 12:31:36 2009 From: sender at promoportugal.com (Ana Paula) Date: Sat, 10 Oct 2009 14:31:36 +0200 Subject: =?utf-8?q?Emagre=C3=A7a_10_Quilos_em_15_dias!?= Message-ID: Emagre?a 10 Quilos em 15 dias Saiba como aqui: http://promoportugal.com/iemailer/link.php?M=584113&N=30&L=17&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Mon Oct 12 03:55:05 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 20:55:05 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Oleg Nesterov's message of Thursday, 8 October 2009 17:20:39 +0200 <20091008152039.GA15039@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091008040358.73BC88D@magilla.sf.frob.com> <20091008152039.GA15039@redhat.com> Message-ID: <20091012035505.9590B1D2@magilla.sf.frob.com> I'm replying out of order. So I'm sorry I started rehashing some of this same stuff in the other thread before reading where you'd already referred to it. > What if the tracee reports a signal and stops, the tracer detaches > but does not wake it up because of SIGNAL_STOP_STOPPED ? In this > case this signal will be visible after the next attach. > > OK, currently ptrace_detach() unconditionally wakes up the tracee. > But we seem to agree this wakeup should be killed, it completely > breaks the group-stop logic and it has other problems. So today the manifest semantics in userland is that PTRACE_DETACH from a signal stop causes immediate delivery of the signal in that thread regardless of the group stoppedness. In a (converted) job stop or non-signal, non-syscall ptrace stop the tracee resumes and drops the passed signr on the floor. Those semantics are very clear for the single-threaded case at least, so we can just be compatible. In MT cases where the result is a group-exit, that is pretty consistent and reliable today, so we probably need to be compatible there too. In MT cases where the result is to flutter back into job stop (SIGSTOP et al), then there too it is reliable today that you'll get another SIGCHLD and wait wakeup to go with that "freshly stopped again". In MT cases where the result is to confuse the group-stop state, i.e. tracee runs (signal handler or ignored signal) while group is supposedly stopped, we probably don't break anything not already broken by cleaning it up somehow. But if the tracer does a loop of PTRACE_DETACH on each tracee thread, then the result today is probably pretty consistent in manifest behavior today: they all get back to running, even if the SIGNAL_STOP_STOPPED flag is still set. But I'm not at all sure anything could discern from userland that SIGNAL_STOP_STOPPED is still set. It will be set anew or cleared by the time it actually matters. So maybe it really is consistent enough with today's observable behavior just to have PTRACE_DETACH clear SIGNAL_STOP_STOPPED. I'm guessing that will be pretty well consistent in the loop-of-detach case (by the end of it). I'm not really sure what would go different in an oddball case where you PTRACE_DETACH'd one thread but the others were actually left stopped (e.g. in true job stop and you only ever attached the one thread). But it probably doesn't much matter, that usage mode must already be pretty broken I would think. > If "monitor" really wants to kill the tracee it should use SIGKILL ;) Say it wants a core dump. > Any other fatal signal can be ignored by the tracee's sub-thread after > detach but before the tracee returns from ptrace_signal(). Say they never tested the MT case before and haven't started caring about it now. They just want what they have observed before to stay the same as they saw with the old kernel. > Since detach_signal() actually sends the signal, ptrace(DETACH, SIGKILL) > really works: it wakes up SIGNAL_STOP_STOPPED tracee. Today's manifest behavior (via the bogus wake_up_process) is that this SIGKILL will get through and take effect (in signal stops, as above). So that should stay. As to the theory of things, this is the flip side of the whole SIGNAL_STOP_DEQUEUED issue I just posted about earlier. Whereas only an earlier SIGCONT/SIGKILL would have cleared stop signals and thus should clear any "pending-equivalent" "half-delivered" stop signals, earlier stop signals would have cleared a pending SIGCONT. I'm not entirely sure what should happen in all the SIGCONT cases, but we can probably enumerate them and hash those out. I doubt anybody is depending much on the corners of that. For the SIGKILL cases, it's more clear. No matter what, if a SIGKILL doesn't just get dropped on the floor (non-signal stop cases), then it's going to override everything else and soon. > Lets discuss how we can implement detach to be compatible... > We already discussed detached_ops. So, we either change engine->ops > (my choice) or add the new engine with ->ops = detached_ops and detach > the ptrace engine. I don't recall all of the earlier discussion about this in detail. But yes, they are equivalent and I think a fresh engine is cleaner. > We need detached_report_signal() callback which > fixups siginfo if signr != info->si_signo and returns > UTRACE_DETACH | UTRACE_SIGNAL_DELIVER. Right, ptrace_report_signal does that now with ->resume = UTRACE_DETACH. > How can detached_report_signal() set info->si_pid correctly? the > tracer has gone away. This probably means this info should be prepared > during detach, the tracer should fill context->siginfo. It means that if the tracer cared at all, he did PTRACE_SETSIGINFO so this would be moot. The vanilla kernel today uses si_pid and si_uid values of what's either the new tracer (with racing PTRACE_ATTACH) or the real parent at the time of actual resumption. It can be any of those values or 0 and I think it's fine. > But the real problem, I can't see how can we teach ptrace_report_signal() > to not play with parting signals. Do you have any idea? perhaps we can > introduce UTRACE_SIGNAL_DELIVER_I_AM_DETACHED_ENGINE, but this is ugly. I'm not sure I'm following you. Do you mean the new attach after the detach? Indeed, we don't want this to see the detached engine's action as "incoming state" and report it again. I guess I would arrange that you never have them both attached and active (i.e. events set). So, attach the new engine, then look up for any existing detached engine. If you find one, you can do one of two things. 1. Take over the old engine's parting signal and mark it in your own context. Then detach the old engine. You set the context to the same state it's in after you have resumed for PTRACE_CONT,signr. Your report_signal callback can always get UTRACE_SIGNAL_REPORT callbacks in that state due to other engines stopping and resuming, so it should already have logic for that state to deliver the signal. 2. Just mark a special state in your context saying that you should do nothing on the next UTRACE_SIGNAL_DELIVER report you see. The old engine will be earlier on the list and run first, getting UTRACE_SIGNAL_REPORT and returning UTRACE_SIGNAL_DELIVER|UTRACE_DETACH. Then your engine runs later, and knows to let this one signal pass through, resetting its context for the next real signal report. > Oh, I'd like to avoid detached_ops. Perhaps the new attach can re-use > the old engine/context? Both can be basically equivalent. I'm not clear on why you prefer that. > ptrace(DETACH, SIGNR) does: > > context->detached = true; // checked in ptrace_report_signal() > return utrace_control(INTERRUPT); > > Now, how ptrace(ATTACH) can clear ->detached and re-use this engine without > utrace->lock ? IOW, will you agree to abuse utrace->lock for this? That sounds insane. > OR. Perhaps we can introduce UTRACE_ATTACH_MATCH_FILTER_DATA ? This sounds more insane. I don't understand why you wouldn't just do a normal MATCH_OPS lookup and then look at the data structure. You could even do CREATE|MATCH_OPS without EXCLUSIVE, and then if (engine->data != ctx) drop your fresh ctx and use ctx=engine->data; use it if ctx->detached and -EPERM if not. > if (!IS_ERR(engine)) { > // We re-used the old engine, but perhaps it is > // going to return UTRACE_DETACH ? > utrace_barrier(engine); > if (engine->ops == utrace_detached_ops) > engine = -EANY; That's what the return value from utrace_barrier is for. > What do you think? I think the code you sent is better than some of these ideas. But it's still not real coherent to me. I feel like you are worrying about particular problems in contorting to some of this really strange hair, but I haven't become clear on what those problems are so as to understand what clean solutions to them might be. Thanks, Roland From roland at redhat.com Mon Oct 12 03:58:12 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 11 Oct 2009 20:58:12 -0700 (PDT) Subject: utrace-ptrace && detach with signal semantics In-Reply-To: Oleg Nesterov's message of Saturday, 10 October 2009 19:17:55 +0200 <20091010171755.GA14853@redhat.com> References: <20091005025132.GA25283@redhat.com> <20091005183947.GA22972@host0.dyn.jankratochvil.net> <20091005190037.GA2103@redhat.com> <20091006082739.GA12639@host0.dyn.jankratochvil.net> <20091006131010.GA5906@redhat.com> <20091006143911.GA7071@host0.dyn.jankratochvil.net> <20091010162421.GA12281@redhat.com> <20091010164825.GA12387@host0.dyn.jankratochvil.net> <20091010164829.GA13521@redhat.com> <20091010171628.GA14763@host0.dyn.jankratochvil.net> <20091010171755.GA14853@redhat.com> Message-ID: <20091012035812.CC0651D2@magilla.sf.frob.com> > I think always-reply-to-all is the best policy ;) For some people's mail-handling habits it makes a difference, so it is always safest not to trim individuals. For me personally, I always see the list copies just the same as the ones CC'd to me personally, so I don't care to be in the CC list as long as the mailing list is CC'd (and I prefer shorter CC lists for no special reason). Thanks, Roland From newsletter at brinde-companhia.com Mon Oct 12 06:19:11 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Mon, 12 Oct 2009 08:19:11 +0200 Subject: =?iso-8859-1?q?Chuva_de_pre=E7os=2E=2E=2E?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Oct 12 09:20:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 11:20:09 +0200 Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee In-Reply-To: <20091012004859.755F1C8@magilla.sf.frob.com> References: <20091010161712.GA12175@redhat.com> <20091012004859.755F1C8@magilla.sf.frob.com> Message-ID: <20091012092009.GA19072@redhat.com> On 10/11, Roland McGrath wrote: > > > Roland, Jan, what user-space expects ptrace(DETACH, SIGKILL) should do? > > > > My guess: this should really kill the tracee asap, hence this patch. > > As far as killing, it is no more reliable than PTRACE_CONT,SIGKILL. > i.e., will fail if it's not stopped, will be dropped on the floor if > stopped at PTRACE_EVENT_EXEC et al. So I would not especially try to make > it any more reliable than that, especially if it takes a special case > kludge like that. OK, good. please ignore this patch then. > For "make it die now", I have been advising people for years to just use > plain kill(,SIGKILL). That is the one thing we have worked the longest and > most consistently to keep reliable in making things really die really soon. Yes! > The one thing that anyone using PTRACE_DETACH,SIGKILL does perhaps expect > is that the detaching and killing are atomic. That is, it's not possible > for another thread in the tracer's process to get the WIFEXITED wait result > for the tracee. Conversely, that race is possible if the tracer does: > kill(pid, SIGKILL); > ptrace(PTRACE_DETACH, pid, anything); I guess you mean that tracee->real_parent doesn't belong to tracer's thread-group. > (And a tracer doesn't want to do them in the other order if it wants to be > sure to go from stopped->dead with no chance of running more user code.) > So IMHO that is the only special wrinkle of PTRACE_DETACH,SIGKILL we need > to worry about for compatibility. In other senses it needs to work no > better or different from PTRACE_CONT,SIGKILL. OK. then we don't to complicate the code. Oleg. From roland at redhat.com Mon Oct 12 10:07:34 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Oct 2009 03:07:34 -0700 (PDT) Subject: [PATCH 83] ptrace(DETACH, SIGKILL) should really kill the tracee In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 11:20:09 +0200 <20091012092009.GA19072@redhat.com> References: <20091010161712.GA12175@redhat.com> <20091012004859.755F1C8@magilla.sf.frob.com> <20091012092009.GA19072@redhat.com> Message-ID: <20091012100734.778D7C6@magilla.sf.frob.com> > > The one thing that anyone using PTRACE_DETACH,SIGKILL does perhaps expect > > is that the detaching and killing are atomic. That is, it's not possible > > for another thread in the tracer's process to get the WIFEXITED wait result > > for the tracee. Conversely, that race is possible if the tracer does: > > kill(pid, SIGKILL); > > ptrace(PTRACE_DETACH, pid, anything); > > I guess you mean that tracee->real_parent doesn't belong to tracer's > thread-group. Yes. Thanks, Roland From oleg at redhat.com Mon Oct 12 10:23:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 12:23:28 +0200 Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: <20091012023001.5603AC8@magilla.sf.frob.com> References: <20091009170905.GA3984@redhat.com> <20091012023001.5603AC8@magilla.sf.frob.com> Message-ID: <20091012102328.GB19072@redhat.com> On 10/11, Roland McGrath wrote: > > I took it from the lack of Signed-off-by: lines that you probably didn't > want me to merge these. Ah, no. I never added mine sob's in these long series, because I thought it doesn't matter. > Instead I applied them all to a new branch > utrace-ptrace-reuse-engine: > magilla 135 % git l utrace-ptrace..utrace-ptrace-reuse-engine > 85f8b3a detach should reset the context of self-detaching engine > a27233a attach: try to re-use the self-detaching engine > 8667615 ptrace_notify_stop: fix engine leak > 3d5d053 ptrace_detach_task: don't use engine ptr before IS_ERR(engine) > 01875c7 fold detach_signal() into ptrace_detach_task() > 464c2b7 don't detach the engine with the parting signal > 97b345c implement the basic detach-with-signal logic OK, great. > I found it far easier to read utrace-ptrace..utrace-ptrace-reuse-engine as > a single diff. Some miscellaneous comments: Yes, as usual the changes were chaotic. I tend to send the changes even if I know they should be redone/cleanuped later, to get your early review and to discuss asap. > + if (valid_signal(sig)) > + context->signr = sig; > + context->options = 0; > + context->eventmsg = 0; > + context->stop_code = 0; > + /* make sure do_wait() can't succeed */ > + tracee->exit_code = 0; > > Since you allocate struct ptrace_context with kzalloc, it would seem > cleanest here to use memset to clear it all first. The only thing you > don't clear explicitly here is siginfo. You need it preserved for the > resume_signal logic to use. But IMHO it's cleaner to make that explicit in > some comments and extract and restore it around the memset. That should be > the one difference in the data structures between fully detaching and then > doing a separate full attach, right? Mostly yes. But I think it would be much better to move this re-initialization into ptrace_attach_task(), in this case we can't do memset(0) + restore siginfo. > Also it feels like there should be a way to consolidate that switch somehow > with the first one in do_ptrace_resume, so e.g. the syscall->send_sig logic > is all in one place. I thought about this too. Currently I don't see how to do this cleanly. This all needs some obvious cleanups, then we will see if we can cleanup the code more and do some consolidation. > + if (context->resume == UTRACE_DETACH) { > + /* we rely on ->cred_guard_mutex */ > + context->resume = UTRACE_RESUME; > > Ok, so this means that when ->resume == UTRACE_DETACH then the only other > thing that could change ->resume is another thread in the same code path. > That path olds cred_guard_mutex, so it excludes other threads. Right? Yes. Other callers of ptrace_attach_task() are ptrace_traceme() and ptrace_clone_attach(), they can not hit this case. > + /* > + * Make sure we don't race with ptrace_report_signal() > + */ > + utrace_barrier(tracee, engine); > + if (engine->ops == &ptrace_utrace_ops) > + goto finish; > > I really don't understand this part. Firstly, what's the race? Secondly, > what is that ->ops check about?? That is clearly not something that the > ptrace layer ought to be fiddling with. If what you mean to detect here is > that the tracee died or was detached while we waited for things to calm > down, then you should just check the return value from utrace_barrier. No, the return calue from utrace_barrier() does not matter. And, if the tracee is killed we don't care. The race is different. So. The tracee reports the signal and stops. The tracer detaches, sets ->resume = UTRACE_DETACH and wakes up the tracee. A new tracer attaches, and changes ->resume back to UTRACE_RESUME. But, since the tracee is not stopped, this can be too later. It is possible that the tracee has already returned UTRACE_DETACH | ... from ptrace_report_signal(), in this case finish_callback() will mark this engine as detached soon or it has already detached it. That is why we do: context->resume = UTRACE_RESUME; utrace_barrier(); if (engine->ops == &ptrace_utrace_ops) SUCCESS! If ptrace_report_signal() has already seen resume = UTRACE_DETACH, this engine should be detached after utrace_barrier(). If ptrace_report_signal() was not called yet, it must see UTRACE_RESUME when it will be called. > (That will handily avoid the new __must_check warning you should be seeing > for calling utrace_barrier without checking its return value, too!) Argh. I didn't even know it is __must_check! OK, will fix... Not that I personally like these __must_check's though ;) > I know we went around on this idea before, and we don't need to rehash the > idea if you still don't like it. But the hair like clearing out the data > structure for this approach makes me think the "second special engine" > approach really might look better. That is, detaching with a signal > attaches a new engine with a different ops vector and then detaches the > real ptrace engine. Agreed, this all is very subjective. I hate the idea to attach another engine here, but can't prove it is really bad. Firstly, I dislike it because it is very unlikely another tracer will attach before the tracee handles this signal, a bit ugly we should arrange the new engine "just in case". And in theory kmem_cache_alloc() can fail, not good. But mostly I dislike the fact we must teach old and new engines to cooperate. > Then on successful attach, you do the look-up for any > ptrace_detached_ops engine, transfer over its ctx->signr and ->siginfo to > your fresh ptrace_context, detach it and free the old context. It has more > data structures live momentarily than you really need, but it seems cleaner. Again, this is subjective, but I'd like to avoid these complications. And. probably I missed something, but it is not trivial to implement. A lot of problems to solve. Just for example, when we attach the new engine, its ->flag has no UTRACE_EVENT(SIGNAL) yet. If we steal ->siginfo we can "lose" this signal. If we set UTRACE_EVENT(SIGNAL) first, the new and old engine can race. Yes I thought about this, but afaics we have to fight with multiple annoying races. Again, again, I do not pretend I am sure this is really true. Oleg. From oleg at redhat.com Mon Oct 12 11:02:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 13:02:09 +0200 Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: <20091012013902.C8AD31D2@magilla.sf.frob.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> Message-ID: <20091012110209.GA22581@redhat.com> On 10/11, Roland McGrath wrote: > > > Issues with ptrace_check_attach(), > > > > - it does utrace_control(UTRACE_STOP). > > > > This is wrong, ptrace_check_attach() must be "passive", > > while utrace_control(UTRACE_STOP) can actualy stop the > > tracee. > > This is not inherently problematic on its own. I'd say it's OK if you > have to actually be the tracer task to get that far, and of course if > you call utrace_control(UTRACE_RESUME) to reverse it in the failure > case. The UTRACE_STOP itself does not have any effect that the tracee > can observe except as scheduling flutter. (I'm not really counting it > cooperating with another process that does "ps" and sees "T"--we can > live with that too.) If the actual tracer making stupid use of ptrace > calls that will wind up failing with ESRCH has the side effect of > lousing up the scheduling of the tracee it's failing to otherwise > molest, so be it. Not sure I understand... This is behaviour change, no? Suppose a tracee is running, but for some reason it is somewhere inside start_callback(). utrace_control(UTRACE_STOP) can change ->flags and provoke report->action = UTRACE_STOP. In this case the tracee will stop. IOW. The tracee is running, say, it does "for (;;) ;". If the tracer does for (;;) ptrace(PTRACE_CONT); it can stop the tracee. As I said, I think this is minor. But I never know which behaviour changes are important. > It's a security issue if you can do UTRACE_STOP on a task that you would > not be allowed to ptrace, even for an instant. I don't think we have security issues, ptrace_check_attach() is only called when we already ptrace the task. It is a bit racy, we should check child->parent after ptrace_lookup_engine(), but this is trivial. (and in fact this race doesn't exist because of lock_kernl(), but sys_ptrace()->lock_kernel() must die). > > - even if it doesn't, this is wrong when we have multiple > > tracers. ptrace_check_attach() should not succeed if the > > tracee was stopped by another engine. > > Yes. UTRACE_STOP state is necessary for ptrace to consider the tracee > to be "in ptrace stop", but it's not sufficient. Ensuring UTRACE_STOP > is the mechanism for the underlying material effect that "in ptrace > stop" means, i.e. in (or on the way into) TASK_TRACED until SIGKILL. > Since we use UTRACE_STOP in report returns to implement ptrace stops, > this is normally already the case in almost all the situations where > ptrace_check_attach should succeed. The only reason we have to use > utrace_control to ensure that's the case is for a tracee in TASK_STOPPED > (job control stop), which we have to convert into being a guaranteed > ptrace stop SIGCONT won't wake (i.e. UTRACE_STOP, i.e. TASK_TRACED). > > So, we use the UTRACE_STOP interlock for that purpose. But it's not > what we should use for "are we in a ptrace stop?" bookkeeping, which > previously was implied directly by task_is_traced(). What might make > sense as the indicator of "in ptrace stop" is "ctx->stop_code != 0" or > "ctx->resume == UTRACE_STOP". We already have the indicator - get_stop_event(). Except it doesn't work for jctl stops. ptrace_check_attach() needs something like: if (!ptrace_event_pending()) { do not change engine->flags, do not set utrace->report, just s/TASK_STOPPED/TASK_TRACED/ or fail } > > - it ignores "int kill". > > That's for PTRACE_KILL. This is a story similar to your question about > PTRACE_DETACH,SIGKILL. That is, it's actually pretty useless but we > still don't want to break some arcane assumptions. Yes, yes, I see. > > Can we ignore these problems in V1 ? Or should we fix something? > > It doesn't seem like it should be very hard to get this right from the > start. I don't think we can submit something upstream that has any > known regressions even in stupid cases, except the explicit intended > "improvements" that we will document. PTRACE_KILL is trivial. Other problems are not completely trivial, afaics, but I didn't really try to think. OK. We should fix this, I'll try to do this later. Right now we have more important work. Oleg. From oleg at redhat.com Mon Oct 12 12:12:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 14:12:37 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091012002924.019E6C8@magilla.sf.frob.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> Message-ID: <20091012121237.GA25684@redhat.com> On 10/11, Roland McGrath wrote: > > > Yes. In particular, ptrace(PTRACE_DETACH, SIGKILL) should cancel > > SIGNAL_STOP_STOPPED, yes? > > Yes. OK. > SIGNAL_STOP_DEQUEUED exists for one purpose. It's to ensure that SIGCONT > and SIGKILL can clear it to make complete their required effect of clearing > all pending stop signals. (It fills the hole when another thread has > dequeued a stop signal and then dropped the siglock to make its call to > is_current_pgrp_orphaned()--so that half-delivered signal is still > considered "pending" and thus must be cancelled by SIGCONT or SIGKILL.) Yes, except this doesn't really work. We have a lot of races, afaics, even without ptrace. The problem is, once we drop ->siglock, we can't trust SIGNAL_STOP_DEQUEUED. And siglock is dropped by dequeue_signal(), it is dropped by get_signal_to_deliver(), by ptrace_signal/utrace too. Example. get_signal_to_deliver() dequeues, say, SIGTTIN, drops ->siglock for is_current_pgrp_orphaned(). SIGCONT comes, clears SIGNAL_STOP_DEQUEUED - we shouldn't stop. Another thread deques SIGTTOU but this signal has a handler, so we should not stop. However, SIGTTOU restores SIGNAL_STOP_DEQUEUED. This means the first thread will initiate the group-stop later. > Another way to put it is to say that the "exists for one purpose" > statement above implies that only an actual SIGCONT or SIGKILL should > ever clear SIGNAL_STOP_DEQUEUED. Yes, agreed. But I really need to re-read this code. > The remaining two places are the ->flags = SIGNAL_STOP_STOPPED cases in > do_signal_stop and exit_signals. Since SIGNAL_STOP_DEQUEUED must always > have been set before if you can get to those situations, it is harmless > to use "->flags = SIGNAL_STOP_STOPPED | SIGNAL_STOP_DEQUEUED" instead of: > > sig->flags &= SIGNAL_STOP_DEQUEUED; > sig->flags |= SIGNAL_STOP_STOPPED; > > or anything like that. It's probably cleanest to consolidate those two > cases to call a single subroutine that does the tracehook_notify_jctl > logic, unlock and do_notify_parent_cldstop. It can take a caller flag > or just check PF_EXITING to omit the ->exit_code + ->state change of the > do_signal_stop version of the code. That one subroutine can have a > clear comment about the nonobvious flag usage. Hmm... not sure, but I need to think more. > > But please remember, the patch above is not complete of course and currently > > I do not see the good solution. > > What's incomplete aside from handling the exit_signals case the same way? Say, ptrace(DETACH/CONT, SIGSTOP). This should work, this means SIGNAL_STOP_DEQUEUED should be set even before the tracee calls do_signal_stop(). But otoh it doesn't look right to set this flag each time the tracee sees a stop signal from the debugger (especially on detach), ->real_parent should not see multiple notifications. > > I am starting to think we should forget > > about these bugs, merge utrace-ptrace, and then try to fix them. > > If we can have utrace-ptrace code whose corner behavior matches the old > code and is itself clean, then I don't care about the order of the > changes going in. But it's not really clear to me that we can even > describe the old behavior in terms clean enough to make an exact > work-alike implementation that could possibly be clean. Yep. The current utrace-ptrace behaviour is close enough to upstream behaviour. I hope. I am going to restore the "detach always wakeup" logic to be compatible. Hopefully in this case utrace-ptrace will be equally buggy. I just can't concentrate on these problems until I finish utrace-ptrace. Because every week I should explain 1-2 times why it is still not ready for submission and when I am going to send it ;) Oleg. From envoi at campaigns.media-sender.net Mon Oct 12 12:30:33 2009 From: envoi at campaigns.media-sender.net (IC Telecom) Date: Mon, 12 Oct 2009 14:30:33 +0200 (CEST) Subject: =?iso-8859-15?q?Illimit=E9_=3A_Communications_-_Internet_-_t=E9l?= =?iso-8859-15?q?=E9phones?= Message-ID: <1011303148415.1103559355.1255350633085@enginex3.emv2.com> Si ce message n'est pas lisible, visualisez la version en ligne : http://ase.emv3.com/HM?a=A9X7CkJQ0FqQsObHi,R9ISvgsA VOTRE SOLUTION PRO TOUT EN UN Ma?triser votre budget, simplifiez votre t?l?phonie Une facture unique Une offre SIMPLE et ECONOMIQUE ICtelecom c'est : La t?l?phonie ILLIMITEE ( France m?tropolitaine fixe) + Standard t?l?phonique (Abonnement inclus) + Internet HAUT DEBIT + Postes t?l?phoniques (Cisco ou ?quivalent) Pour seulement 29? HT/mois Pour b?n?ficier de notre offre rendez vous sur cette page : http://ase.emv3.com/HS?a=A9X7CkJQ0FqQsObHi,R9ISngsg La r?duction des co?ts g?n?raux est un enjeu crucial pour la comp?titivit? de votre entreprise. Avec plus de 10 ans d'exp?rience dans les t?l?communications, ICtelecom sp?cialiste de la voix sur IP, est l'inventeur du "guichet unique" pour les entreprises. Fort de sa ma?trise des technologies en t?l?communications et des r?seaux IP et b?n?ficiant d?une position sans concurrence de premier plan sur le march? de la convergence (t?l?phonie fixe, t?l?phonie mobile, internet), ICtelecom d?veloppe pour le march? professionnel des offres tripe play packag?es (voix, data, mobile). ICtelecom fournit plus de 12000 utilisateurs ? travers plus de 2000 locaux install?s. Pour ne plus recevoir nos messages remplissez ce formulaire : http://ase.emv3.com/HP?a=A9X7CkJQ0FqQsObHi,R9IS7gsw A r?ception, celui-ci sera pris en compte conform?ment ? la loi n? 78-17 du 06-01-1978 relative ? l?informatique, aux fichiers et aux libert?s modifi?e par la loi n?2004-801 du 06-08-2004 -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Oct 12 13:24:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 15:24:21 +0200 Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: <20090909223334.906AB8BF69@magilla.sf.frob.com> References: <20090906134456.GA24701@redhat.com> <20090907211003.B7D1D8BECC@magilla.sf.frob.com> <20090908183920.GB9070@redhat.com> <20090909223334.906AB8BF69@magilla.sf.frob.com> Message-ID: <20091012132421.GA29358@redhat.com> On 09/09, Roland McGrath wrote: > > > 2. Is utrace_barrier() correct???? Note the example above, > > it assumes that utrace_barrier() itself is the barrier > > wrt reporting. But, is it? > > I don't think I understand the question. Sorry for delay on this. I have a lot of emails unanswered, in particular about jctl issues. And this one. I still didn't find the time to read the code around set/clear ->reporting, it is subtle and needs a fresh head. But at least, I think finish_callback() needs an mb() before clearing ->reporting. Let me repeat the pseudo-code from the previous email. Say, we have a global (for simplicity) pointer: something_t *ptr; We have a callback void my_report_callback(...) { if (ptr) dereference(ptr); } And the tracer does: void *tmp = ptr; ptr = NULL; utrace_barrier(my_engine); kfree(tmp); This should work correctly, right? But, I think this is racy because finish_callback() clears ->reporting without the barrier. this means (in theory) utrace_barrier() can see ->reporting == NULL before my_report_callback() sees ptr == NULL. And perhaps utrace_barrier() itself needs a barrier. utrace_barrier() takes utrace->lock, but the reporting loop doesn't always take this lock. So we have TRACER: TRACEE: ptr = NULL; if (ptr) dereference(ptr); if (!->reporting) kfree(ptr); ->reporting = NULL; This looks racy. Oleg. From info at campaigns.canal-marketing.com Mon Oct 12 13:56:04 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Luxe_Priv=E9?=) Date: Mon, 12 Oct 2009 15:56:04 +0200 Subject: =?iso-8859-1?q?Invitation_Vente_Priv=E9e?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Oct 12 16:34:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 12 Oct 2009 18:34:25 +0200 Subject: [PATCH 83] ptrace_attach_task: suppress WARN_ON(err) Message-ID: <20091012163425.GA9965@redhat.com> I noticed you didn't apply [PATCH 23] ptrace_attach_task: kill WARN_ON(err) (perhars we can improve ->reporting logic?) https://www.redhat.com/archives/utrace-devel/2009-September/msg00038.html I am resending it as 83. ptrace_attach_task: engine = utrace_attach_task(CREATE | EXCLUSIVE); err = utrace_set_events(); WARN_ON(err && !tracee->exit_state); Looks correct but it is not. utrace_attach_task() can return EINPROGRESS. Note that start_callback/etc sets ->reporting = engine even if we are not going to call ->report_any(). This WARN_ON() was always wrong, even without multitracing, even without recent changes which introduced reusing. Consider: the tracer exits and does implicit detach when the tracee has already called, say, utrace_resume(). The new tracer attaches, the tracee does list_for_each_entry()->start_callback(). start_callback() sets ->reporting = new_engine even if engine->flags = 0. I'd prefer to just kill this WARN_ON, but you prefer to keep this warning https://www.redhat.com/archives/utrace-devel/2009-September/msg00043.html OK, please see the patch. But I have to admit, I dislike this WARN_ON() in ptrace_attach_task(). First, it needs the comment to explaint why EINPROGRESS is OK. But more importantly, WARN_ON(err && err != -EINPROGRESS && !tracee->exit_state) equally applies to any usage of utrace_set_events(), no? If this warning is useful, then perhaps we should move it into utrace_set_events() ? --- kernel/ptrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- PU/kernel/ptrace.c~83_ATTACH_SUPPRESS_WARNING 2009-10-12 17:46:11.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-12 17:50:36.000000000 +0200 @@ -490,7 +490,7 @@ finish: * must notice this before setting PT_PTRACED. */ err = __ptrace_set_options(tracee, engine, options); - WARN_ON(err && !tracee->exit_state); + WARN_ON(err && err != -EINPROGRESS && !tracee->exit_state); utrace_engine_put(engine); return 0; } From roland at redhat.com Mon Oct 12 18:22:40 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Oct 2009 11:22:40 -0700 (PDT) Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 12:23:28 +0200 <20091012102328.GB19072@redhat.com> References: <20091009170905.GA3984@redhat.com> <20091012023001.5603AC8@magilla.sf.frob.com> <20091012102328.GB19072@redhat.com> Message-ID: <20091012182240.0AF15A8BB@magilla.sf.frob.com> > Ah, no. I never added mine sob's in these long series, because I thought > it doesn't matter. It doesn't. I just need to stay clear on what tree state each day's patches are relative to, and what is "the current code" when we're discussing the details. > Yes, as usual the changes were chaotic. I tend to send the changes even if > I know they should be redone/cleanuped later, to get your early review and > to discuss asap. It's always good to post early and often. Last week I had to be out of the office a fair bit and so it wound up taking me until the weekend to review them all anyway. > But I think it would be much better to move this re-initialization into > ptrace_attach_task(), in this case we can't do memset(0) + restore siginfo. Ok. > I thought about this too. Currently I don't see how to do this cleanly. > This all needs some obvious cleanups, then we will see if we can cleanup > the code more and do some consolidation. Ok. > No, the return calue from utrace_barrier() does not matter. And, if the > tracee is killed we don't care. The race is different. The utrace_barrier return value should cover exactly the case you describe, and that is the clean way to do it. It will fail if the tracee is either dead or detached. Indeed, you don't really care either way when it's dead. A success return tells you positively that it was not detached. (If it's interrupted you want to just back off and return -ERESTARTNOINTR anyway.) > Agreed, this all is very subjective. I hate the idea to attach another > engine here, but can't prove it is really bad. Firstly, I dislike it > because it is very unlikely another tracer will attach before the tracee > handles this signal, a bit ugly we should arrange the new engine "just in > case". And in theory kmem_cache_alloc() can fail, not good. I agree with those concerns. I'm just also concerned with how hairy the code winds up. > But mostly I dislike the fact we must teach old and new engines to cooperate. We have some version of that regardless. > And. probably I missed something, but it is not trivial to implement. > A lot of problems to solve. Just for example, when we attach the new > engine, its ->flag has no UTRACE_EVENT(SIGNAL) yet. If we steal ->siginfo > we can "lose" this signal. If we set UTRACE_EVENT(SIGNAL) first, the new > and old engine can race. This should be taken care of when you detach the old engine. If utrace_control(task, old, UTRACE_DETACH) returns zero, then the old engine's final callback has not run yet. (If it had run, it would have detached already.) If it fails, then the old engine's callback has run or is starting to run, so that callback cycle will finish before the new engine's first callback could run. Hmm. I guess there is a race or three to contend with anyway. > Yes I thought about this, but afaics we have to fight with multiple annoying > races. Again, again, I do not pretend I am sure this is really true. I'm not sure either. If we are keeping all options in mind as we look for the cleanest final form of the code, I am satisfied with whichever approach you take. Thanks, Roland From roland at redhat.com Mon Oct 12 18:38:14 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 12 Oct 2009 11:38:14 -0700 (PDT) Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 13:02:09 +0200 <20091012110209.GA22581@redhat.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> Message-ID: <20091012183814.5544FA8BB@magilla.sf.frob.com> > Not sure I understand... This is behaviour change, no? No, I'm not talking about any change in the user-observable semantics. > Suppose a tracee is running, but for some reason it is somewhere > inside start_callback(). utrace_control(UTRACE_STOP) can change ->flags > and provoke report->action = UTRACE_STOP. In this case the tracee will > stop. And then you check whether it's really in a proper ptrace stop, see that it isn't, and use UTRACE_RESUME. > IOW. The tracee is running, say, it does "for (;;) ;". If the tracer > does > for (;;) > ptrace(PTRACE_CONT); > > it can stop the tracee. No. > As I said, I think this is minor. But I never know which behaviour > changes are important. That one would be quite wrong, but it's not what I said. > I don't think we have security issues, ptrace_check_attach() is only > called when we already ptrace the task. It is called to verify that we already ptrace the task. That's the point. > It is a bit racy, we should > check child->parent after ptrace_lookup_engine(), but this is trivial. As I said, as long as we verify that we are the attached ptracer before calling utrace_control, there is no security issue. > (and in fact this race doesn't exist because of lock_kernl(), but > sys_ptrace()->lock_kernel() must die). Yes, pretend it weren't there. > We already have the indicator - get_stop_event(). Except it doesn't work > for jctl stops. ptrace_check_attach() needs something like: > > if (!ptrace_event_pending()) { > do not change engine->flags, > do not set utrace->report, > just s/TASK_STOPPED/TASK_TRACED/ or fail > } utrace_control(,,UTRACE_STOP) does s/TASK_STOPPED/TASK_TRACED/. That's what I was just saying. If it returns -EINPROGRESS, then it wasn't really in TASK_STOPPED, so you can do UTRACE_RESUME and then fail with -ESRCH. (In that race, you could get a report_quiesce or UTRACE_REPORT_SIGNAL, and those just need to know to do nothing if (!ptrace_event_pending()).) That alone succeeds when it shouldn't, if there is another engine keeping it in TASK_TRACED already so that utrace_control returns zero. To rule that out we might use report_jctl to do some more bookkeeping. But that doesn't cover it being in TASK_TRACED already when you PTRACE_ATTACH. I wonder if we could make ->state = TASK_STOPPED|TASK_TRACED work to keep task_is_stopped() as a meaningful test while in UTRACE_STOP. Thanks, Roland From anita.kekez at tele2.at Tue Oct 13 08:32:40 2009 From: anita.kekez at tele2.at (Mat Alston) Date: Tue, 13 Oct 2009 20:32:40 +1200 Subject: Give her some best drilling Message-ID: <002701ca4bd7$583c9e60$ca65a89e@homeikypre> Get worth any female attention! http://ez.sodiswaswy.com/ From oleg at redhat.com Tue Oct 13 08:28:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 10:28:35 +0200 Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: <20091012183814.5544FA8BB@magilla.sf.frob.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> <20091012183814.5544FA8BB@magilla.sf.frob.com> Message-ID: <20091013082835.GA17774@redhat.com> On 10/12, Roland McGrath wrote: > > > Suppose a tracee is running, but for some reason it is somewhere > > inside start_callback(). utrace_control(UTRACE_STOP) can change ->flags > > and provoke report->action = UTRACE_STOP. In this case the tracee will > > stop. > > And then you check whether it's really in a proper ptrace stop, see that it > isn't, and use UTRACE_RESUME. So far I don't really understand to do this correctly, but OK. > > IOW. The tracee is running, say, it does "for (;;) ;". If the tracer > > does > > for (;;) > > ptrace(PTRACE_CONT); > > > > it can stop the tracee. > > No. I meant, currently it can. > > I don't think we have security issues, ptrace_check_attach() is only > > called when we already ptrace the task. > > It is called to verify that we already ptrace the task. > That's the point. > > > It is a bit racy, we should > > check child->parent after ptrace_lookup_engine(), but this is trivial. > > As I said, as long as we verify that we are the attached ptracer before > calling utrace_control, there is no security issue. ptrace_check_attach() does verify we are ptracer. If the task has ptrace_utrace_ops engine and we are ->parent - we ptrace this task. > > We already have the indicator - get_stop_event(). Except it doesn't work > > for jctl stops. ptrace_check_attach() needs something like: > > > > if (!ptrace_event_pending()) { > > do not change engine->flags, > > do not set utrace->report, > > just s/TASK_STOPPED/TASK_TRACED/ or fail > > } > > utrace_control(,,UTRACE_STOP) does s/TASK_STOPPED/TASK_TRACED/. That's > what I was just saying. If it returns -EINPROGRESS, then it wasn't really > in TASK_STOPPED, so you can do UTRACE_RESUME and then fail with -ESRCH. > (In that race, you could get a report_quiesce or UTRACE_REPORT_SIGNAL, > and those just need to know to do nothing if (!ptrace_event_pending()).) Yes. I meant, perhaps it would be nice to have a "passive" method to check if it stopped or not via utrace API. > That alone succeeds when it shouldn't, if there is another engine keeping > it in TASK_TRACED already so that utrace_control returns zero. To rule > that out we might use report_jctl to do some more bookkeeping. Yes. ptrace should use report_jctl() anyway to solve other problems with jctl stops, but lets discuss this later. > I > wonder if we could make ->state = TASK_STOPPED|TASK_TRACED work to keep > task_is_stopped() as a meaningful test while in UTRACE_STOP. Hmm. Never thought about this! looks interesting and useful to me... Oleg. From oleg at redhat.com Tue Oct 13 09:07:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 11:07:46 +0200 Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: <20091012182240.0AF15A8BB@magilla.sf.frob.com> References: <20091009170905.GA3984@redhat.com> <20091012023001.5603AC8@magilla.sf.frob.com> <20091012102328.GB19072@redhat.com> <20091012182240.0AF15A8BB@magilla.sf.frob.com> Message-ID: <20091013090746.GA18400@redhat.com> On 10/12, Roland McGrath wrote: > > > No, the return calue from utrace_barrier() does not matter. And, if the > > tracee is killed we don't care. The race is different. > > The utrace_barrier return value should cover exactly the case you describe, > and that is the clean way to do it. It will fail if the tracee is either > dead or detached. Ah, indeed!!! Thanks. > > But mostly I dislike the fact we must teach old and new engines to cooperate. > > We have some version of that regardless. Well, we never have 2 engines attached, but yes, we should reinitialize the engine if we are going to reuse it. > > And. probably I missed something, but it is not trivial to implement. > > A lot of problems to solve. Just for example, when we attach the new > > engine, its ->flag has no UTRACE_EVENT(SIGNAL) yet. If we steal ->siginfo > > we can "lose" this signal. If we set UTRACE_EVENT(SIGNAL) first, the new > > and old engine can race. > > This should be taken care of when you detach the old engine. If > utrace_control(task, old, UTRACE_DETACH) returns zero, then the old > engine's final callback has not run yet. Not sure. Suppose we call utrace_control(old, UTRACE_DETACH) right before the tracee utrace_get_signal() calls ops->report_signal(). utrace_control()->get_utrace_lock() succeeds, but when utrace_control() checks ->reporting it could be already cleared. > If it fails, then the old engine's callback has > run or is starting to run, Yes, and we can't know (afaics) whether UTRACE_SIGNAL_DELIVER was already returned or not. Oleg. From ananth at in.ibm.com Tue Oct 13 09:20:56 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 13 Oct 2009 14:50:56 +0530 Subject: [PATCH] (trivial) Use set_stop_code() in ptrace_report_signal() Message-ID: <20091013092056.GB6094@in.ibm.com> Trivial patch - looks like this was opencoded rather than using the helper Use set_stop_code() wherever possible. Signed-off-by: Ananth N Mavinakayanahalli --- kernel/ptrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) Index: ptrace-13oct/kernel/ptrace.c =================================================================== --- ptrace-13oct.orig/kernel/ptrace.c +++ ptrace-13oct/kernel/ptrace.c @@ -331,8 +331,7 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - context->stop_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; - + set_stop_code(context, PTRACE_EVENT_SIGTRAP); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } From oleg at redhat.com Tue Oct 13 09:24:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 11:24:35 +0200 Subject: [PATCH] (trivial) Use set_stop_code() in ptrace_report_signal() In-Reply-To: <20091013092056.GB6094@in.ibm.com> References: <20091013092056.GB6094@in.ibm.com> Message-ID: <20091013092435.GA20837@redhat.com> On 10/13, Ananth N Mavinakayanahalli wrote: > > Use set_stop_code() wherever possible. > > Signed-off-by: Ananth N Mavinakayanahalli > --- > kernel/ptrace.c | 3 +-- > 1 file changed, 1 insertion(+), 2 deletions(-) > > Index: ptrace-13oct/kernel/ptrace.c > =================================================================== > --- ptrace-13oct.orig/kernel/ptrace.c > +++ ptrace-13oct/kernel/ptrace.c > @@ -331,8 +331,7 @@ static u32 ptrace_report_signal(u32 acti > context->siginfo = NULL; > > if (resume != UTRACE_RESUME) { > - context->stop_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; > - > + set_stop_code(context, PTRACE_EVENT_SIGTRAP); > return UTRACE_STOP | UTRACE_SIGNAL_IGN; > } Indeed! thanks Ananth. Missed this one. Oleg. From ananth at in.ibm.com Tue Oct 13 10:15:40 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 13 Oct 2009 15:45:40 +0530 Subject: [PATCH] (cosmetic) rename ptrace_context() Message-ID: <20091013101540.GC6094@in.ibm.com> Rename ptrace_context() to get_ptrace_context() and use it for better code readability. (I know it doesn't take a ref or anything; feel free to ignore) Signed-off-by: Ananth N Mavinakayanahalli --- kernel/ptrace.c | 40 +++++++++++++++++++++------------------- 1 file changed, 21 insertions(+), 19 deletions(-) Index: ptrace-13oct/kernel/ptrace.c =================================================================== --- ptrace-13oct.orig/kernel/ptrace.c +++ ptrace-13oct/kernel/ptrace.c @@ -59,7 +59,7 @@ static inline void set_stop_code(struct } static inline struct ptrace_context * -ptrace_context(struct utrace_engine *engine) +get_ptrace_context(struct utrace_engine *engine) { return engine->data; } @@ -124,7 +124,7 @@ static u32 ptrace_report_exit(enum utrac struct task_struct *task, long orig_code, long *code) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); WARN_ON(ptrace_event_pending(context)); @@ -171,7 +171,7 @@ static u32 ptrace_report_clone(enum utra unsigned long clone_flags, struct task_struct *child) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); int event, ret = UTRACE_RESUME; WARN_ON(ptrace_event_pending(context)); @@ -227,7 +227,7 @@ static u32 ptrace_report_syscall_entry(u struct task_struct *task, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); WARN_ON(ptrace_event_pending(context)); @@ -241,7 +241,7 @@ static u32 ptrace_report_syscall_exit(en struct task_struct *task, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); if (ptrace_event_pending(context)) return UTRACE_STOP; @@ -258,7 +258,7 @@ static u32 ptrace_report_exec(enum utrac const struct linux_binprm *bprm, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); WARN_ON(ptrace_event_pending(context)); @@ -316,7 +316,7 @@ static u32 ptrace_report_signal(u32 acti const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); enum utrace_resume_action resume = context->resume; if (ptrace_event_pending(context)) { @@ -367,7 +367,7 @@ static u32 ptrace_report_quiesce(u32 act struct task_struct *task, unsigned long event) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); if (ptrace_event_pending(context)) return UTRACE_STOP; @@ -395,7 +395,7 @@ static inline int __ptrace_set_options(s struct utrace_engine *engine, unsigned long options) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); /* * We need QUIESCE for resume handling, CLONE to check * for CLONE_PTRACE, other events are always reported. @@ -867,7 +867,7 @@ void ptrace_notify_stop(struct task_stru return; } - context = ptrace_context(engine); + context = get_ptrace_context(engine); if (WARN_ON(!ptrace_event_pending(context))) return; do_ptrace_notify_stop(context, tracee); @@ -896,7 +896,7 @@ static void do_ptrace_resume(struct utra enum utrace_resume_action action, long request, long data) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *context = get_ptrace_context(engine); switch (get_stop_event(context)) { case 0: @@ -994,12 +994,14 @@ int ptrace_request(struct task_struct *c long addr, long data) { struct utrace_engine *engine = ptrace_lookup_engine(child); + struct ptrace_context *context; siginfo_t siginfo; int ret; if (unlikely(IS_ERR(engine))) return -ESRCH; + context = get_ptrace_context(engine); switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: @@ -1017,13 +1019,12 @@ int ptrace_request(struct task_struct *c ret = ptrace_set_options(engine, child, data); break; case PTRACE_GETEVENTMSG: - ret = put_user(ptrace_context(engine)->eventmsg, + ret = put_user(context->eventmsg, (unsigned long __user *) data); break; case PTRACE_GETSIGINFO: - ret = ptrace_rw_siginfo(child, ptrace_context(engine), - &siginfo, false); + ret = ptrace_rw_siginfo(child, context, &siginfo, false); if (!ret) ret = copy_siginfo_to_user((siginfo_t __user *) data, &siginfo); @@ -1034,7 +1035,7 @@ int ptrace_request(struct task_struct *c sizeof siginfo)) ret = -EFAULT; else - ret = ptrace_rw_siginfo(child, ptrace_context(engine), + ret = ptrace_rw_siginfo(child, context, &siginfo, true); break; @@ -1163,6 +1164,7 @@ int compat_ptrace_request(struct task_st compat_ulong_t addr, compat_ulong_t data) { struct utrace_engine *engine = ptrace_lookup_engine(child); + struct ptrace_context *context; compat_ulong_t __user *datap = compat_ptr(data); compat_ulong_t word; siginfo_t siginfo; @@ -1171,6 +1173,7 @@ int compat_ptrace_request(struct task_st if (unlikely(IS_ERR(engine))) return -ESRCH; + context = get_ptrace_context(engine); switch (request) { case PTRACE_PEEKTEXT: case PTRACE_PEEKDATA: @@ -1188,12 +1191,11 @@ int compat_ptrace_request(struct task_st break; case PTRACE_GETEVENTMSG: - ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, - datap); + ret = put_user((compat_ulong_t)context->eventmsg, datap); break; case PTRACE_GETSIGINFO: - ret = ptrace_rw_siginfo(child, ptrace_context(engine), + ret = ptrace_rw_siginfo(child, context, &siginfo, false); if (!ret) ret = copy_siginfo_to_user32( @@ -1207,7 +1209,7 @@ int compat_ptrace_request(struct task_st &siginfo, (struct compat_siginfo __user *) datap)) ret = -EFAULT; else - ret = ptrace_rw_siginfo(child, ptrace_context(engine), + ret = ptrace_rw_siginfo(child, context, &siginfo, true); break; From oleg at redhat.com Tue Oct 13 10:28:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 12:28:51 +0200 Subject: [PATCH] (cosmetic) rename ptrace_context() In-Reply-To: <20091013101540.GC6094@in.ibm.com> References: <20091013101540.GC6094@in.ibm.com> Message-ID: <20091013102851.GA23841@redhat.com> On 10/13, Ananth N Mavinakayanahalli wrote: > > Rename ptrace_context() to get_ptrace_context() and use it for better > code readability. (I know it doesn't take a ref or anything; feel free to > ignore) Well. As for naming, personally I don't care and agree with any naming. I cc'ed Roland, if he likes get_ptrace_context() more - I have no objections. > Signed-off-by: Ananth N Mavinakayanahalli > --- > kernel/ptrace.c | 40 +++++++++++++++++++++------------------- > 1 file changed, 21 insertions(+), 19 deletions(-) > > Index: ptrace-13oct/kernel/ptrace.c > =================================================================== > --- ptrace-13oct.orig/kernel/ptrace.c > +++ ptrace-13oct/kernel/ptrace.c > @@ -59,7 +59,7 @@ static inline void set_stop_code(struct > } > > static inline struct ptrace_context * > -ptrace_context(struct utrace_engine *engine) > +get_ptrace_context(struct utrace_engine *engine) > { > return engine->data; > } > @@ -124,7 +124,7 @@ static u32 ptrace_report_exit(enum utrac > struct task_struct *task, > long orig_code, long *code) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > WARN_ON(ptrace_event_pending(context)); > > @@ -171,7 +171,7 @@ static u32 ptrace_report_clone(enum utra > unsigned long clone_flags, > struct task_struct *child) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > int event, ret = UTRACE_RESUME; > > WARN_ON(ptrace_event_pending(context)); > @@ -227,7 +227,7 @@ static u32 ptrace_report_syscall_entry(u > struct task_struct *task, > struct pt_regs *regs) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > WARN_ON(ptrace_event_pending(context)); > > @@ -241,7 +241,7 @@ static u32 ptrace_report_syscall_exit(en > struct task_struct *task, > struct pt_regs *regs) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > if (ptrace_event_pending(context)) > return UTRACE_STOP; > @@ -258,7 +258,7 @@ static u32 ptrace_report_exec(enum utrac > const struct linux_binprm *bprm, > struct pt_regs *regs) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > WARN_ON(ptrace_event_pending(context)); > > @@ -316,7 +316,7 @@ static u32 ptrace_report_signal(u32 acti > const struct k_sigaction *orig_ka, > struct k_sigaction *return_ka) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > enum utrace_resume_action resume = context->resume; > > if (ptrace_event_pending(context)) { > @@ -367,7 +367,7 @@ static u32 ptrace_report_quiesce(u32 act > struct task_struct *task, > unsigned long event) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > if (ptrace_event_pending(context)) > return UTRACE_STOP; > @@ -395,7 +395,7 @@ static inline int __ptrace_set_options(s > struct utrace_engine *engine, > unsigned long options) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > /* > * We need QUIESCE for resume handling, CLONE to check > * for CLONE_PTRACE, other events are always reported. > @@ -867,7 +867,7 @@ void ptrace_notify_stop(struct task_stru > return; > } > > - context = ptrace_context(engine); > + context = get_ptrace_context(engine); > if (WARN_ON(!ptrace_event_pending(context))) > return; > do_ptrace_notify_stop(context, tracee); > @@ -896,7 +896,7 @@ static void do_ptrace_resume(struct utra > enum utrace_resume_action action, > long request, long data) > { > - struct ptrace_context *context = ptrace_context(engine); > + struct ptrace_context *context = get_ptrace_context(engine); > > switch (get_stop_event(context)) { > case 0: > @@ -994,12 +994,14 @@ int ptrace_request(struct task_struct *c > long addr, long data) > { > struct utrace_engine *engine = ptrace_lookup_engine(child); > + struct ptrace_context *context; > siginfo_t siginfo; > int ret; > > if (unlikely(IS_ERR(engine))) > return -ESRCH; > > + context = get_ptrace_context(engine); > switch (request) { > case PTRACE_PEEKTEXT: > case PTRACE_PEEKDATA: > @@ -1017,13 +1019,12 @@ int ptrace_request(struct task_struct *c > ret = ptrace_set_options(engine, child, data); > break; > case PTRACE_GETEVENTMSG: > - ret = put_user(ptrace_context(engine)->eventmsg, > + ret = put_user(context->eventmsg, > (unsigned long __user *) data); > break; > > case PTRACE_GETSIGINFO: > - ret = ptrace_rw_siginfo(child, ptrace_context(engine), > - &siginfo, false); > + ret = ptrace_rw_siginfo(child, context, &siginfo, false); > if (!ret) > ret = copy_siginfo_to_user((siginfo_t __user *) data, > &siginfo); > @@ -1034,7 +1035,7 @@ int ptrace_request(struct task_struct *c > sizeof siginfo)) > ret = -EFAULT; > else > - ret = ptrace_rw_siginfo(child, ptrace_context(engine), > + ret = ptrace_rw_siginfo(child, context, > &siginfo, true); > break; > > @@ -1163,6 +1164,7 @@ int compat_ptrace_request(struct task_st > compat_ulong_t addr, compat_ulong_t data) > { > struct utrace_engine *engine = ptrace_lookup_engine(child); > + struct ptrace_context *context; > compat_ulong_t __user *datap = compat_ptr(data); > compat_ulong_t word; > siginfo_t siginfo; > @@ -1171,6 +1173,7 @@ int compat_ptrace_request(struct task_st > if (unlikely(IS_ERR(engine))) > return -ESRCH; > > + context = get_ptrace_context(engine); > switch (request) { > case PTRACE_PEEKTEXT: > case PTRACE_PEEKDATA: > @@ -1188,12 +1191,11 @@ int compat_ptrace_request(struct task_st > break; > > case PTRACE_GETEVENTMSG: > - ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, > - datap); > + ret = put_user((compat_ulong_t)context->eventmsg, datap); > break; > > case PTRACE_GETSIGINFO: > - ret = ptrace_rw_siginfo(child, ptrace_context(engine), > + ret = ptrace_rw_siginfo(child, context, > &siginfo, false); > if (!ret) > ret = copy_siginfo_to_user32( > @@ -1207,7 +1209,7 @@ int compat_ptrace_request(struct task_st > &siginfo, (struct compat_siginfo __user *) datap)) > ret = -EFAULT; > else > - ret = ptrace_rw_siginfo(child, ptrace_context(engine), > + ret = ptrace_rw_siginfo(child, context, > &siginfo, true); > break; > From oleg at redhat.com Tue Oct 13 16:27:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 18:27:36 +0200 Subject: [PATCH 84-87] cleanup self-detaching code Message-ID: <20091013162736.GA29364@redhat.com> Cleanup self-detaching code + nice cleanup from Ananth. Tomorrow: change detach to be as close as possible to upstream wrt stop/wakeup behaviour. Oleg. From oleg at redhat.com Tue Oct 13 16:27:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 18:27:39 +0200 Subject: [PATCH 84] use set_stop_code() in ptrace_report_signal(UTRACE_SIGNAL_HANDLER) Message-ID: <20091013162739.GA29372@redhat.com> From: Ananth N Mavinakayanahalli Use set_stop_code() wherever possible. Signed-off-by: Ananth N Mavinakayanahalli --- kernel/ptrace.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) --- PU/kernel/ptrace.c~84_REPORT_SIGNAL_USE_HELPER 2009-10-13 13:25:13.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 14:01:43.000000000 +0200 @@ -361,8 +361,7 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - context->stop_code = (PTRACE_EVENT_SIGTRAP << 8) | SIGTRAP; - + set_stop_code(context, PTRACE_EVENT_SIGTRAP); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } From oleg at redhat.com Tue Oct 13 16:27:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 18:27:42 +0200 Subject: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops Message-ID: <20091013162742.GA29375@redhat.com> On 10/12, Roland McGrath wrote: > > > No, the return calue from utrace_barrier() does not matter. And, if the > > tracee is killed we don't care. The race is different. > > The utrace_barrier return value should cover exactly the case you describe, > and that is the clean way to do it. It will fail if the tracee is either > dead or detached. Thanks, I think you are right, and this should work. But. This is connected to https://www.redhat.com/archives/utrace-devel/2009-October/msg00132.html and I still think utrace_barrier() and finish_callback() pathes need more mb's. This case is very similar to the previous pseudo-code. Suppose that utrace_get_signal() calls ->report_signal() which returns UTRACE_DETACH while the tracer does utrace_barrier(). Tracee, finish_callback() path: if (action == UTRACE_DETACH) engine->ops = utrace_detached_ops; utrace->reporting = NULL; no barries, no utrace->lock() in between. Tracer, utrace_barrier() under utrace->lock: if (engine->ops == utrace_detached_ops) return -EXXX; if (utrace->reporting != engine) return 0; Afaics, this is racy and should be fixed in utrace level. What do you think? --- kernel/ptrace.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~85_REUSE_RELY_ON_BARRIER 2009-10-13 14:01:43.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 14:15:48.000000000 +0200 @@ -459,8 +459,8 @@ static int ptrace_attach_task(struct tas /* * Make sure we don't race with ptrace_report_signal() */ - utrace_barrier(tracee, engine); - if (engine->ops == &ptrace_utrace_ops) + err = utrace_barrier(tracee, engine); + if (!err) goto finish; } utrace_engine_put(engine); From oleg at redhat.com Tue Oct 13 16:27:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 18:27:44 +0200 Subject: [PATCH 86] cleanup/optimize reuse/attch in ptrace_attach_task() Message-ID: <20091013162744.GA29378@redhat.com> No functional changes, move reuse/attach code into the new helpers. Microptimizations: - check ->utrace_flags before trying to re-use the self-detaching engine - if ptrace_reuse_engine() finds engine and ->resume != UTRACE_DETACH, we can just return EPERM without trying UTRACE_ATTACH_CREATE. --- kernel/ptrace.c | 96 +++++++++++++++++++++++++++++++++++--------------------- 1 file changed, 61 insertions(+), 35 deletions(-) --- PU/kernel/ptrace.c~86_CLEANUP_ATTACH_REUSE 2009-10-13 14:15:48.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 17:36:05.000000000 +0200 @@ -421,6 +421,64 @@ 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)) { + /* we rely on ->cred_guard_mutex */ + context->resume = UTRACE_RESUME; + /* make sure we don't race 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) @@ -446,44 +504,12 @@ static inline int __ptrace_set_options(s */ static int ptrace_attach_task(struct task_struct *tracee, int options) { - struct ptrace_context *context; struct utrace_engine *engine; int err; - engine = ptrace_lookup_engine(tracee); - if (!IS_ERR(engine)) { - context = ptrace_context(engine); - if (context->resume == UTRACE_DETACH) { - /* we rely on ->cred_guard_mutex */ - context->resume = UTRACE_RESUME; - /* - * Make sure we don't race with ptrace_report_signal() - */ - err = utrace_barrier(tracee, engine); - if (!err) - goto finish; - } - utrace_engine_put(engine); - } - - context = kzalloc(sizeof(*context), GFP_KERNEL); - if (unlikely(!context)) - return -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))) { - err = PTR_ERR(engine); - if (err != -ESRCH && err != -ERESTARTNOINTR) - err = -EPERM; - kfree(context); - return err; - } -finish: + 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_PTRACED. From oleg at redhat.com Tue Oct 13 16:27:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 18:27:46 +0200 Subject: [PATCH 87] shift context re-initialization from detach to reuse Message-ID: <20091013162746.GA29385@redhat.com> It doesn't make sense to reset engine->context unless we know we are going to re-use it, move this code to ptrace_reuse_engine(). Except: ptrace_detach_task() has to clear context->stop_code (it is checked by ptrace_report_signal()) and tracee->exit_code. This will be removed later, when we change detach to use ptrace_wake_up(action) instead of utrace_control(). Also, improve the comments. --- kernel/ptrace.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) --- PU/kernel/ptrace.c~87_SHIFT_REINIT_TO_REUSE 2009-10-13 17:36:05.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 18:14:55.000000000 +0200 @@ -107,18 +107,11 @@ static void ptrace_detach_task(struct ta break; case PTRACE_EVENT_SIGNAL: + /* make sure do_wait() can't succeed */ + tracee->exit_code = 0; if (valid_signal(sig)) context->signr = sig; - context->options = 0; - context->eventmsg = 0; context->stop_code = 0; - /* make sure do_wait() can't succeed */ - tracee->exit_code = 0; - utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); - /* - * once we set UTRACE_DETACH we don't own this engine, - * utrace_set_events() also acts as a memory barrier. - */ context->resume = UTRACE_DETACH; action = UTRACE_RESUME; break; @@ -434,11 +427,23 @@ ptrace_reuse_engine(struct task_struct * context = ptrace_context(engine); if (unlikely(context->resume == UTRACE_DETACH)) { - /* we rely on ->cred_guard_mutex */ - context->resume = UTRACE_RESUME; - /* make sure we don't race with ptrace_report_signal() */ - err = utrace_barrier(tracee, engine); + /* + * 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; } From oleg at redhat.com Tue Oct 13 17:59:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 19:59:38 +0200 Subject: [PATCH 88-89] detach: bug-compatible changes Message-ID: <20091013175938.GA6574@redhat.com> > Tomorrow: change detach to be as close as possible to upstream > wrt stop/wakeup behaviour. OK, I decided to send the incomplete changes today. Tomorrow: tweak implicit-detach's behaviour. Oleg. From oleg at redhat.com Tue Oct 13 17:59:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 19:59:41 +0200 Subject: [PATCH 88] detach: use ptrace_wake_up() instead of utrace_control() Message-ID: <20091013175941.GA6579@redhat.com> Change ptrace_detach() to use ptrace_wake_up() which provokes the unconditional wakeup for compatibility. Now utrace-ptrace passes attach-wait-on-stopped, the only test it failed compared to upstream. This is still not exactly right, implicit detach (exit_ptrace() path) shouldn't do this, will fix tomorrow. --- kernel/ptrace.c | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~88_DETACH_USE_WAKEUP 2009-10-13 18:14:55.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 19:20:24.000000000 +0200 @@ -80,6 +80,9 @@ void __ptrace_link(struct task_struct *c 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 utrace_engine *engine, + struct task_struct *tracee, + enum utrace_resume_action action); static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) { @@ -91,7 +94,6 @@ static void ptrace_detach_task(struct ta { struct utrace_engine *engine = ptrace_lookup_engine(tracee); enum utrace_resume_action action = UTRACE_DETACH; - int err; if (unlikely(IS_ERR(engine))) return; @@ -107,8 +109,6 @@ static void ptrace_detach_task(struct ta break; case PTRACE_EVENT_SIGNAL: - /* make sure do_wait() can't succeed */ - tracee->exit_code = 0; if (valid_signal(sig)) context->signr = sig; context->stop_code = 0; @@ -118,10 +118,7 @@ static void ptrace_detach_task(struct ta } } - err = utrace_control(tracee, engine, action); - WARN_ON(err && err != -EINPROGRESS && - err != -ESRCH && err != -EALREADY); - + ptrace_wake_up(engine, tracee, action); utrace_engine_put(engine); } From oleg at redhat.com Tue Oct 13 17:59:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 13 Oct 2009 19:59:43 +0200 Subject: [PATCH 89] ptrace_wake_up: clear context->stop_code Message-ID: <20091013175943.GA6586@redhat.com> Change ptrace_wake_up() to clear context->stop_code, this simplifies the callers and looks right in any case. Now ptrace_detach_task() becomes really trivial. If we create the self-detaching engine we simply do: if (valid_signal(sig)) context->signr = sig; context->resume = UTRACE_DETACH; and nothing more. Also, change the prototype to match that of utrace_control/etc. --- kernel/ptrace.c | 15 +++++++-------- 1 file changed, 7 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~89_WAKEUP_CLEAR_STOP_CODE 2009-10-13 19:20:24.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-13 19:55:25.000000000 +0200 @@ -80,8 +80,8 @@ void __ptrace_link(struct task_struct *c 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 utrace_engine *engine, - struct task_struct *tracee, +static void ptrace_wake_up(struct task_struct *tracee, + struct utrace_engine *engine, enum utrace_resume_action action); static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) @@ -111,14 +111,13 @@ static void ptrace_detach_task(struct ta case PTRACE_EVENT_SIGNAL: if (valid_signal(sig)) context->signr = sig; - context->stop_code = 0; context->resume = UTRACE_DETACH; action = UTRACE_RESUME; break; } } - ptrace_wake_up(engine, tracee, action); + ptrace_wake_up(tracee, engine, action); utrace_engine_put(engine); } @@ -943,8 +942,8 @@ void ptrace_notify_stop(struct task_stru utrace_engine_put(engine); } -static void ptrace_wake_up(struct utrace_engine *engine, - struct task_struct *tracee, +static void ptrace_wake_up( struct task_struct *tracee, + struct utrace_engine *engine, enum utrace_resume_action action) { unsigned long flags; @@ -958,6 +957,7 @@ static void ptrace_wake_up(struct utrace // XXX: FIXME!!! racy. tracee->exit_code = 0; + ptrace_context(engine)->stop_code = 0; utrace_control(tracee, engine, action); } @@ -1011,9 +1011,8 @@ static void do_ptrace_resume(struct utra } } - context->stop_code = 0; context->resume = action; - ptrace_wake_up(engine, tracee, action); + ptrace_wake_up(tracee, engine, action); } static int ptrace_resume(struct utrace_engine *engine, From envoi at campaigns.media-sender.net Wed Oct 14 14:16:14 2009 From: envoi at campaigns.media-sender.net (IC Telecom) Date: Wed, 14 Oct 2009 16:16:14 +0200 (CEST) Subject: =?iso-8859-15?q?T=E9l=E9com_PRO_tout_en_un_=3A_29=A4?= Message-ID: <1011303148415.1103574357.1255529774742@enginex2.emv2.com> Si ce message n'est pas lisible, visualisez la version en ligne : http://ase.emv3.com/HM?a=A9X7CkJQ0FqQsOcIZeR4qsLieQ VOTRE SOLUTION PRO TOUT EN UN Ma?triser votre budget, simplifiez votre t?l?phonie Une facture unique Une offre SIMPLE et ECONOMIQUE ICtelecom c'est : La t?l?phonie ILLIMITEE ( France m?tropolitaine fixe) + Standard t?l?phonique (Abonnement inclus) + Internet HAUT DEBIT + Postes t?l?phoniques (Cisco ou ?quivalent) Pour seulement 29? HT/mois Pour b?n?ficier de notre offre rendez vous sur cette page : http://ase.emv3.com/HS?a=A9X7CkJQ0FqQsOcIZeR4qsDiew La r?duction des co?ts g?n?raux est un enjeu crucial pour la comp?titivit? de votre entreprise. Avec plus de 10 ans d'exp?rience dans les t?l?communications, ICtelecom sp?cialiste de la voix sur IP, est l'inventeur du "guichet unique" pour les entreprises. Fort de sa ma?trise des technologies en t?l?communications et des r?seaux IP et b?n?ficiant d?une position sans concurrence de premier plan sur le march? de la convergence (t?l?phonie fixe, t?l?phonie mobile, internet), ICtelecom d?veloppe pour le march? professionnel des offres tripe play packag?es (voix, data, mobile). ICtelecom fournit plus de 12000 utilisateurs ? travers plus de 2000 locaux install?s. Pour ne plus recevoir nos messages remplissez ce formulaire : http://ase.emv3.com/HP?a=A9X7CkJQ0FqQsOcIZeR4qsHifA A r?ception, celui-ci sera pris en compte conform?ment ? la loi n? 78-17 du 06-01-1978 relative ? l?informatique, aux fichiers et aux libert?s modifi?e par la loi n?2004-801 du 06-08-2004 -------------- next part -------------- An HTML attachment was scrubbed... URL: From david.mcneil at 3par.com Wed Oct 14 14:47:21 2009 From: david.mcneil at 3par.com (Marina Britton) Date: Wed, 14 Oct 2009 11:47:21 -0300 Subject: Worried that tiny size will get you down? Message-ID: <001c01ca4cd4$da612de0$246c6ec4@ANGELICAyliai> What you need to please her? http://lyu.favnapzivd.com/ From oleg at redhat.com Wed Oct 14 18:29:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 14 Oct 2009 20:29:09 +0200 Subject: [PATCH 90] ptrace_wake_up: add "bool force_wakeup" argument for implicit detach Message-ID: <20091014182909.GA11819@redhat.com> Move the code which clears SIGNAL_STOP_STOPPED under "if (force_wakeup)". Change ptrace_detach() accordingly. See also the next patch which cleanups/fixes ptrace_wake_up(). Upstream logic: if detach is explicit, we should always wakeup the tracee, otherwise (exit_ptrace() path) we rely on ptrace_untrace() which checks SIGNAL_STOP_STOPPED. utrace-ptrace: ptrace_detach(sig) checks valid_signal(sig) to detect the explicit detach and passes "bool voluntary" to ptrace_wake_up(). both upstream and utrace-ptrace are racy (but these races are different), hopefully utrace-ptrace is not worse. And of course this all is not right and should be fixed, but we seem to agree this should be fixed later, when utrace-ptrace is merged. In my opinion, from now utrace-ptrace is close enough to upstream wrt stop/wakeup oddities. It passes all tests which upstream passes, plus it passes detach-stopped which fails with upstream kernel. This is because utrace_get_signal() sets SIGNAL_STOP_DEQUEUED when it returns a sig_kernel_stop() signal. This logic is not exactly right, but I think it is better than nothing. IOW: afaics we don't need additional functional changes in this area before submitting utrace-ptrace. Of course, it is easy to detect the difference in behaviour and perhaps we will have "it breaks my app" reports, but I don't think we should try hard to be more bug-compatible before V1. What do you think? --- kernel/ptrace.c | 31 ++++++++++++++++++------------- 1 file changed, 18 insertions(+), 13 deletions(-) --- PU/kernel/ptrace.c~90_DETACH_CK_IMPLICIT 2009-10-13 19:55:25.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-14 13:18:45.000000000 +0200 @@ -82,7 +82,8 @@ static int ptrace_attach_task(struct tas 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); + enum utrace_resume_action action, + bool force_wakeup); static struct utrace_engine *ptrace_lookup_engine(struct task_struct *tracee) { @@ -92,8 +93,9 @@ static struct utrace_engine *ptrace_look static void ptrace_detach_task(struct task_struct *tracee, int sig) { - struct utrace_engine *engine = ptrace_lookup_engine(tracee); + bool voluntary = valid_signal(sig); enum utrace_resume_action action = UTRACE_DETACH; + struct utrace_engine *engine = ptrace_lookup_engine(tracee); if (unlikely(IS_ERR(engine))) return; @@ -104,12 +106,12 @@ static void ptrace_detach_task(struct ta switch (get_stop_event(context)) { case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: - if (valid_signal(sig)) + if (voluntary) send_sig_info(sig, SEND_SIG_PRIV, tracee); break; case PTRACE_EVENT_SIGNAL: - if (valid_signal(sig)) + if (voluntary) context->signr = sig; context->resume = UTRACE_DETACH; action = UTRACE_RESUME; @@ -117,7 +119,7 @@ static void ptrace_detach_task(struct ta } } - ptrace_wake_up(tracee, engine, action); + ptrace_wake_up(tracee, engine, action, voluntary); utrace_engine_put(engine); } @@ -944,15 +946,18 @@ void ptrace_notify_stop(struct task_stru static void ptrace_wake_up( struct task_struct *tracee, struct utrace_engine *engine, - enum utrace_resume_action action) + enum utrace_resume_action action, + bool force_wakeup) { - unsigned long flags; + if (force_wakeup) { + unsigned long flags; - /* preserve the compatibility bug */ - if (!lock_task_sighand(tracee, &flags)) - return; - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - unlock_task_sighand(tracee, &flags); + /* preserve the compatibility bug */ + if (!lock_task_sighand(tracee, &flags)) + return; + tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; + unlock_task_sighand(tracee, &flags); + } // XXX: FIXME!!! racy. tracee->exit_code = 0; @@ -1012,7 +1017,7 @@ static void do_ptrace_resume(struct utra } context->resume = action; - ptrace_wake_up(tracee, engine, action); + ptrace_wake_up(tracee, engine, action, true); } static int ptrace_resume(struct utrace_engine *engine, From mldireto at tudoemoferta.com.br Wed Oct 14 20:23:05 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Wed, 14 Oct 2009 17:23:05 -0300 Subject: Aquecimento TudoemOferta. Prepare-se para o verao com as ofertas mais quentes Message-ID: An HTML attachment was scrubbed... URL: From subscriptions at mail.hidec.co.jp Thu Oct 15 03:23:55 2009 From: subscriptions at mail.hidec.co.jp (Michael Rainey) Date: Thu, 15 Oct 2009 10:23:55 +0700 Subject: It is silly to suffer from man's usual problem when the solution is cheap and ideal. Message-ID: <20091015102355.1010505@mail.hidec.co.jp> Be too hot to resist. http://oqkyw.tvommimcoi.com/ From oleg at redhat.com Thu Oct 15 19:53:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Oct 2009 21:53:45 +0200 Subject: [PATCH 91-94] misc attach/detach fixes Message-ID: <20091015195345.GA3998@redhat.com> Roland, do you see other problems with attach/detach which should be fixed before v1? Oleg. From oleg at redhat.com Thu Oct 15 19:53:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Oct 2009 21:53:48 +0200 Subject: [PATCH 91] ptrace_wake_up: don't clear tracee->exit_code + update comments Message-ID: <20091015195348.GA4006@redhat.com> ptrace_wake_up() clears tracee->exit_code, this is racy and no longer needed. This was needed previously when ->exit_code was checked by callbacks. Now ->exit_code is only used by do_wait(), and we have no reasons to clear it. If the tracee exits or stops again ->exit_code will be correctly updated anyway, until then it has no effect. Also, update the comment. --- kernel/ptrace.c | 20 ++++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) --- PU/kernel/ptrace.c~91_CLEANUP_FIX_WAKEUP 2009-10-14 13:18:45.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-15 20:09:10.000000000 +0200 @@ -944,24 +944,24 @@ void ptrace_notify_stop(struct task_stru utrace_engine_put(engine); } -static void ptrace_wake_up( 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) { if (force_wakeup) { unsigned long flags; - - /* preserve the compatibility bug */ - if (!lock_task_sighand(tracee, &flags)) - return; - tracee->signal->flags &= ~SIGNAL_STOP_STOPPED; - unlock_task_sighand(tracee, &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); + } } - // XXX: FIXME!!! racy. - tracee->exit_code = 0; - ptrace_context(engine)->stop_code = 0; utrace_control(tracee, engine, action); } From oleg at redhat.com Thu Oct 15 19:53:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Oct 2009 21:53:51 +0200 Subject: [PATCH 92] do_ptrace_notify_stop: document the usage of tracee->exit_code Message-ID: <20091015195351.GA4009@redhat.com> Not sure this todo-like comment is really needed, but perhaps it can simplify the review. I mean it can help to avoid "this is racy" complaints. Also, kill return after WARN_ON(). It doesn't hurt, but it looks as if we have to return or something bad will happen. --- kernel/ptrace.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~92_NOTIFY_STOP_COMMENTS 2009-10-15 20:09:10.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-15 20:34:46.000000000 +0200 @@ -913,9 +913,14 @@ static int ptrace_rw_siginfo(struct task static void do_ptrace_notify_stop(struct ptrace_context *context, struct task_struct *tracee) { + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ tracee->exit_code = context->stop_code & PTRACE_EVENT_MASK; - if (WARN_ON(!tracee->exit_code)) - return; + WARN_ON(!tracee->exit_code); read_lock(&tasklist_lock); /* From oleg at redhat.com Thu Oct 15 19:53:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Oct 2009 21:53:54 +0200 Subject: [PATCH 93] ptrace_report_exit: fix WARN_ON() condition Message-ID: <20091015195354.GA4012@redhat.com> WARN_ON(ptrace_event_pending(context)) is not right. If PTRACE_O_TRACEEXIT tracee is killed it can enter ->report_exit() callback in any state. Check signal_group_exit(). We can't trust fatal_signal_pending(), SIGKILL can be already dequeued. This reminds me, it is still not clear what should we actually do when the killed tracee calls tracehook_report_exit(), but this is another story. --- kernel/ptrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- PU/kernel/ptrace.c~93_REPORT_EXIT_KILL_WARN 2009-10-15 20:34:46.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-15 21:05:04.000000000 +0200 @@ -147,7 +147,8 @@ static u32 ptrace_report_exit(enum utrac { struct ptrace_context *context = ptrace_context(engine); - WARN_ON(ptrace_event_pending(context)); + WARN_ON(ptrace_event_pending(context) && + !signal_group_exit(task->signal)); set_stop_code(context, PTRACE_EVENT_EXIT); context->eventmsg = *code; From oleg at redhat.com Thu Oct 15 19:53:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 15 Oct 2009 21:53:57 +0200 Subject: [PATCH 94] utrace_stop: do ptrace_notify_stop() unconditionally Message-ID: <20091015195357.GA4019@redhat.com> utrace_stop() checks task_ptrace() before ptrace_notify_stop(). This is right, but unfortunately doesn't work until we kill ->ptrace and change task_ptrace() to mean "ptrace_utrace_ops engine is attached". Until then this check is racy. If the tracee dequeues a signal before ptrace_attach() sets ->ptrace, the tracer won't know why it is stopped. This is still not right, the tracer won't recieve SIGCHLD, but hopefully we can ignore this problem for now. These problems should go away when we kill ->ptrace, move ->parent into context->tracer, change do_notify_parent_cldstop(), etc. --- kernel/utrace.c | 3 +-- kernel/ptrace.c | 5 ++++- 2 files changed, 5 insertions(+), 3 deletions(-) --- PU/kernel/utrace.c~94_UTRACE_STOP_NOTIFY_ALWAYS 2009-10-14 12:51:09.000000000 +0200 +++ PU/kernel/utrace.c 2009-10-15 21:20:57.000000000 +0200 @@ -414,8 +414,7 @@ static void utrace_stop(struct task_stru * be done after we are in TASK_TRACED. This makes the * synchronization with ptrace_do_wait() work right. */ - if (task_ptrace(task)) - ptrace_notify_stop(task); + ptrace_notify_stop(task); #endif schedule(); --- PU/kernel/ptrace.c~94_UTRACE_STOP_NOTIFY_ALWAYS 2009-10-15 21:05:04.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-15 21:25:42.000000000 +0200 @@ -929,7 +929,10 @@ static void do_ptrace_notify_stop(struct * sys_ptrace() needs this task to be inactive. */ preempt_disable(); - /* It can be killed and then released by our subthread */ + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ if (task_ptrace(tracee)) do_notify_parent_cldstop(tracee, CLD_TRAPPED); read_unlock(&tasklist_lock); From roland at redhat.com Fri Oct 16 01:18:03 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 18:18:03 -0700 (PDT) Subject: Stopped detach/attach status In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 14:12:37 +0200 <20091012121237.GA25684@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> <20091012121237.GA25684@redhat.com> Message-ID: <20091016011803.54D6A16D7@magilla.sf.frob.com> > Yes, except this doesn't really work. We have a lot of races, afaics, > even without ptrace. The problem is, once we drop ->siglock, we can't > trust SIGNAL_STOP_DEQUEUED. And siglock is dropped by dequeue_signal(), > it is dropped by get_signal_to_deliver(), by ptrace_signal/utrace too. If you think there are real problems unrelated to ptrace, we should be discussing that separately on LKML. Firstly, an overriding caveat. This logic was originally added to address a race between stop signals and SIGKILL. In that scenario, a SIGKILL or other group-exit came along while we were in the is_orphaned_pgrp() window after dequeuing SIGTTIN or suchlike (I think it was a single-thread case). So after retaking the siglock, we blocked in TASK_STOPPED while SIGKILL was pending. A repeated SIGKILL would find it was already pending and not do any signal_wake_up(), so it became unkillable. Myself, I do care that we get all the cases right by the anal POSIX rules. But I'm pretty sure that upstream at large will only ever actually care about the SIGKILL case. So that's the caveat about how much to worry. Encountering the aforementioned unkillable-stopped-process case and working out the SIGNAL_STOP_DEQUEUED solution all predates numerous cleanups you have done. Now do_signal_stop() checks for signal_group_exit() too--and you've cleaned up all sending paths to use complete_signal() so SIGNAL_GROUP_EXIT is reliably set in all situations--so now that would cover the original case even without any SIGNAL_STOP_DEQUEUED logic. > Example. get_signal_to_deliver() dequeues, say, SIGTTIN, drops ->siglock > for is_current_pgrp_orphaned(). > > SIGCONT comes, clears SIGNAL_STOP_DEQUEUED - we shouldn't stop. Right. SIGCONT also clears all pending stop signals, in the same atomic section with clearing SIGNAL_STOP_DEQUEUED and queuing SIGCONT. > Another thread deques SIGTTOU but this signal has a handler, so we should > not stop. However, SIGTTOU restores SIGNAL_STOP_DEQUEUED. This means the > first thread will initiate the group-stop later. So this is after SIGCONT's atomic section. This clears SIGCONT if it's still pending, atomic with posting SIGTTOU. So either SIGCONT"s handler (i.e. userland knowing for sure there was any SIGCONT) has begun to run already, or it won't run at all. I've been trying to think of a way to define it away is OK, but I can't quite get there. So I think we do indeed have a problem there. I wonder if we can hash that out independent of ptrace stuff. > Say, ptrace(DETACH/CONT, SIGSTOP). This should work, this means > SIGNAL_STOP_DEQUEUED should be set even before the tracee calls > do_signal_stop(). But otoh it doesn't look right to set this flag > each time the tracee sees a stop signal from the debugger (especially > on detach), ->real_parent should not see multiple notifications. I don't think an extra SIGCHLD/wakeup here is going to be considered a problem, in the grand scheme of things. I can't really see any plausible way we'd (want to) preserve whether the real_parent already thought it was stopped or not. > The current utrace-ptrace behaviour is close enough to upstream behaviour. > I hope. I am going to restore the "detach always wakeup" logic to be > compatible. Hopefully in this case utrace-ptrace will be equally buggy. A laudable goal. > I just can't concentrate on these problems until I finish utrace-ptrace. > Because every week I should explain 1-2 times why it is still not ready > for submission and when I am going to send it ;) If we can finish and submit utrace-ptrace without fixing them, that is our first priority. We can make Jan happy with the detach semantics later. Thanks, Roland From roland at redhat.com Fri Oct 16 01:39:59 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 18:39:59 -0700 (PDT) Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 15:24:21 +0200 <20091012132421.GA29358@redhat.com> References: <20090906134456.GA24701@redhat.com> <20090907211003.B7D1D8BECC@magilla.sf.frob.com> <20090908183920.GB9070@redhat.com> <20090909223334.906AB8BF69@magilla.sf.frob.com> <20091012132421.GA29358@redhat.com> Message-ID: <20091016013959.7B08016D7@magilla.sf.frob.com> > I still didn't find the time to read the code around set/clear ->reporting, > it is subtle and needs a fresh head. Ok. I had remembered that your earlier reviews included "review all use of memory barriers in utrace", so I didn't realize this stuff needed review. > But at least, I think finish_callback() needs an mb() before clearing > ->reporting. My thinking about that had been that ->reporting = NULL is the "all clear" signal and we didn't have any issues with thinking the coast was clear too late, only too soon. Since many engines' reports won't ever really care about utrace_barrier() synchronization at all, I wanted to be sure not to introduce any more barriers or other parallelism-hurting things into the unconditional hot paths in reporting loops. > We have a callback > > void my_report_callback(...) > { > if (ptr) > dereference(ptr); > } > > And the tracer does: > > void *tmp = ptr; > ptr = NULL; > utrace_barrier(my_engine); > kfree(tmp); > > This should work correctly, right? I never really thought about memory barriers for the callers own data. utrace_barrier() just guarantees that your callback has returned and its return value been processed (ordering them with respect to utrace_* calls after utrace_barrier), nothing more. My first reaction is to think the caller can do its own memory barriers when it wants to rely on them. But perhaps utrace_barrier() should do more implicitly, and be documented to. > But, I think this is racy because finish_callback() clears ->reporting > without the barrier. this means (in theory) utrace_barrier() can see > ->reporting == NULL before my_report_callback() sees ptr == NULL. And > perhaps utrace_barrier() itself needs a barrier. So today it would have to be: void my_report_callback(...) { if (ptr) dereference(ptr); smp_rmb(); } void *tmp = ptr; ptr = NULL; smp_wmb(); utrace_barrier(my_engine); kfree(tmp); Is that right? Thanks, Roland From roland at redhat.com Fri Oct 16 01:51:49 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 18:51:49 -0700 (PDT) Subject: [PATCH 83] ptrace_attach_task: suppress WARN_ON(err) In-Reply-To: Oleg Nesterov's message of Monday, 12 October 2009 18:34:25 +0200 <20091012163425.GA9965@redhat.com> References: <20091012163425.GA9965@redhat.com> Message-ID: <20091016015149.6C44D16D7@magilla.sf.frob.com> > ptrace_attach_task: > > engine = utrace_attach_task(CREATE | EXCLUSIVE); > > err = utrace_set_events(); > WARN_ON(err && !tracee->exit_state); > > Looks correct but it is not. utrace_attach_task() can return EINPROGRESS. utrace_set_events can, yes. > Note that start_callback/etc sets ->reporting = engine even if we are not > going to call ->report_any(). Yes, I believe this is necessary for the interlocks to work as described. > This WARN_ON() was always wrong, even without multitracing, even without > recent changes which introduced reusing. Right. > But I have to admit, I dislike this WARN_ON() in ptrace_attach_task(). > First, it needs the comment to explaint why EINPROGRESS is OK. Right. > But more importantly, WARN_ON(err && err != -EINPROGRESS && !tracee->exit_state) > equally applies to any usage of utrace_set_events(), no? If this warning > is useful, then perhaps we should move it into utrace_set_events() ? That condition amounts to asserting that utrace_set_events() meets its specified interface, so it's not really useful, no. I what it checks is that the ptrace-layer logic hadn't detached the engine from a live task. That is a sanity check that might be useful, I guess that's why it's there. As I mentioned in the message you cited, we could just make utrace_set_events() a little less paranoid and have it only return -EINPROGRESS when there is any meaningful race possible. That is, when it's clearing any bits. So how about leaving ptrace's sanity check alone and doing this instead? diff --git a/kernel/utrace.c b/kernel/utrace.c index 25737b5..a7bdd88 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -581,7 +581,8 @@ int utrace_set_events(struct task_struct *target, set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); ret = 0; - if (!utrace->stopped && target != current && !target->exit_state) { + if ((old_flags & ~events) != 0 && + !utrace->stopped && target != current && !target->exit_state) { /* * This barrier ensures that our engine->flags changes * have hit before we examine utrace->reporting, Thanks, Roland From roland at redhat.com Fri Oct 16 01:58:56 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 18:58:56 -0700 (PDT) Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Tuesday, 13 October 2009 10:28:35 +0200 <20091013082835.GA17774@redhat.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> <20091012183814.5544FA8BB@magilla.sf.frob.com> <20091013082835.GA17774@redhat.com> Message-ID: <20091016015856.C1EF116D7@magilla.sf.frob.com> > > And then you check whether it's really in a proper ptrace stop, see that it > > isn't, and use UTRACE_RESUME. > > So far I don't really understand to do this correctly, but OK. I guess I'm missing something because it seems trivial to me. > ptrace_check_attach() does verify we are ptracer. If the task has > ptrace_utrace_ops engine and we are ->parent - we ptrace this task. Ok, good. In that case I think we have wide latitude to perturb the task slightly (in the "not visible to the task itself" realm) when handling any corner cases where ptrace will return an error. > Yes. I meant, perhaps it would be nice to have a "passive" method to > check if it stopped or not via utrace API. I don't see the case for that. If you want it stopped, you use UTRACE_STOP. If you care about job-control state, you can just look at its ->signal->flags yourself. If you need some unsynchronized query whether or not some other utrace engine is using UTRACE_STOP, then your engine is just not designed sensibly. You are not supposed to know or care about other engines except for the direct effects of what they are doing that you see in your own callbacks. > Yes. ptrace should use report_jctl() anyway to solve other problems > with jctl stops, but lets discuss this later. Ok. > > I wonder if we could make ->state = TASK_STOPPED|TASK_TRACED work to > > keep task_is_stopped() as a meaningful test while in UTRACE_STOP. > > Hmm. Never thought about this! looks interesting and useful to me... It sure feels cleaner than a lot of SIGNAL_STOP_STOPPED fiddling logic. But it probably has hidden complexities. Right now, it is a significant change outside the existing tracehook.h and core stuff, so it would probably complicate the subject of reviewing and merging utrace. Thanks, Roland From roland at redhat.com Fri Oct 16 02:04:11 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 19:04:11 -0700 (PDT) Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: Oleg Nesterov's message of Tuesday, 13 October 2009 11:07:46 +0200 <20091013090746.GA18400@redhat.com> References: <20091009170905.GA3984@redhat.com> <20091012023001.5603AC8@magilla.sf.frob.com> <20091012102328.GB19072@redhat.com> <20091012182240.0AF15A8BB@magilla.sf.frob.com> <20091013090746.GA18400@redhat.com> Message-ID: <20091016020411.5D8FA16D7@magilla.sf.frob.com> > Not sure. Suppose we call utrace_control(old, UTRACE_DETACH) right > before the tracee utrace_get_signal() calls ops->report_signal(). Then utrace_control() returns -EINPROGRESS. If it returned 0, then ops->report_signal will not be called. If that's not so, utrace_control is broken. > utrace_control()->get_utrace_lock() succeeds, but when utrace_control() > checks ->reporting it could be already cleared. If it's already cleared then that means that ops->report_signal has returned and its return value has been processed. If that's not so, utrace_control is broken. > > If it fails, then the old engine's callback has > > run or is starting to run, > > Yes, and we can't know (afaics) whether UTRACE_SIGNAL_DELIVER was > already returned or not. I don't follow. If utrace_control returned zero, then any callback has returned whatever it was going to return before the detach takes effect. If that's not so, utrace_control is broken. Thanks, Roland From roland at redhat.com Fri Oct 16 02:28:00 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 19:28:00 -0700 (PDT) Subject: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops In-Reply-To: Oleg Nesterov's message of Tuesday, 13 October 2009 18:27:42 +0200 <20091013162742.GA29375@redhat.com> References: <20091013162742.GA29375@redhat.com> Message-ID: <20091016022800.893E51638@magilla.sf.frob.com> > Tracee, finish_callback() path: > > if (action == UTRACE_DETACH) > engine->ops = utrace_detached_ops; > > utrace->reporting = NULL; > > no barries, no utrace->lock() in between. > > Tracer, utrace_barrier() under utrace->lock: > > if (engine->ops == utrace_detached_ops) > return -EXXX; > > if (utrace->reporting != engine) > return 0; > > Afaics, this is racy and should be fixed in utrace level. Let me see if I'm following you. The scenario you mean is that utrace_barrier() returns zero when there had been a callback in progress but it returned UTRACE_DETACH, and so now the engine is detached. The only guarantee utrace_barrier() claims is ordering with respect to the effects of prior utrace_* calls, and a callback not being in progress right now. This scenario meets that interface contract as stated. It's as if utrace_barrier() had returned zero before that callback ran. But you can tell by external means that your callback has started before you called utrace_barrier(), so you want it to return -ESRCH instead of 0. Is that right? Which external means? Thanks, Roland From roland at redhat.com Fri Oct 16 03:09:18 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 20:09:18 -0700 (PDT) Subject: [PATCH 90] ptrace_wake_up: add "bool force_wakeup" argument for implicit detach In-Reply-To: Oleg Nesterov's message of Wednesday, 14 October 2009 20:29:09 +0200 <20091014182909.GA11819@redhat.com> References: <20091014182909.GA11819@redhat.com> Message-ID: <20091016030918.802FE16ED@magilla.sf.frob.com> > ptrace_detach(sig) checks valid_signal(sig) to detect the > explicit detach and passes "bool voluntary" to ptrace_wake_up(). ptrace_detach_task() does. ptrace_detach() has already bailed out if !valid_signal(sig) was really pass in from userland. valid_signal(0) => true, so this is checking specifically for the exit_ptrace() call that passes -1 to ptrace_do_detach()->ptrace_detach_task(). That is all rather nonobvious. But once you do figure it all out, the "voluntary" variable name stops being confusing. :-) It is strange to use valid_signal() at all inside ptrace_detach_task(), where the possible values for sig are -1 from exit_ptrace(), 0, or a valid signal number. Passing 0 to send_sig_info looks like it will get through and then confuse the lower layers. Make that condition sig > 0. If sig==0, remind me why we're not just doing action=UTRACE_DETACH anyway? > both upstream and utrace-ptrace are racy (but these races are > different), hopefully utrace-ptrace is not worse. And of course > this all is not right and should be fixed, but we seem to agree > this should be fixed later, when utrace-ptrace is merged. Ok. > In my opinion, from now utrace-ptrace is close enough to upstream > wrt stop/wakeup oddities. It passes all tests which upstream passes, > plus it passes detach-stopped which fails with upstream kernel. Ok, that sounds good. But remember that ptrace-tests has only the problem cases we've noticed before, not necessarily everything that matters. We should feel comfortable when running the gdb testsuite has no regressions vs the vanilla kernel, for a variety of past and present gdb versions. (That suite tends to have many failures, but all we need to do is match the vanilla kernel's behavior in which ones pass or fail.) Thanks, Roland From roland at redhat.com Fri Oct 16 03:17:45 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 20:17:45 -0700 (PDT) Subject: [PATCH 93] ptrace_report_exit: fix WARN_ON() condition In-Reply-To: Oleg Nesterov's message of Thursday, 15 October 2009 21:53:54 +0200 <20091015195354.GA4012@redhat.com> References: <20091015195354.GA4012@redhat.com> Message-ID: <20091016031745.1F3B816D7@magilla.sf.frob.com> > This reminds me, it is still not clear what should we actually do when the > killed tracee calls tracehook_report_exit(), but this is another story. Indeed it is. Currently old ptrace will stop for exit tracing after processing the SIGKILL. Then you can send it another SIGKILL to wake it up to die quicker, or it should always resume if you kill the tracer. (I think that is considered necessary for "one SIGKILL to everybody" always being sufficient on shutdown.) So for now we should match that. IMHO the truly desireable behavior is to distinguish real SIGKILL (userland kill, oom_kill) from "normal" group-exit. When it's a real SIGKILL that has special urgent priority: no tracing can save you, you die ASAP. For other group-exit deaths, exit tracing et al should work normally. But this seems like a clean refinement we can do after merge. Thanks, Roland From roland at redhat.com Fri Oct 16 03:23:46 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 15 Oct 2009 20:23:46 -0700 (PDT) Subject: [PATCH 91-94] misc attach/detach fixes In-Reply-To: Oleg Nesterov's message of Thursday, 15 October 2009 21:53:45 +0200 <20091015195345.GA3998@redhat.com> References: <20091015195345.GA3998@redhat.com> Message-ID: <20091016032346.5DC9016D7@magilla.sf.frob.com> > Roland, do you see other problems with attach/detach which > should be fixed before v1? It depends what v1 means, on which I am not entirely clear. If you just mean being work-alike compatible, then the proof is in the pudding. Like I said before, if it doesn't regress any tests, including on past gdb's MT attach behavior, and differs (if at all) only on the behaviors of leaving it stopped or not on detach, then that is probably fine. For "merge-worthy", aside from readability/comment cleanup in ptrace.c itself, we still have some deeper issues like a non-kludgey way to do synchronization that also proves utrace proper can be used without a special kludge to implement anything real. I'm guessing that's what you mean will be v>1. Thanks, Roland From info at campaigns.canal-marketing.com Fri Oct 16 07:05:01 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?IC_Telecom?=) Date: Fri, 16 Oct 2009 09:05:01 +0200 Subject: =?iso-8859-1?q?T=E9l=E9com_PRO_tout_en_un_=3A_29_Euros?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Oct 16 08:31:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 10:31:51 +0200 Subject: [PATCH 91-94] misc attach/detach fixes In-Reply-To: <20091016032346.5DC9016D7@magilla.sf.frob.com> References: <20091015195345.GA3998@redhat.com> <20091016032346.5DC9016D7@magilla.sf.frob.com> Message-ID: <20091016083151.GA6539@redhat.com> On 10/15, Roland McGrath wrote: > > > Roland, do you see other problems with attach/detach which > > should be fixed before v1? > > It depends what v1 means, on which I am not entirely clear. The definition of v1 is very simple and absolutely precise. The code is v1 when Roland thinks we can make the RFC patch and send it for review. > For "merge-worthy", aside from readability/comment cleanup in ptrace.c > itself, we still have some deeper issues like a non-kludgey way to do > synchronization that also proves utrace proper can be used without a > special kludge to implement anything real. I'm guessing that's what you > mean will be v>1. In my opinion - yes. More, personally I think it is OK to do this change after utrace and utrace-ptrace are merged, at least in -mm. Oleg. From oleg at redhat.com Fri Oct 16 08:58:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 10:58:10 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091016011803.54D6A16D7@magilla.sf.frob.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> <20091012121237.GA25684@redhat.com> <20091016011803.54D6A16D7@magilla.sf.frob.com> Message-ID: <20091016085810.GB6539@redhat.com> On 10/15, Roland McGrath wrote: > > > Yes, except this doesn't really work. We have a lot of races, afaics, > > even without ptrace. The problem is, once we drop ->siglock, we can't > > trust SIGNAL_STOP_DEQUEUED. And siglock is dropped by dequeue_signal(), > > it is dropped by get_signal_to_deliver(), by ptrace_signal/utrace too. > > If you think there are real problems unrelated to ptrace, we should be > discussing that separately on LKML. Agreed. And iirc we already did, but I can't recall what was the end of discussion. My point was, the discussed problems with ptrace && stop probably are not ptrace-only, we need other changes. Hopefully we should address them after v1. > Myself, I do care that we get all the cases right by the anal POSIX rules. > But I'm pretty sure that upstream at large will only ever actually care > about the SIGKILL case. So that's the caveat about how much to worry. Yes, I think we can't race with SIGKILL. > > Example. get_signal_to_deliver() dequeues, say, SIGTTIN, drops ->siglock > > for is_current_pgrp_orphaned(). > > > > SIGCONT comes, clears SIGNAL_STOP_DEQUEUED - we shouldn't stop. > > I've been trying to think of a way to define it away is OK, but I can't > quite get there. So I think we do indeed have a problem there. I wonder > if we can hash that out independent of ptrace stuff. Yes, I think this is solvable. Iirc, I even did the fix a long ago, but can't recall. But I'd prefer to delay this discussion unless you think we should fix this right now. I mean, I just can't think about this until we solve all known problems in utrace-ptrace. When I am trying to think about 2 different problems at the same time, I can't make any progress ;) > > Say, ptrace(DETACH/CONT, SIGSTOP). This should work, this means > > SIGNAL_STOP_DEQUEUED should be set even before the tracee calls > > do_signal_stop(). But otoh it doesn't look right to set this flag > > each time the tracee sees a stop signal from the debugger (especially > > on detach), ->real_parent should not see multiple notifications. > > I don't think an extra SIGCHLD/wakeup here is going to be considered a > problem, in the grand scheme of things. I can't really see any plausible > way we'd (want to) preserve whether the real_parent already thought it was > stopped or not. I dunno. I am not arguing, just I don't know. But, stopped-attach-transparency seem to check this. I am not sure, but "Excessive waiting SIGSTOP after it was already waited for\n" looks like it it does. I'll re-check. Oleg. From oleg at redhat.com Fri Oct 16 09:26:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 11:26:22 +0200 Subject: [PATCH 90] ptrace_wake_up: add "bool force_wakeup" argument for implicit detach In-Reply-To: <20091016030918.802FE16ED@magilla.sf.frob.com> References: <20091014182909.GA11819@redhat.com> <20091016030918.802FE16ED@magilla.sf.frob.com> Message-ID: <20091016092622.GC6539@redhat.com> On 10/15, Roland McGrath wrote: > > > ptrace_detach(sig) checks valid_signal(sig) to detect the > > explicit detach and passes "bool voluntary" to ptrace_wake_up(). > > ptrace_detach_task() does. ptrace_detach() has already bailed out > if !valid_signal(sig) was really pass in from userland. > > valid_signal(0) => true, so this is checking specifically for the > exit_ptrace() call that passes -1 to ptrace_do_detach()->ptrace_detach_task(). > > That is all rather nonobvious. But once you do figure it all out, the > "voluntary" variable name stops being confusing. :-) Yes, agreed, this needs a comment. I tried, but can't invent a clean and concise one... Perhaps, /* * If we are called when the tracer does PTRACE_DETACH * valid_signal(sig) == T. Otherwise the caller does the * implicit detach during exit. */ > It is strange to use valid_signal() at all inside ptrace_detach_task(), > where the possible values for sig are -1 from exit_ptrace(), 0, or a valid > signal number. OK, agreed. We can check sig >= 0 instead > Passing 0 to send_sig_info looks like it will get through and then confuse > the lower layers. No, send_sig_info() is called under "if (sig)", but I guess I misunderstood you. > If sig==0, remind me why we're not just doing action=UTRACE_DETACH anyway? Hmm. Again, I am not sure I understand you correctly. But, if sig == 0, then we only do utrace_control(DETACH), because sig == 0 means PTRACE_DETACH wants to cancel the signal. The code does action = UTRACE_DETACH; if (sig) { ... change if needed ... } utrace_control(action); > But remember that ptrace-tests has only the problem > cases we've noticed before, not necessarily everything that matters. Yes, yes, I know. > We > should feel comfortable when running the gdb testsuite has no regressions > vs the vanilla kernel, for a variety of past and present gdb versions. > (That suite tends to have many failures, but all we need to do is match the > vanilla kernel's behavior in which ones pass or fail.) You or Jan have alredy mentioned this testsuite... is it gdb-6.8/sim/testsuite/ which I see in gdb-6.8.tar.gz or something else? Oleg. From oleg at redhat.com Fri Oct 16 09:34:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 11:34:27 +0200 Subject: [PATCH 93] ptrace_report_exit: fix WARN_ON() condition In-Reply-To: <20091016031745.1F3B816D7@magilla.sf.frob.com> References: <20091015195354.GA4012@redhat.com> <20091016031745.1F3B816D7@magilla.sf.frob.com> Message-ID: <20091016093427.GD6539@redhat.com> On 10/15, Roland McGrath wrote: > > > This reminds me, it is still not clear what should we actually do when the > > killed tracee calls tracehook_report_exit(), but this is another story. > > IMHO the truly desireable behavior is to distinguish real SIGKILL (userland > kill, oom_kill) from "normal" group-exit. Yes. We already discussed this and I agree. I _think_ it is not hard to implement, but (again) I'd suggest to do this later. Oleg. From oleg at redhat.com Fri Oct 16 10:04:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 12:04:05 +0200 Subject: [PATCH 83] ptrace_attach_task: suppress WARN_ON(err) In-Reply-To: <20091016015149.6C44D16D7@magilla.sf.frob.com> References: <20091012163425.GA9965@redhat.com> <20091016015149.6C44D16D7@magilla.sf.frob.com> Message-ID: <20091016100405.GE6539@redhat.com> On 10/15, Roland McGrath wrote: > > > Note that start_callback/etc sets ->reporting = engine even if we are not > > going to call ->report_any(). > > Yes, I believe this is necessary for the interlocks to work as described. Yes. I'd like to _try_ to think if we can change this, but most probably we can't. > > But more importantly, WARN_ON(err && err != -EINPROGRESS && !tracee->exit_state) > > equally applies to any usage of utrace_set_events(), no? If this warning > > is useful, then perhaps we should move it into utrace_set_events() ? > > That condition amounts to asserting that utrace_set_events() meets its > specified interface, so it's not really useful, no. I what it checks is > that the ptrace-layer logic hadn't detached the engine from a live task. > That is a sanity check that might be useful, I guess that's why it's there. > > As I mentioned in the message you cited, we could just make > utrace_set_events() a little less paranoid and have it only return > -EINPROGRESS when there is any meaningful race possible. That is, > when it's clearing any bits. So how about leaving ptrace's sanity > check alone and doing this instead? > > diff --git a/kernel/utrace.c b/kernel/utrace.c > index 25737b5..a7bdd88 100644 > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -581,7 +581,8 @@ int utrace_set_events(struct task_struct *target, > set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); > > ret = 0; > - if (!utrace->stopped && target != current && !target->exit_state) { > + if ((old_flags & ~events) != 0 && > + !utrace->stopped && target != current && !target->exit_state) { > /* > * This barrier ensures that our engine->flags changes > * have hit before we examine utrace->reporting, Well, I think you are right... But I just can't convince myself I _really_ understand why the "set new bits" case is not interesting. Otoh, I can't imagine why the caller should worry about -EINPROGRESS if it doesn't clear any events. But I think the new code should have the comment to explain this "old_flags & ~events" condition. In any case I agree: if we change utrace_set_events() this way, then we do not need to change WARN_ON() in attach. Oleg. From oleg at redhat.com Fri Oct 16 10:23:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 12:23:52 +0200 Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: <20091016015856.C1EF116D7@magilla.sf.frob.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> <20091012183814.5544FA8BB@magilla.sf.frob.com> <20091013082835.GA17774@redhat.com> <20091016015856.C1EF116D7@magilla.sf.frob.com> Message-ID: <20091016102352.GF6539@redhat.com> On 10/15, Roland McGrath wrote: > > > > And then you check whether it's really in a proper ptrace stop, see that it > > > isn't, and use UTRACE_RESUME. > > > > So far I don't really understand to do this correctly, but OK. > > I guess I'm missing something because it seems trivial to me. Most probably it is me who missed something. Let me think about this a bit later, when I will change this code. > > ptrace_check_attach() does verify we are ptracer. If the task has > > ptrace_utrace_ops engine and we are ->parent - we ptrace this task. > > Ok, good. In that case I think we have wide latitude to perturb the task > slightly (in the "not visible to the task itself" realm) when handling any > corner cases where ptrace will return an error. > > > Yes. I meant, perhaps it would be nice to have a "passive" method to > > check if it stopped or not via utrace API. > > I don't see the case for that. If you want it stopped, you use > UTRACE_STOP. If you care about job-control state, you can just look at > its ->signal->flags yourself. But ptrace_check_attach() needs the tracee to be already stopped. A bit ugly to ask the tracee to stop via UTRACE_STOP and then resume it if it was not already stopped. And I don't even understand how to do this correctly. (but again, I'll try to think later). Apart from utrace_prepare_examine()->wait_task_inactive() and security checks, ptrace_check_attach() should do something like if (!task_stop_or_traced()) FAIL; if (SIGNAL_STOP_STOPPED || // JCTL stop get_stop_event()) { // it was stopped by us ... OK. s/STOPPED/TRACED/ and proceed .. } FAIL; > If you need some unsynchronized query > whether or not some other utrace engine is using UTRACE_STOP, then your > engine is just not designed sensibly. You are not supposed to know or > care about other engines except for the direct effects of what they are > doing that you see in your own callbacks. Not sure. Suppose the tracer does PTRACE_SYSCALL and the tracee spins in user-mode. Another engine stops the tracee. In this case any ptrace() request should fail despite the fact the tracee is STOPPED or TRACED. Yes/No ? > > > I wonder if we could make ->state = TASK_STOPPED|TASK_TRACED work to > > > keep task_is_stopped() as a meaningful test while in UTRACE_STOP. > > > > Hmm. Never thought about this! looks interesting and useful to me... > > It sure feels cleaner than a lot of SIGNAL_STOP_STOPPED fiddling logic. > But it probably has hidden complexities. Right now, it is a significant > change outside the existing tracehook.h and core stuff, so it would > probably complicate the subject of reviewing and merging utrace. Yes! agreed. Oleg. From oleg at redhat.com Fri Oct 16 10:55:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 12:55:46 +0200 Subject: [PATCH 74-78] implement the partly detached engines In-Reply-To: <20091016020411.5D8FA16D7@magilla.sf.frob.com> References: <20091009170905.GA3984@redhat.com> <20091012023001.5603AC8@magilla.sf.frob.com> <20091012102328.GB19072@redhat.com> <20091012182240.0AF15A8BB@magilla.sf.frob.com> <20091013090746.GA18400@redhat.com> <20091016020411.5D8FA16D7@magilla.sf.frob.com> Message-ID: <20091016105546.GA11698@redhat.com> On 10/15, Roland McGrath wrote: > > > Not sure. Suppose we call utrace_control(old, UTRACE_DETACH) right > > before the tracee utrace_get_signal() calls ops->report_signal(). > > Then utrace_control() returns -EINPROGRESS. It returns -EINPROGRESS if it sees ->reporting == engine. But as I said, by the time utrace_control(DETACH) checks ->reporting it can be already cleared by finish_callback(). > If it returned 0, then > ops->report_signal will not be called. If that's not so, utrace_control > is broken. It will not be called, yes. But my point was, perhaps it was already called and now we don't know whether we should deliver old->signr or not. > > utrace_control()->get_utrace_lock() succeeds, but when utrace_control() > > checks ->reporting it could be already cleared. > > If it's already cleared then that means that ops->report_signal has > returned and its return value has been processed. Yes. but we can't know this. Or I missed something. > > > If it fails, then the old engine's callback has > > > run or is starting to run, > > > > Yes, and we can't know (afaics) whether UTRACE_SIGNAL_DELIVER was > > already returned or not. > > I don't follow. If utrace_control returned zero, then any callback has > returned whatever it was going to return before the detach takes effect. See above. But here I was talking about the case when it doesn't return 0. Anyway. I never claimed this can't work. Surely this all is solvable (and probably even simpler than it seems to me). But I still think that re-using is simpler, althought still can't prove this. Perhaps I should make the patch which reimplements this code using _detached_ops engine, so that we could compare... > If that's not so, utrace_control is broken. Well. perhaps finish_callback_report() should take utrace->lock when it does if (action == UTRACE_DETACH) engine->ops = &utrace_detached_ops; This way, afaics, utrace_control(DETACH) will be more "precise" wrt returned value. Again, again. I'd like to re-read this code (and utrace_barrier) later. Right now I am trying to avoid thinking about anything except known problems in utrace-ptrace ;) Oleg. From oleg at redhat.com Fri Oct 16 11:27:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 13:27:53 +0200 Subject: [PATCH 2/4] utrace_reap: do not play with ->reporting In-Reply-To: <20091016013959.7B08016D7@magilla.sf.frob.com> References: <20090906134456.GA24701@redhat.com> <20090907211003.B7D1D8BECC@magilla.sf.frob.com> <20090908183920.GB9070@redhat.com> <20090909223334.906AB8BF69@magilla.sf.frob.com> <20091012132421.GA29358@redhat.com> <20091016013959.7B08016D7@magilla.sf.frob.com> Message-ID: <20091016112753.GB11698@redhat.com> On 10/15, Roland McGrath wrote: > > > We have a callback > > > > void my_report_callback(...) > > { > > if (ptr) > > dereference(ptr); > > } > > > > And the tracer does: > > > > void *tmp = ptr; > > ptr = NULL; > > utrace_barrier(my_engine); > > kfree(tmp); > > > > This should work correctly, right? > > I never really thought about memory barriers for the callers own data. > utrace_barrier() just guarantees that your callback has returned and its > return value been processed (ordering them with respect to utrace_* calls > after utrace_barrier), nothing more. My first reaction is to think the > caller can do its own memory barriers when it wants to rely on them. But > perhaps utrace_barrier() should do more implicitly, and be documented to. Yes, I didn't claim this must be buggy. But yes, if we can't rely on utrace_barrier() is the code like above, then perhaps it needs more documentation to explain which exactly guarantees it provides. > > But, I think this is racy because finish_callback() clears ->reporting > > without the barrier. this means (in theory) utrace_barrier() can see > > ->reporting == NULL before my_report_callback() sees ptr == NULL. And > > perhaps utrace_barrier() itself needs a barrier. > > So today it would have to be: > > void my_report_callback(...) > { > if (ptr) > dereference(ptr); > smp_rmb(); > } > > void *tmp = ptr; > ptr = NULL; > smp_wmb(); > utrace_barrier(my_engine); > kfree(tmp); > > Is that right? I think yes, but s/smp_wmb/smp_mb/. "ptr = NULL" must be visible before utrace_barrier() LOADs ->reporting, but wmb() can only serialize STOREs. ptr = NULL; // for utrace_barrier() which checks ->reporing smp_mb(); utrace_barrier(); kfree(); Likewise, my_report_callback() { if (ptr) dereference(ptr); // make sure the subsequent "->reporting == NULL // can't be re-ordered. smp_mb(); } At least, this all is very unobvious. Oleg. From oleg at redhat.com Fri Oct 16 12:25:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 14:25:47 +0200 Subject: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops In-Reply-To: <20091016022800.893E51638@magilla.sf.frob.com> References: <20091013162742.GA29375@redhat.com> <20091016022800.893E51638@magilla.sf.frob.com> Message-ID: <20091016122547.GC11698@redhat.com> On 10/15, Roland McGrath wrote: > > > Tracee, finish_callback() path: > > > > if (action == UTRACE_DETACH) > > engine->ops = utrace_detached_ops; > > > > utrace->reporting = NULL; > > > > no barries, no utrace->lock() in between. > > > > Tracer, utrace_barrier() under utrace->lock: > > > > if (engine->ops == utrace_detached_ops) > > return -EXXX; > > > > if (utrace->reporting != engine) > > return 0; > > > > Afaics, this is racy and should be fixed in utrace level. > > Let me see if I'm following you. The scenario you mean is that > utrace_barrier() returns zero when there had been a callback in > progress but it returned UTRACE_DETACH, and so now the engine is > detached. The only guarantee utrace_barrier() claims is ordering > with respect to the effects of prior utrace_* calls, and a callback > not being in progress right now. This scenario meets that interface > contract as stated. It's as if utrace_barrier() had returned zero > before that callback ran. > > But you can tell by external means that your callback has started > before you called utrace_barrier(), so you want it to return -ESRCH > instead of 0. Is that right? I think this is right, but I'd like to be absolutely sure we understand each other, please see below. As I said, this is very similar to the problems we discussed in another thread. But this particular race can be solved (I think) if we change finish_callback_report() to set ->ops = utrace_detached_ops under utrace->lock. In fact I feel this makes sense anyway, but I need to reread this code with a fresh head. So. Let's suppose again we have something like bool please_detach; my_report_callback(...) { if (please_detach) return UTRACE_DETACH; ... return UTRACE_WHATEVER_ELSE; } The tracer does: please_detach = false; err = utrace_barrier(); if (err) // too late! return -ESRCH; // Great! we cancelled the possible detach. // the next invocation of my_report_callback() // must see please_detach == false. // if this callback was already called and returned // UTRACE_DETACH, utrace_barrier() shouldn't succeed. // Seriously, if utrace_barrier() was called when the // tracee has already started to handle UTRACE_DETACH // request inside the reporting loop, a naive user like // me would like to expect utrace_barrier() should catch // this detach-in-progress somehow. If it is not supposed utrace_barrier() can be used this way, then I don't understand any longer what did you mean in https://www.redhat.com/archives/utrace-devel/2009-October/msg00135.html > No, the return calue from utrace_barrier() does not matter. And, if the > tracee is killed we don't care. The race is different. The utrace_barrier return value should cover exactly the case you describe, ... A success return tells you positively that it was not detached. That is why initially I did please_detach = false; utrace_barrier(); // we can't trust the returned value if (engine->ops != ptrace_utrace_ops) return -EXXX; // Great! we cancelled the possible detach. // the next invocation of my_report_callback() // must see please_detach == false. But. even the "must see" above needs some barriers, afaics. Either in utrace, or the user should take care. So far I think it is better to modify utrace. Oleg. From oleg at redhat.com Fri Oct 16 12:49:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 16 Oct 2009 14:49:34 +0200 Subject: utrace-ptrace v1 todo list In-Reply-To: <20091016083151.GA6539@redhat.com> References: <20091015195345.GA3998@redhat.com> <20091016032346.5DC9016D7@magilla.sf.frob.com> <20091016083151.GA6539@redhat.com> Message-ID: <20091016124934.GA17374@redhat.com> On 10/16, Oleg Nesterov wrote: > > On 10/15, Roland McGrath wrote: > > > > > Roland, do you see other problems with attach/detach which > > > should be fixed before v1? > > > > It depends what v1 means, on which I am not entirely clear. > > The definition of v1 is very simple and absolutely precise. > The code is v1 when Roland thinks we can make the RFC patch and > send it for review. As I see it, we need the following changes. utrace: - utrace_control(SINGLESTEP) calls get_user_pages() under spin_lock() ptrace: - stacked VFORK_DONE event, finish ptrace_report_clone(). The fix must be trivial, but every time I am trying to complete this I understand I should do this with a fresh head ;) - PTRACE_SYSEMU/PTRACE_SYSEMU_SINGLESTEP should be simple... - stacked JCTL events. Oh. I hope this will not be too hard to do something simple and "not too buggy" for now. - ptrace_check_attch(). Must be simple, but I am starting to think I have a blind spot here. - simple cleanups, may be more comments. Anything else? Oleg. From v-23tok at mdsspain.com Fri Oct 16 14:51:13 2009 From: v-23tok at mdsspain.com (Flo Valentine) Date: Fri, 16 Oct 2009 14:51:13 -0000 Subject: Dont you see her cheating you? Message-ID: <000c01ca679b$6aded260$4eab2341@homepcxvd> Heighten your intimate experience http://qa.tvommimcoi.com/ From iud at yewr.com Fri Oct 2 17:22:06 2009 From: iud at yewr.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 3 Oct 2009 01:22:06 +0800 Subject: (no subject) Message-ID: <200910021722.n92HM5PL014198@mx1.redhat.com> ????36?????? ????? 2009?10?24-25? ?? ?????????????????????????????????????????????? ????????????????????? ? ??3800/??????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? --------------------------------------------------------------------------------------------- ??????????????????????????????????????????????? ????????????????????? ?????????????????????! ??????????????????-??????????????? ???????????????,??? :2007-A-07830. -------------------------------------------------------------------------------------------- ????? 1????????????????????????36????????200????????? 2??????????????????????????????????? 3??????????????????????????????????? 4????????????????????????????? --------------------------------------------------------------------------------------------- ???? 1?????? 2?????????????????? 3?????????????????? 4?????????????????????? --------------------------------------------------------------------------------------------- ???? ????? ?????? 1??????? 2??????? ?? ??:????1? ??:????? ????800? ????? ?????? 10????????? ??:???????? ????? ?????? 15??????? ????? ???? 16?????? 17????? ????? ???? 24??????? 25??????? ?? ??:???????? ????? ???? ??????? 36????????? 37????????? ?? ?????????? ??????? ????? ???? 42????? ????? ???? ?????????????? ?????? ??????? 49???????? 50?????????? ?????? ??????? 51??????? 52??????? ?? ?????? ?????? ??:??????? ?????? ?????? 61????????? 62?????????????? ?? ??:?????? ??:??????? ??:??????? ?????? ?????? 88????????? 89????????? ?? ?????? ?????? ?????????? 97??????? 98??????? ?? ?????????? 104????? 105??????? ?? ??????? 118????????????119???????????? ?????? ?????? 125????? 126????? ?? ??:????? ?????? ???? 129????????? ??:??????? 141?BOT ( BLT?BTO?BCC?BOO?BOOT?BT ) 142?ABS ?? ??:????????? ??????? ?????? 144????? ?? ??????? ???? 145??????? 146????????? ??:?????? ??????? ???? 148???????????? 151??????? ????? ??????? 153??????????? 154???????? ?? ??:??3000??? ??????? ???? 156????? 157??????? ?? 174?????? ?? ??????? ???? 175????? 176????? ?? ?????? ???? ??????????? 186??????? 187??????? ?? ????????? 190????????? 191??????? ??:?? ??????? ?????? 198??????? 199???????? ?? 201??????? ?? ??????? ?????? 204??????? 205???????? ?? ??????? ?????? 207?AMEX 208?NASDAQ ?? ??????? ???????? 211???????? 213?????? ?? ??:?????? ??????? ??????????? 222??????? 225????????? ??:??11?????? ??:??? ??? ?????????? ???????? ?1?????????????????10%???0.5%????????????????????????? ????????70%????????????????????????????????????????? ????????????????????????? ?2?????????9,600??????????????????????????????? ?????????????????????????????????????????????????? ???? ?3????????????????????????????????????250??????????? ????????????????????????????????????? ?4?????3000???????3000??????????????????800~900??????????? ???????????53?????????? ??????????????????????. ?5??????????????????1?????????????? ??+??+???????????????????????? ??????????????????????????????????? ?6?????????????????????????????????????????????????? ??????????????????????????????????????????????????? ???????????? ?????????????????????????????? ?7???????????????????????????????????????60??? ?8?????????????????????? ?9?????????????????????? ???????????? ??????? ???? ?? ???????????? -------????????????????????????????????? ?10?????1984?????????????????????1.5???????????????????? ??????08????????????3000???????????????? ?11?10 ?????????????????????? ?12???????????????????????????? ?13???70?????????????????????????????????????????????? 100???2000??????????????????????????? ?14?????????????????????? ?15????????VC??????????????????????????VC?????????????? ????????VC???VC???????? ?16????????????????????????????????????? ?17?????????????????????????????????????? ???????????????????????????? -------------------------------------------------------------------------------------------------------- ???????????????????????????????????????????????????EMBA ??????????????????????? ????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ????????????????????????????????????????????????????? ??2008??????????????????????????? ????????????????????????????????????????????20?????300?? ????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ??????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ------------------------------------------------------------------------------------ ?????36????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From efg at tduc.com Sat Oct 3 01:41:57 2009 From: efg at tduc.com (=?GB2312?B?xeDRtQ==?=) Date: Sat, 03 Oct 2009 01:41:57 -0000 Subject: (no subject) Message-ID: <200910030119.n931JsKf030094@mx1.redhat.com> ???????????????????? ??????????2009??10??30-31?? ???? ??????????2009??11??6-7?? ???? ??????????????CEO/??????????????????/??????????????/?????????????????????????????????????????????? ????????????/??????????PMO?????????????????????????????????????????????????????????????????? ??????2500??/2??/??(??????????????????????????????????????????????) ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------- ??????????500?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ====================================================================================== ???????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? 1.?????????????????????????????????????????????????? 2.???????????????????????????????????????????? 3.???????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????? 5.?????????????????????????????? 6.?????????????????????????????????????????????????????? 7.?????????????????????????? 8.?????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????,?????????????????????????????? ????????????????????????????????????????. ====================================================================================== ???????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????? ???????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? ====================================================================================== ???????? ?????????????????????????????????????????? 1.???????????????????? 2.?????????????????????? 3.???????????????????????????? 4.?????????????????????????????? 5.???????????????????????????????????????????????? ?????????????????????????????????? 1.???????????????????????????????????? 2.???????????????????????? 3.???????????????????????? 4.?????????????????????????????????????????? 5.???????????????????????????????????? 6.???????????????????????????? 1)???????????????????? 2)???????????????????????? 3)?????????????????????????????????????? 4)???????????????????????????? 5)???????????????????????? 7.?????????????????? 1)???????????????????? 2)???????????? 3)?????????????????? 4)???????????????????????????????? 8.???????????????????????????????????????????????????? 9.?????????????????????????????????????? 10.?????????????? ???????????????????? 1.???????????????????????????????????????? 2.???????????????????? 3.???????????????????????????????????????? 4.?????????????????????????? 1)?????????????????????????????????????????????????? ???????? 2)?????????????????????????????????????????????????????? 3)?????????????????????????????????????????????????????????? 4)?????????????????????????????????????????????????????????????? 5)???????????????????????????????????????????????????? 5.???????????????????D?D???????????????? 6.???????????????????????????? 7.???????????????????????????? 8.???????????????????? 1)??????????????V??R??M???? 2)???????????????????????????? 9.???????????????????????? 1)?????????????????????????????????? 10.?????????????? ???????????????????? 1.?????????????????? 1)?????????????????????????????? 2)???????????????????????????????????? 3)???????????????????????????????????? 2.???????????????????? 1)?????????????????????????? 2)?????????????????????????????????????????? 3)???????????????????????????????????????? 4)???????????????????????????????????????????????????? 3.?????????????????????? 1)?????????????????????????????????????????? 2)???????????????????? 3)?????????????????????????????????????????? 4.???????????????????????? 1)???????????????????????????????????? 2)???????????????????????????????????? 3)???????????????????????????????? 4)???????????????????????????????????????????????? 5.???????????????????? 1)???????????????????????????????????????? 2)?????????????????????????????? 3)???????????????????? 4)???????????????????? 6.?????????????? ???????????????????? 1.????????????????A?????????????????????????? 2.?????????????????????????????????? 3.???????????????????????????????? 1)???????????????? 2)???????????????? 3)???????????????? 4.???????????????????? 1)???????????????????????????????? 2)???????? 3)???????? 4)???????? 5)???????????????????? 5.???????????????????? 1)?????????????? 2)???????????????????????????????????????? 3)???????????????????? 6.??????Beta?????????????????????????????????????? 1)?????????????????? 2)?????????????????? 3)?????????????????????????????????????????? 4)?????????????????????????????????????????????? 7.????????????151?????? 8.???????????????????????????????????????? 9.?????????????????????????????????????? 10.?????????????? ???????????????????????????????? 1.?????????????????? 2.???????????????????? 1)??????????????????????????????????????????????AHP 3.???????????????? 1)?????????????????????????????? 2)???????????????????????????????? 3)?????????????????????????????????? 4)???????????????????????????????????????????????????? 5)???????????????????????????????? 6)???????????????????????? 7)???????????????????????? 8)???????????????????????????????????? 4.?????????????????????? 5.???????????????? 1)???????????????????????????????????????? 2)?????????????? 3)????????????????KPI???? 4)?????????????? 6.???????????????????????? 7.???????????????????????????????? 8.?????????????? ?????????????????? 1.?????????????????????? 1)???????????????????????????????????? 2.???????????????????????D?D?????? 3.???????????? 4.???????????????? 5.???????????????? 6.???????????????? 1)?????????????? 2)?????????????? 3)???????????????????? 4)???????????? 7.?????????????????????? 8.?????????????????????????????????? 1)???????? 2)???????? 3)???????? 9.?????????????????????????????????????????????????????? ====================================================================================== ?????????????????????????? (??????????????????????????????????) ????????????????????: ==>????????????:????????????,?????????????????????? ==>????????:?????????????????????????????????????????????????????? ??????????: 10?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????IBM?????????????????????????????????????????? ??IPD???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????? ==>????????????????????(????????????????) ==>??????????????????????????(??????????????????????????????????????) ==>???????????????????????????????????????????????????????????????????? ==>???????????????????????????????????? ??????????: ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????? ??????????: ???????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????10???????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????,????????????????92%????,???????????????? ????????????????????????????????????,???????????????????????????????????? ====================================================================================== ??????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From ujh at erx.com Sat Oct 3 03:49:15 2009 From: ujh at erx.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 3 Oct 2009 11:49:15 +0800 Subject: (no subject) Message-ID: <200910030349.n933n720007166@mx1.redhat.com> ??????????????????????PPT+Excel+?????????????????? ?????????????????????? ??????????????????????????????office2003??Office2007?? ??????????2009??10??30????11??1?????? ??????????2009??11??6-8?????? ??????????2009??11??20-22?????? ??????????3600/???????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? ====================================================================================== ??????????????20???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????3?????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? ????????????????????????????Powerpoint??Excel???????????????????????????????????????????????????????? ???????????????????????????????????????????? Powerpoint??????????????????????????????????????????Powerpoint????????????????Office???????????????? ????????Powerpoint????????????????PPT?????????????????????????????????????????? ??????????Powerpoint???????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????Photoshp???????????? ?????????????????????????????????????????????????? Excel??????????????????????????????????????????????????????????????Excel??80%???????????????????????? ??????????????????????????????????????????5?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ============================================================================================== ????????????????????????????????????????????????????????????office2003??Office2007 ????PPT??????????????????????????????Powerpoint???????????????????????? 1.???????????????????????????????????????????????????????????? 2.?????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????????????????????????????????? 4.Flash??????????????????????Flash??????????PPT??????????????????????Flash?? ?????????????????????????????????????????? ????Excel??????????????????????????????BladeOfficeExcel???????????????????????? 1.????????????????????????????????????????????????????????????????????Excel???????????????????????????? ???????????????????????????????????????????????????????? 2.Excel??????????????Excel2003???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ======================================================================================================== ???????? ???????????????????????? ?????????????????????????? 1.?????????????????????????????????????????????????????????? 2.????????????????????????500???????????????????????????????? 3.???????????????????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ?????????????????????????? 1.????Office???????????????? 2.???????????????????? 3.?????????????????? 4.???????????????? 5.???????????????????????????????? 6.?????????????????? 7.????3D?????????????? 8.???????????????????????? 9.?????????????????? 10.??????????????* 11.??????????????????????????????????3-D????* ???????????????????????? 1.???????????? 2.???????????????????????? ???????????????????????? 3.???????????? ???????????????????????????????????? 4.????????????????40M??????????6M 5.???????????????? ????SmartArt???????? 1.?????????????????????????????? 2.???????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????????????? 6.??????????????SmartArt ???????????????????? 1.?????????????????????????????? 2.?????????????????????????? 3.?????????????????????????? 4.?????????????? 5.?????????????????????? 6.?????????????????? ????Excel???????? 1.?????????????????????????????????????????????? 2.??????????????????????????????10??????????5???????? 3.?????????????????????? 4.?????????????????? 5.???????????????????????????????????????????????? 6.??????Powerpoint???????????????????? 7.?????????????????????? 8.???????????????????????????????? 9.???????????????????????????????????? ?????????????????? 1.????????????Powerpoint?????????? 2.???????????????????????????? 3.?????????????????? 4.?????????????????????? 5.?????????????????????????????????? ???????????????????? 1.Powerpoint?????????????????? 2.?????????????????????????????????? 3.???????????????? 4.???????????????????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.?????????????????????? 8.?????????????????????????????????????? ????????Excel?????????????? ???????????? 1.?????????????????? 2.?????????????????? 3.??????????2?????? 4.??????????????????Excel?????????????????????????????? 5.?????????????????????????????????? ???????????????? 1.????IF???????????????? 2.AND??OR??NOT???? 3.?????????????????????? ?????????????? 1.?????????????????? 2.???????????????????????????? 3.???????? a)???????????????????????????????? b)?????????? c)???????????????????? ???????????? 1.???????????? 2.???????????????????????? ???????????? 1.???????????????? 2.????VLOOKUP??HLOOKUP???????????? 3.?????????????????????? a)???????????????????????????????????? b)???????????????????????????????????????????????????????????????? 4.?????????????????????????? 5.???????????????????????????? ???????????? 1.???????????????? 2.?????????????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????? 6.?????????????????? ???????????? 1.?????????? 2.?????????? 3.???????????????? ???????????????? 1.???????????????? 2.???????????????? 3.?????????????????? 4.???????????????? 5.?????????????????????????? ?????????????????????? 1.?????????????? 2.?????????????? 3.???????????? 4.???????????? 5.???????????? 6.?????????????????????????????? 7.???????????????????? a)?????????? b)?????????? c)?????? d)?????????? 8.???????????????????????? 9.?????????????????????????????? ?????????????????? 1.?????????????????????? 2.???????????????????????????????? 3.?????????????????? ???????????????????? ?????????????????? 1.?????????????????? 2.????Powerpoint?????????????????? 3.????Word?????????????????? 4.????Excel?????????????????? ???????????? 1.?????????????????????????????????????????????? 2.???????????????? 3.??????????????SmartArt???????????? 4.???????????????????? ???????????????? 1.?????????????????? 2.???????????????????????????????? 3.Outlook?????????????????? ================================================================================================== ??????????????????????????????????????????????IPMP???????????????????????????????????????????????? ????????????????????????????????????????????????????????????????ERP???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????DELL????????????????????????????????????????????????????????????????????TCL???????? ============================================================================================== ????????????????????????PPT+Excel+??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From vb at ng.com Sat Oct 3 08:42:07 2009 From: vb at ng.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Sat, 03 Oct 2009 08:42:07 -0000 Subject: (no subject) Message-ID: <200910030841.n938ftTw012077@mx1.redhat.com> ??????????? ?????2009?11?7-9??????? ?? ??????????CEO???????????????????? ????? ?????????????3800? ?????5800?/?????????/????/??????? ?????020-80560638?020-85917945 ??? ====================================================================== ????????????30?????????????????/???????????? --???????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ????????????????????????????????????????????? --??CEO????????????????????? ???????????????????????????? ??????????????? ????CEO??????????????????????????????????? ???????????????????????????????????????????????????????? ????????????????????????????????????????????? ?????????????????????????????? ?????????????????? ?????????????????? ============================================================================== ?????? ??????????????????????????? ???????? ??????????????????????????????????????? ???????? ????????????????????????????????????????? ???????? ????????????????????????????????????????? 90??1919??????????????????????????????? 60??1949???????????????????????????????? 30??1979????????????????????????????????? 2009??????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ????30???????????????????????? ====================================================================== ?????? ?????????????????? ?????????????????????????????? ????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ???? -????????????????????????????? -?????????1-2??????????????????? -????????/??/?????????????????????? ??????????????????????????????????? ?????????????????????????????????? -????????/????????????????????????? ??????????????????????????????????? ??????????????????????-??-??-???????? -????????????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ?????????????????? ?????????????????????????????? ????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ????????????? --??????????????????????????????/??/???????????????????????? --??????????-??????,????????????????????????????????????? ??????????????????????????????? -???????????????????????????? -??????????????????????????????? -???????????????????????????????? ??????????????????????????????? -????????????????????????????? -???????????????????????????????? -??????????????????????????????? ???????????????\?????? ?????????????????????????????? ?????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????? ?????? -?????????????????????????????????????? ?;?????????????????????????; ????????????????????????????? -??????????????????? -?????????????????????????????? -????????????????????? -???????????????????? ???????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? ====================================================================== ??????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ????????????????????????????????????????????????????1990?? ??????????????????????????? ????? ????????2001?-2003????????2003????????????? ?????????????????2005 ????????????????????????????????????????????? ------------------------------------------------------------------------------ ??????? ?????????????????????????????????????????????15?????????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ? ??HPO?????????????????????????????? ????????????????????????????????????????????????????????? ??????????????????????????????????? ------------------------------------------------------------------------------ ???????????????????????????????????????????????500??????. ??????????????????????????????????????????????????????? ------------------------------------------------------------------------ ??????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638??? From tyg at dfer.com Sat Oct 3 11:58:10 2009 From: tyg at dfer.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sat, 3 Oct 2009 19:58:10 +0800 Subject: (no subject) Message-ID: <200910031158.n93Bw9lG017810@mx1.redhat.com> ???????????????? ??????????2009??10??23-24?? ???? ??????????2009??10??29-30?? ???? ??????????2009??10??31-11??1?? ???? ??????????2009??11??20-21?? ???? ??????????2009??11??27-28?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From erfyu at qvkd.com Sun Oct 4 17:59:24 2009 From: erfyu at qvkd.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sun, 04 Oct 2009 17:59:24 -0000 Subject: (no subject) Message-ID: <200910041759.n94HxAXP011113@mx1.redhat.com> ??????????????--?????????????? ??????????2009??10??26-27?????? ??????????2009??10??28-29?????? ??????????2009??11??02-03?????? ??????????3200??/???? *????????????????*???????????????????????????????? ?????????????????????????????????????????????????????????? ????????????????????/??????????????????/???????????????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? ---------------------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? 1.?????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? 2.???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????? 4.?????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? 5.?????????????????????????????????????????????????????????? 6.???????????????????????????????????? 7.???????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????/????/?????????????????????????????????????????????? ----------------------------------------------------------------------------------------- ???????? 1???????????????????????????????????????????????? 2??????????????????????????DFM?????????????????? 3??????????????????????????DFT?????????????????? 4?????????????????????????????????????? 5???????????????????????????????????????????????????? 6???????????????????????????????? ----------------------------------------------------------------------------------------- ???????? ???????????? ???????????????????? 1.???????????????????????????????????????? 2.?????????????????? 1?????????????????????????????????? 2?????????????????????????????????????? 3.???????????????????????????????????????? 4.?????????????????? 1????????RD??????????D&P??????????P???????? 2???????????????????? 3???????????????? 4?????????????????? *???????? *???????????? *???????????????????? *?????????????????????????????????? 5.?????????????? 1????????????????????????NPI?? 2???????????????????????????? 3???????????????????????????? 4???????????????????????????????????????????????????????? 6.???????????????????????????????????????????????????????????????? ?????????????????? 1.???????????????????? 1?????????? 2?????????? 3?????????? 4?????????? 5?????????? 6???????????????????????????? 2.???????????????????? 3.?????????????????????????????????? 1???????????????????????????? 2???????????????????????????????? 3?????????????????????????????????? *?????????????????? *???????????????????? *???????????????? 4?????????????????????? *???????????????????????????????????????????? *???????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ????????????????????????????DFM?? 1.?????????????????????????????????????????? 1?????????????????????????? 2???????????????????????????????????????????????? 3???????????????????????????????????????????????????????? 4???????????? *?????????????????????? *???????????????????????? *?????????????????????????????????????? *???????????????????????????? *???????????????? *???????????????????????????????????????? *?????????????????????????????????????????? *?????????????????? *?????????????????? *?????????????????????????????????????????????????? 5???????????????? *?????????????? *?????????????????????????? *?????????????????? *?????????????????? *???????????????????????????? *?????????????????????????????????? *?????????????????????????????? 6?????????? *???????????????????????????????? *???????????????????????????????? *?????????????????????????????? 2.???????????????????????????????????????????????????????????????????? 3.???????????????? 1???????????????????????? 2?????????????????????????????????? 3???????????????????? 4???????????????????? 5?????????????????????????????? *???????? *???????? *???????? *???????? 6??????????????????????DFM???????????? 7???????????????????????????????? 8?????????????????????????? 4.?????????????????????????????????????????????????????????????????????????????????? ????????????????????????????DFT?? 1.???????????????????????????????? 1????????????Alpha????????????????Beta???????????? 2.??????????Alpha????BETA???? 1???????????????????????????????????????????????????????? 2???????????????????????????????????? 3????????????????????????????????????????????????BETA?????????????? 4???????????????????????????????? 5???????????????????????????????????????????????????????????????????????????? 3.???????????????????????????????? 1?????????????????????? 2?????????????????????????????????? 3?????????????????????????????????? 4???????????????????????? 5?????????????????????????????????????????????????? *?????????????????????? *?????????????????????????????????????? *???????????????????????????????????????????????????? *?????????????????????????????????????????? *???????????????????????????????????????????????????????? *???????????????????????? *???????????????????????????? 6????????????????????????DFT???????????? 7?????????????????????????? 4.????????????????????????????DFT?????????????????????????????????????????? ???????????????????? 1.?????????????????????????? 2.???????????????????????????? 3.???????????????????????????????????????????????????????????? 4.?????????????????????????????? 1?????????????????????????????????? 5.?????????????????? 1???????????????????????????????????????????? 2?????????????????????????? 3???????????????????? 4?????????????????????????? *?????????????????????????????????????????????????????????????????????? *???????????????????????????????????????? *???????? *??????????????BOM???????????????????? *???????????????????????????????? 5?????????????????????????????????? 6?????????????????????????? 6.???????? 1?????????????????????????????????? 2?????????????????????????????? *???????????????? *?????????????????? *?????????????????? 7.???????????????? 1?????????????????????? 2?????????????????????????? 3?????????????? 4???????????????? 5?????????? 8.?????????????????????????????????????????????????????????????????????? ----------------------------------------------------------------------------------------- ??????????Charles ??????????????????????????????????????????????????????????????????????????????????????10???????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????IBM???????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????IBM?????????????????????????????????????????D?D???????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????IT??????MARKETING???????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????IT????????????????????????????????????????????????????????????????????????KPI ?????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????????????????--??????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From yu at wega.com Mon Oct 5 02:02:06 2009 From: yu at wega.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Mon, 5 Oct 2009 10:02:06 +0800 Subject: (no subject) Message-ID: <200910050202.n95220kf021143@mx1.redhat.com> ????????????-???????????????????? ??????????2009??10??24-25???????? ??????????2009??11??6-7?? ???? ?? ??:25OO??/???????????????????????????????????? ????????:?????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ----------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??????????????????;??????????????????????????????????????????????;?????????????????? ??????????????;????????????????????????????????????;???????????????????????????????? ???????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??????100?????????????????????????? ---------------------------------------------------------------------------------- ???????? ?????????????????????????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????? ?????????????????????? ???????????????????? ???????????????????????? ---------------------------------------------------------------------------------- ???????? ???????? ???????????????????????????? ?????????????????????? ?C ???????????????? ???????????????????????????????????? 1.?????????????????????????? 2.???????????????????????????????????? 3.???????????????????????????? 4.???????????????????????????? ???????????????????????????????? 1.???????????????????????????????????? 2.?????????????????????????????? 3.???????????????????????? 4.???????????????? 5.?????????????????????? 6.?????? ???????????????????????????????? 1.?????????????????????????????????? 2.???????????????????????????????????? 3.???????????? 4.???????????????? ???????????????????????????????????????? 1.?????????? 2.?????????? 3.?????????????????????????????????????? ?????????????????????????????? 1.???????????????????????? 2.??????????5?????? ???????????? ???????????? ?????????? ?????????? ?????????? ?????????? ?????????? ?????????? ???????????? ?????????? 3.?????????????? ???????? ?????????????????????? ?????????????????????? 2.?????????? ???????????????????????????????? ???????????????????????????????????? ???????????????????? 3.???????? ???????????????????????????????? ???????????????????????????????????? ???????????????? 4.?????????????? ???????????????????????????????????????? ???????????????????????????????? ???????????????????????? ?????????????????????????????????????????????? ?????????????????????? 1.???????????????????????? 2.???????????????????????????????????? 3.?????????????????????? 4.???????????????????? ???????????????? 1.???????????????????????????? 2.???????????????????????????????????????????????????????? 3.????????PMC?????????????????????????????? 4.???????????????????????????? 5.?????????????????????????????? 6.?????????????????????? ???????????????? 1.???????????????????????? ?????????? ???????????????? ?????????? ???????????????? 2.???????????????????????? 3.?????????????? 4.???????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????? ???????????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????? ?????????????????????????????????? ???????????????????? 1.???????????????????????? ?????????????????? ???????????????? ?????????????????? 2.???????????????????????? ?????????????????? ???????????????? ???????????????????????????????????? 3.???????????????????????? ?????????????????????? ???????????????????? ?????????????????????????????????????? ???????????????????????? ???????? ???????????? ???????????????????????????????????????????? 1.???????????????? 2.?????????????????????? ???????????????????????????? 1.??????????7?????????? ?????????????????????? 1.?????????????????????? 2.?????????????????????????? 3.?????????????? 4.???????????????? 5.???????????????? ???????????????????????????????????????????????? ???????????????????????????? ???????????????????????????????? 1.???????????????????????????? 2.???????????????????? 3.???????????????????????????? ?????????????????????? ???????????????????????? ???????????????????? 1.?????????????? 2.?????????????????????? 3.????????????????--?????????? 4.?????????????????? ?????????????????????????????? 1.?????????????????? 2.???????????????? 3.???????????????????? 4.???????????????????? 5.?????????????? 6.?????????????????????? 7.?????????????? 8.???????????????????????? 9.?????????????? 10.???????????????????? ???????????????????? ???????? ?????????????? ?????????????????????????????? 1.???????????????????? 2.?????????????? 3.???????????????????????? 4.???????????????????????????? ?????????????????????? 1.?????????????????????????? 2.???????????????????????????????????????????????? 3.???????????????????????????? 4.?????????????????????????????????? ???????????????????????????? ----------------------------------------------------------------------------------- ????????:??????,????????MBA,????????PMP????????PMP????????????,???????????????????? ??????????????????20???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ????????????MTP?????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????? 1??????????????????????????????????46.7%??????96%??????????????64%??????98%??????????1.5???? 2??????????????????????????????????1.8????????????????55%??????85%??????????????????20%??????3%?? 3??????????????????????????1.7????????????????????100%????????????????50%?????????????????????????????????? -------------------------------------------------------------------- ??????????????-????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From fde at werg.com Mon Oct 5 12:08:45 2009 From: fde at werg.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Mon, 5 Oct 2009 20:08:45 +0800 Subject: (no subject) Message-ID: <200910051208.n95C8gwB013192@mx1.redhat.com> ???????????????????????? ?????2009?10?17--18?---? ? ?????2009?10?24--25?---? ? ?????????CEO?????????????????????????????????? ???????????????????????????????????????????? ?????????????? ?????2500?/????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ?????500?????????????????????? ====================================================================================== ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ???????????????? ????????????????????? ??????????????????????? ????????????????????????????????? ?????????????????????????????????? ???????????????????????????????? ????????????????????????????????????????????? ??????,????????????? ================================================================================== ???? ??????????????????????????????????????????? ????????????????????????????????????????????? ?????????? ?????????????????????????????????? ?????????????????????? ????????????????????? ????????????????????? ????????????????????????? ?????????????????? ???????????????????? ?????????????????????? ???????????????????????????...... ====================================================================================== ????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????2009?6?? ??????????120????????????????????????????????,? ?????3000????????97%????????????????????????????? ????????????????????????????????????????????? ???????????????2000???????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? 1???????? ????????? ?????????? ??????? 2???????? ???????????? ????????????? 3???????? ???????????? ???????????? ?????????????? 1???????? ?????????? ???????????? 2???????? ??????? ??????????? ????????? 3??????? ????????????? ??????????????????? 4?????????? ????????? ??????????? 5???????? ?????? ????????? ????????? ?????????????? 1??????????? ???????? ???????????? ?????? 2??????????? RPM?????? DSO????DSO??????DSO????????????DSO A/R????????????????????? A/R???????????????????????????????????? 3???????????? ?????????? ??????????? 1????????? ?????????????? ????????????? 2?????????? ????????? ???????????? 3??????? ????? ?????? 4????????? ???????? ?????????????? 5????????? ?????????????? 1??????? ????????? ???????? 2?????????? ???????????????? ??????????? 3??????????? ???????? ????????? ??????????? 4??????????? ??????????? ??????????? ????????? 5???????????? ??????? ????????? 6??????????? ?????????????? ????????????? ??????????? 1????????? ??? ??????????? 2????? ???????? ????????????? ??????????? ????????????? ????????? ?????????? ??????????? ?????????? ????????????? ?????????? ????????????? 3?????????? ??????????? ???????? ??????????? ???????? ??????????? ??????????? ??????????? 4??????? ??????? ???????????? ???????????????? 1????????? ??????????? ??????????? 2?????????? ??????????? ??????????? 3?????????? ??????????????????? ????????????? 4???????????? ?????????????? ------------------------------------------------------------------------- ???????????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From erg at eukd.com Tue Oct 6 04:27:01 2009 From: erg at eukd.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Tue, 6 Oct 2009 12:27:01 +0800 Subject: (no subject) Message-ID: <200910060426.n964QoD7009085@mx1.redhat.com> ????????????????? ???09???????????? ------------------------------------------------------------------------ ?????2009?10?17-18? ?? ?????2009?10?24-25? ?? ?????2009?10?31-11?1? ?? ?????2860?/???????????????????? ???????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ------------------------------------------------------------------------ ????? ???????????????????????? ????????????????? 1??????????????? 2??????????????????? 3?????????????????????????????? 4?????????????????????? 5??????????????????????? 6????????????????????????? 7?????????????????????????????????? 8?????????????????????????????????? 9???????????????????????,????????????? 10??????????????????????????? 11????????????????????????????????? 12?????????????????????????????????? ????????????????? ------------------------------------------------------------------------ ????? ??????????????????????? 1????????????? 2??????????????? 3???????????????? 4????????? 5?????????????????? ???????????????????????????????????? ??????????????????????????????????? 2,000???????????????????????20,000? ------------------------------------------------------------------------ ????? 1??????????????????? 2??????????????????? 3?????????????????????????? 4????????????????? 5?????2007????????26???????????????,???? ????????????????????????????????? ------------------------------------------------------------------------ ????? ????????????????????? ??????????????????? ???50???? ?????????? ??????? ????????????????????? ????????? ?????????????? ???????? ?? ?????? ??????300% ?????????? ?????????????????? ??????? ??????????? ??????? ?????????????????????? ???????????? ??????? ???????????????????? ?????? ????? ????????????????? ???????????? ???????????? ??????? ???????????????????????? ?????????? ??????????????????? ???????????? ????? ?????????? ?????????? ??????????????? ?????????????????????? ?????? ??????????? ????????????????????????? ????????? ??? ????????????????????????????? ????????? ????????????????????????? ????????????????????? ??? ??????? ??? ????????????1?????????? ??? ????????????2?????? ??? ????????????3??????? ??? ??????????? ??????????????????? ??????? ??????????????? ????????????????????? ?????????????? ????????????????????????????? ???????? ????????????????? ????????????????? ?????????????????? ???????????????? ??????5?????????? ?????????????? ??????????????????????????????? ??????????? ????????? ?????????????????????????????????? ????????????? ????????PK?? ??????????????????? ?????????? ????????? ??????????? ???????????? ??????????????? ????????????? ?????????? ????????????? ?????????? ????????? ????????? ????????????????????????????? ???????????????????? ???????????? ??????????????????????????? ?????????? ????????????????? ??????????????????????????? ????????????????????? ???????????? ?????????? ??? ?????????????? ??????? ???????????????????????? ???????????????????? ?????????????????????? ??? ??????????????? ?????????? ??????????????????? ??????? ?????????????????????? ???????? ??????? ???????????????????? ??????? ?????????????????????? ?????????? ?????????????? ??????? ???????????????????? ???????? ???????????????????? ??????????????????? ?????????????????????? ??????????????????? ?????????????????????? ??????????????????? ??????????????? ????????? ???????????????????????? ????? ????????????????? ????????????????? ???????????????????? ????????1% ??? ??????????????????? ???? ???????????????????? ???GMP?? ????????????????????????????? ???????????? ???? ???????????? ???? ?????????? ???? ????????? ------------------------------------------------------------------------ ????? ??? ???????????????????????????????????? ???????????????????????? ?????PLA??????????????????????????96?? ???????????????????????????????????? ???????????3???????????????,????????? ?????????????????????????? ??????MBA????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ?????????????? ??????????????????????????????????? ????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ??? ?????????????????? ???????????????????????????????? ???????????????????????????? ?????????????????????? ?????????????????????????? ?????????????????????? ------------------------------------------------------------------------ ???????????????????????? ??????????????020-62351156????5???????????? ?????????????????? ?????____________________________________ ??????____________ ?????______________ ?????_____________ ?????____________ ?????___________ ? ?????_____________ ? ? ? ??______________ ?????_____________ ?????____________ ? ? ??______________ ?????_____________ ?????____________ ? ? ??______________ ?????_____________ ?????____________ ????????/?? ??? ????????????????______? ????____________ From ghj at ghj.com Tue Oct 6 14:31:27 2009 From: ghj at ghj.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Tue, 06 Oct 2009 14:31:27 -0000 Subject: (no subject) Message-ID: <200910061431.n96EVFB2012687@mx1.redhat.com> ??????????? ?????2009?11?7-9??????? ?? ??????????CEO???????????????????? ????? ?????????????3800? ?????5800?/?????????/????/??????? ?????020-80560638?020-85917945 ??? ====================================================================== ????????????30?????????????????/???????????? --???????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ????????????????????????????????????????????? --??CEO????????????????????? ???????????????????????????? ??????????????? ????CEO??????????????????????????????????? ???????????????????????????????????????????????????????? ????????????????????????????????????????????? ?????????????????????????????? ?????????????????? ?????????????????? ============================================================================== ?????? ??????????????????????????? ???????? ??????????????????????????????????????? ???????? ????????????????????????????????????????? ???????? ????????????????????????????????????????? 90??1919??????????????????????????????? 60??1949???????????????????????????????? 30??1979????????????????????????????????? 2009??????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ????30???????????????????????? ====================================================================== ?????? ?????????????????? ?????????????????????????????? ????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ???? -????????????????????????????? -?????????1-2??????????????????? -????????/??/?????????????????????? ??????????????????????????????????? ?????????????????????????????????? -????????/????????????????????????? ??????????????????????????????????? ??????????????????????-??-??-???????? -????????????????????????????????? ?????????????????????????????????? ?????????????????????????????????? ?????????????????? ?????????????????????????????? ????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ????????????? --??????????????????????????????/??/???????????????????????? --??????????-??????,????????????????????????????????????? ??????????????????????????????? -???????????????????????????? -??????????????????????????????? -???????????????????????????????? ??????????????????????????????? -????????????????????????????? -???????????????????????????????? -??????????????????????????????? ???????????????\?????? ?????????????????????????????? ?????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????? ?????? -?????????????????????????????????????? ?;?????????????????????????; ????????????????????????????? -??????????????????? -?????????????????????????????? -????????????????????? -???????????????????? ???????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? -??????????????????????????????? ====================================================================== ??????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ????????????????????????????????????????????????????1990?? ??????????????????????????? ????? ????????2001?-2003????????2003????????????? ?????????????????2005 ????????????????????????????????????????????? ------------------------------------------------------------------------------ ??????? ?????????????????????????????????????????????15?????????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ? ??HPO?????????????????????????????? ????????????????????????????????????????????????????????? ??????????????????????????????????? ------------------------------------------------------------------------------ ???????????????????????????????????????????????500??????. ??????????????????????????????????????????????????????? ------------------------------------------------------------------------ ??????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638??? From wef at zyub.com Mon Oct 12 17:12:57 2009 From: wef at zyub.com (=?GB2312?B?xeDRtQ==?=) Date: Tue, 13 Oct 2009 01:12:57 +0800 Subject: (no subject) Message-ID: <200910121712.n9CHCrSI026344@mx1.redhat.com> ??????????????? ?????2009?10?30-31?--- ?? ?????2009?11?6--7? ----?? ????: ?????????????????????????????????????? ????: 2800?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ====================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????? ================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????? ??????????????????? ??????????????????????? ?????????????????? ?????????????????????????? ????????????????????????????????????? ??????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA??????? ??CPA????????CPT???????????????????????????????????? ????????????????????????????????????????????????? ?????????CFO?????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????????????????????????????,?????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????(??)?? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? ???????? ??????????? 1????? 2??????? 3???????? ??????? 1??? 2??? 3?????? 4??? 5??? 6??? ???????? 1???????? 2?????? ????????????? ????????????????????? 1??????????? 2??????????? ?????????????????? 1????? 2????? 3????? 4?????? 5????? 6??? 7)???? 8????? 9????? 10????? 11????? 12?????? 13????? 14?????? 15????? 16????? 17????? 18?????? ?????????? 1??????????????? 2???????????? 3?????????? 4????????????? ??????????? ?????????? 1?????? 2?????? ???????????? 1????? 2????? 3???????? 4????? 5????? 6????? 7?????? 8?????? 9????? 10???? ?????????????? 1????????????? 2????????????? 3????????????? 4????????????? 5???????????? ???????? 1?????????? 2?????????? 3?????????????????? 4????????? ?????????? ???????????? 1?????????????? 2?????????????? 3?????????????? 4?????????????? ???????????? 1???????????????????? 2??????????????? 3????????????? ?????????? 1????????? 2??????? 3????????? ????????????? ????????????? 1?????????? 2?????????? 3????????? 4?????????? 5????????????? ????????? 1??????????? 2???????????? ????? ???????????? 1???????? 2???????? 3???????? ???????? 1??????? 2??????? 3???????? 4?????????? 5????????? 6?????? 7????? 8??????? 9??????? 10?????? 11?????????? 12?????? 13??????? 14???????? 15???????? 16????? ?????????????????? ????????????? ?????????????????? 1????????? 2????????? 3???????????? 4????????? 5????????? ?????? 1???????? 2??????? 3????????? 4??????ABC??? ???????? 1?????????? 2????? 3????? 4?????????? ???????? 1???????? 2??????? 3???????? 4?????????? 5????????????Z-SCORE??? ???????????????????? 1??????? 2?????????????????? ???????????? ???????? ????????????????????? 1??????? 2??????? 3?????????? 4???????? ???????????? 1????? 2????? 3????? 4????? 5????? ???????????? 1????? 2????? 3????? 4????? ?????????? 1?????????? 2?????????? 3?????????? 4?????????? ?????????? 1?????? 2?????? 3?????? ???????????? 1????? 2????? 3????? 4????? 5????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? 6??????? 7??????? 8??????? 9??????? ???????? 1???????? 2???????? ?????????? 1????????????? 2????? 3????? ???????? ??????? 1????????? 2?????????? 3????? 4???????????????? ??????????????? 1?????? 2????? 3????? 4??????? -------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From vff at tbz.com Wed Oct 14 02:50:47 2009 From: vff at tbz.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Wed, 14 Oct 2009 10:50:47 +0800 Subject: (no subject) Message-ID: <200910140250.n9E2ol36007749@mx1.redhat.com> ???????????????????? ??????????2009??10??30-31?? ???? ??????????2009??11??6-7?? ???? ??????????????CEO/??????????????????/??????????????/?????????????????????????????????????????????? ????????????/??????????PMO?????????????????????????????????????????????????????????????????? ??????2500??/2??/??(??????????????????????????????????????????????) ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------- ??????????500?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ====================================================================================== ???????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? 1.?????????????????????????????????????????????????? 2.???????????????????????????????????????????? 3.???????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????? 5.?????????????????????????????? 6.?????????????????????????????????????????????????????? 7.?????????????????????????? 8.?????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????,?????????????????????????????? ????????????????????????????????????????. ====================================================================================== ???????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????? ???????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? ====================================================================================== ???????? ?????????????????????????????????????????? 1.???????????????????? 2.?????????????????????? 3.???????????????????????????? 4.?????????????????????????????? 5.???????????????????????????????????????????????? ?????????????????????????????????? 1.???????????????????????????????????? 2.???????????????????????? 3.???????????????????????? 4.?????????????????????????????????????????? 5.???????????????????????????????????? 6.???????????????????????????? 1)???????????????????? 2)???????????????????????? 3)?????????????????????????????????????? 4)???????????????????????????? 5)???????????????????????? 7.?????????????????? 1)???????????????????? 2)???????????? 3)?????????????????? 4)???????????????????????????????? 8.???????????????????????????????????????????????????? 9.?????????????????????????????????????? 10.?????????????? ???????????????????? 1.???????????????????????????????????????? 2.???????????????????? 3.???????????????????????????????????????? 4.?????????????????????????? 1)?????????????????????????????????????????????????? ???????? 2)?????????????????????????????????????????????????????? 3)?????????????????????????????????????????????????????????? 4)?????????????????????????????????????????????????????????????? 5)???????????????????????????????????????????????????? 5.???????????????????D?D???????????????? 6.???????????????????????????? 7.???????????????????????????? 8.???????????????????? 1)??????????????V??R??M???? 2)???????????????????????????? 9.???????????????????????? 1)?????????????????????????????????? 10.?????????????? ???????????????????? 1.?????????????????? 1)?????????????????????????????? 2)???????????????????????????????????? 3)???????????????????????????????????? 2.???????????????????? 1)?????????????????????????? 2)?????????????????????????????????????????? 3)???????????????????????????????????????? 4)???????????????????????????????????????????????????? 3.?????????????????????? 1)?????????????????????????????????????????? 2)???????????????????? 3)?????????????????????????????????????????? 4.???????????????????????? 1)???????????????????????????????????? 2)???????????????????????????????????? 3)???????????????????????????????? 4)???????????????????????????????????????????????? 5.???????????????????? 1)???????????????????????????????????????? 2)?????????????????????????????? 3)???????????????????? 4)???????????????????? 6.?????????????? ???????????????????? 1.????????????????A?????????????????????????? 2.?????????????????????????????????? 3.???????????????????????????????? 1)???????????????? 2)???????????????? 3)???????????????? 4.???????????????????? 1)???????????????????????????????? 2)???????? 3)???????? 4)???????? 5)???????????????????? 5.???????????????????? 1)?????????????? 2)???????????????????????????????????????? 3)???????????????????? 6.??????Beta?????????????????????????????????????? 1)?????????????????? 2)?????????????????? 3)?????????????????????????????????????????? 4)?????????????????????????????????????????????? 7.????????????151?????? 8.???????????????????????????????????????? 9.?????????????????????????????????????? 10.?????????????? ???????????????????????????????? 1.?????????????????? 2.???????????????????? 1)??????????????????????????????????????????????AHP 3.???????????????? 1)?????????????????????????????? 2)???????????????????????????????? 3)?????????????????????????????????? 4)???????????????????????????????????????????????????? 5)???????????????????????????????? 6)???????????????????????? 7)???????????????????????? 8)???????????????????????????????????? 4.?????????????????????? 5.???????????????? 1)???????????????????????????????????????? 2)?????????????? 3)????????????????KPI???? 4)?????????????? 6.???????????????????????? 7.???????????????????????????????? 8.?????????????? ?????????????????? 1.?????????????????????? 1)???????????????????????????????????? 2.???????????????????????D?D?????? 3.???????????? 4.???????????????? 5.???????????????? 6.???????????????? 1)?????????????? 2)?????????????? 3)???????????????????? 4)???????????? 7.?????????????????????? 8.?????????????????????????????????? 1)???????? 2)???????? 3)???????? 9.?????????????????????????????????????????????????????? ====================================================================================== ?????????????????????????? (??????????????????????????????????) ????????????????????: ==>????????????:????????????,?????????????????????? ==>????????:?????????????????????????????????????????????????????? ??????????: 10?????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????IBM?????????????????????????????????????????? ??IPD???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????? ==>????????????????????(????????????????) ==>??????????????????????????(??????????????????????????????????????) ==>???????????????????????????????????????????????????????????????????? ==>???????????????????????????????????? ??????????: ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????? ??????????: ???????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????10???????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????,????????????????92%????,???????????????? ????????????????????????????????????,???????????????????????????????????? ====================================================================================== ??????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From market at yud.cn Wed Oct 14 11:20:08 2009 From: market at yud.cn (=?GB2312?B?1tC5+s7vwfe9u9LX1tDQxA==?=) Date: Wed, 14 Oct 2009 19:20:08 +0800 Subject: (no subject) Message-ID: <20091014120124.E3EE85FC41B@ns2.71dns.cn> -------------- next part -------------- An HTML attachment was scrubbed... URL: From edko at ergx.com Wed Oct 14 23:49:58 2009 From: edko at ergx.com (=?GB2312?B?16rQ6MfzyMvUsQ==?=) Date: Thu, 15 Oct 2009 07:49:58 +0800 Subject: (no subject) Message-ID: <200910142350.n9ENnwnh015003@mx1.redhat.com> ??????????????? ?????2009?10?30-31?--- ?? ?????2009?11?6--7? ----?? ????: ?????????????????????????????????????? ????: 2800?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ====================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????? ================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????? ??????????????????? ??????????????????????? ?????????????????? ?????????????????????????? ????????????????????????????????????? ??????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA??????? ??CPA????????CPT???????????????????????????????????? ????????????????????????????????????????????????? ?????????CFO?????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????????????????????????????,?????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????(??)?? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? ???????? ??????????? 1????? 2??????? 3???????? ??????? 1??? 2??? 3?????? 4??? 5??? 6??? ???????? 1???????? 2?????? ????????????? ????????????????????? 1??????????? 2??????????? ?????????????????? 1????? 2????? 3????? 4?????? 5????? 6??? 7)???? 8????? 9????? 10????? 11????? 12?????? 13????? 14?????? 15????? 16????? 17????? 18?????? ?????????? 1??????????????? 2???????????? 3?????????? 4????????????? ??????????? ?????????? 1?????? 2?????? ???????????? 1????? 2????? 3???????? 4????? 5????? 6????? 7?????? 8?????? 9????? 10???? ?????????????? 1????????????? 2????????????? 3????????????? 4????????????? 5???????????? ???????? 1?????????? 2?????????? 3?????????????????? 4????????? ?????????? ???????????? 1?????????????? 2?????????????? 3?????????????? 4?????????????? ???????????? 1???????????????????? 2??????????????? 3????????????? ?????????? 1????????? 2??????? 3????????? ????????????? ????????????? 1?????????? 2?????????? 3????????? 4?????????? 5????????????? ????????? 1??????????? 2???????????? ????? ???????????? 1???????? 2???????? 3???????? ???????? 1??????? 2??????? 3???????? 4?????????? 5????????? 6?????? 7????? 8??????? 9??????? 10?????? 11?????????? 12?????? 13??????? 14???????? 15???????? 16????? ?????????????????? ????????????? ?????????????????? 1????????? 2????????? 3???????????? 4????????? 5????????? ?????? 1???????? 2??????? 3????????? 4??????ABC??? ???????? 1?????????? 2????? 3????? 4?????????? ???????? 1???????? 2??????? 3???????? 4?????????? 5????????????Z-SCORE??? ???????????????????? 1??????? 2?????????????????? ???????????? ???????? ????????????????????? 1??????? 2??????? 3?????????? 4???????? ???????????? 1????? 2????? 3????? 4????? 5????? ???????????? 1????? 2????? 3????? 4????? ?????????? 1?????????? 2?????????? 3?????????? 4?????????? ?????????? 1?????? 2?????? 3?????? ???????????? 1????? 2????? 3????? 4????? 5????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? 6??????? 7??????? 8??????? 9??????? ???????? 1???????? 2???????? ?????????? 1????????????? 2????? 3????? ???????? ??????? 1????????? 2?????????? 3????? 4???????????????? ??????????????? 1?????? 2????? 3????? 4??????? -------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From Casdy.254 at yahoo.com.hk Thu Oct 15 18:21:52 2009 From: Casdy.254 at yahoo.com.hk (Vanessa.Gang) Date: Fri, 16 Oct 2009 02:21:52 +0800 Subject: (no subject) Message-ID: <200910151821.n9FILdoB021270@mx1.redhat.com> ============================================================================== ????????????? ============================================================================== ????? 2009?10?31-11?2?(????) ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ???hrlawclub@ 126. com ============================================================================== ?????? 1? ????????????????????????????????????? ??????????????????????????????????????? ???? 2? ????????????????????????????????????? ??????????????????????????????????????? ?????? 3? ????????????????????????????????????? ??????????????????????????????????????? ?????????? 4? ????????????????????????????????????? ??????????????????????????????????????? ???????? 5? ????????????????????????????????????? ??????????????????????????????????????? ?????????? 6? ????????????????????????????????????? ??????????????????????????????????????? ??????????? ????????????????? ???????????????? ?????? ????CEO???????????????????? ????? ?????5800? ?????7800?/?????????/????/??????/??? ============================================================================== ??????????????????? ????????????10?31? 9:00-12:00 ?????? ?????? --?????????????????????????????????????? ????????????????????????? --?????????????????????????????????????? ????????????????????????????? ????????????10?31? 13:30-16:30 ?????? ?????? --?????????????????????????????????????? ?????????????????????????????? --?????????????????????????????????????? ????????????????????????? ????????????11?1? 9:00-12:00 ?????? ?????? --??????????????????????DIY??????????????? ???????????????????????? --?????????????????????????????????????? ??????????????????? ????????????11?1?13:30-16:30 ?????? ????? --?????????????????????????????????????? ?????????????????????????? --?????????????????????????????????????? ?????????????????????? ????????????11?1? 9:00-12:00 ?????? ????? --???????????????1?????????????????????? ??2????????????????????? --?????????????????????????????????????? ?????????????????????????????? 11?2????13:30-16:30???????????(??/???/???/??) ???????????????? ????? ??????????????????????????????????????? ???????????????????????????????? ???????????????????????????????????????? ??4??????25?????????????????????????????? ???????????????? ????????????????????????????????????? ?????????????????????????????????????? ????????????????????????????????????? ============================================================================== ???????18?00-21?00 10?31????????????? ????? ??????????????????????????????????????? ?????? ??????????????????????????????????? 11?1?????????????? ????? ??????????????????????????????????????? ??????????????????????????????????????? ============================================================================== ??????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????1990????????????????????????????? ????? ????????2001?-2003????????2003????????????? ?? ???????????????2005?????????????????????? ??????????????????????? ------------------------------------------------------------------------------ ??????? ??????????????????????????????????????? ??????15???????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????????? ??HPO?????????????????????? ???????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????????? ------------------------------------------------------------------------------ ???????? ??????????????????????????????????????? ???????????? ------------------------------------------------------------------------------ ??????? ??????????????????????????????????????? ???????????????????????? ============================================================================== ????????: ? ?? ???/??????????????????????????????????TOC ???????????????????????????? ???? ??????????????????????????????????????? ?????????????????????????? ???? ??????????????????????????????????????? ?????????????????????????????????? ============================================================================== ????? MMC???? ???????????? ============================================================================== From ewrf at tyxb.com Thu Oct 15 21:11:43 2009 From: ewrf at tyxb.com (=?GB2312?B?xeDRtQ==?=) Date: Thu, 15 Oct 2009 21:11:43 -0000 Subject: (no subject) Message-ID: <200910152111.n9FLBRav002136@mx1.redhat.com> ?????????????? ??????????2009??10??26-27?????? ??????????2009??10??28-29?????? ??????????2009??11??02-03?????? ??????????3200??/???? ???????? ???????????????????????????????????? ?????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????/??????????PMO???????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------------------------------------- ????????2008???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????? 1.?????????????????????????????????????????????????? 2.???????????????????????????????????????????? 3.???????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????? 5.?????????????????????????????? 6.?????????????????????????????????????????????????????? 7.?????????????????????????? 8.?????????????????????????????????????????????????? ???? ????????????4?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? -------------------------------------------------------------------------------------------- ?????????? 1.?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????? 2.???????????????????????????????????????????????????????? 3.???????????????????????????????????????????????? 4.?????????????????????????????????????????????????????? 5.???????????????????????????????????? 6.?????????????????????????????????????????????????????????? 7.???????????????????????????????????????????????????????????????? 8.???????????????????????????????D?D?????? 9.???????????????????????????????????????????????????????????????????????????? ??????????????????????Action Plan???????????????????????????????????????????? ?????????? ?????????????????????????????????? 1.???????????????????????? 2.?????????????????????? 3.???????????????????????????? 4.?????????????????????????????? 5.???????????????????????????????????????????????? ?????????????????????????????????? 1.???????????????????????????????????? 2.???????????????????????? 3.???????????????????????? 4.???????????????????????????????? 5.?????????????????????????????????????????? 6.???????????????????????????????????? 7.???????????????????????????? 1)???????????????????? 2)???????????????????????? 3)?????????????????????????????????? ???? 4)???????????????????????????? 5)???????????????????????? 8.?????????????????? 1)???????????????????? 2)???????????? 3)?????????????????? 4)???????????????????????????????? 9.???????????????????????????????????????????????????? 10.?????????????????????????????????????? 11.?????????????? ???????????????????? 1.???????????????????????????????????????? 2.?????????????????????? 3.???????????????????? 4.???????????????????????????????????????? 5.?????????????????????????? 1)?????????????????????????????????????????????????? ???????? 2)?????????????????????????????????????????????????????? 3)?????????????????????????????????????????????????????????? 4)?????????????????????????????????????????????????????????????? 5)???????????????????????????????????????????????????? 6.???????????????????????????? 7.?????????????????????????????????? 8.???????????????????D?D???????????????? 9.???????????????????????????? 10.???????????????????????????? 11.???????????????????? 1)??????????????V??R??M???? 2)???????????????????????????? 12.???????????????????????? ?????????????????????????????????? 13.?????????????? ???????????????????? 1.?????????????????? 1???????????????????????????????? 2?????????????????????????????????????? 3?????????????????????????????????????? 2.???????????????????? 1)?????????????????????????? 2)?????????????????????????????????????????? 3)???????????????????????????????????????? 4)???????????????????????????????????????????????????? 3.?????????????????????? 1)?????????????????????????????????????????? 2)???????????????????? 3)?????????????????????????????????????????? 4.???????????????????????? 1)???????????????????????????????????? 2)???????????????????????????????????? 3)???????????????????????????????? 4)???????????????????????????????????????????????? 5.???????????????????? 1)???????????????????????????????????????? 2)?????????????????????????????? 3)???????????????????? 4)???????????????????? 6.?????????????? ???????????????????? 1.????????????????A?????????????????????????? 2.?????????????????????????????????? 3.???????????????????????????????? 1)???????????????? 2)???????????????? 3)???????????????? 4.???????????????????? 1)???????????????????????????????? 2)???????? 3)???????? 4)???????? 5)???????????????????? 5.???????????????????? 1)?????????????? 2)???????????????????????????????????????? 3)???????????????????? 6.??????Beta?????????????????????????????????????? 1)?????????????????? 2)?????????????????? 3)?????????????????????????????????????????? 4)?????????????????????????????????????????????? 7.????????????151?????? 8.???????????????????????????????????????? 9.?????????????????????????????????????? 10.?????????????? ???????????????????????????????? 1.?????????????????? 2.???????????????????? 1)??????????????????????????????????????????????AHP 3.???????????????? 1)?????????????????????????????? 2)???????????????????????????????? 3)?????????????????????????????????? 4)???????????????????????????????????????????????????? 5)???????????????????????????????? 6)???????????????????????? 7)???????????????????????? 8)???????????????????????????????????? 4.?????????????????????? 5.???????????????? 1)???????????????????????????????????????? 2)?????????????? 3)????????????????KPI???? 4)?????????????? 6.???????????????????????? 7.???????????????????????????????? 8.?????????????? ?????????????????? 1.?????????????????????? 1)???????????????????????????????????? 2.???????????????????????D?D?????? 3.???????????? 4.???????????????? 5.???????????????? 6.???????????????? 1)?????????????? 2)?????????????? 3)???????????????????? 4)???????????? 7.?????????????????????? 8.?????????????????????????????????? 1)???????? 2)???????? 3)???????? 4)?????????????????????????????????????????????????? ---------------------------------------------------------------------------------- ??????????Jay ???????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ??IPD?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ????????(????????)?????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????CMM/CMMI?????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ???????????? -------------------------------------------------------------------------- ????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From rege at hyuc.com Fri Oct 16 09:33:26 2009 From: rege at hyuc.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Fri, 16 Oct 2009 17:33:26 +0800 Subject: (no subject) Message-ID: <200910160933.n9G9XOxR011868@mx1.redhat.com> ?????????????????????????? 2009??11??5-6?? [????] 2009??11??7-8?? [????] ?????????????????????????????????????????????????????????????????????????????????????????????? ??????2600??/???????????????????????????????????????? ???????????????????????????????????????????????? ============================================================================== ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ???????????????????????????????????????????? =============================================================================== ??????????????????????????????????????????????????,??????????????????????????????,???????????????????? ????????.),????????(PMC)????????????????????????????????????.???????????????????????????????????????? ????????????????????????????????????????????????????????????????.???????????????????????????????????? ??????:????????????????????????????????????(??????????????????????)????????????????????????,?????????? ???????????X???????????? ================================================================================ ????????????60/40??????????(????60%,????40%)??????????/??????????????????/???????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????,??????????????????.???? ??????????????????,????????????. ??????????????????????????????????????????????????/?????????????????? ?????????????????????????????????? ================================================================================= ????????????????????????,??????????????????+??????????????????+?????????? ?????????? ????????????MBA,??????????????????????????????????????(AMA)????????????????????????/???????? /????????/????????EMBA????????????????..?????r?????A???s?@????2004/2005/2006?????????????????????????? ????????????????????????????????????????.??????????????????????????????,????????????????????/?????????? ??. ????????????????????????????????????????/??????4524??????????(??2006??)???????????????????????????? ????????????.??????????????????????????????/?????????????????????????????????r?????A?????????????????? ??2004/2005/2006????????????????????????????/?????????F??????????????(????/JIT-????/????????/??????. ????????????????,????????????????,??????????????,??????????????????????,????????????,?????????????????? ??????????????????.????????????????????????????????????????????????????????????????????. ??????????????????????????????????????,????????????????????????????????????????????????/????????????.?? ????????????????????????????????????????????????????????????????????????????.????????.??????????.?????? ????????.??????????????????/??????????.??????(MULTEK)/ ??????????Jabil??.?????????????????????????????? ???????????????? ?????????F.?????????? ============================================================================== ???????? ?????? ?N??????/???b????/???????????????????? ??.???b????/??????????????????---?????????????????? ??.???b????/???????????????????? ?? ?????????????????b/???????????????? ??.???b????/????????????????----??????????????????????/????????--???? 4 .??????????????????????????- ?? ????????????VS??????????VS???????????????? ?? ????????????????/????????/??????????????????/?????????????? ?? ????????????????????????????????(????)-----?????????????? ?? ????????????/?????????????????????????????????? 5.?????????????????????????????????????????? ?? ?N???????????D?D?????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? 6.???????????????????????????D?D????????????????????????(push)????????????????????(pull)???????????? ?? ?????????????I?????Y??.??????????Schneider?????????????????? ?? ????????????????????????????????-----????????????/????/???????? ?? ?????????????????????????????????????????? ?? ???????????????????????????????????? ?????? ????????????----??????/???????????????????? 1.??????????????????????---????/?????????????????????? ?? ??????????????????????????????????????- ?? ???????????????????????????????????????? ?? ??????????????????????????????????????????/???????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ?????????????I?????????????????????????????????????????????????????????????????? ?? ???????????????I?????Y??????????ultek???b???????????????????? ?? ??????(????????)ERP??SAP/R3?????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ?????????????I???????I??????(push)???????????????? ?? ??????????????????????????(pull)????????????????????????????????- ?? ????????????????????????------?????????????????????? ?? ????????????????????????????/???????????????????????? ?? ??????????????????????????/????????????????????/????????????????????/???????????????????????????? ?? ????????????????????????????????????/????????/??????????????????/?????????????????????????????? 2.???b????????????(????)????---?????????????? ?? ??????/??????????????(JIT)???????????????????? ?? ??????????????(JIT)???????????????????? ?? ??????????BOSCH?????????????????????????????????????????? ?? ??????????BOSCH???????????????????????????????????????????? ?? ?????????????I???????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ??????????????????????????(JIT)?????????? ?? ???????????????????????? ?? ????????IE???????????????????????????? ?? ?????????????????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ??????????????---?????????????????????? ?? ???????????????????????????????? ?? ????PE/IE?????????????? ?? ??????????/????????????????---?????? ------?????????????????????????? ?????? ???????????????? 1.???????????????? ?? ?????????????????????????????????????????????? ?? ???????????????????????????????????????????????????? 2.??/???????????????????????????????????? ?? ???????????????????????????????????????? ?? ???????????????????????????????????????? 3.?????????????????????? 4.??????????????????????---????????/???????????? ?? ??????????????2007/04???????????????????????? ?? ??????????????????-----?????????????????? ?? ??????????????????------?????????? 5.??????????????????????????????---- ?? ??/??????????????????????????????????--????????????????????/???????????????????????????? ?? ?????????????????? 6.???????????????? 7. ????????????????????------????/????/???? ?? ???????????????????? ?? ??????????????????????????????????????????---?????????????? ?? ????????LED????????????????????????????---???????? 8. ????????????????????????--???????????????????????? 9. ??????????????????--???????????????????????? 10.????????????????????????????/????????????????????????--------???????? 11.????????????????????????????????/???C????????????--------???????? ????????????????????????????????-----??????(OEM)/??????(ODM) 1.??????????????????????----??????????????????(??????????????????) ?? ??????????????????MRP??????????(????)???????? ?? ??????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????????? ?? ????????????????????????(????????)ERP??SAP/R3???????????????????????????????????? ?? ??????????????????ERP-???????????????????????????????????? ?? ???????????Y?????????????????????????? ?? ???????????????I?????Y?????????????????????????D?D???????? ?? ?????????????????I???IERP-ORACLE????????????/?????????????????? ??.???????????????????????? ?? ?????????????? ????????????????--?D?D?????????Y?????????????????????????? ?? ??????????????????????????/?????????Y???????????????????? ?? ??????????????????????/????????????????--?????????????? ?? ????/TTi/??????????????/????????????????????/???????????????? 3.????????????????(????)???????? ?? ????????---???????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ??????????????????????????????/?????????????? ?? ??????????????????????????????????????????????????????-- ?? ??????????????/?????? ?? ?????????????????????? ?? ???????????????????????????????????? ?? ??????????BOSCH????????????????????????/???????????? ?? ABB/AREVA???????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????? ?? ??????????????????????????/????/?????????????????????????? ?? ??????JIT???????????????? ?? ????????????????????????????????????Milk-Run?????????? ?? ??????????JIT??????---????????????????????/????/????/???? ?? ???????????????????????????????????????????? ?? ????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????? ?? ????????????????VMI??----???????????????????????? ?? ??????????VMI?????????? ?? ??????????????(????)??????????VMI?????????????????? ?? ????????????????????????VMI ???????????????????? ?? ??????????????????????--????????????????/???????????? ?? ?????????????????? ?? ???????????????????????????????????????????????????? ?? ??????????ERP-ORACLE????SCP?????????????????????? ?? ????????????????????????????????????(EDI)???????? 4.???????? ?? ???????????????????? ?? ?????????????????? ?? ????????????????????????????????????????????????????????????????????----?????????????? ?? -????????????????????MTO /ROP ????????/??????????MOQ???????????????? ?? ???????????????????????????????????????????????????????? ?? ???????????????????????????????????????????? ?? ??????????????????????????????/??????/?????????? ?? ????/?????????????????????????????? ?? ?????????????????????????????? 5.?????????????????????????????? ?? ????:?????????????????? ?? ????/????????,??????????????????????????????- ?? ????????????????--????????/????????/???????? ?? ????/?????????????? ------------------------------------------------------------------------------- ??PMC??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ???? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From roland at redhat.com Fri Oct 16 19:57:33 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 16 Oct 2009 12:57:33 -0700 (PDT) Subject: Stopped detach/attach status In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 10:58:10 +0200 <20091016085810.GB6539@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> <20091012121237.GA25684@redhat.com> <20091016011803.54D6A16D7@magilla.sf.frob.com> <20091016085810.GB6539@redhat.com> Message-ID: <20091016195733.5BE0C1706@magilla.sf.frob.com> > My point was, the discussed problems with ptrace && stop probably are > not ptrace-only, we need other changes. Hopefully we should address > them after v1. Sure. > But I'd prefer to delay this discussion unless you think we should > fix this right now. I'm glad to stop thinking about it for a while. (Let's just not forget for another year.) > I mean, I just can't think about this until we solve all known > problems in utrace-ptrace. When I am trying to think about 2 different > problems at the same time, I can't make any progress ;) I understand the problem. (I do four or five at once and like to think I make marginal progress on one, but that is my famous optimism.) > I dunno. I am not arguing, just I don't know. But, stopped-attach-transparency > seem to check this. I am not sure, but > "Excessive waiting SIGSTOP after it was already waited for\n" looks like it > it does. I'll re-check. I don't know for sure either. I'm just speculating. Thanks, Roland From roland at redhat.com Fri Oct 16 20:01:07 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 16 Oct 2009 13:01:07 -0700 (PDT) Subject: [PATCH 90] ptrace_wake_up: add "bool force_wakeup" argument for implicit detach In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 11:26:22 +0200 <20091016092622.GC6539@redhat.com> References: <20091014182909.GA11819@redhat.com> <20091016030918.802FE16ED@magilla.sf.frob.com> <20091016092622.GC6539@redhat.com> Message-ID: <20091016200107.CF1201706@magilla.sf.frob.com> > No, send_sig_info() is called under "if (sig)", but I guess I misunderstood > you. [...] > if (sig) { > ... change if needed ... > } I somehow failed to see that all that was inside this test. > You or Jan have alredy mentioned this testsuite... is it gdb-6.8/sim/testsuite/ > which I see in gdb-6.8.tar.gz or something else? gdb/testsuite, which is 'make check-gdb' from the top level of the build or 'make check' in gdb/. Thanks, Roland From roland at redhat.com Fri Oct 16 20:01:50 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 16 Oct 2009 13:01:50 -0700 (PDT) Subject: [PATCH 93] ptrace_report_exit: fix WARN_ON() condition In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 11:34:27 +0200 <20091016093427.GD6539@redhat.com> References: <20091015195354.GA4012@redhat.com> <20091016031745.1F3B816D7@magilla.sf.frob.com> <20091016093427.GD6539@redhat.com> Message-ID: <20091016200150.6C4A51706@magilla.sf.frob.com> > > IMHO the truly desireable behavior is to distinguish real SIGKILL (userland > > kill, oom_kill) from "normal" group-exit. > > Yes. We already discussed this and I agree. I _think_ it is not hard to > implement, but (again) I'd suggest to do this later. Agreed. (I think I just said that this is not for now.) Thanks, Roland From news at maisservicos.com Sat Oct 17 07:41:37 2009 From: news at maisservicos.com (ESINE) Date: Sat, 17 Oct 2009 08:41:37 +0100 Subject: Aprenda ingl =?iso-8859-1?q?=EA?= s a partir! Message-ID: <200910170741.n9H7faKu015976@mx1.redhat.com> a melhor institui??o mundial de ensino Aprenda ingl?s a partir de sua casa com o curso NEW BBC ENGLISHMultimedia System m?todo desenvolvido pela 60 milh?es de alunos em 17 pa?ses 77 anos de experi?ncia 87% de efic?cia nos exames da Universidade de Cambridge Aproveite ascondi??es especiais de financiamento! INSCREVA-SE J?! NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sat Oct 17 18:14:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:14:46 +0200 Subject: [PATCH 95-99] finish ptrace && clone bits Message-ID: <20091017181446.GA25200@redhat.com> ptrace.c | 50 +++++++++++++++++++++++++------------------------- 1 file changed, 25 insertions(+), 25 deletions(-) This! nearly! killed! me! I spent the WHOLE DAY doing this... Good luck to anybody who want to review this code ;) It is simple, but the rationality is not understandable without reading the old implementatoion. TODO: cleanup PTRACE_EVENT_VFORK_DONE checks in ptrace_report_clone(). Oleg. From oleg at redhat.com Sat Oct 17 18:14:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:14:49 +0200 Subject: [PATCH 95] pretend PTRACE_O_TRACEVFORKDONE doesn't exist Message-ID: <20091017181449.GA25208@redhat.com> I'd with very much it were true. Kill VFORKDONE code. It doesn't rellay work just fools the poor tests. --- kernel/ptrace.c | 7 ------- 1 file changed, 7 deletions(-) --- PU/kernel/ptrace.c~95_KILL_VFORK_DONE 2009-10-17 16:00:40.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-17 16:15:58.000000000 +0200 @@ -226,12 +226,6 @@ static u32 ptrace_report_clone(enum utra context->eventmsg = child->pid; ret = UTRACE_STOP; - } else if ((clone_flags & CLONE_VFORK) && - (context->options & PTRACE_O_TRACEVFORKDONE)) { - set_stop_code(context, PTRACE_EVENT_VFORK_DONE); - context->eventmsg = child->pid; - - ret = UTRACE_STOP; } return ret; @@ -1001,7 +995,6 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; From oleg at redhat.com Sat Oct 17 18:14:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:14:52 +0200 Subject: [PATCH 96] ptrace_report_clone: uglify CLONE_PTRACE/CLONE_UNTRACED behaviour to match upstream Message-ID: <20091017181452.GA25211@redhat.com> ptrace_report_clone: /* * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. */ if (event || (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); Yes, but even CLONE_UNTRACED must not suppress the auto-attach, we should check it later. To simplify the review: static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, unsigned long clone_flags, struct task_struct *child) { struct ptrace_context *context = ptrace_context(engine); int event = 0; WARN_ON(ptrace_event_pending(context)); if (clone_flags & CLONE_VFORK) { if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { if (context->options & PTRACE_O_TRACECLONE) event = PTRACE_EVENT_CLONE; } else if (context->options & PTRACE_O_TRACEFORK) { event = PTRACE_EVENT_FORK; } /* * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. */ if (event || (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); if (!event || (clone_flags & CLONE_UNTRACED)) return UTRACE_RESUME; set_stop_code(context, event); context->eventmsg = child->pid; return UTRACE_STOP; } Also, kill the fast-path check in ptrace_clone_attach(), it doesn't make much sense since we know that parent (== current) was ptraced at least when tracehook_report_clone() was called. HOWEVER!!! man 2 clone: CLONE_PTRACE If CLONE_PTRACE is specified, and the calling process is being traced, then trace the child also (see ptrace(2)). OK, CLONE_UNTRACED (since Linux 2.5.46) If CLONE_UNTRACED is specified, then a tracing process cannot force CLONE_PTRACE on this child process. ??? --- kernel/ptrace.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) --- PU/kernel/ptrace.c~96_FIX_CLONE_PTRACE 2009-10-17 16:15:58.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-17 17:28:10.000000000 +0200 @@ -163,8 +163,6 @@ static void ptrace_clone_attach(struct t struct task_struct *tracer; bool abort = true; - if (!parent->ptrace) - return; if (unlikely(ptrace_attach_task(child, options))) { WARN_ON(1); return; @@ -194,15 +192,10 @@ static u32 ptrace_report_clone(enum utra struct task_struct *child) { struct ptrace_context *context = ptrace_context(engine); - int event, ret = UTRACE_RESUME; + int event = 0; WARN_ON(ptrace_event_pending(context)); - // XXX: WRONG!!! - if (clone_flags & CLONE_UNTRACED) - return ret; - - event = 0; if (clone_flags & CLONE_VFORK) { if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; @@ -212,7 +205,6 @@ static u32 ptrace_report_clone(enum utra } else if (context->options & PTRACE_O_TRACEFORK) { event = PTRACE_EVENT_FORK; } - /* * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. @@ -220,15 +212,13 @@ static u32 ptrace_report_clone(enum utra if (event || (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); - // XXX: child->pid is wrong! use tracer's pid_ns - if (event) { - set_stop_code(context, event); - context->eventmsg = child->pid; + if (!event || (clone_flags & CLONE_UNTRACED)) + return UTRACE_RESUME; - ret = UTRACE_STOP; - } + set_stop_code(context, event); + context->eventmsg = child->pid; - return ret; + return UTRACE_STOP; } static inline void set_syscall_code(struct ptrace_context *context, int event) From oleg at redhat.com Sat Oct 17 18:14:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:14:57 +0200 Subject: [PATCH 97] ptrace_report_clone: uglify even more to handle TRACEVFORKDONE without TRACEVFORK Message-ID: <20091017181457.GA25218@redhat.com> If the tracer sets PTRACE_O_TRACEVFORKDONE but not PTRACE_O_TRACEVFORK, clone(CLONE_VFORK) should be reported too, so in this case event must be PTRACE_EVENT_VFORK_DONE. But we can't return UTRACE_STOP. Since CLONE_VFORK is set, utrace will actually stop the tracee in tracehook_report_clone_complete() path, this is not we want. We return UTRACE_RESUME which ensures ->report_quiesce() will notice ptrace_event_pending() and return UTRACE_STOP later, before return to user-mode. Small problem. PTRACE_O_TRACEVFORKDONE doesn't imply auto-attach, so we have to check it before ptrace_clone_attach(). TODO: cleanup this !!! As expected, this fixes tests/o_tracevforkdone again but the code is still wrong. --- kernel/ptrace.c | 9 +++++++-- 1 file changed, 7 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~97_CLONE_VFORKDONE 2009-10-17 17:28:10.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-17 19:37:45.000000000 +0200 @@ -199,6 +199,8 @@ static u32 ptrace_report_clone(enum utra if (clone_flags & CLONE_VFORK) { if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; + else if (context->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { if (context->options & PTRACE_O_TRACECLONE) event = PTRACE_EVENT_CLONE; @@ -209,7 +211,7 @@ static u32 ptrace_report_clone(enum utra * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. */ - if (event || (clone_flags & CLONE_PTRACE)) + if ((event && event != PTRACE_EVENT_VFORK_DONE) || (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); if (!event || (clone_flags & CLONE_UNTRACED)) @@ -218,7 +220,10 @@ static u32 ptrace_report_clone(enum utra set_stop_code(context, event); context->eventmsg = child->pid; - return UTRACE_STOP; + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; } static inline void set_syscall_code(struct ptrace_context *context, int event) From oleg at redhat.com Sat Oct 17 18:15:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:15:00 +0200 Subject: [PATCH 98] fix PTRACE_SYSCALL after PTRACE_EVENT_VFORK_DONE stop Message-ID: <20091017181500.GA25225@redhat.com> This is simple. Now that we report PTRACE_EVENT_VFORK_DONE we should check it to handle PTRACE_SYSCALL/SINGLESTEP before return to user-mode. --- kernel/ptrace.c | 2 ++ 1 file changed, 2 insertions(+) --- PU/kernel/ptrace.c~98_VFORKDONE_THEN_SYSCALL 2009-10-17 19:37:45.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-17 19:46:42.000000000 +0200 @@ -990,6 +990,7 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; @@ -1001,6 +1002,7 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: case PTRACE_EVENT_SYSCALL_EXIT: read_lock(&tasklist_lock); if (tracee->sighand) From oleg at redhat.com Sat Oct 17 18:15:04 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 17 Oct 2009 20:15:04 +0200 Subject: [PATCH 99] uglify the code again to report VFORK_DONE after VFORK Message-ID: <20091017181504.GA25228@redhat.com> If the tracee sets PTRACE_O_TRACEVFORK and the tracee does vfork(), the tracee stops inside do_fork() and reports PTRACE_EVENT_VFORK. If we need to report PTRACE_EVENT_VFORK_DONE after that, ptrace_resume() can use ptrace_wake_up() or just report the stacked event. We need to wake up the tracee, it should pass wait_for_completion() and then stop and report before return to user-mode. So. change ptrace_resume() to do set_stop_code() + utrace_control(REPORT) like ptrace_report_clone() does, we rely on ->report_quiesce() which must notice ptrace_event_pending() and return UTRACE_STOP. And inow we pass this test: #include #include #include #include #include #include #include #include #define WEVENT(s) ((s & 0xFF0000) >> 16) static unsigned long __step(int line, int pid, int o, int e) { int stat, cont = PTRACE_CONT; unsigned long msg; if (o == PTRACE_SYSCALL) { cont = o; } else if (o) { assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, o)); } assert(0 == ptrace(cont, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); // assert(WIFSTOPPED(stat)); // assert(WSTOPSIG(stat) == SIGTRAP); if (!WIFSTOPPED(stat) || WSTOPSIG(stat) != SIGTRAP) { printf("ERR!! %3d: %06X\n", line, stat); exit(1); } assert(WEVENT(stat) == e); assert(0 == ptrace(PTRACE_GETEVENTMSG, pid, 0, &msg)); return msg; } #define step(pid, o, e) __step(__LINE__, pid, o, e) #define T_FORK_A 0x01 #define T_FORK_Z 0x02 #define T_SYSCALL 0x04 #define T_SIGNAL 0x08 #define T_ALL (T_FORK_A | T_FORK_Z | T_SYSCALL | T_SIGNAL) static void p_todo(int todo) { printf("todo: "); #define P(n) if (todo & n) printf(#n " ") P(T_FORK_A); P(T_FORK_Z); P(T_SYSCALL); P(T_SIGNAL); #undef P if (todo & ~T_ALL) printf("ERR!!!"); printf("\n"); } static void tst(int todo) { int pid, cpid=-1, stat; long msg; p_todo(todo); pid = fork(); if (!pid) { int vp; if (!(todo & T_SIGNAL)) signal(SIGCHLD, SIG_IGN); assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); vp = vfork(); exit(0x43); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); if (todo & T_SYSCALL) { msg = step(pid, PTRACE_SYSCALL, 0); assert(msg == 0); } if (todo & T_FORK_A) { cpid = step(pid, PTRACE_O_TRACEVFORK, PTRACE_EVENT_VFORK); assert(waitpid(cpid, &stat, __WALL) == cpid); assert(WIFSTOPPED(stat)); assert(WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_CONT, cpid, 0, 0)); assert(waitpid(cpid, &stat, __WALL) == cpid); assert(WIFEXITED(stat)); } if (todo & T_FORK_Z) { msg = step(pid, PTRACE_O_TRACEVFORKDONE, PTRACE_EVENT_VFORK_DONE); if (todo & T_FORK_A) assert(msg == cpid); } if (todo & T_SIGNAL) { assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); if (!(todo & T_FORK_A) && stat == 0x4300) goto parent_exited_first; assert(WIFSTOPPED(stat)); assert(WSTOPSIG(stat) == SIGCHLD); } if (todo & T_SYSCALL) { msg = step(pid, PTRACE_SYSCALL, 0); if (todo & T_FORK_A) assert(msg == cpid); } assert(0 == ptrace(PTRACE_CONT, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); assert(WIFEXITED(stat)); parent_exited_first: assert(waitpid(-1, &stat, __WALL) == -1); assert(errno == ECHILD); } int main(int argc, char* argv[]) { int todo; if (argc > 1) { todo = atoi(argv[1]); tst(todo); } else { int todo; for (todo = 0; todo <= T_ALL; ++todo) tst(todo); } return 0; } --- kernel/ptrace.c | 10 ++++++++++ 1 file changed, 10 insertions(+) --- PU/kernel/ptrace.c~99_VFORK_THEN_VFORKDONE 2009-10-17 19:46:42.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-17 19:50:54.000000000 +0200 @@ -975,11 +975,21 @@ static void do_ptrace_resume(struct utra case 0: // XXX: JCTL stop break; + + case PTRACE_EVENT_VFORK: + if (context->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(context, PTRACE_EVENT_VFORK_DONE); + utrace_control(tracee, engine, UTRACE_REPORT); + return; + } + break; + case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); break; + case PTRACE_EVENT_SIGNAL: context->signr = data; break; From annafaith55 at gmail.com Sat Oct 17 18:26:34 2009 From: annafaith55 at gmail.com (=?iso-8859-1?Q?Anna_Faith_White?=) Date: Sat, 17 Oct 2009 13:26:34 -0500 Subject: This is a Great Site Message-ID: <200910171826.n9HIQauK009485@mx1.redhat.com> Would you like to earn an extra Earn $200 - $500 Every Day? for just 45 minutes work? Data Entry Workers Needed Worldwide! FOR MORE INFO PLEASE GO TO: http://vur.me/annafaith55/Global_Data_Entry_here/ I would personally like to invite you to become part of our team doing work-at-home data entry. We have guided thousands of team members to success using our new type of data-entry job called Global Data Entry. Some members are currently making $300 - $2000 and more per day, we have been dealing with online data entry for over 7 years. Once you become a via member, you will have exclusive access to legitimate data entry opportunities life time. Forms are just 1-3 pages and take only a few minutes to complete You will be in control and they will pay you directly via direct deposit, paypal or check. Earnings are paid every 2 weeks. Once you have signed up with our via team member, we will provide you with complete guidance and tutorials on exactly how to do these different job tasks and to make this work for you, especially the downloadables files of GLOBAL DATA ENTRY to send you in your email account. It is possible to quit your job for the first used 3 days, how much more if you work hardly 8 hours a day. This is what you have been waiting for! don't hesitate to grab this big opportunities, just try it and I can guarantee you 100% you'll enjoy it. Anna Faith White Home-Data Entry Affiliate Marketer annafaith55 at gmail.com FOR MORE INFO PLEASE GO TO: http://vur.me/annafaith55/Global_Data_Entry_here/ God Bless from a very satisfied member one time only registration fee because we only want serious job If we allowed for free we would have "curiosity" applicants filling applications that were not really serious This is a one time adv. email only and you won't received further mailings about this. If you would like to opt-out just send an e-mail with "Opt Out in the subject line to the address From sender at netpromouter.net Fri Oct 16 16:27:41 2009 From: sender at netpromouter.net (Johnnie Walker) Date: Fri, 16 Oct 2009 20:27:41 +0400 Subject: =?utf-8?q?Oferecemos_um_Private_Tasting_na_sua_pr=C3=B3pria_casa?= Message-ID: <382d16d8c84c09e08532c2aa2888e8c4@netpromouter.net> Johnnie Walker apresenta o melhor programa para a sua semana, Um Private Tasting, na sua pr?pria casa. Convide os seus amigos e seja anfitri?o desta experi?ncia memor?vel Siga este link: http://netpromouter.net/iem/link.php?M=21794&N=3&L=8&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sun Oct 18 18:13:59 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 18 Oct 2009 20:13:59 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification Message-ID: <20091018181359.GA30753@redhat.com> Cleanups. Tomorrow: PTRACE_SYSEMU/PTRACE_SYSEMU_SINGLESTEP > The semantics is that the entry report always does like > UTRACE_SYSCALL_ABORT to skip the actual call, and then > there is no exit report. Thanks! this is easy. What about PTRACE_SYSEMU_SINGLESTEP ? I will read the code tomorrow, but it is easy to miss some detail and we don't have any test-cases. Looks like, PTRACE_SYSEMU_SINGLESTEP is PTRACE_SINGLESTEP plus: if we enter syscall we should - return UTRACE_SYSCALL_ABORT - avoid SYSCALL_EXIT report like PTRACE_SYSEMU - avoid the unnecessary send_sigtrap() in syscall_trace_leave() somehow, but the exact semantics is not clear to me... since utrace doesn't actually stops in tracehook_report_syscall_exit(), we shouldn't worry? Hmm, except the tracee stops in SYSCALL_ENTRY, I guess... Could you clarify? In particular. The tracee stops in SYSCALL_ENTRY, the tracer does PTRACE_SYSEMU_SINGLESTEP. We should just do enable_step() and clear UTRACE_EVENT(SYSCALL_EXIT), correct? Oleg. From oleg at redhat.com Sun Oct 18 18:14:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 18 Oct 2009 20:14:01 +0200 Subject: [PATCH 100] do_ptrace_resume: consolidate multiple switch stmts Message-ID: <20091018181401.GA30757@redhat.com> Consolidate multiple switch statements in do_ptrace_resume(). No functional changes, except in PTRACE_EVENT_SYSCALL_EXIT case ptrace(SINGLESTEP, signr)->ptrace_resume() first does send_sigtrap() then send_sig_info(signr). Hopefully this is OK, and we should move this sigtrap logic into the tracee's context anyway. To simplify the review: static void do_ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, enum utrace_resume_action action, long request, long data) { struct ptrace_context *context = ptrace_context(engine); switch (get_stop_event(context)) { case PTRACE_EVENT_VFORK: if (context->options & PTRACE_O_TRACEVFORKDONE) { set_stop_code(context, PTRACE_EVENT_VFORK_DONE); utrace_control(tracee, engine, UTRACE_REPORT); return; } break; case PTRACE_EVENT_EXEC: case PTRACE_EVENT_FORK: case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: if (request == PTRACE_SYSCALL) { set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } /* fallthrough, but suppress send_sig_info() below */ data = 0; case PTRACE_EVENT_SYSCALL_EXIT: if (action != UTRACE_RESUME) { read_lock(&tasklist_lock); if (tracee->sighand) send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); read_unlock(&tasklist_lock); action = UTRACE_RESUME; } /* fallthrough */ case PTRACE_EVENT_SYSCALL_ENTRY: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); break; case PTRACE_EVENT_SIGNAL: context->signr = data; break; case 0: // XXX: JCTL stop break; } context->resume = action; ptrace_wake_up(tracee, engine, action, true); } --- kernel/ptrace.c | 53 +++++++++++++++++++++++------------------------------ 1 file changed, 23 insertions(+), 30 deletions(-) --- PU/kernel/ptrace.c~100_RESUME_CONSOLIDATE_SWITCH 2009-10-17 19:50:54.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-18 16:51:38.000000000 +0200 @@ -972,10 +972,6 @@ static void do_ptrace_resume(struct utra struct ptrace_context *context = ptrace_context(engine); switch (get_stop_event(context)) { - case 0: - // XXX: JCTL stop - break; - case PTRACE_EVENT_VFORK: if (context->options & PTRACE_O_TRACEVFORKDONE) { set_stop_code(context, PTRACE_EVENT_VFORK_DONE); @@ -984,45 +980,41 @@ static void do_ptrace_resume(struct utra } break; - case PTRACE_EVENT_SYSCALL_ENTRY: - case PTRACE_EVENT_SYSCALL_EXIT: - if (data) - send_sig_info(data, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - context->signr = data; - break; - } - - if (request == PTRACE_SYSCALL) { - switch (get_stop_event(context)) { - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); do_ptrace_notify_stop(context, tracee); return; } - } + /* fallthrough, but suppress send_sig_info() below */ + data = 0; - if (action != UTRACE_RESUME) { - switch (get_stop_event(context)) { - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: - case PTRACE_EVENT_SYSCALL_EXIT: + case PTRACE_EVENT_SYSCALL_EXIT: + if (action != UTRACE_RESUME) { read_lock(&tasklist_lock); if (tracee->sighand) send_sigtrap(tracee, task_pt_regs(tracee), 0, TRAP_BRKPT); read_unlock(&tasklist_lock); - action = UTRACE_RESUME; - break; } + /* fallthrough */ + + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + context->signr = data; + break; + + case 0: + // XXX: JCTL stop + break; } context->resume = action; From oleg at redhat.com Sun Oct 18 18:14:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 18 Oct 2009 20:14:03 +0200 Subject: [PATCH 101] do_ptrace_resume: always use ptrace_wake_up() Message-ID: <20091018181403.GA30760@redhat.com> do_ptrace_resume(PTRACE_EVENT_VFORK) can't use ptrace_wake_up() because it clears context->stop_code. Not good, we should follow the "force_wakeup" logic, and it is always good to consolidate the calls to utrace layer. Change ptrace_wake_up() to check "action != UTRACE_REPORT" and change do_ptrace_resume() to rely on ptrace_wake_up(). --- kernel/ptrace.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- PU/kernel/ptrace.c~101_RESUME_ALWAYS_USE_WAKEUP 2009-10-18 16:51:38.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-18 18:34:55.000000000 +0200 @@ -960,7 +960,8 @@ static void ptrace_wake_up(struct task_s } } - ptrace_context(engine)->stop_code = 0; + if (action != UTRACE_REPORT) + ptrace_context(engine)->stop_code = 0; utrace_control(tracee, engine, action); } @@ -975,8 +976,7 @@ static void do_ptrace_resume(struct utra case PTRACE_EVENT_VFORK: if (context->options & PTRACE_O_TRACEVFORKDONE) { set_stop_code(context, PTRACE_EVENT_VFORK_DONE); - utrace_control(tracee, engine, UTRACE_REPORT); - return; + action = UTRACE_REPORT; } break; From oleg at redhat.com Sun Oct 18 18:14:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 18 Oct 2009 20:14:06 +0200 Subject: [PATCH 102] ptrace_resume: rewrite request processing Message-ID: <20091018181406.GA30767@redhat.com> Subjective of course, but imho makes the code more readable. No functional changes (I hope), PTRACE_SYSEMU/PTRACE_SYSEMU_SINGLESTEP logic still waits for implementation. Rewrite the code to use switch(request) instead of multiple "if" checks. This also consolidates some ifdef's and kills is_xxx(request). Also, factor our utrace_set_events() calls. static int ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, long request, long data) { enum utrace_resume_action action; enum utrace_syscall_action syscall; unsigned long events; if (!valid_signal(data)) return -EIO; syscall = UTRACE_SYSCALL_RUN; events = engine->flags & ~UTRACE_EVENT_SYSCALL; action = UTRACE_RESUME; switch (request) { #ifdef PTRACE_SINGLEBLOCK case PTRACE_SINGLEBLOCK: if (unlikely(!arch_has_block_step())) return -EIO; action = UTRACE_BLOCKSTEP; break; #endif #ifdef PTRACE_SINGLESTEP case PTRACE_SINGLESTEP: if (unlikely(!arch_has_single_step())) return -EIO; action = UTRACE_SINGLESTEP; break; #endif #ifdef PTRACE_SYSEMU case PTRACE_SYSEMU_SINGLESTEP: if (unlikely(!arch_has_single_step())) return -EIO; action = UTRACE_SINGLESTEP; case PTRACE_SYSEMU: syscall = UTRACE_SYSCALL_ABORT; /* fallthrough */ #endif case PTRACE_SYSCALL: events |= UTRACE_EVENT_SYSCALL; break; } if (events != engine->flags && utrace_set_events(tracee, engine, events)) return -ESRCH; do_ptrace_resume(engine, tracee, action, request, data); return 0; } --- kernel/ptrace.c | 78 +++++++++++++++++++++++++------------------------------- 1 file changed, 35 insertions(+), 43 deletions(-) --- PU/kernel/ptrace.c~102_RESUME_CLEANUP_REQUEST_PROCESSING 2009-10-18 18:34:55.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-18 18:35:30.000000000 +0200 @@ -882,24 +882,6 @@ static int ptrace_rw_siginfo(struct task } } -#ifdef PTRACE_SINGLESTEP -#define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) -#else -#define is_singlestep(request) 0 -#endif - -#ifdef PTRACE_SINGLEBLOCK -#define is_singleblock(request) ((request) == PTRACE_SINGLEBLOCK) -#else -#define is_singleblock(request) 0 -#endif - -#ifdef PTRACE_SYSEMU -#define is_sysemu_singlestep(request) ((request) == PTRACE_SYSEMU_SINGLESTEP) -#else -#define is_sysemu_singlestep(request) 0 -#endif - static void do_ptrace_notify_stop(struct ptrace_context *context, struct task_struct *tracee) { @@ -1022,47 +1004,57 @@ static void do_ptrace_resume(struct utra } static int ptrace_resume(struct utrace_engine *engine, - struct task_struct *child, long request, long data) + struct task_struct *tracee, long request, long data) { enum utrace_resume_action action; enum utrace_syscall_action syscall; - int ret = 0; + unsigned long events; if (!valid_signal(data)) return -EIO; syscall = UTRACE_SYSCALL_RUN; -#ifdef PTRACE_SYSEMU - if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) - syscall = UTRACE_SYSCALL_ABORT; -#endif - - if (syscall != UTRACE_SYSCALL_RUN || request == PTRACE_SYSCALL) { - if (!(engine->flags & UTRACE_EVENT_SYSCALL) && - utrace_set_events(child, engine, - engine->flags | UTRACE_EVENT_SYSCALL)) - ret = -ESRCH; - } else if (engine->flags & UTRACE_EVENT(SYSCALL_ENTRY)) { - if (utrace_set_events(child, engine, - engine->flags & ~UTRACE_EVENT_SYSCALL)) - ret = -ESRCH; - } + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; - action = UTRACE_RESUME; - if (is_singleblock(request)) { + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: if (unlikely(!arch_has_block_step())) - ret = -EIO; + return -EIO; action = UTRACE_BLOCKSTEP; - } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: if (unlikely(!arch_has_single_step())) - ret = -EIO; + return -EIO; action = UTRACE_SINGLESTEP; + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + syscall = UTRACE_SYSCALL_ABORT; + /* fallthrough */ +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; } - if (!ret) - do_ptrace_resume(engine, child, action, request, data); + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; - return ret; + do_ptrace_resume(engine, tracee, action, request, data); + return 0; } int ptrace_request(struct task_struct *child, long request, From oleg at redhat.com Sun Oct 18 18:14:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 18 Oct 2009 20:14:08 +0200 Subject: [PATCH 103] ptrace_report_clone: minor cleanups + comments Message-ID: <20091018181408.GA30770@redhat.com> We can check CLONE_UNTRACED earlier, this makes the code more symmetrical and avoids the subsequent checks. Also, add the comment. I failed to remove the multiple usage of PTRACE_EVENT_VFORK_DONE, whatever I tried doesn't make the code more readable. --- kernel/ptrace.c | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) --- PU/kernel/ptrace.c~103_CLEANUP_REPORT_CLONE 2009-10-18 18:35:30.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-18 19:56:28.000000000 +0200 @@ -196,7 +196,9 @@ static u32 ptrace_report_clone(enum utra WARN_ON(ptrace_event_pending(context)); - if (clone_flags & CLONE_VFORK) { + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { if (context->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; else if (context->options & PTRACE_O_TRACEVFORKDONE) @@ -211,15 +213,19 @@ static u32 ptrace_report_clone(enum utra * Any of these reports implies auto-attaching the new child. * So does CLONE_PTRACE, even with no event to report. */ - if ((event && event != PTRACE_EVENT_VFORK_DONE) || (clone_flags & CLONE_PTRACE)) + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) ptrace_clone_attach(parent, child, context->options); - if (!event || (clone_flags & CLONE_UNTRACED)) + if (!event) return UTRACE_RESUME; set_stop_code(context, event); context->eventmsg = child->pid; - + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ if (event == PTRACE_EVENT_VFORK_DONE) return UTRACE_REPORT; else From jan.kratochvil at redhat.com Sun Oct 18 20:00:11 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sun, 18 Oct 2009 22:00:11 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091016085810.GB6539@redhat.com> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> <20091012121237.GA25684@redhat.com> <20091016011803.54D6A16D7@magilla.sf.frob.com> <20091016085810.GB6539@redhat.com> Message-ID: <20091018200011.GA16617@host0.dyn.jankratochvil.net> On Fri, 16 Oct 2009 10:58:10 +0200, Oleg Nesterov wrote: > On 10/15, Roland McGrath wrote: > > > Say, ptrace(DETACH/CONT, SIGSTOP). This should work, this means > > > SIGNAL_STOP_DEQUEUED should be set even before the tracee calls > > > do_signal_stop(). But otoh it doesn't look right to set this flag > > > each time the tracee sees a stop signal from the debugger (especially > > > on detach), ->real_parent should not see multiple notifications. > > > > I don't think an extra SIGCHLD/wakeup here is going to be considered a > > problem, in the grand scheme of things. I can't really see any plausible > > way we'd (want to) preserve whether the real_parent already thought it was > > stopped or not. > > I dunno. I am not arguing, just I don't know. But, stopped-attach-transparency > seem to check this. I am not sure, but > "Excessive waiting SIGSTOP after it was already waited for\n" looks like it > it does. I'll re-check. "stopped-attach-transparency" is there to fulfill wishes from users that 1. kill -STOP PID 2. gcore PID or gstack PID 3. kill -CONT PID should not affect PID and its interaction (such as PID parent's waitpid) in any way. But as the point 1 and 3 already signal PID's parent some SIGSTOP/SIGCONT events the parent generally does not expect it may not matter much if the point 2 does some more of such unexpected signal reporting to PID's parent. So feel free to break stopped-attach-transparency if it makes sense so. Regards, Jan From thaicounsel at gmail.com Mon Oct 19 13:51:59 2009 From: thaicounsel at gmail.com (kitti law office) Date: Mon, 19 Oct 2009 13:51:59 Subject: =?iso-8859-1?q?LEGAL_SERVICES-=BA=C3=D4=A1=D2=C3=C7=D4=AA=D2=AA?= =?iso-8859-1?q?=D5=BE=A1=AE=CB=C1=D2=C2-=A8=B4=E0=A4=C3=D7=E8=CD?= =?iso-8859-1?q?=A7=CB=C1=D2=C2=A1=D2=C3=A4=E9=D2-=BA=C3=D4=C9=D1?= =?iso-8859-1?q?=B7?= Message-ID: <200910190648.n9J6m9cN032549@mx1.redhat.com> An HTML attachment was scrubbed... URL: From polo5574 at ocompany.com.redhat.com Mon Oct 19 10:22:20 2009 From: polo5574 at ocompany.com.redhat.com (Louie Howard) Date: Mon, 19 Oct 2009 10:22:20 -0000 Subject: If good health is what you really need. Message-ID: <001b01ca509d$a88b27e0$8c5b7b88@bc0217jcg> Enjoy feeling and looking in good shape. http://anvui.qwiquxipijy.com/ From oleg at redhat.com Mon Oct 19 15:46:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 19 Oct 2009 17:46:05 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: <20091018181359.GA30753@redhat.com> References: <20091018181359.GA30753@redhat.com> Message-ID: <20091019154605.GA21242@redhat.com> On 10/18, Oleg Nesterov wrote: > > > The semantics is that the entry report always does like > > UTRACE_SYSCALL_ABORT to skip the actual call, and then > > there is no exit report. > > Thanks! this is easy. Hmm. This is not what I see in upstream kernel... Afaics, PTRACE_SYSEMU means: - cancel this syscall, and do _not_ report SYSCALL_ENTRY to the tracer - SYSCALL_EXIT should be reported, but send_sigtrap() should be avoied (in case it was SYSEMU_SINGLESTEP). Correct? Oleg. From oleg at redhat.com Mon Oct 19 16:10:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 19 Oct 2009 18:10:23 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: <20091019154605.GA21242@redhat.com> References: <20091018181359.GA30753@redhat.com> <20091019154605.GA21242@redhat.com> Message-ID: <20091019161022.GA23446@redhat.com> On 10/19, Oleg Nesterov wrote: > > On 10/18, Oleg Nesterov wrote: > > > > > The semantics is that the entry report always does like > > > UTRACE_SYSCALL_ABORT to skip the actual call, and then > > > there is no exit report. > > > > Thanks! this is easy. > > Hmm. This is not what I see in upstream kernel... > > Afaics, PTRACE_SYSEMU means: > > - cancel this syscall, and do _not_ report SYSCALL_ENTRY > to the tracer Argh, I missreaf the next check after test_thread_flag(TIF_SYSCALL_EMU) in syscall_trace_enter(), we should report SYSCALL_ENTRY and stop... > - SYSCALL_EXIT should be reported, but send_sigtrap() > should be avoied (in case it was SYSEMU_SINGLESTEP). Correct? Oleg. From oleg at redhat.com Mon Oct 19 16:17:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 19 Oct 2009 18:17:42 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: <20091019161022.GA23446@redhat.com> References: <20091018181359.GA30753@redhat.com> <20091019154605.GA21242@redhat.com> <20091019161022.GA23446@redhat.com> Message-ID: <20091019161742.GA23684@redhat.com> On 10/19, Oleg Nesterov wrote: > > On 10/19, Oleg Nesterov wrote: > > > > On 10/18, Oleg Nesterov wrote: > > > > > > > The semantics is that the entry report always does like > > > > UTRACE_SYSCALL_ABORT to skip the actual call, and then > > > > there is no exit report. > > > > > > Thanks! this is easy. > > > > Hmm. This is not what I see in upstream kernel... > > > > Afaics, PTRACE_SYSEMU means: > > > > - cancel this syscall, and do _not_ report SYSCALL_ENTRY > > to the tracer > > Argh, I missreaf the next check after test_thread_flag(TIF_SYSCALL_EMU) > in syscall_trace_enter(), we should report SYSCALL_ENTRY and stop... > > > - SYSCALL_EXIT should be reported, OMG, now I misread ptrace_resume(). SYSEMU doesn't set TIF_SYSCALL_TRACE, so SYSCALL_EXIT should not be reported. Sorry for noise... So. Looks like the only complication is that we should avoid the unnecessary send_sigtrap() in syscall_trace_leave(), but we shouldn't use TIF_SYSCALL_EMU - it must die. Correct? Oleg. From vendas at mardeb.com.br Mon Oct 19 16:42:48 2009 From: vendas at mardeb.com.br (Piero Jimenez) Date: Mon, 19 Oct 2009 16:42:48 GMT Subject: TINTAS INDUSTRIAIS LACA E ESMALTE SINTETICO Message-ID: <20091019164243.3806A1772E8@mhu18mtaz-tvt-spo.fly.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Oct 19 18:06:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 19 Oct 2009 20:06:57 +0200 Subject: [PATCH 104] PTRACE_SYSEMU support Message-ID: <20091019180657.GA29121@redhat.com> Something like this? This patch: - adds ptrace_context->sysemu boolean. (it will die) - changes ptrace_resume() so that SYSEMU/SYSEMU_SINGLESTEP set context ->sysemu, and require only SYSCALL_ENTRY event, not UTRACE_EVENT_SYSCALL which includes SYSCALL_EXIT as well. Afaics, this should handle PTRACE_SYSEMU correctly. But PTRACE_SYSEMU_SINGLESTEP case is not exactly right, it always sets action = UTRACE_SINGLESTEP. Looks like, it should be UTRACE_RESUME if the tracee has stopped somewhere after SYSCALL_ENTRY was reported. Will continue tomorrow. --- kernel/ptrace.c | 19 ++++++++++++------- 1 file changed, 12 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~104_PTRACE_SYSEMU 2009-10-18 19:56:28.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-19 18:46:50.000000000 +0200 @@ -25,7 +25,9 @@ #include struct ptrace_context { - int options; + int options; + + bool sysemu; // XXX: will die soon int signr; siginfo_t *siginfo; @@ -250,6 +252,8 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + if (unlikely(context->sysemu)) + return UTRACE_SYSCALL_ABORT | UTRACE_STOP; return UTRACE_SYSCALL_RUN | UTRACE_STOP; } @@ -1012,16 +1016,16 @@ static void do_ptrace_resume(struct utra static int ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, long request, long data) { + struct ptrace_context *context = ptrace_context(engine); enum utrace_resume_action action; - enum utrace_syscall_action syscall; unsigned long events; if (!valid_signal(data)) return -EIO; - syscall = UTRACE_SYSCALL_RUN; - events = engine->flags & ~UTRACE_EVENT_SYSCALL; - action = UTRACE_RESUME; + context->sysemu = false; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; switch (request) { #ifdef PTRACE_SINGLEBLOCK @@ -1046,8 +1050,9 @@ static int ptrace_resume(struct utrace_e return -EIO; action = UTRACE_SINGLESTEP; case PTRACE_SYSEMU: - syscall = UTRACE_SYSCALL_ABORT; - /* fallthrough */ + context->sysemu = true; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; #endif case PTRACE_SYSCALL: From oleg at redhat.com Tue Oct 20 08:52:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 10:52:51 +0200 Subject: Stopped detach/attach status In-Reply-To: <20091018200011.GA16617@host0.dyn.jankratochvil.net> References: <20091001201725.GA2947@host0.dyn.jankratochvil.net> <20091005023208.GA23901@redhat.com> <20091008052424.29E15D3@magilla.sf.frob.com> <20091008160658.GA15768@redhat.com> <20091012002924.019E6C8@magilla.sf.frob.com> <20091012121237.GA25684@redhat.com> <20091016011803.54D6A16D7@magilla.sf.frob.com> <20091016085810.GB6539@redhat.com> <20091018200011.GA16617@host0.dyn.jankratochvil.net> Message-ID: <20091020085251.GA4625@redhat.com> On 10/18, Jan Kratochvil wrote: > > On Fri, 16 Oct 2009 10:58:10 +0200, Oleg Nesterov wrote: > > On 10/15, Roland McGrath wrote: > > > > Say, ptrace(DETACH/CONT, SIGSTOP). This should work, this means > > > > SIGNAL_STOP_DEQUEUED should be set even before the tracee calls > > > > do_signal_stop(). But otoh it doesn't look right to set this flag > > > > each time the tracee sees a stop signal from the debugger (especially > > > > on detach), ->real_parent should not see multiple notifications. > > > > > > I don't think an extra SIGCHLD/wakeup here is going to be considered a > > > problem, in the grand scheme of things. I can't really see any plausible > > > way we'd (want to) preserve whether the real_parent already thought it was > > > stopped or not. > > > > I dunno. I am not arguing, just I don't know. But, stopped-attach-transparency > > seem to check this. I am not sure, but > > "Excessive waiting SIGSTOP after it was already waited for\n" looks like it > > it does. I'll re-check. > > "stopped-attach-transparency" is there to fulfill wishes from users that > > 1. kill -STOP PID > 2. gcore PID or gstack PID > 3. kill -CONT PID > > should not affect PID and its interaction (such as PID parent's waitpid) in > any way. > > But as the point 1 and 3 already signal PID's parent some SIGSTOP/SIGCONT > events the parent generally does not expect it may not matter much if the > point 2 does some more of such unexpected signal reporting to PID's parent. > > So feel free to break stopped-attach-transparency if it makes sense so. Thanks a lot Jan. I'll return to this a bit later, and ask you more questions. Oleg. From info at soft-direct.net Wed Oct 21 18:36:38 2009 From: info at soft-direct.net (Celine de Fizeo) Date: Wed, 21 Oct 2009 21:36:38 +0300 Subject: =?utf-8?q?Votre_devis_T=C3=A9l=C3=A9phonie?= Message-ID: <575c54b594f03572fcb7329ee38939f1@om3.market-products.com> An HTML attachment was scrubbed... URL: From info at soft-direct.net Tue Oct 20 11:49:49 2009 From: info at soft-direct.net (BestPub) Date: Tue, 20 Oct 2009 13:49:49 +0200 Subject: Demandez votre catalogue gratuit d objets publicitaires. Message-ID: An HTML attachment was scrubbed... URL: From info at campaigns.canal-marketing.com Tue Oct 20 14:20:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Direction_Hygi=E8ne_France?=) Date: Tue, 20 Oct 2009 16:20:00 +0200 Subject: =?iso-8859-1?q?Prot=E9gez_votre_entreprise_contre_la_grippe_A?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Oct 20 14:43:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 16:43:01 +0200 Subject: [PATCH 105] PTRACE_SYSEMU_SINGLESTEP support Message-ID: <20091020144301.GA16853@redhat.com> PTRACE_SYSEMU_SINGLESTEP works, but we should avoid an extra send_sigtrap() from syscall_trace_leave(). Change the code under "if (->sysemu)" in ptrace_report_syscall_entry() to clear TIF_SINGLESTEP and return "| UTRACE_REPORT" instead of UTRACE_STOP. This way we report PTRACE_EVENT_SYSCALL_ENTRY but the tracee stops later, after syscall_trace_leave() path. Test case: #include #include #include #include #include #include #include #include #include #include #include #define PTRACE_SYSEMU 31 #define PTRACE_SYSEMU_SINGLESTEP 32 #define WEVENT(s) ((s & 0xFF0000) >> 16) static int verbose; #define d_printf(fmt, ...) do { if (verbose) printf(fmt, ##__VA_ARGS__); } while (0) static struct user_regs_struct regs; static void resume(int pid, int req, int ck_stat) { int stat; assert(0 == ptrace(req, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); //printf("===> %06X\n %06X\n", ck_stat, stat); assert(stat == ck_stat); assert(0 == ptrace(PTRACE_GETREGS, pid, NULL, ®s)); } int main(int argc, const char *argv[]) { int pid, stat; long rip; if (getpid() == __NR_getppid) { printf("sorry, restart\n"); return 0; } verbose = argc > 1; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); getppid(); getppid(); getppid(); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD)); //----------------------------------------------------------------------------- d_printf("1: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); rip = regs.rip - 2; //-------------------------------------------------------------------------------- d_printf("2: sysemu\n"); resume(pid, PTRACE_SYSEMU, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); assert(regs.rip == rip + 2); //-------------------------------------------------------------------------------- d_printf("3: stop before syscall insn\n"); do { long cur = regs.rip; resume(pid, PTRACE_SYSEMU_SINGLESTEP, 0x57F); assert(regs.rip != cur); } while (regs.rip != rip); assert(regs.rax == __NR_getppid); d_printf("3: step into syscall\n"); resume(pid, PTRACE_SYSEMU_SINGLESTEP, 0x857F); assert(regs.rip == rip + 2); d_printf("3: step next\n"); resume(pid, PTRACE_SYSEMU_SINGLESTEP, 0x57F); assert(regs.rip != rip + 2); //-------------------------------------------------------------------------------- kill(pid, SIGKILL); return 0; } However, I still do not understand what SYSEMU should really do. Afaics, only uml needs it... I don't see how we can implement the same behaviour without using TIF_SYSCALL_EMU, but perhaps we can ignore the behaviour difference? - The tracer does PTRACE_SYSEMU or PTRACE_SYSEMU_SINGLESTEP, the tracee stops. The tracer does PTRACE_SYSCALL. Should we report SYSCALL_EXIT? This is easy to do. But the next case is nasty, - The tracer does PTRACE_SYSCALL, the tracee reports SYSCALL_ENTER. The tracer does PTRACE_SYSEMU_SINGLESTEP. how we can suppress syscall_trace_leave()->send_sigtrap() without using TIF_SYSCALL_EMU ? Of course, we can. But this needs so nasty complications :/ Can't we ignore this incompatibility? --- kernel/ptrace.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~105_PTRACE_SYSEMU_STEP 2009-10-19 18:46:50.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-20 15:58:19.000000000 +0200 @@ -252,8 +252,11 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); - if (unlikely(context->sysemu)) - return UTRACE_SYSCALL_ABORT | UTRACE_STOP; + if (unlikely(context->sysemu)) { + if (test_thread_flag(TIF_SINGLESTEP)) + user_disable_single_step(task); + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + } return UTRACE_SYSCALL_RUN | UTRACE_STOP; } From oleg at redhat.com Tue Oct 20 16:15:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 18:15:20 +0200 Subject: [PATCH 106-108] kill context->sysemu + cleanups Message-ID: <20091020161520.GA30631@redhat.com> The last 2 patches are purely cosmetic, they just move the code from/to ptrace_resume(). Oleg. From oleg at redhat.com Tue Oct 20 16:15:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 18:15:24 +0200 Subject: [PATCH 106] turn context->sysemu into PTRACE_O_SYSEMU Message-ID: <20091020161524.GA30639@redhat.com> Turn context->sysemu into PTRACE_O_SYSEMU. This flag is not visible to user space, and it has no effect after the tracee was stopped. IOW, PTRACE_SETOPTIONS always clear PTRACE_O_SYSEMU but this doesn't matter, all we need it should be correct after ptrace_resume() wakes up the tracee. --- kernel/ptrace.c | 13 +++++++------ 1 file changed, 7 insertions(+), 6 deletions(-) --- PU/kernel/ptrace.c~106_KILL_CONTEXT_SYSEMU 2009-10-20 15:58:19.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-20 17:22:27.000000000 +0200 @@ -27,8 +27,6 @@ struct ptrace_context { int options; - bool sysemu; // XXX: will die soon - int signr; siginfo_t *siginfo; @@ -38,6 +36,8 @@ struct ptrace_context { enum utrace_resume_action resume; }; +#define PTRACE_O_SYSEMU 0x100 + #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) #define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) #define PTRACE_EVENT_SIGTRAP (3 << 16) @@ -252,7 +252,7 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); - if (unlikely(context->sysemu)) { + if (unlikely(context->options & PTRACE_O_SYSEMU)) { if (test_thread_flag(TIF_SINGLESTEP)) user_disable_single_step(task); return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; @@ -851,8 +851,9 @@ int ptrace_writedata(struct task_struct static int ptrace_set_options(struct utrace_engine *engine, struct task_struct *child, long data) { - __ptrace_set_options(child, engine, data & PTRACE_O_MASK); + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + __ptrace_set_options(child, engine, data & PTRACE_O_MASK); return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } @@ -1026,7 +1027,7 @@ static int ptrace_resume(struct utrace_e if (!valid_signal(data)) return -EIO; - context->sysemu = false; + context->options &= ~PTRACE_O_SYSEMU; events = engine->flags & ~UTRACE_EVENT_SYSCALL; action = UTRACE_RESUME; @@ -1053,7 +1054,7 @@ static int ptrace_resume(struct utrace_e return -EIO; action = UTRACE_SINGLESTEP; case PTRACE_SYSEMU: - context->sysemu = true; + context->options |= PTRACE_O_SYSEMU; events |= UTRACE_EVENT(SYSCALL_ENTRY); break; #endif From oleg at redhat.com Tue Oct 20 16:15:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 18:15:27 +0200 Subject: [PATCH 107] cosmetic, introduce ptrace_resume_action() Message-ID: <20091020161527.GA30642@redhat.com> No functional changes. Move the "switch (request)" code from ptrace_resume() into the new helper, ptrace_resume_action(). --- kernel/ptrace.c | 26 +++++++++++++++++++------- 1 file changed, 19 insertions(+), 7 deletions(-) --- PU/kernel/ptrace.c~107_PTRACE_RESUME_ACTION 2009-10-20 17:22:27.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-20 17:55:20.000000000 +0200 @@ -1017,15 +1017,12 @@ static void do_ptrace_resume(struct utra ptrace_wake_up(tracee, engine, action, true); } -static int ptrace_resume(struct utrace_engine *engine, - struct task_struct *tracee, long request, long data) +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) { struct ptrace_context *context = ptrace_context(engine); - enum utrace_resume_action action; unsigned long events; - - if (!valid_signal(data)) - return -EIO; + int action; context->options &= ~PTRACE_O_SYSEMU; events = engine->flags & ~UTRACE_EVENT_SYSCALL; @@ -1065,9 +1062,24 @@ static int ptrace_resume(struct utrace_e } if (events != engine->flags && - utrace_set_events(tracee, engine, events)) + utrace_set_events(tracee, engine, events)) return -ESRCH; + return action; +} + +static int ptrace_resume(struct utrace_engine *engine, + struct task_struct *tracee, long request, long data) +{ + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + do_ptrace_resume(engine, tracee, action, request, data); return 0; } From oleg at redhat.com Tue Oct 20 16:15:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 20 Oct 2009 18:15:30 +0200 Subject: [PATCH 108] cosmetic, fold do_ptrace_resume() into ptrace_resume() Message-ID: <20091020161530.GA30649@redhat.com> ptrace_resume() is trivial now, it can absorb do_ptrace_resume(). This and the previous patches are pure cosmetic, I can't explain why I think the code looks more readable this way, but it certainly looks better to me. --- kernel/ptrace.c | 105 +++++++++++++++++++++++++------------------------------- 1 file changed, 48 insertions(+), 57 deletions(-) --- PU/kernel/ptrace.c~108_FOLD_DO_PTRACE_RESUME 2009-10-20 17:55:20.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-20 18:03:02.000000000 +0200 @@ -961,62 +961,6 @@ static void ptrace_wake_up(struct task_s utrace_control(tracee, engine, action); } -static void do_ptrace_resume(struct utrace_engine *engine, - struct task_struct *tracee, - enum utrace_resume_action action, - long request, long data) -{ - struct ptrace_context *context = ptrace_context(engine); - - switch (get_stop_event(context)) { - case PTRACE_EVENT_VFORK: - if (context->options & PTRACE_O_TRACEVFORKDONE) { - set_stop_code(context, PTRACE_EVENT_VFORK_DONE); - action = UTRACE_REPORT; - } - break; - - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: - if (request == PTRACE_SYSCALL) { - set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); - do_ptrace_notify_stop(context, tracee); - return; - } - /* fallthrough, but suppress send_sig_info() below */ - data = 0; - - case PTRACE_EVENT_SYSCALL_EXIT: - if (action != UTRACE_RESUME) { - read_lock(&tasklist_lock); - if (tracee->sighand) - send_sigtrap(tracee, task_pt_regs(tracee), - 0, TRAP_BRKPT); - read_unlock(&tasklist_lock); - action = UTRACE_RESUME; - } - /* fallthrough */ - - case PTRACE_EVENT_SYSCALL_ENTRY: - if (data) - send_sig_info(data, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - context->signr = data; - break; - - case 0: - // XXX: JCTL stop - break; - } - - context->resume = action; - ptrace_wake_up(tracee, engine, action, true); -} - static int ptrace_resume_action(struct task_struct *tracee, struct utrace_engine *engine, long request) { @@ -1071,6 +1015,7 @@ static int ptrace_resume_action(struct t static int ptrace_resume(struct utrace_engine *engine, struct task_struct *tracee, long request, long data) { + struct ptrace_context *context = ptrace_context(engine); int action; if (!valid_signal(data)) @@ -1080,7 +1025,53 @@ static int ptrace_resume(struct utrace_e if (action < 0) return action; - do_ptrace_resume(engine, tracee, action, request, data); + switch (get_stop_event(context)) { + case PTRACE_EVENT_VFORK: + if (context->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(context, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + do_ptrace_notify_stop(context, tracee); + return 0; + } + /* fallthrough, but suppress send_sig_info() below */ + data = 0; + + case PTRACE_EVENT_SYSCALL_EXIT: + if (action != UTRACE_RESUME) { + read_lock(&tasklist_lock); + if (tracee->sighand) + send_sigtrap(tracee, task_pt_regs(tracee), + 0, TRAP_BRKPT); + read_unlock(&tasklist_lock); + action = UTRACE_RESUME; + } + /* fallthrough */ + + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + context->signr = data; + break; + + case 0: + // XXX: JCTL stop + break; + } + + context->resume = action; + ptrace_wake_up(tracee, engine, action, true); return 0; } From roland at redhat.com Tue Oct 20 21:20:25 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 20 Oct 2009 14:20:25 -0700 (PDT) Subject: [PATCH 83] ptrace_attach_task: suppress WARN_ON(err) In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 12:04:05 +0200 <20091016100405.GE6539@redhat.com> References: <20091012163425.GA9965@redhat.com> <20091016015149.6C44D16D7@magilla.sf.frob.com> <20091016100405.GE6539@redhat.com> Message-ID: <20091020212025.C3D9914@magilla.sf.frob.com> > Well, I think you are right... But I just can't convince myself I > _really_ understand why the "set new bits" case is not interesting. > Otoh, I can't imagine why the caller should worry about -EINPROGRESS > if it doesn't clear any events. If you set a new bit and utrace_set_events() returns 0, that very instant, before you even examine the return value, a just-enabled report_* callback could be in progress. So indeed it is hard to see a value in even claiming any such behavior. > But I think the new code should have the comment to explain this > "old_flags & ~events" condition. Yes, I intended to change/add comments if I put it in. Thanks, Roland From roland at redhat.com Tue Oct 20 21:37:07 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 20 Oct 2009 14:37:07 -0700 (PDT) Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 12:23:52 +0200 <20091016102352.GF6539@redhat.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> <20091012183814.5544FA8BB@magilla.sf.frob.com> <20091013082835.GA17774@redhat.com> <20091016015856.C1EF116D7@magilla.sf.frob.com> <20091016102352.GF6539@redhat.com> Message-ID: <20091020213707.B69AB14@magilla.sf.frob.com> > But ptrace_check_attach() needs the tracee to be already stopped. > A bit ugly to ask the tracee to stop via UTRACE_STOP and then resume > it if it was not already stopped. And I don't even understand how to > do this correctly. (but again, I'll try to think later). Ugly, but correct and simple. It's only ugly when called in an error case. > Apart from utrace_prepare_examine()->wait_task_inactive() and security > checks, ptrace_check_attach() should do something like > > if (!task_stop_or_traced()) > FAIL; > > if (SIGNAL_STOP_STOPPED || // JCTL stop > get_stop_event()) { // it was stopped by us > > ... OK. s/STOPPED/TRACED/ and proceed .. > } > > FAIL; Right. That is fine as long as there are no races that can confuse it. I don't see any off hand. > Not sure. Suppose the tracer does PTRACE_SYSCALL and the tracee spins in > user-mode. Another engine stops the tracee. In this case any ptrace() > request should fail despite the fact the tracee is STOPPED or TRACED. Correct (if it's in TASK_TRACED, not TASK_STOPPED). It needs to test the ptrace-stoppedness state in ptrace_context. You only need any UTRACE_STOP-related logic to counter any possible races with wakeup. i.e., if the stoppedness state is still left when you resume and cleared by the tracee's own callbacks, you would get a false positive in case the tracee had not been scheduled yet. Since the ptrace-stoppedness should never be indicated without the engine being in UTRACE_STOP state, the only other race is with SIGKILL wakeups. That one probably doesn't matter, since it's no different from the SIGKILL wakeup coming just after ptrace_check_attach() returns 0. Thanks, Roland From roland at redhat.com Tue Oct 20 21:43:00 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 20 Oct 2009 14:43:00 -0700 (PDT) Subject: utrace-ptrace v1 todo list In-Reply-To: Oleg Nesterov's message of Friday, 16 October 2009 14:49:34 +0200 <20091016124934.GA17374@redhat.com> References: <20091015195345.GA3998@redhat.com> <20091016032346.5DC9016D7@magilla.sf.frob.com> <20091016083151.GA6539@redhat.com> <20091016124934.GA17374@redhat.com> Message-ID: <20091020214300.0CD1D14@magilla.sf.frob.com> > The definition of v1 is very simple and absolutely precise. > The code is v1 when Roland thinks we can make the RFC patch and > send it for review. Ok. My definition of success remains "whatever works to get it merged". > As I see it, we need the following changes. > > utrace: > > - utrace_control(SINGLESTEP) calls get_user_pages() under > spin_lock() Yes. > ptrace: I'm not actually tracking closely enough to verify which implementation holes are or aren't there. So I'd state it in the high-level way: it works without regressions and is not too much slower. That means verifying ptrace-tests (perhaps modulo job-control corners), gdb testsuite, and UML. > - simple cleanups, may be more comments. Right, I call this "whatever is needed for upstream review". Thanks, Roland From roland at redhat.com Tue Oct 20 21:46:42 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 20 Oct 2009 14:46:42 -0700 (PDT) Subject: [PATCH 96] ptrace_report_clone: uglify CLONE_PTRACE/CLONE_UNTRACED behaviour to match upstream In-Reply-To: Oleg Nesterov's message of Saturday, 17 October 2009 20:14:52 +0200 <20091017181452.GA25211@redhat.com> References: <20091017181452.GA25211@redhat.com> Message-ID: <20091020214642.5AD3314@magilla.sf.frob.com> > HOWEVER!!! man 2 clone: > > CLONE_PTRACE > If CLONE_PTRACE is specified, and the calling process is being > traced, then trace the child also (see ptrace(2)). That is accurate. > OK, > > CLONE_UNTRACED (since Linux 2.5.46) > If CLONE_UNTRACED is specified, then a tracing process cannot > force CLONE_PTRACE on this child process. > > ??? This is not. Don't trust the man pages, match the actual kernel behavior. The man pages are written by people who don't really understand the kernel, and only once in a while ask me and you for clarification to make them actually accurate. I don't even look at them, I only look at the source and the manifest behavior of the kernel on test cases. Thanks, Roland From roland at redhat.com Tue Oct 20 22:30:05 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 20 Oct 2009 15:30:05 -0700 (PDT) Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: Oleg Nesterov's message of Sunday, 18 October 2009 20:13:59 +0200 <20091018181359.GA30753@redhat.com> References: <20091018181359.GA30753@redhat.com> Message-ID: <20091020223005.D42CE81A3@magilla.sf.frob.com> > What about PTRACE_SYSEMU_SINGLESTEP ? I will read the code > tomorrow, but it is easy to miss some detail and we don't > have any test-cases. These exist purely for UML. So the real test cases are to use UML. To start with, make sure that check_sysemu() gets the same results as on the vanilla kernel. > Looks like, PTRACE_SYSEMU_SINGLESTEP is PTRACE_SINGLESTEP > plus: if we enter syscall we should > > - return UTRACE_SYSCALL_ABORT > > - avoid SYSCALL_EXIT report like PTRACE_SYSEMU Right. I believe that the intent is PTRACE_SYSEMU_SINGLESTEP into a syscall insn behaves exactly like PTRACE_SYSEMU. If it's any other insn, it behaves exactly like PTRACE_SINGLESTEP. > - avoid the unnecessary send_sigtrap() in syscall_trace_leave() > somehow, but the exact semantics is not clear to me... If there was a syscall-entry report under SYSEMU, then you do not also report that as a single-step stop. > In particular. The tracee stops in SYSCALL_ENTRY, the tracer > does PTRACE_SYSEMU_SINGLESTEP. We should just do enable_step() > and clear UTRACE_EVENT(SYSCALL_EXIT), correct? That is a possible implementation detail, sure. The semantics are that the syscall doesn't happen, and there is only one stop. > Afaics, PTRACE_SYSEMU means: > > - cancel this syscall, and do _not_ report SYSCALL_ENTRY > to the tracer > > - SYSCALL_EXIT should be reported, but send_sigtrap() > should be avoied (in case it was SYSEMU_SINGLESTEP). > > Correct? There is no distinction in ptrace between the entry and exit reports. So this is implementation detail, not semantics. The semantics say that the tracer sees only one stop per syscall insn, not two. The other thing that is possibly relevant to the semantics is the interaction with syscall audit. In the syscall entry path, we decide that the syscall will be skipped, then stop for the ptrace report. After resuming, we'll get to audit_syscall_entry and it will examine the register state as changed by ptrace before the resumption. So that will claim something or other (chosen by the tracer) for audit, even though the syscall doesn't really happen. Then we'll get to the syscall exit path, do audit_syscall_exit with the very same register state, and do nothing else. Those audit calls seem pretty useless since they don't even really tell a lie chosen by the tracer--the audit log just sees the "not really made" syscall entry state followed by the "aborted" (-ENOSYS) exit state. But it might be considered worthwhile upstream to keep this exactly as it was. > So. Looks like the only complication is that we should avoid > the unnecessary send_sigtrap() in syscall_trace_leave(), but > we shouldn't use TIF_SYSCALL_EMU - it must die. Right. There is another possible wrinkle, though this probably doesn't matter. If you used PTRACE_SYSEMU{,_SINGLESTEP} and got a syscall entry stop, then you can resume it with PTRACE_SYSCALL or PTRACE_SINGLESTEP instead. In those cases, you will get a syscall-exit report or will get a synthetic TRAP_BRKPT, looking at the "syscall returned -ENOSYS" state. I'm almost positive that nobody ever does this and that nobody cares about this behaving that way (i.e. UML doesn't care, and nobody else uses this stuff). But them's the manifest semantics of today. So if we were to care about preserving that, it could impinge on whether we implement by stopping in syscall-entry and then skipping syscall-exit or vice versa. Thanks, Roland From mldireto at tudoemoferta.com.br Tue Oct 20 22:01:21 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Tue, 20 Oct 2009 20:01:21 -0200 Subject: Bricolagem TudoemOferta. Sua vontade, nossas Ferramentas Message-ID: <78ed2863fb317053fcc2e6c600139a8b@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Oct 21 08:58:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 10:58:14 +0200 Subject: [PATCH 96] ptrace_report_clone: uglify CLONE_PTRACE/CLONE_UNTRACED behaviour to match upstream In-Reply-To: <20091020214642.5AD3314@magilla.sf.frob.com> References: <20091017181452.GA25211@redhat.com> <20091020214642.5AD3314@magilla.sf.frob.com> Message-ID: <20091021085814.GA8280@redhat.com> On 10/20, Roland McGrath wrote: > > > CLONE_UNTRACED (since Linux 2.5.46) > > If CLONE_UNTRACED is specified, then a tracing process cannot > > force CLONE_PTRACE on this child process. > > > > ??? > > This is not. Don't trust the man pages, match the actual kernel behavior. OK, thanks. The actual (upstream) kernel behavior disagrees with the man, so does utrace-ptrace. Oleg. From oleg at redhat.com Wed Oct 21 09:56:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 11:56:46 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: <20091020223005.D42CE81A3@magilla.sf.frob.com> References: <20091018181359.GA30753@redhat.com> <20091020223005.D42CE81A3@magilla.sf.frob.com> Message-ID: <20091021095646.GB8280@redhat.com> On 10/20, Roland McGrath wrote: > > These exist purely for UML. So the real test cases are to use UML. > To start with, make sure that check_sysemu() gets the same results > as on the vanilla kernel. If only I knew how to use UML... OK, thanks. I'll try to test it later, along with gdb testsuite testing. > There is no distinction in ptrace between the entry and exit reports. > So this is implementation detail, not semantics. The semantics say that > the tracer sees only one stop per syscall insn, not two. Yes, yes, I see. I used ENTRY/EXIT terms just to clarify what I mean. > The other thing that is possibly relevant to the semantics is the > interaction with syscall audit. In the syscall entry path, we decide > that the syscall will be skipped, then stop for the ptrace report. > After resuming, we'll get to audit_syscall_entry and it will examine the > register state as changed by ptrace before the resumption. So that will > claim something or other (chosen by the tracer) for audit, even though > the syscall doesn't really happen. Then we'll get to the syscall exit > path, do audit_syscall_exit with the very same register state, and do > nothing else. Yes, thanks. With the patches I sent the tracee stops after both audit_syscall_entry() and audit_syscall_exit() were already called. If the tracer changes (say) ->orig_ax, this won't be visible to audit. > Those audit calls seem pretty useless since they don't even really tell > a lie chosen by the tracer--the audit log just sees the "not really > made" syscall entry state followed by the "aborted" (-ENOSYS) exit > state. But it might be considered worthwhile upstream to keep this > exactly as it was. Oh. Then we should stop in utrace_report_syscall_entry() path and we need the additional complications to handle SYSEMU_SINGLESTEP correctly. Although these complications are straightforward. Can't we ignore this difference for now? > Right. There is another possible wrinkle, though this probably doesn't > matter. If you used PTRACE_SYSEMU{,_SINGLESTEP} and got a syscall entry > stop, then you can resume it with PTRACE_SYSCALL or PTRACE_SINGLESTEP > instead. Yes, please see the changelog for "[PATCH 105] PTRACE_SYSEMU_SINGLESTEP". This looks simple simple. we can introduce PTRACE_EVENT_SYSEMU_SYSCALL, then add the new "case" into ptrace_resume()->switch(). Oleg. From oleg at redhat.com Wed Oct 21 10:28:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 12:28:20 +0200 Subject: utrace-ptrace && ptrace_check_attach() In-Reply-To: <20091020213707.B69AB14@magilla.sf.frob.com> References: <20091010164018.GA13218@redhat.com> <20091012013902.C8AD31D2@magilla.sf.frob.com> <20091012110209.GA22581@redhat.com> <20091012183814.5544FA8BB@magilla.sf.frob.com> <20091013082835.GA17774@redhat.com> <20091016015856.C1EF116D7@magilla.sf.frob.com> <20091016102352.GF6539@redhat.com> <20091020213707.B69AB14@magilla.sf.frob.com> Message-ID: <20091021102820.GC8280@redhat.com> On 10/20, Roland McGrath wrote: > > > But ptrace_check_attach() needs the tracee to be already stopped. > > A bit ugly to ask the tracee to stop via UTRACE_STOP and then resume > > it if it was not already stopped. And I don't even understand how to > > do this correctly. (but again, I'll try to think later). > > Ugly, but correct and simple. It's only ugly when called in an error case. I don't see why it is simple ;) But as I said, I must have a blind spot here. Afaics it is not easy to cancel UTRACE_STOP request correctly. > > Apart from utrace_prepare_examine()->wait_task_inactive() and security > > checks, ptrace_check_attach() should do something like > > > > if (!task_stop_or_traced()) > > FAIL; > > > > if (SIGNAL_STOP_STOPPED || // JCTL stop > > get_stop_event()) { // it was stopped by us > > > > ... OK. s/STOPPED/TRACED/ and proceed .. > > } > > > > FAIL; > > Right. That is fine as long as there are no races that can confuse it. > I don't see any off hand. > > > Not sure. Suppose the tracer does PTRACE_SYSCALL and the tracee spins in > > user-mode. Another engine stops the tracee. In this case any ptrace() > > request should fail despite the fact the tracee is STOPPED or TRACED. > > Correct (if it's in TASK_TRACED, not TASK_STOPPED). It needs to test the > ptrace-stoppedness state in ptrace_context. You only need any > UTRACE_STOP-related logic to counter any possible races with wakeup. > i.e., if the stoppedness state is still left when you resume and cleared by > the tracee's own callbacks, you would get a false positive in case the > tracee had not been scheduled yet. Since the ptrace-stoppedness should > never be indicated without the engine being in UTRACE_STOP state, the only > other race is with SIGKILL wakeups. That one probably doesn't matter, > since it's no different from the SIGKILL wakeup coming just after > ptrace_check_attach() returns 0. OK. I need to think about this later. So, we have 2 known problems: this one and jctl stacked events. Both are minor, and I doubt some test-case can notice. Especially because the multitracing case is not possible now. I am going to do some other changes which hopefully can reduce the number of necessary changes outside of ptrace.c, then return to these problems. Oleg. From oleg at redhat.com Wed Oct 21 12:08:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 14:08:54 +0200 Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: <20091021095646.GB8280@redhat.com> References: <20091018181359.GA30753@redhat.com> <20091020223005.D42CE81A3@magilla.sf.frob.com> <20091021095646.GB8280@redhat.com> Message-ID: <20091021120854.GA18258@redhat.com> On 10/21, Oleg Nesterov wrote: > > On 10/20, Roland McGrath wrote: > > > > These exist purely for UML. So the real test cases are to use UML. > > To start with, make sure that check_sysemu() gets the same results > > as on the vanilla kernel. > > If only I knew how to use UML... > > OK, thanks. I'll try to test it later, Not sure this is adequate testing, but I compiled arch/um/os-Linux/start_up.c as user-space program (I had to remove some unnecessary stuff from *.h) and it prints Checking that ptrace can change system call numbers...OK Checking syscall emulation patch for ptrace...OK Checking advanced syscall emulation patch for ptrace...OK Oleg. From oleg at redhat.com Wed Oct 21 18:27:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:23 +0200 Subject: [PATCH 109-113] preparations for V1 Message-ID: <20091021182723.GA14815@redhat.com> utrace-ptrace still has some known problems, but I'd like to do some prepatations beforehand. Oleg. From oleg at redhat.com Wed Oct 21 18:27:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:26 +0200 Subject: [PATCH 109] hack ptrace_check_attach() to make it almost correct Message-ID: <20091021182726.GA14823@redhat.com> Add some temporary hacks into ptrace_check_attach() for now to make it almost correct. - check "child->parent == current" after ptrace_lookup_engine(), this way we can't race with ptrace_attach(). - check task_is_stopped_or_traced() before utrace_control(UTRACE_STOP), the child must be already stopped. This way we can't provoke the unnecessary stop unless (in the very unlikely case) we race with SIGCONT in between. The multitracing issues are ignored for now. - Check "int kill". Again, this is not 100% right but hopefully enough to forget about ptrace_check_attach() problems until we resolve other issues and do the testing. --- kernel/ptrace.c | 25 ++++++++++++++----------- 1 file changed, 14 insertions(+), 11 deletions(-) --- PU/kernel/ptrace.c~109_CHECK_ATTACH_ALMOST_FIX 2009-10-21 12:29:47.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-21 14:37:44.000000000 +0200 @@ -535,26 +535,29 @@ int ptrace_check_attach(struct task_stru { struct utrace_engine *engine; struct utrace_examiner exam; - int ret; - - if (child->parent != current) - return -ESRCH; + int ret = -ESRCH; engine = ptrace_lookup_engine(child); if (IS_ERR(engine)) - return -ESRCH; + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + if (!task_is_stopped_or_traced(child)) + goto out; /* * Make sure our engine has already stopped the child. * Then wait for it to be off the CPU. */ - ret = 0; - if (utrace_control(child, engine, UTRACE_STOP) || - utrace_prepare_examine(child, engine, &exam)) - ret = -ESRCH; - + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: utrace_engine_put(engine); - return ret; } From oleg at redhat.com Wed Oct 21 18:27:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:28 +0200 Subject: [PATCH 110] revert the clone() related changes in tracehook.h Message-ID: <20091021182728.GA14826@redhat.com> The changes in tracehook_prepare_clone() and tracehook_report_clone() are no longer needed, we can revert them to lessen the size of the first patch(es) and simplify the review/merging. The reverted changes were necessary before, now - tracehook_prepare_clone() none of "->ptrace & PT_" conditions can be true, ->ptrace can contain only PT_PTRACED or PT_PTRACE_CAP - tracehook_report_clone() task_ptrace(child) is not possible at this point see also the next patches. --- include/linux/tracehook.h | 20 ++++++++++++++++++++ 1 file changed, 20 insertions(+) --- PU/include/linux/tracehook.h~110_REVERT_CLONE_CHANGES_IN_H 2009-09-02 20:30:00.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-10-21 19:20:39.000000000 +0200 @@ -208,6 +208,18 @@ static inline void tracehook_report_exit */ static inline int tracehook_prepare_clone(unsigned clone_flags) { + if (clone_flags & CLONE_UNTRACED) + return 0; + + if (clone_flags & CLONE_VFORK) { + if (current->ptrace & PT_TRACE_VFORK) + return PTRACE_EVENT_VFORK; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (current->ptrace & PT_TRACE_CLONE) + return PTRACE_EVENT_CLONE; + } else if (current->ptrace & PT_TRACE_FORK) + return PTRACE_EVENT_FORK; + return 0; } @@ -252,6 +264,14 @@ static inline void tracehook_report_clon { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) utrace_report_clone(clone_flags, child); + if (unlikely(task_ptrace(child))) { + /* + * It doesn't matter who attached/attaching to this + * task, the pending SIGSTOP is right in any case. + */ + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); + } } /** From oleg at redhat.com Wed Oct 21 18:27:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:31 +0200 Subject: [PATCH 111] tracehooks: remove some PT_PTRACED checks Message-ID: <20091021182731.GA14832@redhat.com> Preparation for the next patch. This patch doesn't change the behaviour for upstream, neither it does for utrace-ptrace. --- include/linux/tracehook.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- PU/include/linux/tracehook.h~111_KILL_SOME_PTRACED_CHECKS_IN_H 2009-10-21 19:20:39.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-10-21 19:46:33.000000000 +0200 @@ -132,7 +132,7 @@ static inline int tracehook_unsafe_exec( { int unsafe = 0; int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { + if (ptrace) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else @@ -154,7 +154,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (task_ptrace(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -484,7 +484,7 @@ static inline int tracehook_notify_jctl( { if (task_utrace_flags(current) & UTRACE_EVENT(JCTL)) utrace_report_jctl(notify, why); - return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; + return notify ?: task_ptrace(current) ? why : 0; } /** From oleg at redhat.com Wed Oct 21 18:27:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:34 +0200 Subject: [PATCH 112] introduce PT_UTRACED to replace PT_PTRACED inside ptrace.c Message-ID: <20091021182734.GA14836@redhat.com> Trivial. Pick the new "random" value to use it instead of PT_PTRACED. We need this old or new bit only to make sure task_ptrace() != 0. This allows us to simplify/lessen the first patch(es) we are going to send to lkml, because now we can drop some of unnecessary changes outside of ptrace.c. See the next patch as an example. --- kernel/ptrace.c | 10 ++++++---- 1 file changed, 6 insertions(+), 4 deletions(-) --- PU/kernel/ptrace.c~112_PT_UTRACED 2009-10-21 19:43:59.000000000 +0200 +++ PU/kernel/ptrace.c 2009-10-21 19:57:49.000000000 +0200 @@ -36,6 +36,8 @@ struct ptrace_context { enum utrace_resume_action resume; }; +#define PT_UTRACED 0x00001000 + #define PTRACE_O_SYSEMU 0x100 #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) @@ -518,7 +520,7 @@ static int ptrace_attach_task(struct tas return PTR_ERR(engine); /* * It can fail only if the tracee is dead, the caller - * must notice this before setting PT_PTRACED. + * must notice this before setting PT_UTRACED. */ err = __ptrace_set_options(tracee, engine, options); WARN_ON(err && !tracee->exit_state); @@ -645,7 +647,7 @@ int ptrace_attach(struct task_struct *ta goto unlock_tasklist; BUG_ON(task->ptrace); - task->ptrace = PT_PTRACED; + task->ptrace = PT_UTRACED; if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; @@ -664,7 +666,7 @@ out: /** * ptrace_traceme -- helper for PTRACE_TRACEME * - * Performs checks and sets PT_PTRACED. + * Performs checks and sets PT_UTRACED. * Should be used by all ptrace implementations for PTRACE_TRACEME. */ int ptrace_traceme(void) @@ -685,7 +687,7 @@ int ptrace_traceme(void) * pretend ->real_parent untraces us right after return. */ if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_PTRACED; + current->ptrace = PT_UTRACED; __ptrace_link(current, current->real_parent); detach = false; } From oleg at redhat.com Wed Oct 21 18:27:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 21 Oct 2009 20:27:36 +0200 Subject: [PATCH 113] revert utrace-ptrace changes in kernel/signal.c Message-ID: <20091021182736.GA14839@redhat.com> Now that utrace-ptrace doesn't use PT_PTRACED, we don't need ifdefs in signal.c, we can filter out ptrace_signal() if we check PT_PTRACED bit. Again, note that this change in ptrace_signal() is equally correct for upstream. IOW, I am going to make the preparation patch which adds/removes some PT_PTRACED checks for upstream, then utrace-ptrace will only change ptrace.c and nothing outside. --- kernel/signal.c | 14 +------------- 1 file changed, 1 insertion(+), 13 deletions(-) --- PU/kernel/signal.c~113_REVERT_UTRACE_HACKS_IN_SIGNAL 2009-10-09 13:19:11.000000000 +0200 +++ PU/kernel/signal.c 2009-10-21 20:11:46.000000000 +0200 @@ -1533,8 +1533,6 @@ void do_notify_parent_cldstop(struct tas spin_unlock_irqrestore(&sighand->siglock, flags); } -#ifndef CONFIG_UTRACE_PTRACE - static inline int may_ptrace_stop(void) { if (!likely(task_ptrace(current))) @@ -1675,8 +1673,6 @@ void ptrace_notify(int exit_code) spin_unlock_irq(¤t->sighand->siglock); } -#endif /* !CONFIG_UTRACE_PTRACE */ - /* * This performs the stopping for SIGSTOP and other stop signals. * We have to stop all threads in the thread group. @@ -1750,11 +1746,10 @@ static int do_signal_stop(int signr) return 1; } -#ifndef CONFIG_UTRACE_PTRACE static int ptrace_signal(int signr, siginfo_t *info, struct pt_regs *regs, void *cookie) { - if (!task_ptrace(current)) + if (!(task_ptrace(current) & PT_PTRACED)) return signr; ptrace_signal_deliver(regs, cookie); @@ -1789,13 +1784,6 @@ static int ptrace_signal(int signr, sigi return signr; } -#else -static int ptrace_signal(int signr, siginfo_t *info, - struct pt_regs *regs, void *cookie) -{ - return signr; -} -#endif int get_signal_to_deliver(siginfo_t *info, struct k_sigaction *return_ka, struct pt_regs *regs, void *cookie) From roland at redhat.com Wed Oct 21 18:57:31 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 21 Oct 2009 11:57:31 -0700 (PDT) Subject: [PATCH 100-103] ptrace_resume cleanup/simplification In-Reply-To: Oleg Nesterov's message of Wednesday, 21 October 2009 11:56:46 +0200 <20091021095646.GB8280@redhat.com> References: <20091018181359.GA30753@redhat.com> <20091020223005.D42CE81A3@magilla.sf.frob.com> <20091021095646.GB8280@redhat.com> Message-ID: <20091021185731.18E281D@magilla.sf.frob.com> > If only I knew how to use UML... See http://user-mode-linux.sourceforge.net/ for instructions and download some old kernel/fs images from there to test. These old builds are good for verifying the lack of regressions. It's also very easy to build a fresh UML kernel from your own sources: make ARCH=um defconfig; make ARCH=um; ./vmlinux root=... Without an fs image you can test that it boots as far as the "Cannot open root device" error, and that the startup messages match what you see running on the vanilla kernel as host. > Yes, thanks. With the patches I sent the tracee stops after both > audit_syscall_entry() and audit_syscall_exit() were already called. > > If the tracer changes (say) ->orig_ax, this won't be visible to audit. Right. It's hard to claim that's not utterly useless, but still... > Oh. Then we should stop in utrace_report_syscall_entry() path and > we need the additional complications to handle SYSEMU_SINGLESTEP > correctly. Although these complications are straightforward. If we think we care, yes. > Can't we ignore this difference for now? Yes. I also think you can ask the UML people if they ever care at all and if they don't then it will be OK upstream to change these corners. > Not sure this is adequate testing, but I compiled arch/um/os-Linux/start_up.c > as user-space program (I had to remove some unnecessary stuff from *.h) and > it prints > > Checking that ptrace can change system call numbers...OK > Checking syscall emulation patch for ptrace...OK > Checking advanced syscall emulation patch for ptrace...OK That's certainly a good sign! We do need to also test at least that using some old UML kernel+fs images we get as far as booting userland and running a few processes. Thanks, Roland From news at maisservicos.com Thu Oct 22 18:00:14 2009 From: news at maisservicos.com (MaisServicos) Date: Thu, 22 Oct 2009 19:00:14 +0100 Subject: Teste o seu QI! Message-ID: <20091022180013.C21B33F8C6@server17.nortenet.pt> Caso n?o visualize correctamente este e-mail, por favor clique AQUI. Faz o IQ teste e descobre se ?s inteligente. NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Oct 22 21:35:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 22 Oct 2009 23:35:16 +0200 Subject: [RFC, PATCH 0/2] Was: problem: utrace-ptrace && jctl stacked stop In-Reply-To: <20090918094947.F3D5E278D@magilla.sf.frob.com> References: <20090917173040.GA10129@redhat.com> <20090917191405.GA25722@redhat.com> <20090918094947.F3D5E278D@magilla.sf.frob.com> Message-ID: <20091022213516.GA19889@redhat.com> Sorry for late reply. I delayed it because I hoped I will see how to solve this problem cleanly during the rewrite. No. I don't see how we can fix this without some changes in utrace. Just in case, let me remind you what is the problem. For simplicity, let's ignore SIGKILL issues, and let's discuss this particular case: a PTRACE_O_TRACESYSGOOD tracee reports SYSCALL_ENTRY and stops. the tracer does ptrace(PTRACE_SYSCALL); // we must have SYSCALL_EXIT report waitpid(&state); assert(state == 0x857F); <--- 1 assert(ptrace(PTRACE_GETEVENTMSG) == 0); <--- 2 This must always work, both 1 and 2 asserts are valid. (but, for the moment, please forget about 2). However, with utrace-ptrace the tracee can notice ->group_stop_count and call do_signal_stop() before it has a chance to do finish_resume_report() and actually stop. This breaks the 1st assert. On 09/18, Roland McGrath wrote: > > I'll point out that the only symptom that matters to ptrace is ->exit_code > and that issue disappears if you stop overloading it for ptrace purposes, Firstly, I agree of course, in the long term ptrace should not use task_struct->exit_code. But this doesn't matter at all, please see below. > In this scenario, the event has already happened and that's externally > visible (the child exists). (In the equivalent case for exec, you can > tell from /proc/pid/exe, the effects of setuid have happened, etc.) > We don't have the option of saying that the group-stop happened first. > If that were so, this event would not have happened yet, but it's > already been both reported via utrace and become observable by > userland. So it should appear as if the other thread started its > group-stop after we were already in TASK_TRACED. Agreed, I thought about this too. IOW, we can just silently drop this JCTL stop event and report SYSCALL_EXIT instead. So, we add ptrace_report_jctl(notify) which does if (notify == CLD_STOPPED) { if (get_stop_event(context)) { // pretend we we already stopped when another // thread initiated this group-stop, set the // correct ->exit_code and return, our tracer // will be notified by do_signal_stop() task->exit_code = context->stop_code & PTRACE_EVENT_MASK; return; } } (yes, this can't work because ->exit_code will be overwritten by do_signal_stop() but this is very trivial to fix). Unfortunately, this doesn't help. Because the tracee will stop in TASK_STOPPED state, and this means SIGCONT can break the 2nd assert above. This is the problem. Since do_signal_stop() sets TASK_STOPPED, we can't report anything but JCTL event. And it is not possible to hack do_signal_stop() so that it sets TASK_TRACED if the debugger has changed task->exit_code (or context->exit_code or whatever). > In other versions of this race, we'll already be in utrace_stop() or > on the way to it, and hit "we must participate in the bookkeeping." > But the bookkeeping is not really enough. In the case where we were > the last thread we do set SIGNAL_STOP_STOPPED, but we swallow the > parent's notification. Yes, but this is another story. And the current (upstream) implementation is not better, lets forget about this problem for now. > Hmm, perhaps ->exit_code is only ever set now > because of ptrace, at least since your task_stopped_code() changes? > Perhaps we should just nix setting it in do_signal_stop() too (after > new ptrace). Yes. But: please don't forget the tracer can attach after the tracee does do_signal_stop(). Again, this is another story, lets discuss this later. > Now, back to your case, a different ordering of that same race. > > There is nothing really wrong with having utrace's hook be before the > group_stop_count check in get_signal_to_deliver(). But that would > require changing the tracehook interface there, and the existing > tracehook_get_signal() seems about as clean as we can make it. Please see the patches. They are very simple. Perhaps, it makes sense to do more. We can introduce the new UTRACE_SIGNAL_JCTL utrace_signal_action, but I don't think it is really needed. Yes, the debugger can, say, fill *info and return UTRACE_SIGNAL_DELIVER while ->group_stop_count != 0, but a) I think this is harmless and b) can happen anyway (see the changelog for 2nd patch). What do you think? > We can > change tracehook_notify_jctl() > ... > If (after the report_jctl > pass if any) anybody wants UTRACE_STOP, then we handle it with > utrace_stop() right there Yes, I considered this option too. Imho, not nice. This needs more changes and afaics doesn't have any advantages compared to the patch I am sending. But more importantly, I believe this change will complicate the interaction between do_signal_stop() and utrace, and this interaction becomes even more unobvious. Oleg. From oleg at redhat.com Thu Oct 22 21:35:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 22 Oct 2009 23:35:54 +0200 Subject: [PATCH 1/2] (upstream) signals: check ->group_stop_count after tracehook_get_signal() In-Reply-To: <20091022213516.GA19889@redhat.com> References: <20090917173040.GA10129@redhat.com> <20090917191405.GA25722@redhat.com> <20090918094947.F3D5E278D@magilla.sf.frob.com> <20091022213516.GA19889@redhat.com> Message-ID: <20091022213554.GB19889@redhat.com> Move the call to do_signal_stop() down, after tracehook call. This makes ->group_stop_count condition visible to tracers before do_signal_stop() will participate in this group-stop. Currently the patch has no effect, tracehook_get_signal() always returns 0. Signed-off-by: Oleg Nesterov --- kernel/signal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) --- __UTRACE/kernel/signal.c~1_do_signal_stop_after_tracehook 2009-10-09 16:23:34.000000000 +0200 +++ __UTRACE/kernel/signal.c 2009-10-22 22:52:56.000000000 +0200 @@ -1807,11 +1807,6 @@ relock: for (;;) { struct k_sigaction *ka; - - if (unlikely(signal->group_stop_count > 0) && - do_signal_stop(0)) - goto relock; - /* * Tracing can induce an artifical signal and choose sigaction. * The return value in @signr determines the default action, @@ -1823,6 +1818,10 @@ relock: if (unlikely(signr != 0)) ka = return_ka; else { + if (unlikely(signal->group_stop_count > 0) && + do_signal_stop(0)) + goto relock; + signr = dequeue_signal(current, ¤t->blocked, info); From oleg at redhat.com Thu Oct 22 21:36:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 22 Oct 2009 23:36:21 +0200 Subject: [PATCH 2/2] (utrace) utrace_get_signal: don't dequeue_signal() if ->group_stop_count In-Reply-To: <20091022213516.GA19889@redhat.com> References: <20090917173040.GA10129@redhat.com> <20090917191405.GA25722@redhat.com> <20090918094947.F3D5E278D@magilla.sf.frob.com> <20091022213516.GA19889@redhat.com> Message-ID: <20091022213621.GC19889@redhat.com> Check ->group_stop_count before dequeue_signal(). If it is true and we don't have ->interrupt/etc events to report, we should return to participate in group-stop. Please note again that this (and the previous) patches in fact do not change the behaviour "too much". Since we drop ->siglock it is quite possible we can report (say) UTRACE_SIGNAL_REPORT when group_stop_count is not zero. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- __UTRACE/kernel/utrace.c~2_utrace_signal_ck_jctl 2009-10-22 20:50:49.000000000 +0200 +++ __UTRACE/kernel/utrace.c 2009-10-22 23:08:26.000000000 +0200 @@ -1944,10 +1944,12 @@ int utrace_get_signal(struct task_struct event = 0; ka = NULL; memset(return_ka, 0, sizeof *return_ka); - } else if ((task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) == 0) { + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || + unlikely(task->signal->group_stop_count)) { /* - * If no engine is interested in intercepting signals, - * let the caller just dequeue them normally. + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally + * or participate in group-stop. */ return 0; } else { From hot-deals at clubvacationdeals.com Wed Oct 21 16:25:20 2009 From: hot-deals at clubvacationdeals.com (Club Vacation Deals) Date: Wed, 21 Oct 2009 12:25:20 -0400 Subject: Christmas Spectacular Message-ID: <47b60f7c3ec809457049a46febe06952@vallarta-paradise.com> An HTML attachment was scrubbed... URL: From ssc at sscservizi.com Thu Oct 22 15:45:35 2009 From: ssc at sscservizi.com (SSC Srl) Date: Thu, 22 Oct 2009 17:45:35 +0200 Subject: =?utf-8?q?UN=E2=80=99OCCASIONE_PER_MIGLIORARE_LE_PROSPETTIVE_DI_?= =?utf-8?q?GUADAGNO=3F?= Message-ID: <20091022155007.6040.1153694926.swift@mailing.ssc-finance.local> An HTML attachment was scrubbed... URL: From sender at netpromouter.net Fri Oct 23 17:00:18 2009 From: sender at netpromouter.net (Juliana Cruz) Date: Fri, 23 Oct 2009 21:00:18 +0400 Subject: =?utf-8?q?Queres_ir_=C3=A0_Festa_JB_na_Argentina?= Message-ID: Queres ir ? Festa JB na Argentina http://netpromouter.net/iem/link.php?M=21794&N=4&L=19&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Oct 23 23:20:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 24 Oct 2009 01:20:57 +0200 Subject: [PATCH 114-115] ptrace.h cleanups Message-ID: <20091023232057.GA26888@redhat.com> I guess my intent is clear, but just in case... the second patch is the only change in ptrace.h we need and we can send it upstream right now. I am thinking how can we fix utrace_control(SINGLESTEP). I don't have good ideas so far. But, perhaps we can add utrace->please_enable_single_step:1 ? utrace_control() case UTRACE_RESUME: if (likely(resume)) utrace->please_enable_single_step = 1; utrace_stop() and utrace_finish_jctl() can check this flag after wakeup if (unlikely(utrace->stopped)) { ... } esle if (utrace->please_enable_single_step) { user_enable_single_state(current); ... } Or, we can use ENGINE_SINGLESTEP, which probably makes more sense. Like ENGINE_STOP, it lives both in engine->flags and ->utrace_flags. I no longer think utrace_control() should just turn SINGLESTEP into REPORT silently. Oleg. From oleg at redhat.com Fri Oct 23 23:21:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 24 Oct 2009 01:21:00 +0200 Subject: [PATCH 114] revert all utrace-ptrace changes in ptrace.h Message-ID: <20091023232100.GA26892@redhat.com> Revert all changes in ptrace.h, except declaration of ptrace_notify_stop(). The reverted changes in ptrace_init_task() break utrace-ptrace, fixed by the next patch. --- include/linux/ptrace.h | 26 ++++++++++++++++++++++++++ 1 file changed, 26 insertions(+) --- PU/include/linux/ptrace.h~114_REVERT_PTRACE_INIT_TASK 2009-10-23 00:23:15.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-10-24 00:31:32.000000000 +0200 @@ -132,6 +132,28 @@ static inline int task_ptrace(struct tas } /** + * ptrace_event - possibly stop for a ptrace event notification + * @mask: %PT_* bit to check in @current->ptrace + * @event: %PTRACE_EVENT_* value to report if @mask is set + * @message: value for %PTRACE_GETEVENTMSG to return + * + * This checks the @mask bit to see if ptrace wants stops for this event. + * If so we stop, reporting @event and @message to the ptrace parent. + * + * Returns nonzero if we did a ptrace notification, zero if not. + * + * Called without locks. + */ +static inline int ptrace_event(int mask, int event, unsigned long message) +{ + if (mask && likely(!(current->ptrace & mask))) + return 0; + current->ptrace_message = message; + ptrace_notify((event << 8) | SIGTRAP); + return 1; +} + +/** * ptrace_init_task - initialize ptrace state for a new child * @child: new child task * @ptrace: true if child should be ptrace'd by parent's tracer @@ -147,6 +169,10 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; + if (unlikely(ptrace)) { + child->ptrace = current->ptrace; + ptrace_link(child, current->parent); + } } /** From oleg at redhat.com Fri Oct 23 23:21:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 24 Oct 2009 01:21:02 +0200 Subject: [PATCH 115] (upstream) ptrace_init_task: cleanup the usage of ptrace_link() Message-ID: <20091023232102.GA26899@redhat.com> ptrace_init_task() looks confusing, as if we always auto-attach when "bool ptrace" argument is true, while in fact we attach only if current is traced. Make the code more explicit and kill now unused ptrace_link(). Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) --- PU/include/linux/ptrace.h~115_PTRACE_INIT_TASK 2009-10-24 00:31:32.000000000 +0200 +++ PU/include/linux/ptrace.h 2009-10-24 00:46:14.000000000 +0200 @@ -105,12 +105,7 @@ static inline int ptrace_reparented(stru { return child->real_parent != child->parent; } -static inline void ptrace_link(struct task_struct *child, - struct task_struct *new_parent) -{ - if (unlikely(child->ptrace)) - __ptrace_link(child, new_parent); -} + static inline void ptrace_unlink(struct task_struct *child) { if (unlikely(child->ptrace)) @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; - if (unlikely(ptrace)) { + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { child->ptrace = current->ptrace; - ptrace_link(child, current->parent); + __ptrace_link(child, current->parent); } } From sender at netpromouter.net Sat Oct 24 20:48:29 2009 From: sender at netpromouter.net (Johnnie Walker) Date: Sun, 25 Oct 2009 00:48:29 +0400 Subject: =?utf-8?q?Oferecemos_um_Private_Tasting_na_sua_pr=C3=B3pria_casa?= Message-ID: Johnnie Walker apresenta o melhor programa para a sua semana, Um Private Tasting, na sua pr?pria casa. Convide os seus amigos e seja anfitri?o desta experi?ncia memor?vel Siga este link: http://netpromouter.net/iem/link.php?M=21794&N=5&L=8&F=T -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Oct 26 02:23:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:23:57 +0100 Subject: [PATCH 116-121] misc cleanups Message-ID: <20091026022357.GA28088@redhat.com> No functional changes. Prepartions for V1. Oleg. From oleg at redhat.com Mon Oct 26 02:24:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:00 +0100 Subject: [PATCH 116] tracehooks: revert utrace-ptrace changes Message-ID: <20091026022400.GA28092@redhat.com> Revert utrace-ptrace changes in tracehook.h. The reverted change in tracehook_signal_handler() breaks utrace-ptrace, fixed by the next patch. --- include/linux/tracehook.h | 34 ++++++++++++++++++++++++++++++++++ 1 file changed, 34 insertions(+) --- PU/include/linux/tracehook.h~116_REVERT_TRACEHOOK 2009-10-21 19:46:33.000000000 +0200 +++ PU/include/linux/tracehook.h 2009-10-26 00:06:21.000000000 +0100 @@ -69,6 +69,29 @@ static inline int tracehook_expect_break return (task_ptrace(task) & PT_PTRACED) != 0; } +/* + * ptrace report for syscall entry and exit looks identical. + */ +static inline void ptrace_report_syscall(struct pt_regs *regs) +{ + int ptrace = task_ptrace(current); + + if (!(ptrace & PT_PTRACED)) + return; + + ptrace_notify(SIGTRAP | ((ptrace & PT_TRACESYSGOOD) ? 0x80 : 0)); + + /* + * this isn't the same as continuing with a signal, but it will do + * for normal use. strace only continues with a signal if the + * stopping signal is not SIGTRAP. -brl + */ + if (current->exit_code) { + send_sig(current->exit_code, current, 1); + current->exit_code = 0; + } +} + /** * tracehook_report_syscall_entry - task is about to attempt a system call * @regs: user register state of current task @@ -94,6 +117,7 @@ static inline __must_check int tracehook if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && utrace_report_syscall_entry(regs)) return 1; + ptrace_report_syscall(regs); return 0; } @@ -118,6 +142,7 @@ static inline void tracehook_report_sysc { if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); + ptrace_report_syscall(regs); } /** @@ -179,6 +204,9 @@ static inline void tracehook_report_exec { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) utrace_report_exec(fmt, bprm, regs); + if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && + unlikely(task_ptrace(current) & PT_PTRACED)) + send_sig(SIGTRAP, current, 0); } /** @@ -195,6 +223,7 @@ static inline void tracehook_report_exit { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) utrace_report_exit(exit_code); + ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); } /** @@ -299,6 +328,8 @@ static inline void tracehook_report_clon if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && (clone_flags & CLONE_VFORK)) utrace_finish_vfork(current); + if (unlikely(trace)) + ptrace_event(0, trace, pid); } /** @@ -316,6 +347,7 @@ static inline void tracehook_report_clon static inline void tracehook_report_vfork_done(struct task_struct *child, pid_t pid) { + ptrace_event(PT_TRACE_VFORK_DONE, PTRACE_EVENT_VFORK_DONE, pid); } /** @@ -369,6 +401,8 @@ static inline void tracehook_signal_hand { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); + if (stepping) + ptrace_notify(SIGTRAP); } /** From oleg at redhat.com Mon Oct 26 02:24:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:03 +0100 Subject: [PATCH 117] (upstream) tracehook_signal_handler: check PT_PTRACED Message-ID: <20091026022403.GA28099@redhat.com> No functional changes, preparation for utrace-ptrace. tracehook_signal_handler() is the only caller of ptrace_notify() which doesn't check the task is ptraced, it assumes that only ptrace can set TIF_SINGLESTEP. Currently this is true but we are going to change this, check PT_PTRACED. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- PU/include/linux/tracehook.h~117_SIGNAL_HANDLER_CK_PTRACE 2009-10-26 00:06:21.000000000 +0100 +++ PU/include/linux/tracehook.h 2009-10-26 00:10:49.000000000 +0100 @@ -401,7 +401,7 @@ static inline void tracehook_signal_hand { if (task_utrace_flags(current)) utrace_signal_handler(current, stepping); - if (stepping) + if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } From oleg at redhat.com Mon Oct 26 02:24:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:06 +0100 Subject: [PATCH 118] (upstream) introduce kernel/ptrace.h Message-ID: <20091026022406.GA28102@redhat.com> Introduce kernel/ptrace.h and move the code which can be shared with the old implementation into this new header. Signed-off-by: Oleg Nesterov --- kernel/ptrace-common.h | 278 +++++++++++++++++++++++++++++++++++++++++++++++++ kernel/ptrace.c | 278 ------------------------------------------------- 2 files changed, 279 insertions(+), 277 deletions(-) --- /dev/null 2009-10-25 19:46:00.608018007 +0100 +++ PU/kernel/ptrace-common.h 2009-10-26 02:10:36.000000000 +0100 @@ -0,0 +1,278 @@ +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ --- PU/kernel/ptrace.c~118_COMMON_CODE 2009-10-26 01:24:29.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-26 02:11:29.000000000 +0100 @@ -23,6 +23,7 @@ #include #include #include +#include "ptrace-common.h" struct ptrace_context { int options; @@ -563,53 +564,6 @@ out: return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -698,57 +652,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) { bool detach, release; @@ -803,56 +706,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_set_options(struct utrace_engine *engine, struct task_struct *child, long data) { @@ -1162,93 +1015,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -1308,47 +1075,4 @@ int compat_ptrace_request(struct task_st utrace_engine_put(engine); return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Mon Oct 26 02:24:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:08 +0100 Subject: [PATCH 119] cosmetic, relocate some code in ptrace.c Message-ID: <20091026022408.GA28109@redhat.com> 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 #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) { From oleg at redhat.com Mon Oct 26 02:24:11 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:11 +0100 Subject: [PATCH 120] cosmetic, renames Message-ID: <20091026022411.GA28112@redhat.com> Cosmetic changes as you suggested: - s/__ptrace_set_options/ptrace_set_events/ - change the order of arguments in ptrace_set_events() and ptrace_resume() to match utrace API. --- kernel/ptrace.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) --- PU/kernel/ptrace.c~120_RENAMES 2009-10-26 02:48:49.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-26 03:05:58.000000000 +0100 @@ -177,7 +177,7 @@ ptrace_attach_engine(struct task_struct return engine; } -static inline int __ptrace_set_options(struct task_struct *target, +static inline int ptrace_set_events(struct task_struct *target, struct utrace_engine *engine, unsigned long options) { @@ -212,7 +212,7 @@ static int ptrace_attach_task(struct tas * 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); + err = ptrace_set_events(tracee, engine, options); WARN_ON(err && !tracee->exit_state); utrace_engine_put(engine); return 0; @@ -723,12 +723,12 @@ void exit_ptrace(struct task_struct *tra } } -static int ptrace_set_options(struct utrace_engine *engine, - struct task_struct *child, long data) +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) { BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); - __ptrace_set_options(child, engine, data & PTRACE_O_MASK); + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; } @@ -864,8 +864,9 @@ static int ptrace_resume_action(struct t return action; } -static int ptrace_resume(struct utrace_engine *engine, - struct task_struct *tracee, long request, long data) +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) { struct ptrace_context *context = ptrace_context(engine); int action; @@ -951,7 +952,7 @@ int ptrace_request(struct task_struct *c case PTRACE_OLDSETOPTIONS: #endif case PTRACE_SETOPTIONS: - ret = ptrace_set_options(engine, child, data); + ret = ptrace_set_options(child, engine, data); break; case PTRACE_GETEVENTMSG: ret = put_user(ptrace_context(engine)->eventmsg, @@ -991,13 +992,13 @@ int ptrace_request(struct task_struct *c #endif case PTRACE_SYSCALL: case PTRACE_CONT: - ret = ptrace_resume(engine, child, request, data); + ret = ptrace_resume(child, engine, request, data); break; case PTRACE_KILL: ret = 0; if (!child->exit_state) /* already dead */ - ret = ptrace_resume(engine, child, request, SIGKILL); + ret = ptrace_resume(child, engine, request, SIGKILL); break; default: From oleg at redhat.com Mon Oct 26 02:24:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 03:24:13 +0100 Subject: [PATCH 121] ptrace_detach_task: don't use valid_signal() Message-ID: <20091026022413.GA28115@redhat.com> ptrace_detach_task()->valid_signal() looks confusing. Check sig >= 0 instead and add the comment. --- kernel/ptrace.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~121_COMMENT_VOLUNTARY 2009-10-26 03:05:58.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-26 03:18:12.000000000 +0100 @@ -243,9 +243,13 @@ static void ptrace_wake_up(struct task_s static void ptrace_detach_task(struct task_struct *tracee, int sig) { - bool voluntary = valid_signal(sig); - enum utrace_resume_action action = UTRACE_DETACH; + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; if (unlikely(IS_ERR(engine))) return; From oleg at redhat.com Mon Oct 26 03:28:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:39 +0100 Subject: [PATCH 0/7] utrace-ptrace V1 Message-ID: <20091026032839.GA6242@redhat.com> For early review. Patches 1-5 can be sent upstream right now. The last 2 patches add the new implementation. utrace.patch can come before or after, I think "after" is better. Oleg. From oleg at redhat.com Mon Oct 26 03:28:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:41 +0100 Subject: [PATCH 1/7] tracehooks: kill some PT_PTRACED checks Message-ID: <20091026032841.GA6250@redhat.com> No functional changes, preparation for utrace-ptrace. task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill some PT_PTRACED checks in tracehook.h. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- V1/include/linux/tracehook.h~1_TRACEHOOK_KILL_PTRACED_CHECKS 2009-09-24 21:38:54.000000000 +0200 +++ V1/include/linux/tracehook.h 2009-10-25 23:34:16.000000000 +0100 @@ -149,7 +149,7 @@ static inline int tracehook_unsafe_exec( { int unsafe = 0; int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { + if (ptrace) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else @@ -171,7 +171,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (task_ptrace(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -485,7 +485,7 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { - return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; + return notify ?: task_ptrace(current) ? why : 0; } /** From oleg at redhat.com Mon Oct 26 03:28:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:44 +0100 Subject: [PATCH 2/7] tracehook_signal_handler: check PT_PTRACED Message-ID: <20091026032844.GA6253@redhat.com> No functional changes, preparation for utrace-ptrace. tracehook_signal_handler() is the only caller of ptrace_notify() which doesn't check the task is ptraced, it assumes that only ptrace can set TIF_SINGLESTEP. Currently this is true but we are going to change this, check PT_PTRACED. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- V1/include/linux/tracehook.h~2_SIGNAL_HANDLER_CK_PTRACE 2009-10-25 23:34:16.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-10-26 00:25:53.000000000 +0100 @@ -379,7 +379,7 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { - if (stepping) + if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } From oleg at redhat.com Mon Oct 26 03:28:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:46 +0100 Subject: [PATCH 3/7] ptrace_init_task: cleanup the usage of ptrace_link() Message-ID: <20091026032846.GA6256@redhat.com> No functional changes, preparation for utrace-ptrace. ptrace_init_task() looks confusing, as if we always auto-attach when "bool ptrace" argument is true, while in fact we attach only if current is traced. Make the code more explicit and kill now unused ptrace_link(). Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) --- V1/include/linux/ptrace.h~3_PTRACE_INIT_TASK 2009-06-19 01:12:47.000000000 +0200 +++ V1/include/linux/ptrace.h 2009-10-26 00:33:58.000000000 +0100 @@ -105,12 +105,7 @@ static inline int ptrace_reparented(stru { return child->real_parent != child->parent; } -static inline void ptrace_link(struct task_struct *child, - struct task_struct *new_parent) -{ - if (unlikely(child->ptrace)) - __ptrace_link(child, new_parent); -} + static inline void ptrace_unlink(struct task_struct *child) { if (unlikely(child->ptrace)) @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; - if (unlikely(ptrace)) { + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { child->ptrace = current->ptrace; - ptrace_link(child, current->parent); + __ptrace_link(child, current->parent); } } From oleg at redhat.com Mon Oct 26 03:28:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:48 +0100 Subject: [PATCH 4/7] ptrace_signal: check PT_PTRACED Message-ID: <20091026032848.GA6264@redhat.com> No functional changes, preparation for utrace-ptrace. Change ptrace_signal() to check PT_PTRACED instead of task_ptrace() != 0. Currently this is the same, PT_PTRACED must be always set if the task is ptraced. This change is needed to make sure ptrace_sgnal() does nothing if ptrace is implemented on top of utrace. Signed-off-by: Oleg Nesterov --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- V1/kernel/signal.c~4_PTRACE_SIGNAL_CK_PTRACED 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/signal.c 2009-10-26 00:43:05.000000000 +0100 @@ -1731,7 +1731,7 @@ static int do_signal_stop(int signr) static int ptrace_signal(int signr, siginfo_t *info, struct pt_regs *regs, void *cookie) { - if (!task_ptrace(current)) + if (!(task_ptrace(current) & PT_PTRACED)) return signr; ptrace_signal_deliver(regs, cookie); From oleg at redhat.com Mon Oct 26 03:28:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:50 +0100 Subject: [PATCH 5/7] signals: check ->group_stop_count after tracehook_get_signal() Message-ID: <20091026032850.GA6267@redhat.com> No functional changes, preparation for utrace-ptrace. Move the call to do_signal_stop() down, after tracehook call. This makes ->group_stop_count condition visible to tracers before do_signal_stop() will participate in this group-stop. Currently the patch has no effect, tracehook_get_signal() always returns 0. Signed-off-by: Oleg Nesterov --- kernel/signal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) --- V1/kernel/signal.c~5_DO_SIGNAL_STOP_AFTER_TRACEHOOK 2009-10-26 00:43:05.000000000 +0100 +++ V1/kernel/signal.c 2009-10-26 01:01:47.000000000 +0100 @@ -1807,11 +1807,6 @@ relock: for (;;) { struct k_sigaction *ka; - - if (unlikely(signal->group_stop_count > 0) && - do_signal_stop(0)) - goto relock; - /* * Tracing can induce an artifical signal and choose sigaction. * The return value in @signr determines the default action, @@ -1823,6 +1818,10 @@ relock: if (unlikely(signr != 0)) ka = return_ka; else { + if (unlikely(signal->group_stop_count > 0) && + do_signal_stop(0)) + goto relock; + signr = dequeue_signal(current, ¤t->blocked, info); From oleg at redhat.com Mon Oct 26 03:28:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:52 +0100 Subject: [PATCH 6/7] introduce kernel/ptrace.h Message-ID: <20091026032852.GA6270@redhat.com> No functional changes, preparation for utrace-ptrace. Introduce kernel/ptrace.h and move the code which can be shared with the new implementation into this new header. Signed-off-by: Oleg Nesterov --- kernel/ptrace-common.h | 278 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel/ptrace.c | 280 ------------------------------------------------- 2 files changed, 279 insertions(+), 279 deletions(-) --- /dev/null 2009-10-25 19:46:00.608018007 +0100 +++ V1/kernel/ptrace-common.h 2009-10-26 02:20:44.000000000 +0100 @@ -0,0 +1,278 @@ +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ --- V1/kernel/ptrace.c~6_PTRACE_COMMON 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/ptrace.c 2009-10-26 02:21:50.000000000 +0100 @@ -22,7 +22,7 @@ #include #include #include - +#include "ptrace-common.h" /* * ptrace a task: make the debugger its new parent and @@ -117,53 +117,6 @@ int ptrace_check_attach(struct task_stru return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -243,57 +196,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; @@ -347,56 +249,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -457,7 +309,6 @@ static int ptrace_setsiginfo(struct task return error; } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -580,93 +431,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -718,47 +483,4 @@ int compat_ptrace_request(struct task_st return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Mon Oct 26 03:28:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 04:28:55 +0100 Subject: [PATCH 7/7] implement utrace-ptrace Message-ID: <20091026032855.GA6277@redhat.com> For early review. The patch adds the new file, kernel/ptrace-utrace.c, which contains the implementation. This patch expects utrace.patch comes next and adds CONFIG_UTRACE into init/Kconfig. Until then kernel/ptrace-utrace.c is not compiled. --- include/linux/ptrace.h | 2 init/Kconfig | 3 kernel/Makefile | 4 kernel/ptrace-utrace.c | 1068 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1075 insertions(+), 2 deletions(-) --- V1/include/linux/ptrace.h~7_UTRACE_PTRACE 2009-10-26 00:33:58.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-10-26 03:42:51.000000000 +0100 @@ -79,7 +79,7 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ - +extern void ptrace_notify_stop(struct task_struct *tracee); extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); --- V1/init/Kconfig~7_UTRACE_PTRACE 2009-10-09 19:52:23.000000000 +0200 +++ V1/init/Kconfig 2009-10-26 04:15:51.000000000 +0100 @@ -1205,6 +1205,9 @@ config STOP_MACHINE help Need stop_machine() primitive. +config PTRACE_OLD + def_bool !UTRACE + source "block/Kconfig" config PREEMPT_NOTIFIERS --- V1/kernel/Makefile~7_UTRACE_PTRACE 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/Makefile 2009-10-26 04:12:16.000000000 +0100 @@ -4,7 +4,7 @@ obj-y = sched.o fork.o exec_domain.o panic.o printk.o \ cpu.o exit.o itimer.o time.o softirq.o resource.o \ - sysctl.o capability.o ptrace.o timer.o user.o \ + sysctl.o capability.o timer.o user.o \ signal.o sys.o kmod.o workqueue.o pid.o \ rcupdate.o extable.o params.o posix-timers.o \ kthread.o wait.o kfifo.o sys_ni.o posix-cpu-timers.o mutex.o \ @@ -68,6 +68,8 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_PTRACE_OLD) += ptrace.o +obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ --- /dev/null 2009-10-25 19:46:00.608018007 +0100 +++ V1/kernel/ptrace-utrace.c 2009-10-26 03:56:46.000000000 +0100 @@ -0,0 +1,1068 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + + int signr; + siginfo_t *siginfo; + + int stop_code; + unsigned long eventmsg; + + enum utrace_resume_action resume; +}; + +#define PT_UTRACED 0x00001000 + +#define PTRACE_O_SYSEMU 0x100 + +#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) +#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) +#define PTRACE_EVENT_SIGTRAP (3 << 16) +#define PTRACE_EVENT_SIGNAL (4 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF + +static inline bool ptrace_event_pending(struct ptrace_context *context) +{ + return context->stop_code != 0; +} + +static inline int get_stop_event(struct ptrace_context *context) +{ + return context->stop_code >> 8; +} + +static inline void set_stop_code(struct ptrace_context *context, int event) +{ + context->stop_code = (event << 8) | SIGTRAP; +} + +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) +{ + 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_events(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_events(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; +} + +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 void ptrace_detach_task(struct task_struct *tracee, int sig) +{ + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; + + if (unlikely(IS_ERR(engine))) + return; + + if (sig) { + struct ptrace_context *context = ptrace_context(engine); + + switch (get_stop_event(context)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (voluntary) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (voluntary) + context->signr = sig; + context->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + ptrace_wake_up(tracee, engine, action, voluntary); + utrace_engine_put(engine); +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + ptrace_detach_task(tracee, 0); +} + +static u32 ptrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct ptrace_context *context = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(context) && + !signal_group_exit(task->signal)); + + set_stop_code(context, PTRACE_EVENT_EXIT); + context->eventmsg = *code; + + return UTRACE_STOP; +} + +static void ptrace_clone_attach(struct task_struct *parent, + struct task_struct *child, + int options) +{ + struct task_struct *tracer; + bool abort = true; + + if (unlikely(ptrace_attach_task(child, options))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); +} + +static u32 ptrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + struct ptrace_context *context = ptrace_context(engine); + int event = 0; + + WARN_ON(ptrace_event_pending(context)); + + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { + if (context->options & PTRACE_O_TRACEVFORK) + event = PTRACE_EVENT_VFORK; + else if (context->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (context->options & PTRACE_O_TRACECLONE) + event = PTRACE_EVENT_CLONE; + } else if (context->options & PTRACE_O_TRACEFORK) { + event = PTRACE_EVENT_FORK; + } + /* + * Any of these reports implies auto-attaching the new child. + * So does CLONE_PTRACE, even with no event to report. + */ + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(parent, child, context->options); + + if (!event) + return UTRACE_RESUME; + + set_stop_code(context, event); + context->eventmsg = child->pid; + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; +} + +static inline void set_syscall_code(struct ptrace_context *context, int event) +{ + set_stop_code(context, event); + if (context->options & PTRACE_O_TRACESYSGOOD) + context->stop_code |= 0x80; +} + +static u32 ptrace_report_syscall_entry(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *context = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(context)); + + set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + + if (unlikely(context->options & PTRACE_O_SYSEMU)) { + if (test_thread_flag(TIF_SINGLESTEP)) + user_disable_single_step(task); + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + } + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (ptrace_event_pending(context)) + return UTRACE_STOP; + + set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + + return UTRACE_STOP; +} + +static u32 ptrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *context = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(context)); + + if (!(context->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, task, 0); + return UTRACE_RESUME; + } + + set_stop_code(context, PTRACE_EVENT_EXEC); + + return UTRACE_STOP; +} + +static enum utrace_signal_action resume_signal(struct task_struct *task, + int signr, siginfo_t *info, + struct k_sigaction *return_ka) +{ + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(&task->blocked, signr)) { + send_sig_info(signr, info, task); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[signr - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; +} + +static u32 ptrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct ptrace_context *context = ptrace_context(engine); + enum utrace_resume_action resume = context->resume; + + if (ptrace_event_pending(context)) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + if (WARN_ON(context->siginfo)) + context->siginfo = NULL; + + if (resume != UTRACE_RESUME) { + set_stop_code(context, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + case UTRACE_SIGNAL_REPORT: + if (!context->siginfo) + return resume | UTRACE_SIGNAL_IGN; + + if (WARN_ON(context->siginfo != info)) + return resume | UTRACE_SIGNAL_IGN; + context->siginfo = NULL; + + return resume | resume_signal(task, context->signr, + info, return_ka); + default: + WARN_ON(context->siginfo); + context->siginfo = info; + /* + * context->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); + + context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; + context->signr = info->si_signo; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } +} + +static u32 ptrace_report_quiesce(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + struct ptrace_context *context = ptrace_context(engine); + + if (ptrace_event_pending(context)) + return UTRACE_STOP; + + return event ? UTRACE_RESUME : context->resume; +} + +static void ptrace_release(void *data) +{ + kfree(data); +} + +static const struct utrace_engine_ops ptrace_utrace_ops = { + .report_signal = ptrace_report_signal, + .report_quiesce = ptrace_report_quiesce, + .report_exec = ptrace_report_exec, + .report_exit = ptrace_report_exit, + .report_clone = ptrace_report_clone, + .report_syscall_entry = ptrace_report_syscall_entry, + .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, +}; + +int ptrace_check_attach(struct task_struct *child, int kill) +{ + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret = -ESRCH; + + engine = ptrace_lookup_engine(child); + if (IS_ERR(engine)) + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + + if (!task_is_stopped_or_traced(child)) + goto out; + /* + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. + */ + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: + utrace_engine_put(engine); + return ret; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + retval = ptrace_attach_task(task, 0); + if (unlikely(retval)) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + + BUG_ON(task->ptrace); + task->ptrace = PT_UTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/** + * ptrace_traceme -- helper for PTRACE_TRACEME + * + * Performs checks and sets PT_UTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + bool detach = true; + int ret = ptrace_attach_task(current, 0); + + if (unlikely(ret)) + return ret; + + ret = -EPERM; + write_lock_irq(&tasklist_lock); + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_UTRACED; + __ptrace_link(current, current->real_parent); + detach = false; + } + write_unlock_irq(&tasklist_lock); + + if (detach) + ptrace_abort_attach(current); + return ret; +} + +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) +{ + bool detach, release; + + write_lock_irq(&tasklist_lock); + /* + * This tracee can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + detach = tracee->ptrace != 0; + release = false; + if (likely(detach)) + release = __ptrace_detach(current, tracee); + write_unlock_irq(&tasklist_lock); + + if (unlikely(release)) + release_task(tracee); + else if (likely(detach)) + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + for (;;) { + struct task_struct *tracee = NULL; + + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; + + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); + } +} + +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) +{ + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *context, + siginfo_t *info, bool write) +{ + unsigned long flags; + int err; + + switch (get_stop_event(context)) { + case 0: /* jctl stop */ + return -EINVAL; + + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *context->siginfo = *info; + else + *info = *context->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } + + return err; + + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = context->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } + + return 0; + } +} + +static void do_ptrace_notify_stop(struct ptrace_context *context, + struct task_struct *tracee) +{ + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ + tracee->exit_code = context->stop_code & PTRACE_EVENT_MASK; + WARN_ON(!tracee->exit_code); + + read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + preempt_enable_no_resched(); +} + +void ptrace_notify_stop(struct task_struct *tracee) +{ + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + + if (IS_ERR(engine)) { + // XXX: temporary check, wrong with mutlitracing + WARN_ON(tracee->state != TASK_RUNNING); + return; + } + + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); +} + +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) +{ + struct ptrace_context *context = ptrace_context(engine); + unsigned long events; + int action; + + context->options &= ~PTRACE_O_SYSEMU; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; + + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: + if (unlikely(!arch_has_block_step())) + return -EIO; + action = UTRACE_BLOCKSTEP; + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + context->options |= PTRACE_O_SYSEMU; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; + } + + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; + + return action; +} + +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) +{ + struct ptrace_context *context = ptrace_context(engine); + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + + switch (get_stop_event(context)) { + case PTRACE_EVENT_VFORK: + if (context->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(context, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + do_ptrace_notify_stop(context, tracee); + return 0; + } + /* fallthrough, but suppress send_sig_info() below */ + data = 0; + + case PTRACE_EVENT_SYSCALL_EXIT: + if (action != UTRACE_RESUME) { + read_lock(&tasklist_lock); + if (tracee->sighand) + send_sigtrap(tracee, task_pt_regs(tracee), + 0, TRAP_BRKPT); + read_unlock(&tasklist_lock); + action = UTRACE_RESUME; + } + /* fallthrough */ + + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + context->signr = data; + break; + + case 0: + // XXX: JCTL stop + break; + } + + context->resume = action; + ptrace_wake_up(tracee, engine, action, true); + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = generic_ptrace_pokedata(child, addr, data); + break; + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_set_options(child, engine, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(ptrace_context(engine)->eventmsg, + (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: +#endif +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: +#endif +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU: + case PTRACE_SYSEMU_SINGLESTEP: +#endif + case PTRACE_SYSCALL: + case PTRACE_CONT: + ret = ptrace_resume(child, engine, request, data); + break; + + case PTRACE_KILL: + ret = 0; + if (!child->exit_state) /* already dead */ + ret = ptrace_resume(child, engine, request, SIGKILL); + break; + + default: + ret = -EIO; + break; + } + + utrace_engine_put(engine); + return ret; +} + +#if defined CONFIG_COMPAT +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, + datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + utrace_engine_put(engine); + return ret; +} +#endif /* CONFIG_COMPAT */ From oleg at redhat.com Mon Oct 26 04:05:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 26 Oct 2009 05:05:35 +0100 Subject: [PATCH 0/7] utrace-ptrace V1 In-Reply-To: <20091026032839.GA6242@redhat.com> References: <20091026032839.GA6242@redhat.com> Message-ID: <20091026040535.GA8509@redhat.com> On 10/26, Oleg Nesterov wrote: > > For early review. > > Patches 1-5 can be sent upstream right now. The last 2 patches > add the new implementation. > > utrace.patch can come before or after, I think "after" is better. Forgot to mention, this series is against Linus's tree. Oleg. From news at voidcreations.org Mon Oct 26 08:22:31 2009 From: news at voidcreations.org (VOID CREATIONS) Date: Mon, 26 Oct 2009 09:22:31 +0100 Subject: FESTA DAS BRUXAS - Sabado 31 Outubro @ Santiago Alquimista Message-ID: Caso n?o consiga visualizar correctamente esta newsletter clique aqui. No pr?ximo 31 de Outubro, o Santiago Alquimista , junto ao Castelo de S. Jorge, prepara-se para receber uma noite arrepiante... A maior Festa das Bruxas de Lisboa vai fazer-se com todas as criaturas do Inferno: vampiros, duendes, fantasmas, goblins e fadas m?s que prometem assombrar a Costa do Castelo. Neste sabat, vamos festejar ? grande com CONCERTOS - ouviremos os uivos dos F.E.V.E.R., sussurros mal?volos dos Million Dollar Lips e ainda gritos assustadores dos Badlovers e Hysteria Iberika - muito BAILE - pela m?o do live act de Woman in Panic e o p? do DJ Serotonin - CINEMA e ainda as imagens de horror da VJ Psyberdoll. Todos estes ingredientes completam o feiti?o para uma noite inesquec?vel! A gruta do Castelo abrir? portas, depois do crep?sculo, ?s 21h30, com a exibi??o do filme de terror "H?xan" e no foyer do Santiago Alquimista, durante toda a noite, teremos uma mostra de vestu?rio, discos, joalharia, artesanato, cinema, um mini-est?dio fotogr?fico , maquilhagem tem?tica gratuita e aluguer de fatos. Toda a gente vai estar a rigor! A entrada ser? livre at? ?s 22h! A abertura das hostilidades em palco vai estar a cargo dos Million Dollar Lips. Este quarteto de Sesimbra, que se estreou recentemente com o ?lbum Lust, traz a sua excentricidade electro-pop com um cheirinho a David Bowie. Nas suas performances, onde n?o faltam bu?s de penas e muito glitter, revisitam oldies com todo o perfeccionismo das modernas tecnologias, ?s quais o vocalista Z empresta a voz e muito jogo de cintura. A estrear o single 'Ressurection' estar?o os lisboetas F.E.V.E.R. Este grupo da Amadora vem apresentar algumas das suas novas apostas para o cd de originais, Behold a Pale Horse, a ser lan?ado no Inverno de 2010. Auto-denominado grupo de sci-fi rock, os F.E.V.E.R prometem uma actua??o old school com guitarras, distor??o e montes de estilo. J? bem conhecidos do p?blico portugu?s, estar?o os Badlovers e Hysteria Iberika . Um franc?s, um portugu?s, uma espanhola e uma caixa de ritmos s?o mais do que suficientes para um espect?culo de rock n roll selvagem e cheio de energia, a que ningu?m fica indiferente. O trio vai encerrar o palco do Alquimista com o seu esp?rito rockeiro, de roupagem electro e doses de muita pervers?o e fantasia. Para o baile das bruxas, o Castelo vai receber as sonoridades electro de Woman in Panic e os 80's do DJ Serotonin , que alia uma presen?a peculiar aos sucessos desta d?cada, t?o pirosa quanto divertida. A anima??o visual estar? a cargo da VJ Psyberdoll . Info: Local: Santiago Alquimista Hora: A partir das 21h30 at? ?s 04h00 Morada: Rua de Santiago, n?19, 110-493 Lisboa Metro: Rossio / Baixa-Chiado / Martim Moniz Autocarros: 37 El?ctrico: 28 Comboio: Restauradores Mapa: Entrada: 5 ? Entrada livre at? 22h!!! Contactos: Void Creations E-mail: info at voidcreations.org @ Info adicional : www.voidcreations.org - ? favor divulgar - Para RE-ENVIAR / To FORWARD - http://www.divulgacaodigital.com/void-creations/?p=forward&uid=8796d6f78d5efbb8958965a0e70ab9c8&mid=3 Para REMOVER / To REMOVE - http://www.divulgacaodigital.com/void-creations/?p=unsubscribe&uid=8796d6f78d5efbb8958965a0e70ab9c8 Para MODIFICAR / To MODIFY - http://www.divulgacaodigital.com/void-creations/?p=preferences&uid=8796d6f78d5efbb8958965a0e70ab9c8 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From roland at redhat.com Mon Oct 26 08:46:46 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 26 Oct 2009 01:46:46 -0700 (PDT) Subject: [PATCH 115] (upstream) ptrace_init_task: cleanup the usage of ptrace_link() In-Reply-To: Oleg Nesterov's message of Saturday, 24 October 2009 01:21:02 +0200 <20091023232102.GA26899@redhat.com> References: <20091023232102.GA26899@redhat.com> Message-ID: <20091026084646.1F6FA1E@magilla.sf.frob.com> I think you can send this one upstream right away with no controversy. It does pure cleanup. (Is it even needed for utrace in particular?) Acked-by: Roland McGrath Thanks, Roland From info at campaigns.canal-marketing.com Mon Oct 26 13:07:25 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Luxe_Priv=E9?=) Date: Mon, 26 Oct 2009 14:07:25 +0100 Subject: =?iso-8859-1?q?Invitation_Vente_Priv=E9e?= Message-ID: An HTML attachment was scrubbed... URL: From speedpro at bol.com.br Tue Oct 27 01:36:35 2009 From: speedpro at bol.com.br (Adriana Menezes) Date: Tue, 27 Oct 2009 01:36:35 GMT Subject: Aumento_Natural Message-ID: <200910270141.n9R1flqd003398@mx1.redhat.com> An HTML attachment was scrubbed... URL: From ananth at in.ibm.com Tue Oct 27 04:37:09 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 27 Oct 2009 10:07:09 +0530 Subject: [PATCH 6/7] introduce kernel/ptrace.h In-Reply-To: <20091026032852.GA6270@redhat.com> References: <20091026032852.GA6270@redhat.com> Message-ID: <20091027043708.GA10792@in.ibm.com> On Mon, Oct 26, 2009 at 04:28:52AM +0100, Oleg Nesterov wrote: > No functional changes, preparation for utrace-ptrace. > > Introduce kernel/ptrace.h and move the code which can be shared > with the new implementation into this new header. Did you want this to be a .h? Couldn't this just be a ptrace-common.c whose functions can be called from ptrace.c, while a ptrace-common.h can have the function definitions? Ananth From srikar at linux.vnet.ibm.com Tue Oct 27 06:56:10 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 27 Oct 2009 12:26:10 +0530 Subject: [PATCH 3/7] ptrace_init_task: cleanup the usage of ptrace_link() In-Reply-To: <20091026032846.GA6256@redhat.com> References: <20091026032846.GA6256@redhat.com> Message-ID: <20091027065610.GB14650@linux.vnet.ibm.com> * Oleg Nesterov [2009-10-26 04:28:46]: > @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru > INIT_LIST_HEAD(&child->ptraced); > child->parent = child->real_parent; > child->ptrace = 0; > - if (unlikely(ptrace)) { > + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { Any reason for directly accessing current->ptrace instead of accessing thro task_ptrace(current) ? Also would something like this suffice. + if (unlikely(ptrace) && (task_ptrace(current)) { i.e the first patch in this series removes checks to see if ptrace field is set with PT_TRACED. "task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill some PT_PTRACED checks in tracehook.h." Can you please explain how this situation is different from the situation in tracehook.h? > child->ptrace = current->ptrace; -- Thanks and Regards Srikar From info at campaigns.canal-marketing.com Tue Oct 27 13:00:06 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?IC_Telecom?=) Date: Tue, 27 Oct 2009 14:00:06 +0100 Subject: =?iso-8859-1?q?T=E9l=E9com_PRO_tout_en_un_=3A_29_Euros?= Message-ID: An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Oct 27 19:56:42 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 12:56:42 -0700 (PDT) Subject: [PATCH 118] (upstream) introduce kernel/ptrace.h In-Reply-To: Oleg Nesterov's message of Monday, 26 October 2009 03:24:06 +0100 <20091026022406.GA28102@redhat.com> References: <20091026022406.GA28102@redhat.com> Message-ID: <20091027195642.2472D8D1@magilla.sf.frob.com> I'm skeptical this is the desireable way to move the code around. Of course, for all such things, I am fine with whatever upstream likes. But here are my concerns: That is not friendly to git history at all. If you move big chunks of code to different files, it's ideal to do it in a sequence of changes wherein the git file rename detection will grok what you are doing. With big cut and paste changes like this, it winds up looking like you introduced all the moved old code today. It takes manual looking and poking with git to see you moved it out of another file in this commit and then "git annotate this~1 -- kernel/ptrace.c" to find the commits that are really responsible for each line of code. I don't see how this route is any better than having the new and old code in kernel/ptrace.c with #ifdef. Conversely, just leave the common code in ptrace.c and compile it there. AFAICT the only static function that would need to be made global for that is __ptrace_detach. Thanks, Roland From oleg at redhat.com Tue Oct 27 19:52:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 27 Oct 2009 20:52:53 +0100 Subject: [PATCH 3/7] ptrace_init_task: cleanup the usage of ptrace_link() In-Reply-To: <20091027065610.GB14650@linux.vnet.ibm.com> References: <20091026032846.GA6256@redhat.com> <20091027065610.GB14650@linux.vnet.ibm.com> Message-ID: <20091027195253.GA6650@redhat.com> On 10/27, Srikar Dronamraju wrote: > > * Oleg Nesterov [2009-10-26 04:28:46]: > > > @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru > > INIT_LIST_HEAD(&child->ptraced); > > child->parent = child->real_parent; > > child->ptrace = 0; > > - if (unlikely(ptrace)) { > > + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { > > Any reason for directly accessing current->ptrace instead of accessing > thro task_ptrace(current) ? Yes, we can use task_ptrace(), but we don't use this helper in ptrace.h. In fact it should die. Initially it was introduced for tracehooks, then it was overloaded (by me). Currently it is used to read task->ptrace flags, and to check the task is traced, iow to check task_ptrace() != 0. Not good. > Also would something like this suffice. > + if (unlikely(ptrace) && (task_ptrace(current)) { No. The whole point (apart from cleanup) is to add PT_PTRACED check. Currently, task_ptrace() != 0 means that PT_PTRACED must be set, so we could use task_ptrace() != 0. But with utrace-ptrace, task_ptrace() != 0 means the task is ptraced, while PT_PTRACED is not set. IOW, PT_PTRACED is only true when !CONFIG_UTRACE. With utrace-ptrace, ptrace_init_task() must not auto-attach the new child, that is why we check PT_PTRACED. Please note that, once the old implementation is removed (when CONFIG_UTRACE goes away) we can just kill allmost all tracehooks from do_fork() path. They are only needed for the old implementation. > i.e the first patch in this series removes checks to see if ptrace field > is set with PT_TRACED. > "task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill > some PT_PTRACED checks in tracehook.h." Yes, but see above. And the first patch ensures that, say, tracehook_tracer_task() works correctly regardless of CONFIG_UTRACE. Again, this all is only needed because we have two implementations until CONFIG_UTRACE goes away. Oleg. From roland at redhat.com Tue Oct 27 20:18:30 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 13:18:30 -0700 (PDT) Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: Oleg Nesterov's message of Saturday, 24 October 2009 01:20:57 +0200 <20091023232057.GA26888@redhat.com> References: <20091023232057.GA26888@redhat.com> Message-ID: <20091027201830.A18D17CDF@magilla.sf.frob.com> [I have no idea why you appended this to that message introducing patches that are not related to this at all. Please use separate threads for separate topics, and choose clearly apropos Subject: lines.] > I am thinking how can we fix utrace_control(SINGLESTEP). I don't > have good ideas so far. But, perhaps we can add > utrace->please_enable_single_step:1 ? If anything like this, it would be an enum utrace_resume_action field. Otherwise you are changing the API fundamentally. > utrace_stop() and utrace_finish_jctl() can check this flag after wakeup What you mean here is an API where utrace_control's choice of resume_action takes effect without further callbacks when nothing else has requested any. As always, I want a discussion of the API semantics to be clear and separate from implementation details. > Or, we can use ENGINE_SINGLESTEP, which probably makes more sense. > Like ENGINE_STOP, it lives both in engine->flags and ->utrace_flags. This takes us back to the old old utrace API where we had sticky state bits for the things that are now represented in utrace_resume_action. That is a very bad API choice IMHO, and its inherent unpleasantnesses are why we abandoned it before. > I no longer think utrace_control() should just turn SINGLESTEP into > REPORT silently. IMHO this characterization misrepresents what the API is today, and glosses over the real complexities that are why it is that way. There is no "silent" about it. If things are going on that affect what you asked for, then you get a callback to decide what you really want. The inability to react to other engines' effects this way was one of the major failings of the old "sticky action bits" API. The other thing that was completely wrong about sticky "action state bits" for single-step and block-step is that they are inherently just not sticky states. Each is a one-shot action that leads to a single provoked event (at most). It just doesn't make sense to represent them as states. Thanks, Roland From roland at redhat.com Tue Oct 27 21:19:02 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 14:19:02 -0700 (PDT) Subject: [RFC, PATCH 0/2] Was: problem: utrace-ptrace && jctl stacked stop In-Reply-To: Oleg Nesterov's message of Thursday, 22 October 2009 23:35:16 +0200 <20091022213516.GA19889@redhat.com> References: <20090917173040.GA10129@redhat.com> <20090917191405.GA25722@redhat.com> <20090918094947.F3D5E278D@magilla.sf.frob.com> <20091022213516.GA19889@redhat.com> Message-ID: <20091027211902.962C28D1@magilla.sf.frob.com> > No. I don't see how we can fix this without some changes in utrace. Ok. I think we could come up with more contortions to cope with do_signal_stop happening before the pending UTRACE_STOP processing. But in the general case it's fundamentally a race. It doesn't matter if we invert the outcome of that race in some cases. So I see nothing really wrong with doing the utrace "pre-signal safe point" before job control processing. Assuming well-behaved callbacks, all that matters is that we do the job control bookkeeping for UTRACE_STOP (which we do). > Just in case, let me remind you what is the problem. For simplicity, > let's ignore SIGKILL issues, and let's discuss this particular case: > > a PTRACE_O_TRACESYSGOOD tracee reports SYSCALL_ENTRY and stops. > > the tracer does > > ptrace(PTRACE_SYSCALL); > > // we must have SYSCALL_EXIT report > waitpid(&state); > > assert(state == 0x857F); <--- 1 > assert(ptrace(PTRACE_GETEVENTMSG) == 0); <--- 2 > > This must always work, both 1 and 2 asserts are valid. (but, for the > moment, please forget about 2). > > However, with utrace-ptrace the tracee can notice ->group_stop_count and > call do_signal_stop() before it has a chance to do finish_resume_report() > and actually stop. This breaks the 1st assert. Though I described the general case as a race, this particular scenario can arise with no actual racing. During the syscall-entry stop, userland can synchronously invoke the job control stop (SIGSTOP to another thread, etc.) before it ptrace-resumes the traced thread. In that case we know (at the utrace API level) that the job control stop in truth precedes any later UTRACE_STOPs we provoke after resuming from the syscall-entry stop. But I don't have any problem with saying that the "handle MT job control normally" semantics just always take place at the same time/sequence where "delivering pending signals normally" takes places. That is, after UTRACE_SIGNAL_REPORT can choose UTRACE_STOP. > Agreed, I thought about this too. IOW, we can just silently drop this > JCTL stop event and report SYSCALL_EXIT instead. Right. > So, we add ptrace_report_jctl(notify) which does > > if (notify == CLD_STOPPED) { > if (get_stop_event(context)) { > // pretend we we already stopped when another > // thread initiated this group-stop, set the > // correct ->exit_code and return, our tracer > // will be notified by do_signal_stop() > > task->exit_code = context->stop_code & PTRACE_EVENT_MASK; > return; should be: return UTRACE_STOP; > Unfortunately, this doesn't help. Because the tracee will stop in > TASK_STOPPED state, and this means SIGCONT can break the 2nd assert > above. Yes and no. When a report_jctl hook returns UTRACE_STOP, then you expect it to wind up in TASK_TRACED before it gets back to user mode. It will do that here too, but not quite how you might expect. It will set TIF_NOTIFY_RESUME, then go into TASK_STOPPED and stay there until SIGCONT, then wake up, run until report_quiesce(0) or report_signal where your callback can return UTRACE_STOP again. But that's fine. Staying truly stopped throughout rather than waking and stopping again differently only matters if there is an examination in progress. So the only question is the interim where it was in TASK_STOPPED. If ptrace_check_attach() uses utrace_control here, then it will turn that TASK_STOPPED into TASK_TRACED and thus exclude any SIGCONT problem. > This is the problem. Since do_signal_stop() sets TASK_STOPPED, we > can't report anything but JCTL event. It looks funny if you can tell (i.e. /proc/pid/status) that it is in TASK_STOPPED rather than TASK_TRACED. But aside from that, who can tell? > And it is not possible to > hack do_signal_stop() so that it sets TASK_TRACED if the debugger > has changed task->exit_code (or context->exit_code or whatever). Anything is possible! ;-) What would make sense, if anything, is to go into TASK_TRACED instead of TASK_STOPPED when UTRACE_STOP is in use. That seems entirely doable with another rejiggering of the tracehook call interface there. But all that's just as devil's advocate. I don't see any problem with changing the order of do_signal_stop vs utrace_get_signal as you want. > Please see the patches. They are very simple. Yeah, it looks about fine to me. > Perhaps, it makes sense to do more. We can introduce the new > UTRACE_SIGNAL_JCTL utrace_signal_action, but I don't think it is > really needed. I don't understand what that would mean. Thanks, Roland From oleg at redhat.com Tue Oct 27 21:29:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 27 Oct 2009 22:29:48 +0100 Subject: [PATCH 118] (upstream) introduce kernel/ptrace.h In-Reply-To: <20091027195642.2472D8D1@magilla.sf.frob.com> References: <20091026022406.GA28102@redhat.com> <20091027195642.2472D8D1@magilla.sf.frob.com> Message-ID: <20091027212948.GA10087@redhat.com> On 10/27, Roland McGrath wrote: > > I'm skeptical this is the desireable way to move the code around. > Of course, for all such things, I am fine with whatever upstream likes. > But here are my concerns: I am not sure this is the best choice too. > That is not friendly to git history at all. Yes, I agree completely. > If you move big chunks of code > to different files, it's ideal to do it in a sequence of changes wherein > the git file rename detection will grok what you are doing. Not sure I understand. Do you mean it is possible to move the code from the old file to the new one in a git-friendly manner? Afaics, there is no way to do this, git can only hanlde renames. (but my git skills is close to zero). > I don't see how this route is any better than having the new and old code > in kernel/ptrace.c with #ifdef. This is what I'd like to avoid as much as possible. As usual, this is very subjective, but imho this way it will be very difficult to read the code, even if we have a single ifdef which separates the old and new implementation. Say, not good to have 2 almost identical ptrace_attach() implementations in the same file. Instead of the single ifdef, we can add a lot of them. For example, as for ptrace_attach() we can do int ptrace_attach(struct task_struct *task) { int retval; audit_ptrace(task); retval = -EPERM; if (unlikely(task->flags & PF_KTHREAD)) goto out; if (same_thread_group(task, current)) goto out; /* * Protect exec's credential calculations against our interference; * interference; SUID, SGID and LSM creds get determined differently * under ptrace. */ retval = -ERESTARTNOINTR; if (mutex_lock_interruptible(&task->cred_guard_mutex)) goto out; task_lock(task); retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); task_unlock(task); if (retval) goto unlock_creds; #ifdef CONFIG_UTRACE retval = ptrace_attach_task(task, 0); if (unlikely(retval)) goto unlock_creds; #endif write_lock_irq(&tasklist_lock); retval = -EPERM; if (unlikely(task->exit_state)) goto unlock_tasklist; #ifdef CONFIG_UTRACE BUG_ON(task->ptrace); task->ptrace = PT_UTRACED; #else if (task->ptrace) goto unlock_tasklist; task->ptrace = PT_PTRACED; #endif if (capable(CAP_SYS_PTRACE)) task->ptrace |= PT_PTRACE_CAP; __ptrace_link(task, current); send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); retval = 0; unlock_tasklist: write_unlock_irq(&tasklist_lock); unlock_creds: mutex_unlock(&task->cred_guard_mutex); out: return retval; } but this is much, much worse and guess you didn't mean this. > Conversely, just leave the common code in > ptrace.c and compile it there. AFAICT the only static function that would > need to be made global for that is __ptrace_detach. OK, agreed, this can work too. In this case kernelptrace.c becomes ... the context of kernel/ptrace-common.h ... #ifndef CONFIG_UTRACE ... other code ... #endif and we don't need CONFIG_PTRACE_OLD. Do you agree with approach? Oleg. From oleg at redhat.com Tue Oct 27 23:08:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 00:08:38 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091027201830.A18D17CDF@magilla.sf.frob.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> Message-ID: <20091027230838.GA12313@redhat.com> On 10/27, Roland McGrath wrote: > > [I have no idea why you appended this to that message introducing patches > that are not related to this at all. Please use separate threads for > separate topics, and choose clearly apropos Subject: lines.] OK. > > I am thinking how can we fix utrace_control(SINGLESTEP). I don't > > have good ideas so far. But, perhaps we can add > > utrace->please_enable_single_step:1 ? > > If anything like this, it would be an enum utrace_resume_action field. > Otherwise you are changing the API fundamentally. Not sure I understand... This is like utrace->vfork_stop:1, it is only visible to utrace code. > > utrace_stop() and utrace_finish_jctl() can check this flag after wakeup > > What you mean here is an API where utrace_control's choice of resume_action > takes effect without further callbacks when nothing else has requested any. > As always, I want a discussion of the API semantics to be clear and > separate from implementation details. Yes. please see below. > > Or, we can use ENGINE_SINGLESTEP, which probably makes more sense. > > Like ENGINE_STOP, it lives both in engine->flags and ->utrace_flags. > > This takes us back to the old old utrace API where we had sticky state > bits for the things that are now represented in utrace_resume_action. > That is a very bad API choice IMHO, and its inherent unpleasantnesses > are why we abandoned it before. Agreed. I tried to think about ENGINE_SINGLESTEP more and came to the same conclusion. So. I am still not sure this is the best solution (in fact this doesn't even look like a good solution to me), but afaics we can preserve the current API and fix the problem if we add utrace->set_singlestep and utrace->set_blockstep. utrace_control() case UTRACE_RESUME: if (likely(reset)) { user_disable_single_step(target); utrace->set_singlestep = utrace->set_blockstep = 0; } break; case UTRACE_SINGLESTEP: if (likely(reset)) utrace->set_singlestep = true; else ret = -EAGAIN; break; void utrace_finish_stop(...) { if (!(utrace->stop || utrace->set_singlestep)) return; set_singlestep = utrace->set_singlestep; spin_lock(&utrace->lock); utrace->stopped = trace->set_singlestep = false; spin_unlock(&utrace->lock); if (set_singlestep) user_enable_single_step(current); } utrace_finish_jctl() and utrace_stop() should call this new helper instead of "if (utrace->stopped) {}" code. > > I no longer think utrace_control() should just turn SINGLESTEP into > > REPORT silently. > > IMHO this characterization misrepresents what the API is today, and > glosses over the real complexities that are why it is that way. > > There is no "silent" about it. If things are going on that affect what > you asked for, then you get a callback to decide what you really want. > The inability to react to other engines' effects this way was one of the > major failings of the old "sticky action bits" API. Yes I see. And I agree, the current behaviour of utrace_control(SINGLESTEP) which ->set_blockstep hack tries to preserve is not very good. As for ptrace. If utrace_control(SINGLESTEP) doesn't set TIF_SINGLESTEP, then we need more (probably nasty) changes. report_quiesce/interrupt should somehow figure out whether we need send_sigtrap() if ->resume == XXXSTEP. So. What do you think we should do for V1 ? Oleg. From roland at redhat.com Tue Oct 27 23:14:51 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 16:14:51 -0700 (PDT) Subject: [PATCH 0/7] utrace-ptrace V1 In-Reply-To: Oleg Nesterov's message of Monday, 26 October 2009 04:28:39 +0100 <20091026032839.GA6242@redhat.com> References: <20091026032839.GA6242@redhat.com> Message-ID: <20091027231451.8C90E7CE4@magilla.sf.frob.com> 5/7 belongs first and I've already merged it as prerequisite to utrace. We can send that upstream without delay. I hope it can get queued quickly regardless of the review delays for the utrace and ptrace work. All the other "preparatory" patches are just to introduce PT_PTRACED as the distinction between the obsolete hooks for old ptrace and the remaining ptrace-specific kludges (unsafe_exec, tracer_task, and the interference with SIGCHLD/wait semantics). IMHO it's pretty questionable to do that rather than test those statically such that under CONFIG_UTRACE the old hooks are compiled away entirely (either via #ifdef or via things that reduce to "if (0)"). But moreover, this is fritter in the details of coexistence with the old implementation or sequencing of phasing it out. I really have no idea what the acceptable path for that is going to be at all. In the past, upstream reactions have ranged from "utrace never!" to "no options, have only the utrace-based ptrace exist at all". I don't know that anyone is positively in favor of conditionally having two ptrace implementations, except perhaps as a compromise position for those who would prefer us to jump in the lake and never propose utrace again. I'm not at all sure that there isn't any one of the people with de facto veto power who will be dead-set against ever having both in the source at the same time. I don't think we can answer that except in the actual upstream review. So if this is v1 for upstream review, then take this path or whatever other makes for the necessary fritter being easiest to read (which is usually perceived upstream to mean least patch text) and get on with it. Thanks, Roland From roland at redhat.com Tue Oct 27 23:14:48 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 16:14:48 -0700 (PDT) Subject: [PATCH 118] (upstream) introduce kernel/ptrace.h In-Reply-To: Oleg Nesterov's message of Tuesday, 27 October 2009 22:29:48 +0100 <20091027212948.GA10087@redhat.com> References: <20091026022406.GA28102@redhat.com> <20091027195642.2472D8D1@magilla.sf.frob.com> <20091027212948.GA10087@redhat.com> Message-ID: <20091027231448.C17BE8D1@magilla.sf.frob.com> > Not sure I understand. Do you mean it is possible to move the code from > the old file to the new one in a git-friendly manner? Afaics, there is no > way to do this, git can only hanlde renames. (but my git skills is close > to zero). What I meant is a sequence of patches like: 1. move non-common code from ptrace.c to ptrace-old.c 2. rename ptrace.c to ptrace.h 3. rename ptrace-old.c to ptrace.c or numerous other sequences that have that property, where one of the steps in the sequence renames a file without changing it. (That example is not a particularly good idea.) > This is what I'd like to avoid as much as possible. As usual, this is very > subjective, but imho this way it will be very difficult to read the code, > even if we have a single ifdef which separates the old and new implementation. > Say, not good to have 2 almost identical ptrace_attach() implementations in > the same file. I agree that's ugly. > Instead of the single ifdef, we can add a lot of them. For example, as for > ptrace_attach() we can do Opinions also vary on whether that is more or less ugly. For some reason there seems to be a preference upstream for repeating identical declarations on both sides of an #ifdef over putting an #ifdef inside a function. I don't really get it. > In this case kernelptrace.c becomes > > ... the context of kernel/ptrace-common.h ... > > #ifndef CONFIG_UTRACE > ... other code ... > #endif > > and we don't need CONFIG_PTRACE_OLD. > > Do you agree with approach? That's what I had in mind. But I'm almost sorry I raised the issue. I don't think there is much benefit to debating these details amongst ourselves. The right answer is whatever the upstream reviewers demand. You and I just want something merged ASAP and all the nits are secondary. Thanks, Roland From oleg at redhat.com Tue Oct 27 23:38:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 00:38:20 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091027230838.GA12313@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> Message-ID: <20091027233820.GA17255@redhat.com> On 10/28, Oleg Nesterov wrote: > > As for ptrace. If utrace_control(SINGLESTEP) doesn't set TIF_SINGLESTEP, > then we need more (probably nasty) changes. report_quiesce/interrupt should > somehow figure out whether we need send_sigtrap() if ->resume == XXXSTEP. Or. We can add the hack below for V1, then fix/cleanup this. Oleg. --- a/kernel/ptrace-utrace.c +++ b/kernel/ptrace-utrace.c @@ -227,6 +227,14 @@ static void ptrace_wake_up(struct task_s } } + // XXX!!! temporary hack. + // this and ptrace_resume()->send_sigtrap() + // should not exist !!! + if (action = UTRACE_SINGLESTEP) + user_enable_single_step(tracee); + else if (action = UTRACE_BLOCKSTEP) + user_enable_block_step(tracee); + if (action != UTRACE_REPORT) ptrace_context(engine)->stop_code = 0; utrace_control(tracee, engine, action); From oleg at redhat.com Tue Oct 27 23:43:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 00:43:00 +0100 Subject: [PATCH 118] (upstream) introduce kernel/ptrace.h In-Reply-To: <20091027231448.C17BE8D1@magilla.sf.frob.com> References: <20091026022406.GA28102@redhat.com> <20091027195642.2472D8D1@magilla.sf.frob.com> <20091027212948.GA10087@redhat.com> <20091027231448.C17BE8D1@magilla.sf.frob.com> Message-ID: <20091027234300.GB17255@redhat.com> On 10/27, Roland McGrath wrote: > > > In this case kernelptrace.c becomes > > > > ... the context of kernel/ptrace-common.h ... > > > > #ifndef CONFIG_UTRACE > > ... other code ... > > #endif > > > > and we don't need CONFIG_PTRACE_OLD. > > > > Do you agree with approach? > > That's what I had in mind. OK, will do. > The right answer is whatever the upstream reviewers demand. Which we can't predict. But your suggestion looks more simple and clean. Especially because we can avoid CONFIG_PTRACE_OLD. > You and I just want something merged ASAP and all the nits are secondary. Yes ;) Oleg. From roland at redhat.com Tue Oct 27 23:55:57 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 16:55:57 -0700 (PDT) Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: Oleg Nesterov's message of Wednesday, 28 October 2009 00:08:38 +0100 <20091027230838.GA12313@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> Message-ID: <20091027235557.143CD8D1@magilla.sf.frob.com> > Not sure I understand... This is like utrace->vfork_stop:1, it is > only visible to utrace code. Show me the change the the utrace_control kerneldoc wording that makes it match what difference you propose this implementation detail would make. When you consider other engines using UTRACE_BLOCKSTEP and all other such interactions, I think you'll find that there isn't a clean API description that could be implemented using a flag like you suggested. > So. I am still not sure this is the best solution (in fact this doesn't > even look like a good solution to me), but afaics we can preserve the > current API and fix the problem if we add utrace->set_singlestep and > utrace->set_blockstep. This approach loses the existing possibility e.g. for an engine that tried UTRACE_BLOCKSTEP to find out that an earlier engine is already using UTRACE_SINGLESTEP and so the stop it gets next won't necessarily be at a block boundary. As I alluded to before, the version of this approach that seems like it could be clean is to store an enum utrace_resume_action rather than a flag (or two flags). Thinking about it more, my intuition is that this could be the way to go. This field could also replace the report and interrupt bits we have now, and that starts to feel clean. In fact, with a broader view it might not even be desireable to do user_enable_single_step in the tracer rather than the tracee. I always thought of it as desireable because it is how ptrace does it now, and I recalled that on one arch (s390) enabling single-step has to fiddle CPU state that is normally set by context switch--so on that machine, it has to do an extra state-fiddle step to enable in self after context switch. But, on at least as many machines (x86, score) it could be advantageous to enable in self rather than enable from tracer. (On all the other machines, it really doesn't matter--it's just purely in register bits like you would expect.) Those two use access_process_vm to look at the PC instruction, and we could (later) optimize those to use copy_from_user when called on current, which has much lower overhead. So I now have reversed in complementary directions. As to the API, I do think it would be nice to avoid always getting a callback when there really is nothing else going on--though I still insist engines are broken if they don't have one so they can react to other engines' actions. But as to the mechanics, I now think we should favor calling user_enable_single_step et al in current rather than not. > As for ptrace. If utrace_control(SINGLESTEP) doesn't set TIF_SINGLESTEP, > then we need more (probably nasty) changes. report_quiesce/interrupt should > somehow figure out whether we need send_sigtrap() if ->resume == XXXSTEP. I may have lost the plot again, sorry. You're talking about the case of PTRACE_SINGLESTEP at a syscall-exit stop, which is not even consistent across machines in the vanilla kernel. Right? Thanks, Roland From oleg at redhat.com Wed Oct 28 00:08:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 01:08:02 +0100 Subject: [PATCH 0/7] utrace-ptrace V1 In-Reply-To: <20091027231451.8C90E7CE4@magilla.sf.frob.com> References: <20091026032839.GA6242@redhat.com> <20091027231451.8C90E7CE4@magilla.sf.frob.com> Message-ID: <20091028000802.GC17255@redhat.com> On 10/27, Roland McGrath wrote: > > 5/7 belongs first and I've already merged it as prerequisite to utrace. > We can send that upstream without delay. I hope it can get queued quickly > regardless of the review delays for the utrace and ptrace work. Agreed, I'll send it to Andrew. > All the other "preparatory" patches are just to introduce PT_PTRACED as the > distinction between the obsolete hooks for old ptrace and the remaining > ptrace-specific kludges (unsafe_exec, tracer_task, and the interference > with SIGCHLD/wait semantics). Yes. And, although you didn't say this, I completely agree: this is dirty hack. > IMHO it's pretty questionable to do that > rather than test those statically such that under CONFIG_UTRACE the old > hooks are compiled away entirely (either via #ifdef or via things that > reduce to "if (0)"). Agreed! Hopefully we can do this later. As you understand, the goal is to make the first series as small as possible, where "small" means the number of changes outside of ptrace.c. > But moreover, this is fritter in the details of coexistence with the old > implementation or sequencing of phasing it out. I really have no idea > what the acceptable path for that is going to be at all. In the past, > upstream reactions have ranged from "utrace never!" to "no options, have > only the utrace-based ptrace exist at all". Yes. CONFIG_UTRACE should go away, but when this will happen? We have to fix !HAVE_ARCH_TRACEHOOK arches first and to ensure bobody in arch/ plays with ptrace internals. > I don't know that anyone is > positively in favor of conditionally having two ptrace implementations, At least, we don't have CONFIG_UTRACE_PTRACE. > I don't think we can answer that except in the actual upstream review. Yep. > So if this is v1 for upstream review, Yes, I hope so. Oleg. From oleg at redhat.com Wed Oct 28 01:06:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 02:06:48 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091027235557.143CD8D1@magilla.sf.frob.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> Message-ID: <20091028010648.GA18669@redhat.com> On 10/27, Roland McGrath wrote: > > > Not sure I understand... This is like utrace->vfork_stop:1, it is > > only visible to utrace code. > > Show me the change the the utrace_control kerneldoc wording that makes it > match what difference you propose this implementation detail would make. > When you consider other engines using UTRACE_BLOCKSTEP and all other such > interactions, I think you'll find that there isn't a clean API description > that could be implemented using a flag like you suggested. Again, I don't understand. Let me repeat, I tried to propose something that do not make any visible difference except fixes the problem with get_user_pages() under spin_lock(). And yes, while I don't pretend I know what should be done, I agree the current API (I don't mean the documentation, I mean the actual code) is not right. > > So. I am still not sure this is the best solution (in fact this doesn't > > even look like a good solution to me), but afaics we can preserve the > > current API and fix the problem if we add utrace->set_singlestep and > > utrace->set_blockstep. > > This approach loses the existing possibility e.g. for an engine that tried > UTRACE_BLOCKSTEP to find out that an earlier engine is already using > UTRACE_SINGLESTEP and so the stop it gets next won't necessarily be at a > block boundary. Afaics, the current code can't work properly in this case anyway. But yes, the pseudo-code I showed is not complete, it was only to roughly explain what I mean. > As I alluded to before, the version of this approach that seems like it > could be clean is to store an enum utrace_resume_action rather than a flag > (or two flags). Thinking about it more, my intuition is that this could be > the way to go. This field could also replace the report and interrupt bits > we have now, and that starts to feel clean. At firts glance, this looks right to me. > In fact, with a broader view it might not even be desireable to do > user_enable_single_step in the tracer rather than the tracee. I agree. But I can't explain why I agree ;) I mean, I feel this should be more clean, but given that I do not understand the low level details even remotely I can't judge. > Those two use access_process_vm to look at the PC instruction, > and we could (later) optimize those to use copy_from_user when called on > current, which has much lower overhead. Yes, I thought about this too. > So I now have reversed in complementary directions. As to the API, I do > think it would be nice to avoid always getting a callback when there really > is nothing else going on--though I still insist engines are broken if they > don't have one so they can react to other engines' actions. But as to the > mechanics, I now think we should favor calling user_enable_single_step et > al in current rather than not. OK. Unless I misunderstand "avoid always getting a callback" above, this means the tracee should call enable_step() after wakeup in utrace_stop(), yes? In this case ptrace doesn't need any changes for now. > > As for ptrace. If utrace_control(SINGLESTEP) doesn't set TIF_SINGLESTEP, > > then we need more (probably nasty) changes. report_quiesce/interrupt should > > somehow figure out whether we need send_sigtrap() if ->resume == XXXSTEP. > > I may have lost the plot again, sorry. You're talking about the case of > PTRACE_SINGLESTEP at a syscall-exit stop, which is not even consistent > across machines in the vanilla kernel. Right? Not necessary in syscall-exit stop, but yes. And yes, this is not even consistent across machines (as you explained before), that is why I am very nervous when I think about the changes in this area. Oleg. From oleg at redhat.com Wed Oct 28 01:28:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 28 Oct 2009 02:28:13 +0100 Subject: [PATCH 6/7] introduce kernel/ptrace.h In-Reply-To: <20091027043708.GA10792@in.ibm.com> References: <20091026032852.GA6270@redhat.com> <20091027043708.GA10792@in.ibm.com> Message-ID: <20091028012813.GA21926@redhat.com> On 10/27, Ananth N Mavinakayanahalli wrote: > > On Mon, Oct 26, 2009 at 04:28:52AM +0100, Oleg Nesterov wrote: > > No functional changes, preparation for utrace-ptrace. > > > > Introduce kernel/ptrace.h and move the code which can be shared > > with the new implementation into this new header. > > Did you want this to be a .h? Couldn't this just be a ptrace-common.c > whose functions can be called from ptrace.c, while a ptrace-common.h can > have the function definitions? I think Roland has a better idea, hopefully you read this discussion. Oleg. From roland at redhat.com Wed Oct 28 02:30:58 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 19:30:58 -0700 (PDT) Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: Oleg Nesterov's message of Wednesday, 28 October 2009 02:06:48 +0100 <20091028010648.GA18669@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> Message-ID: <20091028023058.7A6A37CDF@magilla.sf.frob.com> > Again, I don't understand. Let me repeat, I tried to propose something > that do not make any visible difference except fixes the problem with > get_user_pages() under spin_lock(). Ok. > And yes, while I don't pretend I know what should be done, I agree the > current API (I don't mean the documentation, I mean the actual code) is > not right. The behavior is fine in practice, it's just that the lockdep rules are violated (and that's indeed horribly wrong in the cases that matter, which are vanishingly rare in real-world practice). > I agree. But I can't explain why I agree ;) I mean, I feel this should be > more clean, but given that I do not understand the low level details even > remotely I can't judge. What level of details don't you understand? I hope you understand everything in utrace.c! Speaking of which, it really looks like it's already the case now that ->stopped exactly matches task_is_traced(). I know we discussed this before and put it off. But I'm just looking again now, and it seems fairly clear. Even without getting the deep logic clear in my head, it looks pretty solid just from local inspection that they match. Do you agree? In fact, as I count them, 8 of 10 uses of ->stopped are purely to reconcile the bookkeeping so it will match task_is_traced(). > OK. Unless I misunderstand "avoid always getting a callback" above, this > means the tracee should call enable_step() after wakeup in utrace_stop(), > yes? Something like that, yes. > And yes, this is not even consistent across machines (as you explained > before), that is why I am very nervous when I think about the changes > in this area. Ok. I think this is a corner where we will have some play in cleaning up and unifying the behavior upstream without much complaint. In the status quo, x86 passes only 0 to tracehook_report_syscall_exit and will synthesize a SIGTRAP only if TIF_SINGLESTEP is set on its return (i.e. the last call user_enable_*_step was after the last call to user_disable_single_step). Other machines either pass step=1 when user_enable_*_step had been used to reach tracehook_report_syscall_exit and do nothing else, or pass step=0 and have no other related checks I can see. For us, step=1 doesn't really give any new information. It means PTRACE_{SINGLE,BLOCK}STEP was used to hit the syscall insn (or used after PTRACE_SYSCALL stopped for syscall-entry). But now ptrace_context.resume tells us that if we check it. So, if nothing else, we can do user_disable_single_step somewhere inside tracehook_report_syscall_exit to disarm the x86 code and then behave uniformly across machines inside there. But, the x86 maintainers are generally friendly to our changes if we are clear about their purpose. On all those other machines with unconditional step=0, we can assume that either they don't have single-step at all, PTRACE_SINGLESTEP over a syscall insn is already broken (actually stops after the following insn instead of after the syscall insn), or their hardware works differently so it doesn't have this issue, and regardless that they never much cared about the nit. Today's behavior on e.g. powerpc (a sometimes step=1 arch) is not the desireable one. Since it uses ptrace_notify, an infinite sequence of waitpid; print status; PTRACE_SINGLESTEP, WSTOPSIG(status) will double report any signal received during (or induced by) a syscall (because ptrace_syscall_exit requeues it to be reported again, instead of delivering it). For observed behavior, the x86 one is the most desireable one in that scenario. For the synthetic test case where you've used PTRACE_SYSCALL to get to the syscall-exit stop and then used PTRACE_SINGLESTEP, nobody really cares, but the observed behavior that makes intuitive sense is not to get any second stop without going back to user-mode--not the x86 behavior. I don't think anyone would object if we made the behavior consistent with those two "most desireable"s across all machines, though no single machine today is consistent with both. As to the first scenario, chances are that nobody today is noticing that detail on non-x86 machines. Today they get a bogus syscall-exit report when doing PTRACE_SINGLESTEP, but if not using PTRACE_O_SYSGOOD then they just see a SIGTRAP with si_code=0. A real single-step SIGTRAP has si_code set, and on some machines also has si_addr. On x86, the synthesized SIGTRAP matches what a real single-step one would have in the siginfo_t, which is si_code and si_addr. So the only difficulty in just using uniform code across machines is getting the right si_code and si_addr values. Every machine but x86 gets 0 for those today, so a "general solution" that starts out by only actually getting real values in for x86 would be OK. Perhaps we could require asm/siginfo.h to do: #define TRAP_SINGLESTEP TRAP_BRKPT /* TRAP_TRACE on powerpc, etc. */ Then require asm/ptrace.h to provide user_instruction_pointer(): static inline unsigned long user_instruction_pointer(struct pt_regs *regs) { return user_mode_vm(regs) ? regs->ip : 0; } This is only required vs just using: si_addr = user_mode(regs) ? instruction_pointer(regs) : 0; because x86 wants user_mode_vm vs user_mode. Then arch-independent code can fill siginfo_t just right for a synthetic single-step trap. Thanks, Roland From roland at redhat.com Wed Oct 28 03:18:35 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 20:18:35 -0700 (PDT) Subject: [PATCH 7/7] implement utrace-ptrace In-Reply-To: Oleg Nesterov's message of Monday, 26 October 2009 04:28:55 +0100 <20091026032855.GA6277@redhat.com> References: <20091026032855.GA6277@redhat.com> Message-ID: <20091028031835.310288D1@magilla.sf.frob.com> > --- /dev/null 2009-10-25 19:46:00.608018007 +0100 > +++ V1/kernel/ptrace-utrace.c 2009-10-26 03:56:46.000000000 +0100 Generally, needs more comments. That's not news, I'm sure. But just giving reactions as I would if doing upstream review without other context. > +struct ptrace_context { > + int options; > + > + int signr; > + siginfo_t *siginfo; > + > + int stop_code; > + unsigned long eventmsg; > + > + enum utrace_resume_action resume; > +}; If you are lining up whitespace in field decls, do them all. This struct merits a top comment about what it is and where it hangs. Either in more top comment or interspersed, at least a little on what the fields are for. > +#define PT_UTRACED 0x00001000 > + > +#define PTRACE_O_SYSEMU 0x100 > + > +#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) > +#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) > +#define PTRACE_EVENT_SIGTRAP (3 << 16) > +#define PTRACE_EVENT_SIGNAL (4 << 16) > +/* events visible to user-space */ > +#define PTRACE_EVENT_MASK 0xFFFF Needs comments about what it is, and why it is not in linux/ptrace.h. Personally I am glad to have these private bits in private source only. But it certainly looks to the casual observer like these belong next to the macros for the adjacent bits. > +static inline bool ptrace_event_pending(struct ptrace_context *context) s/context/ctx/ throughout for variable names (but leave ptrace_context as the struct name). > + if (action != UTRACE_REPORT) > + ptrace_context(engine)->stop_code = 0; > + utrace_control(tracee, engine, action); __must_check > +/** > + * ptrace_traceme -- helper for PTRACE_TRACEME Don't use /** kerneldoc magic. You're not matching the whole form, and these are not functions we extract docs for anyway. > +void ptrace_notify_stop(struct task_struct *tracee) > +{ > + struct utrace_engine *engine = ptrace_lookup_engine(tracee); > + > + if (IS_ERR(engine)) { > + // XXX: temporary check, wrong with mutlitracing > + WARN_ON(tracee->state != TASK_RUNNING); > + return; Explain this scenario at least a little in the comment. > +#ifdef PTRACE_SINGLESTEP > + case PTRACE_SINGLESTEP: > +#endif > +#ifdef PTRACE_SINGLEBLOCK > + case PTRACE_SINGLEBLOCK: > +#endif > +#ifdef PTRACE_SYSEMU > + case PTRACE_SYSEMU: > + case PTRACE_SYSEMU_SINGLESTEP: > +#endif > + case PTRACE_SYSCALL: > + case PTRACE_CONT: > + ret = ptrace_resume(child, engine, request, data); > + break; Since ptrace_resume_action has a switch with these #ifdef's anyway, maybe make this the default case here and give that other switch a default error case. > + case PTRACE_KILL: > + ret = 0; > + if (!child->exit_state) /* already dead */ > + ret = ptrace_resume(child, engine, request, SIGKILL); > + break; This could be inside ptrace_resume too. That fits better if you fold ptrace_resume_action into ptrace_resume, and I don't see any reason at all not to do that anyway. Thanks, Roland From roland at redhat.com Wed Oct 28 06:24:10 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 27 Oct 2009 23:24:10 -0700 (PDT) Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: Oleg Nesterov's message of Monday, 26 October 2009 04:28:55 +0100 <20091026032855.GA6277@redhat.com> References: <20091026032855.GA6277@redhat.com> Message-ID: <20091028062410.8A83B8D1@magilla.sf.frob.com> This is used only in the UTRACE_SIGNAL_HANDLER case. That means after tracehook_signal_handler(), which is where a signal handler has just been set up. For reference, in old ptrace, tracehook_signal_handler() is: if (stepping) ptrace_notify(SIGTRAP); This means that when PTRACE_SINGLE{STEP,BLOCK},signr was used to deliver the handled signal, we stop there in ptrace_notify. This is in lieu of a proper single-step trap, with the theory that what you meant to "step to" next was the first instruction of the signal handler, rather than the second instruction of the handler. The only purpose of PTRACE_EVENT_SIGTRAP is to distinguish this case from PTRACE_EVENT_SIGNAL as it would be for a real SIGTRAP after a normal instruction step. The only purposes of this distinction are to make PTRACE_SETSIGINFO have no effect, and to make resumptions ignore the data/signr argument. The former makes it consistent with other cases in utrace-ptrace that replace ptrace_notify() calls in the old ptrace, but that itself is a known nit incompatibility with the old behavior, so it's superfluous at best. The latter is just intended for pure bug-compatibility with the old behavior. Aside from these, there are no other reasons not to have the UTRACE_SIGNAL_HANDLER case result in PTRACE_EVENT_SIGNAL, with siginfo_t filled in to match what the old ptrace_notify() does. Is that all correct? In short, PTRACE_EVENT_SIGTRAP provides bug compatibility for PTRACE_SINGLESTEP,signr silently acting like PTRACE_SINGLESTEP,0 when called at the stop just provoked by the last PTRACE_SINGLESTEP,signr. Is that it? I think this is a piece of bug compatibility that upstream will be happy to have "broken". That is, I bet most people don't realize at all PTRACE_SINGLESTEP,signr will sometimes swallow a signal after what appears to be a normal single-step stop. In fact, I suspect many might say that this is worse than the previous behavior my addition of this ptrace_notify() call (sometime before git so <2.6.12; Sep 2004, not sure what version that was, maybe 2.6.9). That behavior was that PTRACE_SINGLESTEP,signr would stop at the second instruction of the signal handler and never the first--but that would be a real step (like you now get after PTRACE_SINGLESTEP,0 when stopped in ptrace_notify() at the first instruction of the handler). I'm quite sure that at the time I never contemplated the signal-swallowing implication of using ptrace_notify() here. So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look like a vanilla SIGTRAP and then fall into the default case for real signals. Does that all sound right to you, or did I miss something? Thanks, Roland From ashley.hovan at coxohio.com Wed Oct 28 15:47:53 2009 From: ashley.hovan at coxohio.com (Patricia Stinson) Date: Wed, 28 Oct 2009 16:47:53 +0100 Subject: She will give her heart to you for incredible night Message-ID: <001001ca57e6$02df8ca0$e522b78a@SMB00020yzw> Upsize your dignity http://oiqn.pharmgo43.com/ From reservations at crownparadisedeals.com Wed Oct 28 16:33:07 2009 From: reservations at crownparadisedeals.com (Crown Paradise Resorts) Date: Wed, 28 Oct 2009 12:33:07 -0400 Subject: Christmas on the beach at the best price Message-ID: <1dc011aa5a821ca276d4e1000ca55710@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From sender at netpromouter.net Wed Oct 28 15:59:41 2009 From: sender at netpromouter.net (Alexandra Paisana) Date: Wed, 28 Oct 2009 17:59:41 +0200 Subject: Tratamento Anti-Envelhecimento - oferta limitada Message-ID: Um tratamento anti-envelhecimento incr?vel que j? se pode encontrar na Europa e que prop?e realizar o sonho de todas as pessoas que querem verdadeiramente permanecer jovens e em forma durante o maior tempo poss?vel. Durante um per?odo limitado, o Centro Especial Sa?de distribui gratuitamente um tratamento de anti-envelhecimento ? no valor de 39? ?s primeiras 500 pessoas a efectuar o pedido. Siga este link: www.netpromouter.net/envelhecimento.html -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Thu Oct 29 01:55:32 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 28 Oct 2009 18:55:32 -0700 (PDT) Subject: utrace-indirect branch Message-ID: <20091029015532.4DADB534@magilla.sf.frob.com> Please take a look at the patch below and tell me what you think. This is the new(ish) utrace-indirect branch (not to be confused with what's now old/utrace-indirect). I first made it a while ago, but I don't recall if I ever mentioned it. This compiles and looks right, but I have not done any testing at all. Unlike the old code that freaked upstream reviewers all the way out, this has very simple lifetime rules for struct utrace. Once allocated, it lives until task_struct is freed. The utrace_task_alloc() logic covers the only race (at first attach), and that seems pretty easy to understand and be confident in. For those of us who hack on utrace guts, this is much nicer. The struct is private in utrace.c where it naturally belongs, and we don't have to wait for the whole kernel to be recompiled every time we want to tweak that struct. For those of us who have to maintain long-term stable production kernels, this is crucial. We need the freedom to change utrace implementation details (and backport new utrace APIs) into our kernels in the future, without perturbing the all-important task_struct layout. This is not a concern that upstream ever cares about, but it is unavoidable in real life. I am a bit concerned about letting the ugly utrace_struct.h way ever get merged in, so that to fix it later we have to convince people all over again about "changing what works". But of course I am really not at all sure whether even this innocuous version will upset the reviewers. What do you think? Thanks, Roland --- include/linux/init_task.h | 1 - include/linux/sched.h | 3 +- include/linux/tracehook.h | 12 ++++++ include/linux/utrace.h | 9 ++--- include/linux/utrace_struct.h | 59 ------------------------------ kernel/fork.c | 1 + kernel/utrace.c | 80 ++++++++++++++++++++++++++++++++++++----- 7 files changed, 89 insertions(+), 76 deletions(-) diff --git a/include/linux/init_task.h b/include/linux/init_task.h index a598a6b..21a6f5d 100644 --- a/include/linux/init_task.h +++ b/include/linux/init_task.h @@ -177,7 +177,6 @@ extern struct cred init_cred; [PIDTYPE_SID] = INIT_PID_LINK(PIDTYPE_SID), \ }, \ .dirties = INIT_PROP_LOCAL_SINGLE(dirties), \ - INIT_UTRACE(tsk) \ INIT_IDS \ INIT_PERF_EVENTS(tsk) \ INIT_TRACE_IRQFLAGS \ diff --git a/include/linux/sched.h b/include/linux/sched.h index 94ca5c5..8eeb46a 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -61,7 +61,6 @@ struct sched_param { #include #include #include -#include #include #include @@ -1395,7 +1394,7 @@ struct task_struct { seccomp_t seccomp; #ifdef CONFIG_UTRACE - struct utrace utrace; + struct utrace *utrace; unsigned long utrace_flags; #endif diff --git a/include/linux/tracehook.h b/include/linux/tracehook.h index 3caaf30..a01f8a9 100644 --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -609,6 +609,18 @@ static inline void tracehook_report_deat utrace_report_death(task, death_cookie, group_dead, signal); } +/** + * tracehook_free_task - task_struct is being freed + * @task: dead &struct task_struct being freed + * + * Called from free_task() when @task is no longer in use. + */ +static inline void tracehook_free_task(struct task_struct *task) +{ + if (task_utrace_struct(task)) + utrace_free_task(task); +} + #ifdef TIF_NOTIFY_RESUME /** * set_notify_resume - cause tracehook_notify_resume() to be called diff --git a/include/linux/utrace.h b/include/linux/utrace.h index f968792..6e8129b 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -92,6 +92,8 @@ enum utrace_events { * tracehook.h doesn't need to #ifndef CONFIG_UTRACE them to * avoid external references in case of unoptimized compilation. */ +void utrace_free_task(struct task_struct *) + __attribute__((weak)); bool utrace_interrupt_pending(void) __attribute__((weak)); void utrace_resume(struct task_struct *, struct pt_regs *) @@ -155,16 +157,13 @@ static inline unsigned long task_utrace_ static inline struct utrace *task_utrace_struct(struct task_struct *task) { - return &task->utrace; + return task->utrace; } static inline void utrace_init_task(struct task_struct *task) { task->utrace_flags = 0; - memset(&task->utrace, 0, sizeof(task->utrace)); - INIT_LIST_HEAD(&task->utrace.attached); - INIT_LIST_HEAD(&task->utrace.attaching); - spin_lock_init(&task->utrace.lock); + task->utrace = NULL; } void utrace_release_task(struct task_struct *); diff --git a/include/linux/utrace_struct.h b/include/linux/utrace_struct.h deleted file mode 100644 index ee7489f... . --- a/include/linux/utrace_struct.h +++ /dev/null @@ -1,59 +0,0 @@ -/* - * 'struct utrace' data structure for kernel/utrace.c private use. - * - * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. - * - * This copyrighted material is made available to anyone wishing to use, - * modify, copy, or redistribute it subject to the terms and conditions - * of the GNU General Public License v.2. - */ - -#ifndef _LINUX_UTRACE_STRUCT_H -#define _LINUX_UTRACE_STRUCT_H 1 - -#ifdef CONFIG_UTRACE - -#include -#include - -/* - * Per-thread structure private to utrace implementation. This properly - * belongs in kernel/utrace.c and its use is entirely private to the code - * there. It is only defined in a header file so that it can be embedded - * in the struct task_struct layout. It is here rather than in utrace.h - * to avoid header nesting order issues getting too complex. - * - */ -struct utrace { - struct task_struct *cloning; - - struct list_head attached, attaching; - spinlock_t lock; - - struct utrace_engine *reporting; - - unsigned int stopped:1; - unsigned int report:1; - unsigned int interrupt:1; - unsigned int signal_handler:1; - unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ - unsigned int death:1; /* in utrace_report_death() now */ - unsigned int reap:1; /* release_task() has run */ - unsigned int pending_attach:1; /* need splice_attaching() */ -}; - -# define INIT_UTRACE(tsk) \ - .utrace_flags = 0, \ - .utrace = { \ - .lock = __SPIN_LOCK_UNLOCKED(tsk.utrace.lock), \ - .attached = LIST_HEAD_INIT(tsk.utrace.attached), \ - .attaching = LIST_HEAD_INIT(tsk.utrace.attaching), \ - }, - -#else - -# define INIT_UTRACE(tsk) /* Nothing. */ - -#endif /* CONFIG_UTRACE */ - -#endif /* linux/utrace_struct.h */ diff --git a/kernel/fork.c b/kernel/fork.c index 4c20fff..77a3b25 100644 --- a/kernel/fork.c +++ b/kernel/fork.c @@ -147,6 +147,7 @@ static void account_kernel_stack(struct void free_task(struct task_struct *tsk) { + tracehook_free_task(tsk); prop_local_destroy_single(&tsk->dirties); account_kernel_stack(tsk->stack, -1); free_thread_info(tsk->stack); diff --git a/kernel/utrace.c b/kernel/utrace.c index 25c0908..eadc87d 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -25,8 +25,10 @@ /* - * Rules for 'struct utrace', defined in - * but used entirely privately in this file. + * Per-thread structure private to utrace implementation. + * If task_struct.utrace_flags is nonzero, task_struct.utrace + * has always been allocated first. Once allocated, it is + * never freed until free_task(). * * The common event reporting loops are done by the task making the * report without ever taking any locks. To facilitate this, the two @@ -49,18 +51,71 @@ * engines attached asynchronously go on the stable @attached list * in time to have their callbacks seen. */ +struct utrace { + struct task_struct *cloning; + struct list_head attached, attaching; + spinlock_t lock; + + struct utrace_engine *reporting; + + unsigned int stopped:1; + unsigned int report:1; + unsigned int interrupt:1; + unsigned int signal_handler:1; + unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ + unsigned int death:1; /* in utrace_report_death() now */ + unsigned int reap:1; /* release_task() has run */ + unsigned int pending_attach:1; /* need splice_attaching() */ +}; + +static struct kmem_cache *utrace_cachep; static struct kmem_cache *utrace_engine_cachep; static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ static int __init utrace_init(void) { + utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); return 0; } module_init(utrace_init); /* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() + * governs installing the new pointer. If another one got in first, + * we just punt the new one we allocated. + * + * This returns false only in case of a memory allocation failure. + */ +static bool utrace_task_alloc(struct task_struct *task) +{ + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); + if (unlikely(!utrace)) + return false; + INIT_LIST_HEAD(&utrace->attached); + INIT_LIST_HEAD(&utrace->attaching); + spin_lock_init(&utrace->lock); + task_lock(task); + if (likely(!task->utrace)) + task->utrace = utrace; + task_unlock(task); + if (unlikely(task->utrace != utrace)) + kmem_cache_free(utrace_cachep, utrace); + return true; +} + +/* + * This is called via tracehook_free_task() from free_task() + * when @task is being deallocated. + */ +void utrace_free_task(struct task_struct *task) +{ + kmem_cache_free(utrace_cachep, task->utrace); +} + +/* * This is called with @utrace->lock held when the task is safely * quiescent, i.e. it won't consult utrace->attached without the lock. * Move any engines attached asynchronously from @utrace->attaching @@ -119,7 +174,8 @@ static struct utrace_engine *matching_en static inline int utrace_attach_delay(struct task_struct *target) { if ((target->flags & PF_STARTING) && - current->utrace.cloning != target) + task_utrace_struct(current) && + task_utrace_struct(current)->cloning != target) do { schedule_timeout_interruptible(1); if (signal_pending(current)) @@ -225,6 +281,8 @@ struct utrace_engine *utrace_attach_task int ret; if (!(flags & UTRACE_ATTACH_CREATE)) { + if (unlikely(!utrace)) + ERR_PTR(-ENOENT); spin_lock(&utrace->lock); engine = matching_engine(utrace, flags, ops, data); if (engine) @@ -242,6 +300,12 @@ struct utrace_engine *utrace_attach_task */ return ERR_PTR(-EPERM); + if (!utrace) { + if (unlikely(!utrace_task_alloc(target))) + return ERR_PTR(-ENOMEM); + utrace = target->utrace; + } + engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); if (unlikely(!engine)) return ERR_PTR(-ENOMEM); @@ -370,7 +434,7 @@ static struct utrace *get_utrace_lock(st return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); } - utrace = &target->utrace; + utrace = task_utrace_struct(target); spin_lock(&utrace->lock); if (unlikely(!engine->ops) || unlikely(engine->ops == &utrace_detached_ops)) { @@ -440,9 +504,7 @@ static void utrace_reap(struct task_stru */ void utrace_release_task(struct task_struct *target) { - struct utrace *utrace; - - utrace = &target->utrace; + struct utrace *utrace = task_utrace_struct(target); spin_lock(&utrace->lock); @@ -1896,7 +1958,7 @@ int utrace_get_signal(struct task_struct u32 ret; int signr; - utrace = &task->utrace; + utrace = task_utrace_struct(task); if (utrace->interrupt || utrace->report || utrace->signal_handler) { /* * We've been asked for an explicit report before we @@ -2335,7 +2397,7 @@ EXPORT_SYMBOL_GPL(task_user_regset_view) */ void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) { - struct utrace *utrace = &p->utrace; + struct utrace *utrace = task_utrace_struct(p); seq_printf(m, "Utrace:\t%lx%s%s%s\n", p->utrace_flags, utrace->stopped ? " (stopped)" : "", From roland at redhat.com Thu Oct 29 02:03:29 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 28 Oct 2009 19:03:29 -0700 (PDT) Subject: utrace-cleanup branch Message-ID: <20091029020329.A58A0534@magilla.sf.frob.com> I've made a new branch, utrace-cleanup. This forks from utrace-indirect and has: 26fefca utrace: sticky resume action 28b2774 utrace: remove ->stopped field Those are the two changes we talked about during tangential ptrace discussions. Again, I have compiled these but not tested a lick. I'd just like to get some feedback. They both seem like happy clean-ups to me, making the code smaller and simpler. What do you think? Thanks, Roland From ananth at in.ibm.com Thu Oct 29 04:54:31 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 29 Oct 2009 10:24:31 +0530 Subject: utrace-indirect branch In-Reply-To: <20091029015532.4DADB534@magilla.sf.frob.com> References: <20091029015532.4DADB534@magilla.sf.frob.com> Message-ID: <20091029045431.GB4632@in.ibm.com> On Wed, Oct 28, 2009 at 06:55:32PM -0700, Roland McGrath wrote: > Please take a look at the patch below and tell me what you think. This > is the new(ish) utrace-indirect branch (not to be confused with what's > now old/utrace-indirect). I first made it a while ago, but I don't > recall if I ever mentioned it. This compiles and looks right, but I > have not done any testing at all. > > Unlike the old code that freaked upstream reviewers all the way out, > this has very simple lifetime rules for struct utrace. Once allocated, > it lives until task_struct is freed. The utrace_task_alloc() logic > covers the only race (at first attach), and that seems pretty easy > to understand and be confident in. First glance, this looks much simpler and easier to understand compared to the earlier rcu implementation. ... > + if (!utrace) { > + if (unlikely(!utrace_task_alloc(target))) > + return ERR_PTR(-ENOMEM); > + utrace = target->utrace; utrace = task_utrace_struct(target); > + } > + > engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); > if (unlikely(!engine)) > return ERR_PTR(-ENOMEM); Ananth From oleg at redhat.com Thu Oct 29 19:41:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 20:41:58 +0100 Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: <20091028062410.8A83B8D1@magilla.sf.frob.com> References: <20091026032855.GA6277@redhat.com> <20091028062410.8A83B8D1@magilla.sf.frob.com> Message-ID: <20091029194158.GA13059@redhat.com> On 10/27, Roland McGrath wrote: > > This is used only in the UTRACE_SIGNAL_HANDLER case. That means after > tracehook_signal_handler(), which is where a signal handler has just > been set up. > > For reference, in old ptrace, tracehook_signal_handler() is: > > if (stepping) > ptrace_notify(SIGTRAP); > > This means that when PTRACE_SINGLE{STEP,BLOCK},signr was used to > deliver the handled signal, we stop there in ptrace_notify. This is > in lieu of a proper single-step trap, with the theory that what you > meant to "step to" next was the first instruction of the signal > handler, rather than the second instruction of the handler. > > The only purpose of PTRACE_EVENT_SIGTRAP is to distinguish this case > from PTRACE_EVENT_SIGNAL as it would be for a real SIGTRAP after a > normal instruction step. The only purposes of this distinction are to > make PTRACE_SETSIGINFO have no effect, and to make resumptions ignore > the data/signr argument. The former makes it consistent with other > cases in utrace-ptrace that replace ptrace_notify() calls in the old > ptrace, but that itself is a known nit incompatibility with the old > behavior, so it's superfluous at best. The latter is just intended > for pure bug-compatibility with the old behavior. Aside from these, > there are no other reasons not to have the UTRACE_SIGNAL_HANDLER case > result in PTRACE_EVENT_SIGNAL, with siginfo_t filled in to match what > the old ptrace_notify() does. > > Is that all correct? > > In short, PTRACE_EVENT_SIGTRAP provides bug compatibility for > PTRACE_SINGLESTEP,signr silently acting like PTRACE_SINGLESTEP,0 when (s/PTRACE_SINGLESTEP/PTRACE_ANY/) > called at the stop just provoked by the last PTRACE_SINGLESTEP,signr. > Is that it? Yes. > I think this is a piece of bug compatibility that upstream will be > happy to have "broken". That is, I bet most people don't realize at > all PTRACE_SINGLESTEP,signr will sometimes swallow a signal after what > appears to be a normal single-step stop. In fact, I suspect many > might say that this is worse than the previous behavior my addition of > this ptrace_notify() call (sometime before git so <2.6.12; Sep 2004, > not sure what version that was, maybe 2.6.9). That behavior was that > PTRACE_SINGLESTEP,signr would stop at the second instruction of the > signal handler and never the first--but that would be a real step > (like you now get after PTRACE_SINGLESTEP,0 when stopped in > ptrace_notify() at the first instruction of the handler). I'm quite > sure that at the time I never contemplated the signal-swallowing > implication of using ptrace_notify() here. > > So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of > UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look > like a vanilla SIGTRAP and then fall into the default case for > real signals. Yes, I already thought about this. The patch is trivial, please see below. > Does that all sound right to you, or did I miss something? Don't ask me, I never know what can be changed ;) But yes, I agree. The current behaviour looks strange (if not wrong). With this change ptrace(PTRACE_WHATEVER, signr) after PTRACE_SINGLESTEP never ignores signr. Even if perhaps this is not really useful, this is consistent. Afaics, this case was a single exception when ptrace(signr) or PTRACE_SETSIGINFO) was ignored after PTRACE_SINGLESTEP. The only problem with this change (if we do it now), it is always nice to have a separate changelog to document the behaviour change. But hopefully nobody cares, I mean, nobody will notice the difference. Oleg. --- a/kernel/ptrace.c +++ b/kernel/ptrace.c @@ -73,7 +73,6 @@ struct ptrace_context { #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) #define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGTRAP (3 << 16) #define PTRACE_EVENT_SIGNAL (4 << 16) /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF @@ -495,8 +494,8 @@ static u32 ptrace_report_signal(u32 acti context->siginfo = NULL; if (resume != UTRACE_RESUME) { - set_stop_code(context, PTRACE_EVENT_SIGTRAP); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; + info->si_signo = SIGTRAO; + break; } case UTRACE_SIGNAL_REPORT: @@ -509,21 +508,21 @@ static u32 ptrace_report_signal(u32 acti return resume | resume_signal(task, context->signr, info, return_ka); - default: - WARN_ON(context->siginfo); - context->siginfo = info; - /* - * context->siginfo points to the caller's stack. - * Make sure the subsequent UTRACE_SIGNAL_REPORT clears - * ->siginfo before return from get_signal_to_deliver(). - */ - utrace_control(task, engine, UTRACE_INTERRUPT); + } - context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; - context->signr = info->si_signo; + WARN_ON(context->siginfo); + context->siginfo = info; + /* + * context->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; - } + context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; + context->signr = info->si_signo; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; } static u32 ptrace_report_quiesce(u32 action, From oleg at redhat.com Thu Oct 29 19:42:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 20:42:35 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091028023058.7A6A37CDF@magilla.sf.frob.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> <20091028023058.7A6A37CDF@magilla.sf.frob.com> Message-ID: <20091029194235.GB13059@redhat.com> On 10/27, Roland McGrath wrote: > > > And yes, while I don't pretend I know what should be done, I agree the > > current API (I don't mean the documentation, I mean the actual code) is > > not right. > > The behavior is fine in practice, it's just that the lockdep rules are > violated (and that's indeed horribly wrong in the cases that matter, which > are vanishingly rare in real-world practice). In this case I confused again. Let's forget about get_user_pages() under spin_lock(), pretend it works. Two engines, E1 and E2, the tracee sleeps in utrace_resume()->utrace_stop(). E1 does utrace_control(UTRACE_RESUME), E2 does utrace_control(UTRACE_SINGLESTEP). How this can work? If E2 calls utrace_control() first, the subsequent UTRACE_RESUME does user_disable_single_step(), and (in general) E2 has no chance to re-assert SINGLESTEP. > > I agree. But I can't explain why I agree ;) I mean, I feel this should be > > more clean, but given that I do not understand the low level details even > > remotely I can't judge. > > What level of details don't you understand? > I hope you understand everything in utrace.c! Yes, I hope I understand utrace.c ;) I meant user_enable_single_step(). I don't really understand it even in x86 case, to many low level magic. > Speaking of which, it really looks like it's already the case now that > ->stopped exactly matches task_is_traced(). Yes. I believe, currently ->stopped can go away. > I know we discussed this > before and put it off. By the time we discussed it, ->stopped was a bit more complicated iirc, it could be set in some subtle ->exit_state cases. Afaics, we can kill ->stopped, but utrace_stop() and utrace_finish_jctl() should do unconditial spin_unlock_wait(utrace->lock) after resume (or lock/unlock). Of course, unlike ->stopped, task_is_traced() == T is not stable under under untrace->lock, but I think we don't care. > > And yes, this is not even consistent across machines (as you explained > > before), that is why I am very nervous when I think about the changes > > in this area. > > Ok. I think this is a corner where we will have some play in cleaning up > and unifying the behavior upstream without much complaint. In the status > quo, x86 passes only 0 to tracehook_report_syscall_exit and will synthesize > a SIGTRAP only if TIF_SINGLESTEP is set on its return (i.e. the last call > user_enable_*_step was after the last call to user_disable_single_step). > Other machines either pass step=1 when user_enable_*_step had been used to > reach tracehook_report_syscall_exit and do nothing else, or pass step=0 and > have no other related checks I can see. > > For us, step=1 doesn't really give any new information. It means > PTRACE_{SINGLE,BLOCK}STEP was used to hit the syscall insn (or used after > PTRACE_SYSCALL stopped for syscall-entry). But now ptrace_context.resume > tells us that if we check it. > > So, if nothing else, we can do user_disable_single_step somewhere inside > tracehook_report_syscall_exit to disarm the x86 code and then behave > uniformly across machines inside there. But, the x86 maintainers are > generally friendly to our changes if we are clear about their purpose. Yes, but sometimes ptrace (current implementation) has no chance to notice this case and it relies on syscall_trace_leave()->send_sigtrap(), we are going to return to user-mode without utrace->report/interrupt set. > On all those other machines with unconditional step=0, we can assume that > either they don't have single-step at all, PTRACE_SINGLESTEP over a syscall > insn is already broken (actually stops after the following insn instead of > after the syscall insn), or their hardware works differently so it doesn't > have this issue, and regardless that they never much cared about the nit. Horror. Horror, horror, horror. I just realized that ptrace_resume()->send_sigtrap() can only work on x86. I always knew this should be changed, but I hoped this more or less correct for now. But send_sigtrap() doesn't even exist on !x86 machines! > [...snip...] > > Then arch-independent code can fill siginfo_t just right for a synthetic > single-step trap. Yes, I think we should do something arch-independent. I need to read the code and think, then I'll ask you stupid questions. Oleg. From oleg at redhat.com Thu Oct 29 20:14:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 21:14:44 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091029194235.GB13059@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> <20091028023058.7A6A37CDF@magilla.sf.frob.com> <20091029194235.GB13059@redhat.com> Message-ID: <20091029201444.GA14419@redhat.com> On 10/29, Oleg Nesterov wrote: > > In this case I confused again. Let's forget about get_user_pages() under > spin_lock(), pretend it works. > > Two engines, E1 and E2, the tracee sleeps in utrace_resume()->utrace_stop(). > > E1 does utrace_control(UTRACE_RESUME), E2 does utrace_control(UTRACE_SINGLESTEP). > How this can work? > > If E2 calls utrace_control() first, the subsequent UTRACE_RESUME does > user_disable_single_step(), and (in general) E2 has no chance to re-assert > SINGLESTEP. Looks like, 26fefca "sticky resume action" fixes this... Oleg. From oleg at redhat.com Thu Oct 29 20:35:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 21:35:41 +0100 Subject: utrace-cleanup branch In-Reply-To: <20091029020329.A58A0534@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> Message-ID: <20091029203541.GB14419@redhat.com> On 10/28, Roland McGrath wrote: > > I've made a new branch, utrace-cleanup. > This forks from utrace-indirect and has: > > 26fefca utrace: sticky resume action Can't comment right now, need to read the code. But I feel this is "right" change. > 28b2774 utrace: remove ->stopped field Again, need to actually read the code, but. Afaics, we can't just remove utrace_finish_jctl() and the similar code in utrace_stop(). We need void utrace_finish_jctl(void) { struct utrace *utrace = task_utrace_struct(current); /* * While in TASK_STOPPED, we can be considered safely stopped by * utrace_do_stop(). Make sure we can do nothing until the tracer * drops utrace->lock */ if (unlikely(__fatal_signal_pending())) spin_unlock_wait(utrace->lock); } and utrace_stop() should do the same. Otherwise, the killed tracee can start another reporting loop and list_for_each() can race with, say, utrace_reset(DETACH)->utrace_reset(). More generally, if the tracer sees "it is stopped" under utrace->lock, the tracee must be "really" stopped until we drop utrace->lock(), it must not "escape" from utrace_stop() or do_signal_stop(). Right? Oleg. From oleg at redhat.com Thu Oct 29 20:46:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 21:46:24 +0100 Subject: utrace-indirect branch In-Reply-To: <20091029015532.4DADB534@magilla.sf.frob.com> References: <20091029015532.4DADB534@magilla.sf.frob.com> Message-ID: <20091029204624.GC14419@redhat.com> On 10/28, Roland McGrath wrote: > > Unlike the old code that freaked upstream reviewers all the way out, > this has very simple lifetime rules for struct utrace. Once allocated, > it lives until task_struct is freed. The utrace_task_alloc() logic > covers the only race (at first attach), and that seems pretty easy > to understand and be confident in. Yep, I already noticed utrace-indirect branch before. While I didn't look at the code closely, this change looks very simple and imho desirable. I'll try to read it carefully later. > I am a bit concerned about letting the ugly utrace_struct.h way ever get > merged in, so that to fix it later we have to convince people all over > again about "changing what works". But of course I am really not at all > sure whether even this innocuous version will upset the reviewers. Yes, this is the question ;) My opinion, it would be better to send this as a separate patch, when the utrace is already merged. Because they were too many complaints about task_struct->utrace pointer before. And given that nobody actually read the code during review (at least this happened before), I am afraid we can have "ugh, it is a pointer again?" complaints. But of course I don't really sure. Speaking of this change. Do you think we can remove "void *cookie" from exit_notify() pathes before sending utrace/ptrace to lkml? Afaics, given that task->utrace never goes away utrace-indirect doesn't need this hack. Oleg. From oleg at redhat.com Thu Oct 29 21:25:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 22:25:39 +0100 Subject: [PATCH 7/7] implement utrace-ptrace In-Reply-To: <20091028031835.310288D1@magilla.sf.frob.com> References: <20091026032855.GA6277@redhat.com> <20091028031835.310288D1@magilla.sf.frob.com> Message-ID: <20091029212539.GA17529@redhat.com> On 10/27, Roland McGrath wrote: > > > --- /dev/null 2009-10-25 19:46:00.608018007 +0100 > > +++ V1/kernel/ptrace-utrace.c 2009-10-26 03:56:46.000000000 +0100 > > Generally, needs more comments. That's not news, I'm sure. > But just giving reactions as I would if doing upstream review > without other context. > > > +struct ptrace_context { > > + int options; > > + > > + int signr; > > + siginfo_t *siginfo; > > + > > + int stop_code; > > + unsigned long eventmsg; > > + > > + enum utrace_resume_action resume; > > +}; > > If you are lining up whitespace in field decls, do them all. This struct > merits a top comment about what it is and where it hangs. Either in more > top comment or interspersed, at least a little on what the fields are for. Oh, comments. Yes we need more. I can only say I will try to add more documentation, but this is not easy. > > +static inline bool ptrace_event_pending(struct ptrace_context *context) > > s/context/ctx/ throughout for variable names (but leave ptrace_context as > the struct name). OK. > > > + if (action != UTRACE_REPORT) > > + ptrace_context(engine)->stop_code = 0; > > + utrace_control(tracee, engine, action); > > __must_check OK. > > +/** > > + * ptrace_traceme -- helper for PTRACE_TRACEME > > Don't use /** kerneldoc magic. You're not matching the whole form, > and these are not functions we extract docs for anyway. Heh, this was blindly copied from the old code, will remove that part. > > +void ptrace_notify_stop(struct task_struct *tracee) > > +{ > > + struct utrace_engine *engine = ptrace_lookup_engine(tracee); > > + > > + if (IS_ERR(engine)) { > > + // XXX: temporary check, wrong with mutlitracing > > + WARN_ON(tracee->state != TASK_RUNNING); > > + return; > > Explain this scenario at least a little in the comment. This WARN (and another "XXX" comment in ptrace_resume) should go away. > > +#ifdef PTRACE_SINGLESTEP > > + case PTRACE_SINGLESTEP: > > +#endif > > +#ifdef PTRACE_SINGLEBLOCK > > + case PTRACE_SINGLEBLOCK: > > +#endif > > +#ifdef PTRACE_SYSEMU > > + case PTRACE_SYSEMU: > > + case PTRACE_SYSEMU_SINGLESTEP: > > +#endif > > + case PTRACE_SYSCALL: > > + case PTRACE_CONT: > > + ret = ptrace_resume(child, engine, request, data); > > + break; > > Since ptrace_resume_action has a switch with these #ifdef's anyway, > maybe make this the default case here and give that other switch a > default error case. Hmm. Yes, at first glance this would be cleaner... > > + case PTRACE_KILL: > > + ret = 0; > > + if (!child->exit_state) /* already dead */ > > + ret = ptrace_resume(child, engine, request, SIGKILL); > > + break; > > This could be inside ptrace_resume too. Yes, and we don't even need to check exit_state. > That fits better if you fold > ptrace_resume_action into ptrace_resume, and I don't see any reason at > all not to do that anyway. Well, I'd like to keep ptrace_resume_action(). ptrace_resume() is fat enough, and while ptrace_resume_action's code is simple, it is not easily readable. But yes, we can fold it although I don't understand why you don't like it, to me its logic deserves a separate function. If nothing else, ptrace_resume() becomes >100 lines after the folding. Oleg. From oleg at redhat.com Thu Oct 29 22:25:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 29 Oct 2009 23:25:57 +0100 Subject: utrace-cleanup branch In-Reply-To: <20091029020329.A58A0534@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> Message-ID: <20091029222557.GA19858@redhat.com> Btw, why does utrace_set_events() check utrace->stopped? If a tracee is stopped then ->reporting == engine is not possible, ->reporting must be NULL. To optimize out other checks + mb() in the likely "stopped" case? Oleg. From roland at redhat.com Thu Oct 29 22:42:46 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 15:42:46 -0700 (PDT) Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 20:42:35 +0100 <20091029194235.GB13059@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> <20091028023058.7A6A37CDF@magilla.sf.frob.com> <20091029194235.GB13059@redhat.com> Message-ID: <20091029224246.A9E31538@magilla.sf.frob.com> > E1 does utrace_control(UTRACE_RESUME), E2 does utrace_control(UTRACE_SINGLESTEP). > How this can work? > > If E2 calls utrace_control() first, the subsequent UTRACE_RESUME does > user_disable_single_step(), and (in general) E2 has no chance to re-assert > SINGLESTEP. I see your point. > Looks like, 26fefca "sticky resume action" fixes this... It handles that scenario. But you've actually raised a broader issue. Even with utrace-cleanup where we get the "most intrusive wins" logic, we still have a version of this issue. That is, ordering of utrace_control calls is an uncoordinated variable that does not tie in with the engine callback ordering. Another example is E1 does UTRACE_BLOCKSTEP and then E2 does UTRACE_SINGLESTEP. Now single-step will win out, which is right. But E2 gets no notice about this, so it can't know that the step is for an insn rather than a block. In contrast, say utrace_control reduces both to UTRACE_REPORT, either implicitly as we had been discussing before, or because E3 comes along (before or after) and calls utrace_control(,,UTRACE_REPORT). Then E[123] get report_quiesce(0) in their callback order. (We can't control that order much today, but that is still to consolidate the utrace_control ordering issue into that existing general ordering issue.) One easy thing relative to utrace-cleanup is to say that when a pending *STEP is changed to the other * then it just reduces to REPORT. IOW, you always get a callback after utrace_control if any other engine is doing any action different from yours (and < RESUME). If we later add something like an engine priority number that controls callback order, then it would be a compatible optimization of this to store the priority along with the pending action and have utrace_control calls reduce to REPORT only if the previous utrace_control(,,*STEP) was by an engine whose report_quiesce would have been before yours (so that it wouldn't know what you had done anyway). > Yes, I hope I understand utrace.c ;) I meant user_enable_single_step(). > I don't really understand it even in x86 case, to many low level magic. Ok, good. You officially don't need to understand that unless you want to. It's essential we have you as an expert on utrace and ptrace. But you do not also need to become an arch/x86 expert unless it takes your fancy. It's enough to know that the arch code has certain contraints (i.e. here it's __might_sleep). For all these arch interfaces, I've endeavored to make the kerneldoc comments give the complete specification of the contract between the arch code and the generic code. If some arch code does not match that specification, then it can be my problem to resolve that with the arch code and its humans. If an arch needs it to involve changing that interface contract, then it can be my problem to mediate that with you and keep the kerneldoc current and accurate. > By the time we discussed it, ->stopped was a bit more complicated iirc, > it could be set in some subtle ->exit_state cases. Yes. > Afaics, we can kill ->stopped, but utrace_stop() and utrace_finish_jctl() > should do unconditial spin_unlock_wait(utrace->lock) after resume (or > lock/unlock). Ok. Please send a patch relative to utrace-cleanup with that code including comments that explain those needs. > Of course, unlike ->stopped, task_is_traced() == T is not stable under > under untrace->lock, but I think we don't care. Right. > Yes, but sometimes ptrace (current implementation) has no chance to > notice this case and it relies on syscall_trace_leave()->send_sigtrap(), > we are going to return to user-mode without utrace->report/interrupt set. Right, it would require that tracehook_report_syscall_exit() calls into utrace even without utrace_flags & UTRACE_EVENT(SYSCALL_EXIT) so it can do something about this case. > Horror. Horror, horror, horror. > > I just realized that ptrace_resume()->send_sigtrap() can only work on x86. > I always knew this should be changed, but I hoped this more or less correct > for now. But send_sigtrap() doesn't even exist on !x86 machines! Sorry, I didn't mention that lately since I presumed you already knew. It's just a simple wrapper. With the arch-specific si_code/si_addr determination interfaces I mentioned, it would be (almost) subsumed by generic code doing the same thing anyway. The (almost) is: tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; which is x86 magic that can only ever be seen in userland handler's sigcontext (not in siginfo!), and it's only a undesired misfeature that these ptrace-induced signals can ever reach userland. But, I mention it so as not to omit anything more about the status quo. > I need to read the code and think, then I'll ask you stupid questions. :-) Putting those first two steps before the third is what makes you a rock star! Thanks, Roland From roland at redhat.com Thu Oct 29 22:46:53 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 15:46:53 -0700 (PDT) Subject: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 23:25:57 +0100 <20091029222557.GA19858@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091029222557.GA19858@redhat.com> Message-ID: <20091029224653.32EE7538@magilla.sf.frob.com> > To optimize out other checks + mb() in the likely "stopped" case? Yes. Thanks, Roland From roland at redhat.com Thu Oct 29 23:30:35 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 16:30:35 -0700 (PDT) Subject: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 21:35:41 +0100 <20091029203541.GB14419@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091029203541.GB14419@redhat.com> Message-ID: <20091029233035.C749B1D3@magilla.sf.frob.com> > Can't comment right now, need to read the code. Such gentlemanly restraint. > Afaics, we can't just remove utrace_finish_jctl() and the similar code in > utrace_stop(). We need > > void utrace_finish_jctl(void) > { > struct utrace *utrace = task_utrace_struct(current); > /* > * While in TASK_STOPPED, we can be considered safely stopped by > * utrace_do_stop(). Make sure we can do nothing until the tracer > * drops utrace->lock > */ > if (unlikely(__fatal_signal_pending())) > spin_unlock_wait(utrace->lock); > } > > and utrace_stop() should do the same. I see. The comments should be more clear that SIGKILL breaking TASK_TRACED is the only way this can arise. In the jctl case, that is in particular after utrace_do_stop() changed TASK_STOPPED into TASK_TRACED. > Otherwise, the killed tracee can start another reporting loop and > list_for_each() can race with, say, utrace_reset(DETACH)->utrace_reset(). > More generally, if the tracer sees "it is stopped" under utrace->lock, > the tracee must be "really" stopped until we drop utrace->lock(), it > must not "escape" from utrace_stop() or do_signal_stop(). Correct. So today ->stopped really does still mean one other thing. It means that it's either still in TASK_TRACED or is just waking up for SIGKILL. I think we've discussed the related stuff before. A contrary approach would be to ensure that in the SIGKILL-breaks-UTRACE_STOP case we never make any more normal reports at all before utrace_report_death. It seems like a good API choice on its face: if you used UTRACE_STOP, you didn't expect to see any SYSCALL_EXIT, SIGNAL, etc. events--the special case is the instant-death scenario, so straight to report_death makes some sense. I was attracted by this until I started going through it. It's all good until you consider report_clone. If a SIGKILL is pending when you get to utrace_report_clone(), the clone has already happened. If you skip that callback, the engine doesn't find out about the new child, and that matters if it's not a CLONE_THREAD. Thanks, Roland From roland at redhat.com Thu Oct 29 23:35:20 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 16:35:20 -0700 (PDT) Subject: [PATCH 7/7] implement utrace-ptrace In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 22:25:39 +0100 <20091029212539.GA17529@redhat.com> References: <20091026032855.GA6277@redhat.com> <20091028031835.310288D1@magilla.sf.frob.com> <20091029212539.GA17529@redhat.com> Message-ID: <20091029233520.E6C991D3@magilla.sf.frob.com> > Well, I'd like to keep ptrace_resume_action(). ptrace_resume() is fat > enough, and while ptrace_resume_action's code is simple, it is not easily > readable. Your preference is fine here. Subfunctions can become counterproductive when you have to complicate the caller's control flow because of them (where you might have used multiple returns more concisely in a single function). Net readability (mostly by being shorter in total) is the only priority. Thanks, Roland From roland at redhat.com Thu Oct 29 23:46:43 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 16:46:43 -0700 (PDT) Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 20:41:58 +0100 <20091029194158.GA13059@redhat.com> References: <20091026032855.GA6277@redhat.com> <20091028062410.8A83B8D1@magilla.sf.frob.com> <20091029194158.GA13059@redhat.com> Message-ID: <20091029234643.696631D3@magilla.sf.frob.com> > > In short, PTRACE_EVENT_SIGTRAP provides bug compatibility for > > PTRACE_SINGLESTEP,signr silently acting like PTRACE_SINGLESTEP,0 when > > (s/PTRACE_SINGLESTEP/PTRACE_ANY/) Right. > > Does that all sound right to you, or did I miss something? > > Don't ask me, I never know what can be changed ;) :-) I only meant to ask that you verify all my factual statements. You are on the hook for being sure about what exactly what the behaviors are now and would be if changed how. I can represent whether given exact changes are good fixes or bad incompatibilities. > But yes, I agree. The current behaviour looks strange (if not wrong). > With this change ptrace(PTRACE_WHATEVER, signr) after PTRACE_SINGLESTEP > never ignores signr. Even if perhaps this is not really useful, this is > consistent. Afaics, this case was a single exception when ptrace(signr) > or PTRACE_SETSIGINFO) was ignored after PTRACE_SINGLESTEP. Aside from any resumption after a PTRACE_O_TRACE* stop, yes, I think it is. > The only problem with this change (if we do it now), it is always nice > to have a separate changelog to document the behaviour change. But > hopefully nobody cares, I mean, nobody will notice the difference. This seems like something we could change upstream first, to clarify and separate the behavior change. If the arch bits about choosing si_code et al are resolved, then it is simple to make the old kernel's tracehook calls post a signal instead of using ptrace_notify. Thanks, Roland From oleg at redhat.com Fri Oct 30 00:19:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 01:19:10 +0100 Subject: utrace-cleanup branch In-Reply-To: <20091029233035.C749B1D3@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091029203541.GB14419@redhat.com> <20091029233035.C749B1D3@magilla.sf.frob.com> Message-ID: <20091030001910.GA26508@redhat.com> On 10/29, Roland McGrath wrote: > > > void utrace_finish_jctl(void) > > { > > struct utrace *utrace = task_utrace_struct(current); > > /* > > * While in TASK_STOPPED, we can be considered safely stopped by > > * utrace_do_stop(). Make sure we can do nothing until the tracer > > * drops utrace->lock > > */ > > if (unlikely(__fatal_signal_pending())) > > spin_unlock_wait(utrace->lock); > > } > > > > and utrace_stop() should do the same. > > I see. The comments should be more clear that SIGKILL breaking > TASK_TRACED is the only way this can arise. In the jctl case, that is > in particular after utrace_do_stop() changed TASK_STOPPED into TASK_TRACED. Agreed. > So today ->stopped really does still mean one other thing. It means > that it's either still in TASK_TRACED or is just waking up for SIGKILL. > > I think we've discussed the related stuff before. A contrary approach > would be to ensure that in the SIGKILL-breaks-UTRACE_STOP case we never > make any more normal reports at all before utrace_report_death. Yes, I agree. > I was attracted by this until I started going through it. > It's all good until you consider report_clone. If a SIGKILL is pending > when you get to utrace_report_clone(), the clone has already happened. > If you skip that callback, the engine doesn't find out about the new > child, and that matters if it's not a CLONE_THREAD. another nasty case is report_exit(). Even if we fix the discussed problems with explicit/implicit SIGKILL's. We shouldn't afaics skip this report if the tracee was killed by execing sub-thread. Both can be fixed if we add spin_unlock_wait() before REPORT(). But imho it would be safer if we start with spin_unlock_wait() in utrace_stop(), perhaps there is something else to consider. Oleg. From roland at redhat.com Fri Oct 30 00:31:48 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 17:31:48 -0700 (PDT) Subject: utrace-indirect branch In-Reply-To: Oleg Nesterov's message of Thursday, 29 October 2009 21:46:24 +0100 <20091029204624.GC14419@redhat.com> References: <20091029015532.4DADB534@magilla.sf.frob.com> <20091029204624.GC14419@redhat.com> Message-ID: <20091030003148.287F7538@magilla.sf.frob.com> > Yes, this is the question ;) At this point I have an irrational distaste for utrace_struct.h and a pathological displeasure at having a contentious upstream discussion on this again. We need to get the "right" code in upstream, and in the "right" state before another lifetime passes. I'm leaving it entirely in your discretion how best to make that happen. My ruminations are just there for whatever they're worth. > Do you think we can remove "void *cookie" from exit_notify() pathes > before sending utrace/ptrace to lkml? Afaics, given that task->utrace > never goes away utrace-indirect doesn't need this hack. My inclination is that we not fiddle with any tracehook or other changes that do not have a direct positive effect on keeping the utrace code simpler today. If upstream wants us to fiddle with them, then we will. Otherwise we can get things merged, do more rounds of internal changes, and let the dust settle, before we look for cosmetic cleanups. IMHO today it's just more trivia to read over and get distracted by, more fiddling for anyone trying a backport to an older base kernel, etc. I don't really recall the exact details in previous generations of code that made it important to save that pointer across that locking window. Now that you have cleaned up and fixed the attach vs release_task interactions, introduced utrace_finish_jctl, etc., I suspect we could (later) introduce free-on-last-detach behavior and have the code be far easier to follow and more reliable than the past situation. Even then, chances are it wouldn't wind up needing that pointer. But, who knows? It's a trivium compiled away from the tracehook inlines today. Thanks, Roland From oleg at redhat.com Fri Oct 30 00:27:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 01:27:09 +0100 Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: <20091029234643.696631D3@magilla.sf.frob.com> References: <20091026032855.GA6277@redhat.com> <20091028062410.8A83B8D1@magilla.sf.frob.com> <20091029194158.GA13059@redhat.com> <20091029234643.696631D3@magilla.sf.frob.com> Message-ID: <20091030002709.GB26508@redhat.com> On 10/29, Roland McGrath wrote: > > > The only problem with this change (if we do it now), it is always nice > > to have a separate changelog to document the behaviour change. But > > hopefully nobody cares, I mean, nobody will notice the difference. > > This seems like something we could change upstream first, to clarify and > separate the behavior change. If the arch bits about choosing si_code et > al are resolved, then it is simple to make the old kernel's tracehook calls > post a signal instead of using ptrace_notify. Ah, yes. I forgot about si_code/etc filling. Of course, the discussed change which kills PTRACE_EVENT_SIGTRAP has to fill *info correctly too. Oleg. From roland at redhat.com Fri Oct 30 00:52:48 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 17:52:48 -0700 (PDT) Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: Oleg Nesterov's message of Friday, 30 October 2009 01:27:09 +0100 <20091030002709.GB26508@redhat.com> References: <20091026032855.GA6277@redhat.com> <20091028062410.8A83B8D1@magilla.sf.frob.com> <20091029194158.GA13059@redhat.com> <20091029234643.696631D3@magilla.sf.frob.com> <20091030002709.GB26508@redhat.com> Message-ID: <20091030005248.C3EF8538@magilla.sf.frob.com> > > This seems like something we could change upstream first, to clarify and > > separate the behavior change. If the arch bits about choosing si_code et > > al are resolved, then it is simple to make the old kernel's tracehook calls > > post a signal instead of using ptrace_notify. > > Ah, yes. I forgot about si_code/etc filling. > > Of course, the discussed change which kills PTRACE_EVENT_SIGTRAP has to > fill *info correctly too. Yes. We previously discussed si_code et al in the context of what utrace-ptrace could do, and that's when I first raised having some kind of arch hook for it. My suggestion above assumed that we'd invent the arch hook to use first in the upstream version in such a way that it would be natural to use the same hook in utrace-ptrace. Thanks, Roland From roland at redhat.com Fri Oct 30 01:01:27 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 18:01:27 -0700 (PDT) Subject: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Friday, 30 October 2009 01:19:10 +0100 <20091030001910.GA26508@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091029203541.GB14419@redhat.com> <20091029233035.C749B1D3@magilla.sf.frob.com> <20091030001910.GA26508@redhat.com> Message-ID: <20091030010127.87751538@magilla.sf.frob.com> > another nasty case is report_exit(). Even if we fix the discussed problems > with explicit/implicit SIGKILL's. We shouldn't afaics skip this report if > the tracee was killed by execing sub-thread. Yes, that's a good point. The rationale for true SIGKILL being "more direct" (i.e. skipping events) doesn't necessarily apply at all to the exec case. (We should still get rid of that case involving the fake SIGKILL as it does today for other reasons, but that's not for now.) What I'd had in mind was skipping the exit report too, but I'd overlooked that __fatal_signal_pending() will no longer catch there. But the exec case muddles this as an API choice, regardless of implementation details. > Both can be fixed if we add spin_unlock_wait() before REPORT(). But imho > it would be safer if we start with spin_unlock_wait() in utrace_stop(), > perhaps there is something else to consider. I was only musing about the API choice. If we keep today's API where those reporting passes will still be made after a SIGKILL (but effectively ignore UTRACE_STOP), then synchronizing only in utrace_stop and utrace_finish_jctl is clearly right. Thanks, Roland From oleg at redhat.com Fri Oct 30 00:58:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 01:58:31 +0100 Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: <20091029224246.A9E31538@magilla.sf.frob.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> <20091028023058.7A6A37CDF@magilla.sf.frob.com> <20091029194235.GB13059@redhat.com> <20091029224246.A9E31538@magilla.sf.frob.com> Message-ID: <20091030005831.GC26508@redhat.com> On 10/29, Roland McGrath wrote: > > Another example is E1 does UTRACE_BLOCKSTEP and then E2 > does UTRACE_SINGLESTEP. > > Now single-step will win out, which is right. But E2 gets no notice about > this, so it can't know that the step is for an insn rather than a block. Yes. > In contrast, say utrace_control reduces both to UTRACE_REPORT, either > implicitly as we had been discussing before, or because E3 comes along > (before or after) and calls utrace_control(,,UTRACE_REPORT). Then E[123] > get report_quiesce(0) in their callback order. (We can't control that > order much today, but that is still to consolidate the utrace_control > ordering issue into that existing general ordering issue.) Yes, we can't control the callback order, and this means we have the same problem even without utrace_control(). Suppose that we enter utrace_resume(), E1->report_quiesce() returns UTRACE_BLOCKSTEP, then E2->report_quiesce() returns UTRACE_SINGLESTEP. UTRACE_SINGLESTEP wins, but E1 can't know about this. > > Yes, I hope I understand utrace.c ;) I meant user_enable_single_step(). > > I don't really understand it even in x86 case, to many low level magic. > > Ok, good. You officially don't need to understand that unless you want to. I want ;) Just every time I recall about enable_step/etc I have more prioritized pending problems. > > Afaics, we can kill ->stopped, but utrace_stop() and utrace_finish_jctl() > > should do unconditial spin_unlock_wait(utrace->lock) after resume (or > > lock/unlock). > > Ok. Please send a patch relative to utrace-cleanup with that code > including comments that explain those needs. OK, will do. Oleg. From roland at redhat.com Fri Oct 30 01:06:49 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 29 Oct 2009 18:06:49 -0700 (PDT) Subject: utrace_control(,,UTRACE_SINGLESTEP) In-Reply-To: Oleg Nesterov's message of Friday, 30 October 2009 01:58:31 +0100 <20091030005831.GC26508@redhat.com> References: <20091023232057.GA26888@redhat.com> <20091027201830.A18D17CDF@magilla.sf.frob.com> <20091027230838.GA12313@redhat.com> <20091027235557.143CD8D1@magilla.sf.frob.com> <20091028010648.GA18669@redhat.com> <20091028023058.7A6A37CDF@magilla.sf.frob.com> <20091029194235.GB13059@redhat.com> <20091029224246.A9E31538@magilla.sf.frob.com> <20091030005831.GC26508@redhat.com> Message-ID: <20091030010649.84311538@magilla.sf.frob.com> > Yes, we can't control the callback order, and this means we have the > same problem even without utrace_control(). Right, but that is the known item on the list to consider for API refinements. If at least utrace_control doesn't add any new wrinkles to that issue, then we know that if we later address the general callback order question so we're happy, we will be done altogether with the subject. Thanks, Roland From oleg at redhat.com Fri Oct 30 03:28:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 04:28:37 +0100 Subject: [PATCH 122-124] PTRACE_KILL tweaks + cosmetic cleanups Message-ID: <20091030032837.GA5731@redhat.com> PTRACE_KILL tweaks + cosmetic cleanups Oleg. From oleg at redhat.com Fri Oct 30 03:28:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 04:28:40 +0100 Subject: [PATCH 122] ptrace_request(PTRACE_KILL) should not(?) return -ESRCH Message-ID: <20091030032840.GA5735@redhat.com> On 10/29, Oleg Nesterov wrote: > > On 10/27, Roland McGrath wrote: > > > > > + case PTRACE_KILL: > > > + ret = 0; > > > + if (!child->exit_state) /* already dead */ > > > + ret = ptrace_resume(child, engine, request, SIGKILL); > > > + break; > > > > This could be inside ptrace_resume too. > > Yes, and we don't even need to check exit_state. Damn, this PTRACE_KILL is so weird. If we move this "case:" into ptrace_resume() path, then we have to make sure we do not return -ESRCH if request == SIGKILL (or we can ignore this incompatibility?) Apart from that, what it should actually do? If the tracee was STOPPED/TRACED, then it is equivalent to PTRACE_CONT,SIGKILL. Otherwise it has no effect except it can race with exit() and spoil ->exit_code, and wake_up_process() is not good if course. (I am talking about upstream). Perhaps it is better to leave this strange and special case in ptrace_request() like this patch does? Otherwise, we can change ptrace_resume() to never return the error if, say, utrace_set_events() fails, but while this is correct it looks a bit ugly. Please tell me what do you think, then I'll do other changes you suggested. --- kernel/ptrace.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~122_PTRACE_KILL 2009-10-26 03:18:12.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-30 04:00:15.000000000 +0100 @@ -1000,9 +1000,10 @@ int ptrace_request(struct task_struct *c break; case PTRACE_KILL: + /* Ugly historical behaviour. */ + if (task_is_traced(child)) + ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); ret = 0; - if (!child->exit_state) /* already dead */ - ret = ptrace_resume(child, engine, request, SIGKILL); break; default: From oleg at redhat.com Fri Oct 30 03:28:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 04:28:43 +0100 Subject: [PATCH 123] ptrace_notify_stop: kill the temporary WARN_ON() Message-ID: <20091030032843.GA5742@redhat.com> - Remove the temporary debugging check in ptrace_notify_stop(). - Remove the "XXX" marker in ptrace_resume(), the recent changes hopefully fixed the problems with jctl nested stops. --- kernel/ptrace.c | 9 +-------- 1 file changed, 1 insertion(+), 8 deletions(-) --- PU/kernel/ptrace.c~123_KILL_XXX 2009-10-30 04:00:15.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-30 04:01:41.000000000 +0100 @@ -807,11 +807,8 @@ void ptrace_notify_stop(struct task_stru { struct utrace_engine *engine = ptrace_lookup_engine(tracee); - if (IS_ERR(engine)) { - // XXX: temporary check, wrong with mutlitracing - WARN_ON(tracee->state != TASK_RUNNING); + if (IS_ERR(engine)) return; - } do_ptrace_notify_stop(ptrace_context(engine), tracee); utrace_engine_put(engine); @@ -921,10 +918,6 @@ static int ptrace_resume(struct task_str case PTRACE_EVENT_SIGNAL: context->signr = data; break; - - case 0: - // XXX: JCTL stop - break; } context->resume = action; From oleg at redhat.com Fri Oct 30 03:28:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 30 Oct 2009 04:28:45 +0100 Subject: [PATCH 124] s/context/ctx/ Message-ID: <20091030032845.GA5745@redhat.com> No changes in ptrace.o - s/context/ctx/ - line up ptrace_context->resume decl - remove kerneldoc bits from ptrace_traceme(). The comment is not very nice, I'd better remove it completely. --- kernel/ptrace.c | 192 +++++++++++++++++++++++++++----------------------------- 1 file changed, 95 insertions(+), 97 deletions(-) --- PU/kernel/ptrace.c~124_S_CONTEXT_CTX 2009-10-30 04:01:41.000000000 +0100 +++ PU/kernel/ptrace.c 2009-10-30 04:25:53.000000000 +0100 @@ -56,15 +56,15 @@ void __ptrace_unlink(struct task_struct } struct ptrace_context { - int options; + int options; - int signr; - siginfo_t *siginfo; + int signr; + siginfo_t *siginfo; - int stop_code; - unsigned long eventmsg; + int stop_code; + unsigned long eventmsg; - enum utrace_resume_action resume; + enum utrace_resume_action resume; }; #define PT_UTRACED 0x00001000 @@ -78,19 +78,19 @@ struct ptrace_context { /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF -static inline bool ptrace_event_pending(struct ptrace_context *context) +static inline bool ptrace_event_pending(struct ptrace_context *ctx) { - return context->stop_code != 0; + return ctx->stop_code != 0; } -static inline int get_stop_event(struct ptrace_context *context) +static inline int get_stop_event(struct ptrace_context *ctx) { - return context->stop_code >> 8; + return ctx->stop_code >> 8; } -static inline void set_stop_code(struct ptrace_context *context, int event) +static inline void set_stop_code(struct ptrace_context *ctx, int event) { - context->stop_code = (event << 8) | SIGTRAP; + ctx->stop_code = (event << 8) | SIGTRAP; } static inline struct ptrace_context * @@ -111,27 +111,27 @@ static struct utrace_engine * ptrace_reuse_engine(struct task_struct *tracee) { struct utrace_engine *engine; - struct ptrace_context *context; + struct ptrace_context *ctx; int err = -EPERM; engine = ptrace_lookup_engine(tracee); if (IS_ERR(engine)) return engine; - context = ptrace_context(engine); - if (unlikely(context->resume == UTRACE_DETACH)) { + ctx = ptrace_context(engine); + if (unlikely(ctx->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; + ctx->options = 0; + ctx->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; + ctx->resume = UTRACE_RESUME; /* synchronize with ptrace_report_signal() */ err = utrace_barrier(tracee, engine); } @@ -149,7 +149,7 @@ static struct utrace_engine * ptrace_attach_engine(struct task_struct *tracee) { struct utrace_engine *engine; - struct ptrace_context *context; + struct ptrace_context *ctx; if (unlikely(task_utrace_flags(tracee))) { engine = ptrace_reuse_engine(tracee); @@ -157,21 +157,21 @@ ptrace_attach_engine(struct task_struct return engine; } - context = kzalloc(sizeof(*context), GFP_KERNEL); - if (unlikely(!context)) + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (unlikely(!ctx)) return ERR_PTR(-ENOMEM); - context->resume = UTRACE_RESUME; + ctx->resume = UTRACE_RESUME; engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | UTRACE_ATTACH_EXCLUSIVE | UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, context); + &ptrace_utrace_ops, ctx); if (unlikely(IS_ERR(engine))) { if (engine != ERR_PTR(-ESRCH) && engine != ERR_PTR(-ERESTARTNOINTR)) engine = ERR_PTR(-EPERM); - kfree(context); + kfree(ctx); } return engine; @@ -181,7 +181,7 @@ static inline int ptrace_set_events(stru struct utrace_engine *engine, unsigned long options) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); /* * We need QUIESCE for resume handling, CLONE to check * for CLONE_PTRACE, other events are always reported. @@ -189,7 +189,7 @@ static inline int ptrace_set_events(stru unsigned long events = UTRACE_EVENT(QUIESCE) | UTRACE_EVENT(CLONE) | UTRACE_EVENT(EXEC) | UTRACE_EVENT_SIGNAL_ALL; - context->options = options; + ctx->options = options; if (options & PTRACE_O_TRACEEXIT) events |= UTRACE_EVENT(EXIT); @@ -255,9 +255,9 @@ static void ptrace_detach_task(struct ta return; if (sig) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - switch (get_stop_event(context)) { + switch (get_stop_event(ctx)) { case PTRACE_EVENT_SYSCALL_ENTRY: case PTRACE_EVENT_SYSCALL_EXIT: if (voluntary) @@ -266,8 +266,8 @@ static void ptrace_detach_task(struct ta case PTRACE_EVENT_SIGNAL: if (voluntary) - context->signr = sig; - context->resume = UTRACE_DETACH; + ctx->signr = sig; + ctx->resume = UTRACE_DETACH; action = UTRACE_RESUME; break; } @@ -287,13 +287,13 @@ static u32 ptrace_report_exit(enum utrac struct task_struct *task, long orig_code, long *code) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - WARN_ON(ptrace_event_pending(context) && + WARN_ON(ptrace_event_pending(ctx) && !signal_group_exit(task->signal)); - set_stop_code(context, PTRACE_EVENT_EXIT); - context->eventmsg = *code; + set_stop_code(ctx, PTRACE_EVENT_EXIT); + ctx->eventmsg = *code; return UTRACE_STOP; } @@ -333,22 +333,22 @@ static u32 ptrace_report_clone(enum utra unsigned long clone_flags, struct task_struct *child) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); int event = 0; - WARN_ON(ptrace_event_pending(context)); + WARN_ON(ptrace_event_pending(ctx)); if (clone_flags & CLONE_UNTRACED) { /* no events reported */ } else if (clone_flags & CLONE_VFORK) { - if (context->options & PTRACE_O_TRACEVFORK) + if (ctx->options & PTRACE_O_TRACEVFORK) event = PTRACE_EVENT_VFORK; - else if (context->options & PTRACE_O_TRACEVFORKDONE) + else if (ctx->options & PTRACE_O_TRACEVFORKDONE) event = PTRACE_EVENT_VFORK_DONE; } else if ((clone_flags & CSIGNAL) != SIGCHLD) { - if (context->options & PTRACE_O_TRACECLONE) + if (ctx->options & PTRACE_O_TRACECLONE) event = PTRACE_EVENT_CLONE; - } else if (context->options & PTRACE_O_TRACEFORK) { + } else if (ctx->options & PTRACE_O_TRACEFORK) { event = PTRACE_EVENT_FORK; } /* @@ -357,13 +357,13 @@ static u32 ptrace_report_clone(enum utra */ if ((event && event != PTRACE_EVENT_VFORK_DONE) || (clone_flags & CLONE_PTRACE)) - ptrace_clone_attach(parent, child, context->options); + ptrace_clone_attach(parent, child, ctx->options); if (!event) return UTRACE_RESUME; - set_stop_code(context, event); - context->eventmsg = child->pid; + set_stop_code(ctx, event); + ctx->eventmsg = child->pid; /* * We shouldn't stop now, inside the do_fork() path. * We will stop later, before return to user-mode. @@ -374,11 +374,11 @@ static u32 ptrace_report_clone(enum utra return UTRACE_STOP; } -static inline void set_syscall_code(struct ptrace_context *context, int event) +static inline void set_syscall_code(struct ptrace_context *ctx, int event) { - set_stop_code(context, event); - if (context->options & PTRACE_O_TRACESYSGOOD) - context->stop_code |= 0x80; + set_stop_code(ctx, event); + if (ctx->options & PTRACE_O_TRACESYSGOOD) + ctx->stop_code |= 0x80; } static u32 ptrace_report_syscall_entry(u32 action, @@ -386,13 +386,13 @@ static u32 ptrace_report_syscall_entry(u struct task_struct *task, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - WARN_ON(ptrace_event_pending(context)); + WARN_ON(ptrace_event_pending(ctx)); - set_syscall_code(context, PTRACE_EVENT_SYSCALL_ENTRY); + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); - if (unlikely(context->options & PTRACE_O_SYSEMU)) { + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { if (test_thread_flag(TIF_SINGLESTEP)) user_disable_single_step(task); return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; @@ -405,12 +405,12 @@ static u32 ptrace_report_syscall_exit(en struct task_struct *task, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - if (ptrace_event_pending(context)) + if (ptrace_event_pending(ctx)) return UTRACE_STOP; - set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); return UTRACE_STOP; } @@ -422,11 +422,11 @@ static u32 ptrace_report_exec(enum utrac const struct linux_binprm *bprm, struct pt_regs *regs) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - WARN_ON(ptrace_event_pending(context)); + WARN_ON(ptrace_event_pending(ctx)); - if (!(context->options & PTRACE_O_TRACEEXEC)) { + if (!(ctx->options & PTRACE_O_TRACEEXEC)) { /* * Old-fashioned ptrace'd exec just posts a plain signal. */ @@ -434,7 +434,7 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } - set_stop_code(context, PTRACE_EVENT_EXEC); + set_stop_code(ctx, PTRACE_EVENT_EXEC); return UTRACE_STOP; } @@ -480,10 +480,10 @@ static u32 ptrace_report_signal(u32 acti const struct k_sigaction *orig_ka, struct k_sigaction *return_ka) { - struct ptrace_context *context = ptrace_context(engine); - enum utrace_resume_action resume = context->resume; + struct ptrace_context *ctx = ptrace_context(engine); + enum utrace_resume_action resume = ctx->resume; - if (ptrace_event_pending(context)) { + if (ptrace_event_pending(ctx)) { action = utrace_signal_action(action); WARN_ON(action != UTRACE_SIGNAL_REPORT); return action | UTRACE_STOP; @@ -491,36 +491,36 @@ static u32 ptrace_report_signal(u32 acti switch (utrace_signal_action(action)) { case UTRACE_SIGNAL_HANDLER: - if (WARN_ON(context->siginfo)) - context->siginfo = NULL; + if (WARN_ON(ctx->siginfo)) + ctx->siginfo = NULL; if (resume != UTRACE_RESUME) { - set_stop_code(context, PTRACE_EVENT_SIGTRAP); + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); return UTRACE_STOP | UTRACE_SIGNAL_IGN; } case UTRACE_SIGNAL_REPORT: - if (!context->siginfo) + if (!ctx->siginfo) return resume | UTRACE_SIGNAL_IGN; - if (WARN_ON(context->siginfo != info)) + if (WARN_ON(ctx->siginfo != info)) return resume | UTRACE_SIGNAL_IGN; - context->siginfo = NULL; + ctx->siginfo = NULL; - return resume | resume_signal(task, context->signr, + return resume | resume_signal(task, ctx->signr, info, return_ka); default: - WARN_ON(context->siginfo); - context->siginfo = info; + WARN_ON(ctx->siginfo); + ctx->siginfo = info; /* - * context->siginfo points to the caller's stack. + * ctx->siginfo points to the caller's stack. * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->siginfo before return from get_signal_to_deliver(). */ utrace_control(task, engine, UTRACE_INTERRUPT); - context->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; - context->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; + ctx->signr = info->si_signo; return UTRACE_STOP | UTRACE_SIGNAL_IGN; } @@ -531,12 +531,12 @@ static u32 ptrace_report_quiesce(u32 act struct task_struct *task, unsigned long event) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); - if (ptrace_event_pending(context)) + if (ptrace_event_pending(ctx)) return UTRACE_STOP; - return event ? UTRACE_RESUME : context->resume; + return event ? UTRACE_RESUME : ctx->resume; } static void ptrace_release(void *data) @@ -638,9 +638,7 @@ out: return retval; } -/** - * ptrace_traceme -- helper for PTRACE_TRACEME - * +/* * Performs checks and sets PT_UTRACED. * Should be used by all ptrace implementations for PTRACE_TRACEME. */ @@ -737,13 +735,13 @@ static int ptrace_set_options(struct tas } static int ptrace_rw_siginfo(struct task_struct *tracee, - struct ptrace_context *context, + struct ptrace_context *ctx, siginfo_t *info, bool write) { unsigned long flags; int err; - switch (get_stop_event(context)) { + switch (get_stop_event(ctx)) { case 0: /* jctl stop */ return -EINVAL; @@ -752,9 +750,9 @@ static int ptrace_rw_siginfo(struct task if (lock_task_sighand(tracee, &flags)) { if (likely(task_is_traced(tracee))) { if (write) - *context->siginfo = *info; + *ctx->siginfo = *info; else - *info = *context->siginfo; + *info = *ctx->siginfo; err = 0; } unlock_task_sighand(tracee, &flags); @@ -766,7 +764,7 @@ static int ptrace_rw_siginfo(struct task if (!write) { memset(info, 0, sizeof(*info)); info->si_signo = SIGTRAP; - info->si_code = context->stop_code & PTRACE_EVENT_MASK; + info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; info->si_pid = task_pid_vnr(tracee); info->si_uid = task_uid(tracee); } @@ -775,7 +773,7 @@ static int ptrace_rw_siginfo(struct task } } -static void do_ptrace_notify_stop(struct ptrace_context *context, +static void do_ptrace_notify_stop(struct ptrace_context *ctx, struct task_struct *tracee) { /* @@ -784,7 +782,7 @@ static void do_ptrace_notify_stop(struct * for wait_task_stopped()->task_stopped_code(), we should * change it to use ptrace_context. */ - tracee->exit_code = context->stop_code & PTRACE_EVENT_MASK; + tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; WARN_ON(!tracee->exit_code); read_lock(&tasklist_lock); @@ -817,11 +815,11 @@ void ptrace_notify_stop(struct task_stru static int ptrace_resume_action(struct task_struct *tracee, struct utrace_engine *engine, long request) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); unsigned long events; int action; - context->options &= ~PTRACE_O_SYSEMU; + ctx->options &= ~PTRACE_O_SYSEMU; events = engine->flags & ~UTRACE_EVENT_SYSCALL; action = UTRACE_RESUME; @@ -848,7 +846,7 @@ static int ptrace_resume_action(struct t return -EIO; action = UTRACE_SINGLESTEP; case PTRACE_SYSEMU: - context->options |= PTRACE_O_SYSEMU; + ctx->options |= PTRACE_O_SYSEMU; events |= UTRACE_EVENT(SYSCALL_ENTRY); break; #endif @@ -869,7 +867,7 @@ static int ptrace_resume(struct task_str struct utrace_engine *engine, long request, long data) { - struct ptrace_context *context = ptrace_context(engine); + struct ptrace_context *ctx = ptrace_context(engine); int action; if (!valid_signal(data)) @@ -879,10 +877,10 @@ static int ptrace_resume(struct task_str if (action < 0) return action; - switch (get_stop_event(context)) { + switch (get_stop_event(ctx)) { case PTRACE_EVENT_VFORK: - if (context->options & PTRACE_O_TRACEVFORKDONE) { - set_stop_code(context, PTRACE_EVENT_VFORK_DONE); + if (ctx->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); action = UTRACE_REPORT; } break; @@ -892,8 +890,8 @@ static int ptrace_resume(struct task_str case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: if (request == PTRACE_SYSCALL) { - set_syscall_code(context, PTRACE_EVENT_SYSCALL_EXIT); - do_ptrace_notify_stop(context, tracee); + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + do_ptrace_notify_stop(ctx, tracee); return 0; } /* fallthrough, but suppress send_sig_info() below */ @@ -916,11 +914,11 @@ static int ptrace_resume(struct task_str break; case PTRACE_EVENT_SIGNAL: - context->signr = data; + ctx->signr = data; break; } - context->resume = action; + ctx->resume = action; ptrace_wake_up(tracee, engine, action, true); return 0; } From roland at redhat.com Fri Oct 30 07:36:46 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 30 Oct 2009 00:36:46 -0700 (PDT) Subject: [PATCH 122] ptrace_request(PTRACE_KILL) should not(?) return -ESRCH In-Reply-To: Oleg Nesterov's message of Friday, 30 October 2009 04:28:40 +0100 <20091030032840.GA5735@redhat.com> References: <20091030032840.GA5735@redhat.com> Message-ID: <20091030073646.E09419BF@magilla.sf.frob.com> > Damn, this PTRACE_KILL is so weird. Yes. It's useless. Not regressing on the expectations of stupid old programs that don't really know what it does is all that's required. > Apart from that, what it should actually do? It should work like PTRACE_CONT,SIGKILL but the only error case is -ESRCH when you aren't the tracer and always returns 0 otherwise. That's the whole of its mandate. > If the tracee was STOPPED/TRACED, then it is equivalent to PTRACE_CONT,SIGKILL. > Otherwise it has no effect except it can race with exit() and spoil ->exit_code, > and wake_up_process() is not good if course. (I am talking about upstream). Correct. In job control stop (including one already turned into TASK_TRACED by a prior ptrace call), the resumption signal is ignored. So the only reliable effect at all is when it's in a proper ptrace stop that doesn't otherwise swallow signals (i.e. exactly PTRACE_CONT,SIGKILL that ignores liveness/stoppedness errors). In every other case it has no effect at best, so fixing that to "no effect at all" is just fine. > Please tell me what do you think, then I'll do other changes you suggested. In the old code, PTRACE_KILL can never fail once the initial attachedness test has passed. So: (void) ptrace_resume(child, engine, request, SIGKILL); ret = 0; /* Historical compatibility. */ is probably fine. Thanks, Roland From newsletter at usbportugal.com Fri Oct 30 13:41:13 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Fri, 30 Oct 2009 14:41:13 +0100 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_44?= Message-ID: <9bb72cb4e9a84e9d6462a4dac13a65b7@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From ananth at in.ibm.com Fri Oct 30 16:14:14 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Fri, 30 Oct 2009 21:44:14 +0530 Subject: PTRACE_EVENT_SIGTRAP In-Reply-To: <20091029194158.GA13059@redhat.com> References: <20091026032855.GA6277@redhat.com> <20091028062410.8A83B8D1@magilla.sf.frob.com> <20091029194158.GA13059@redhat.com> Message-ID: <20091030161414.GB22230@in.ibm.com> On Thu, Oct 29, 2009 at 08:41:58PM +0100, Oleg Nesterov wrote: > On 10/27, Roland McGrath wrote: > @@ -495,8 +494,8 @@ static u32 ptrace_report_signal(u32 acti > context->siginfo = NULL; > > if (resume != UTRACE_RESUME) { > - set_stop_code(context, PTRACE_EVENT_SIGTRAP); > - return UTRACE_STOP | UTRACE_SIGNAL_IGN; > + info->si_signo = SIGTRAO; Surely you meant SIGTRAP here, right? :-) From teste at oxydo.enviamarketing.com.br Thu Oct 29 16:11:29 2009 From: teste at oxydo.enviamarketing.com.br (Guardia Tercerização de Serviços) Date: Thu, 29 Oct 2009 14:11:29 -0200 Subject: =?iso-8859-1?q?Guardia_Terceriza=E7=E3o?= Message-ID: An HTML attachment was scrubbed... URL: From news at maisservicos.com Sat Oct 31 22:01:36 2009 From: news at maisservicos.com (Codigo da Estrada 2009) Date: Sat, 31 Oct 2009 22:01:36 +0000 Subject: Exame de codigo! Message-ID: <20091031220130.9D64040434@server17.nortenet.pt> Caso n?o visualize correctamente este e-mail, por favor clique AQUI. EXAME DE C?DIGO Teste os seus conhecimentos do Novo C?digo da Estrada e verifique se est? apto a conduzir. GARANTIA DE CONFIDENCIALIDADE Insira os seus dados e receba um pin no seu telem?vel para validar a sua identidade e saber o resultado do teste. NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From reservaciones at laspalmasclub.com Sat Oct 31 07:09:34 2009 From: reservaciones at laspalmasclub.com (Las Palmas By The Sea resort) Date: Sat, 31 Oct 2009 03:09:34 -0400 Subject: Autumn and winter vacations on the beach Message-ID: <9adf986c6978002cfd7e457ff10a4356@www.vallarta-paradise.com> An HTML attachment was scrubbed... URL: From cornel at upload-ro.ro Sat Oct 31 00:51:49 2009 From: cornel at upload-ro.ro (cornel) Date: Sat, 31 Oct 2009 02:51:49 +0200 Subject: cursuri perfectionare Message-ID: <20091030.XESWTIASYMUHNQYF@upload-ro.ro> An HTML attachment was scrubbed... URL: From noreply at oxydo.enviamarketing.com.br Thu Oct 29 03:03:18 2009 From: noreply at oxydo.enviamarketing.com.br (Guardia Tercerizações) Date: Thu, 29 Oct 2009 01:03:18 -0200 Subject: =?iso-8859-1?q?Guardia_Terceriza=E7=E3o_de_Servi=E7os?= Message-ID: An HTML attachment was scrubbed... URL: From teste at oxydo.enviamarketing.com.br Fri Oct 30 21:18:42 2009 From: teste at oxydo.enviamarketing.com.br (Guardia Tercerização de Serviços) Date: Fri, 30 Oct 2009 19:18:42 -0200 Subject: =?iso-8859-1?q?Guardia_Terceriza=E7=E3o?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Nov 2 06:44:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:26 +0100 Subject: upstream/utrace: copy_process() && TIF_SINGLESTEP Message-ID: <20091102064426.GA30242@redhat.com> shouldn't copy_process() do clear_tsk_thread_flag(child, TIF_SINGLESTEP) ? I'll recheck this, but looks like both upstream and utrace-ptrace should do this. Otherwise, the new child can start with TIF_SINGLESTEP copied from parent's ti->flags. This looks just wrong, but if we do not auto-attach this looks much worse. No? Oleg. From oleg at redhat.com Mon Nov 2 06:44:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:47 +0100 Subject: [PATCH 125-129] SIGTRAP changes Message-ID: <20091102064447.GA30264@redhat.com> It took me more time/efforts than I expected, and probably needs more changes. I still owe you review/fixes for utrace-cleanup branch. Oleg. From oleg at redhat.com Mon Nov 2 06:44:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:51 +0100 Subject: [PATCH 125] ptrace_request: turn ptrace_resume() into default case Message-ID: <20091102064451.GA30267@redhat.com> As you suggested, we can simplify ptrace_request()->ptrace_resume() path, ptrace_resume_action() checks all "for resume" requests except PTRACE_CONT. --- kernel/ptrace.c | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) --- PU/kernel/ptrace.c~125_PTRACE_REQUEST_DEFAULT_RESUME 2009-10-30 04:25:53.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-01 22:48:24.000000000 +0100 @@ -854,6 +854,11 @@ static int ptrace_resume_action(struct t case PTRACE_SYSCALL: events |= UTRACE_EVENT_SYSCALL; break; + + case PTRACE_CONT: + break; + default: + return -EIO; } if (events != engine->flags && @@ -975,21 +980,6 @@ int ptrace_request(struct task_struct *c ret = ptrace_detach(child, data); break; -#ifdef PTRACE_SINGLESTEP - case PTRACE_SINGLESTEP: -#endif -#ifdef PTRACE_SINGLEBLOCK - case PTRACE_SINGLEBLOCK: -#endif -#ifdef PTRACE_SYSEMU - case PTRACE_SYSEMU: - case PTRACE_SYSEMU_SINGLESTEP: -#endif - case PTRACE_SYSCALL: - case PTRACE_CONT: - ret = ptrace_resume(child, engine, request, data); - break; - case PTRACE_KILL: /* Ugly historical behaviour. */ if (task_is_traced(child)) @@ -998,7 +988,7 @@ int ptrace_request(struct task_struct *c break; default: - ret = -EIO; + ret = ptrace_resume(child, engine, request, data); break; } From oleg at redhat.com Mon Nov 2 06:44:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:53 +0100 Subject: [PATCH 126] prepare ptrace_report_signal() to synthesize SIGTRAP Message-ID: <20091102064453.GA30274@redhat.com> Preparation, no functional changes. - change ptrace_report_signal()->resume_signal() to clear ctx->signr, not only ctx->siginfo. This allows us to overload ctx->signr. IOW, with this patch ctx->signr != 0 is only possible when a tracee is stopped with the valid ctx->siginfo after reporting the signal. - move the "default" case out of "switch()". This allows to re-use this code path to inject SIGTRAP's. --- kernel/ptrace.c | 39 +++++++++++++++++++++++---------------- 1 file changed, 23 insertions(+), 16 deletions(-) --- PU/kernel/ptrace.c~126_REPORT_SIGNAL_MOVE_DEFAULT 2009-11-01 22:48:24.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-02 00:31:30.000000000 +0100 @@ -440,9 +440,15 @@ static u32 ptrace_report_exec(enum utrac } static enum utrace_signal_action resume_signal(struct task_struct *task, - int signr, siginfo_t *info, + struct ptrace_context *ctx, struct k_sigaction *return_ka) { + siginfo_t *info = ctx->siginfo; + int signr = ctx->signr; + + ctx->siginfo = NULL; + ctx->signr = 0; + /* Did the debugger cancel the sig? */ if (!signr) return UTRACE_SIGNAL_IGN; @@ -505,25 +511,26 @@ static u32 ptrace_report_signal(u32 acti if (WARN_ON(ctx->siginfo != info)) return resume | UTRACE_SIGNAL_IGN; - ctx->siginfo = NULL; - return resume | resume_signal(task, ctx->signr, - info, return_ka); + return resume | resume_signal(task, ctx, return_ka); + default: - WARN_ON(ctx->siginfo); - ctx->siginfo = info; - /* - * ctx->siginfo points to the caller's stack. - * Make sure the subsequent UTRACE_SIGNAL_REPORT clears - * ->siginfo before return from get_signal_to_deliver(). - */ - utrace_control(task, engine, UTRACE_INTERRUPT); + break; + } - ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | info->si_signo; - ctx->signr = info->si_signo; + WARN_ON(ctx->siginfo); + ctx->siginfo = info; + /* + * ctx->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; - } + ctx->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; } static u32 ptrace_report_quiesce(u32 action, From oleg at redhat.com Mon Nov 2 06:44:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:56 +0100 Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() Message-ID: <20091102064456.GA30277@redhat.com> Move send_sigtrap() logic from ptrace_resume() to ptrace_report_signal(). ptrace_resume() sets ctx->signr = SIGTRAP and returns UTRACE_INTERRUPT. ptrace_report_signal() notices SIGTRAP, fills *info and reports the signal. fill_sigtrap_info() mimics x86-specific send_sigtrap(), therefore: - it sets task->thread.trap_no/error_code under CONFIG_X86, what should it do in the #else case? - it sets info->si_addr = KSTK_EIP() which doesn't check user_mode_vm(). Hopefully this is OK? - with or without this patch utrace-ptrace assumes that PTRACE_SINGLESTEP after PTRACE_EVENT_SYSCALL_EXIT needs fill_sigtrap_info()'ed signal, this may break or fix !x86 machines, and I don't know how to check. Perhaps ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) needs ifdef's. User-visible changes: - unlike send_sigtrap()->force_sig_info() we don't unblock SIGTRAP or reset the handler - UTRACE_SIGNAL_REPORT synthesizes the "extra" SIGTRAP even if this signal is already penging these changes looks good (but see the next patch). However, any user-visible change is dangerous. For example, suppose a tracee reports SYSCALL_EXIT and the tracer does ptrace(PTRACE_SINGLESTEP, SIGTRAP). Before this change (or with upstream kernel) send_sigtrap() is "lost", because ptrace_report_syscall() does send_sig(SIGTRAP, current) first. With this patch we report TRAP_BRKPT and then the normal SIGTRAP. Also, we don't depend on dequeue_signal() which can dequeue another signr before SIGTRAP. Again, looks like a fix actually, but may break some test-case or stupid app. --- kernel/ptrace.c | 35 +++++++++++++++++++++++++++-------- 1 file changed, 27 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~127_OFFLOAD_SEND_SIGTRAP_TO_REPORT_SIGNAL 2009-11-02 00:31:30.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-02 05:31:46.000000000 +0100 @@ -439,6 +439,18 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } +static void fill_sigtrap_info(struct task_struct *task, siginfo_t *info) +{ +#ifdef CONFIG_X86 + task->thread.trap_no = 1; + task->thread.error_code = 0; +#endif + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = TRAP_BRKPT; + info->si_addr = (void __user*)KSTK_EIP(task); +} + static enum utrace_signal_action resume_signal(struct task_struct *task, struct ptrace_context *ctx, struct k_sigaction *return_ka) @@ -506,8 +518,15 @@ static u32 ptrace_report_signal(u32 acti } case UTRACE_SIGNAL_REPORT: - if (!ctx->siginfo) - return resume | UTRACE_SIGNAL_IGN; + if (!ctx->siginfo) { + if (!ctx->signr) + return resume | UTRACE_SIGNAL_IGN; + + WARN_ON(ctx->signr != SIGTRAP); + /* set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) */ + fill_sigtrap_info(task, info); + break; + } if (WARN_ON(ctx->siginfo != info)) return resume | UTRACE_SIGNAL_IGN; @@ -911,12 +930,12 @@ static int ptrace_resume(struct task_str case PTRACE_EVENT_SYSCALL_EXIT: if (action != UTRACE_RESUME) { - read_lock(&tasklist_lock); - if (tracee->sighand) - send_sigtrap(tracee, task_pt_regs(tracee), - 0, TRAP_BRKPT); - read_unlock(&tasklist_lock); - action = UTRACE_RESUME; + /* + * single-stepping. UTRACE_SIGNAL_REPORT will + * synthesize a trap to follow the syscall insn. + */ + ctx->signr = SIGTRAP; + action = UTRACE_INTERRUPT; } /* fallthrough */ From oleg at redhat.com Mon Nov 2 06:44:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:44:58 +0100 Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() Message-ID: <20091102064458.GA30280@redhat.com> Suppose that a PTRACE_O_TRACEFORK tracee does fork() and stops in SYSCALL_ENTRY state. The tracer does PTRACE_SINGLESTEP. In this case the tracee resumes and stops after syscall_trace_leave() to report PTRACE_EVENT_FORK, but since it passes syscall_trace_leave() with TIF_SINGLESTEP set the tracee gets the unwanted send_sigtrap(). Note: of course, this is hack. I think this should be move to utrace layer. Unless we are going to call finish_resume_report(), finish_report() should look at report->action and clear TIF_SINGLESTEP when needed. What do you think? --- kernel/ptrace.c | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) --- PU/kernel/ptrace.c~128_SUPRESS_UNWANTED_SEND_SIGTRAP 2009-11-02 05:31:46.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-02 06:16:53.000000000 +0100 @@ -327,6 +327,16 @@ static void ptrace_clone_attach(struct t set_tsk_thread_flag(child, TIF_SIGPENDING); } +/* + * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). + * Called when we are going to emulate the stop before SYSCALL_EXIT. + */ +static void suppress_sigtrap(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) + user_disable_single_step(task); +} + static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, @@ -362,6 +372,8 @@ static u32 ptrace_report_clone(enum utra if (!event) return UTRACE_RESUME; + suppress_sigtrap(parent); + set_stop_code(ctx, event); ctx->eventmsg = child->pid; /* @@ -393,8 +405,7 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { - if (test_thread_flag(TIF_SINGLESTEP)) - user_disable_single_step(task); + suppress_sigtrap(task); return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; } return UTRACE_SYSCALL_RUN | UTRACE_STOP; @@ -434,6 +445,7 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } + suppress_sigtrap(task); set_stop_code(ctx, PTRACE_EVENT_EXEC); return UTRACE_STOP; From oleg at redhat.com Mon Nov 2 06:45:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 2 Nov 2009 07:45:01 +0100 Subject: [PATCH 129] turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL Message-ID: <20091102064501.GA30287@redhat.com> Kill PTRACE_EVENT_SIGTRAP state, report PTRACE_EVENT_SIGNAL with the valid ctx->siginfo instead. Note: we can change ptrace_report_exec() to set ->signr = SIGTRAP and return UTRACE_INTERRUPT too, instead of send_sig(SIGTRAP). We can even change ptrace_resume(PTRACE_EVENT_SIGNAL) similarly, but this needs more efforts. --- kernel/ptrace.c | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) --- PU/kernel/ptrace.c~129_KILL_PTRACE_EVENT_SIGTRAP 2009-11-02 06:16:53.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-02 06:54:49.000000000 +0100 @@ -73,8 +73,7 @@ struct ptrace_context { #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) #define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGTRAP (3 << 16) -#define PTRACE_EVENT_SIGNAL (4 << 16) +#define PTRACE_EVENT_SIGNAL (3 << 16) /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF @@ -525,9 +524,12 @@ static u32 ptrace_report_signal(u32 acti ctx->siginfo = NULL; if (resume != UTRACE_RESUME) { - set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; + WARN_ON(resume != UTRACE_BLOCKSTEP && + resume != UTRACE_SINGLESTEP); + WARN_ON(ctx->signr); + ctx->signr = SIGTRAP; } + /* fallthrough */ case UTRACE_SIGNAL_REPORT: if (!ctx->siginfo) { @@ -535,7 +537,10 @@ static u32 ptrace_report_signal(u32 acti return resume | UTRACE_SIGNAL_IGN; WARN_ON(ctx->signr != SIGTRAP); - /* set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) */ + /* + * set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) or + * by UTRACE_SIGNAL_HANDLER above. + */ fill_sigtrap_info(task, info); break; } From roland at redhat.com Mon Nov 2 09:56:39 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 2 Nov 2009 01:56:39 -0800 (PST) Subject: upstream/utrace: copy_process() && TIF_SINGLESTEP In-Reply-To: Oleg Nesterov's message of Monday, 2 November 2009 07:44:26 +0100 <20091102064426.GA30242@redhat.com> References: <20091102064426.GA30242@redhat.com> Message-ID: <20091102095639.4B8164EC@magilla.sf.frob.com> You are right. I added step-fork to ptrace-tests for this. The place that should do this is arch/*:copy_thread. TIF_* bits are arch implementation details. x86 and powerpc both have a TIF_SINGLESTEP that should be cleared, and others might too. Each arch maintainer should check if their implementation has this issue. This is a pure arch bug that has nothing in particular to do with utrace. It should impact us no differently than it does upstream. So just take it there as an arch-specific issue for all arch maintainers to check on. Thanks, Roland From roland at redhat.com Mon Nov 2 10:06:46 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 2 Nov 2009 02:06:46 -0800 (PST) Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: Oleg Nesterov's message of Monday, 2 November 2009 07:44:56 +0100 <20091102064456.GA30277@redhat.com> References: <20091102064456.GA30277@redhat.com> Message-ID: <20091102100646.5593F4EC@magilla.sf.frob.com> > - it sets task->thread.trap_no/error_code under CONFIG_X86, > what should it do in the #else case? This can't be this way. It has to be a proper arch hook of some kind. > - it sets info->si_addr = KSTK_EIP() which doesn't check > user_mode_vm(). Hopefully this is OK? Ditto. The si_code/si_addr settings are altogether arch-specific. As long as you are using x86 details with #ifdef for hack drafts, just copy the exact details used in x86's send_sigtrap. > - with or without this patch utrace-ptrace assumes that > PTRACE_SINGLESTEP after PTRACE_EVENT_SYSCALL_EXIT needs > fill_sigtrap_info()'ed signal, this may break or fix !x86 > machines, and I don't know how to check. Perhaps > ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) needs ifdef's. It should be easy enough to add a ptrace-tests case that distinguishes the two behaviors. I think we can then call the non-x86 behaviors broken and harmonize on the x86 behavior to make that test pass everywhere. > - unlike send_sigtrap()->force_sig_info() we don't unblock > SIGTRAP or reset the handler This is nicer for debugger things actually, but we don't have such niceness for real traps and won't soon. IMHO it is best to start with doing exactly what the old x86 code does, which is force_sig_info--which is also making all machines uniformly do "what a real single-step trap does" and is thus consistent in this PTRACE_SINGLESTEP case matching all others, which we have been saying is a sensible principle. > these changes looks good (but see the next patch). However, any > user-visible change is dangerous. Let's not roll it in. As well as it just being bad form to roll that into implementation detail changes, it makes things less consistent rather than more (on x86, anyway, and arguably across the board). Thanks, Roland From kasi at tyrolean.at Mon Nov 2 14:27:56 2009 From: kasi at tyrolean.at (Doll Orozco) Date: Mon, 2 Nov 2009 14:27:56 -0000 Subject: Sensational sales Message-ID: <002f01ca5bc8$abd06ab0$a37384be@sppt130qqcdus> Great variety of little helpers for your health. http://pef.pharmlydon43.com/ From oleg at redhat.com Tue Nov 3 05:37:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Nov 2009 06:37:47 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091029020329.A58A0534@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> Message-ID: <20091103053747.GA11794@redhat.com> On 10/28, Roland McGrath wrote: > > I've made a new branch, utrace-cleanup. > This forks from utrace-indirect and has: > > 26fefca utrace: sticky resume action > 28b2774 utrace: remove ->stopped field I am not sure I understand the new code in details - too much changes. Anyway, I can never understand the code after the first reading. At first glance, imho this change is "right in general" but: 1. This breaks the current implementation of utrace-ptrace. I guess I misunderstood you when we discussed this before, I thought that the tracee should handle UTRACE_SINGLESTEP right after resume and call user_enable_single_step(). However, enable_step() is called at utrace_resume/utrace_get_signal time, this is too late for ptrace. I guess this branch is the code which will be sent to lkml, right? In this case utrace-cleanup should be merged into utrace-ptrace right now, then I need to fix ptrace. Basically, ptrace_report_quiesce() and ptrace_report_interrupt() should detect the case when the tracee was resumed by PTRACE_XXXSTEP and then it passed syscall_trace_leave() without TIF_SINGLESTEP, and synthesize a trap. The main problem is that this is not consistent across the different arch'es :[ 2. Cosmetic, but the usage of utrace_task_alloc() looks a bit strange. Why it returns bool, not struct utrace * ? 3. Now that we have utrace->resume, can't we kill report->resume_action ? 4. One of the changes in utrace_get_signal() doesn't look exactly right. if (utrace->resume < UTRACE_RESUME || utrace->signal_handler) { ... if (resume > UTRACE_REPORT) { report.action = resume; finish_resume_report(&report); } Yes, we need finish_resume_report() here, but since report->takers is not set, finish_report_reset() will always call utrace_reset(). OTOH, we can't set ->takers before finish_resume_report(), we can miss UTRACE_DETACH request. utrace_control(DETACH)->utrace_do_stop() does not change utrace->resume != UTRACE_RESUME. And since utrace_do_stop() never "upgrades" utrace->resume, we have another problem: UTRACE_STOP request can be lost here. 5. utrace_resume() has the same problems. If report->action != REPORT we do not call callbacks and finish_resume_report() is called with ->takers == F. 6. But! I think utrace_resume() was always wrong here. Because it calls start_callback(events => 0) and thus we nevet set ->takers. 7. utrace_attach_task() has an implicit wmb() between "->utrace = new_utrace" and "->utrace_flags = REAP", this is good. But, for example, tracehook_force_sigpending() does not have rmb(), this means utrace_interrupt_pending() can OOPS in theory. 8. Completely off-topic, but utrace_control() has a very strange comment under "case UTRACE_INTERRUPT", * When it's stopped, we know it's always going * through utrace_get_signal() and will recalculate. can't recall if it were ever true, but surely it is not now? Oleg. From oleg at redhat.com Tue Nov 3 05:38:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 3 Nov 2009 06:38:43 +0100 Subject: [PATCH 1/1] re-introduce utrace_finish_stop() to fix the race with SIGKILL In-Reply-To: <20091029020329.A58A0534@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> Message-ID: <20091103053843.GB11794@redhat.com> A killed tracee should do nothing until the tracer drops utrace->lock. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 2 ++ include/linux/utrace.h | 2 ++ kernel/utrace.c | 16 +++++++++++++++- 3 files changed, 19 insertions(+), 1 deletion(-) --- UTRACE/include/linux/tracehook.h~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/include/linux/tracehook.h 2009-11-03 05:38:49.000000000 +0100 @@ -531,6 +531,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_stop(); } #define DEATH_REAP -1 --- UTRACE/include/linux/utrace.h~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/include/linux/utrace.h 2009-11-03 05:39:41.000000000 +0100 @@ -98,6 +98,8 @@ bool utrace_interrupt_pending(void) __attribute__((weak)); void utrace_resume(struct task_struct *, struct pt_regs *) __attribute__((weak)); +void utrace_finish_stop(void) + __attribute__((weak)); int utrace_get_signal(struct task_struct *, struct pt_regs *, siginfo_t *, struct k_sigaction *) __attribute__((weak)); --- UTRACE/kernel/utrace.c~1_FINISH_STOP 2009-11-03 01:38:22.000000000 +0100 +++ UTRACE/kernel/utrace.c 2009-11-03 06:10:10.000000000 +0100 @@ -701,7 +701,7 @@ static bool utrace_do_stop(struct task_s if (task_is_stopped(target)) { /* * Stopped is considered quiescent; when it wakes up, it will - * go through utrace_finish_jctl() before doing anything else. + * go through utrace_finish_stop() before doing anything else. */ spin_lock_irq(&target->sighand->siglock); if (likely(task_is_stopped(target))) @@ -809,6 +809,18 @@ static bool utrace_reset(struct task_str return !flags; } +void utrace_finish_stop(void) +{ + /* + * If we were task_is_traced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { + struct utrace *utrace = task_utrace_struct(current); + spin_unlock_wait(&utrace->lock); + } +} + /* * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. * @task == current, @utrace == current->utrace, which is not locked. @@ -875,6 +887,8 @@ relock: schedule(); + utrace_finish_stop(); + /* * While in TASK_TRACED, we were considered "frozen enough". * Now that we woke up, it's crucial if we're supposed to be From roland at redhat.com Tue Nov 3 22:05:05 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 3 Nov 2009 14:05:05 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Tuesday, 3 November 2009 06:37:47 +0100 <20091103053747.GA11794@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> Message-ID: <20091103220505.C1C85113@magilla.sf.frob.com> > 2. Cosmetic, but the usage of utrace_task_alloc() looks a bit strange. > Why it returns bool, not struct utrace * ? The pointer it would return is always target->utrace or it's NULL. So the bool just says which of those it would be instead. Either way I imagine it should be inlined so the check on the return value from kmem_cache_zalloc is the only test/branch. I have no special opinion about the cosmetic choice. Whatever you and/or upstream prefer is fine. Send a patch if you would like it to be different. Thanks, Roland From roland at redhat.com Tue Nov 3 22:11:12 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 3 Nov 2009 14:11:12 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Tuesday, 3 November 2009 06:37:47 +0100 <20091103053747.GA11794@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> Message-ID: <20091103221112.B22FD113@magilla.sf.frob.com> > 8. Completely off-topic, but utrace_control() has a very strange comment > under "case UTRACE_INTERRUPT", > > * When it's stopped, we know it's always going > * through utrace_get_signal() and will recalculate. > > can't recall if it were ever true, but surely it is not now? I think what's true now is what's always been true. The comment is a bit confusing, though. The two kinds of stopped are inside do_signal_stop() and inside utrace_stop(). In the former, it is inside the signal-checking loop and will check again. In the latter, utrace_stop() ends with a call to recalc_sigpending(). Thanks, Roland From roland at redhat.com Tue Nov 3 22:13:55 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 3 Nov 2009 14:13:55 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Tuesday, 3 November 2009 06:37:47 +0100 <20091103053747.GA11794@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> Message-ID: <20091103221355.81012113@magilla.sf.frob.com> > 7. utrace_attach_task() has an implicit wmb() between "->utrace = new_utrace" > and "->utrace_flags = REAP", this is good. > > But, for example, tracehook_force_sigpending() does not have rmb(), > this means utrace_interrupt_pending() can OOPS in theory. Ok. Please send a patch. Off hand it seems to me it isn't worth using a barrier because the winner of that race doesn't matter. So: struct utrace *utrace = task_utrace_struct(current); return likely(utrace) && utrace->resume == UTRACE_INTERRUPT; is fine, right? (With comment changes to explain the need for the check.) Thanks, Roland From roland at redhat.com Tue Nov 3 23:14:11 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 3 Nov 2009 15:14:11 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Tuesday, 3 November 2009 06:37:47 +0100 <20091103053747.GA11794@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> Message-ID: <20091103231411.5AB7471C3@magilla.sf.frob.com> > 4. One of the changes in utrace_get_signal() doesn't look exactly right. > > if (utrace->resume < UTRACE_RESUME || utrace->signal_handler) { > ... > if (resume > UTRACE_REPORT) { > report.action = resume; > finish_resume_report(&report); > } > > Yes, we need finish_resume_report() here, but since report->takers > is not set, finish_report_reset() will always call utrace_reset(). > > OTOH, we can't set ->takers before finish_resume_report(), we can > miss UTRACE_DETACH request. utrace_control(DETACH)->utrace_do_stop() > does not change utrace->resume != UTRACE_RESUME. > > And since utrace_do_stop() never "upgrades" utrace->resume, we have > another problem: UTRACE_STOP request can be lost here. Hmm. Maybe this? diff --git a/kernel/utrace.c b/kernel/utrace.c index f46854b..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1740,8 +1740,6 @@ static void finish_resume_report(struct struct task_struct *task, struct utrace *utrace) { - finish_report_reset(task, utrace, report); - switch (report->action) { case UTRACE_STOP: utrace_stop(task, utrace, report->resume_action); @@ -1829,6 +1827,8 @@ void utrace_resume(struct task_struct *t report.action = UTRACE_RESUME; list_for_each_entry(engine, &utrace->attached, entry) start_callback(utrace, &report, engine, task, 0); + + finish_report_reset(task, utrace, report); } /* @@ -2147,6 +2147,7 @@ int utrace_get_signal(struct task_struct * as in utrace_resume(), above. After we've dealt with that, * our caller will relock and come back through here. */ + finish_report_reset(task, utrace, &report); finish_resume_report(&report, task, utrace); if (unlikely(fatal_signal_pending(task))) { > 5. utrace_resume() has the same problems. If report->action != REPORT > we do not call callbacks and finish_resume_report() is called with > ->takers == F. > > 6. But! I think utrace_resume() was always wrong here. Because it > calls start_callback(events => 0) and thus we nevet set ->takers. I think that change covers these too. What do you think? Thanks, Roland From info at campaigns.canal-marketing.com Wed Nov 4 15:15:24 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Bouygues_Telecom?=) Date: Wed, 04 Nov 2009 16:15:24 +0100 Subject: Iphone 3GS + Forfait NEO ILLIMITE Message-ID: An HTML attachment was scrubbed... URL: From info at campaigns.canal-marketing.com Wed Nov 4 17:43:36 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Telecom_Pro?=) Date: Wed, 04 Nov 2009 18:43:36 +0100 Subject: =?iso-8859-1?q?T=E9l=E9com_PRO_tout_en_un_=3A_29_Euros?= Message-ID: An HTML attachment was scrubbed... URL: From global at naviprousa.com Wed Nov 4 17:45:08 2009 From: global at naviprousa.com (U.S. NaviPro) Date: Wed, 04 Nov 2009 18:45:08 +0100 Subject: New platform: GoogleMaps - Deadline Message-ID: You have just 4 days left to enabIe YOUR BUSINESS INFORMATION to display on GPS devices & Mobile Phones for the low monthly fee of $8.95 This discount for updating the 2010 database ends on November 6th, 2009! Supported platforms Mobile phones/ applications: Motorola, Nokia, Samsung, SonyEricsson, iPHONE, Google Maps, Garmin Mobile, Garmin XT, TomTom GO, iGO 2006, iGO 8, iGO amigo GPS PNA: Garmin, Tomtom, NNG Systems: Airis, Altina, Apontador, ASUS, AudioMedia, Audiovox, Autovision, Aviton, BendixKing, Blaupunkt, Caska, Clarion, CNS, Crypton, Cyclone, DreimGO, Ergo, Evolve, Exper, Explay, Geographic, Globalsat, GlobWay, GPS Aquarus, GPSTURK, Guepard, H-Buster, HP, Hyundai, iconX, iFind, Invion, Isuzu, Jensen, JoyPlus, Macrom, Mando, Mappy, MyGuide, Mypilot, Navigo, Navitech, NavOn, NBX, Next, Nextar, OCN, Orion, Phonocar, Piranha, Pocket Navigator, P?sitron, Prestigio, QUE, Ramar, Reaction, Renault, RoadCommander, Rosen, Scania, Scott, Shturmann, Siga-me, Skyway, Stromberg Carlson, takeMS, Telefunken, TELE System, Tilborg, Toshiba, Unicars, Uniden, Vector, Vendeka, VMS, Wondeproud, XZENT, Zenec Learn more or register HERE: http://massmail.navipro-international.com/link.php?M=2680854&N=60&L=9&F=T NaviPro U.S. Llc. - Customer service: 888-524 9365 Customer support: support at naviprousa.com 8835 SW 107 AVE, # 281, MIAMI, FL 33176, www.NaviProUSA.com To stop receiving these emails:http://massmail.navipro-international.com/unsubscribe.php?M=2680854&C=d3ac11a949eda20b4659837fc7092fff&L=64&N=60 Powered by Interspire -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 893c8fabd72cc00a0a8f2fd3fcee1d39 Type: image/jpeg Size: 22979 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: fb3138e7e8aac6c66696369a923e46ad Type: image/jpeg Size: 80938 bytes Desc: not available URL: -------------- next part -------------- From divulgacao at refrimur.com Wed Nov 4 20:43:55 2009 From: divulgacao at refrimur.com (Refrimur) Date: Wed, 04 Nov 2009 18:43:55 -0200 Subject: REFRIMUR NOVEMBRO 2009 Message-ID: An HTML attachment was scrubbed... URL: From roland at redhat.com Wed Nov 4 20:45:28 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 4 Nov 2009 12:45:28 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Tuesday, 3 November 2009 06:37:47 +0100 <20091103053747.GA11794@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> Message-ID: <20091104204528.1DE1971D8@magilla.sf.frob.com> > 3. Now that we have utrace->resume, can't we kill report->resume_action ? I thought this initially when making the change and then decided against it. I don't recall exactly what was in my mind at the time. It would take some more thought now to be sure whether there is a semantic problem. But at any rate, keeping it reduces the number of cases in which we take the utrace lock in finish_callback_report, which seems like a good thing. Still, if you propose a patch to remove it with thorough rationale on why it's good or better, then that will be fine. Thanks, Roland From roland at redhat.com Wed Nov 4 20:58:39 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 4 Nov 2009 12:58:39 -0800 (PST) Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Monday, 2 November 2009 07:44:58 +0100 <20091102064458.GA30280@redhat.com> References: <20091102064458.GA30280@redhat.com> Message-ID: <20091104205839.7FF6471D8@magilla.sf.frob.com> > In this case the tracee resumes and stops after syscall_trace_leave() > to report PTRACE_EVENT_FORK, but since it passes syscall_trace_leave() > with TIF_SINGLESTEP set the tracee gets the unwanted send_sigtrap(). > > Note: of course, this is hack. I think this should be move to utrace > layer. Unless we are going to call finish_resume_report(), finish_report() > should look at report->action and clear TIF_SINGLESTEP when needed. I thought we had just covered this before. TIF_SINGLESTEP is an arch implementation detail and will never belong in either the ptrace layer or the utrace layer. All of this is just to work around the x86-specific case of the step state on return from tracehook_report_syscall_exit() producing (or not producing) the synthetic single-step SIGTRAP. I think the sequence of changes we'll want for this is something like: 1. (upstream) add arch hook(s) for single-step SIGTRAP siginfo_t + arch fields (i.e. x86's thread.error_code + thread.trap_no). 2. (upstream) change tracehook_report_syscall_exit() to use force_sig_info instead of ptrace_notify, use that arch hook -> powerpc et al PTRACE_SINGLESTEP-over-syscall goes from ptrace-swallows-signal to normal signal case 3. (upstream) implement that arch hook for at least powerpc -> synthetic SIGTRAP gets si_* as a real step would, rather than 0 4. (upstream) implement that arch hook for x86 5. (upstream) change x86 syscall_trace_leave to pass flag tracehook_report_syscall_exit(), not call send_sigtrap() -> x86 PTRACE_SINGLESTEP from syscall-exit stop no longer fake-traps without another insn, but takes a true step trap after next insn -> compatible with powerpc et al behavior, makes more sense 6. profit -> more consistent behavior upstream, simpler mandate for utrace-ptrace Is there anything wrong with that? Thanks, Roland From newsletter at rmcvisual.upmailer.com.br Tue Nov 3 13:09:19 2009 From: newsletter at rmcvisual.upmailer.com.br (RMC Visual) Date: Tue, 03 Nov 2009 08:09:19 -0500 Subject: Superando Obstaculos? Message-ID: Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://rmcvisual.upmailer.com.br/display.php?M=852994&C=ee01399d46ca8b905e8d4526eb991169&S=13&L=13&N=13 Para parar de receber nossos e-mails:http://rmcvisual.upmailer.com.br/unsubscribe.php?M=852994&C=ee01399d46ca8b905e8d4526eb991169&L=13&N=13 Desenvolvido por UpMailer -------------- next part -------------- An HTML attachment was scrubbed... URL: From maralopess at gmail.com Thu Nov 5 06:13:39 2009 From: maralopess at gmail.com (Mara Lopes) Date: Thu, 5 Nov 2009 04:13:39 -0200 (BRST) Subject: 1, 2 e 3 quartos em =?utf-8?q?S=C3=A3o_Cristov=C3=A3o_-_Rio_de_Ja?= =?utf-8?q?neiro?= Message-ID: <20091105061339.322A243A8B2@hw42.tc.webservidor.net> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Nov 5 10:01:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 5 Nov 2009 11:01:23 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091103231411.5AB7471C3@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> Message-ID: <20091105100123.GA11286@redhat.com> On 11/03, Roland McGrath wrote: > > > 4. One of the changes in utrace_get_signal() doesn't look exactly right. > > > > if (utrace->resume < UTRACE_RESUME || utrace->signal_handler) { > > ... > > if (resume > UTRACE_REPORT) { > > report.action = resume; > > finish_resume_report(&report); > > } > > > > Yes, we need finish_resume_report() here, but since report->takers > > is not set, finish_report_reset() will always call utrace_reset(). > > > > OTOH, we can't set ->takers before finish_resume_report(), we can > > miss UTRACE_DETACH request. utrace_control(DETACH)->utrace_do_stop() > > does not change utrace->resume != UTRACE_RESUME. > > > > And since utrace_do_stop() never "upgrades" utrace->resume, we have > > another problem: UTRACE_STOP request can be lost here. > > Hmm. Maybe this? > > diff --git a/kernel/utrace.c b/kernel/utrace.c > index f46854b..0000000 100644 > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -1740,8 +1740,6 @@ static void finish_resume_report(struct > struct task_struct *task, > struct utrace *utrace) > { > - finish_report_reset(task, utrace, report); > - > switch (report->action) { > case UTRACE_STOP: > utrace_stop(task, utrace, report->resume_action); > @@ -1829,6 +1827,8 @@ void utrace_resume(struct task_struct *t > report.action = UTRACE_RESUME; > list_for_each_entry(engine, &utrace->attached, entry) > start_callback(utrace, &report, engine, task, 0); > + > + finish_report_reset(task, utrace, report); > } > > /* > @@ -2147,6 +2147,7 @@ int utrace_get_signal(struct task_struct > * as in utrace_resume(), above. After we've dealt with that, > * our caller will relock and come back through here. > */ > + finish_report_reset(task, utrace, &report); > finish_resume_report(&report, task, utrace); > > if (unlikely(fatal_signal_pending(task))) { Afaics this fixes nothing. Yes, this avoids the unnecessary utrace_reset() in utrace_get_signal(), but sometimes we need utrace_reset() here, now it is never called. Suppose a tracee is stopped (TASK_TRACED). The tracer does utrace_control(UTRACE_SINGLESTEP). This sets ->resume = UTRACE_SINGLESTEP and wakes up the tracee. Right after that, the tracer does utrace_control(UTRACE_DETACH). This calls mark_engine_detached(), but utrace_do_stop() do not change ->resume, it is still UTRACE_SINGLESTEP. Now, the tracee enters utrace_get_signal(), notices ->resume < UTRACE_RESUME, sets utrace->resume = UTRACE_RESUME and does if (resume > UTRACE_REPORT) { /* * We only got here to process utrace->resume. */ report.action = resume; finish_resume_report(&report, task, utrace); return -1; } Now that finish_resume_report() does not do finish_report_reset(), we call user_enable_single_step() and return. Unless we have another engine which triggers utrace_resume() eventually, UTRACE_DETACH can't be completed, utrace_detached_ops engine is "lost". UTRACE_STOP can be lost in the same way, with or without this change. mark_engine_wants_stop() sets ENGINE_STOP, but since we reset ->resume it can't be noticed until some engine sets ->resume = REPORT/INTERRUPT. > > 5. utrace_resume() has the same problems. Including the possibility to miss UTRACE_STOP or UTRACE_DETACH. And, > > 6. But! I think utrace_resume() was always wrong here. Because it > > calls start_callback(events => 0) and thus we nevet set ->takers. > > I think that change covers these too. What do you think? I think no. finish_report_reset() will always call utrace_reset() because start_callback(event => 0) can never set takers. If report.action != UTRACE_REPORT, then we don't call utrace_reset(). But, like above, sometime it is needed to complete UTRACE_DETACH. Oleg. From oleg at redhat.com Thu Nov 5 10:56:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 5 Nov 2009 11:56:50 +0100 Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091104205839.7FF6471D8@magilla.sf.frob.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> Message-ID: <20091105105650.GA13644@redhat.com> On 11/04, Roland McGrath wrote: > > All of this is just to work around the x86-specific case > of the step state on return from tracehook_report_syscall_exit() producing > (or not producing) the synthetic single-step SIGTRAP. Yes. > I think the sequence of changes we'll want for this is something like: Oh. Just can't understand what do you mean. > 1. (upstream) add arch hook(s) for single-step SIGTRAP siginfo_t + arch > fields (i.e. x86's thread.error_code + thread.trap_no). OK. say, arch_fill_sigtrap_info(siginfo_t *info, ...). > 2. (upstream) change tracehook_report_syscall_exit() to use force_sig_info > instead of ptrace_notify, force_sig_info() instead of ptrace_notify() ? So, the tracee doesn't stop in tracehook_report_syscall_exit() path but sends the arch_fill_sigtrap_info()'ed signal to itself ? > use that arch hook "that" means arch_fill_sigtrap_info() above? > -> powerpc et al PTRACE_SINGLESTEP-over-syscall goes from > ptrace-swallows-signal to normal signal case > 3. (upstream) implement that arch hook for at least powerpc > -> synthetic SIGTRAP gets si_* as a real step would, rather than 0 > 4. (upstream) implement that arch hook for x86 again, "that arch hook" means arch_fill_sigtrap_info() ? > 5. (upstream) change x86 syscall_trace_leave to pass flag > tracehook_report_syscall_exit(), not call send_sigtrap() you mean, pass TIF_SINGLESTEP flag to tracehook_report_syscall_exit() and do not call send_sigtrap() ? > -> x86 PTRACE_SINGLESTEP from syscall-exit stop no longer fake-traps > without another insn, but takes a true step trap after next insn But. 2. above suggests to use force_sig_info() ? Perhaps, this should depend on TIF_SINGLESTEP flag passed to tracehook_report_syscall_exit() ? In any case, "but takes a true step trap after next insn" means the serious user-visible change? > -> compatible with powerpc et al behavior, makes more sense What was the point of send_sigtrap() then? Roland, I am all confused. Could you please explain what should syscall_trace_leave(TIF_SINGLESTEP) do, at least on x86 machine? What it should do if TIF_SINGLESTEP is set, but TIF_SYSCALL_TRACE is not? In this case tracehook_report_syscall_exit() is not called. Perhaps you can explain this with some pseudo code? Oleg. From newsletter at brinde-companhia.com Thu Nov 5 14:14:01 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Thu, 5 Nov 2009 15:14:01 +0100 Subject: =?iso-8859-1?q?Chuva_de_pre=E7os=2E=2E=2E?= Message-ID: <95b0cfb0673e0c061bcc34c1b23c4355@newsletter2.brinde-companhia.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Nov 5 16:17:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 5 Nov 2009 17:17:42 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091105100123.GA11286@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> Message-ID: <20091105161742.GA26428@redhat.com> On 11/05, Oleg Nesterov wrote: > > Suppose a tracee is stopped (TASK_TRACED). The tracer does > utrace_control(UTRACE_SINGLESTEP). This sets ->resume = UTRACE_SINGLESTEP > and wakes up the tracee. > > Right after that, the tracer does utrace_control(UTRACE_DETACH). This > calls mark_engine_detached(), but utrace_do_stop() do not change ->resume, > it is still UTRACE_SINGLESTEP. > > Now, the tracee enters utrace_get_signal(), notices ->resume < UTRACE_RESUME, > sets utrace->resume = UTRACE_RESUME and does > > if (resume > UTRACE_REPORT) { > /* > * We only got here to process utrace->resume. > */ > report.action = resume; > finish_resume_report(&report, task, utrace); > return -1; > } > > Now that finish_resume_report() does not do finish_report_reset(), > we call user_enable_single_step() and return. Unless we have another > engine which triggers utrace_resume() eventually, UTRACE_DETACH can't > be completed, utrace_detached_ops engine is "lost". > > UTRACE_STOP can be lost in the same way, with or without this change. > mark_engine_wants_stop() sets ENGINE_STOP, but since we reset ->resume > it can't be noticed until some engine sets ->resume = REPORT/INTERRUPT. > > > > 5. utrace_resume() has the same problems. > > Including the possibility to miss UTRACE_STOP or UTRACE_DETACH. Looks like this is easy to fix, UTRACE_STOP/UTRACE_DETACH should always win and set ->resume = REPORT/INTERRUPT --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -707,7 +707,7 @@ static bool utrace_do_stop(struct task_s if (likely(task_is_stopped(target))) __set_task_state(target, TASK_TRACED); spin_unlock_irq(&target->sighand->siglock); - } else if (utrace->resume == UTRACE_RESUME) { + } else if (utrace->resume > UTRACE_REPORT) { utrace->resume = UTRACE_REPORT; set_notify_resume(target); } If ->resume was UTRACE_SINGLESTEP, engine can re-assert it. Now it is safe to change utrace_get_signal() to avoid the unnecessary utrace_reset(): --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1937,6 +1937,7 @@ int utrace_get_signal(struct task_struct * We only got here to process utrace->resume. */ report.action = resume; + report.takers = true; finish_resume_report(&report, task, utrace); return -1; } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { It is not clear to me how to avoid the unnecessary utrace_reset() in utrace_resume() cleanly, but this is minor. However, we seem to have more problems. utrace_resume: /* * Update our bookkeeping even if there are no callbacks made here. */ report.action = utrace->resume; start_report(utrace); This is racy. We are reading utrace->resume lockless, then start_report() resets utrace->resume. If utrace_control() changes utrace->resume in between then report.action is wrong. Hmm... this is minor, but static void start_report(struct utrace *utrace) { if (utrace->resume < UTRACE_RESUME || utrace->pending_attach) { spin_lock(&utrace->lock); splice_attaching(utrace); if (utrace->resume > UTRACE_INTERRUPT) utrace->resume = UTRACE_RESUME; Perhaps it makes sense to check "resume > UTRACE_INTERRUPT" before taking utrace->lock. if ((utrace->resume > UTRACE_INTERRUPT && utrace->resume < UTRACE_RESUME) || utrace->pending_attach) { spin_lock(&utrace->lock); ... Oleg. From mldireto at tudoemoferta.com.br Thu Nov 5 15:20:13 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 5 Nov 2009 13:20:13 -0200 Subject: Mergulhe em nossa Ofertas. Prepare-se para o Verao. Message-ID: <1efcd2000c6a4244139e4d14001d7d9e@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Nov 5 17:39:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 5 Nov 2009 18:39:31 +0100 Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: <20091105161742.GA26428@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> Message-ID: <20091105173931.GA29215@redhat.com> Another minor problem, finish_report: if (resume == UTRACE_STOP) resume = UTRACE_REPORT; This is correct, unless the caller is utrace_report_syscall_entry() which does finish_report(report); if (report.action == UTRACE_STOP) utrace_stop(); IOW, this is harmless, but every stop in utrace_report_syscall_entry() provokes the unnecessary TIF_NOTIFY_RESUME. This wasn't cause by utrace-cleanup changes... Hmm. When report.action == UTRACE_STOP, finish_report() is only needed to handle ->detaches == T case. utrace_stop() should update ->resume correctly, and ->takers must be true. utrace_report_clone() has the same (minor) problem. Perhaps something patch below makes sense, but I don't like this uglification. Oleg. --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1557,10 +1557,11 @@ bool utrace_report_syscall_entry(struct REPORT_CALLBACKS(_reverse, task, utrace, &report, UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, report.result | report.action, engine, current, regs); - finish_report(&report, task, utrace); - if (report.action == UTRACE_STOP) { - utrace_stop(task, utrace, report.resume_action); + if (report.action != UTRACE_STOP) { + finish_report(&report, task, utrace); + } else { + finish_resume_report(&report, task, utrace); if (fatal_signal_pending(task)) /* * We are continuing despite UTRACE_STOP because of a @@ -1611,7 +1612,6 @@ void utrace_report_clone(unsigned long c report.action, engine, task, clone_flags, child); utrace->cloning = NULL; - finish_report(&report, task, utrace); /* * For a vfork, we will go into an uninterruptible block waiting @@ -1619,9 +1619,12 @@ void utrace_report_clone(unsigned long c * after. For CLONE_VFORK, utrace_finish_vfork() will be called. */ if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { + finish_report_reset(task, utrace, &report); spin_lock(&utrace->lock); utrace->vfork_stop = 1; spin_unlock(&utrace->lock); + } else { + finish_report(&report, task, utrace); } } From support at staffpatrol.com Thu Nov 5 17:40:19 2009 From: support at staffpatrol.com (Staff Patrol, Inc.) Date: Thu, 05 Nov 2009 09:40:19 -0800 Subject: Resumes Message-ID: <200911051915.nA5JFL2m016135@mx1.redhat.com> Hello, I wanted to ask about your process for hiring employees. We offer some unique employment screening services and I would greatly appreciate any assistance in speaking with the person who may be responsible for these services. I would also be happy to send a brochure with more details on our services for your review. Thank you in advance, Dexter Marley Staff Patrol, Inc. (800) 383-1327 http://www.staffpatrol.com/employers.htm Click here on http://server1.streamsend.com/streamsend/unsubscribe.php?cd=28762&md=1712&ud=d7e13a439c9963f2c622f11d022e065f to update your profile or Unsubscribe -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Thu Nov 5 20:12:28 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 5 Nov 2009 12:12:28 -0800 (PST) Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Thursday, 5 November 2009 11:56:50 +0100 <20091105105650.GA13644@redhat.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> <20091105105650.GA13644@redhat.com> Message-ID: <20091105201229.01902DE8@magilla.sf.frob.com> > > 1. (upstream) add arch hook(s) for single-step SIGTRAP siginfo_t + arch > > fields (i.e. x86's thread.error_code + thread.trap_no). > > OK. say, arch_fill_sigtrap_info(siginfo_t *info, ...). Something like that, right. Since this is only for single-step in particular, that should be in the name. Also something that makes it not seem incongruous to have the x86 one set those thread.error_code et al fields, i.e. it's not only just filling in siginfo_t. > force_sig_info() instead of ptrace_notify() ? > > So, the tracee doesn't stop in tracehook_report_syscall_exit() path > but sends the arch_fill_sigtrap_info()'ed signal to itself ? Right, like x86 does today. > > use that arch hook > > "that" means arch_fill_sigtrap_info() above? Right. > > -> powerpc et al PTRACE_SINGLESTEP-over-syscall goes from > > ptrace-swallows-signal to normal signal case > > 3. (upstream) implement that arch hook for at least powerpc > > -> synthetic SIGTRAP gets si_* as a real step would, rather than 0 > > 4. (upstream) implement that arch hook for x86 > > again, "that arch hook" means arch_fill_sigtrap_info() ? Right. > > 5. (upstream) change x86 syscall_trace_leave to pass flag > > tracehook_report_syscall_exit(), not call send_sigtrap() > > you mean, pass TIF_SINGLESTEP flag to tracehook_report_syscall_exit() > and do not call send_sigtrap() ? Right, like powerpc et al do today. > > -> x86 PTRACE_SINGLESTEP from syscall-exit stop no longer fake-traps > > without another insn, but takes a true step trap after next insn > > But. 2. above suggests to use force_sig_info() ? Perhaps, this should > depend on TIF_SINGLESTEP flag passed to tracehook_report_syscall_exit() ? Right, x86 would do like powerpc et al do today: step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); > In any case, "but takes a true step trap after next insn" means the > serious user-visible change? It's a minor user-visible change in a strange corner case, but yes, it's a change. As to where you stop next for PTRACE_SINGLESTEP done at the syscall-exit stop, it makes x86 match powerpc et al. > > -> compatible with powerpc et al behavior, makes more sense > > What was the point of send_sigtrap() then? I'm not sure I follow this question. send_sigtrap is an x86 implementation detail. If you are asking about why that function exists as an implementation detail, it's just consolidating the synthetic call for faked-step with the main SIGTRAP path in the do_debug trap handler. But I can't tell if you are instead asking why to make the change to powerpc et al (i.e. generic tracehook_report_syscall_exit) to send a SIGTRAP instead of ptrace_notify, and have x86 use that same logic. > Roland, I am all confused. Could you please explain what should > syscall_trace_leave(TIF_SINGLESTEP) do, at least on x86 machine? > > What it should do if TIF_SINGLESTEP is set, but TIF_SYSCALL_TRACE > is not? In this case tracehook_report_syscall_exit() is not called. > > Perhaps you can explain this with some pseudo code? Real code, even! :-) step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); This gives the tracehook call the chance to choose the exact behavior, so that becomes consistent across x86 and other machines. So at that level, the "what should" answer is that it should give the tracehook layer the chance to implement uniform behavior across machines. Thanks, Roland From info at aguahesp.net Thu Nov 5 14:46:04 2009 From: info at aguahesp.net (AGUAHESP) Date: Thu, 05 Nov 2009 15:46:04 +0100 Subject: URGENTE! Como esta a agua que voce bebe? Message-ID: Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://www.aguahesp.net/painel/display.php?M=292906&C=bbe5ed06fc3f5aa48a39e551fe0067ea&S=30&L=12&N=4 Para parar de receber nossos e-mails:http://www.aguahesp.net/painel/unsubscribe.php?M=292906&C=bbe5ed06fc3f5aa48a39e551fe0067ea&L=12&N=30 -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Nov 6 18:37:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 6 Nov 2009 19:37:26 +0100 Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091105201229.01902DE8@magilla.sf.frob.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> <20091105105650.GA13644@redhat.com> <20091105201229.01902DE8@magilla.sf.frob.com> Message-ID: <20091106183726.GA17473@redhat.com> On 11/05, Roland McGrath wrote: > > Real code, even! :-) > > step = test_thread_flag(TIF_SINGLESTEP); > if (step || test_thread_flag(TIF_SYSCALL_TRACE)) > tracehook_report_syscall_exit(regs, step); > > This gives the tracehook call the chance to choose the exact behavior, > so that becomes consistent across x86 and other machines. So at that > level, the "what should" answer is that it should give the tracehook > layer the chance to implement uniform behavior across machines. That part was clear ;) except I guess we should also check TIF_SYSCALL_EMU. So, if I understand correctly arch/x86/kernel/ptrace.c:syscall_trace_leave() becomes: asmregparm void syscall_trace_leave(struct pt_regs *regs) { int step; if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->ax); step = test_thread_flag(TIF_SINGLESTEP) && !test_thread_flag(TIF_SYSCALL_EMU); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); } but I still can't understand what tracehook_report_syscall_exit() should do. Do you mean void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { siginfo_t info; if (!step) ptrace_report_syscall(regs); else { arch_fill_sigtrap_info(current, &info); force_sig_info(SIGTRAP, &info, current); } } ? This changes the current behaviour (both for x86 and powerpc), but > > In any case, "but takes a true step trap after next insn" means the > > serious user-visible change? > > It's a minor user-visible change in a strange corner case, but yes, it's > a change. As to where you stop next for PTRACE_SINGLESTEP done at the > syscall-exit stop, it makes x86 match powerpc et al. since you think this is minor, I won't worry. So. As for x86, PTRACE_SINGLESTEP after syscall-exit stop means: do nothing, just return to user-mode with X86_EFLAGS_TF set, the tracee will stop after the next instruction. > > So, the tracee doesn't stop in tracehook_report_syscall_exit() path > > but sends the arch_fill_sigtrap_info()'ed signal to itself ? > > Right, like x86 does today. Surely x86 doesn't do this. Probably I misunderstood you from the very beginning and you meant the code above, iow: force_sig_info() instead of ptrace_notify() when step == T ? Or, did you really mean something like void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { siginfo_t info; if (!step) { memset(&info, 0, sizeof info); info.si_signo = SIGTRAP; info.si_code = SIGTRAP | ((current->ptrace & PT_TRACESYSGOOD) ? 0x80 : 0); info.si_pid = task_pid_vnr(current); info.si_uid = current_uid(); } else { arch_fill_sigtrap_info(current, &info); } force_sig_info(SIGTRAP, &info, current); } ? If yes: what if SIGTRAP is already pending? And more importantly, what is the point? Oleg. From oleg at redhat.com Fri Nov 6 19:28:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 6 Nov 2009 20:28:35 +0100 Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091104205839.7FF6471D8@magilla.sf.frob.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> Message-ID: <20091106192835.GA19680@redhat.com> On 11/04, Roland McGrath wrote: > > > In this case the tracee resumes and stops after syscall_trace_leave() > > to report PTRACE_EVENT_FORK, but since it passes syscall_trace_leave() > > with TIF_SINGLESTEP set the tracee gets the unwanted send_sigtrap(). > > > > Note: of course, this is hack. I think this should be move to utrace > > layer. Unless we are going to call finish_resume_report(), finish_report() > > should look at report->action and clear TIF_SINGLESTEP when needed. > > I thought we had just covered this before. Let's return to this patch. I don't understand how the discussed changes in syscall_trace_leave() path can make any difference here. Once again. The PTRACE_O_TRACEFORK tracee calls fork(), stops in SYSCALL_ENTRY. The tracer does PTRACE_SINGLESTEP. utrace_control(UTRACE_SINGLESTEP) sets TIF_SINGLESTEP. The tracee resumes, it must report PTRACE_EVENT_FORK. But, unlike upstream, we don't stop inside do_fork(), the tracee will stop in utrace_resume(). Before that, it passes syscall_trace_leave(), and since TIF_SINGLESTEP is set the tracee gets SIGTRAP. Perhaps you meant utrace-cleanup branch? In this case ptrace_report_clone() doesn't need suppress_sigtrap(), because utrace_control(UTRACE_SINGLESTEP) will not set TIF_SINGLESTEP. But what about other users, ptrace_report_syscall_entry(PTRACE_O_SYSEMU) and ptrace_report_exec(PTRACE_O_TRACEEXEC) ? Don't they need suppress_sigtrap() anyway? Consider: the tracee is going to call exec(), it is stopped right before syscall insn. the tracer does PTRACE_SINGLESTEP. the tracee returns to user mode and enters syscall with TIF_SINGLESTEP set. ptrace_report_exec() returns UTRACE_STOP, but again, it stops in utrace_resume() after syscall_trace_leave() has already sent SIGTRAP. Confused. Oleg. From roland at redhat.com Fri Nov 6 21:44:37 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 6 Nov 2009 13:44:37 -0800 (PST) Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Friday, 6 November 2009 19:37:26 +0100 <20091106183726.GA17473@redhat.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> <20091105105650.GA13644@redhat.com> <20091105201229.01902DE8@magilla.sf.frob.com> <20091106183726.GA17473@redhat.com> Message-ID: <20091106214437.AF9B8CF@magilla.sf.frob.com> > That part was clear ;) except I guess we should also check TIF_SYSCALL_EMU. Oh, I hadn't thought about the SYSEMU bit. > So, if I understand correctly arch/x86/kernel/ptrace.c:syscall_trace_leave() > becomes: Yes. > but I still can't understand what tracehook_report_syscall_exit() should do. > Do you mean Yes. > This changes the current behaviour (both for x86 and powerpc), but Right. That's why it needs to be in several incremental steps, where each patch does at most one of the changes. At the end both machines match. > > It's a minor user-visible change in a strange corner case, but yes, it's > > a change. As to where you stop next for PTRACE_SINGLESTEP done at the > > syscall-exit stop, it makes x86 match powerpc et al. > > since you think this is minor, I won't worry. Right. It needs clear explanation in its own patch, but I don't think it is going to be controversial. > So. As for x86, PTRACE_SINGLESTEP after syscall-exit stop means: do > nothing, just return to user-mode with X86_EFLAGS_TF set, the tracee > will stop after the next instruction. Right. > > > So, the tracee doesn't stop in tracehook_report_syscall_exit() path > > > but sends the arch_fill_sigtrap_info()'ed signal to itself ? > > > > Right, like x86 does today. > > Surely x86 doesn't do this. Today an x86 tracee under PTRACE_SINGLESTEP indeed does not stop in (does not even call) tracehook_report_syscall_exit() and does instead send itself the normal SIGTRAP (calls send_sigtrap). > Probably I misunderstood you from the very > beginning and you meant the code above, iow: force_sig_info() instead > of ptrace_notify() when step == T ? Yes. > Or, did you really mean something like Certainly not! Thanks, Roland From roland at redhat.com Sat Nov 7 00:06:15 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 6 Nov 2009 16:06:15 -0800 (PST) Subject: [PATCH 128] introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Friday, 6 November 2009 20:28:35 +0100 <20091106192835.GA19680@redhat.com> References: <20091102064458.GA30280@redhat.com> <20091104205839.7FF6471D8@magilla.sf.frob.com> <20091106192835.GA19680@redhat.com> Message-ID: <20091107000615.18653CF@magilla.sf.frob.com> > I don't understand how the discussed changes in syscall_trace_leave() path > can make any difference here. All that part does is move all decisions about what to do into the tracehook/utrace/ptrace layers out of arch code. > The PTRACE_O_TRACEFORK tracee calls fork(), stops in SYSCALL_ENTRY. > > The tracer does PTRACE_SINGLESTEP. utrace_control(UTRACE_SINGLESTEP) > sets TIF_SINGLESTEP. > > The tracee resumes, it must report PTRACE_EVENT_FORK. But, unlike > upstream, we don't stop inside do_fork(), the tracee will stop > in utrace_resume(). Before that, it passes syscall_trace_leave(), > and since TIF_SINGLESTEP is set the tracee gets SIGTRAP. After the arch/tracehook cleanup we've been discussing, what happens here is consistent across machines. It reaches tracehook_report_syscall_exit() with step=1, and nothing else magical happens when after returns. So that is the hook into utrace/higher code that decides what to do. Its options here are just like all other "stacked events" cases. Thanks, Roland From news at maisservicos.com Sun Nov 8 19:31:12 2009 From: news at maisservicos.com (EDICLUBE) Date: Sun, 8 Nov 2009 19:31:12 +0000 Subject: Curso Nutri =?iso-8859-1?q?=E7=E3?= o e Diet =?iso-8859-1?q?=E9?= tica! Message-ID: <20091108193103.A6BB73FE05@server17.nortenet.pt> Curso Pr?tico de: Nutri??o e Diet?tica Aproveite esta magn?fica oportunidade para mudar o seu futuro profissional ? A partir de casa, em apenas 6 meses ? Servi?o de assessoria gratuito durante 24 meses ? Prepare-se para aceder a uma ?rea onde existe uma procura urgente de profissionais ? Acesso a uma bolsa de trabalho ? Certificado de Forma??o que comprova os conhecimentos adquiridos NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sun Nov 8 20:54:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 8 Nov 2009 21:54:37 +0100 Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() Message-ID: <20091108205437.GA24252@redhat.com> On 11/06, Roland McGrath wrote: > > All that part does is move all decisions about what to do into the > tracehook/utrace/ptrace layers out of arch code. > ... > After the arch/tracehook cleanup we've been discussing, what happens here > is consistent across machines. Yes, agreed. Just I greatly misunderstood what you meant. In particular I got it as if this change itself should somehow remove the need for suppress_sigtrap() right now. OK, how about these 2 simple patches for upstream? Then we can change powerpc, etc. Perhaps, instead of arch_has_fill_sigtrap_info we can start with the patch below? Since tracehook_report_syscall_exit() is inline we can can add the "if (step)" code without ifdef's. Or something else instead? Oleg. --------------------------------------------------------------------- [PATCH] tracehook_report_syscall_exit: change callers to use step = 0 Preparation for the next patches. Make sure every caller of tracehook_report_syscall_exit(step) uses step == 0 argument. This doesn't change the compiled code because currently this argument is ignored. --- arch/parisc/kernel/ptrace.c | 2 +- arch/powerpc/kernel/ptrace.c | 2 +- arch/ia64/kernel/ptrace.c | 2 +- arch/microblaze/kernel/ptrace.c | 2 +- arch/sh/kernel/ptrace_32.c | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) --- TH/arch/parisc/kernel/ptrace.c~xxx_syscall_exit_desable_step 2009-10-09 19:52:22.000000000 +0200 +++ TH/arch/parisc/kernel/ptrace.c 2009-11-08 21:33:19.000000000 +0100 @@ -280,5 +280,5 @@ void do_syscall_trace_exit(struct pt_reg test_thread_flag(TIF_BLOCKSTEP); if (stepping || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, stepping); + tracehook_report_syscall_exit(regs, 0); } --- TH/arch/powerpc/kernel/ptrace.c~xxx_syscall_exit_desable_step 2009-07-16 23:28:59.000000000 +0200 +++ TH/arch/powerpc/kernel/ptrace.c 2009-11-08 21:33:29.000000000 +0100 @@ -1082,5 +1082,5 @@ void do_syscall_trace_leave(struct pt_re step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, step); + tracehook_report_syscall_exit(regs, 0); } --- TH/arch/ia64/kernel/ptrace.c~xxx_syscall_exit_desable_step 2009-07-13 17:39:43.000000000 +0200 +++ TH/arch/ia64/kernel/ptrace.c 2009-11-08 21:33:39.000000000 +0100 @@ -1284,7 +1284,7 @@ syscall_trace_leave (long arg0, long arg step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(®s, step); + tracehook_report_syscall_exit(®s, 0); /* copy user rbs to kernel rbs */ if (test_thread_flag(TIF_RESTORE_RSE)) --- TH/arch/microblaze/kernel/ptrace.c~xxx_syscall_exit_desable_step 2009-09-24 21:38:54.000000000 +0200 +++ TH/arch/microblaze/kernel/ptrace.c 2009-11-08 21:33:48.000000000 +0100 @@ -210,7 +210,7 @@ asmlinkage void do_syscall_trace_leave(s step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, step); + tracehook_report_syscall_exit(regs, 0); } #if 0 --- TH/arch/sh/kernel/ptrace_32.c~xxx_syscall_exit_desable_step 2009-09-19 18:32:15.000000000 +0200 +++ TH/arch/sh/kernel/ptrace_32.c 2009-11-08 21:33:55.000000000 +0100 @@ -486,5 +486,5 @@ asmlinkage void do_syscall_trace_leave(s step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, step); + tracehook_report_syscall_exit(regs, 0); } From oleg at redhat.com Sun Nov 8 20:54:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 8 Nov 2009 21:54:39 +0100 Subject: [PATCH 1/2] teach tracehook_report_syscall_exit() to handle stepping Message-ID: <20091108205439.GA24260@redhat.com> Preparation, no changes in compiled code. Currently tracehook_report_syscall_exit() ignores "int step" argument. Each architecture has to implement the stepping itself in the low-level code, and the behaviour is not consistent across different machines. Change tracehook_report_syscall_exit() to handle "step == T" case but hide the code under #ifdef, then we can change each arch separately. --- include/linux/tracehook.h | 8 ++++++++ 1 file changed, 8 insertions(+) --- TH/include/linux/tracehook.h~1_SYSCALL_EXIT 2009-10-30 00:44:25.000000000 +0100 +++ TH/include/linux/tracehook.h 2009-11-08 20:05:20.000000000 +0100 @@ -134,6 +134,14 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { +#ifdef arch_has_fill_sigtrap_info + if (step) { + siginfo_t info; + arch_fill_sigtrap_info(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); + return; + } +#endif ptrace_report_syscall(regs); } From oleg at redhat.com Sun Nov 8 20:54:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 8 Nov 2009 21:54:42 +0100 Subject: [PATCH 2/2] x86: change syscall_trace_leave() to rely on tracehook_report_syscall_exit(step) Message-ID: <20091108205442.GA24263@redhat.com> Extract arch_fill_sigtrap_info() from send_sigtrap() and change syscall_trace_leave() to rely on tracehook_report_syscall_exit() to handle stepping. Note: before this patch x86 generated the unnecessary SIGTRAP when PTRACE_SINGLESTEP done at the syscall-exit stop, now x86 matches other architectures. --- arch/x86/include/asm/ptrace.h | 5 ++++ arch/x86/kernel/ptrace.c | 51 +++++++++++++++++++++++------------------- 2 files changed, 33 insertions(+), 23 deletions(-) --- TH/arch/x86/include/asm/ptrace.h~2_CONVERT_X86 2009-06-11 14:16:46.000000000 +0200 +++ TH/arch/x86/include/asm/ptrace.h 2009-11-08 20:45:21.000000000 +0100 @@ -230,6 +230,11 @@ extern void user_enable_block_step(struc #define arch_has_block_step() (boot_cpu_data.x86 >= 6) #endif +struct siginfo; +void arch_fill_sigtrap_info(struct task_struct *tsk, struct pt_regs *regs, + struct siginfo *info); +#define arch_has_fill_sigtrap_info + struct user_desc; extern int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *info); --- TH/arch/x86/kernel/ptrace.c~2_CONVERT_X86 2009-09-23 21:12:01.000000000 +0200 +++ TH/arch/x86/kernel/ptrace.c 2009-11-08 20:54:26.000000000 +0100 @@ -1437,21 +1437,33 @@ const struct user_regset_view *task_user #endif } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, - int error_code, int si_code) +static inline void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, + struct siginfo *info) { - struct siginfo info; - tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; - memset(&info, 0, sizeof(info)); - info.si_signo = SIGTRAP; - info.si_code = si_code; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = si_code; + info->si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; +} - /* User-mode ip? */ - info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; +void arch_fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + struct siginfo *info) +{ + fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); +} +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) +{ + struct siginfo info; + + fill_sigtrap_info(tsk, regs, error_code, si_code, &info); /* Send us the fake SIGTRAP */ force_sig_info(SIGTRAP, &info, tsk); } @@ -1516,29 +1528,22 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + bool step; + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->ax); - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); - /* * If TIF_SYSCALL_EMU is set, we only get here because of * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). * We already reported this syscall instruction in - * syscall_trace_enter(), so don't do any more now. - */ - if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) - return; - - /* - * If we are single-stepping, synthesize a trap to follow the - * system call instruction. + * syscall_trace_enter(). */ - if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) - send_sigtrap(current, regs, 0, TRAP_BRKPT); + step = unlikely(test_thread_flag(TIF_SINGLESTEP)) && + !test_thread_flag(TIF_SYSCALL_EMU); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } From boss at iammyownboss.co.uk Sun Nov 8 23:49:59 2009 From: boss at iammyownboss.co.uk (boss at iammyownboss.co.uk) Date: Sun, 8 Nov 2009 23:49:59 +0000 Subject: [VIDEO] Check This $636,217.33 CPA Account For FREE Message-ID: <7219326c379a98bd7edc32b4a18e62b9@www.solduk.com> Hey, what's happening? I have just seen a weird video of an underground marketer logging in LIVE into a CPA account with $636,217.33 Inside it... The craziest part is that all this money was generated with NO GOOGLE ADWORDS & NO SELLING! The video is completely FREE to watch and you have got to check it out right now (Click Link Below) ==>> Click Here! Im still a bit dazed & shocked from what I have just seen... The video is from a guy named Saj P who has broken all records and over the last year has had four number #1 Best Selling Clickbank courses. The difference between Saj and most other marketers is that this guy actually really knows his stuff, and his techniques and methods are completely different to what anybody else is teaching. He is known to be a pain in the Arse to Gurus as he exposes the secret systems they actually use to milk in big cash online while churning out crap to the masses to hide their tracks. Saj also has a record amount of students earning full time JOB CRUSHING income online using the UNDERGROUND systems and techniques he teaches. Rumour has it that he is now EXPOSING one of the most powerful CPA formulas online that uses SECRET TRAFFIC funnels to bring in some EXPLOSIVE PAYDAYS! I've seen live proof of over $50K generated in one day and you gotta see it yourself to believe it: ==>> Click Here! ================================ AFFILIATE MARKETING LIES ================================ Most Gurus will tell you that affiliate marketing is the easiest way to earn big money online, and although this can be true to a certain extent, they never tell you the ad costs and complexities in setting up a profitable campaign and then scaling it up to earn the really big figures. All of this is actually alot more difficult than it is made out to be in most of the online courses you have bought. The SECRET to EARNING BIG CASH with affiliate marketing is to do it with CPA offers, and this is what the people in the know have been trying to hide for a very long time. If you dont know already, CPA stands for Cost Per Action, and the reason why it is so powerful is because you dont have to generate a sale to get paid commissions. If you were promoting a clickbank product for example, you would have to drive traffic and get someone to whip out their credit card and make a purchase before you saw any commissions in your account. With CPA however, you get paid for the most basic information such as someone typing in their email address or zip code into an online form!! This is why CPA offers have INSANE CONVERSIONS and are way more powerful than any other form of affiliate marketing! CPA Affiliates are the real ones making six and seven figures a month! See the PROOF With your own eyes HERE NOW for FREE: ==>> Click Here! Saj was one of the first people in Internet Marketing to expose the CPA world with his Number One Best Selling course Affiliate Payload which was released in conjunction with Alex Goad. The amount of people that made a downright filthy income with the techniques revealed in that course are quite frankly shocking! Now He is back with the most Secretive Underground CPA formula ever to be released online and you would be crazy if you didnt check this out: ==>> Click Here! ======================================== SCREW GOOGLE ADWORDS ======================================== The Second part of the big deception online is that you need to use Google Adwords to make the real cash on the internet. SCREW THAT! Although yes Google Adwords is a truely powerful system to use in your marketing, the fact of the matter is that the competition on adwords is insane, and unless you have a big ad budget and alot of time on your hands to test your campaigns, be prepared to get wiped out FAST! The truth is you dont need Google Adwords... Saj explains how you can use the power of MSN and other secret CHEAPER traffic funnels like Media Buying and Myspace PPC to completely dominate affiliate marketing, and when you combine these UNDERGROUND TRAFFIC SOURCES with CPA marketing, you instantly start to transform your life as you FINALLY see those BIG FAT commission figures build up FAST inside your account. Like I said before this is the guy to listen to when you want the real underground knowledge of how to earn big bucks online and you would be crazy if you didnt check this out. SEE THE PROOF LIVE FOR YOUR OWN EYES: ==>> Click Here! I personally cant wait to find out more myself and am going to be following this thing like a Hawk. It looks so good that its almost scary and I am not going to lie to you but I am real excited! After all, who in their right mind would refuse an underground system to generate six figures with No Google Awords and No Selling involved. I am off to email Saj now to get more INSIDER Information, I suggest you do the same and watch his FREE Revealing Video here: ==>> Click Here! Laters. P.S. This Secret Page will be taken down in exactly 24 hours and will never be up again so if you want some real insider information from someone who has proven to be a success in this industry and helped many others achieve the same results you should stop everything else your are doing right now and check this out. WATCH THE CRAZY FREE PROOF VIDEO NOW: ==>> Click Here! -- If you do not want to receive any more newsletters, http://www.solduk.com/design/mailer/?p=unsubscribe&uid=b540d2cbc9c91ab36421a1c99474d5c1 To update your preferences and to unsubscribe visit http://www.solduk.com/design/mailer/?p=preferences&uid=b540d2cbc9c91ab36421a1c99474d5c1 Forward a Message to Someone http://www.solduk.com/design/mailer/?p=forward&uid=b540d2cbc9c91ab36421a1c99474d5c1&mid=1 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From caiqian at redhat.com Mon Nov 9 08:51:03 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Mon, 9 Nov 2009 03:51:03 -0500 (EST) Subject: utrace tests In-Reply-To: <1595272436.1446701257756517095.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <992593847.1446751257756663642.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hello! Sorry for the cross-posting. Wondering if there are some existing utrace tests that can be used for regression testing. There is a ntrace tests under, http://people.redhat.com/roland/utrace/old/ Are those tests still relevant? Thanks! CAI Qian From roland at redhat.com Mon Nov 9 18:00:33 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 9 Nov 2009 10:00:33 -0800 (PST) Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Sunday, 8 November 2009 21:54:37 +0100 <20091108205437.GA24252@redhat.com> References: <20091108205437.GA24252@redhat.com> Message-ID: <20091109180033.E0A3A712@magilla.sf.frob.com> > OK, how about these 2 simple patches for upstream? Then we can change > powerpc, etc. > > Perhaps, instead of arch_has_fill_sigtrap_info we can start with the > patch below? Since tracehook_report_syscall_exit() is inline we can > can add the "if (step)" code without ifdef's. I don't understand the intent of breaking the existing arch's first at all. Just leave them alone. When the arch hook is not defined, just 0-fill the siginfo_t. If you do the patches in the right order, then there will never even be a tree state where powerpc et al get any change at all before the final one. Thanks, Roland From roland at redhat.com Mon Nov 9 18:11:38 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 9 Nov 2009 10:11:38 -0800 (PST) Subject: [PATCH 1/2] teach tracehook_report_syscall_exit() to handle stepping In-Reply-To: Oleg Nesterov's message of Sunday, 8 November 2009 21:54:39 +0100 <20091108205439.GA24260@redhat.com> References: <20091108205439.GA24260@redhat.com> Message-ID: <20091109181138.549DB712@magilla.sf.frob.com> I wouldn't make the behavior conditional on the arch hook's definition. I think a consistent change to a real SIGTRAP signal is better for any arch. Until each arch defines the hook, it can just get the default siginfo_t contents of 0-fill. This arch hook is purely for the single-step case. For that the name "arch_fill_sigtrap_info" is too generic-sounding. I'd make it fit in with the existing *_step stuff, e.g. "user_single_step_siginfo". I think for an arch_has_* #ifdef it is normal to make them uppercase. Anyway, those naming details can get upstream feedback when you post. Thanks, Roland From roland at redhat.com Mon Nov 9 18:44:28 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 9 Nov 2009 10:44:28 -0800 (PST) Subject: utrace tests In-Reply-To: caiqian@redhat.com's message of Monday, 9 November 2009 03:51:03 -0500 <992593847.1446751257756663642.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <1595272436.1446701257756517095.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <992593847.1446751257756663642.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091109184428.F2C8070@magilla.sf.frob.com> > Wondering if there are some existing utrace tests that can be used for > regression testing. There is a ntrace tests under, > http://people.redhat.com/roland/utrace/old/ > > Are those tests still relevant? I'm not really sure what you mean by "relevant". That old testing code is certainly not "working right now". It hasn't been touched (or tried) in a long time. It is still relevant in the sense that it tests some of the utrace API, that API still exists, and the things it tested are still there and need to be right. There were never very many test cases in there, so it does not do all that much useful testing really. But it is the only thing we've ever had that's something like a pure utrace API unit test suite. Thanks, Roland From oleg at redhat.com Mon Nov 9 18:52:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 9 Nov 2009 19:52:26 +0100 Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091109180033.E0A3A712@magilla.sf.frob.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> Message-ID: <20091109185226.GA11917@redhat.com> On 11/09, Roland McGrath wrote: > > > OK, how about these 2 simple patches for upstream? Then we can change > > powerpc, etc. > > > > Perhaps, instead of arch_has_fill_sigtrap_info we can start with the > > patch below? Since tracehook_report_syscall_exit() is inline we can > > can add the "if (step)" code without ifdef's. > > I don't understand the intent of breaking the existing arch's first at all. This patch ("change callers to use step = 0") can't break arch's ? Currently tracehook_report_syscall_exit() ignores "int step" argument, the patch doesn't change the compiled code at all. > Just leave them alone. When the arch hook is not defined, just 0-fill the > siginfo_t. Not sure I understand. You mean, if arch hook is not defined, we add the default arch_fill_sigtrap_info (or whatever) which only sets si_signo? > If you do the patches in the right order, then there will never > even be a tree state where powerpc et al get any change at all before the > final one. I am confused again. If we do the above, then powerpc's behaviour will be changed iimediately? Not only powerpcs. parisc, ia64, etc. To clarify, of course I agree with the change above, but I am afraid I do not understand you again. Help! Oleg. From oleg at redhat.com Mon Nov 9 18:54:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 9 Nov 2009 19:54:21 +0100 Subject: [PATCH 1/2] teach tracehook_report_syscall_exit() to handle stepping In-Reply-To: <20091109181138.549DB712@magilla.sf.frob.com> References: <20091108205439.GA24260@redhat.com> <20091109181138.549DB712@magilla.sf.frob.com> Message-ID: <20091109185421.GA12558@redhat.com> I think this answers my questions in the previous email I sent. On 11/09, Roland McGrath wrote: > > I wouldn't make the behavior conditional on the arch hook's definition. I > think a consistent change to a real SIGTRAP signal is better for any arch. > Until each arch defines the hook, it can just get the default siginfo_t > contents of 0-fill. OK. > This arch hook is purely for the single-step case. For that the name > "arch_fill_sigtrap_info" is too generic-sounding. I'd make it fit in with > the existing *_step stuff, e.g. "user_single_step_siginfo". OK. > I think for an arch_has_* #ifdef it is normal to make them uppercase. > Anyway, those naming details can get upstream feedback when you post. OK. ARCH_HAS_SINGLE_STEP_INFO ? Oleg. From roland at redhat.com Mon Nov 9 19:11:12 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 9 Nov 2009 11:11:12 -0800 (PST) Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Monday, 9 November 2009 19:52:26 +0100 <20091109185226.GA11917@redhat.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> <20091109185226.GA11917@redhat.com> Message-ID: <20091109191112.917C970@magilla.sf.frob.com> > This patch ("change callers to use step = 0") can't break arch's ? > Currently tracehook_report_syscall_exit() ignores "int step" argument, > the patch doesn't change the compiled code at all. Oh, yes. That's true. I still don't like it. The existing arch code is right today. So you'll change it to wrong only to change it back later. That makes no sense to me. Only on x86 does the tracehook call really need to change. I wouldn't touch it on the others--unless you decide to roll in the arch hook to that API somehow, which I don't think would come out pretty enough to warrant it. > Not sure I understand. You mean, if arch hook is not defined, we add > the default arch_fill_sigtrap_info (or whatever) which only sets si_signo? Right. To be more precise, I think the arch hook should only set what's arch-specific and nonzero, so have generic code zero-fill and set si_signo. The arch hook just sets si_code et al, so that if there is no arch hook then the default one is empty. The arch code will only ever define what it needs to add vs that default. > > If you do the patches in the right order, then there will never > > even be a tree state where powerpc et al get any change at all before the > > final one. > > I am confused again. If we do the above, then powerpc's behaviour will > be changed iimediately? Not only powerpcs. parisc, ia64, etc. What I meant is that we can do: 1. specify arch hook, define default case 2. define powerpc's arch hook 3. change tracehook_report_syscall_exit to look at step flag 4. define x86's arch hook 5. change x86 tracehook_report_syscall_exit to match common pattern Then powerpc goes from status quo (ptrace_notify as if PTRACE_SYSCALL) to final status (SIGTRAP with correct si_code) in #3. In another order we might have an intermediate status where powerpc is sending SIGTRAP with si_code=0, which is suboptimal. That's not really a big deal though. What's important is that we can have a mergeable tracehook.h patch (#3) without waiting for all the arch's to merge their updates to define the arch hook. I can write the powerpc one as demonstration, and if the arch/powerpc maintainers are slow to approve/merge it then they might get the si_code=0 state on powerpc for a while, but that is OK. We can write and submit the x86 changes; only those will depend on the generic change having gone in first to avoid any intermediate tree state with a regression. Thanks, Roland From roland at redhat.com Mon Nov 9 19:18:50 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 9 Nov 2009 11:18:50 -0800 (PST) Subject: [PATCH 1/2] teach tracehook_report_syscall_exit() to handle stepping In-Reply-To: Oleg Nesterov's message of Monday, 9 November 2009 19:54:21 +0100 <20091109185421.GA12558@redhat.com> References: <20091108205439.GA24260@redhat.com> <20091109181138.549DB712@magilla.sf.frob.com> <20091109185421.GA12558@redhat.com> Message-ID: <20091109191850.AEF2986D@magilla.sf.frob.com> > > I think for an arch_has_* #ifdef it is normal to make them uppercase. > > Anyway, those naming details can get upstream feedback when you post. > > OK. ARCH_HAS_SINGLE_STEP_INFO ? I think the convention is ARCH_HAS_FOO where foo is the exact name sans "arch_" of the actual function name. Another approach sometimes used is an arch_* macro where the generic code can use #ifdef arch_foo #define arch_foo. Then if an arch wants to use an extern or inline instead of a macro, it can do "#define arch_foo arch_foo" or "#define arch_foo x86_foo" or suchlike. Anyway, upstream opinions on these details change with the winds. Just pick an existing example of an arch_* hook to use as the model and do something analogous. The upstream review will tell you if they want it to follow some other model instead. The only thing I'd say is to follow one of the models where you don't need each arch to define anything new just to keep compiling. i.e., some existing cases have added: #define arch_foobar(x, y, z) do { } while (0) to arch/*/include/asm/foo.h where they have to repeat that en masse in every arch just to get back to "nothing new". That seems foolish to me. Thanks, Roland From oleg at redhat.com Mon Nov 9 20:56:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 9 Nov 2009 21:56:50 +0100 Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091109191112.917C970@magilla.sf.frob.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> <20091109185226.GA11917@redhat.com> <20091109191112.917C970@magilla.sf.frob.com> Message-ID: <20091109205650.GA22673@redhat.com> On 11/09, Roland McGrath wrote: > > > Not sure I understand. You mean, if arch hook is not defined, we add > > the default arch_fill_sigtrap_info (or whatever) which only sets si_signo? > > Right. To be more precise, I think the arch hook should only set what's > arch-specific and nonzero, so have generic code zero-fill and set si_signo. > The arch hook just sets si_code et al, so that if there is no arch hook > then the default one is empty. The arch code will only ever define what it > needs to add vs that default. Oh... this adds more naming problems. And this way x86's send_sigtrap() can't use this helper easily. OK, please see below, but perhaps it is better to not introduce the generic helper. ------------------------------------------------------------------------------- > 1. specify arch hook, define default case [PATCH 1/x] introduce user_single_step_siginfo() perhaps user_single_step_siginfo() should go into ptrace.c ? ARCH_HAS_USER_SINGLE_STEP_INFO doesn't match arch_has_single_step. it should be ARCH_HAS_ARCH_USER_SINGLE_STEP_INFO, but this looks ugly. I don't really care, up to you. --- include/linux/ptrace.h | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+) --- TH/include/linux/ptrace.h~1_ARCH_DEFAULT_HOOK 2009-10-30 00:46:06.000000000 +0100 +++ TH/include/linux/ptrace.h 2009-11-09 21:38:07.000000000 +0100 @@ -273,6 +273,25 @@ static inline void user_enable_block_ste } #endif /* arch_has_block_step */ +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO +extern void arch_user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info); +#else +static inline void arch_user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ +} +#endif + +static inline void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + + arch_user_single_step_siginfo(tsk, regs, info); +} + #ifndef arch_ptrace_stop_needed /** * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called -------------------------------------------------------------------------------- OK? > 2. define powerpc's arch hook [PATCH 2/x] change powepc --- arch/powerpc/include/asm/ptrace.h | 2 ++ arch/powerpc/kernel/traps.c | 7 +++++++ 2 files changed, 9 insertions(+) --- TH/arch/powerpc/include/asm/ptrace.h~2_POWERPC 2009-11-09 21:32:17.000000000 +0100 +++ TH/arch/powerpc/include/asm/ptrace.h 2009-11-09 21:39:19.000000000 +0100 @@ -140,6 +140,8 @@ extern void user_enable_single_step(stru extern void user_enable_block_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *); +#define ARCH_HAS_USER_SINGLE_STEP_INFO + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ --- TH/arch/powerpc/kernel/traps.c~2_POWERPC 2009-11-09 21:32:17.000000000 +0100 +++ TH/arch/powerpc/kernel/traps.c 2009-11-09 21:39:39.000000000 +0100 @@ -174,6 +174,13 @@ int die(const char *str, struct pt_regs return 0; } +void arch_user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + info->si_code = TRAP_TRACE; + info->si_addr = (void __user *) regs->nip; +} + void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { siginfo_t info; ------------------------------------------------------------------------------- Correct? > 3. change tracehook_report_syscall_exit to look at step flag [PATCH 3/x] change tracehook_report_syscall_exit() to look at step flag --- include/linux/tracehook.h | 6 ++++++ 1 file changed, 6 insertions(+) --- TH/include/linux/tracehook.h~3_TRACEHOOK 2009-11-09 21:00:38.000000000 +0100 +++ TH/include/linux/tracehook.h 2009-11-09 21:42:16.000000000 +0100 @@ -134,6 +134,12 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); + return; + } ptrace_report_syscall(regs); } ----------------------------------------------------------------------------- > 4. define x86's arch hook > 5. change x86 tracehook_report_syscall_exit to match common pattern This is clear. What do you think? Oleg. From Cheap at cheapforshoes.cn Tue Nov 10 16:49:20 2009 From: Cheap at cheapforshoes.cn (David Lockley) Date: Wed, 11 Nov 2009 03:49:20 +1100 Subject: 75% off on brand Shoes, Boots & Bags Message-ID: <3EB9437E.C2B683EB@cheapforshoes.cn> For utrace-devel at redhat.com: Big discount on name-brand shoes and boots to you. Lowest prices and speedy delivery. We also sell brand Fashion Shoes, Handbags. Including Nike, Adidas, Puma, Gucci, Louis Vuitton and UGGs boots etc. Looking forward to have your inquiries and orders. Buy Supper: Motely at ZJ.com Other discount name-brand products: T-shirts, Jeans, Hats, Wallets, Belts, Sunglasses, Scarves, Wig, watches etc. From info at campaigns.canal-marketing.com Tue Nov 10 18:30:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Luxe_Priv=E9?=) Date: Tue, 10 Nov 2009 19:30:00 +0100 Subject: =?iso-8859-1?q?Invitation_Vente_Priv=E9e?= Message-ID: An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Nov 10 21:11:16 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 10 Nov 2009 13:11:16 -0800 (PST) Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Monday, 9 November 2009 21:56:50 +0100 <20091109205650.GA22673@redhat.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> <20091109185226.GA11917@redhat.com> <20091109191112.917C970@magilla.sf.frob.com> <20091109205650.GA22673@redhat.com> Message-ID: <20091110211116.604B58C0@magilla.sf.frob.com> > Oh... this adds more naming problems. And this way x86's send_sigtrap() > can't use this helper easily. It's true. Another approach would be to genericize send_sigtrap so that all arch's can use it, and call that from tracehook_report_syscall_exit. On x86 and powerpc TRAP_TRACE is the right si_code for step. So perhaps you could just pass that to send_sigtrap from generic code. If another arch differs, then you could make it use a new macro TRAP_SINGLE_STEP instead--then define that to TRAP_TRACE when not defined and let other arch's define it appropriately for their other value. Currently the only other caller of send_sigtrap is do_debug. AFAICT that case has already ruled out VM86 mode. So perhaps it would really be OK for it to be using user_mode() instead of user_mode_vm(). In that case, it could just use: info->si_code = TRAP_TRACE; info->si_addr = user_mode(regs) ? instruction_pointer(regs) : 0; But you still need another arch hook there anyway for x86's extra task->thread.foo fields. (And I'm not really sure that the syscall-exit path has ruled out VM86 mode too, so maybe you do need user_mode_vm() in there--and that's not a call other arch's define.) > [PATCH 1/x] introduce user_single_step_siginfo() I won't bother here with all the potential nit ways to do it differently. Upstream review will help us decide that. > perhaps user_single_step_siginfo() should go into ptrace.c ? Yes, I don't think it needs to be inlined. > +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO > +extern void arch_user_single_step_siginfo(struct task_struct *tsk, > + struct pt_regs *regs, siginfo_t *info); > +#else > +static inline void arch_user_single_step_siginfo(struct task_struct *tsk, > + struct pt_regs *regs, siginfo_t *info) > +{ > +} > +#endif Another way these things are sometimes done is to have a definition with __attribute__((weak)) in kernel/ptrace.c and then let arch code give a non-weak definition to override. (I don't much like that style, but it does avoid all the #ifdef hair.) > [PATCH 2/x] change powepc Looks ok to me. > [PATCH 3/x] change tracehook_report_syscall_exit() to look at step flag Right. > This is clear. > > What do you think? That's all close enough to what I had in mind. Exact details have to be ironed out with the upstream arch maintainers. Thanks, Roland From oleg at redhat.com Tue Nov 10 21:44:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:17 +0100 Subject: [PATCH 0/5] for upstream, user_single_step_siginfo() changes Message-ID: <20091110214417.GA14293@redhat.com> Seriously, I don't think it makes sense to factor out memset + si_signo = SIGTRAP. Imho we need a single helper which can/should be overriden by arch's. How about this? Oleg. From oleg at redhat.com Tue Nov 10 21:44:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:23 +0100 Subject: [PATCH 1/5] ptrace: introduce user_single_step_siginfo() helper Message-ID: <20091110214423.GA14301@redhat.com> Currently there is no way to synthesize a single-stepping trap in the arch-independent manner. This patch adds the default helper which fills siginfo_t, arch/ can can override it. Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) --- TH/include/linux/ptrace.h~1_DEFAULT_HELPER 2009-11-10 01:03:24.000000000 +0100 +++ TH/include/linux/ptrace.h 2009-11-10 21:31:25.000000000 +0100 @@ -273,6 +273,18 @@ static inline void user_enable_block_ste } #endif /* arch_has_block_step */ +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO +extern void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info); +#else +static inline void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; +} +#endif + #ifndef arch_ptrace_stop_needed /** * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called From oleg at redhat.com Tue Nov 10 21:44:25 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:25 +0100 Subject: [PATCH 2/5] ptrace: powerpc: implement user_single_step_siginfo() Message-ID: <20091110214425.GA14305@redhat.com> Implement user_single_step_siginfo() for powerpc. Signed-off-by: Oleg Nesterov --- arch/powerpc/include/asm/ptrace.h | 2 ++ arch/powerpc/kernel/traps.c | 9 +++++++++ 2 files changed, 11 insertions(+) --- TH/arch/powerpc/include/asm/ptrace.h~2_PPC_HELPER 2009-11-10 01:03:23.000000000 +0100 +++ TH/arch/powerpc/include/asm/ptrace.h 2009-11-10 21:48:53.000000000 +0100 @@ -140,6 +140,8 @@ extern void user_enable_single_step(stru extern void user_enable_block_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *); +#define ARCH_HAS_USER_SINGLE_STEP_INFO + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ --- TH/arch/powerpc/kernel/traps.c~2_PPC_HELPER 2009-11-10 01:06:41.000000000 +0100 +++ TH/arch/powerpc/kernel/traps.c 2009-11-10 21:52:45.000000000 +0100 @@ -174,6 +174,15 @@ int die(const char *str, struct pt_regs return 0; } +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = TRAP_TRACE; + info->si_addr = (void __user *)regs->nip; +} + void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { siginfo_t info; From oleg at redhat.com Tue Nov 10 21:44:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:28 +0100 Subject: [PATCH 3/5] ptrace: change tracehook_report_syscall_exit() to handle stepping Message-ID: <20091110214428.GA14308@redhat.com> Change tracehook_report_syscall_exit() to look at step flag and send the trap signal if needed. This change affects ia64, microblaze, parisc, powerpc, sh. They pass nonzero "step" argument to tracehook but since it was ignored the tracee reports via ptrace_notify(), this is not right and not consistent. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 7 +++++++ 1 file changed, 7 insertions(+) --- TH/include/linux/tracehook.h~3_TRACEHOOK_HANDLE_STEPPING 2009-11-10 01:03:22.000000000 +0100 +++ TH/include/linux/tracehook.h 2009-11-10 22:00:37.000000000 +0100 @@ -134,6 +134,13 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); + return; + } + ptrace_report_syscall(regs); } From oleg at redhat.com Tue Nov 10 21:44:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:30 +0100 Subject: [PATCH 4/5] ptrace: x86: implement user_single_step_siginfo() Message-ID: <20091110214430.GA14315@redhat.com> Implement user_single_step_siginfo() for x86. Extract this code from send_sigtrap(). Since x86 calls tracehook_report_syscall_exit(step => 0) the new helper is not used yet. Signed-off-by: Oleg Nesterov --- arch/x86/include/asm/ptrace.h | 2 ++ arch/x86/kernel/ptrace.c | 30 +++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) --- TH/arch/x86/include/asm/ptrace.h~4_X86_HELPER 2009-11-09 21:00:17.000000000 +0100 +++ TH/arch/x86/include/asm/ptrace.h 2009-11-10 22:16:28.000000000 +0100 @@ -230,6 +230,8 @@ extern void user_enable_block_step(struc #define arch_has_block_step() (boot_cpu_data.x86 >= 6) #endif +#define ARCH_HAS_USER_SINGLE_STEP_INFO + struct user_desc; extern int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *info); --- TH/arch/x86/kernel/ptrace.c~4_X86_HELPER 2009-11-09 21:00:17.000000000 +0100 +++ TH/arch/x86/kernel/ptrace.c 2009-11-10 22:21:42.000000000 +0100 @@ -1437,21 +1437,33 @@ const struct user_regset_view *task_user #endif } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, - int error_code, int si_code) +static void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, + struct siginfo *info) { - struct siginfo info; - tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; - memset(&info, 0, sizeof(info)); - info.si_signo = SIGTRAP; - info.si_code = si_code; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = si_code; + info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; +} - /* User-mode ip? */ - info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, + struct siginfo *info) +{ + fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); +} +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) +{ + struct siginfo info; + + fill_sigtrap_info(tsk, regs, error_code, si_code, &info); /* Send us the fake SIGTRAP */ force_sig_info(SIGTRAP, &info, tsk); } From oleg at redhat.com Tue Nov 10 21:44:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:44:33 +0100 Subject: [PATCH 5/5] ptrace: Message-ID: <20091110214433.GA14318@redhat.com> Unlike powepc, x86 always calls tracehook_report_syscall_exit(step) with step = 0, and sends the trap by hand. This results in unnecessary SIGTRAP when PTRACE_SINGLESTEP follows the syscall-exit stop. Change syscall_trace_leave() to pass the correct "step" argument to tracehook and remove the send_sigtrap() logic. Signed-off-by: Oleg Nesterov --- arch/x86/kernel/ptrace.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) --- TH/arch/x86/kernel/ptrace.c~5_X86_CONVERT_SYSCALL_LEAVE 2009-11-10 22:21:42.000000000 +0100 +++ TH/arch/x86/kernel/ptrace.c 2009-11-10 22:29:54.000000000 +0100 @@ -1528,29 +1528,22 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + bool step; + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->ax); - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); - /* * If TIF_SYSCALL_EMU is set, we only get here because of * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). * We already reported this syscall instruction in - * syscall_trace_enter(), so don't do any more now. - */ - if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) - return; - - /* - * If we are single-stepping, synthesize a trap to follow the - * system call instruction. + * syscall_trace_enter(). */ - if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) - send_sigtrap(current, regs, 0, TRAP_BRKPT); + step = unlikely(test_thread_flag(TIF_SINGLESTEP)) && + !test_thread_flag(TIF_SYSCALL_EMU); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } From oleg at redhat.com Tue Nov 10 21:59:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 10 Nov 2009 22:59:20 +0100 Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: <20091110211116.604B58C0@magilla.sf.frob.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> <20091109185226.GA11917@redhat.com> <20091109191112.917C970@magilla.sf.frob.com> <20091109205650.GA22673@redhat.com> <20091110211116.604B58C0@magilla.sf.frob.com> Message-ID: <20091110215920.GA14330@redhat.com> Ugh. I sent the patches before I checked email. On 11/10, Roland McGrath wrote: > > > Oh... this adds more naming problems. And this way x86's send_sigtrap() > > can't use this helper easily. > > It's true. Another approach would be to genericize send_sigtrap so that > all arch's can use it, and call that from tracehook_report_syscall_exit. > On x86 and powerpc TRAP_TRACE is the right si_code for step. But syscall_trace_leave() uses TRAP_BRKPT on x86. Should I change 4/5 ? It is not easy to genericize send_sigtrap(). The code is simple, but the changes in arch/ code are painfull. Besides, we need some "fill info" helper for utrace-ptrace. So. What about the 1-5 patches I sent? > > [PATCH 1/x] introduce user_single_step_siginfo() > > > perhaps user_single_step_siginfo() should go into ptrace.c ? > > Yes, I don't think it needs to be inlined. The new version of default helper is really trivial, an it is only inlined if the arch code doesn't care about the right implementation. Perhaps it can stay in ptrace.h? Oleg. From roland at redhat.com Wed Nov 11 04:12:39 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 10 Nov 2009 20:12:39 -0800 (PST) Subject: [PATCH 0/5] for upstream, user_single_step_siginfo() changes In-Reply-To: Oleg Nesterov's message of Tuesday, 10 November 2009 22:44:17 +0100 <20091110214417.GA14293@redhat.com> References: <20091110214417.GA14293@redhat.com> Message-ID: <20091111041239.4B0128FE@magilla.sf.frob.com> > Seriously, I don't think it makes sense to factor out memset + > si_signo = SIGTRAP. Imho we need a single helper which can/should > be overriden by arch's. Sure. I am fine with whatever hashes out upstream for this. Thanks, Roland From roland at redhat.com Wed Nov 11 04:15:57 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 10 Nov 2009 20:15:57 -0800 (PST) Subject: [PATCH 3/5] ptrace: change tracehook_report_syscall_exit() to handle stepping In-Reply-To: Oleg Nesterov's message of Tuesday, 10 November 2009 22:44:28 +0100 <20091110214428.GA14308@redhat.com> References: <20091110214428.GA14308@redhat.com> Message-ID: <20091111041558.0528B8FE@magilla.sf.frob.com> > This change affects ia64, microblaze, parisc, powerpc, sh. They pass > nonzero "step" argument to tracehook but since it was ignored the tracee > reports via ptrace_notify(), this is not right and not consistent. This could be more explicit about the details of the change. Ideally we should point to an actual test program whose results are changed by fixing the kernel. I think the best thing to say is that previously using purely PTRACE_SINGLESTEP without regard to what the user instructions were could sometimes swallow a provided signal, whereas now it treats the syscall instruction like any other user instruction. Thanks, Roland From roland at redhat.com Wed Nov 11 04:18:24 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 10 Nov 2009 20:18:24 -0800 (PST) Subject: [PATCH 0/2] Was: introduce suppress_sigtrap() to prevent unwanted send_sigtrap() In-Reply-To: Oleg Nesterov's message of Tuesday, 10 November 2009 22:59:20 +0100 <20091110215920.GA14330@redhat.com> References: <20091108205437.GA24252@redhat.com> <20091109180033.E0A3A712@magilla.sf.frob.com> <20091109185226.GA11917@redhat.com> <20091109191112.917C970@magilla.sf.frob.com> <20091109205650.GA22673@redhat.com> <20091110211116.604B58C0@magilla.sf.frob.com> <20091110215920.GA14330@redhat.com> Message-ID: <20091111041824.588F48FE@magilla.sf.frob.com> > But syscall_trace_leave() uses TRAP_BRKPT on x86. Should I change 4/5 ? Oh, I was sloppy in checking the values this time. Then probably the default TRAP_SINGLE_STEP should be 0 instead just to make clear that every arch needs to define it. But your other way is fine instead too. > The new version of default helper is really trivial, an it is only inlined > if the arch code doesn't care about the right implementation. Perhaps it can > stay in ptrace.h? I don't care. Do whatever you think is best and that upstream reviewers like. Thanks, Roland From roland at redhat.com Wed Nov 11 04:53:15 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 10 Nov 2009 20:53:15 -0800 (PST) Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: Oleg Nesterov's message of Thursday, 5 November 2009 18:39:31 +0100 <20091105173931.GA29215@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> <20091105173931.GA29215@redhat.com> Message-ID: <20091111045315.44B2C8FE@magilla.sf.frob.com> Ok. I realize it's largely separate, but I think we want to hash through this along with the other set of after-report-behavior problems. Also, it doesn't seem sensible to fiddle with utrace_report_syscall_entry separate from resolving UTRACE_SYSCALL_RESUMED change to the API. There was not much feedback about that change, but IIRC nobody was against it. So I've decided to merge the old utrace-syscall-resumed branch into utrace-cleanup. We can consider the resume-action handling details given that code. I'll try to look at all this with, as you say, a fresh head, on Wednesday. Thanks, Roland From sales003 at 28581848.cn Wed Nov 11 16:59:58 2009 From: sales003 at 28581848.cn (America Logistics-kiko) Date: Thu, 12 Nov 2009 00:59:58 +0800 Subject: America Logistics Message-ID: <200911111821.nABIKwKT018675@mx2.redhat.com> AMERICA INTERNATIONAL LOGISTICS?SHENZHEN? CO.,LTD Dear Sir/Madam, Good day! I'm kiko from ShenZhen China. I am working as forwarder in Guangdong port(Shenzhen,Guangzhou,Foshan port and so on.) for such long time, always provide the best service for Import and Export both of ocean and air freight. These services include: FCL Import and Export, LCL Consolidation, Break-Bulk; Air Freight Import and Export, Sea-Land Transportation; as well as arranging booking, clearance, inspection,loading and storage, consultation, insurance, etc, forwarding supported services. Sincerely hope that we can cooperate for international forwarding to reach to win-win situation.We would like to discuss such like, 1.FCL: Import and Export for Middle East, India and Pakistan, Africa, South &North America Europe, Mediterranean and so on ; 2..LCL: Freight comparison for all ports of worldwide (competitive); 3.Sea/air freight of chemical products, DG cargo in Shenzhen ports (negotiable); 4.Air freight:Ecport for Europe,South&North America. If this E-mail disturbs you and causes inconvenience, please inform us, and it will be stopped! B&R Sales Manager/kiko *********************************************************** America International Logistics(ShenZhen) Co.,Ltd Tel:86-0755-82020113 Fax:86-0755-82020123 82020160 Moblie:13554866206 QQ:385369704 E-mail:kiko at americalogi.com.cn MSN:kiko198263 at hotmail.com Http://www.americalogi.com.cn ADD;5E DongFang Ge,DongFang XinYueJu,FuMin Road,FuTian District,ShenZhen City,GuangDong province,China -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: clip_image002.jpg Type: image/jpeg Size: 3076 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: Clear Day Bkgrd.JPG Type: image/jpeg Size: 5675 bytes Desc: not available URL: From oleg at redhat.com Wed Nov 11 20:11:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 11 Nov 2009 21:11:24 +0100 Subject: [PATCH 3/5] ptrace: change tracehook_report_syscall_exit() to handle stepping In-Reply-To: <20091111041558.0528B8FE@magilla.sf.frob.com> References: <20091110214428.GA14308@redhat.com> <20091111041558.0528B8FE@magilla.sf.frob.com> Message-ID: <20091111201124.GA4792@redhat.com> On 11/10, Roland McGrath wrote: > > > This change affects ia64, microblaze, parisc, powerpc, sh. They pass > > nonzero "step" argument to tracehook but since it was ignored the tracee > > reports via ptrace_notify(), this is not right and not consistent. > > This could be more explicit about the details of the change. Ideally > we should point to an actual test program whose results are changed by > fixing the kernel. > > I think the best thing to say is that previously using purely > PTRACE_SINGLESTEP without regard to what the user instructions were > could sometimes swallow a provided signal, whereas now it treats the > syscall instruction like any other user instruction. Well, ptrace_report_syscall() checks current->exit_code after ptrace_notify() and does send_sig(). But yes, PTRACE_SETSIGINFO is doesn't work. Also. If PT_TRACESYSGOOD is set ptrace_report_syscall() adds 0x80 which is then reported by wait(&status), this doesn't look right. OK, I assume otherwise you acked these changes, I am going to update the changelog and send them to akpm with your acked-by included. You still have a chance to stop me ;) Oleg. From roland at redhat.com Wed Nov 11 20:23:31 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 11 Nov 2009 12:23:31 -0800 (PST) Subject: [PATCH 3/5] ptrace: change tracehook_report_syscall_exit() to handle stepping In-Reply-To: Oleg Nesterov's message of Wednesday, 11 November 2009 21:11:24 +0100 <20091111201124.GA4792@redhat.com> References: <20091110214428.GA14308@redhat.com> <20091111041558.0528B8FE@magilla.sf.frob.com> <20091111201124.GA4792@redhat.com> Message-ID: <20091111202331.510E39BC@magilla.sf.frob.com> > Well, ptrace_report_syscall() checks current->exit_code after > ptrace_notify() and does send_sig(). But yes, PTRACE_SETSIGINFO is > doesn't work. Oh, right. Aside from PTRACE_SETSIGINFO, it's more subtly wrong in that it generates a new signal (to be seen again by ptrace) rather than delivering it. > Also. If PT_TRACESYSGOOD is set ptrace_report_syscall() adds 0x80 > which is then reported by wait(&status), this doesn't look right. Right. > OK, I assume otherwise you acked these changes, I am going to update > the changelog and send them to akpm with your acked-by included. Yes. Thanks, Roland From oleg at redhat.com Wed Nov 11 21:56:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 11 Nov 2009 22:56:52 +0100 Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: <20091111045315.44B2C8FE@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> <20091105173931.GA29215@redhat.com> <20091111045315.44B2C8FE@magilla.sf.frob.com> Message-ID: <20091111215652.GA11151@redhat.com> On 11/10, Roland McGrath wrote: > > Ok. I realize it's largely separate, but I think we want to hash through > this along with the other set of after-report-behavior problems. > > Also, it doesn't seem sensible to fiddle with utrace_report_syscall_entry > separate from resolving UTRACE_SYSCALL_RESUMED change to the API. There > was not much feedback about that change, but IIRC nobody was against it. > So I've decided to merge the old utrace-syscall-resumed branch into > utrace-cleanup. I saw you have utrace-syscall-resumed branch but never looked at it. I'll try to follow these changes once I fix utrace-ptrace. Now that upstream problems with syscall_exit && trap are hopefully resolved this should be easy. Today I was distracted by workqueue bug (bluetooth driver actually), will try tomorrow. Roland, I guess utrace-cleanup becomes the "master" branch, yes? I mean, utrace-ptrace should be updated according to the recent changes in utrace-cleanup, and this is what you are going to send upstream. This means you should also merge utrace-cleanup into utrace-ptrace? Then I fix utrace-ptrace. I _think_ this will be easy too. ptrace_report_syscall_exit() can notice ctx->resume == UTRACE_SINGLESTEP and send the trap if utrace_control() doesn't set TIF_SINGLESTEP "synchronously". (And this means with utrace tracehook_report_syscall_exit() can do nothing except utrace_report_syscall_exit()). Oleg. From roland at redhat.com Wed Nov 11 23:01:11 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 11 Nov 2009 15:01:11 -0800 (PST) Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: Oleg Nesterov's message of Wednesday, 11 November 2009 22:56:52 +0100 <20091111215652.GA11151@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> <20091105173931.GA29215@redhat.com> <20091111045315.44B2C8FE@magilla.sf.frob.com> <20091111215652.GA11151@redhat.com> Message-ID: <20091111230111.DA2122E@magilla.sf.frob.com> > I saw you have utrace-syscall-resumed branch but never looked at it. For those not concerned with its purpose, there is one thing you must know. Every report_syscall_entry callback must do: if (utrace_syscall_action(action) == UTRACE_SYSCALL_RESUMED) return UTRACE_RESUME; to avoid being confused by the new extra callbacks. > Roland, I guess utrace-cleanup becomes the "master" branch, yes? > I mean, utrace-ptrace should be updated according to the recent > changes in utrace-cleanup, and this is what you are going to send > upstream. Right. I was waiting to be sure you didn't object. But AFAICT we now seem to be happy with this branch modulo more necessary fixes. > This means you should also merge utrace-cleanup into utrace-ptrace? Right. > Then I fix utrace-ptrace. I _think_ this will be easy too. > ptrace_report_syscall_exit() can notice ctx->resume == UTRACE_SINGLESTEP > and send the trap if utrace_control() doesn't set TIF_SINGLESTEP > "synchronously". > > (And this means with utrace tracehook_report_syscall_exit() can do > nothing except utrace_report_syscall_exit()). Today we don't call into utrace unless UTRACE_EVENT(SYSCALL_EXIT) is set. So if nothing changes in the utrace layer, this means that ptrace will enable UTRACE_EVENT(SYSCALL_EXIT) (i.e. TIF_SYSCALL) for PTRACE_SINGLE*. Is that what you had in mind? There are two possible issues with doing it that way. The first is purely from a ptrace perspective. Today PTRACE_SINGLE* does not set TIF_SYSCALL. On x86 this doesn't really make a difference in the underlying code, because TIF_SINGLESTEP takes the same path. So probably this is fine. But on other machines I'm not entirely sure that TIF_SYSCALL won't take a slower path than single-step alone caused already for syscall entries. This surely pales in comparison to the overhead of the ptrace stop and context switch and all, but still, it could be a change. On x86 I'm not sure there's any reason not to optimize that better in the future, too. Even in the most optimal circumstance imaginable, the whole point is to handle a SIGTRAP signal after the syscall, so that too probably dwarfs the overhead difference of the faster entry path. The other issue comes from the utrace API perspective. Here it just seems entirely wrong to require the engine (ptrace or any other) to do any syscall-exit magic of its own to make UTRACE_SINGLESTEP work on a syscall insn like it does on other insns. The utrace layer should make that trap appear transparently like the normal traps seen for UTRACE_SINGLESTEP. So, we could have tracehook_report_syscall_exit send the signal as it does now upstream. But probably better is to do it all in the utrace layer, i.e. pass the step flag to utrace_report_syscall_exit. Since today single-step generates a plain (forced) SIGTRAP, we can synthesize that. There are at least two options here. One is to do: if (step && (task->utrace_flags & UTRACE_SIGNAL_CORE)) { force_sig_info(...); } That approximates the check that yesterday's x86 code does: if (test_thread_flag(TIF_SINGLESTEP) && tracehook_consider_fatal_signal(current, SIGTRAP)) send_sigtrap(current, regs, 0, TRAP_BRKPT); But still we are queuing a real signal here. That is no different from the real hardware trap case, so perhaps that is the right thing to do for now. (Eventually we want to have a way for all these traps to avoid becoming real signals at all, but that is a subject for another day.) Like a real signal, that has the problem of still being queued if the tracer detaches immediately thereafter (so it gets delivered to the user). We could avoid that for this fake signal by just setting some flag that tells utrace_get_signal to synthesize it before dequeuing real signals. It's probably not worth bothering with that complexity now. Thanks, Roland From vendas at mardeb.com.br Thu Nov 12 12:38:20 2009 From: vendas at mardeb.com.br (Piero Jimenez) Date: Thu, 12 Nov 2009 12:38:20 GMT Subject: TINTAS INDUSTRIAIS LACA E ESMALTE SINTETICO Message-ID: <20091112123648.B92F83540ED@mhu16mtaz-tvt-spo.fly.com.br> An HTML attachment was scrubbed... URL: From david_riddle at jetty.net Thu Nov 12 12:39:14 2009 From: david_riddle at jetty.net (Dobbin Perkins) Date: Thu, 12 Nov 2009 13:39:14 +0100 Subject: Must have anti-EDs are now available all over the world! Message-ID: <002e01ca6395$246b7720$9937b8d7@ris67dwlxc> Medical news! http://ou.fliphas.com/ From boss at iammyownboss.co.uk Thu Nov 12 14:11:13 2009 From: boss at iammyownboss.co.uk (boss at iammyownboss.co.uk) Date: Thu, 12 Nov 2009 14:11:13 +0000 Subject: How Would you Like To Say Goodbye To Your Power Bill...? Message-ID: <069a7e7ff3c77ea8a090c271df5227a0@www.solduk.com> Hello, Have you found yourself frustrated due to the ever-rising power bills? I have found myself struggling with the same problem as well, But now, there is a solution. Did you know that you can generate your own electric energy, using a magnetic energy generator. It works by itself, and it produces absolutely free energy. It's called Magniwork, visit the following link to find out more : >>> Click Here! It is getting widely popular and people are starting to massively implement these generators, and completely eliminate their power bills. Proceed to: >>> Click Here! Also, They're currently running a special discount, and I have never seen Magniwork being priced so low. However, I have some 'inside' information that this offer is only going to last for a few days only, so you better take advantage of it, before the price goes back up >>> Click Here! p.s They're so sure that this will slash your power bill, that they're even offering an unconditonal 60 day money back guarantee!! -- If you do not want to receive any more newsletters, http://www.solduk.com/design/mailer/?p=unsubscribe&uid=b540d2cbc9c91ab36421a1c99474d5c1 To update your preferences and to unsubscribe visit http://www.solduk.com/design/mailer/?p=preferences&uid=b540d2cbc9c91ab36421a1c99474d5c1 Forward a Message to Someone http://www.solduk.com/design/mailer/?p=forward&uid=b540d2cbc9c91ab36421a1c99474d5c1&mid=2 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From info at campaigns.canal-marketing.com Thu Nov 12 18:15:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?FaxReception?=) Date: Thu, 12 Nov 2009 19:15:00 +0100 Subject: =?iso-8859-1?q?Vous_avez_re=E7u_un_Fax?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Thu Nov 12 21:40:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Nov 2009 22:40:00 +0100 Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: <20091111230111.DA2122E@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> <20091105173931.GA29215@redhat.com> <20091111045315.44B2C8FE@magilla.sf.frob.com> <20091111215652.GA11151@redhat.com> <20091111230111.DA2122E@magilla.sf.frob.com> Message-ID: <20091112214000.GA22914@redhat.com> On 11/11, Roland McGrath wrote: > > > I saw you have utrace-syscall-resumed branch but never looked at it. > > For those not concerned with its purpose, there is one thing you must > know. Every report_syscall_entry callback must do: > > if (utrace_syscall_action(action) == UTRACE_SYSCALL_RESUMED) > return UTRACE_RESUME; > > to avoid being confused by the new extra callbacks. OK, thanks. > > Then I fix utrace-ptrace. I _think_ this will be easy too. > > ptrace_report_syscall_exit() can notice ctx->resume == UTRACE_SINGLESTEP > > and send the trap if utrace_control() doesn't set TIF_SINGLESTEP > > "synchronously". > > > > (And this means with utrace tracehook_report_syscall_exit() can do > > nothing except utrace_report_syscall_exit()). > > Today we don't call into utrace unless UTRACE_EVENT(SYSCALL_EXIT) is set. > So if nothing changes in the utrace layer, this means that ptrace will > enable UTRACE_EVENT(SYSCALL_EXIT) (i.e. TIF_SYSCALL) for PTRACE_SINGLE*. > Is that what you had in mind? Yes, exactly. > There are two possible issues with doing it that way. > > The first is purely from a ptrace perspective. Today PTRACE_SINGLE* does > not set TIF_SYSCALL. On x86 this doesn't really make a difference in the > underlying code, because TIF_SINGLESTEP takes the same path. So probably > this is fine. But on other machines I'm not entirely sure that TIF_SYSCALL > won't take a slower path than single-step alone caused already for syscall > entries. This surely pales in comparison to the overhead of the ptrace > stop and context switch and all, but still, it could be a change. On x86 > I'm not sure there's any reason not to optimize that better in the future, I see. > The other issue comes from the utrace API perspective. Here it just seems > entirely wrong to require the engine (ptrace or any other) to do any > syscall-exit magic of its own to make UTRACE_SINGLESTEP work on a syscall > insn like it does on other insns. The utrace layer should make that trap > appear transparently like the normal traps seen for UTRACE_SINGLESTEP. > > So, we could have tracehook_report_syscall_exit send the signal as it does > now upstream. But probably better is to do it all in the utrace layer, Indeed! > i.e. pass the step flag to utrace_report_syscall_exit. The problem is, we can't use step flag. step == TIF_SINGLESTEP, and it can be unset despite the fact ptrace (or other engine) did utrace_control(UTRACE_SINGLESTEP) to resume. Simple example. The tracee stopped in syscall-entry. the tracer does PTRACE_SINGLESTEP. With the recent changes in utrace-cleanup utrace_control() doesn't set TIF_SINGLESTEP, and the tracee passes syscall_trace_leave() without TIF_SINGLESTEP. But I guess utrace_report_syscall_exit() can look at utrace->resume and notice UTRACE_SINGLESTEP ? > That approximates the check that yesterday's x86 code does: > > if (test_thread_flag(TIF_SINGLESTEP) && > tracehook_consider_fatal_signal(current, SIGTRAP)) > send_sigtrap(current, regs, 0, TRAP_BRKPT); > > But still we are queuing a real signal here. That is no different from the > real hardware trap case, so perhaps that is the right thing to do for now. > (Eventually we want to have a way for all these traps to avoid becoming > real signals at all, but that is a subject for another day.) Like a real > signal, that has the problem of still being queued if the tracer detaches > immediately thereafter (so it gets delivered to the user). We could avoid > that for this fake signal by just setting some flag that tells > utrace_get_signal to synthesize it before dequeuing real signals. > It's probably not worth bothering with that complexity now. Yes, I think we have more important problems ;) Oleg. From roland at redhat.com Thu Nov 12 22:05:33 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Nov 2009 14:05:33 -0800 (PST) Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: Oleg Nesterov's message of Thursday, 5 November 2009 11:01:23 +0100 <20091105100123.GA11286@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> Message-ID: <20091112220533.5C18288D@magilla.sf.frob.com> I did some tweaks that I think address the several things you've raised. But I didn't try to reply point by point. I've merged everything up now, so the utrace-cleanup branch is gone. Please review the current code and post about anything we still need to fix. I merged into utrace-ptrace and did the trivial hack to handle UTRACE_SYSCALL_RESUMED. Later we probably want to change this to some smarter handling so that ptrace doesn't report until other engines have finished their fiddling and let the thread resume. That way we can have e.g. strace vs kmview show something consistent. But we can refine this later. I think what I did is sufficient to maintain the status quo in your code. You can fix it up as needed. Thanks, Roland From oleg at redhat.com Thu Nov 12 22:08:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Nov 2009 23:08:31 +0100 Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: <20091102100646.5593F4EC@magilla.sf.frob.com> References: <20091102064456.GA30277@redhat.com> <20091102100646.5593F4EC@magilla.sf.frob.com> Message-ID: <20091112220831.GA24206@redhat.com> On 11/02, Roland McGrath wrote: > > > - unlike send_sigtrap()->force_sig_info() we don't unblock > > SIGTRAP or reset the handler > > This is nicer for debugger things actually, but we don't have such niceness > for real traps and won't soon. IMHO it is best to start with doing exactly > what the old x86 code does, which is force_sig_info--which is also making > all machines uniformly do "what a real single-step trap does" and is thus > consistent in this PTRACE_SINGLESTEP case matching all others, which we > have been saying is a sensible principle. > > > these changes looks good (but see the next patch). However, any > > user-visible change is dangerous. > > Let's not roll it in. As well as it just being bad form to roll that into > implementation detail changes, it makes things less consistent rather than > more (on x86, anyway, and arguably across the board). OK. So, we should revert this change and send the trap from ptrace_resume(), - instead of send_sigtrap() we should use user_single_step_siginfo() + force_sig_info() - PTRACE_EVENT_SYSCALL_EXIT shouldn't send the trap, this was x86 specific behaviour, and this is fixed in upstream by [PATCH v2 5/5] ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping we recently sent. (btw, I wrongly thought x86 is right and other machines should be fixed). Correct? If yes: - force_sig_info() needs tasklist_lock. we can change force_sig_info() to use lock_task_sighand(), but perhaps we should not worry about this now - what should we do with PTRACE_EVENT_SIGTRAP ? > So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of > UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look > like a vanilla SIGTRAP and then fall into the default case for > real signals. should UTRACE_SIGNAL_HANDLER use force_sig_info() too or it can just deliver this *info as you initially suggested ? Or we can forget about this change for now? I agree in advance with everything you prefer, you definetely know better. Anything else I missed? Oleg. From oleg at redhat.com Thu Nov 12 22:17:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Nov 2009 23:17:22 +0100 Subject: [PATCH 122] ptrace_request(PTRACE_KILL) should not(?) return -ESRCH In-Reply-To: <20091030073646.E09419BF@magilla.sf.frob.com> References: <20091030032840.GA5735@redhat.com> <20091030073646.E09419BF@magilla.sf.frob.com> Message-ID: <20091112221722.GA24283@redhat.com> Just noticed I didn't reply to this message, On 10/30, Roland McGrath wrote: > > > If the tracee was STOPPED/TRACED, then it is equivalent to PTRACE_CONT,SIGKILL. > > Otherwise it has no effect except it can race with exit() and spoil ->exit_code, > > and wake_up_process() is not good if course. (I am talking about upstream). > > Correct. In job control stop (including one already turned into > TASK_TRACED by a prior ptrace call), the resumption signal is ignored. > So the only reliable effect at all is when it's in a proper ptrace stop > that doesn't otherwise swallow signals (i.e. exactly PTRACE_CONT,SIGKILL > that ignores liveness/stoppedness errors). In every other case it has > no effect at best, so fixing that to "no effect at all" is just fine. > > > Please tell me what do you think, then I'll do other changes you suggested. > > In the old code, PTRACE_KILL can never fail once the initial attachedness > test has passed. So: > > (void) ptrace_resume(child, engine, request, SIGKILL); > ret = 0; /* Historical compatibility. */ > > is probably fine. Yes, but utrace-ptrace does a lot more in ptrace_resume() compared to upstream. If the tracee is not stopped, then ptrace_resume() can race with the tracee in many ways. This is mostly harmless, I think, but still I did if (task_is_traced(child)) ptrace_resume(PTRACE_CONT, SIGKILL); ret = 0; Oleg. From roland at redhat.com Thu Nov 12 22:27:05 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Nov 2009 14:27:05 -0800 (PST) Subject: utrace_report_syscall_entry() && finish_report() In-Reply-To: Oleg Nesterov's message of Thursday, 12 November 2009 22:40:00 +0100 <20091112214000.GA22914@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091105161742.GA26428@redhat.com> <20091105173931.GA29215@redhat.com> <20091111045315.44B2C8FE@magilla.sf.frob.com> <20091111215652.GA11151@redhat.com> <20091111230111.DA2122E@magilla.sf.frob.com> <20091112214000.GA22914@redhat.com> Message-ID: <20091112222705.B294E505@magilla.sf.frob.com> > Simple example. The tracee stopped in syscall-entry. the tracer does > PTRACE_SINGLESTEP. With the recent changes in utrace-cleanup > utrace_control() doesn't set TIF_SINGLESTEP, and the tracee passes > syscall_trace_leave() without TIF_SINGLESTEP. Ah, yes. Well, the point of the arch/tracehook tweaks was that the utrace layer has all the information and can decide what to do. > But I guess utrace_report_syscall_exit() can look at utrace->resume > and notice UTRACE_SINGLESTEP ? Yes. Unlike ptrace, at the utrace layer we can have both syscall-exit and single-step going on at the same time (even by unrelated engines). If some engine doesn't care about syscall-exit, it will still get report_quiesce there and should reassert UTRACE_SINGLESTEP with its return value. But that makes it a bit unclear whether a UTRACE_SINGLESTEP return from report_syscall_exit wants a fresh step after the next insn, or wants a synthetic trap immediately after the syscall insn. So I wonder if what might be right is to have utrace_report_syscall_exit look at ->resume before its reporting. If it's single/block-step it can synthesize the trap there, so the signal is queued before the syscall-exit report is made. Thanks, Roland From oleg at redhat.com Thu Nov 12 22:24:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 12 Nov 2009 23:24:52 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091112220533.5C18288D@magilla.sf.frob.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091112220533.5C18288D@magilla.sf.frob.com> Message-ID: <20091112222452.GB24283@redhat.com> On 11/12, Roland McGrath wrote: > > I did some tweaks that I think address the several things you've raised. > But I didn't try to reply point by point. I've merged everything up now, > so the utrace-cleanup branch is gone. Please review the current code and > post about anything we still need to fix. Great, thanks. I will definitely read the changes in utrace.c, if nothing else this is interesting to me. But for now, until utrace-ptrace is updated/finished, I will assume it is correct and doesn't need any further changes. Oleg. From roland at redhat.com Thu Nov 12 22:36:07 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Nov 2009 14:36:07 -0800 (PST) Subject: [PATCH 122] ptrace_request(PTRACE_KILL) should not(?) return -ESRCH In-Reply-To: Oleg Nesterov's message of Thursday, 12 November 2009 23:17:22 +0100 <20091112221722.GA24283@redhat.com> References: <20091030032840.GA5735@redhat.com> <20091030073646.E09419BF@magilla.sf.frob.com> <20091112221722.GA24283@redhat.com> Message-ID: <20091112223607.EDEC9505@magilla.sf.frob.com> > Yes, but utrace-ptrace does a lot more in ptrace_resume() compared > to upstream. If the tracee is not stopped, then ptrace_resume() can > race with the tracee in many ways. This is mostly harmless, I think, > but still I did > > if (task_is_traced(child)) > ptrace_resume(PTRACE_CONT, SIGKILL); > ret = 0; That is fine enough. But it's probably good to attain confidence that these races are truly harmless. If it can clobber tracee->exit_code, that is no worse than old ptrace, though it would be better to make that impossible. If it can post signals, that is fine since this is only for the already-SIGKILL'd case. Thanks, Roland From roland at redhat.com Thu Nov 12 22:50:50 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 12 Nov 2009 14:50:50 -0800 (PST) Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: Oleg Nesterov's message of Thursday, 12 November 2009 23:08:31 +0100 <20091112220831.GA24206@redhat.com> References: <20091102064456.GA30277@redhat.com> <20091102100646.5593F4EC@magilla.sf.frob.com> <20091112220831.GA24206@redhat.com> Message-ID: <20091112225050.9B8B9505@magilla.sf.frob.com> > So, we should revert this change and send the trap from ptrace_resume(), What's wrong with ptrace_report_signal doing it? > - instead of send_sigtrap() we should use user_single_step_siginfo() > + force_sig_info() Right. > - PTRACE_EVENT_SYSCALL_EXIT shouldn't send the trap, this was > x86 specific behaviour, and this is fixed in upstream by Right. > (btw, I wrongly thought x86 is right and other machines should > be fixed). In these corner cases it is always debatable what "right" is. I didn't really think and decide about it until recently when we decided about the upstream change. > - force_sig_info() needs tasklist_lock. > > we can change force_sig_info() to use lock_task_sighand(), > but perhaps we should not worry about this now It would be much better if we can leave the signals code alone. (It can always use more cleanups, but let those happen later on their own.) I think ideally we should try to invoke it the way it's invoked now, i.e. force_sig_info() is called on current. > - what should we do with PTRACE_EVENT_SIGTRAP ? > > > So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of > > UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look > > like a vanilla SIGTRAP and then fall into the default case for > > real signals. > > should UTRACE_SIGNAL_HANDLER use force_sig_info() too or > it can just deliver this *info as you initially suggested ? > > Or we can forget about this change for now? We need to make it consistent with the upstream ptrace behavior, so we can't forget about anything that's needed for that. Today tracehook_signal_handler() uses ptrace_notify(). So that is more like an implicit fake signal report than a real queued SIGTRAP. (Still we won't ignore the resume signal any more, but that is a desireable change.) Conversely, we could make an upstream change along the lines of the tracehook_report_syscall_exit() change, so that this uses a real SIGTRAP instead of ptrace_notify(). That has some logic to it. But today this case is consistent across machines, so we could consider that behavior change separately after utrace merges. > I agree in advance with everything you prefer, you definetely > know better. :-) Perhaps I do when I have it all in mind at the same moment. But my brain capacity is feeling a bit low this week. > Anything else I missed? I hope not! This area is not really fresh in my mind right now. Thanks, Roland From newsletter at brinde-companhia.com Fri Nov 13 11:58:24 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Fri, 13 Nov 2009 12:58:24 +0100 Subject: =?iso-8859-1?q?Chuva_de_pre=E7os=2E=2E=2E?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Nov 13 18:59:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 19:59:31 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091112222452.GB24283@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091112220533.5C18288D@magilla.sf.frob.com> <20091112222452.GB24283@redhat.com> Message-ID: <20091113185931.GA9252@redhat.com> On 11/12, Oleg Nesterov wrote: > > On 11/12, Roland McGrath wrote: > > > > I did some tweaks that I think address the several things you've raised. > > But I didn't try to reply point by point. I've merged everything up now, > > so the utrace-cleanup branch is gone. Please review the current code and > > post about anything we still need to fix. > > Great, thanks. > > I will definitely read the changes in utrace.c, if nothing else this is > interesting to me. But for now, until utrace-ptrace is updated/finished, > I will assume it is correct and doesn't need any further changes. (except the SIGTRAP changes in utrace_report_syscall_exit() we are discussing in another thread) Roland, I pulled the last changes in your tree (utrace-cleanup merged in utrace-ptrace) and did some testing. In short: utrace-ptrace does not work at all. It fails a lot (if not most) of tests, in particular sa-resethand-on-cont-signal hangs and clone-multi-ptrace silently crashes the kernel. The quick investigation didn't help, utrace.c has too much changes, I will read the code tomorrow from the very beginning. Today I am going to pretend utrace works and do the discussed changes in utrace-ptrace, then try to fix utrace. Oleg. From oleg at redhat.com Fri Nov 13 19:46:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 20:46:05 +0100 Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: <20091112225050.9B8B9505@magilla.sf.frob.com> References: <20091102064456.GA30277@redhat.com> <20091102100646.5593F4EC@magilla.sf.frob.com> <20091112220831.GA24206@redhat.com> <20091112225050.9B8B9505@magilla.sf.frob.com> Message-ID: <20091113194605.GA11051@redhat.com> On 11/12, Roland McGrath wrote: > > > So, we should revert this change and send the trap from ptrace_resume(), > > What's wrong with ptrace_report_signal doing it? Nothing wrong (I think), but this is more complex and implies more unnecessary work. If the trap is sent by ptrace_resume() everything is simple. The tracee is stopped, we send the signal, and that is all. If ptrace_report_signal() sends the trap, we actually send the signal twice. Firstly ptrace_resume() does utrace_control(UTRACE_INTERRUPT) (ok, this is not the signal sending but sort of), then ->report_signal() notices we need the trap and send the "real" signal, then we return to get_signal_to_deliver() which calls utrace_get_signal() again, it dequeues SIGTRAP and calls ptrace_report_signal() again to finally report SIGTRAP to the tracer. But see below. > I > think ideally we should try to invoke it the way it's invoked now, i.e. > force_sig_info() is called on current. OK. Then we should send it from the callback. But: I am not sure yet, but I think the current code is not optimal for that, it was written to report *info without force_sig_info(). If we are going to send the signal instead, we can send it from ->report_quiesce() as well. So, I am going to revert these changes to move the send_sigtrap() logic back to ptrace_resume(), then I will think how to move this into callback context. > > - what should we do with PTRACE_EVENT_SIGTRAP ? > > > > > So, get rid of PTRACE_EVENT_SIGTRAP. Instead for the case of > > > UTRACE_SIGNAL_HANDLER when stepping, initialize *info to look > > > like a vanilla SIGTRAP and then fall into the default case for > > > real signals. > > > > should UTRACE_SIGNAL_HANDLER use force_sig_info() too or > > it can just deliver this *info as you initially suggested ? > > > > Or we can forget about this change for now? > > We need to make it consistent with the upstream ptrace behavior, > so we can't forget about anything that's needed for that. Today > tracehook_signal_handler() uses ptrace_notify(). So that is more > like an implicit fake signal report than a real queued SIGTRAP. So, lets revert this change for now to be compatible. This change is simple and can be done again at any time, probably along with upstream change. OK? Oleg. From roland at redhat.com Fri Nov 13 20:21:28 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 13 Nov 2009 12:21:28 -0800 (PST) Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: Oleg Nesterov's message of Friday, 13 November 2009 20:46:05 +0100 <20091113194605.GA11051@redhat.com> References: <20091102064456.GA30277@redhat.com> <20091102100646.5593F4EC@magilla.sf.frob.com> <20091112220831.GA24206@redhat.com> <20091112225050.9B8B9505@magilla.sf.frob.com> <20091113194605.GA11051@redhat.com> Message-ID: <20091113202128.C4286E3@magilla.sf.frob.com> > Nothing wrong (I think), but this is more complex and implies more > unnecessary work. You mean the code path taken is longer. But the code's logic remains simple. > If ptrace_report_signal() sends the trap, we actually send the signal > twice. Firstly ptrace_resume() does utrace_control(UTRACE_INTERRUPT) > (ok, this is not the signal sending but sort of), then ->report_signal() > notices we need the trap and send the "real" signal, then we return > to get_signal_to_deliver() which calls utrace_get_signal() again, it > dequeues SIGTRAP and calls ptrace_report_signal() again to finally > report SIGTRAP to the tracer. I don't think this extra step is particuarly costly given the context. > But: I am not sure yet, but I think the current code is not optimal for > that, it was written to report *info without force_sig_info(). I don't really follow that bit. But I'll just see what new code you come up with. > So, lets revert this change for now to be compatible. This change > is simple and can be done again at any time, probably along with > upstream change. Ok. Thanks, Roland From oleg at redhat.com Fri Nov 13 22:05:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 23:05:08 +0100 Subject: [PATCH 127] move ptrace_resume()->send_sigtrap() logic into ptrace_report_signal() In-Reply-To: <20091113202128.C4286E3@magilla.sf.frob.com> References: <20091102064456.GA30277@redhat.com> <20091102100646.5593F4EC@magilla.sf.frob.com> <20091112220831.GA24206@redhat.com> <20091112225050.9B8B9505@magilla.sf.frob.com> <20091113194605.GA11051@redhat.com> <20091113202128.C4286E3@magilla.sf.frob.com> Message-ID: <20091113220508.GA32600@redhat.com> On 11/13, Roland McGrath wrote: > > > Nothing wrong (I think), but this is more complex and implies more > > unnecessary work. > > You mean the code path taken is longer. But the code's logic remains simple. The logic a bit complicated too, because ctx->signr is overloaded. Otohm, I don't like to add "bool send_trap" into ptrace_context. But yes, it is still simple. > > But: I am not sure yet, but I think the current code is not optimal for > > that, it was written to report *info without force_sig_info(). > > I don't really follow that bit. > But I'll just see what new code you come up with. No, you won't see the more optimal code ;) I was going to use UTRACE_REPORT instead of UTRACE_INTERRUPT and factor out some common code in report_quiesce/report_signal, but that was a bad idea. Please see the simple 130-132 patches I am sending, tomorrow I'll try to understand/fix the breakage caused by utrace-cleanup changed. I tried to understand why the kernel crashes at least, but no luck today. The kernel just hangs silently without any messages. Fortunately this all is reproducible ;) Oleg. From oleg at redhat.com Fri Nov 13 22:05:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 23:05:41 +0100 Subject: [PATCH 130] revert "turn PTRACE_EVENT_SIGTRAP into PTRACE_EVENT_SIGNAL" Message-ID: <20091113220541.GA856@redhat.com> By the previous discussion, revert 603e19c41ba5c97e48a25543c63c081c5fe64137 for now. But keep WARN_ON(resume != XXX_STEP), it may help. --- kernel/ptrace.c | 14 ++++++-------- 1 file changed, 6 insertions(+), 8 deletions(-) --- PU/kernel/ptrace.c~130_REVERT_KILL_PTRACE_EVENT_SIGTRAP 2009-11-02 06:54:49.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-13 22:34:23.000000000 +0100 @@ -73,7 +73,8 @@ struct ptrace_context { #define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) #define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGNAL (3 << 16) +#define PTRACE_EVENT_SIGTRAP (3 << 16) +#define PTRACE_EVENT_SIGNAL (4 << 16) /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF @@ -526,10 +527,10 @@ static u32 ptrace_report_signal(u32 acti if (resume != UTRACE_RESUME) { WARN_ON(resume != UTRACE_BLOCKSTEP && resume != UTRACE_SINGLESTEP); - WARN_ON(ctx->signr); - ctx->signr = SIGTRAP; + + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; } - /* fallthrough */ case UTRACE_SIGNAL_REPORT: if (!ctx->siginfo) { @@ -537,10 +538,7 @@ static u32 ptrace_report_signal(u32 acti return resume | UTRACE_SIGNAL_IGN; WARN_ON(ctx->signr != SIGTRAP); - /* - * set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) or - * by UTRACE_SIGNAL_HANDLER above. - */ + /* set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) */ fill_sigtrap_info(task, info); break; } From oleg at redhat.com Fri Nov 13 22:05:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 23:05:44 +0100 Subject: [PATCH 131] don't send the unnecessary SIGTRAP after SYSCALL_EXIT Message-ID: <20091113220544.GA863@redhat.com> PTRACE_SINGLESTEP after syscall-exit shouldn't trigger the trap before return to user-mode. This was the x86 spicific oddity which is already fixed in -mm by ptrace-x86-change-syscall_trace_leave-to-rely-on-tracehook-when-stepping.patch --- kernel/ptrace.c | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) --- PU/kernel/ptrace.c~131_SYSCALL_EXIT_DONT_TRAP 2009-11-13 22:34:23.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-13 22:35:40.000000000 +0100 @@ -940,10 +940,7 @@ static int ptrace_resume(struct task_str do_ptrace_notify_stop(ctx, tracee); return 0; } - /* fallthrough, but suppress send_sig_info() below */ - data = 0; - case PTRACE_EVENT_SYSCALL_EXIT: if (action != UTRACE_RESUME) { /* * single-stepping. UTRACE_SIGNAL_REPORT will @@ -952,8 +949,9 @@ static int ptrace_resume(struct task_str ctx->signr = SIGTRAP; action = UTRACE_INTERRUPT; } - /* fallthrough */ + break; + case PTRACE_EVENT_SYSCALL_EXIT: case PTRACE_EVENT_SYSCALL_ENTRY: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); From oleg at redhat.com Fri Nov 13 22:05:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 13 Nov 2009 23:05:46 +0100 Subject: [PATCH 132] change ptrace_report_signal() to use user_single_step_siginfo() Message-ID: <20091113220546.GA866@redhat.com> Change ptrace_report_signal() to report SIGTRAP via user_single_step_siginfo() + force_sig_info(). --- kernel/ptrace.c | 24 +++++++++--------------- 1 file changed, 9 insertions(+), 15 deletions(-) --- PU/kernel/ptrace.c~132_USER_SINGLE_STEP_INFO 2009-11-13 22:35:40.000000000 +0100 +++ PU/kernel/ptrace.c 2009-11-13 22:44:10.000000000 +0100 @@ -451,16 +451,10 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_STOP; } -static void fill_sigtrap_info(struct task_struct *task, siginfo_t *info) +static void ptrace_send_sigtrap(struct task_struct *task, siginfo_t *info) { -#ifdef CONFIG_X86 - task->thread.trap_no = 1; - task->thread.error_code = 0; -#endif - memset(info, 0, sizeof(*info)); - info->si_signo = SIGTRAP; - info->si_code = TRAP_BRKPT; - info->si_addr = (void __user*)KSTK_EIP(task); + user_single_step_siginfo(task, task_pt_regs(task), info); + force_sig_info(SIGTRAP, info, task); } static enum utrace_signal_action resume_signal(struct task_struct *task, @@ -534,13 +528,13 @@ static u32 ptrace_report_signal(u32 acti case UTRACE_SIGNAL_REPORT: if (!ctx->siginfo) { - if (!ctx->signr) - return resume | UTRACE_SIGNAL_IGN; + if (ctx->signr) { + /* set by ptrace_resume(SYSCALL_EXIT) */ + WARN_ON(ctx->signr != SIGTRAP); + ptrace_send_sigtrap(task, info); + } - WARN_ON(ctx->signr != SIGTRAP); - /* set by ptrace_resume(PTRACE_EVENT_SYSCALL_EXIT) */ - fill_sigtrap_info(task, info); - break; + return resume | UTRACE_SIGNAL_IGN; } if (WARN_ON(ctx->siginfo != info)) From TheCuteKid at iammyownboss.co.uk Sat Nov 14 17:57:16 2009 From: TheCuteKid at iammyownboss.co.uk (TheCuteKid at iammyownboss.co.uk) Date: Sat, 14 Nov 2009 17:57:16 +0000 Subject: Cute Kid of the Year - enter to win $25,000 Message-ID: <079b79ebba45072eb216713ff8e1e0d7@www.solduk.com> Welcome to The CuteKid, the internet?s largest online child photo contest! Judged by professional talent and casting agents. Do you have a Cute Kid? If so, we invite you to join our growing community of loving parents just like you by submitting a photo of YOUR cute kid for a chance to win a $25,000 College Tuition Fund! Submit your photo today! Enter today and receive instant rewards like a 1 year subscription to Parenting Magazine and a 8X10 Canvas portrait of your photo. If you have a cute kid that is just waiting to be discovered, don?t delay. Membership is free and easy ? Sign Up Today! For more information about the 2008 CuteKid? of the Year Contest, please visit our How it Works page. If you seek more information including our address, Click here. -- If you do not want to receive any more newsletters, http://www.solduk.com/design/mailer/?p=unsubscribe&uid=b540d2cbc9c91ab36421a1c99474d5c1 To update your preferences and to unsubscribe visit http://www.solduk.com/design/mailer/?p=preferences&uid=b540d2cbc9c91ab36421a1c99474d5c1 Forward a Message to Someone http://www.solduk.com/design/mailer/?p=forward&uid=b540d2cbc9c91ab36421a1c99474d5c1&mid=4 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From news at maisservicos.com Sun Nov 15 03:31:02 2009 From: news at maisservicos.com (MaisServicos) Date: Sun, 15 Nov 2009 03:31:02 +0000 Subject: Perca 10 Quilos em 15 dias! Message-ID: <20091115033259.81BAD23A7B@server17.nortenet.pt> Caso n?o visualize correctamente este e-mail, por favor clique AQUI. NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From oleg at redhat.com Sun Nov 15 03:48:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 15 Nov 2009 04:48:44 +0100 Subject: [PATCH 0/1] Was: utrace-cleanup branch In-Reply-To: <20091113185931.GA9252@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091112220533.5C18288D@magilla.sf.frob.com> <20091112222452.GB24283@redhat.com> <20091113185931.GA9252@redhat.com> Message-ID: <20091115034844.GA8511@redhat.com> On 11/13, Oleg Nesterov wrote: > > Roland, I pulled the last changes in your tree (utrace-cleanup merged > in utrace-ptrace) and did some testing. > > In short: utrace-ptrace does not work at all. > > It fails a lot (if not most) of tests, in particular > sa-resethand-on-cont-signal hangs and clone-multi-ptrace silently > crashes the kernel. > > The quick investigation didn't help, utrace.c has too much changes, > I will read the code tomorrow from the very beginning. Ooooooooooooohhhhhhhhh. In short, the code in utrace.c was broken even before utrace-cleanup was merged (but I bet utrace-cleanup adds more problems which I don't understand yet), and the patch below "fixes" utrace.c (without utrace-cleanup applied). Cough. I guess you want to know why I didn't notice this before. Because the code in my utrace.c didn't match the code in your utrace-ptrace branch. How did this happen? I added some hacks to utrace.c for debugging purposes. In particular, I added the code to track engine alloc/free, and added the dirty hack to fix "access_process_vm() under spinlock" bug. And some more changes. But! I do not remember how, why and when the code below was added to utrace_attach_task() in my tree. I guess it was the temporary debugging change which I forgot to revert later. Will continue tomorrow. Oleg. --- OOPS/kernel/utrace.c~TTF 2009-11-15 03:48:09.000000000 +0100 +++ OOPS/kernel/utrace.c 2009-11-15 03:52:47.000000000 +0100 @@ -180,6 +180,10 @@ static int utrace_add_engine(struct task * notified about the event that precipitated its own * creation. This is not what the user wants. */ + +utrace->report = 1; +set_notify_resume(target); + list_add_tail(&engine->entry, &utrace->attaching); utrace->pending_attach = 1; ret = 0; From oleg at redhat.com Sun Nov 15 18:26:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 15 Nov 2009 19:26:33 +0100 Subject: [PATCH, FYI] fix attach vs report signal race in the old utrace branch In-Reply-To: <20091115034844.GA8511@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091112220533.5C18288D@magilla.sf.frob.com> <20091112222452.GB24283@redhat.com> <20091113185931.GA9252@redhat.com> <20091115034844.GA8511@redhat.com> Message-ID: <20091115182633.GA26748@redhat.com> On 11/15, Oleg Nesterov wrote: > > In short, the code in utrace.c was broken even before utrace-cleanup > was merged (but I bet utrace-cleanup adds more problems which I don't > understand yet), and the patch below "fixes" utrace.c (without > utrace-cleanup applied). Please see the patch below. I know it is too late to fix this old branch (utrace without utrace-cleanup changes), just fyi. The race is simple. utrace_attach_task() sets ->pending_attach, but utrace_get_signal() can miss it and dequeue/report a signal without splice_attaching(). Now everything in ptrace-tests works again as before. Just in case, the last commit in my utrace.c now is utrace_set_events: nit clean up 9e0f357ab8de409cb722921e7fca7e6a94fd6e09 Now I am going to switch to your tree again, make the similar fix and test. --- kernel/utrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- PU/kernel/utrace.c~UTRACE_ATTACH_SIGNAL_RACE 2009-11-15 18:36:38.000000000 +0100 +++ PU/kernel/utrace.c 2009-11-15 18:44:44.000000000 +0100 @@ -1899,7 +1899,8 @@ int utrace_get_signal(struct task_struct int signr; utrace = &task->utrace; - if (utrace->interrupt || utrace->report || utrace->signal_handler) { + if (utrace->report || utrace->interrupt || + utrace->pending_attach || utrace->signal_handler) { /* * We've been asked for an explicit report before we * even check for pending signals. From oleg at redhat.com Sun Nov 15 19:36:14 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 15 Nov 2009 20:36:14 +0100 Subject: [PATCH] utrace: utrace_get_signal() must check ->pending_attach In-Reply-To: <20091115034844.GA8511@redhat.com> References: <20091029020329.A58A0534@magilla.sf.frob.com> <20091103053747.GA11794@redhat.com> <20091103231411.5AB7471C3@magilla.sf.frob.com> <20091105100123.GA11286@redhat.com> <20091112220533.5C18288D@magilla.sf.frob.com> <20091112222452.GB24283@redhat.com> <20091113185931.GA9252@redhat.com> <20091115034844.GA8511@redhat.com> Message-ID: <20091115193614.GA8652@redhat.com> On 11/15, Oleg Nesterov wrote: > > On 11/13, Oleg Nesterov wrote: > > > > Roland, I pulled the last changes in your tree (utrace-cleanup merged > > in utrace-ptrace) and did some testing. > > > > In short: utrace-ptrace does not work at all. > > > > It fails a lot (if not most) of tests, in particular > > sa-resethand-on-cont-signal hangs and clone-multi-ptrace silently > > crashes the kernel. > > > > The quick investigation didn't help, utrace.c has too much changes, > > I will read the code tomorrow from the very beginning. > > Ooooooooooooohhhhhhhhh. > > In short, the code in utrace.c was broken even before utrace-cleanup > was merged And your current tree has the same problem: utrace_attach_task() sets ->pending_attach, but utrace_get_signal() can miss it and dequeue/report a signal without splice_attaching(). Change utrace_get_signal() to check ->pending_attach. I do not understand the new code yet, I am not sure this patch is optimal. But it helps, the kernel doesn't crash/hang any longer. We still have problems, 5 tests fail. Some failures are expected, we know that the changes in utrace-cleanup must break the stepping logic in ptrace (to remind you just in case, utrace_control(STEP) doesn't call enable_step() synchronously). Some are not, ptrace_event_clone for example. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) --- UTRACE-PTRACE/kernel/utrace.c~UTRACE_ATTACH_SIGNAL_RACE 2009-11-13 18:00:06.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-15 19:52:29.000000000 +0100 @@ -1955,7 +1955,8 @@ int utrace_get_signal(struct task_struct int signr; utrace = task_utrace_struct(task); - if (utrace->resume < UTRACE_RESUME || utrace->signal_handler) { + if (utrace->resume < UTRACE_RESUME || + utrace->pending_attach || utrace->signal_handler) { enum utrace_resume_action resume; /* From oleg at redhat.com Sun Nov 15 22:04:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 15 Nov 2009 23:04:22 +0100 Subject: [PATCH] utrace: finish_report() must never set ->resume = UTRACE_STOP Message-ID: <20091115220422.GA31683@redhat.com> finish_report: if (will_not_stop && resume == UTRACE_STOP) resume = UTRACE_REPORT; OK, this is to avoid the subsequent utrace_resume() report when we are going to stop. But the logic is wrong, ->resume must never be UTRACE_STOP. Once we set ->resume = UTRACE_STOP, we break every code which tries to update ->resume doing if (action < utrace->resume) utrace->resume = action; With this patch the kernel passes all tests except single-step ones, as expected. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~UTRACE_RESUME_MUST_NOT_BE_STOP 2009-11-15 22:39:33.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-15 22:41:57.000000000 +0100 @@ -1357,8 +1357,10 @@ static void finish_report(struct task_st struct utrace_report *report, bool will_not_stop) { enum utrace_resume_action resume = report->action; - if (will_not_stop && resume == UTRACE_STOP) - resume = UTRACE_REPORT; + + if (resume == UTRACE_STOP) { + resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; + } if (resume < utrace->resume) { spin_lock(&utrace->lock); From oleg at redhat.com Sun Nov 15 22:11:11 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 15 Nov 2009 23:11:11 +0100 Subject: [PATCH] utrace: finish_report() must never set ->resume = UTRACE_STOP In-Reply-To: <20091115220422.GA31683@redhat.com> References: <20091115220422.GA31683@redhat.com> Message-ID: <20091115221111.GA31834@redhat.com> On 11/15, Oleg Nesterov wrote: > > With this patch the kernel passes all tests except single-step ones, as > expected. Forgot to mention, your tree lacks these patches we sent upstream: ptrace-introduce-user_single_step_siginfo-helper.patch ptrace-powerpc-implement-user_single_step_siginfo.patch ptrace-change-tracehook_report_syscall_exit-to-handle-stepping.patch ptrace-x86-implement-user_single_step_siginfo.patch ptrace-x86-change-syscall_trace_leave-to-rely-on-tracehook-when-stepping.patch I applied them to my tree, otherwise ptrace.c can't be compiled. Oleg. From oleg at redhat.com Sun Nov 15 23:45:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 00:45:30 +0100 Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL Message-ID: <20091115234530.GA6627@redhat.com> I forgot about "make xcheck", it crashes the kernel. Fortunately the kernel dumps the stack trace. Trust me, it wasn't easy to notice the missing return ;) I am wondering why the compiler doesn't complain. Roland, this all needs more fixes. Look at the fixed code, utrace = target->utrace; if (!utrace) return ERR; spin_lock(utrace->lock); Now, if we race with another task doing utrace_task_alloc() and see ->utrace != NULL, why should we see the correctly initialized *utrace? utrace_task_alloc() needs wmb(), and the code like above read_barrier_depends(). UPD: tested the kernel with this patch, now late-ptrace-may-attach-check crashes the kernel silently (no output under kvm). Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- UTRACE-PTRACE/kernel/utrace.c~UTRACE_ATTACH_FIX_UTRACE_CK 2009-11-16 00:02:08.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-16 00:06:26.000000000 +0100 @@ -281,7 +281,7 @@ struct utrace_engine *utrace_attach_task if (!(flags & UTRACE_ATTACH_CREATE)) { if (unlikely(!utrace)) - ERR_PTR(-ENOENT); + return ERR_PTR(-ENOENT); spin_lock(&utrace->lock); engine = matching_engine(utrace, flags, ops, data); if (engine) From oleg at redhat.com Mon Nov 16 01:21:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 02:21:46 +0100 Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: <20091115234530.GA6627@redhat.com> References: <20091115234530.GA6627@redhat.com> Message-ID: <20091116012146.GA15672@redhat.com> On 11/16, Oleg Nesterov wrote: > > UPD: tested the kernel with this patch, now late-ptrace-may-attach-check > crashes the kernel silently (no output under kvm). Repeated this test. Got several oopses, bad spinlock magic in utrace->lock. The stack trace varies, often from utrace_get_signal(). Oh, will continue tomorrow. Oleg. From roland at redhat.com Mon Nov 16 09:05:36 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 01:05:36 -0800 (PST) Subject: [PATCH] utrace: finish_report() must never set ->resume = UTRACE_STOP In-Reply-To: Oleg Nesterov's message of Sunday, 15 November 2009 23:11:11 +0100 <20091115221111.GA31834@redhat.com> References: <20091115220422.GA31683@redhat.com> <20091115221111.GA31834@redhat.com> Message-ID: <20091116090536.1BD26DB@magilla.sf.frob.com> > Forgot to mention, your tree lacks these patches we sent upstream: Right. I'll merge these into some requirements branch (or maybe just the existing tracehook branch) and merge that into utrace. Thanks, Roland From roland at redhat.com Mon Nov 16 09:41:58 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 01:41:58 -0800 (PST) Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: Oleg Nesterov's message of Monday, 16 November 2009 00:45:30 +0100 <20091115234530.GA6627@redhat.com> References: <20091115234530.GA6627@redhat.com> Message-ID: <20091116094158.A3BC6E0@magilla.sf.frob.com> > Now, if we race with another task doing utrace_task_alloc() and see > ->utrace != NULL, why should we see the correctly initialized *utrace? > > utrace_task_alloc() needs wmb(), and the code like above read_barrier_depends(). Ok. Please review what I put in (esp. commit c575558) and send patches relative to the latest tree if that's not right. Perhaps it is overkill to do read_barrier_depends() in task_utrace_struct(). But AFAICT if we don't actually need it all those places, that is only because of some less-obvious barrier effect with checks on ->utrace_flags or something. Do you think it's not really needed in all those places we extract the pointer before spin_lock et al? Thanks, Roland From trisha.frauenhofer at gmail.com Mon Nov 16 15:33:17 2009 From: trisha.frauenhofer at gmail.com (Trisha Frauenhofer) Date: Mon, 16 Nov 2009 09:33:17 -0600 Subject: EXTRA INCOME DATA ENTRY JOB WORK AT HOME Message-ID: <20091116-09331766-c28@umcom2b113.DMZ.UMCOM.ORG> Would you like to earn an extra Earn $200 - $500 Every Day? for just 45 minutes work? Data Entry Workers Needed Worldwide! FOR MORE INFO PLEASE GO TO: http://vur.me/JOBS_WORK_AT-_HOME/Global_Data_Entry/ I would personally like to invite you to become part of our team doing work-at-home data entry. We have guided thousands of team members to success using our new type of data-entry job called Global Data Entry. Some members are currently making $300 - $2000 and more per day, we have been dealing with online data entry for over 7 years. Once you become a via member, you will have exclusive access to legitimate data entry opportunities life time. Forms are just 1-3 pages and take only a few minutes to complete You will be in control and they will pay you directly via direct deposit, paypal or check. Earnings are paid every 2 weeks. Once you have signed up with our via team member, we will provide you with complete guidance and tutorials on exactly how to do these different job tasks and to make this work for you, especially the downloadables files of GLOBAL DATA ENTRY to send you in your email account. It is possible to quit your job for the first used 3 days, how much more if you work hardly 8 hours a day. This is what you have been waiting for! don't hesitate to grab this big opportunities, just try it and I can guarantee you 100% you'll enjoy it. Vance Williamson Home-Data Entry Affiliate Marketer vance.williamson42 at yahoo.com FOR MORE INFO PLEASE GO TO: http://vur.me/JOBS_WORK_AT-_HOME/Global_Data_Entry/ God Bless from a very satisfied member one time only registration fee because we only want serious job If we allowed for free we would have "curiosity" applicants filling applications that were not really serious This is a one time adv. email only and you won't received further mailings about this. If you would like to opt-out just send an e-mail with "Opt Out in the subject line to the address http://www.google.com/search?q=send+to+friend+link&ie=utf-8&oe=utf-8&aq=t&rls=org.mozilla:en-US:official&client=firefox-a From oleg at redhat.com Mon Nov 16 16:52:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 17:52:15 +0100 Subject: [HACK] utrace: "fix" utrace_resume()->finish_resume_report() logic Message-ID: <20091116165215.GA15130@redhat.com> In short, it is just wrong to call finish_resume_report() in utrace_resume() without reporting loop, because utrace never clears TIF_NOTIFY_RESUME. It is very possible we enter utrace_resume() with utrace->resume == UTRACE_RESUME, in this case finish_resume_report() does user_disable_single_step(). And if TIF_SINGLESTEP was previously set by utrace_get_signal() which noticed ->resume < UTRACE_RESUME we lost: engine can't re-assert the stepping. IOW. Just one example. The tracee reports the signal and sleeps in utrace_get_signal()->finish_resume_report(). Suppose that the tracee has TIF_NOTIFY_RESUME bit set. A lot of reasons why this can happen. The tracer wakes up the tracee via utrace_control(UTRACE_SINGLESTEP). The tracee resumes, calls utrace_get_signal_again(), notices utrace->resume < UTRACE_RESUME, resets utrace->resume, and does finish_resume_report()->enable_step() correctly. But, since TIF_NOTIFY_RESUME is set, the tracee will call utrace_resume() before return to user-mode, and the next finish_resume_report() from utrace_resume() clears TIF_SINGLESTEP. Of course, this is just the temporary hack, to do the testing right now. I still do not understand the new code in details, need to read it carefully but didn't have the time yet :/ --- kernel/utrace.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- UTRACE-PTRACE/kernel/utrace.c~UTRACE_HACK_RESUME 2009-11-16 17:02:11.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-16 17:28:10.000000000 +0100 @@ -1871,7 +1871,7 @@ void utrace_resume(struct task_struct *t */ report.action = start_report(utrace); - if (report.action == UTRACE_REPORT && + if (1 && //report.action == UTRACE_REPORT && likely(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { /* * Do a simple reporting pass, with no specific From oleg at redhat.com Mon Nov 16 16:52:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 17:52:40 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes Message-ID: <20091116165240.GA15153@redhat.com> This needs more comment, I'll try to add them in a separate patch. With the recent changes in utrace API utrace_control(UTRACE_SINGLESTEP) postpones enable_step() to utrace_resume() stage. The tracee can pass tracehook_report_syscall_exit() without TIF_SINGLESTEP, this breaks the send_sigtrap() logic. Change ptrace_resume_action() to set UTRACE_EVENT(SYSCALL_EXIT) in PTRACE_SINGLESTEP/PTRACE_SINGLEBLOCK case, change report_syscall_exit() to check ctx->resume to detect this case. To synthesize the trap we set ctx->signr = SIGTRAP and provoke UTRACE_SIGNAL_REPORT, like ptrace_resume() does. Roland, we already discussed this a bit and I agree, this is not optimal. We need some changes in utrace, but currently it has a lot of problems and it is not clear yet what utrace should do. Let's fix the code now, once we find a better solution we can revert this change. With this patch "make check" passes all tests again (to clarify, except some tests which upstream doesn't pass too), including this one: #include #include #include #include #include #include #include #include #include #include #include #define WEVENT(s) ((s & 0xFF0000) >> 16) static int verbose; #define d_printf(fmt, ...) do { if (verbose) printf(fmt, ##__VA_ARGS__); } while (0) static struct user_regs_struct regs; static void resume(int pid, int req, int ck_stat) { int stat; assert(0 == ptrace(req, pid, 0, 0)); assert(waitpid(pid, &stat, __WALL) == pid); //d_printf("===> %06X\n %06X\n", ck_stat, stat); assert(stat == ck_stat); assert(0 == ptrace(PTRACE_GETREGS, pid, NULL, ®s)); } int main(int argc, const char *argv[]) { int pid, child, stat; long rip, nxt_rip; if (getpid() == __NR_getppid) { printf("sorry, restart\n"); return 0; } verbose = argc > 1; pid = fork(); if (!pid) { assert(0 == ptrace(PTRACE_TRACEME, 0,0,0)); kill(getpid(), SIGSTOP); // 1: SYSCALL + SYSCALL + STEP getppid(); // 2: SYSCALL + STEP getppid(); // 3: STEP getppid(); // 4: SYSCALL + STEP if (!fork()) exit(73); // STEPs only if (!fork()) exit(73); assert(0); } assert(wait(&stat) == pid); assert(WIFSTOPPED(stat) && WSTOPSIG(stat) == SIGSTOP); assert(0 == ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD | PTRACE_O_TRACEFORK)); //----------------------------------------------------------------------------- d_printf("1: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); rip = regs.rip; d_printf("1: syscall leave\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert((long)regs.orig_rax < 0); assert(regs.rax == getpid()); assert(regs.rip != rip); d_printf("1: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("2: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("2: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == -ENOSYS); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("2: singlestep\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //-------------------------------------------------------------------------------- d_printf("3: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_getppid); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.orig_rax == __NR_getppid); assert(regs.rax == getpid()); assert(regs.rip == rip); d_printf("3: step over syscall\n"); resume(pid, PTRACE_SINGLESTEP, 0x57F); assert(regs.rip != rip); //---------------------------------------------------------------------------------- d_printf("4: syscall enter\n"); resume(pid, PTRACE_SYSCALL, 0x857F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == -ENOSYS); rip = regs.rip; child = waitpid (-1, &stat, WNOHANG); assert(child == 0); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("4: provoke SIGCHLD\n"); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGCHLD << 8)); assert(regs.rip == rip); d_printf("4: SIGTERM + STEP\n"); kill(pid, SIGTERM); resume(pid, PTRACE_SINGLESTEP, 0x7F | (SIGTERM << 8)); assert(regs.rip == rip); d_printf("4: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != rip); nxt_rip = regs.rip; //--------------------------------------------------------------------------- d_printf("5: stop before syscall insn\n"); do { resume(pid, PTRACE_SINGLESTEP, 0x57F); } while (regs.rip != rip - 2); assert(regs.rax == __NR_clone); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F | (PTRACE_EVENT_FORK << 16)); assert(regs.orig_rax == __NR_clone); //assert(regs.rax == -ENOSYS); assert(regs.rip == rip); child = waitpid (-1, &stat, __WALL); assert(child > 0 && child != pid); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.orig_rax == __NR_clone); assert(regs.rax == child); assert(regs.rip == rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip == nxt_rip); kill(child, SIGKILL); assert(child == waitpid (-1, &stat, __WALL)); assert(stat = SIGKILL); d_printf("5: step\n"); resume(pid, PTRACE_CONT, 0x7F | (SIGCHLD << 8)); assert(regs.rip == nxt_rip); d_printf("5: step\n"); resume(pid, PTRACE_SINGLESTEP, 0x057F); assert(regs.rip != nxt_rip); //---------------------------------------------------------------------------- kill(pid, SIGKILL); return 0; } --- kernel/ptrace.c | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) --- UTRACE-PTRACE/kernel/ptrace.c~133_SYSCALL_EXIT_TRAP 2009-11-16 00:04:22.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace.c 2009-11-16 16:59:48.000000000 +0100 @@ -436,8 +436,16 @@ static u32 ptrace_report_syscall_exit(en if (ptrace_event_pending(ctx)) return UTRACE_STOP; - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + if (ctx->resume != UTRACE_RESUME) { + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && + ctx->resume != UTRACE_SINGLESTEP); + ctx->resume = UTRACE_RESUME; + + ctx->signr = SIGTRAP; + return UTRACE_INTERRUPT; + } + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); return UTRACE_STOP; } @@ -879,6 +887,7 @@ static int ptrace_resume_action(struct t if (unlikely(!arch_has_block_step())) return -EIO; action = UTRACE_BLOCKSTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); break; #endif @@ -887,6 +896,7 @@ static int ptrace_resume_action(struct t if (unlikely(!arch_has_single_step())) return -EIO; action = UTRACE_SINGLESTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); break; #endif From oleg at redhat.com Mon Nov 16 16:56:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 17:56:37 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091116165240.GA15153@redhat.com> References: <20091116165240.GA15153@redhat.com> Message-ID: <20091116165637.GA15173@redhat.com> Just in case, forgot to clarify... On 11/16, Oleg Nesterov wrote: > > With this patch "make check" passes all tests again (to clarify, except > some tests which upstream doesn't pass too), including this one: with this patch + "[HACK] utrace: "fix" utrace_resume()->finish_resume_report() logic" And I didn't check "make xcheck", I guess it still crashes the kernel. Oleg. From oleg at redhat.com Mon Nov 16 17:28:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 18:28:13 +0100 Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: <20091116094158.A3BC6E0@magilla.sf.frob.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> Message-ID: <20091116172813.GA16078@redhat.com> On 11/16, Roland McGrath wrote: > > > Now, if we race with another task doing utrace_task_alloc() and see > > ->utrace != NULL, why should we see the correctly initialized *utrace? > > > > utrace_task_alloc() needs wmb(), and the code like above read_barrier_depends(). > > Ok. Please review what I put in (esp. commit c575558) Yes, I think this is correct. Just in case fyi, I cooked the almost identical patch yesterday, but it didn't help: make xcheck crashes. Not that I really expected it can help on x86. > Perhaps it is overkill to > do read_barrier_depends() in task_utrace_struct(). Yes, perhaps. But this is safer. > Do you think it's not really needed in all those places we extract the > pointer before spin_lock et al? Not sure I understand exactly... Yes, sometimes we know we don't need read_barrier_depends(). For example, @@ -302,7 +309,7 @@ struct utrace_engine *utrace_attach_task( if (!utrace) { if (unlikely(!utrace_task_alloc(target))) return ERR_PTR(-ENOMEM); - utrace = target->utrace; + utrace = task_utrace_struct(target); } I think this change is not necessary (but imho good anyway), this path must take task_lock() and thus it must always see the correct *utrace. But read_barrier_depends() does nothig except on alpha, why should we care? This reminds me, utrace_interrupt_pending() and similar code needs rmb() or task->utrace != NULL check. Oleg. From roland at redhat.com Mon Nov 16 20:39:59 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 12:39:59 -0800 (PST) Subject: [HACK] utrace: "fix" utrace_resume()->finish_resume_report() logic In-Reply-To: Oleg Nesterov's message of Monday, 16 November 2009 17:52:15 +0100 <20091116165215.GA15130@redhat.com> References: <20091116165215.GA15130@redhat.com> Message-ID: <20091116203959.255211A2@magilla.sf.frob.com> > In short, it is just wrong to call finish_resume_report() in utrace_resume() > without reporting loop, because utrace never clears TIF_NOTIFY_RESUME. It's not supposed to. The arch code clears TIF_NOTIFY_RESUME before calling tracehook_notify_resume(). This implies that utrace must keep its own independent bookkeeping sufficient to know what to do when there is a spurious call to utrace_resume(). > It is > very possible we enter utrace_resume() with utrace->resume == UTRACE_RESUME, Let's figure out exactly when this can happen. Perhaps we need more state bits in some form. But perhaps it's just the case that we don't really need to do anything at all for UTRACE_RESUME, i.e. we should just never call finish_resume_report() in that case. You cited the one most obvious case: utrace_get_signal() has just run, so finish_resume_report() has just run and everything is already as we want. What else? * TIF_NOTIFY_RESUME spuriously set for some unrelated reason (arch purposes) -> want to do nothing * utrace_signal_handler set it -> want to do nothing more after clearing utrace->signal_handler * TIF_NOTIFY_RESUME just set by utrace_control() -> it also set utrace->resume != UTRACE_RESUME, so not this case It feels like there should be more corners, but they are not coming to mind immediately. For just those cases, I think the change below would do it. What do you think? Thanks, Roland diff --git a/kernel/utrace.c b/kernel/utrace.c index 34c990a..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1866,8 +1866,18 @@ void utrace_resume(struct task_struct *t */ report.action = start_report(utrace); - if (report.action == UTRACE_REPORT && - likely(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + switch (report.action) { + case UTRACE_RESUME: + /* + * Anything we might have done was already handled by + * utrace_get_signal(), or this is an entirely spurious + * call. (The arch might use TIF_NOTIFY_RESUME for other + * purposes as well as calling us.) + */ + return; + case UTRACE_REPORT: + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) + break; /* * Do a simple reporting pass, with no specific * callback after report_quiesce. @@ -1875,13 +1885,15 @@ void utrace_resume(struct task_struct *t report.action = UTRACE_RESUME; list_for_each_entry(engine, &utrace->attached, entry) start_callback(utrace, &report, engine, task, 0); - } else { + break; + default: /* * Even if this report was truly spurious, there is no need * for utrace_reset() now. TIF_NOTIFY_RESUME was already * cleared--it doesn't stay spuriously set. */ report.spurious = false; + break; } /* From roland at redhat.com Mon Nov 16 21:46:26 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 13:46:26 -0800 (PST) Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: Oleg Nesterov's message of Monday, 16 November 2009 18:28:13 +0100 <20091116172813.GA16078@redhat.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> <20091116172813.GA16078@redhat.com> Message-ID: <20091116214626.F33872F@magilla.sf.frob.com> > Just in case fyi, I cooked the almost identical patch yesterday, but > it didn't help: make xcheck crashes. Not that I really expected it can > help on x86. Right. > Not sure I understand exactly... Yes, sometimes we know we don't need > read_barrier_depends(). For example, > > @@ -302,7 +309,7 @@ struct utrace_engine *utrace_attach_task( > if (!utrace) { > if (unlikely(!utrace_task_alloc(target))) > return ERR_PTR(-ENOMEM); > - utrace = target->utrace; > + utrace = task_utrace_struct(target); > } > > I think this change is not necessary (but imho good anyway), this path > must take task_lock() and thus it must always see the correct *utrace. Ok. If we were to change it we should add a comment about that. > But read_barrier_depends() does nothig except on alpha, why should we > care? I thought this was the barrier you were talking about. Anyway, we should be pedantically correct about these. (People do even still build Linux/Alpha.) > This reminds me, utrace_interrupt_pending() and similar code needs rmb() > or task->utrace != NULL check. I take it you mean that: if (task->utrace_flags) ... use task->utrace ... paths need a barrier to ensure task->utrace_flags read nonzero implies task->utrace will be read non-null when racing with the first attach. Right? This only needs smp_rmb(), right? Is there an existing explicit barrier this pairs with? The corresponding smp_wmb() needs to be somewhere between utrace_task_alloc()'s "task->utrace = utrace;" and utrace_add_engine(): if (!target->utrace_flags) { target->utrace_flags = UTRACE_EVENT(REAP); Right? A lot goes on in between there that probably has some implied barriers (task_unlock, kmem_cache_alloc, spin_lock). But do we really have the exact barrier we need? Or maybe we need: /* * This barrier makes sure the initialization of the struct * precedes the installation of the pointer. This pairs * with read_barrier_depends() in task_utrace_struct(). */ wmb(); task->utrace = utrace; /* * This barrier pairs with task_utrace_struct()'s smp_rmb(). * It ensures this task->utrace store is always seen before * task->utrace_flags is first set in utrace_add_engine(). */ smp_wmb(); This is basically all the tracehook.h paths calling into utrace. I think the easiest thing to do is to assume that use pattern and also roll this barrier into task_utrace_struct(). diff --git a/include/linux/utrace.h b/include/linux/utrace.h index 8924783..0000000 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -157,7 +157,18 @@ static inline unsigned long task_utrace_ static inline struct utrace *task_utrace_struct(struct task_struct *task) { - struct utrace *utrace = task->utrace; + struct utrace *utrace; + + /* + * This barrier ensures that any prior load of task->utrace_flags + * is ordered before this load of task->utrace. We use those + * utrace_flags checks in the hot path to decide to call into + * the utrace code. The first attach installs task->utrace before + * setting task->utrace_flags nonzero, with a barrier between. + */ + smp_rmb(); + utrace = task->utrace; + read_barrier_depends(); /* See utrace_task_alloc(). */ return utrace; } Is that what you have in mind? Thanks, Roland From oleg at redhat.com Mon Nov 16 22:55:55 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 16 Nov 2009 23:55:55 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091116165637.GA15173@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> Message-ID: <20091116225555.GA11810@redhat.com> On 11/16, Oleg Nesterov wrote: > > And I didn't check "make xcheck", I guess it still crashes the kernel. Yes it does. I am almost sure the bug should be trivial, but somehow can't find find it. Just fyi, to ensure this is connected to utrace-indirect I applied the hack below and the bug goes away. OK. Tomorrow I will just read utrace.c trying to understand the details of the new code, perhaps I will notice something. Oleg. --- UTRACE-PTRACE/kernel/fork.c~XXX_CRASH 2009-11-16 20:26:23.000000000 +0100 +++ UTRACE-PTRACE/kernel/fork.c 2009-11-16 21:18:57.000000000 +0100 @@ -970,6 +970,8 @@ static void posix_cpu_timers_init(struct * parts of the process environment (as per the clone * flags). The actual kick-off is left to the caller. */ +bool utrace_task_alloc(struct task_struct *task); + static struct task_struct *copy_process(unsigned long clone_flags, unsigned long stack_start, struct pt_regs *regs, @@ -1227,6 +1229,10 @@ static struct task_struct *copy_process( cgroup_fork_callbacks(p); cgroup_callbacks_done = 1; + p->utrace = NULL; + if (!utrace_task_alloc(p)) + WARN_ON(1); + /* Need tasklist lock for parent etc handling! */ write_lock_irq(&tasklist_lock); --- UTRACE-PTRACE/kernel/utrace.c~XXX_CRASH 2009-11-16 20:31:38.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-16 21:19:26.000000000 +0100 @@ -87,9 +87,9 @@ module_init(utrace_init); * * This returns false only in case of a memory allocation failure. */ -static bool utrace_task_alloc(struct task_struct *task) +bool utrace_task_alloc(struct task_struct *task) { - struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); + struct utrace *utrace = kzalloc(sizeof(struct utrace), GFP_KERNEL); if (unlikely(!utrace)) return false; spin_lock_init(&utrace->lock); @@ -108,7 +108,7 @@ static bool utrace_task_alloc(struct tas } task_unlock(task); if (unlikely(task->utrace != utrace)) - kmem_cache_free(utrace_cachep, utrace); + kfree(utrace); return true; } @@ -118,7 +118,7 @@ static bool utrace_task_alloc(struct tas */ void utrace_free_task(struct task_struct *task) { - kmem_cache_free(utrace_cachep, task->utrace); + kfree(task->utrace); } /* @@ -286,6 +286,8 @@ struct utrace_engine *utrace_attach_task struct utrace_engine *engine; int ret; + WARN_ON(!utrace); + if (!(flags & UTRACE_ATTACH_CREATE)) { if (unlikely(!utrace)) return ERR_PTR(-ENOENT); --- UTRACE-PTRACE/include/linux/utrace.h~XXX_CRASH 2009-11-16 01:06:34.000000000 +0100 +++ UTRACE-PTRACE/include/linux/utrace.h 2009-11-16 20:50:38.000000000 +0100 @@ -163,7 +163,7 @@ static inline struct utrace *task_utrace static inline void utrace_init_task(struct task_struct *task) { task->utrace_flags = 0; - task->utrace = NULL; + WARN_ON(!task->utrace); } void utrace_release_task(struct task_struct *); From roland at redhat.com Mon Nov 16 23:13:27 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 15:13:27 -0800 (PST) Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: Oleg Nesterov's message of Monday, 16 November 2009 17:52:40 +0100 <20091116165240.GA15153@redhat.com> References: <20091116165240.GA15153@redhat.com> Message-ID: <20091116231327.9F9801A2@magilla.sf.frob.com> Whatever temporary hacks are fine by me one way or the other. They will just be coming out later along with assorted other cleanup. We certainly do want to get this right in the utrace layer. The change we talked about before seems simple enough and should cover this without new kludges in the ptrace layer. I did this (commit f19442c). I think that should cover what you need without this ptrace change. (All untested, of course!) Thanks, Roland From roland at redhat.com Mon Nov 16 23:19:06 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 15:19:06 -0800 (PST) Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: Oleg Nesterov's message of Monday, 16 November 2009 23:55:55 +0100 <20091116225555.GA11810@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> Message-ID: <20091116231906.50A712F@magilla.sf.frob.com> > Yes it does. I am almost sure the bug should be trivial, but > somehow can't find find it. Just fyi, to ensure this is connected > to utrace-indirect I applied the hack below and the bug goes away. Does s/kmem_cache_zalloc/kzalloc/ really have anything to do with it? Isn't it just the allocation synchronization logic? > OK. Tomorrow I will just read utrace.c trying to understand the > details of the new code, perhaps I will notice something. Ok. I hope you'll find something not too strange. But if it takes long, then probably we should just change utrace_init_task() to eagerly call utrace_task_alloc() and let you work through other issues first. Thanks, Roland From oleg at redhat.com Mon Nov 16 23:21:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 00:21:49 +0100 Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: <20091116214626.F33872F@magilla.sf.frob.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> <20091116172813.GA16078@redhat.com> <20091116214626.F33872F@magilla.sf.frob.com> Message-ID: <20091116232149.GA12083@redhat.com> On 11/16, Roland McGrath wrote: > > > But read_barrier_depends() does nothig except on alpha, why should we > > care? > > I thought this was the barrier you were talking about. Anyway, we should > be pedantically correct about these. (People do even still build Linux/Alpha.) Yes, sure. I meant, we shouldn't worry that this barrier adds too much overhead to task_utrace_struct(). > > This reminds me, utrace_interrupt_pending() and similar code needs rmb() > > or task->utrace != NULL check. > > I take it you mean that: > > if (task->utrace_flags) > ... use task->utrace ... > > paths need a barrier to ensure task->utrace_flags read nonzero implies > task->utrace will be read non-null when racing with the first attach. > Right? Yes, > This only needs smp_rmb(), right? I think yes. > Is there an existing explicit barrier > this pairs with? The corresponding smp_wmb() needs to be somewhere between > utrace_task_alloc()'s "task->utrace = utrace;" and utrace_add_engine(): > > if (!target->utrace_flags) { > target->utrace_flags = UTRACE_EVENT(REAP); We don't have the explicit barrier, but I think it is not needed. In this case utrace_attach_task() does unlock+lock at least once before changing ->utrace_flags, this implies mb(). > static inline struct utrace *task_utrace_struct(struct task_struct *task) > { > - struct utrace *utrace = task->utrace; > + struct utrace *utrace; > + > + /* > + * This barrier ensures that any prior load of task->utrace_flags > + * is ordered before this load of task->utrace. We use those > + * utrace_flags checks in the hot path to decide to call into > + * the utrace code. The first attach installs task->utrace before > + * setting task->utrace_flags nonzero, with a barrier between. > + */ > + smp_rmb(); > + utrace = task->utrace; > + > read_barrier_depends(); /* See utrace_task_alloc(). */ > return utrace; > } Yes, I think this patch should close this (pure theoretical) problem. But this smp_rmb() in task_utrace_struct() is only needed when the caller does something like if (task_utrace_flags(tsk)) do_something(task_utrace_struct()); it would be more logical to move this rmb() info task_utrace_flags(). However task_utrace_flags() must be fast. Perhaps, to avoid this smp_rmb(), we can change bool utrace_interrupt_pending(void) { struct utrace *utrace = task_utrace_struct(current); return utrace && utrace->resume == UTRACE_INTERRUPT; } I dunno. Oleg. From oleg at redhat.com Mon Nov 16 23:28:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 00:28:28 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091116231906.50A712F@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> <20091116231906.50A712F@magilla.sf.frob.com> Message-ID: <20091116232828.GA13291@redhat.com> On 11/16, Roland McGrath wrote: > > > Yes it does. I am almost sure the bug should be trivial, but > > somehow can't find find it. Just fyi, to ensure this is connected > > to utrace-indirect I applied the hack below and the bug goes away. > > Does s/kmem_cache_zalloc/kzalloc/ really have anything to do with it? No, I think it doesn't. I did this s/kmem_cache_zalloc/kzalloc/ change because I am not sure copy_process() during the boot stage can safely use utrace_cachep which is initialized by module_init(). Oleg. From roland at redhat.com Tue Nov 17 04:20:53 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 16 Nov 2009 20:20:53 -0800 (PST) Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: Oleg Nesterov's message of Tuesday, 17 November 2009 00:21:49 +0100 <20091116232149.GA12083@redhat.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> <20091116172813.GA16078@redhat.com> <20091116214626.F33872F@magilla.sf.frob.com> <20091116232149.GA12083@redhat.com> Message-ID: <20091117042053.08A401A2@magilla.sf.frob.com> > Yes, sure. I meant, we shouldn't worry that this barrier adds too much > overhead to task_utrace_struct(). Ah! Sorry, I misread you. Yes, good point. > We don't have the explicit barrier, but I think it is not needed. > In this case utrace_attach_task() does unlock+lock at least once > before changing ->utrace_flags, this implies mb(). Ok, this is exactly the sort of thing that merits explicit comments. > Yes, I think this patch should close this (pure theoretical) problem. > > But this smp_rmb() in task_utrace_struct() is only needed when the > caller does something like > > if (task_utrace_flags(tsk)) > do_something(task_utrace_struct()); If you look at where task_utrace_struct() is used, it's basically always like this. All the tracehook.h callers into utrace.c do that. > it would be more logical to move this rmb() info task_utrace_flags(). > However task_utrace_flags() must be fast. Right. The hot path is that you test task->utrace_flags and it's zero. It seems better not to add anything else to that path, not even lfence. > Perhaps, to avoid this smp_rmb(), we can change > > bool utrace_interrupt_pending(void) > { > struct utrace *utrace = task_utrace_struct(current); > return utrace && utrace->resume == UTRACE_INTERRUPT; > } > > I dunno. But that's not the only place, is it? Every utrace_report_* and most every other utrace.c entry point is called from tracehook.h code using this pattern. Those can have the same issue. So you'd have to make all of those do an: if (unlikely(!utrace)) return; sort of check. Is that what you mean? I guess we'd need some chip-knowledgeable microoptimizers to tell us whether: smp_rmb(); /* guarantees we can't be here seeing utrace==NULL */ utrace = task->utrace; is better or worse than: utrace = task->utrace; if (unlikely(!utrace)) return; on today's chips. The latter is more hairy for the utrace.c code to always be sure to check. But it's not prohibitively so. Thanks, Roland From info at campaigns.canal-marketing.com Tue Nov 17 12:00:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Bouygues_Telecom?=) Date: Tue, 17 Nov 2009 13:00:00 +0100 Subject: Iphone 3GS + Forfait NEO ILLIMITE Message-ID: An HTML attachment was scrubbed... URL: From devillem.m at gmail.com Tue Nov 17 16:24:37 2009 From: devillem.m at gmail.com (Deville, Melanie) Date: Tue, 17 Nov 2009 11:24:37 -0500 Subject: web-site presence Message-ID: <61571267.20091117112437@gmail.com> Dear Utrace-devel With your permission, we would like to show you how to get better positioning and more traffic on the web. If you are interested, reply us and we'll do a complementary no charge site assessment. Sincerely, Melanie Deville Spark Media utrace-devel at redhat.com 17/11/2009 From oleg at redhat.com Tue Nov 17 19:53:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 20:53:51 +0100 Subject: copy_process && utrace_init_task (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: <20091116225555.GA11810@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> Message-ID: <20091117195351.GA7687@redhat.com> On 11/16, Oleg Nesterov wrote: > > On 11/16, Oleg Nesterov wrote: > > > > And I didn't check "make xcheck", I guess it still crashes the kernel. > > Yes it does. I am almost sure the bug should be trivial, but > somehow can't find find it. Found the trivial but nasty problem. tracehook_finish_clone()->utrace_init_task() sets ->utrace = NULL, but this is too late. If copy_process() fails before, tracehook_free_task() will free parent's ->utrace copied by dup_task_struct(). This is nasty because we need some changes outside of utrace/tracehook files. Perhaps we should send something like the patch below to Andrew right now? And! While this bug could perfectly explain the crash, it doesn't. I appiled this patch --- UTRACE-PTRACE/kernel/fork.c~XXX_CRASH 2009-11-16 20:26:23.000000000 +0100 +++ UTRACE-PTRACE/kernel/fork.c 2009-11-17 20:33:50.000000000 +0100 @@ -1019,6 +1019,7 @@ static struct task_struct *copy_process( if (!p) goto fork_out; +p->utrace = NULL; ftrace_graph_init_task(p); rt_mutex_init_task(p); but "make xcheck" still crashes. Still investigating. Oleg. --- TH/include/linux/ptrace.h~TH_INIT_TASK 2009-11-10 21:31:25.000000000 +0100 +++ TH/include/linux/ptrace.h 2009-11-17 20:43:42.000000000 +0100 @@ -148,6 +148,14 @@ static inline int ptrace_event(int mask, return 1; } +static inline void ptrace_init_task(struct task_struct *child) +{ + INIT_LIST_HEAD(&child->ptrace_entry); + INIT_LIST_HEAD(&child->ptraced); + child->parent = child->real_parent; + child->ptrace = 0; +} + /** * ptrace_init_task - initialize ptrace state for a new child * @child: new child task @@ -158,12 +166,8 @@ static inline int ptrace_event(int mask, * * Called with current's siglock and write_lock_irq(&tasklist_lock) held. */ -static inline void ptrace_init_task(struct task_struct *child, bool ptrace) +static inline void ptrace_finish_clone(struct task_struct *child, bool ptrace) { - INIT_LIST_HEAD(&child->ptrace_entry); - INIT_LIST_HEAD(&child->ptraced); - child->parent = child->real_parent; - child->ptrace = 0; if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { child->ptrace = current->ptrace; __ptrace_link(child, current->parent); --- TH/include/linux/tracehook.h~TH_INIT_TASK 2009-11-11 21:49:42.000000000 +0100 +++ TH/include/linux/tracehook.h 2009-11-17 20:42:43.000000000 +0100 @@ -247,6 +247,11 @@ static inline int tracehook_prepare_clon return 0; } +static inline void tracehook_init_task(struct task_struct *child) +{ + ptrace_init_task(child); +} + /** * tracehook_finish_clone - new child created and being attached * @child: new child task @@ -261,7 +266,7 @@ static inline int tracehook_prepare_clon static inline void tracehook_finish_clone(struct task_struct *child, unsigned long clone_flags, int trace) { - ptrace_init_task(child, (clone_flags & CLONE_PTRACE) || trace); + ptrace_finish_clone(child, (clone_flags & CLONE_PTRACE) || trace); } /** --- TH/kernel/fork.c~TH_INIT_TASK 2009-11-07 22:15:15.000000000 +0100 +++ TH/kernel/fork.c 2009-11-17 20:40:52.000000000 +0100 @@ -1018,8 +1018,8 @@ static struct task_struct *copy_process( if (!p) goto fork_out; + tracehook_init_task(p); ftrace_graph_init_task(p); - rt_mutex_init_task(p); #ifdef CONFIG_PROVE_LOCKING From oleg at redhat.com Tue Nov 17 19:56:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 20:56:41 +0100 Subject: copy_process && utrace_init_task (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: <20091117195351.GA7687@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> <20091117195351.GA7687@redhat.com> Message-ID: <20091117195641.GB7687@redhat.com> On 11/17, Oleg Nesterov wrote: > > This is nasty because we need some changes outside of utrace/tracehook > files. Perhaps we should send something like the patch below to Andrew > right now? > > ... > > +static inline void ptrace_init_task(struct task_struct *child) > +{ > + INIT_LIST_HEAD(&child->ptrace_entry); > + INIT_LIST_HEAD(&child->ptraced); > + child->parent = child->real_parent; ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ this line belongs to ptrace_finish_clone(), of course. Oleg. From oleg at redhat.com Tue Nov 17 21:02:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 22:02:27 +0100 Subject: kernel crash: solved (Was: copy_process && utrace_init_task) In-Reply-To: <20091117195351.GA7687@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> <20091117195351.GA7687@redhat.com> Message-ID: <20091117210227.GA14237@redhat.com> On 11/17, Oleg Nesterov wrote: > > On 11/16, Oleg Nesterov wrote: > > > > On 11/16, Oleg Nesterov wrote: > > > > > > And I didn't check "make xcheck", I guess it still crashes the kernel. > > > > Yes it does. I am almost sure the bug should be trivial, but > > somehow can't find find it. > > Found the trivial but nasty problem. > > And! While this bug could perfectly explain the crash, it doesn't. > I appiled this patch > > --- UTRACE-PTRACE/kernel/fork.c~XXX_CRASH 2009-11-16 20:26:23.000000000 +0100 > +++ UTRACE-PTRACE/kernel/fork.c 2009-11-17 20:33:50.000000000 +0100 > @@ -1019,6 +1019,7 @@ static struct task_struct *copy_process( > if (!p) > goto fork_out; > > +p->utrace = NULL; > ftrace_graph_init_task(p); > > rt_mutex_init_task(p); > > but "make xcheck" still crashes. Still investigating. Damn!!! It works, the kernel does NOT crash. (by mistake, I copied bzImage to the wrong location, iow I tested the kernel without the patch above). Oleg. From oleg at redhat.com Tue Nov 17 22:07:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 23:07:57 +0100 Subject: tracehook_report_syscall_exit() && PT_PTRACED (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: <20091116231327.9F9801A2@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> Message-ID: <20091117220757.GA15906@redhat.com> On 11/16, Roland McGrath wrote: > > The change we talked about before seems simple enough and should cover this > without new kludges in the ptrace layer. I did this (commit f19442c). I will reply to this in the next email, I'd like to discuss another minor related issue first. I noticed this change in your tree commit 2583b3267ed599cb25f6f893c24465204e06b3a6 utrace: nit for utrace-ptrace --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -143,7 +143,7 @@ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(regs); - if (step && task_ptrace(current)) { + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); Yes, and in fact I already had this change in my tree but didn't send it to you yet. But, I can't understand whats going on, - if (step && task_ptrace(current)) { + if (step && (task_ptrace(current) & PT_PTRACED)) { The code after ptrace-change-tracehook_report_syscall_exit-to-handle-stepping.patch is "if (step)", not "if (step && task_ptrace(current))", can't understand where did this "&& task_ptrace(current)" come from. The previous commit in your tree is 462a57bb7a6a5c67b70e4388f97239f1e4da98df ptrace: change tracehook_report_syscall_exit() to handle stepping Initially I was going to add the change below into "tracehooks: prepare for utrace-ptrace", --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -134,6 +134,9 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (!(task_ptrace(current) & PT_PTRACED)) + return; + if (step) { siginfo_t info; user_single_step_siginfo(current, regs, &info); but now I think perhaps it would be better to send ptrace-change-tracehook_report_syscall_exit-to-handle-stepping_fix to akpm right now: --- a/include/linux/tracehook.h +++ b/include/linux/tracehook.h @@ -134,7 +134,7 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { - if (step) { + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); What do you think? Now, let's return to the original topic. Please note that utrace does not need "int step" at all, see the next email. Oleg. From oleg at redhat.com Tue Nov 17 22:09:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 23:09:00 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091116231327.9F9801A2@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> Message-ID: <20091117220900.GB15906@redhat.com> On 11/16, Roland McGrath wrote: > > Whatever temporary hacks are fine by me one way or the other. > They will just be coming out later along with assorted other cleanup. > We certainly do want to get this right in the utrace layer. Yes. But imho it is always good to test/review the patches against the working kernel. The patch I sent is very simple, and can be easily reverted once we improve utrace. IOW, I am asking you to apply my patch for now and revert your change to have the working tree, then discuss the "right" fix. > The change we talked about before seems simple enough and should cover this > without new kludges in the ptrace layer. I did this (commit f19442c). I don't think this can work. tracehook_report_syscall_exit(step) if (step || UTRACE_EVENT(SYSCALL_EXIT)) utrace_report_syscall_exit(step); and, utrace_report_syscall_exit(step) if (step) send_sigtrap(); The problems is: we can trust "bool step", and in fact we do not need it at all. Once again. The tracee sleeps in SYSCALL_ENTER. The tracer resumes the tracee via utrace_control(UTRACE_SINGLESTEP). By the time the resumed tracee passes tracehook_report_syscall_exit() step == F, utrace_control() does not set TIF_SINGLESTEP. So, I think we should do something like tracehook_report_syscall_exit(step) // do not use step at all if (task_utrace_flags() != 0) utrace_report_syscall_exit(); // this code below is only for old ptrace if (step && (task_ptrace(current) & PT_PTRACED)) send_sigtrap(); ptrace_report_syscall(); and, utrace_report_syscall_exit() if (UTRACE_EVENT(SYSCALL_EXIT)) REPORT(report_syscall_exit); if (utrace->resume == UTRACE_SINGLESTEP || utrace->resume == UTRACE_BLOCKSTEP) send_sigtrap(); What do you think? Oleg. From oleg at redhat.com Tue Nov 17 22:58:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 17 Nov 2009 23:58:56 +0100 Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: <20091117042053.08A401A2@magilla.sf.frob.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> <20091116172813.GA16078@redhat.com> <20091116214626.F33872F@magilla.sf.frob.com> <20091116232149.GA12083@redhat.com> <20091117042053.08A401A2@magilla.sf.frob.com> Message-ID: <20091117225856.GA18836@redhat.com> On 11/16, Roland McGrath wrote: > > > But this smp_rmb() in task_utrace_struct() is only needed when the > > caller does something like > > > > if (task_utrace_flags(tsk)) > > do_something(task_utrace_struct()); > > If you look at where task_utrace_struct() is used, it's basically always > like this. All the tracehook.h callers into utrace.c do that. > > ... > > But that's not the only place, is it? Every utrace_report_* and most every > other utrace.c entry point is called from tracehook.h code using this pattern. > Those can have the same issue. So you'd have to make all of those do an: > if (unlikely(!utrace)) > return; > sort of check. Is that what you mean? Yes, agreed, this doesn't look good. So, I think it is better to add the barriers into task_utrace_struct() like you already did. (a very minor nit: s/read_barrier_depends/smp_read_barrier_depends/) Just to complete the discussion, we could do static inline unsigned long task_utrace_flags(struct task_struct *task) { if (!task->utrace) return 0; return task->utrace_flags; } to void rmb() without complicationg the code, but this still adds some overhead to the hot path. And a bit offtopic question. Apart from "task_utrace_flags() should be as fast as possible", any other reason we can't move ->utrace_flags into "struct utrace" ? In the "likely" case we should worry about (the task was never traced), ->utrace == NULL and task_utrace_flags(struct task_struct *task) { if (likley(!task->utrace)) return 0; return task->utrace->flags; } shouldn't be slower. If the task was ever traced and then utraced this adds the extra dereference, yes. Oleg. From roland at redhat.com Wed Nov 18 05:36:50 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 17 Nov 2009 21:36:50 -0800 (PST) Subject: tracehook_report_syscall_exit() && PT_PTRACED (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: Oleg Nesterov's message of Tuesday, 17 November 2009 23:07:57 +0100 <20091117220757.GA15906@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220757.GA15906@redhat.com> Message-ID: <20091118053650.82180A15@magilla.sf.frob.com> > but now I think perhaps it would be better to send > ptrace-change-tracehook_report_syscall_exit-to-handle-stepping_fix > to akpm right now: > > --- a/include/linux/tracehook.h > +++ b/include/linux/tracehook.h > @@ -134,7 +134,7 @@ static inline __must_check int tracehook > */ > static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) > { > - if (step) { > + if (step && (task_ptrace(current) & PT_PTRACED)) { > siginfo_t info; > user_single_step_siginfo(current, regs, &info); > force_sig_info(SIGTRAP, &info, current); > > What do you think? Yes, this makes it consistent with the x86 behavior before the change, which used tracehook_consider_fatal_signal(current, SIGTRAP) in its test. Thanks, Roland From roland at redhat.com Wed Nov 18 10:22:56 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 02:22:56 -0800 (PST) Subject: copy_process && utrace_init_task (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: Oleg Nesterov's message of Tuesday, 17 November 2009 20:53:51 +0100 <20091117195351.GA7687@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> <20091117195351.GA7687@redhat.com> Message-ID: <20091118102256.1538A120F@magilla.sf.frob.com> > Found the trivial but nasty problem. Ah! Good catch. I added tracehook_init_task() in my tree. I don't see much benefit in sending any tracehook patch upstream for this. tracehook_init_task() corresponds to tracehook_free_task(), which is only added by utrace (and both would just be empty in a separate preparatory patch). I don't see any reason to fiddle the ptrace_init_task() call. The setup it does is all stuff that only matters for teardown done by release_task() or even earlier in the exit sequence. So it makes enough sense that the setup side should happen later as it does now. In the long run, the ptrace init stuff will all just go away. Before then I can't see any rationale for touching it. Thanks, Roland From roland at redhat.com Wed Nov 18 10:34:45 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 02:34:45 -0800 (PST) Subject: [PATCH] utrace: utrace_attach_task() forgets to return when ->utrace == NULL In-Reply-To: Oleg Nesterov's message of Tuesday, 17 November 2009 23:58:56 +0100 <20091117225856.GA18836@redhat.com> References: <20091115234530.GA6627@redhat.com> <20091116094158.A3BC6E0@magilla.sf.frob.com> <20091116172813.GA16078@redhat.com> <20091116214626.F33872F@magilla.sf.frob.com> <20091116232149.GA12083@redhat.com> <20091117042053.08A401A2@magilla.sf.frob.com> <20091117225856.GA18836@redhat.com> Message-ID: <20091118103445.91E2F120F@magilla.sf.frob.com> > (a very minor nit: s/read_barrier_depends/smp_read_barrier_depends/) commit 23ab966 > Just to complete the discussion, we could do > > static inline unsigned long task_utrace_flags(struct task_struct *task) > { > if (!task->utrace) > return 0; > return task->utrace_flags; > } > > to void rmb() without complicationg the code, but this still adds > some overhead to the hot path. Right. > And a bit offtopic question. Apart from "task_utrace_flags() should > be as fast as possible", any other reason we can't move ->utrace_flags > into "struct utrace" ? No, I think that's the only reason. But this one reason has a nuance that your suggestion overlooks. We've been saying "the hot path" and "the tracing path" as if there were just one bifurcation to consider. But that's not really so. The hot paths are all the places that call tracehook.h functions (roughly speaking). Each of these has its own bifurcation between a hot path and a tracing path. Each of these tests a different utrace_flags bit. So e.g. if utrace_flags has only UTRACE_EVENT(SIGNAL_CORE), then tracehook_report_exit() is still a "hot path" that does not need to go off into utrace code at all. Thanks, Roland From roland at redhat.com Wed Nov 18 11:48:43 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 03:48:43 -0800 (PST) Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: Oleg Nesterov's message of Tuesday, 17 November 2009 23:09:00 +0100 <20091117220900.GB15906@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> Message-ID: <20091118114843.A5DAF29@magilla.sf.frob.com> > IOW, I am asking you to apply my patch for now and revert your > change to have the working tree, then discuss the "right" fix. Ok, done. > Once again. The tracee sleeps in SYSCALL_ENTER. The tracer resumes > the tracee via utrace_control(UTRACE_SINGLESTEP). Right. This is another strange corner. It doesn't necessarily make especially good sense intrinsically for single-step to have this meaning from this place. But it's the status quo in the ptrace interface. In the pure utrace context, stepping and syscall tracing are independent moving parts as they aren't in ptrace. So one could say it makes sense for a single-step that precedes the syscall-entry report to apply to "that instruction", meaning the syscall instruction. This clearly makes sense when it's one engine doing the step and another unrelated one doing the syscall tracing. But then the utrace idiom is that the stepping engine gets report_quiesce(SYSCALL_ENTRY) and returns UTRACE_SINGLESTEP to preserve its "what to do next" choice from before--and this has the right results anyway. > By the time the resumed tracee passes tracehook_report_syscall_exit() > step == F, utrace_control() does not set TIF_SINGLESTEP. In old ptrace, a PTRACE_SINGLESTEP resuming from the syscall-entry stop does do user_enable_single_step() just like any other resume. So today we do get there with that flag set. The utrace equivalent would be finish_resume_report() in utrace_report_syscall_entry(). But that would have no other use except for this quirk (none that I can see). > So, I think we should do something like > > tracehook_report_syscall_exit(step) > > // do not use step at all > if (task_utrace_flags() != 0) > utrace_report_syscall_exit(); The trouble here is that the arch code looks like this: step = test_thread_flag(TIF_SINGLESTEP); if (step || test_thread_flag(TIF_SYSCALL_TRACE)) tracehook_report_syscall_exit(regs, step); i.e. unless syscall tracing is enabled, we won't even get there at all. > utrace_report_syscall_exit() > > if (UTRACE_EVENT(SYSCALL_EXIT)) > REPORT(report_syscall_exit); > > if (utrace->resume == UTRACE_SINGLESTEP || > utrace->resume == UTRACE_BLOCKSTEP) > send_sigtrap(); > > What do you think? This can't work in the REPORT case. There start_report() will have reset utrace->resume, so you are only seeing the value set by report_syscall_exit callbacks just made. That has the behavior of the old x86 code rather than what we want now. You'd have to cache the value before REPORT, e.g. start_report() return value as in utrace_resume(), and use that. But if (as now) we need the step flag to be set in these cases to be sure we got called at all, then might as well just use that. So what about this? (This would go with un-reverting f19442c and reverting 3bd4be9.) Thanks, Roland ===== diff --git a/kernel/utrace.c b/kernel/utrace.c index 5af0f94..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -1584,20 +1584,25 @@ static inline u32 do_report_syscall_entr UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, resume_report | report->result | report->action, engine, current, regs); - finish_report(task, utrace, report, false); + + /* + * Now we'll stop if asked. If we're proceeding with the syscall, + * now we'll first enable single-step if asked. That leaves the + * task in "stepping" state so tracehook_report_syscall_exit() and + * the arch code that calls it will know. + */ + finish_resume_report(task, utrace, report); if (report->action != UTRACE_STOP) return 0; - utrace_stop(task, utrace, report->resume_action); - if (fatal_signal_pending(task)) { /* * We are continuing despite UTRACE_STOP because of a * SIGKILL. Don't let the system call actually proceed. */ report->result = UTRACE_SYSCALL_ABORT; - } else if (utrace->resume == UTRACE_REPORT) { + } else if (utrace->resume <= UTRACE_REPORT) { /* * If we've been asked for another report after our stop, * go back to report (and maybe stop) again before we run From oleg at redhat.com Wed Nov 18 20:25:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Nov 2009 21:25:00 +0100 Subject: copy_process && utrace_init_task (Was: [PATCH 133] stepping, accommodate to utrace-cleanup changes) In-Reply-To: <20091118102256.1538A120F@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116165637.GA15173@redhat.com> <20091116225555.GA11810@redhat.com> <20091117195351.GA7687@redhat.com> <20091118102256.1538A120F@magilla.sf.frob.com> Message-ID: <20091118202500.GA6858@redhat.com> On 11/18, Roland McGrath wrote: > > I added tracehook_init_task() in my tree. I don't see much benefit in > sending any tracehook patch upstream for this. tracehook_init_task() > corresponds to tracehook_free_task(), which is only added by utrace > (and both would just be empty in a separate preparatory patch). > > I don't see any reason to fiddle the ptrace_init_task() call. > ... > In the long run, the ptrace init stuff will all just go away. OK, agreed. Oleg. From oleg at redhat.com Wed Nov 18 21:41:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Nov 2009 22:41:27 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091118114843.A5DAF29@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> <20091118114843.A5DAF29@magilla.sf.frob.com> Message-ID: <20091118214127.GA11214@redhat.com> On 11/18, Roland McGrath wrote: > > > Once again. The tracee sleeps in SYSCALL_ENTER. The tracer resumes > > the tracee via utrace_control(UTRACE_SINGLESTEP). > > Right. This is another strange corner. It doesn't necessarily make > especially good sense intrinsically for single-step to have this meaning > from this place. But it's the status quo in the ptrace interface. Yes. > > So, I think we should do something like > > > > tracehook_report_syscall_exit(step) > > > > // do not use step at all > > if (task_utrace_flags() != 0) > > utrace_report_syscall_exit(); > > The trouble here is that the arch code looks like this: > > step = test_thread_flag(TIF_SINGLESTEP); > if (step || test_thread_flag(TIF_SYSCALL_TRACE)) > tracehook_report_syscall_exit(regs, step); > > i.e. unless syscall tracing is enabled, we won't even get there at all. You are right, I missed this. > > utrace_report_syscall_exit() > > > > if (UTRACE_EVENT(SYSCALL_EXIT)) > > REPORT(report_syscall_exit); > > > > if (utrace->resume == UTRACE_SINGLESTEP || > > utrace->resume == UTRACE_BLOCKSTEP) > > send_sigtrap(); > > > > What do you think? > > This can't work in the REPORT case. There start_report() will have reset > utrace->resume, Yes, yes, the pseudo-code above was just for illustration. > (This would go with un-reverting f19442c and reverting 3bd4be9.) > > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -1584,20 +1584,25 @@ static inline u32 do_report_syscall_entr > UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, > resume_report | report->result | report->action, > engine, current, regs); > - finish_report(task, utrace, report, false); > + > + /* > + * Now we'll stop if asked. If we're proceeding with the syscall, > + * now we'll first enable single-step if asked. That leaves the > + * task in "stepping" state so tracehook_report_syscall_exit() and > + * the arch code that calls it will know. > + */ > + finish_resume_report(task, utrace, report); Hmm. not sure I understand how this can work. I mean, this won't enable stepping (in this particular case we are discussing). > - } else if (utrace->resume == UTRACE_REPORT) { > + } else if (utrace->resume <= UTRACE_REPORT) { perhaps, you meant ">= UTRACE_REPORT" ? In this case yes, UTRACE_SINGLESTEP will be noticed after resume, and ptrace or another engine can reassert it during the next reporting loop, and then finish_resume_report() will enable the stepping. But we can't trust ">=", another engine can do utrace_control(INTERRUPT) and change ->resume before the tracee resumes. OK, probably I missed the implemenation details, but I think I got the idea, and this should fix the step-after-syscall_enter problem. But. We have the same problem with utrace_finish_vfork(), no? Instead of fixing utrace_report_syscall_entry(), perhaps we should change utrace_stop() path to enable the stepping if needed, but this means we return to "synchronous" utrace_control(UTRACE_XXXSTEP). Oleg. From oleg at redhat.com Wed Nov 18 22:22:11 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 18 Nov 2009 23:22:11 +0100 Subject: Q: UTRACE_SYSCALL_RESUMED logic Message-ID: <20091118222211.GA13022@redhat.com> Just can't understand UTRACE_SYSCALL_RESUMED code. To the pointed, I tried to read the docs: * When %UTRACE_STOP is used in @report_syscall_entry, then @task * stops before attempting the system call. In this case, another * @report_syscall_entry callback follows after @task resumes; Probably I misread this comment, or code (or both) but this is not what utrace_report_syscall_entry(). The second reporting loop is done if the tracee stops, and its ->resume = UTRACE_REPORT after wakeup. This can happen if, during the first report, one engine returns UTRACE_STOP and another engine returns UTRACE_REPORT. Or, no matter how many engines we have, the tracer uses UTRACE_REPORT to wakeup the tracee after SYSCALL_ENTRY stop. In any case, what is the rationality? And how can we trust "if (utrace->resume == UTRACE_REPORT)" ? If we have multiple engines, some engine can use UTRACE_INTERRUPT ? Oleg. From oleg at redhat.com Wed Nov 18 23:47:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 00:47:13 +0100 Subject: [HACK] utrace: "fix" utrace_resume()->finish_resume_report() logic In-Reply-To: <20091116203959.255211A2@magilla.sf.frob.com> References: <20091116165215.GA15130@redhat.com> <20091116203959.255211A2@magilla.sf.frob.com> Message-ID: <20091118234713.GA16263@redhat.com> On 11/16, Roland McGrath wrote: > > You cited the one most obvious case: utrace_get_signal() has just run, so > finish_resume_report() has just run and everything is already as we want. > > What else? I think, we can say that finish_resume_report() must be never called without reporting loop if ->resume = UTRACE_RESUME. > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -1866,8 +1866,18 @@ void utrace_resume(struct task_struct *t > */ > report.action = start_report(utrace); > > - if (report.action == UTRACE_REPORT && > - likely(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { > + switch (report.action) { > + case UTRACE_RESUME: > + /* > + * Anything we might have done was already handled by > + * utrace_get_signal(), or this is an entirely spurious > + * call. (The arch might use TIF_NOTIFY_RESUME for other > + * purposes as well as calling us.) > + */ > + return; Yes, I think this change is right. Will test and report later, but it "obviously" should fix the testing. I feel we need some cleanups, but can't suggest anything ;) And can't convince myself I am 100% sure we don't have other similar issues. At least, don't we also need the patch below? Oleg. --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -2002,7 +2002,7 @@ int utrace_get_signal(struct task_struct spin_unlock_irq(&task->sighand->siglock); } - if (resume > UTRACE_REPORT) { + if (resume > UTRACE_REPORT && utrace < UTRACE_RESUME) { /* * We only got here to process utrace->resume. * Despite no callbacks, this report is not spurious. From oleg at redhat.com Wed Nov 18 23:53:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 00:53:00 +0100 Subject: [HACK] utrace: "fix" utrace_resume()->finish_resume_report() logic In-Reply-To: <20091118234713.GA16263@redhat.com> References: <20091116165215.GA15130@redhat.com> <20091116203959.255211A2@magilla.sf.frob.com> <20091118234713.GA16263@redhat.com> Message-ID: <20091118235300.GB16263@redhat.com> On 11/19, Oleg Nesterov wrote: > > At least, don't we also need the patch below? > > --- a/kernel/utrace.c > +++ b/kernel/utrace.c > @@ -2002,7 +2002,7 @@ int utrace_get_signal(struct task_struct > spin_unlock_irq(&task->sighand->siglock); > } > > - if (resume > UTRACE_REPORT) { > + if (resume > UTRACE_REPORT && utrace < UTRACE_RESUME) { > /* > * We only got here to process utrace->resume. > * Despite no callbacks, this report is not spurious. No, this is wrong. Please see below. Oleg. --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -2007,9 +2007,11 @@ int utrace_get_signal(struct task_struct * We only got here to process utrace->resume. * Despite no callbacks, this report is not spurious. */ - report.action = resume; - report.spurious = false; - finish_resume_report(task, utrace, &report); + if (resume != UTRACE_RESUME) { + report.action = resume; + report.spurious = false; + finish_resume_report(task, utrace, &report); + } return -1; } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { /* From roland at redhat.com Thu Nov 19 01:19:39 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 17:19:39 -0800 (PST) Subject: Q: UTRACE_SYSCALL_RESUMED logic In-Reply-To: Oleg Nesterov's message of Wednesday, 18 November 2009 23:22:11 +0100 <20091118222211.GA13022@redhat.com> References: <20091118222211.GA13022@redhat.com> Message-ID: <20091119011939.090171E2C@magilla.sf.frob.com> > Just can't understand UTRACE_SYSCALL_RESUMED code. You understand too well! :-) > To the pointed, I tried to read the docs: > > * When %UTRACE_STOP is used in @report_syscall_entry, then @task > * stops before attempting the system call. In this case, another > * @report_syscall_entry callback follows after @task resumes; > > Probably I misread this comment, or code (or both) but this is not > what utrace_report_syscall_entry(). No, the comment is wrong. I probably wrote it during one iteration of the API idea and then thought of different nits while writing the code. > This can happen if, during the first report, one engine returns > UTRACE_STOP and another engine returns UTRACE_REPORT. > > Or, no matter how many engines we have, the tracer uses UTRACE_REPORT > to wakeup the tracee after SYSCALL_ENTRY stop. Right, that's the intent. > In any case, what is the rationality? The rationale is that if you see utrace_resume_action(action)==UTRACE_STOP in your callback, then you know another engine asked for stop and you can decide to return UTRACE_REPORT if you want to see the UTRACE_SYSCALL_RESUMED notification after the other engine resumes. If you aren't delaying your consideration of the event until the UTRACE_SYSCALL_RESUMED case because you don't care, then you don't return UTRACE_REPORT and are not guaranteed the second report. > And how can we trust "if (utrace->resume == UTRACE_REPORT)" ? > If we have multiple engines, some engine can use UTRACE_INTERRUPT ? That's why it should be <= instead. (I just noticed this while poking at the stop/step issues, but it's not related to that, only to this.) I did this and changed the comment in de5a46ea. Is that clear now? Thanks, Roland From roland at redhat.com Thu Nov 19 02:02:28 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 18:02:28 -0800 (PST) Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: Oleg Nesterov's message of Wednesday, 18 November 2009 22:41:27 +0100 <20091118214127.GA11214@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> <20091118114843.A5DAF29@magilla.sf.frob.com> <20091118214127.GA11214@redhat.com> Message-ID: <20091119020228.AB0831E2C@magilla.sf.frob.com> > Hmm. not sure I understand how this can work. I mean, this won't > enable stepping (in this particular case we are discussing). I might be confused. I'm thinking of two cases: the report_syscall_entry pass yields UTRACE_SINGLESTEP, or that it yields UTRACE_STOP and then utrace_control() sets utrace->resume to UTRACE_SINGLESTEP. The former is e.g. PTRACE_SINGLESTEP while an unrelated engine uses UTRACE_EVENT(SYSCALL_ENTRY). The ptrace engine's report_quiesce returns UTRACE_SINGLESTEP. finish_resume_report() calls user_enable_single_step(). That seems fine. Right? The latter is e.g. PTRACE_SINGLESTEP after ptrace stop at syscall entry. I see. finish_resume_report() will only do utrace_stop() and then we'll go directly into the syscall unless someone used UTRACE_REPORT. utrace_stop() will only set TIF_NOTIFY_RESUME and utrace->resume. In the real resume-to-user cases, that's fine because we'll handle that in utrace_resume() or utrace_get_signal() before doing anything else. I think this maybe wouldn't hurt anything: @@ -1794,11 +1794,13 @@ static void finish_resume_report(struct { finish_report_reset(task, utrace, report); - switch (report->action) { - case UTRACE_STOP: - utrace_stop(task, utrace, report->resume_action); - break; + if (report->action == UTRACE_STOP) { + utrace_stop(task, utrace, report->resume_action, true); + report->action = start_report(utrace); + WARN_ON(report->action == UTRACE_STOP); + } + switch (report->action) { case UTRACE_INTERRUPT: if (!signal_pending(task)) set_tsk_thread_flag(task, TIF_SIGPENDING); (In the omitted part of the patch, the new flag to utrace_stop tells it never to bother with setting TIF_NOTIFY_RESUME for < UTRACE_REPORT.) Then even for the real resume-to-user cases, we skip a cycle out to arch asm and back into utrace_resume() for utrace_control(,,UTRACE_SINGLESTEP) after UTRACE_STOP. (That microoptimization does not really matter, but it falls naturally out of the change.) > > - } else if (utrace->resume == UTRACE_REPORT) { > > + } else if (utrace->resume <= UTRACE_REPORT) { > > perhaps, you meant ">= UTRACE_REPORT" ? No, it's to catch UTRACE_INTERRUPT as requesting a report too, as you noticed in the other email thread should be done. > OK, probably I missed the implemenation details, but I think I got > the idea, and this should fix the step-after-syscall_enter problem. Right. My implementation details are not quite right either. But this seems like the right idea for how to get tracehook_report_syscall_exit called in the cases where it is in old ptrace. > But. We have the same problem with utrace_finish_vfork(), no? Yes. But, hmm. utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ This XXX was there about passing UTRACE_RESUME, because that's not really right. I guess I was actually thinking of this very case, but didn't know at the time quite what the case was. > Instead of fixing utrace_report_syscall_entry(), perhaps we should > change utrace_stop() path to enable the stepping if needed, but this > means we return to "synchronous" utrace_control(UTRACE_XXXSTEP). I don't really follow what you mean by "synchronous". Your suggestion is equivalent to making utrace_finish_vfork call finish_resume_report instead of utrace_stop, isn't it? The callers of utrace_stop() are: * finish_resume_report -> the main guy -> proposed (above) to also handle utrace->resume immediately after stop * utrace_report_exit -> doesn't matter (?), nothing but UTRACE_STOP and possibly TIF_SIGPENDING are meaningful any more * do_report_syscall_entry -> proposed to call finish_resume_report instead * utrace_finish_vfork Ok. So I can see a bit of cleanup to be done in splitting finish_resume_report and utrace_finish_vfork calling the parts of it, as will the "We only got here to process utrace->resume." case. But it will be functionally equivalent to finish_resume_report with {.spurious=false, .action=utrace->resume}. That seems like it would cover it all, no? But I am still hesitant because I don't really understand your "return to synchronous..." comment. Thanks, Roland From oleg at redhat.com Thu Nov 19 02:15:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:15:51 +0100 Subject: [PATCH 0/4] utrace->resume fixes Message-ID: <20091119021551.GA10373@redhat.com> On top of your patch in https://www.redhat.com/archives/utrace-devel/2009-November/msg00109.html I attached this patch below just in case. As expected, it fixes the problem with the lost TIF_SINGLESTEP. Oleg. --- UTRACE-PTRACE/kernel/utrace.c~__ROLAND_RESUME_FIX 2009-11-18 21:16:23.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-19 02:17:26.000000000 +0100 @@ -1882,8 +1882,18 @@ void utrace_resume(struct task_struct *t */ report.action = start_report(utrace); - if (report.action == UTRACE_REPORT && - likely(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + switch (report.action) { + case UTRACE_RESUME: + /* + * Anything we might have done was already handled by + * utrace_get_signal(), or this is an entirely spurious + * call. (The arch might use TIF_NOTIFY_RESUME for other + * purposes as well as calling us.) + */ + return; + case UTRACE_REPORT: + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) + break; /* * Do a simple reporting pass, with no specific * callback after report_quiesce. @@ -1891,13 +1901,15 @@ void utrace_resume(struct task_struct *t report.action = UTRACE_RESUME; list_for_each_entry(engine, &utrace->attached, entry) start_callback(utrace, &report, engine, task, 0); - } else { + break; + default: /* * Even if this report was truly spurious, there is no need * for utrace_reset() now. TIF_NOTIFY_RESUME was already * cleared--it doesn't stay spuriously set. */ report.spurious = false; + break; } /* From oleg at redhat.com Thu Nov 19 02:15:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:15:53 +0100 Subject: [PATCH 1/4] finish_resume_report(UTRACE_RESUME) must not be called without report Message-ID: <20091119021553.GA10376@redhat.com> We should never call finish_resume_report(report) when report->action == UTRACE_RESUME, this can "destroy" the result of the previous finish_resume_report(). Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~1_UGS_FIX_FINISH_RESUME_REPORT 2009-11-19 02:17:26.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-19 02:24:41.000000000 +0100 @@ -2019,9 +2019,11 @@ int utrace_get_signal(struct task_struct * We only got here to process utrace->resume. * Despite no callbacks, this report is not spurious. */ - report.action = resume; - report.spurious = false; - finish_resume_report(task, utrace, &report); + if (resume != UTRACE_RESUME) { + report.action = resume; + report.spurious = false; + finish_resume_report(task, utrace, &report); + } return -1; } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { /* From oleg at redhat.com Thu Nov 19 02:15:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:15:56 +0100 Subject: [PATCH 2/4] fix finish_report() vs utrace_control() race Message-ID: <20091119021556.GA10383@redhat.com> finish_report: if (resume < utrace->resume) { spin_lock(utrace_lock); utrace->resume = resume; this can race with utrace_control(). If we are going to change utrace->resume we must always check it under utrace->lock to ensure the new value is less than. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 12 +++++++----- 1 file changed, 7 insertions(+), 5 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~2_FINISH_REPORT_CK_RESUME_UNDER_LOCK 2009-11-19 02:24:41.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-19 02:40:52.000000000 +0100 @@ -1375,11 +1375,13 @@ static void finish_report(struct task_st if (resume < utrace->resume) { spin_lock(&utrace->lock); - utrace->resume = resume; - if (resume == UTRACE_INTERRUPT) - set_tsk_thread_flag(task, TIF_SIGPENDING); - else - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + if (resume < utrace->resume) { + utrace->resume = resume; + if (resume == UTRACE_INTERRUPT) + set_tsk_thread_flag(task, TIF_SIGPENDING); + else + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + } spin_unlock(&utrace->lock); } From oleg at redhat.com Thu Nov 19 02:15:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:15:58 +0100 Subject: [PATCH 3/4] introduce utrace_set_resume() helper Message-ID: <20091119021558.GA10386@redhat.com> Introduce utrace_set_resume() helper (please rename to whatever you like) to factor out the code in utrace_stop() and finish_report(). Note that utrace_set_resume() doesn have "task_struct *task" argument. This is correct, the task must be current. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 35 +++++++++++++++++------------------ 1 file changed, 17 insertions(+), 18 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~3_SET_RESUME_HELPER 2009-11-19 02:40:52.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-19 02:55:42.000000000 +0100 @@ -833,6 +833,18 @@ void utrace_finish_stop(void) } } +static void utrace_set_resume(struct utrace *utrace, + enum utrace_resume_action action) +{ + if (action < utrace->resume) { + utrace->resume = action; + if (action == UTRACE_INTERRUPT) + set_thread_flag(TIF_SIGPENDING); + else + set_thread_flag(TIF_NOTIFY_RESUME); + } +} + /* * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. * @task == current, @utrace == current->utrace, which is not locked. @@ -844,17 +856,10 @@ static void utrace_stop(struct task_stru { relock: spin_lock(&utrace->lock); - - if (action < utrace->resume) { - /* - * Ensure a reporting pass when we're resumed. - */ - utrace->resume = action; - if (action == UTRACE_INTERRUPT) - set_thread_flag(TIF_SIGPENDING); - else - set_thread_flag(TIF_NOTIFY_RESUME); - } + /* + * Ensure a reporting pass when we're resumed. + */ + utrace_set_resume(utrace, action); /* * If the ENGINE_STOP bit is clear in utrace_flags, that means @@ -1375,13 +1380,7 @@ static void finish_report(struct task_st if (resume < utrace->resume) { spin_lock(&utrace->lock); - if (resume < utrace->resume) { - utrace->resume = resume; - if (resume == UTRACE_INTERRUPT) - set_tsk_thread_flag(task, TIF_SIGPENDING); - else - set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); - } + utrace_set_resume(utrace, resume); spin_unlock(&utrace->lock); } From oleg at redhat.com Thu Nov 19 02:16:01 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:16:01 +0100 Subject: [PATCH 4/4] utrace_report_clone(CLONE_VFORK) shouldn't ignore report->resume_action Message-ID: <20091119021601.GA10389@redhat.com> If the tracee stops in utrace_finish_vfork(), we lose ->resume_action. Change utrace_report_clone() to call utrace_set_resume() when we know we are going to stop. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 1 + 1 file changed, 1 insertion(+) --- UTRACE-PTRACE/kernel/utrace.c~4_CLONE_USE_SET_RESUME 2009-11-19 02:55:42.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-19 03:03:02.000000000 +0100 @@ -1685,6 +1685,7 @@ void utrace_report_clone(unsigned long c if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { spin_lock(&utrace->lock); utrace->vfork_stop = 1; + utrace_set_resume(utrace, report.resume_action); spin_unlock(&utrace->lock); } } From oleg at redhat.com Thu Nov 19 02:36:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 19 Nov 2009 03:36:06 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091119020228.AB0831E2C@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> <20091118114843.A5DAF29@magilla.sf.frob.com> <20091118214127.GA11214@redhat.com> <20091119020228.AB0831E2C@magilla.sf.frob.com> Message-ID: <20091119023606.GA10694@redhat.com> I'll reply tomorrow, it is to late for me. But I noticed the funny detail in your email, On 11/18, Roland McGrath wrote: > > Yes. But, hmm. > > utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ > > This XXX was there about passing UTRACE_RESUME, because that's not really > right. I didn't notice this XXX marker, but I guess I just sent the patch which makes this case correct. (of course this patch doesn't fix the problem we are dicussing in this thread). Oleg. From roland at redhat.com Thu Nov 19 02:59:27 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 18 Nov 2009 18:59:27 -0800 (PST) Subject: [PATCH 0/4] utrace->resume fixes In-Reply-To: Oleg Nesterov's message of Thursday, 19 November 2009 03:15:51 +0100 <20091119021551.GA10373@redhat.com> References: <20091119021551.GA10373@redhat.com> Message-ID: <20091119025927.EF35220E1@magilla.sf.frob.com> Ack! While you were doing that, I was hacking up this patch. I probably won't get to integrating your stuff tonight either. So maybe you will look at this and merge them before I do. Thanks, Roland diff --git a/kernel/utrace.c b/kernel/utrace.c index 3f98f84..0000000 100644 --- a/kernel/utrace.c +++ b/kernel/utrace.c @@ -840,11 +840,16 @@ void utrace_finish_stop(void) * engine may still want us to stay stopped. */ static void utrace_stop(struct task_struct *task, struct utrace *utrace, - enum utrace_resume_action action) + enum utrace_resume_action action, bool skip_notify) { relock: spin_lock(&utrace->lock); + /* + * We're stopping now, so this covers the pending vfork stop. + */ + utrace->vfork_stop = 0; + if (action < utrace->resume) { /* * Ensure a reporting pass when we're resumed. @@ -852,7 +857,7 @@ relock: utrace->resume = action; if (action == UTRACE_INTERRUPT) set_thread_flag(TIF_SIGPENDING); - else + else if (action == UTRACE_REPORT || !skip_notify) set_thread_flag(TIF_NOTIFY_RESUME); } @@ -1522,6 +1527,77 @@ static const struct utrace_engine_ops *s } /* + * Apply a resume action, possibly after a stop. + * Returns true iff this resume action is requesting a report. + */ +static bool apply_resume_action(struct task_struct *task, + struct utrace *utrace, + enum utrace_resume_action action) +{ + switch (action) { + case UTRACE_INTERRUPT: + if (!signal_pending(task)) + set_tsk_thread_flag(task, TIF_SIGPENDING); + return true; + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { + user_enable_block_step(task); + break; + } + + /* + * This means some callback is to blame for failing + * to check arch_has_block_step() itself. Warn and + * then fall through to treat it as SINGLESTEP. + */ + WARN_ON(1); + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) + user_enable_single_step(task); + else + /* + * This means some callback is to blame for failing + * to check arch_has_single_step() itself. Spew + * about it so the loser will fix his module. + */ + WARN_ON(1); + break; + + default: + user_disable_single_step(task); + return action == UTRACE_REPORT; + } + + return false; +} + +/* + * Finish the last reporting pass before returning to user mode, + * This is also used at syscall entry, where we both stop and set + * arch single-step state as if returning to user. Returns true iff + * the resume action (possibly after a stop) requested another report. + */ +static bool finish_resume_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + enum utrace_resume_action action; + + finish_report_reset(task, utrace, report); + + action = report->action; + if (action == UTRACE_STOP) { + utrace_stop(task, utrace, report->resume_action, true); + action = start_report(utrace); + WARN_ON(action == UTRACE_STOP); + } + + return apply_resume_action(task, utrace, action); +} + +/* * Do a normal reporting pass for engines interested in @event. * @callback is the name of the member in the ops vector, and remaining * args are the extras it takes after the standard three args. @@ -1568,17 +1644,21 @@ static inline u32 do_report_syscall_entr struct utrace_report *report, u32 resume_report) { + bool again; + start_report(utrace); REPORT_CALLBACKS(_reverse, task, utrace, report, UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, resume_report | report->result | report->action, engine, current, regs); - finish_report(task, utrace, report, false); - - if (report->action != UTRACE_STOP) - return 0; - utrace_stop(task, utrace, report->resume_action); + /* + * Now we'll stop if asked. If we're proceeding with the syscall, + * now we'll first enable single-step if asked. That leaves the + * task in "stepping" state so tracehook_report_syscall_exit() and + * the arch code that calls it will know. + */ + again = finish_resume_report(task, utrace, report); if (fatal_signal_pending(task)) { /* @@ -1586,7 +1666,7 @@ static inline u32 do_report_syscall_entr * SIGKILL. Don't let the system call actually proceed. */ report->result = UTRACE_SYSCALL_ABORT; - } else if (utrace->resume <= UTRACE_REPORT) { + } else if (again) { /* * If we've been asked for another report after our stop, * go back to report (and maybe stop) again before we run @@ -1688,10 +1768,8 @@ void utrace_finish_vfork(struct task_str struct utrace *utrace = task_utrace_struct(task); if (utrace->vfork_stop) { - spin_lock(&utrace->lock); - utrace->vfork_stop = 0; - spin_unlock(&utrace->lock); - utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ + utrace_stop(task, utrace, UTRACE_RESUME, true); + apply_resume_action(task, utrace, start_report(utrace)); } } @@ -1728,7 +1806,7 @@ void utrace_report_exit(long *exit_code) report_exit, orig_code, exit_code); if (report.action == UTRACE_STOP) - utrace_stop(task, utrace, report.resume_action); + utrace_stop(task, utrace, report.resume_action, true); } /* @@ -1786,58 +1864,6 @@ void utrace_report_death(struct task_str } /* - * Finish the last reporting pass before returning to user mode. - */ -static void finish_resume_report(struct task_struct *task, - struct utrace *utrace, - struct utrace_report *report) -{ - finish_report_reset(task, utrace, report); - - switch (report->action) { - case UTRACE_STOP: - utrace_stop(task, utrace, report->resume_action); - break; - - case UTRACE_INTERRUPT: - if (!signal_pending(task)) - set_tsk_thread_flag(task, TIF_SIGPENDING); - break; - - case UTRACE_BLOCKSTEP: - if (likely(arch_has_block_step())) { - user_enable_block_step(task); - break; - } - - /* - * This means some callback is to blame for failing - * to check arch_has_block_step() itself. Warn and - * then fall through to treat it as SINGLESTEP. - */ - WARN_ON(1); - - case UTRACE_SINGLESTEP: - if (likely(arch_has_single_step())) - user_enable_single_step(task); - else - /* - * This means some callback is to blame for failing - * to check arch_has_single_step() itself. Spew - * about it so the loser will fix his module. - */ - WARN_ON(1); - break; - - case UTRACE_REPORT: - case UTRACE_RESUME: - default: - user_disable_single_step(task); - break; - } -} - -/* * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). * We are close to user mode, and this is the place to report or stop. * When we return, we're going to user mode or into the signals code. @@ -1994,11 +2020,8 @@ int utrace_get_signal(struct task_struct if (resume > UTRACE_REPORT) { /* * We only got here to process utrace->resume. - * Despite no callbacks, this report is not spurious. */ - report.action = resume; - report.spurious = false; - finish_resume_report(task, utrace, &report); + apply_resume_action(task, utrace, resume); return -1; } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { /* From sam4560123 at sina.com Thu Nov 19 06:37:28 2009 From: sam4560123 at sina.com (=?utf-8?B?5a696aqP572R?=) Date: Thu, 19 Nov 2009 14:37:28 +0800 Subject: =?utf-8?b?572R5LiK56ys5LiA5Lit5LuL5Lqk5piT5bmz5Y+w?= Message-ID: <20091118.HLCIXVEDWFPWOWJK@sina.com> ??v -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: swqf-1.jpg Type: image/jpeg Size: 131229 bytes Desc: not available URL: From news at voidcreations.org Thu Nov 19 09:00:57 2009 From: news at voidcreations.org (VOID CREATIONS) Date: Thu, 19 Nov 2009 10:00:57 +0100 Subject: Convite para a abertura das Trash Sessions, esta sexta-feira no Bairro Alto Message-ID: <3c0e57611105256fb001d61fb69ee3a1@www.divulgacaodigital.com> Se n?o visualizares esta p?gina correctamente, clica aqui Adiciona-nos ? tua safe-list, para garantir que recebes sempre a info dos nossos eventos. ** ** **Apresenta:** Na pr?xima sexta-feira, 20 de Novembro, vai haver um tsunami no centro cultural O S?culo : a primeira ?Trash Sessions?, organizada pela Void Creations. A Void ir? realizar regularmente estas sess?es em diferentes espa?os da noite lisboeta, que ter?o em comum uma programa??o criteriosamente seleccionada e o desejo de proporcionar noites de arromba, das quais ningu?m sair? indiferente. Pelas 21h30, teremos a exibi??o do filme Plan 9 From Outer Space , realizado pelo lend?rio Ed Wood, e que foi considerado o melhor dos piores filmes de sempre. A festa vai aquecer ao som dos Tsunamiz . Estes margem-sulenses, compostos por Bruno Sobral e Marco Dinis, descrevem-se como ?Abba being molested by Atari Teenage Riot? e proclamam influ?ncias t?o d?spares quanto Beethoven, 2Pac, Queens of the Stone Age, Beck, Bob Marley ou The Doors. Em palco, prometem uma actua??o verdadeiramente el?ctrica, j? que para este duo ?Nada ? Verdadeiro e Tudo ? Permitido!? A completar a soir?e, o dj set estar? a cargo de Playgirl. Tamb?m oriunda da margem sul do Tejo, oferece ?guitarras e alguma elect?nica? ? desde Sonic Youth, Jesus and the Mary Chain, Babes in Toyland, David Bowie, Stereo Lab at? Crystal Castles, Chicks on Speed, Ellen Alien ou She Wants Revenge ? e uma festa muito dan??vel. Os visuais estar?o a cargo da VJ Psyberdoll , que desde 2005 encontrou nos audiovisuais a sua melhor forma de express?o. Desde ent?o, tem explorado as potencialidades de fus?o entre o org?nico e o tecnol?gico. A festa n? O S?culo ter? in?cio pelas 21h30, hora em que come?am a ser servidos os jantares que j? est?o a ganhar fama no circuito lisboeta. A ementa ? variada e, para marcar lugar, basta entrar em contacto com a Void Creations para o email reservas at voidcreations.org. A entrada ? gratuita mediante a apresenta??o do flyer. Imprimam-no ou apanhem-no? se conseguirem! Electro, Indie rock, pop electr?nico, bom cinema, muita dan?a e oferta de J?gerbombs!? Apare?am! Local: O S?culo ? Centro Cultural Hora: 21h30 Entrada: Livre com apresenta??o de flyer / sem flyer 3? Morada: Rua do S?culo n? 80, 1200-436, Bairro Alto, Lisboa Mapa: Contactos: Void Creations E-mail: info at voidcreations.org @ Info adicional : www.voidcreations.org - ? favor divulgar - Powered by Divulga??o Digital Para RE-ENVIAR / To FORWARD - http://www.divulgacaodigital.com/void-creations/?p=forward&uid=8796d6f78d5efbb8958965a0e70ab9c8&mid=18 Para REMOVER / To REMOVE - http://www.divulgacaodigital.com/void-creations/?p=unsubscribe&uid=8796d6f78d5efbb8958965a0e70ab9c8 Para MODIFICAR / To MODIFY - http://www.divulgacaodigital.com/void-creations/?p=preferences&uid=8796d6f78d5efbb8958965a0e70ab9c8 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From promove at soscartuchos.com.br Thu Nov 19 13:53:10 2009 From: promove at soscartuchos.com.br (SOSCARTUCHOS) Date: Thu, 19 Nov 2009 13:53:10 GMT Subject: =?iso-8859-1?q?Recarrgue_=E1rtir_de_R=24_3=2C00?= Message-ID: <200911191353.nAJDr7QQ016117@mx2.redhat.com> An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: pronov.jpg Type: image/jpeg Size: 174166 bytes Desc: not available URL: From info at aguahesp.net Thu Nov 19 11:04:04 2009 From: info at aguahesp.net (=?UTF-8?B?TGFib3JhdMOzcmlvIEFHVUFIRVNQ?=) Date: Thu, 19 Nov 2009 12:04:04 +0100 Subject: URGENTE! Como esta a agua que voce bebe? Message-ID: <3088b41e3dff2a764d1413c5033a5aa6@www.aguahesp.net> Seu cliente de e-mail n?o pode ler este e-mail. Para visualiz?-lo on-line, por favor, clique aqui: http://www.aguahesp.net/painel/display.php?M=292906&C=bbe5ed06fc3f5aa48a39e551fe0067ea&S=32&L=12&N=4 Para parar de receber nossos e-mails:http://www.aguahesp.net/painel/unsubscribe.php?M=292906&C=bbe5ed06fc3f5aa48a39e551fe0067ea&L=12&N=32 -------------- next part -------------- An HTML attachment was scrubbed... URL: From info at geniedream.com Thu Nov 19 17:28:02 2009 From: info at geniedream.com (info at geniedream.com) Date: Thu, 19 Nov 2009 18:28:02 +0100 Subject: MAKE MONEY FAST!! Message-ID: <1466665bd4c412a6c6eaac9669880a65@mailer.geniedream.com> CHECK IT OUT !! http://WWW.MAKEMONEYWITHGOLD.CO.UK http://www.makemoneywithgold.co.uk a subsidiary of http://www.geniedream.com World Class Series . A Genie Dream Product www.geniedream.com -- If you do not want to receive any more newsletters, http://mailer.geniedream.com/?p=unsubscribe&uid=b827143f780fb434e6d5ea58d8b32539 To update your preferences and to unsubscribe visit http://mailer.geniedream.com/?p=preferences&uid=b827143f780fb434e6d5ea58d8b32539 Forward a Message to Someone http://mailer.geniedream.com/?p=forward&uid=b827143f780fb434e6d5ea58d8b32539&mid=1 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From oleg at redhat.com Fri Nov 20 04:02:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Nov 2009 05:02:49 +0100 Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: <20091119020228.AB0831E2C@magilla.sf.frob.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> <20091118114843.A5DAF29@magilla.sf.frob.com> <20091118214127.GA11214@redhat.com> <20091119020228.AB0831E2C@magilla.sf.frob.com> Message-ID: <20091120040249.GA12739@redhat.com> On 11/18, Roland McGrath wrote: > > > Hmm. not sure I understand how this can work. I mean, this won't > > enable stepping (in this particular case we are discussing). > > I might be confused. I'm thinking of two cases: the report_syscall_entry > pass yields UTRACE_SINGLESTEP, or that it yields UTRACE_STOP and then > utrace_control() sets utrace->resume to UTRACE_SINGLESTEP. > > The former is e.g. PTRACE_SINGLESTEP while an unrelated engine uses > UTRACE_EVENT(SYSCALL_ENTRY). The ptrace engine's report_quiesce returns > UTRACE_SINGLESTEP. finish_resume_report() calls user_enable_single_step(). > That seems fine. Right? In this case ptrace_report_quiesce(event) returns UTRACE_RESUME, note that it does return event ? UTRACE_RESUME : ctx->resume; and event == SYSCALL_ENTRY. This looks correct. > The latter is e.g. PTRACE_SINGLESTEP after ptrace stop at syscall entry. Yes, this is the case I was talking about. > I see. finish_resume_report() will only do utrace_stop() and then we'll > go directly into the syscall unless someone used UTRACE_REPORT. Yes, > utrace_stop() will only set TIF_NOTIFY_RESUME and utrace->resume. In > the real resume-to-user cases, that's fine because we'll handle that in > utrace_resume() or utrace_get_signal() before doing anything else. Not sure I understand. utrace_stop() will not set TIF_NOTIFY_RESUME? We are talking about the case when the tracee stops in SYSCALL_ENTER, and then the tracer does utrace_control(UTRACE_SINGLESTEP) to resume. In this case utrace_control() sets ->resume/TIF_NOTIFY_RESUME, yes. > @@ -1794,11 +1794,13 @@ static void finish_resume_report(struct > { > finish_report_reset(task, utrace, report); > > - switch (report->action) { > - case UTRACE_STOP: > - utrace_stop(task, utrace, report->resume_action); > - break; > + if (report->action == UTRACE_STOP) { > + utrace_stop(task, utrace, report->resume_action, true); > + report->action = start_report(utrace); > + WARN_ON(report->action == UTRACE_STOP); > + } > > + switch (report->action) { > case UTRACE_INTERRUPT: > if (!signal_pending(task)) > set_tsk_thread_flag(task, TIF_SIGPENDING); Yes, this means the tracee gets TIF_SINGLESTEP right after resume, and > this > seems like the right idea for how to get tracehook_report_syscall_exit > called in the cases where it is in old ptrace. Afaics yes. But, what if another engine does utrace_control(UTRACE_INTERRUPT) ? > > Instead of fixing utrace_report_syscall_entry(), perhaps we should > > change utrace_stop() path to enable the stepping if needed, but this > > means we return to "synchronous" utrace_control(UTRACE_XXXSTEP). > > I don't really follow what you mean by "synchronous". Argh. I meant, from the caller pov, utrace_control(UTRACE_SINGLESTEP) does enable_step() "immediately", like it did before utrace-cleanup changes. IOW, suppose the tracee is stopped, and ptrace does UTRACE_SINGLESTEP. The tracee resumes, processes ->resume, and does enable_step(). >From the ptrace pov, it looks as if utrace_control() does enable_step() before utrace_wakeup(). > Your suggestion is > equivalent to making utrace_finish_vfork call finish_resume_report instead > of utrace_stop, isn't it? I meant, every time the tracee stops, it should process ->resume after wakeup. Looks like, the patch you sent in another thread (which adds apply_resume_action()) does something like this, right? I'll try to read it carefully now. Oleg. From oleg at redhat.com Fri Nov 20 06:25:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Nov 2009 07:25:58 +0100 Subject: [PATCH 0/4] utrace->resume fixes In-Reply-To: <20091119025927.EF35220E1@magilla.sf.frob.com> References: <20091119021551.GA10373@redhat.com> <20091119025927.EF35220E1@magilla.sf.frob.com> Message-ID: <20091120062558.GA17019@redhat.com> On 11/18, Roland McGrath wrote: > > So maybe you will look at this and merge them before I do. Somehow I can't really understand this patch. I hope more or less I can see what it does, but the resulting code looks even more subtle to me. OK, probably I need to re-read this patch tomorrow, I can never understand the code after the first reading. With this patch, apply_resume_action() is always called after utrace_stop(). Well, except for utrace_report_exit(), but I guess it could do apply_resume_action() too. Now it is not clear why utrace_control(SINGLESTEP) sets TIF_NOTIFY_RESUME, it is not needed after apply_resume_action() processes ->resume. Yes, we have jctl stops, but we can move this code into utrace_finish_stop(). It is not clear to me why apply_resume_action(UTRACE_INTERRUPT) does set_tsk_thread_flag(TIF_SIGPENDING). In fact I don't understand why apply_resume_action() checks UTRACE_INTERRUPT at all. If it is called after utrace_stop(), action == start_report() which never resets UTRACE_INTERRUPT. And since we process ->resume after stop, it is not clear why we set ->resume = report->resume_action before stop, apply_resume_action() could use min(report->resume_action, utrace->resume). Yes, yes, we have the nasty utrace->vfork_stop case, I mean it is not easy to understand the logic behind all these ->resume changes. And afaics, this can't help to fix the tracehook_report_syscall_exit() && TIF_SINGLESTEP problems in the multitracing case, UTRACE_INTERRUPT "destroys" UTRACE_SINGLESTEP. Ptrace can reassert it later, but this will be too late, the trace has already passed this tracehook. > static void utrace_stop(struct task_struct *task, struct utrace *utrace, > - enum utrace_resume_action action) > + enum utrace_resume_action action, bool skip_notify) > { > ... > - else > + else if (action == UTRACE_REPORT || !skip_notify) > set_thread_flag(TIF_NOTIFY_RESUME); I don't understand this skip_notify, utrace_stop() is always called with skip_notify == true? Oleg. From oleg at redhat.com Fri Nov 20 10:27:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Nov 2009 11:27:44 +0100 Subject: [PATCH 134] mv kernel/ptrace.c kernel/ptrace-utrace.c Message-ID: <20091120102744.GA31489@redhat.com> mv kernel/ptrace.c kernel/ptrace-utrace.c. Then I will send the patch which "restores" the old ptrace.c and moves kernel/ptrace-common.h into it as you suggested before. I am not sure what is the best way to do these renames but I hope this doesn't really matter, utrace-ptrace branch is only for us. The goal is to make it testable with and without CONFIG_UTRACE. --- kernel/Makefile | 1 + kernel/ptrace-utrace.c | 1117 ++++++++++++++++++++++++++++++++++++++++++++++++ kernel/ptrace.c | 1117 ------------------------------------------------ 3 files changed, 1118 insertions(+), 1117 deletions(-) create mode 100644 kernel/ptrace-utrace.c delete mode 100644 kernel/ptrace.c diff --git a/kernel/Makefile b/kernel/Makefile index 8f41620..04e9139 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o obj-$(CONFIG_UTRACE) += utrace.o +obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ diff --git a/kernel/ptrace-utrace.c b/kernel/ptrace-utrace.c new file mode 100644 index 0000000..e10410c --- /dev/null +++ b/kernel/ptrace-utrace.c @@ -0,0 +1,1117 @@ +/* + * linux/kernel/ptrace.c + * + * (C) Copyright 1999 Linus Torvalds + * + * Common interfaces for "ptrace()" which we do not want + * to continually duplicate across every architecture. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#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; + + int signr; + siginfo_t *siginfo; + + int stop_code; + unsigned long eventmsg; + + enum utrace_resume_action resume; +}; + +#define PT_UTRACED 0x00001000 + +#define PTRACE_O_SYSEMU 0x100 + +#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) +#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) +#define PTRACE_EVENT_SIGTRAP (3 << 16) +#define PTRACE_EVENT_SIGNAL (4 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF + +static inline bool ptrace_event_pending(struct ptrace_context *ctx) +{ + return ctx->stop_code != 0; +} + +static inline int get_stop_event(struct ptrace_context *ctx) +{ + return ctx->stop_code >> 8; +} + +static inline void set_stop_code(struct ptrace_context *ctx, int event) +{ + ctx->stop_code = (event << 8) | SIGTRAP; +} + +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) +{ + 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 *ctx; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + ctx = ptrace_context(engine); + if (unlikely(ctx->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. + */ + ctx->options = 0; + ctx->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + ctx->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 *ctx; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (unlikely(!ctx)) + return ERR_PTR(-ENOMEM); + + ctx->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, ctx); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(ctx); + } + + return engine; +} + +static inline int ptrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *ctx = 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; + + ctx->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_events(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; +} + +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 void ptrace_detach_task(struct task_struct *tracee, int sig) +{ + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; + + if (unlikely(IS_ERR(engine))) + return; + + if (sig) { + struct ptrace_context *ctx = ptrace_context(engine); + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (voluntary) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (voluntary) + ctx->signr = sig; + ctx->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + ptrace_wake_up(tracee, engine, action, voluntary); + utrace_engine_put(engine); +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + ptrace_detach_task(tracee, 0); +} + +static u32 ptrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx) && + !signal_group_exit(task->signal)); + + set_stop_code(ctx, PTRACE_EVENT_EXIT); + ctx->eventmsg = *code; + + return UTRACE_STOP; +} + +static void ptrace_clone_attach(struct task_struct *parent, + struct task_struct *child, + int options) +{ + struct task_struct *tracer; + bool abort = true; + + if (unlikely(ptrace_attach_task(child, options))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); +} + +/* + * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). + * Called when we are going to emulate the stop before SYSCALL_EXIT. + */ +static void suppress_sigtrap(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) + user_disable_single_step(task); +} + +static u32 ptrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int event = 0; + + WARN_ON(ptrace_event_pending(ctx)); + + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { + if (ctx->options & PTRACE_O_TRACEVFORK) + event = PTRACE_EVENT_VFORK; + else if (ctx->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (ctx->options & PTRACE_O_TRACECLONE) + event = PTRACE_EVENT_CLONE; + } else if (ctx->options & PTRACE_O_TRACEFORK) { + event = PTRACE_EVENT_FORK; + } + /* + * Any of these reports implies auto-attaching the new child. + * So does CLONE_PTRACE, even with no event to report. + */ + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(parent, child, ctx->options); + + if (!event) + return UTRACE_RESUME; + + suppress_sigtrap(parent); + + set_stop_code(ctx, event); + ctx->eventmsg = child->pid; + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; +} + +static inline void set_syscall_code(struct ptrace_context *ctx, int event) +{ + set_stop_code(ctx, event); + if (ctx->options & PTRACE_O_TRACESYSGOOD) + ctx->stop_code |= 0x80; +} + +static u32 ptrace_report_syscall_entry(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (action & UTRACE_SYSCALL_RESUMED) { + /* + * We already reported the first time. + * Nothing more to do now. + */ + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + return utrace_syscall_action(action) | UTRACE_RESUME; + } + + WARN_ON(ptrace_event_pending(ctx)); + + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); + + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { + suppress_sigtrap(task); + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + } + + /* + * Stop now to report. We will get another callback after + * we resume, with the UTRACE_SYSCALL_RESUMED flag set. + */ + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + if (ctx->resume != UTRACE_RESUME) { + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && + ctx->resume != UTRACE_SINGLESTEP); + ctx->resume = UTRACE_RESUME; + + ctx->signr = SIGTRAP; + return UTRACE_INTERRUPT; + } + + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + return UTRACE_STOP; +} + +static u32 ptrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx)); + + if (!(ctx->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, task, 0); + return UTRACE_RESUME; + } + + suppress_sigtrap(task); + set_stop_code(ctx, PTRACE_EVENT_EXEC); + + return UTRACE_STOP; +} + +static void ptrace_send_sigtrap(struct task_struct *task, siginfo_t *info) +{ + user_single_step_siginfo(task, task_pt_regs(task), info); + force_sig_info(SIGTRAP, info, task); +} + +static enum utrace_signal_action resume_signal(struct task_struct *task, + struct ptrace_context *ctx, + struct k_sigaction *return_ka) +{ + siginfo_t *info = ctx->siginfo; + int signr = ctx->signr; + + ctx->siginfo = NULL; + ctx->signr = 0; + + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(&task->blocked, signr)) { + send_sig_info(signr, info, task); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[signr - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; +} + +static u32 ptrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct ptrace_context *ctx = ptrace_context(engine); + enum utrace_resume_action resume = ctx->resume; + + if (ptrace_event_pending(ctx)) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + if (WARN_ON(ctx->siginfo)) + ctx->siginfo = NULL; + + if (resume != UTRACE_RESUME) { + WARN_ON(resume != UTRACE_BLOCKSTEP && + resume != UTRACE_SINGLESTEP); + + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + case UTRACE_SIGNAL_REPORT: + if (!ctx->siginfo) { + if (ctx->signr) { + /* set by ptrace_resume(SYSCALL_EXIT) */ + WARN_ON(ctx->signr != SIGTRAP); + ptrace_send_sigtrap(task, info); + } + + return resume | UTRACE_SIGNAL_IGN; + } + + if (WARN_ON(ctx->siginfo != info)) + return resume | UTRACE_SIGNAL_IGN; + + return resume | resume_signal(task, ctx, return_ka); + + default: + break; + } + + WARN_ON(ctx->siginfo); + ctx->siginfo = info; + /* + * ctx->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); + + ctx->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; +} + +static u32 ptrace_report_quiesce(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + return event ? UTRACE_RESUME : ctx->resume; +} + +static void ptrace_release(void *data) +{ + kfree(data); +} + +static const struct utrace_engine_ops ptrace_utrace_ops = { + .report_signal = ptrace_report_signal, + .report_quiesce = ptrace_report_quiesce, + .report_exec = ptrace_report_exec, + .report_exit = ptrace_report_exit, + .report_clone = ptrace_report_clone, + .report_syscall_entry = ptrace_report_syscall_entry, + .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, +}; + +int ptrace_check_attach(struct task_struct *child, int kill) +{ + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret = -ESRCH; + + engine = ptrace_lookup_engine(child); + if (IS_ERR(engine)) + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + + if (!task_is_stopped_or_traced(child)) + goto out; + /* + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. + */ + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: + utrace_engine_put(engine); + return ret; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + retval = ptrace_attach_task(task, 0); + if (unlikely(retval)) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + + BUG_ON(task->ptrace); + task->ptrace = PT_UTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/* + * Performs checks and sets PT_UTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + bool detach = true; + int ret = ptrace_attach_task(current, 0); + + if (unlikely(ret)) + return ret; + + ret = -EPERM; + write_lock_irq(&tasklist_lock); + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_UTRACED; + __ptrace_link(current, current->real_parent); + detach = false; + } + write_unlock_irq(&tasklist_lock); + + if (detach) + ptrace_abort_attach(current); + return ret; +} + +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) +{ + bool detach, release; + + write_lock_irq(&tasklist_lock); + /* + * This tracee can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + detach = tracee->ptrace != 0; + release = false; + if (likely(detach)) + release = __ptrace_detach(current, tracee); + write_unlock_irq(&tasklist_lock); + + if (unlikely(release)) + release_task(tracee); + else if (likely(detach)) + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + for (;;) { + struct task_struct *tracee = NULL; + + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; + + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); + } +} + +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) +{ + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *ctx, + siginfo_t *info, bool write) +{ + unsigned long flags; + int err; + + switch (get_stop_event(ctx)) { + case 0: /* jctl stop */ + return -EINVAL; + + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *ctx->siginfo = *info; + else + *info = *ctx->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } + + return err; + + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } + + return 0; + } +} + +static void do_ptrace_notify_stop(struct ptrace_context *ctx, + struct task_struct *tracee) +{ + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ + tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; + WARN_ON(!tracee->exit_code); + + read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + preempt_enable_no_resched(); +} + +void ptrace_notify_stop(struct task_struct *tracee) +{ + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + + if (IS_ERR(engine)) + return; + + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); +} + +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) +{ + struct ptrace_context *ctx = ptrace_context(engine); + unsigned long events; + int action; + + ctx->options &= ~PTRACE_O_SYSEMU; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; + + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: + if (unlikely(!arch_has_block_step())) + return -EIO; + action = UTRACE_BLOCKSTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + ctx->options |= PTRACE_O_SYSEMU; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; + + case PTRACE_CONT: + break; + default: + return -EIO; + } + + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; + + return action; +} + +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_VFORK: + if (ctx->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + do_ptrace_notify_stop(ctx, tracee); + return 0; + } + + if (action != UTRACE_RESUME) { + /* + * single-stepping. UTRACE_SIGNAL_REPORT will + * synthesize a trap to follow the syscall insn. + */ + ctx->signr = SIGTRAP; + action = UTRACE_INTERRUPT; + } + break; + + case PTRACE_EVENT_SYSCALL_EXIT: + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + ctx->signr = data; + break; + } + + ctx->resume = action; + ptrace_wake_up(tracee, engine, action, true); + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = generic_ptrace_pokedata(child, addr, data); + break; + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_set_options(child, engine, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(ptrace_context(engine)->eventmsg, + (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + + case PTRACE_KILL: + /* Ugly historical behaviour. */ + if (task_is_traced(child)) + ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); + ret = 0; + break; + + default: + ret = ptrace_resume(child, engine, request, data); + break; + } + + utrace_engine_put(engine); + return ret; +} + +#if defined CONFIG_COMPAT +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, + datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + utrace_engine_put(engine); + return ret; +} +#endif /* CONFIG_COMPAT */ diff --git a/kernel/ptrace.c b/kernel/ptrace.c deleted file mode 100644 index e10410c..0000000 --- a/kernel/ptrace.c +++ /dev/null @@ -1,1117 +0,0 @@ -/* - * linux/kernel/ptrace.c - * - * (C) Copyright 1999 Linus Torvalds - * - * Common interfaces for "ptrace()" which we do not want - * to continually duplicate across every architecture. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#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; - - int signr; - siginfo_t *siginfo; - - int stop_code; - unsigned long eventmsg; - - enum utrace_resume_action resume; -}; - -#define PT_UTRACED 0x00001000 - -#define PTRACE_O_SYSEMU 0x100 - -#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) -#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGTRAP (3 << 16) -#define PTRACE_EVENT_SIGNAL (4 << 16) -/* events visible to user-space */ -#define PTRACE_EVENT_MASK 0xFFFF - -static inline bool ptrace_event_pending(struct ptrace_context *ctx) -{ - return ctx->stop_code != 0; -} - -static inline int get_stop_event(struct ptrace_context *ctx) -{ - return ctx->stop_code >> 8; -} - -static inline void set_stop_code(struct ptrace_context *ctx, int event) -{ - ctx->stop_code = (event << 8) | SIGTRAP; -} - -static inline struct ptrace_context * -ptrace_context(struct utrace_engine *engine) -{ - 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 *ctx; - int err = -EPERM; - - engine = ptrace_lookup_engine(tracee); - if (IS_ERR(engine)) - return engine; - - ctx = ptrace_context(engine); - if (unlikely(ctx->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. - */ - ctx->options = 0; - ctx->eventmsg = 0; - - /* make sure we don't get unwanted reports */ - err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); - if (!err || err == -EINPROGRESS) { - ctx->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 *ctx; - - if (unlikely(task_utrace_flags(tracee))) { - engine = ptrace_reuse_engine(tracee); - if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) - return engine; - } - - ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); - if (unlikely(!ctx)) - return ERR_PTR(-ENOMEM); - - ctx->resume = UTRACE_RESUME; - - engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | - UTRACE_ATTACH_EXCLUSIVE | - UTRACE_ATTACH_MATCH_OPS, - &ptrace_utrace_ops, ctx); - if (unlikely(IS_ERR(engine))) { - if (engine != ERR_PTR(-ESRCH) && - engine != ERR_PTR(-ERESTARTNOINTR)) - engine = ERR_PTR(-EPERM); - kfree(ctx); - } - - return engine; -} - -static inline int ptrace_set_events(struct task_struct *target, - struct utrace_engine *engine, - unsigned long options) -{ - struct ptrace_context *ctx = 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; - - ctx->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_events(tracee, engine, options); - WARN_ON(err && !tracee->exit_state); - utrace_engine_put(engine); - return 0; -} - -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 void ptrace_detach_task(struct task_struct *tracee, int sig) -{ - /* - * If true, the caller is PTRACE_DETACH, otherwise - * the tracer detaches implicitly during exit. - */ - bool voluntary = (sig >= 0); - struct utrace_engine *engine = ptrace_lookup_engine(tracee); - enum utrace_resume_action action = UTRACE_DETACH; - - if (unlikely(IS_ERR(engine))) - return; - - if (sig) { - struct ptrace_context *ctx = ptrace_context(engine); - - switch (get_stop_event(ctx)) { - case PTRACE_EVENT_SYSCALL_ENTRY: - case PTRACE_EVENT_SYSCALL_EXIT: - if (voluntary) - send_sig_info(sig, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - if (voluntary) - ctx->signr = sig; - ctx->resume = UTRACE_DETACH; - action = UTRACE_RESUME; - break; - } - } - - ptrace_wake_up(tracee, engine, action, voluntary); - utrace_engine_put(engine); -} - -static void ptrace_abort_attach(struct task_struct *tracee) -{ - ptrace_detach_task(tracee, 0); -} - -static u32 ptrace_report_exit(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - long orig_code, long *code) -{ - struct ptrace_context *ctx = ptrace_context(engine); - - WARN_ON(ptrace_event_pending(ctx) && - !signal_group_exit(task->signal)); - - set_stop_code(ctx, PTRACE_EVENT_EXIT); - ctx->eventmsg = *code; - - return UTRACE_STOP; -} - -static void ptrace_clone_attach(struct task_struct *parent, - struct task_struct *child, - int options) -{ - struct task_struct *tracer; - bool abort = true; - - if (unlikely(ptrace_attach_task(child, options))) { - WARN_ON(1); - return; - } - - write_lock_irq(&tasklist_lock); - tracer = parent->parent; - if (!(tracer->flags & PF_EXITING) && parent->ptrace) { - child->ptrace = parent->ptrace; - __ptrace_link(child, tracer); - abort = false; - } - write_unlock_irq(&tasklist_lock); - if (unlikely(abort)) { - ptrace_abort_attach(child); - return; - } - - sigaddset(&child->pending.signal, SIGSTOP); - set_tsk_thread_flag(child, TIF_SIGPENDING); -} - -/* - * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). - * Called when we are going to emulate the stop before SYSCALL_EXIT. - */ -static void suppress_sigtrap(struct task_struct *task) -{ - if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) - user_disable_single_step(task); -} - -static u32 ptrace_report_clone(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *parent, - unsigned long clone_flags, - struct task_struct *child) -{ - struct ptrace_context *ctx = ptrace_context(engine); - int event = 0; - - WARN_ON(ptrace_event_pending(ctx)); - - if (clone_flags & CLONE_UNTRACED) { - /* no events reported */ - } else if (clone_flags & CLONE_VFORK) { - if (ctx->options & PTRACE_O_TRACEVFORK) - event = PTRACE_EVENT_VFORK; - else if (ctx->options & PTRACE_O_TRACEVFORKDONE) - event = PTRACE_EVENT_VFORK_DONE; - } else if ((clone_flags & CSIGNAL) != SIGCHLD) { - if (ctx->options & PTRACE_O_TRACECLONE) - event = PTRACE_EVENT_CLONE; - } else if (ctx->options & PTRACE_O_TRACEFORK) { - event = PTRACE_EVENT_FORK; - } - /* - * Any of these reports implies auto-attaching the new child. - * So does CLONE_PTRACE, even with no event to report. - */ - if ((event && event != PTRACE_EVENT_VFORK_DONE) || - (clone_flags & CLONE_PTRACE)) - ptrace_clone_attach(parent, child, ctx->options); - - if (!event) - return UTRACE_RESUME; - - suppress_sigtrap(parent); - - set_stop_code(ctx, event); - ctx->eventmsg = child->pid; - /* - * We shouldn't stop now, inside the do_fork() path. - * We will stop later, before return to user-mode. - */ - if (event == PTRACE_EVENT_VFORK_DONE) - return UTRACE_REPORT; - else - return UTRACE_STOP; -} - -static inline void set_syscall_code(struct ptrace_context *ctx, int event) -{ - set_stop_code(ctx, event); - if (ctx->options & PTRACE_O_TRACESYSGOOD) - ctx->stop_code |= 0x80; -} - -static u32 ptrace_report_syscall_entry(u32 action, - struct utrace_engine *engine, - struct task_struct *task, - struct pt_regs *regs) -{ - struct ptrace_context *ctx = ptrace_context(engine); - - if (action & UTRACE_SYSCALL_RESUMED) { - /* - * We already reported the first time. - * Nothing more to do now. - */ - if (unlikely(ctx->options & PTRACE_O_SYSEMU)) - return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; - return utrace_syscall_action(action) | UTRACE_RESUME; - } - - WARN_ON(ptrace_event_pending(ctx)); - - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); - - if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { - suppress_sigtrap(task); - return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; - } - - /* - * Stop now to report. We will get another callback after - * we resume, with the UTRACE_SYSCALL_RESUMED flag set. - */ - return UTRACE_SYSCALL_RUN | UTRACE_STOP; -} - -static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - struct pt_regs *regs) -{ - struct ptrace_context *ctx = ptrace_context(engine); - - if (ptrace_event_pending(ctx)) - return UTRACE_STOP; - - if (ctx->resume != UTRACE_RESUME) { - WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && - ctx->resume != UTRACE_SINGLESTEP); - ctx->resume = UTRACE_RESUME; - - ctx->signr = SIGTRAP; - return UTRACE_INTERRUPT; - } - - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); - return UTRACE_STOP; -} - -static u32 ptrace_report_exec(enum utrace_resume_action action, - struct utrace_engine *engine, - struct task_struct *task, - const struct linux_binfmt *fmt, - const struct linux_binprm *bprm, - struct pt_regs *regs) -{ - struct ptrace_context *ctx = ptrace_context(engine); - - WARN_ON(ptrace_event_pending(ctx)); - - if (!(ctx->options & PTRACE_O_TRACEEXEC)) { - /* - * Old-fashioned ptrace'd exec just posts a plain signal. - */ - send_sig(SIGTRAP, task, 0); - return UTRACE_RESUME; - } - - suppress_sigtrap(task); - set_stop_code(ctx, PTRACE_EVENT_EXEC); - - return UTRACE_STOP; -} - -static void ptrace_send_sigtrap(struct task_struct *task, siginfo_t *info) -{ - user_single_step_siginfo(task, task_pt_regs(task), info); - force_sig_info(SIGTRAP, info, task); -} - -static enum utrace_signal_action resume_signal(struct task_struct *task, - struct ptrace_context *ctx, - struct k_sigaction *return_ka) -{ - siginfo_t *info = ctx->siginfo; - int signr = ctx->signr; - - ctx->siginfo = NULL; - ctx->signr = 0; - - /* Did the debugger cancel the sig? */ - if (!signr) - return UTRACE_SIGNAL_IGN; - /* - * Update the siginfo structure if the signal has changed. - * If the debugger wanted something specific in the siginfo - * then it should have updated *info via PTRACE_SETSIGINFO. - */ - if (info->si_signo != signr) { - info->si_signo = signr; - info->si_errno = 0; - info->si_code = SI_USER; - info->si_pid = task_pid_vnr(current->parent); - info->si_uid = task_uid(current->parent); - } - - /* If the (new) signal is now blocked, requeue it. */ - if (sigismember(&task->blocked, signr)) { - send_sig_info(signr, info, task); - return UTRACE_SIGNAL_IGN; - } - - spin_lock_irq(&task->sighand->siglock); - *return_ka = task->sighand->action[signr - 1]; - spin_unlock_irq(&task->sighand->siglock); - - return UTRACE_SIGNAL_DELIVER; -} - -static u32 ptrace_report_signal(u32 action, - struct utrace_engine *engine, - struct task_struct *task, - struct pt_regs *regs, - siginfo_t *info, - const struct k_sigaction *orig_ka, - struct k_sigaction *return_ka) -{ - struct ptrace_context *ctx = ptrace_context(engine); - enum utrace_resume_action resume = ctx->resume; - - if (ptrace_event_pending(ctx)) { - action = utrace_signal_action(action); - WARN_ON(action != UTRACE_SIGNAL_REPORT); - return action | UTRACE_STOP; - } - - switch (utrace_signal_action(action)) { - case UTRACE_SIGNAL_HANDLER: - if (WARN_ON(ctx->siginfo)) - ctx->siginfo = NULL; - - if (resume != UTRACE_RESUME) { - WARN_ON(resume != UTRACE_BLOCKSTEP && - resume != UTRACE_SINGLESTEP); - - set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); - return UTRACE_STOP | UTRACE_SIGNAL_IGN; - } - - case UTRACE_SIGNAL_REPORT: - if (!ctx->siginfo) { - if (ctx->signr) { - /* set by ptrace_resume(SYSCALL_EXIT) */ - WARN_ON(ctx->signr != SIGTRAP); - ptrace_send_sigtrap(task, info); - } - - return resume | UTRACE_SIGNAL_IGN; - } - - if (WARN_ON(ctx->siginfo != info)) - return resume | UTRACE_SIGNAL_IGN; - - return resume | resume_signal(task, ctx, return_ka); - - default: - break; - } - - WARN_ON(ctx->siginfo); - ctx->siginfo = info; - /* - * ctx->siginfo points to the caller's stack. - * Make sure the subsequent UTRACE_SIGNAL_REPORT clears - * ->siginfo before return from get_signal_to_deliver(). - */ - utrace_control(task, engine, UTRACE_INTERRUPT); - - ctx->signr = info->si_signo; - ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; - - return UTRACE_STOP | UTRACE_SIGNAL_IGN; -} - -static u32 ptrace_report_quiesce(u32 action, - struct utrace_engine *engine, - struct task_struct *task, - unsigned long event) -{ - struct ptrace_context *ctx = ptrace_context(engine); - - if (ptrace_event_pending(ctx)) - return UTRACE_STOP; - - return event ? UTRACE_RESUME : ctx->resume; -} - -static void ptrace_release(void *data) -{ - kfree(data); -} - -static const struct utrace_engine_ops ptrace_utrace_ops = { - .report_signal = ptrace_report_signal, - .report_quiesce = ptrace_report_quiesce, - .report_exec = ptrace_report_exec, - .report_exit = ptrace_report_exit, - .report_clone = ptrace_report_clone, - .report_syscall_entry = ptrace_report_syscall_entry, - .report_syscall_exit = ptrace_report_syscall_exit, - .release = ptrace_release, -}; - -int ptrace_check_attach(struct task_struct *child, int kill) -{ - struct utrace_engine *engine; - struct utrace_examiner exam; - int ret = -ESRCH; - - engine = ptrace_lookup_engine(child); - if (IS_ERR(engine)) - return ret; - - if (child->parent != current) - goto out; - - if (unlikely(kill)) - ret = 0; - - if (!task_is_stopped_or_traced(child)) - goto out; - /* - * Make sure our engine has already stopped the child. - * Then wait for it to be off the CPU. - */ - if (!utrace_control(child, engine, UTRACE_STOP) && - !utrace_prepare_examine(child, engine, &exam)) - ret = 0; -out: - utrace_engine_put(engine); - return ret; -} - -int ptrace_attach(struct task_struct *task) -{ - int retval; - - audit_ptrace(task); - - retval = -EPERM; - if (unlikely(task->flags & PF_KTHREAD)) - goto out; - if (same_thread_group(task, current)) - goto out; - - /* - * Protect exec's credential calculations against our interference; - * interference; SUID, SGID and LSM creds get determined differently - * under ptrace. - */ - retval = -ERESTARTNOINTR; - if (mutex_lock_interruptible(&task->cred_guard_mutex)) - goto out; - - task_lock(task); - retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); - task_unlock(task); - if (retval) - goto unlock_creds; - - retval = ptrace_attach_task(task, 0); - if (unlikely(retval)) - goto unlock_creds; - - write_lock_irq(&tasklist_lock); - retval = -EPERM; - if (unlikely(task->exit_state)) - goto unlock_tasklist; - - BUG_ON(task->ptrace); - task->ptrace = PT_UTRACED; - if (capable(CAP_SYS_PTRACE)) - task->ptrace |= PT_PTRACE_CAP; - - __ptrace_link(task, current); - send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); - - retval = 0; -unlock_tasklist: - write_unlock_irq(&tasklist_lock); -unlock_creds: - mutex_unlock(&task->cred_guard_mutex); -out: - return retval; -} - -/* - * Performs checks and sets PT_UTRACED. - * Should be used by all ptrace implementations for PTRACE_TRACEME. - */ -int ptrace_traceme(void) -{ - bool detach = true; - int ret = ptrace_attach_task(current, 0); - - if (unlikely(ret)) - return ret; - - ret = -EPERM; - write_lock_irq(&tasklist_lock); - BUG_ON(current->ptrace); - ret = security_ptrace_traceme(current->parent); - /* - * Check PF_EXITING to ensure ->real_parent has not passed - * exit_ptrace(). Otherwise we don't report the error but - * pretend ->real_parent untraces us right after return. - */ - if (!ret && !(current->real_parent->flags & PF_EXITING)) { - current->ptrace = PT_UTRACED; - __ptrace_link(current, current->real_parent); - detach = false; - } - write_unlock_irq(&tasklist_lock); - - if (detach) - ptrace_abort_attach(current); - return ret; -} - -static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) -{ - bool detach, release; - - write_lock_irq(&tasklist_lock); - /* - * This tracee can be already killed. Make sure de_thread() or - * our sub-thread doing do_wait() didn't do release_task() yet. - */ - detach = tracee->ptrace != 0; - release = false; - if (likely(detach)) - release = __ptrace_detach(current, tracee); - write_unlock_irq(&tasklist_lock); - - if (unlikely(release)) - release_task(tracee); - else if (likely(detach)) - ptrace_detach_task(tracee, data); -} - -int ptrace_detach(struct task_struct *child, unsigned int data) -{ - if (!valid_signal(data)) - return -EIO; - - ptrace_do_detach(child, data); - - return 0; -} - -/* - * Detach all tasks we were using ptrace on. - */ -void exit_ptrace(struct task_struct *tracer) -{ - for (;;) { - struct task_struct *tracee = NULL; - - read_lock(&tasklist_lock); - if (!list_empty(&tracer->ptraced)) { - tracee = list_first_entry(&tracer->ptraced, - struct task_struct, ptrace_entry); - get_task_struct(tracee); - } - read_unlock(&tasklist_lock); - if (!tracee) - break; - - ptrace_do_detach(tracee, -1); - put_task_struct(tracee); - } -} - -static int ptrace_set_options(struct task_struct *tracee, - struct utrace_engine *engine, long data) -{ - BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); - - ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); - return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; -} - -static int ptrace_rw_siginfo(struct task_struct *tracee, - struct ptrace_context *ctx, - siginfo_t *info, bool write) -{ - unsigned long flags; - int err; - - switch (get_stop_event(ctx)) { - case 0: /* jctl stop */ - return -EINVAL; - - case PTRACE_EVENT_SIGNAL: - err = -ESRCH; - if (lock_task_sighand(tracee, &flags)) { - if (likely(task_is_traced(tracee))) { - if (write) - *ctx->siginfo = *info; - else - *info = *ctx->siginfo; - err = 0; - } - unlock_task_sighand(tracee, &flags); - } - - return err; - - default: - if (!write) { - memset(info, 0, sizeof(*info)); - info->si_signo = SIGTRAP; - info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; - info->si_pid = task_pid_vnr(tracee); - info->si_uid = task_uid(tracee); - } - - return 0; - } -} - -static void do_ptrace_notify_stop(struct ptrace_context *ctx, - struct task_struct *tracee) -{ - /* - * This can race with SIGKILL, but we borrow this race from - * the old ptrace implementation. ->exit_code is only needed - * for wait_task_stopped()->task_stopped_code(), we should - * change it to use ptrace_context. - */ - tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; - WARN_ON(!tracee->exit_code); - - read_lock(&tasklist_lock); - /* - * Don't want to allow preemption here, because - * sys_ptrace() needs this task to be inactive. - */ - preempt_disable(); - /* - * It can be killed and then released by our subthread, - * or ptrace_attach() has not completed yet. - */ - if (task_ptrace(tracee)) - do_notify_parent_cldstop(tracee, CLD_TRAPPED); - read_unlock(&tasklist_lock); - preempt_enable_no_resched(); -} - -void ptrace_notify_stop(struct task_struct *tracee) -{ - struct utrace_engine *engine = ptrace_lookup_engine(tracee); - - if (IS_ERR(engine)) - return; - - do_ptrace_notify_stop(ptrace_context(engine), tracee); - utrace_engine_put(engine); -} - -static int ptrace_resume_action(struct task_struct *tracee, - struct utrace_engine *engine, long request) -{ - struct ptrace_context *ctx = ptrace_context(engine); - unsigned long events; - int action; - - ctx->options &= ~PTRACE_O_SYSEMU; - events = engine->flags & ~UTRACE_EVENT_SYSCALL; - action = UTRACE_RESUME; - - switch (request) { -#ifdef PTRACE_SINGLEBLOCK - case PTRACE_SINGLEBLOCK: - if (unlikely(!arch_has_block_step())) - return -EIO; - action = UTRACE_BLOCKSTEP; - events |= UTRACE_EVENT(SYSCALL_EXIT); - break; -#endif - -#ifdef PTRACE_SINGLESTEP - case PTRACE_SINGLESTEP: - if (unlikely(!arch_has_single_step())) - return -EIO; - action = UTRACE_SINGLESTEP; - events |= UTRACE_EVENT(SYSCALL_EXIT); - break; -#endif - -#ifdef PTRACE_SYSEMU - case PTRACE_SYSEMU_SINGLESTEP: - if (unlikely(!arch_has_single_step())) - return -EIO; - action = UTRACE_SINGLESTEP; - case PTRACE_SYSEMU: - ctx->options |= PTRACE_O_SYSEMU; - events |= UTRACE_EVENT(SYSCALL_ENTRY); - break; -#endif - - case PTRACE_SYSCALL: - events |= UTRACE_EVENT_SYSCALL; - break; - - case PTRACE_CONT: - break; - default: - return -EIO; - } - - if (events != engine->flags && - utrace_set_events(tracee, engine, events)) - return -ESRCH; - - return action; -} - -static int ptrace_resume(struct task_struct *tracee, - struct utrace_engine *engine, - long request, long data) -{ - struct ptrace_context *ctx = ptrace_context(engine); - int action; - - if (!valid_signal(data)) - return -EIO; - - action = ptrace_resume_action(tracee, engine, request); - if (action < 0) - return action; - - switch (get_stop_event(ctx)) { - case PTRACE_EVENT_VFORK: - if (ctx->options & PTRACE_O_TRACEVFORKDONE) { - set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); - action = UTRACE_REPORT; - } - break; - - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_CLONE: - case PTRACE_EVENT_VFORK_DONE: - if (request == PTRACE_SYSCALL) { - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); - do_ptrace_notify_stop(ctx, tracee); - return 0; - } - - if (action != UTRACE_RESUME) { - /* - * single-stepping. UTRACE_SIGNAL_REPORT will - * synthesize a trap to follow the syscall insn. - */ - ctx->signr = SIGTRAP; - action = UTRACE_INTERRUPT; - } - break; - - case PTRACE_EVENT_SYSCALL_EXIT: - case PTRACE_EVENT_SYSCALL_ENTRY: - if (data) - send_sig_info(data, SEND_SIG_PRIV, tracee); - break; - - case PTRACE_EVENT_SIGNAL: - ctx->signr = data; - break; - } - - ctx->resume = action; - ptrace_wake_up(tracee, engine, action, true); - return 0; -} - -int ptrace_request(struct task_struct *child, long request, - long addr, long data) -{ - struct utrace_engine *engine = ptrace_lookup_engine(child); - siginfo_t siginfo; - int ret; - - if (unlikely(IS_ERR(engine))) - return -ESRCH; - - switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = generic_ptrace_peekdata(child, addr, data); - break; - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = generic_ptrace_pokedata(child, addr, data); - break; - -#ifdef PTRACE_OLDSETOPTIONS - case PTRACE_OLDSETOPTIONS: -#endif - case PTRACE_SETOPTIONS: - ret = ptrace_set_options(child, engine, data); - break; - case PTRACE_GETEVENTMSG: - ret = put_user(ptrace_context(engine)->eventmsg, - (unsigned long __user *) data); - break; - - case PTRACE_GETSIGINFO: - ret = ptrace_rw_siginfo(child, ptrace_context(engine), - &siginfo, false); - if (!ret) - ret = copy_siginfo_to_user((siginfo_t __user *) data, - &siginfo); - break; - - case PTRACE_SETSIGINFO: - if (copy_from_user(&siginfo, (siginfo_t __user *) data, - sizeof siginfo)) - ret = -EFAULT; - else - ret = ptrace_rw_siginfo(child, ptrace_context(engine), - &siginfo, true); - break; - - case PTRACE_DETACH: /* detach a process that was attached. */ - ret = ptrace_detach(child, data); - break; - - case PTRACE_KILL: - /* Ugly historical behaviour. */ - if (task_is_traced(child)) - ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); - ret = 0; - break; - - default: - ret = ptrace_resume(child, engine, request, data); - break; - } - - utrace_engine_put(engine); - return ret; -} - -#if defined CONFIG_COMPAT -int compat_ptrace_request(struct task_struct *child, compat_long_t request, - compat_ulong_t addr, compat_ulong_t data) -{ - struct utrace_engine *engine = ptrace_lookup_engine(child); - compat_ulong_t __user *datap = compat_ptr(data); - compat_ulong_t word; - siginfo_t siginfo; - int ret; - - if (unlikely(IS_ERR(engine))) - return -ESRCH; - - switch (request) { - case PTRACE_PEEKTEXT: - case PTRACE_PEEKDATA: - ret = access_process_vm(child, addr, &word, sizeof(word), 0); - if (ret != sizeof(word)) - ret = -EIO; - else - ret = put_user(word, datap); - break; - - case PTRACE_POKETEXT: - case PTRACE_POKEDATA: - ret = access_process_vm(child, addr, &data, sizeof(data), 1); - ret = (ret != sizeof(data) ? -EIO : 0); - break; - - case PTRACE_GETEVENTMSG: - ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, - datap); - break; - - case PTRACE_GETSIGINFO: - ret = ptrace_rw_siginfo(child, ptrace_context(engine), - &siginfo, false); - if (!ret) - ret = copy_siginfo_to_user32( - (struct compat_siginfo __user *) datap, - &siginfo); - break; - - case PTRACE_SETSIGINFO: - memset(&siginfo, 0, sizeof siginfo); - if (copy_siginfo_from_user32( - &siginfo, (struct compat_siginfo __user *) datap)) - ret = -EFAULT; - else - ret = ptrace_rw_siginfo(child, ptrace_context(engine), - &siginfo, true); - break; - - default: - ret = ptrace_request(child, request, addr, data); - } - - utrace_engine_put(engine); - return ret; -} -#endif /* CONFIG_COMPAT */ -- 1.5.5.1 From oleg at redhat.com Fri Nov 20 10:33:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 20 Nov 2009 11:33:26 +0100 Subject: [PATCH 0/4] utrace->resume fixes In-Reply-To: <20091119025927.EF35220E1@magilla.sf.frob.com> References: <20091119021551.GA10373@redhat.com> <20091119025927.EF35220E1@magilla.sf.frob.com> Message-ID: <20091120103326.GA31562@redhat.com> On 11/18, Roland McGrath wrote: > > So maybe you will look at this and merge them before I do. Whatever we do, perhaps it makes sense to apply your patch in https://www.redhat.com/archives/utrace-devel/2009-November/msg00109.html first and then do further changes? This way we will have the "working" utrace-ptrace branch which passes ptrace-tests at least, and we can ask Cai to do more testing. Oleg. From roland at redhat.com Fri Nov 20 22:47:36 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 20 Nov 2009 14:47:36 -0800 (PST) Subject: [PATCH 133] stepping, accommodate to utrace-cleanup changes In-Reply-To: Oleg Nesterov's message of Friday, 20 November 2009 05:02:49 +0100 <20091120040249.GA12739@redhat.com> References: <20091116165240.GA15153@redhat.com> <20091116231327.9F9801A2@magilla.sf.frob.com> <20091117220900.GB15906@redhat.com> <20091118114843.A5DAF29@magilla.sf.frob.com> <20091118214127.GA11214@redhat.com> <20091119020228.AB0831E2C@magilla.sf.frob.com> <20091120040249.GA12739@redhat.com> Message-ID: <20091120224736.B7954D8@magilla.sf.frob.com> > > The former is e.g. PTRACE_SINGLESTEP while an unrelated engine uses > > UTRACE_EVENT(SYSCALL_ENTRY). The ptrace engine's report_quiesce returns > > UTRACE_SINGLESTEP. finish_resume_report() calls user_enable_single_step(). > > That seems fine. Right? > > In this case ptrace_report_quiesce(event) returns UTRACE_RESUME, note > that it does > > return event ? UTRACE_RESUME : ctx->resume; > > and event == SYSCALL_ENTRY. This looks correct. With the utrace layer changes we're discussing, we need it to return UTRACE_SINGLESTEP (i.e. ctx->resume) here. AFAICT that never hurts even with today's utrace layer. > > I see. finish_resume_report() will only do utrace_stop() and then we'll > > go directly into the syscall unless someone used UTRACE_REPORT. > > Yes, > > > utrace_stop() will only set TIF_NOTIFY_RESUME and utrace->resume. In > > the real resume-to-user cases, that's fine because we'll handle that in > > utrace_resume() or utrace_get_signal() before doing anything else. > > Not sure I understand. utrace_stop() will not set TIF_NOTIFY_RESUME? > > We are talking about the case when the tracee stops in SYSCALL_ENTER, > and then the tracer does utrace_control(UTRACE_SINGLESTEP) to resume. > In this case utrace_control() sets ->resume/TIF_NOTIFY_RESUME, yes. I think you do understand fine. Yes, that's what it will do. I was just recognizing that this isn't enough in the syscall-entry case. > > this > > seems like the right idea for how to get tracehook_report_syscall_exit > > called in the cases where it is in old ptrace. > > Afaics yes. > > But, what if another engine does utrace_control(UTRACE_INTERRUPT) ? Hmm. Yes, I think this is the one case that is unlike all the others. That is, UTRACE_INTERRUPT at syscall-entry. In all other cases, nothing would care about utrace->resume until we get to get_signal_to_deliver anyway, where the UTRACE_SIGNAL_REPORT pass will trump any pending resume action anyway so you don't care that you lost track of it when UTRACE_INTERRUPT came in. Hmm. So what does UTRACE_INTERRUPT mean here anyway? It means that we should report "soon" and that signal_pending() should be true until that report. So today that means you can get into the syscall with signal_pending() and depending on the particular call that might cause a normal blocking path not to block and/or a -EINTR/-ERESTART* return, but some syscalls will just complete normally. How about if we say that UTRACE_INTERRUPT at syscall-entry means that the syscall really doesn't happen at all? That is, instead, you force an -ERESTARTNOHAND return and the normal roll-back such that you get your report_signal callback before the syscall is entered. That even seems like a useful utrace API feature, as well as conveniently smoothing over this quirk in the resume action handling. My idea here is that this makes it OK to lose UTRACE_SINGLESTEP here because from the user-mode-centric perspective no instruction has happened yet. The original guy who did UTRACE_SINGLESTEP (and perhaps never cared about syscall tracing) will get a generic report_quiesce or report_signal at which it needs to reassert UTRACE_SINGLESTEP. This merits more thought. For now, let's just leave an XXX comment about a UTRACE_INTERRUPT effectively swallowing the UTRACE_SINGLESTEP that should cause utrace_report_syscall_exit to be called. I think we can revisit this corner after we have merged up all the rest of it. > Argh. I meant, from the caller pov, utrace_control(UTRACE_SINGLESTEP) > does enable_step() "immediately", like it did before utrace-cleanup > changes. I see. From the utrace API perspective, I don't think anything changes here. In today's code, the resume action can take effect without a subsequent utrace callback. So that's the same as it ever was, and where this actually happens is not something that a utrace caller should know or can tell. > IOW, suppose the tracee is stopped, and ptrace does UTRACE_SINGLESTEP. > The tracee resumes, processes ->resume, and does enable_step(). > From the ptrace pov, it looks as if utrace_control() does enable_step() > before utrace_wakeup(). Sure. > I meant, every time the tracee stops, it should process ->resume > after wakeup. Looks like, the patch you sent in another thread > (which adds apply_resume_action()) does something like this, right? Right. Thanks, Roland From roland at redhat.com Fri Nov 20 22:55:11 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 20 Nov 2009 14:55:11 -0800 (PST) Subject: [PATCH 134] mv kernel/ptrace.c kernel/ptrace-utrace.c In-Reply-To: Oleg Nesterov's message of Friday, 20 November 2009 11:27:44 +0100 <20091120102744.GA31489@redhat.com> References: <20091120102744.GA31489@redhat.com> Message-ID: <20091120225511.6A3EDD8@magilla.sf.frob.com> > I am not sure what is the best way to do these renames but I hope > this doesn't really matter, utrace-ptrace branch is only for us. Sure, whatever you want to try is fine. > The goal is to make it testable with and without CONFIG_UTRACE. Ok. We need to get upstream feedback on what they do or don't want like that. Some people have definitely said they don't want to see two implementations in the tree at the same time. But I can never guess what they will say next week. You'll get the joy of hashing that out with them. :-) Thanks, Roland From roland at redhat.com Fri Nov 20 23:20:07 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 20 Nov 2009 15:20:07 -0800 (PST) Subject: [PATCH 0/4] utrace->resume fixes In-Reply-To: Oleg Nesterov's message of Friday, 20 November 2009 11:33:26 +0100 <20091120103326.GA31562@redhat.com> References: <20091119021551.GA10373@redhat.com> <20091119025927.EF35220E1@magilla.sf.frob.com> <20091120103326.GA31562@redhat.com> Message-ID: <20091120232007.B59EEC94F@magilla.sf.frob.com> > Whatever we do, perhaps it makes sense to apply your patch > in https://www.redhat.com/archives/utrace-devel/2009-November/msg00109.html > first and then do further changes? Ok. v2.6.32-rc8-245-g3d4f9cf has that. I'll shelve this 4-patch series while we keep discussing (one more reply to come from me as of now). Then you send me a fresh series done however you think is best given that discussion. (So if you want to do more relative to these 4 patches, just resend them as part of the new series.) Thanks, Roland From roland at redhat.com Sat Nov 21 00:00:39 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 20 Nov 2009 16:00:39 -0800 (PST) Subject: [PATCH 0/4] utrace->resume fixes In-Reply-To: Oleg Nesterov's message of Friday, 20 November 2009 07:25:58 +0100 <20091120062558.GA17019@redhat.com> References: <20091119021551.GA10373@redhat.com> <20091119025927.EF35220E1@magilla.sf.frob.com> <20091120062558.GA17019@redhat.com> Message-ID: <20091121000039.C3CC6C94F@magilla.sf.frob.com> > Somehow I can't really understand this patch. I hope more or less > I can see what it does, but the resulting code looks even more > subtle to me. Well, it was an untested draft and probably needed more comments. > With this patch, apply_resume_action() is always called after > utrace_stop(). Well, except for utrace_report_exit(), but I guess > it could do apply_resume_action() too. It could, but it just never matters at all. The only thing that can possibly be meaningful is UTRACE_INTERRUPT, and for that finish_report has set TIF_SIGPENDING already anyway. > Now it is not clear why utrace_control(SINGLESTEP) sets > TIF_NOTIFY_RESUME, it is not needed after apply_resume_action() > processes ->resume. Yes, we have jctl stops, but we can move > this code into utrace_finish_stop(). Yes, it is not really needed. But note that it is actually now possible to use UTRACE_SINGLESTEP without UTRACE_STOP first--not that it's really useful, but we don't really have any reason to disallow it. So in that case it does make a difference. We could just do: @@ -1183,7 +1183,8 @@ int utrace_control(struct task_struct *target, clear_engine_wants_stop(engine); if (action < utrace->resume) { utrace->resume = action; - set_notify_resume(target); + if (reset) + set_notify_resume(target); } break; Since TIF_NOTIFY_RESUME will now always be superfluous when stopped. > It is not clear to me why apply_resume_action(UTRACE_INTERRUPT) does > set_tsk_thread_flag(TIF_SIGPENDING). In fact I don't understand why > apply_resume_action() checks UTRACE_INTERRUPT at all. If it is called > after utrace_stop(), action == start_report() which never resets > UTRACE_INTERRUPT. It's only because this code path is shared with the tail of finish_resume_report, where it is the only thing processing UTRACE_INTERRUPT in the real return-to-user cases. i.e., in paths that don't call finish_report(), TIF_SIGPENDING won't ever have been set by a callback return value. utrace_control does always set it up front, so it is superfluous when that's how UTRACE_INTERRUPT got set. > And since we process ->resume after stop, it is not clear why we > set ->resume = report->resume_action before stop, apply_resume_action() > could use min(report->resume_action, utrace->resume). Yes, yes, > we have the nasty utrace->vfork_stop case, I mean it is not easy to > understand the logic behind all these ->resume changes. Ok. Feel free to clean it up if you think it makes things clearer. To me, it's just natural to do that MIN operation as soon as you know about it. utrace_stop() always takes the lock anyway, so it's relatively free. If the ambient state is stored early, then e.g. utrace_control() won't bother to set TIF_SIGPENDING or TIF_NOTIFY_RESUME. I guess I think the logic is simple: apply a new minimum to ->resume as soon as you know about it. > And afaics, this can't help to fix the tracehook_report_syscall_exit() > && TIF_SINGLESTEP problems in the multitracing case, UTRACE_INTERRUPT > "destroys" UTRACE_SINGLESTEP. Ptrace can reassert it later, but this > will be too late, the trace has already passed this tracehook. See the other thread, but what I said there is let's take this case up in its own thread later. > I don't understand this skip_notify, utrace_stop() is always called > with skip_notify == true? Hmm. Yes, this patch was unfinished when I sent it because your patches were crossing paths with what I was doing. We can skip TIF_NOTIFY_RESUME when we'll always call apply_resume_action() after utrace_stop() before user mode (i.e. report_exit doesn't matter). Since report_exit doesn't matter one way or the other, perhaps it will be cleaner to roll apply_resume_action() into utrace_stop() in some fashion. I notice we're now actually using the REPORT() macro only four times, and one of those is report_exit. So maybe that and finish_report() could change somehow too to refactor things. I'll leave it to you to rework all those and finish_* to the most useful organization of subroutines. I think we're mutually clear now on the idea of when to do user_*_step() calls (i.e. apply_resume_action). Thanks, Roland From fche at redhat.com Sat Nov 21 19:47:47 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Sat, 21 Nov 2009 14:47:47 -0500 Subject: systemtap PR10171, itrace crashes Message-ID: <20091121194747.GD29296@redhat.com> Hi - itrace is a utrace engine included in the systemtap runtime that activates UTRACE_SINGLESTEP / BLOCKSTEP on targeted userspace processes. It seems to work OK on ppc64, but crashes lots on recent fedora (inc. rawhide) level utrace on x86/x86-64. (Lately I've been unable to boot a utrace/master branch version of the kernel to try it against.) The systemtap code is at git://sourceware.org/git/systemtap.git, master branch for the near-original code, pr10653-itrace-crashes branch for a partial rewrite. The key file is runtime/itrace.c. tapsets-itrace.cxx generates code that calls into this for new or dying threads. The crash is now intermittent (an "improvement" over a near-100% crash on rawhide x86 machines), and is triggered with a systemtap testsuite run thusly: % configure ... ; make; make install # build systemtap % sudo make installcheck RUNTESTFLAGS=itrace.exp While hacking up my near-rewritten form of runtime/itrace.c, I came across several cases where utrace made calls on our engine seemingly long after a UTRACE_DETACH was to take effect. This included cases where a signal or other reporting callback had already returned UTRACE_DETACH, or after a debugging task seemingly completed a utrace_control(DETACH). So I added hack after hack, using engine->data as an indication that someone else has already requested a DETACH, and to keep echoing that back to utrace until it "takes". (Maybe it's a bug in x86 single-stepping logic that didn't appear on ppc. Dunno. We've also had to disable itrace on ia64 for suspicious crashes that may also be the same problem. sourceware.org/PR10171 and /PR10653.) Could you guys take a look at old/new runtime/itrace.c, to see what the code's trying to do with utrace? Do you have a utrace/master-level kernel handy to try it on? I don't understand why any of these hacks are supposed to be necessary. A typical kernel crash log follows (3-cpu virtual machine). Sometimes this triggers somewhat *after* the systemtap session has completed, up to and including unloading of the runtime/itrace.c-containing module. [ 634.676957] stap_198c84f334a07f5b8157be1fd1be6bec_1461: systemtap: 1.0/0.143, base: fa97b000, memory: 16305+20172+1344+13600 data+text+ctx+net, probes: 5 [ 634.926718] [ 634.926719] ============================================= [ 634.927113] [ INFO: possible recursive locking detected ] [ 634.927113] 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 634.927113] --------------------------------------------- [ 634.927113] ls_5066/5705 is trying to acquire lock: [ 634.927113] (&sighand->siglock){......}, at: [] get_signal_to_deliver+0x5c/0x344 [ 634.927113] [ 634.927113] but task is already holding lock: [ 634.927113] (&sighand->siglock){......}, at: [] utrace_get_signal+0x50b/0x53d [ 634.927113] [ 634.927113] other info that might help us debug this: [ 634.927113] 1 lock held by ls_5066/5705: [ 634.927113] #0: (&sighand->siglock){......}, at: [] utrace_get_signal+0x50b/0x53d [ 634.927113] [ 634.927113] stack backtrace: [ 634.927113] Pid: 5705, comm: ls_5066 Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 634.927113] Call Trace: [ 634.927113] [] ? printk+0x14/0x1b [ 634.927113] [] __lock_acquire+0x833/0xb6f [ 634.927113] [] ? utrace_get_signal+0x50b/0x53d [ 634.927113] [] lock_acquire+0x93/0xb1 [ 634.927113] [] ? get_signal_to_deliver+0x5c/0x344 [ 634.927113] [] _spin_lock_irq+0x2e/0x5e [ 634.927113] [] ? get_signal_to_deliver+0x5c/0x344 [ 634.927113] [] get_signal_to_deliver+0x5c/0x344 [ 634.927113] [] do_signal+0x5f/0x703 [ 634.927113] [] ? force_sig_info+0xa2/0xac [ 634.927113] [] ? kprobe_exceptions_notify+0xe/0x43c [ 634.927113] [] ? send_sigtrap+0x6d/0x74 [ 634.927113] [] do_notify_resume+0x27/0x77 [ 634.927113] [] work_notifysig+0x13/0x1b [ 639.001030] BUG: spinlock lockup on CPU#3, ls_5066/5705, ec094704 (Not tainted) [ 818.430111] Pid: 5705, comm: ls_5066 Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 818.433097] Call Trace: [ 818.435096] [] ? printk+0x14/0x1b [ 818.437097] [] _raw_spin_lock+0x102/0x128 [ 818.439096] [] _spin_lock_irq+0x4d/0x5e [ 818.441097] [] get_signal_to_deliver+0x5c/0x344 [ 818.541097] [] do_signal+0x5f/0x703 [ 818.543096] [] ? force_sig_info+0xa2/0xac [ 818.545097] [] ? kprobe_exceptions_notify+0xe/0x43c [ 818.547096] [] ? send_sigtrap+0x6d/0x74 [ 818.549097] [] do_notify_resume+0x27/0x77 [ 818.551312] [] work_notifysig+0x13/0x1b [ 818.553097] sending NMI to all CPUs: [ 818.555096] NMI backtrace for cpu 3 [ 818.555096] [ 818.555096] Pid: 5705, comm: ls_5066 Not tainted (2.6.32-0.48.rc7.git1.fc13.i686 #1) [ 818.555096] EIP: 0060:[] EFLAGS: 00210046 CPU: 3 [ 818.555096] EIP is at __default_send_IPI_dest_field+0x5f/0x64 [ 818.555096] EAX: 00000c00 EBX: 0f000000 ECX: 00000800 EDX: fffff000 [ 818.555096] ESI: 00000002 EDI: 00000c00 EBP: eb601e08 ESP: eb601dfc [ 818.555096] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 818.555096] CR0: 8005003b CR2: 00ac3eac CR3: 2a44d000 CR4: 000006d0 [ 818.555096] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 818.555096] DR6: ffff4ff0 DR7: 00000400 [ 818.555096] Call Trace: [ 818.555096] [] default_send_IPI_mask_logical+0x80/0xac [ 818.555096] [] default_send_IPI_all+0x27/0x68 [ 818.555096] [] arch_trigger_all_cpu_backtrace+0x32/0x54 [ 818.555096] [] _raw_spin_lock+0x107/0x128 [ 818.555096] [] _spin_lock_irq+0x4d/0x5e [ 818.555096] [] get_signal_to_deliver+0x5c/0x344 [ 818.555096] [] do_signal+0x5f/0x703 [ 818.555096] [] ? force_sig_info+0xa2/0xac [ 818.555096] [] ? kprobe_exceptions_notify+0xe/0x43c [ 818.555096] [] ? send_sigtrap+0x6d/0x74 [ 818.555096] [] do_notify_resume+0x27/0x77 [ 818.555096] [] work_notifysig+0x13/0x1b [ 818.555096] Pid: 5705, comm: ls_5066 Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 818.555096] Call Trace: [ 818.555096] [] ? show_regs+0x24/0x2a [ 818.555096] [] nmi_watchdog_tick+0x9d/0x171 [ 818.555096] [] do_nmi+0xa8/0x289 [ 818.555096] [] nmi_stack_correct+0x2f/0x34 [ 818.555096] [] ? do_machine_check+0x683/0x6ec [ 818.555096] [] ? do_machine_check+0x6e8/0x6ec [ 818.555096] [] ? __default_send_IPI_dest_field+0x5f/0x64 [ 818.555096] [] default_send_IPI_mask_logical+0x80/0xac [ 818.555096] [] default_send_IPI_all+0x27/0x68 [ 818.555096] [] arch_trigger_all_cpu_backtrace+0x32/0x54 [ 818.555096] [] _raw_spin_lock+0x107/0x128 [ 818.555096] [] _spin_lock_irq+0x4d/0x5e [ 818.555096] [] get_signal_to_deliver+0x5c/0x344 [ 818.555096] [] do_signal+0x5f/0x703 [ 818.555096] [] ? force_sig_info+0xa2/0xac [ 818.555096] [] ? kprobe_exceptions_notify+0xe/0x43c [ 818.555096] [] ? send_sigtrap+0x6d/0x74 [ 818.555096] [] do_notify_resume+0x27/0x77 [ 818.555096] [] work_notifysig+0x13/0x1b [ 818.556078] NMI backtrace for cpu 2 [ 818.556078] [ 818.556078] Pid: 0, comm: swapper Not tainted (2.6.32-0.48.rc7.git1.fc13.i686 #1) [ 818.556078] EIP: 0060:[] EFLAGS: 00000246 CPU: 2 [ 818.556078] EIP is at native_safe_halt+0xa/0xc [ 818.556078] EAX: c0409645 EBX: c0a3301c ECX: f6d02ba0 EDX: 00000000 [ 818.556078] ESI: 00000002 EDI: 00000000 EBP: f6cfff78 ESP: f6cfff78 [ 818.556078] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 818.556078] CR0: 8005003b CR2: b76be000 CR3: 27f2e000 CR4: 000006d0 [ 818.556078] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 818.556078] DR6: ffff0ff0 DR7: 00000400 [ 818.556078] Call Trace: [ 818.556078] [] default_idle+0x44/0x6e [ 818.556078] [] cpu_idle+0x9b/0xb4 [ 818.556078] [] start_secondary+0x204/0x242 [ 818.556078] Pid: 0, comm: swapper Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 818.556078] Call Trace: [ 818.556078] [] ? show_regs+0x24/0x2a [ 818.556078] [] nmi_watchdog_tick+0x9d/0x171 [ 818.556078] [] do_nmi+0xa8/0x289 [ 818.556078] [] nmi_stack_correct+0x2f/0x34 [ 818.556078] [] ? default_idle+0x3f/0x6e [ 818.556078] [] ? default_idle+0x3f/0x6e [ 818.556078] [] ? native_safe_halt+0xa/0xc [ 818.556078] [] default_idle+0x44/0x6e [ 818.556078] [] cpu_idle+0x9b/0xb4 [ 818.556078] [] start_secondary+0x204/0x242 [ 634.927053] NMI backtrace for cpu 1 [ 634.927053] [ 634.927053] Pid: 5698, comm: stapio Not tainted (2.6.32-0.48.rc7.git1.fc13.i686 #1) [ 634.927053] EIP: 0060:[] EFLAGS: 00200096 CPU: 1 [ 634.927053] EIP is at delay_tsc+0x1f/0x66 [ 634.927053] EAX: b833d718 EBX: 00000001 ECX: 00000001 EDX: 00033e0e [ 634.927053] ESI: 00000001 EDI: 00000000 EBP: ea53fe6c ESP: ea53fe5c [ 634.927053] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 634.927053] CR0: 8005003b CR2: 08f862b8 CR3: 27f2e000 CR4: 000006d0 [ 634.927053] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 634.927053] DR6: ffff0ff0 DR7: 00000400 [ 634.927053] Call Trace: [ 634.927053] [] __delay+0xe/0x10 [ 634.927053] [] _raw_spin_lock+0xbb/0x128 [ 634.927053] [] _spin_lock_irq+0x4d/0x5e [ 634.927053] [] utrace_do_stop+0x1e/0x75 [ 634.927053] [] utrace_control+0xc9/0x1b8 [ 634.927053] [] stap_utrace_detach+0x92/0xef [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_utrace_detach_ops+0x2a/0x81 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_stop_task_finder+0x5e/0xf2 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_cleanup_and_exit+0x6b/0x1b3 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_ctl_write_cmd+0x790/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] ? rcu_read_unlock+0x0/0x1e [ 634.927053] [] ? selinux_file_permission+0x4f/0x96 [ 634.927053] [] ? security_file_permission+0x14/0x16 [ 634.927053] [] ? rw_verify_area+0x9d/0xc0 [ 634.927053] [] ? _stp_ctl_write_cmd+0x0/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] vfs_write+0x85/0xe4 [ 634.927053] [] sys_write+0x40/0x62 [ 634.927053] [] syscall_call+0x7/0xb [ 634.927053] Pid: 5698, comm: stapio Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 634.927053] EAX: b833d718 EBX: 00000001 ECX: 00000001 EDX: 00033e0e [ 634.927053] ESI: 00000001 EDI: 00000000 EBP: ea53fe6c ESP: ea53fe5c [ 634.927053] DS: 007b ES: 007b FS: 00d8 GS: 00e0 SS: 0068 [ 634.927053] CR0: 8005003b CR2: 08f862b8 CR3: 27f2e000 CR4: 000006d0 [ 634.927053] DR0: 00000000 DR1: 00000000 DR2: 00000000 DR3: 00000000 [ 634.927053] DR6: ffff0ff0 DR7: 00000400 [ 634.927053] Call Trace: [ 634.927053] [] __delay+0xe/0x10 [ 634.927053] [] _raw_spin_lock+0xbb/0x128 [ 634.927053] [] _spin_lock_irq+0x4d/0x5e [ 634.927053] [] utrace_do_stop+0x1e/0x75 [ 634.927053] [] utrace_control+0xc9/0x1b8 [ 634.927053] [] stap_utrace_detach+0x92/0xef [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_utrace_detach_ops+0x2a/0x81 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_stop_task_finder+0x5e/0xf2 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_cleanup_and_exit+0x6b/0x1b3 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_ctl_write_cmd+0x790/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] ? rcu_read_unlock+0x0/0x1e [ 634.927053] [] ? selinux_file_permission+0x4f/0x96 [ 634.927053] [] ? security_file_permission+0x14/0x16 [ 634.927053] [] ? rw_verify_area+0x9d/0xc0 [ 634.927053] [] ? _stp_ctl_write_cmd+0x0/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] vfs_write+0x85/0xe4 [ 634.927053] [] sys_write+0x40/0x62 [ 634.927053] [] syscall_call+0x7/0xb [ 634.927053] Pid: 5698, comm: stapio Not tainted 2.6.32-0.48.rc7.git1.fc13.i686 #1 [ 634.927053] Call Trace: [ 634.927053] [] ? show_regs+0x24/0x2a [ 634.927053] [] nmi_watchdog_tick+0x9d/0x171 [ 634.927053] [] do_nmi+0xa8/0x289 [ 634.927053] [] nmi_stack_correct+0x2f/0x34 [ 634.927053] [] ? ktime_get_ts+0x33/0xa2 [ 634.927053] [] ? delay_tsc+0x1f/0x66 [ 634.927053] [] __delay+0xe/0x10 [ 634.927053] [] _raw_spin_lock+0xbb/0x128 [ 634.927053] [] _spin_lock_irq+0x4d/0x5e [ 634.927053] [] utrace_do_stop+0x1e/0x75 [ 634.927053] [] utrace_control+0xc9/0x1b8 [ 634.927053] [] stap_utrace_detach+0x92/0xef [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_utrace_detach_ops+0x2a/0x81 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] stap_stop_task_finder+0x5e/0xf2 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_cleanup_and_exit+0x6b/0x1b3 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] _stp_ctl_write_cmd+0x790/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] ? rcu_read_unlock+0x0/0x1e [ 634.927053] [] ? selinux_file_permission+0x4f/0x96 [ 634.927053] [] ? security_file_permission+0x14/0x16 [ 634.927053] [] ? rw_verify_area+0x9d/0xc0 [ 634.927053] [] ? _stp_ctl_write_cmd+0x0/0x909 [stap_198c84f334a07f5b8157be1fd1be6bec_1461] [ 634.927053] [] vfs_write+0x85/0xe4 [ 634.927053] [] sys_write+0x40/0x62 [ 634.927053] [] syscall_call+0x7/0xb [ 819.261347] NMI backtrace for cpu 0 [ 819.261347] [ 819.261347] Pid: 0, comm: swapper Not tainted (2.6.32-0.48.rc7.git1.fc13.i686 #1) [ 819.261347] EIP: 0060:[] EFLAGS: 00000246 CPU: 0 [ 819.261347] EIP is at native_safe_hal From oleg at redhat.com Sun Nov 22 16:45:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:33 +0100 Subject: [PATCH 135-139] restore the old ptrace code in utrace-ptrace branch Message-ID: <20091122164533.GA28896@redhat.com> >From now utrace-ptrace branch works with or without CONFIG_UTRACE. Modulo futher fixes, I hope from now utrace-ptrace represents the code we are going to send for review and upstream. Oleg. From oleg at redhat.com Sun Nov 22 16:45:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:36 +0100 Subject: [PATCH 135] restore the old kernel/ptrace.c Message-ID: <20091122164536.GA28900@redhat.com> Restore the old kernel/ptrace.c. --- kernel/ptrace.c | 764 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 764 insertions(+) --- /dev/null 2009-11-21 14:04:55.632015473 +0100 +++ UTRACE-PTRACE/kernel/ptrace.c 2009-09-24 21:38:54.000000000 +0200 @@ -0,0 +1,764 @@ +/* + * linux/kernel/ptrace.c + * + * (C) Copyright 1999 Linus Torvalds + * + * Common interfaces for "ptrace()" which we do not want + * to continually duplicate across every architecture. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * 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; +} + +/* + * Turn a tracing stop into a normal stop now, since with no tracer there + * would be no way to wake it up with SIGCONT or SIGKILL. If there was a + * signal sent that would resume the child, but didn't because it was in + * TASK_TRACED, resume it now. + * Requires that irqs be disabled. + */ +static void ptrace_untrace(struct task_struct *child) +{ + spin_lock(&child->sighand->siglock); + if (task_is_traced(child)) { + /* + * If the group stop is completed or in progress, + * this thread was already counted as stopped. + */ + if (child->signal->flags & SIGNAL_STOP_STOPPED || + child->signal->group_stop_count) + __set_task_state(child, TASK_STOPPED); + else + signal_wake_up(child, 1); + } + spin_unlock(&child->sighand->siglock); +} + +/* + * 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); + if (task_is_traced(child)) + ptrace_untrace(child); +} + +/* + * Check that we have indeed attached to the thing.. + */ +int ptrace_check_attach(struct task_struct *child, int kill) +{ + int ret = -ESRCH; + + /* + * We take the read lock around doing both checks to close a + * possible race where someone else was tracing our child and + * detached between these two checks. After this locked check, + * we are sure that this is our traced child and that can only + * be changed by us so it's not changing right after this. + */ + read_lock(&tasklist_lock); + if ((child->ptrace & PT_PTRACED) && child->parent == current) { + ret = 0; + /* + * child->sighand can't be NULL, release_task() + * does ptrace_unlink() before __exit_signal(). + */ + spin_lock_irq(&child->sighand->siglock); + if (task_is_stopped(child)) + child->state = TASK_TRACED; + else if (!task_is_traced(child) && !kill) + ret = -ESRCH; + spin_unlock_irq(&child->sighand->siglock); + } + read_unlock(&tasklist_lock); + + if (!ret && !kill) + ret = wait_task_inactive(child, TASK_TRACED) ? 0 : -ESRCH; + + /* All systems go.. */ + return ret; +} + +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + if (task->ptrace) + goto unlock_tasklist; + + task->ptrace = PT_PTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/** + * ptrace_traceme -- helper for PTRACE_TRACEME + * + * Performs checks and sets PT_PTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + int ret = -EPERM; + + write_lock_irq(&tasklist_lock); + /* Are we already being traced? */ + if (!current->ptrace) { + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_PTRACED; + __ptrace_link(current, current->real_parent); + } + } + write_unlock_irq(&tasklist_lock); + + return ret; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + bool dead = false; + + if (!valid_signal(data)) + return -EIO; + + /* Architecture-specific hardware disable .. */ + ptrace_disable(child); + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + + write_lock_irq(&tasklist_lock); + /* + * This child can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + if (child->ptrace) { + child->exit_code = data; + dead = __ptrace_detach(current, child); + if (!child->exit_state) + wake_up_process(child); + } + write_unlock_irq(&tasklist_lock); + + if (unlikely(dead)) + release_task(child); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + struct task_struct *p, *n; + LIST_HEAD(ptrace_dead); + + write_lock_irq(&tasklist_lock); + list_for_each_entry_safe(p, n, &tracer->ptraced, ptrace_entry) { + if (__ptrace_detach(tracer, p)) + list_add(&p->ptrace_entry, &ptrace_dead); + } + write_unlock_irq(&tasklist_lock); + + BUG_ON(!list_empty(&tracer->ptraced)); + + list_for_each_entry_safe(p, n, &ptrace_dead, ptrace_entry) { + list_del_init(&p->ptrace_entry); + release_task(p); + } +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static int ptrace_setoptions(struct task_struct *child, long data) +{ + child->ptrace &= ~PT_TRACE_MASK; + + if (data & PTRACE_O_TRACESYSGOOD) + child->ptrace |= PT_TRACESYSGOOD; + + if (data & PTRACE_O_TRACEFORK) + child->ptrace |= PT_TRACE_FORK; + + if (data & PTRACE_O_TRACEVFORK) + child->ptrace |= PT_TRACE_VFORK; + + if (data & PTRACE_O_TRACECLONE) + child->ptrace |= PT_TRACE_CLONE; + + if (data & PTRACE_O_TRACEEXEC) + child->ptrace |= PT_TRACE_EXEC; + + if (data & PTRACE_O_TRACEVFORKDONE) + child->ptrace |= PT_TRACE_VFORK_DONE; + + if (data & PTRACE_O_TRACEEXIT) + child->ptrace |= PT_TRACE_EXIT; + + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_getsiginfo(struct task_struct *child, siginfo_t *info) +{ + unsigned long flags; + int error = -ESRCH; + + if (lock_task_sighand(child, &flags)) { + error = -EINVAL; + if (likely(child->last_siginfo != NULL)) { + *info = *child->last_siginfo; + error = 0; + } + unlock_task_sighand(child, &flags); + } + return error; +} + +static int ptrace_setsiginfo(struct task_struct *child, const siginfo_t *info) +{ + unsigned long flags; + int error = -ESRCH; + + if (lock_task_sighand(child, &flags)) { + error = -EINVAL; + if (likely(child->last_siginfo != NULL)) { + *child->last_siginfo = *info; + error = 0; + } + unlock_task_sighand(child, &flags); + } + return error; +} + + +#ifdef PTRACE_SINGLESTEP +#define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) +#else +#define is_singlestep(request) 0 +#endif + +#ifdef PTRACE_SINGLEBLOCK +#define is_singleblock(request) ((request) == PTRACE_SINGLEBLOCK) +#else +#define is_singleblock(request) 0 +#endif + +#ifdef PTRACE_SYSEMU +#define is_sysemu_singlestep(request) ((request) == PTRACE_SYSEMU_SINGLESTEP) +#else +#define is_sysemu_singlestep(request) 0 +#endif + +static int ptrace_resume(struct task_struct *child, long request, long data) +{ + if (!valid_signal(data)) + return -EIO; + + if (request == PTRACE_SYSCALL) + set_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_TRACE); + +#ifdef TIF_SYSCALL_EMU + if (request == PTRACE_SYSEMU || request == PTRACE_SYSEMU_SINGLESTEP) + set_tsk_thread_flag(child, TIF_SYSCALL_EMU); + else + clear_tsk_thread_flag(child, TIF_SYSCALL_EMU); +#endif + + if (is_singleblock(request)) { + if (unlikely(!arch_has_block_step())) + return -EIO; + user_enable_block_step(child); + } else if (is_singlestep(request) || is_sysemu_singlestep(request)) { + if (unlikely(!arch_has_single_step())) + return -EIO; + user_enable_single_step(child); + } else { + user_disable_single_step(child); + } + + child->exit_code = data; + wake_up_process(child); + + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + int ret = -EIO; + siginfo_t siginfo; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + return generic_ptrace_peekdata(child, addr, data); + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + return generic_ptrace_pokedata(child, addr, data); + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_setoptions(child, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(child->ptrace_message, (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_getsiginfo(child, &siginfo); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_setsiginfo(child, &siginfo); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: +#endif +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: +#endif +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU: + case PTRACE_SYSEMU_SINGLESTEP: +#endif + case PTRACE_SYSCALL: + case PTRACE_CONT: + return ptrace_resume(child, request, data); + + case PTRACE_KILL: + if (child->exit_state) /* already dead */ + return 0; + return ptrace_resume(child, request, SIGKILL); + + default: + break; + } + + return ret; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t) child->ptrace_message, datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_getsiginfo(child, &siginfo); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_setsiginfo(child, &siginfo); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + return ret; +} + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ From oleg at redhat.com Sun Nov 22 16:45:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:38 +0100 Subject: [PATCH 136] (upstream) reorder the code in kernel/ptrace.c Message-ID: <20091122164538.GA28907@redhat.com> No functional changes. Move the code which can be shared with utrace-ptrace up, before __ptrace_link(). --- kernel/ptrace.c | 556 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 278 insertions(+), 278 deletions(-) --- UTRACE-PTRACE/kernel/ptrace.c~136_REORDER_FUNCS 2009-09-24 21:38:54.000000000 +0200 +++ UTRACE-PTRACE/kernel/ptrace.c 2009-11-21 21:41:41.000000000 +0100 @@ -23,6 +23,284 @@ #include #include +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ /* * ptrace a task: make the debugger its new parent and @@ -117,53 +395,6 @@ int ptrace_check_attach(struct task_stru return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -243,57 +474,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; @@ -347,56 +527,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -457,7 +587,6 @@ static int ptrace_setsiginfo(struct task return error; } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -580,93 +709,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -718,47 +761,4 @@ int compat_ptrace_request(struct task_st return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Sun Nov 22 16:45:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:41 +0100 Subject: [PATCH 137] export __ptrace_detach(), add "ifndef CONFIG_UTRACE" into ptrace.c Message-ID: <20091122164541.GA28910@redhat.com> No functional changes. Export __ptrace_detach() and add "ifndef CONFIG_UTRACE" into ptrace.c around the code re-implemented by utrace-ptrace. --- include/linux/ptrace.h | 1 + kernel/ptrace.c | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) --- UTRACE-PTRACE/include/linux/ptrace.h~137_PTRACE_CONFIG_UTRACE 2009-11-16 18:30:26.000000000 +0100 +++ UTRACE-PTRACE/include/linux/ptrace.h 2009-11-21 21:59:17.000000000 +0100 @@ -85,6 +85,7 @@ extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); +extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee); extern int ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); --- UTRACE-PTRACE/kernel/ptrace.c~137_PTRACE_CONFIG_UTRACE 2009-11-21 21:41:41.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace.c 2009-11-21 22:01:22.000000000 +0100 @@ -98,7 +98,7 @@ static int ignoring_children(struct sigh * reap it now, in that case we must also wake up sub-threads sleeping in * do_wait(). */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) { __ptrace_unlink(p); @@ -302,6 +302,7 @@ asmlinkage long compat_sys_ptrace(compat } #endif /* CONFIG_COMPAT */ +#ifndef CONFIG_UTRACE /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -762,3 +763,4 @@ int compat_ptrace_request(struct task_st return ret; } #endif /* CONFIG_COMPAT */ +#endif /* CONFIG_UTRACE */ From oleg at redhat.com Sun Nov 22 16:45:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:43 +0100 Subject: [PATCH 138] rm kernel/ptrace-common.h Message-ID: <20091122164543.GA28917@redhat.com> Kill kernel/ptrace-common.h, this code lives in kernel/ptrace.c above "#ifndef CONFIG_UTRACE". --- kernel/ptrace-utrace.c | 3 kernel/ptrace-common.h | 278 ------------------------------------------------- 2 files changed, 2 insertions(+), 279 deletions(-) --- UTRACE-PTRACE/kernel/ptrace-utrace.c~138_KILL_PTRACE_COMMON 2009-11-21 21:47:11.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace-utrace.c 2009-11-21 22:15:51.000000000 +0100 @@ -23,7 +23,6 @@ #include #include #include -#include "ptrace-common.h" /* * ptrace a task: make the debugger its new parent and @@ -1055,6 +1054,8 @@ int ptrace_request(struct task_struct *c } #if defined CONFIG_COMPAT +#include + int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { --- UTRACE-PTRACE/kernel/ptrace-common.h +++ /dev/null @@ -1,278 +0,0 @@ -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - -#if defined CONFIG_COMPAT -#include - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} -#endif /* CONFIG_COMPAT */ From oleg at redhat.com Sun Nov 22 16:45:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 17:45:46 +0100 Subject: [PATCH 139] kill CONFIG_UTRACE_PTRACE Message-ID: <20091122164546.GA28921@redhat.com> If I understand correctly, we are not going to have CONFIG_UTRACE_PTRACE, CONFIG_UTRACE should use utrace-ptrace unconditionally. Remove CONFIG_UTRACE_PTRACE. I do not know where is the right place for CONFIG_UTRACE option and what the help text should say, I assume you can fix this patch or make the necessary changes on top. --- init/Kconfig | 20 +------------------- kernel/utrace.c | 2 -- 2 files changed, 1 insertion(+), 21 deletions(-) --- UTRACE-PTRACE/init/Kconfig~139_KILL_CONFIG_UTRACE_PTRACE 2009-11-13 18:00:06.000000000 +0100 +++ UTRACE-PTRACE/init/Kconfig 2009-11-22 17:05:10.000000000 +0100 @@ -1205,7 +1205,7 @@ config STOP_MACHINE help Need stop_machine() primitive. -menuconfig UTRACE +config UTRACE bool "Infrastructure for tracing and debugging user processes" depends on EXPERIMENTAL depends on HAVE_ARCH_TRACEHOOK @@ -1214,24 +1214,6 @@ menuconfig UTRACE kernel interface exported to kernel modules, to track events in user threads, extract and change user thread state. -config UTRACE_PTRACE - bool "utrace-based ptrace (EXPERIMENTAL)" - default y if UTRACE - depends on UTRACE - help - This changes the implementation of ptrace() to cooperate with the - utrace facility. Without this option, using any utrace facility - on a task that anything also uses ptrace() on (i.e. usual - debuggers, strace, etc) fails with -EBUSY; likewise, if utrace is - in use on a task, the ptrace() system call on that task will fail - with EBUSY. With this option, the ptrace() implementation is - changed to work via utrace facilities and the two cooperate well. - - It's recommended to enable this if you are experimenting with - new modules that use utrace. But, disabling it makes sure that - using traditional ptrace() on tasks not touched by utrace will - not use any experimental new code that might be unreliable. - source "block/Kconfig" config PREEMPT_NOTIFIERS --- UTRACE-PTRACE/kernel/utrace.c~139_KILL_CONFIG_UTRACE_PTRACE 2009-11-21 15:12:27.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-11-21 22:41:01.000000000 +0100 @@ -897,7 +897,6 @@ relock: spin_unlock_irq(&task->sighand->siglock); spin_unlock(&utrace->lock); -#ifdef CONFIG_UTRACE_PTRACE /* * If ptrace is among the reasons for this stop, do its * notification now. This could not just be done in @@ -906,7 +905,6 @@ relock: * synchronization with ptrace_do_wait() work right. */ ptrace_notify_stop(task); -#endif schedule(); From oleg at redhat.com Sun Nov 22 22:12:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:24 +0100 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review Message-ID: <20091122221224.GA8674@redhat.com> Roland, this is what I am going to send for review. Any objections? 1-7 are already in -mm tree, I am sending them to simplify the review. 8-12 doesn't change the behaviour, simple preaparations. Perhaps we should send 8-10 to akpm right now? 13 adds kernel/ptrace-utrace.c NOTE! This series assumes utrace.patch comes next, after utrace-ptrace. This way we can avoid "exclude_ptrace" hacks in ptrace.c, but I am not sure this is good idea. Up to you. Just in case, please find below your utrace.patch re-diffed against this series, it doesn't touch ptrace.c and comes with ptrace_notify_stop() in utrace_stop(). Oleg. --- V1/Documentation/DocBook/Makefile~__UTRACE 2009-09-22 00:42:54.000000000 +0200 +++ V1/Documentation/DocBook/Makefile 2009-11-22 22:54:44.000000000 +0100 @@ -9,7 +9,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml networking.xml \ - kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ + kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml utrace.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ mac80211.xml debugobjects.xml sh.xml regulator.xml \ --- /dev/null 2009-11-22 14:49:16.630265461 +0100 +++ V1/Documentation/DocBook/utrace.tmpl 2009-11-22 22:54:44.000000000 +0100 @@ -0,0 +1,590 @@ + + + + + + The utrace User Debugging Infrastructure + + + + + utrace concepts + + Introduction + + + utrace is infrastructure code for tracing + and controlling user threads. This is the foundation for writing + tracing engines, which can be loadable kernel modules. + + + + The basic actors in utrace are the thread + and the tracing engine. A tracing engine is some body of code that + calls into the <linux/utrace.h> + interfaces, represented by a struct + utrace_engine_ops. (Usually it's a kernel module, + though the legacy ptrace support is a tracing + engine that is not in a kernel module.) The interface operates on + individual threads (struct task_struct). + If an engine wants to treat several threads as a group, that is up + to its higher-level code. + + + + Tracing begins by attaching an engine to a thread, using + utrace_attach_task or + utrace_attach_pid. If successful, it returns a + pointer that is the handle used in all other calls. + + + + + Events and Callbacks + + + An attached engine does nothing by default. An engine makes something + happen by requesting callbacks via utrace_set_events + and poking the thread with utrace_control. + The synchronization issues related to these two calls + are discussed further below in . + + + + Events are specified using the macro + UTRACE_EVENT(type). + Each event type is associated with a callback in struct + utrace_engine_ops. A tracing engine can leave unused + callbacks NULL. The only callbacks required + are those used by the event flags it sets. + + + + Many engines can be attached to each thread. When a thread has an + event, each engine gets a callback if it has set the event flag for + that event type. For most events, engines are called in the order they + attached. Engines that attach after the event has occurred do not get + callbacks for that event. This includes any new engines just attached + by an existing engine's callback function. Once the sequence of + callbacks for that one event has completed, such new engines are then + eligible in the next sequence that starts when there is another event. + + + + Event reporting callbacks have details particular to the event type, + but are all called in similar environments and have the same + constraints. Callbacks are made from safe points, where no locks + are held, no special resources are pinned (usually), and the + user-mode state of the thread is accessible. So, callback code has + a pretty free hand. But to be a good citizen, callback code should + never block for long periods. It is fine to block in + kmalloc and the like, but never wait for i/o or + for user mode to do something. If you need the thread to wait, use + UTRACE_STOP and return from the callback + quickly. When your i/o finishes or whatever, you can use + utrace_control to resume the thread. + + + + The UTRACE_EVENT(SYSCALL_ENTRY) event is a special + case. While other events happen in the kernel when it will return to + user mode soon, this event happens when entering the kernel before it + will proceed with the work requested from user mode. Because of this + difference, the report_syscall_entry callback is + special in two ways. For this event, engines are called in reverse of + the normal order (this includes the report_quiesce + call that precedes a report_syscall_entry call). + This preserves the semantics that the last engine to attach is called + "closest to user mode"--the engine that is first to see a thread's user + state when it enters the kernel is also the last to see that state when + the thread returns to user mode. For the same reason, if these + callbacks use UTRACE_STOP (see the next section), + the thread stops immediately after callbacks rather than only when it's + ready to return to user mode; when allowed to resume, it will actually + attempt the system call indicated by the register values at that time. + + + + + Stopping Safely + + Writing well-behaved callbacks + + + Well-behaved callbacks are important to maintain two essential + properties of the interface. The first of these is that unrelated + tracing engines should not interfere with each other. If your engine's + event callback does not return quickly, then another engine won't get + the event notification in a timely manner. The second important + property is that tracing should be as noninvasive as possible to the + normal operation of the system overall and of the traced thread in + particular. That is, attached tracing engines should not perturb a + thread's behavior, except to the extent that changing its user-visible + state is explicitly what you want to do. (Obviously some perturbation + is unavoidable, primarily timing changes, ranging from small delays due + to the overhead of tracing, to arbitrary pauses in user code execution + when a user stops a thread with a debugger for examination.) Even when + you explicitly want the perturbation of making the traced thread block, + just blocking directly in your callback has more unwanted effects. For + example, the CLONE event callbacks are called when + the new child thread has been created but not yet started running; the + child can never be scheduled until the CLONE + tracing callbacks return. (This allows engines tracing the parent to + attach to the child.) If a CLONE event callback + blocks the parent thread, it also prevents the child thread from + running (even to process a SIGKILL). If what you + want is to make both the parent and child block, then use + utrace_attach_task on the child and then use + UTRACE_STOP on both threads. A more crucial + problem with blocking in callbacks is that it can prevent + SIGKILL from working. A thread that is blocking + due to UTRACE_STOP will still wake up and die + immediately when sent a SIGKILL, as all threads + should. Relying on the utrace + infrastructure rather than on private synchronization calls in event + callbacks is an important way to help keep tracing robustly + noninvasive. + + + + + Using <constant>UTRACE_STOP</constant> + + + To control another thread and access its state, it must be stopped + with UTRACE_STOP. This means that it is + stopped and won't start running again while we access it. When a + thread is not already stopped, utrace_control + returns -EINPROGRESS and an engine must wait + for an event callback when the thread is ready to stop. The thread + may be running on another CPU or may be blocked. When it is ready + to be examined, it will make callbacks to engines that set the + UTRACE_EVENT(QUIESCE) event bit. To wake up an + interruptible wait, use UTRACE_INTERRUPT. + + + + As long as some engine has used UTRACE_STOP and + not called utrace_control to resume the thread, + then the thread will remain stopped. SIGKILL + will wake it up, but it will not run user code. When the stop is + cleared with utrace_control or a callback + return value, the thread starts running again. + (See also .) + + + + + + + Tear-down Races + + Primacy of <constant>SIGKILL</constant> + + Ordinarily synchronization issues for tracing engines are kept fairly + straightforward by using UTRACE_STOP. You ask a + thread to stop, and then once it makes the + report_quiesce callback it cannot do anything else + that would result in another callback, until you let it with a + utrace_control call. This simple arrangement + avoids complex and error-prone code in each one of a tracing engine's + event callbacks to keep them serialized with the engine's other + operations done on that thread from another thread of control. + However, giving tracing engines complete power to keep a traced thread + stuck in place runs afoul of a more important kind of simplicity that + the kernel overall guarantees: nothing can prevent or delay + SIGKILL from making a thread die and release its + resources. To preserve this important property of + SIGKILL, it as a special case can break + UTRACE_STOP like nothing else normally can. This + includes both explicit SIGKILL signals and the + implicit SIGKILL sent to each other thread in the + same thread group by a thread doing an exec, or processing a fatal + signal, or making an exit_group system call. A + tracing engine can prevent a thread from beginning the exit or exec or + dying by signal (other than SIGKILL) if it is + attached to that thread, but once the operation begins, no tracing + engine can prevent or delay all other threads in the same thread group + dying. + + + + Final callbacks + + The report_reap callback is always the final event + in the life cycle of a traced thread. Tracing engines can use this as + the trigger to clean up their own data structures. The + report_death callback is always the penultimate + event a tracing engine might see; it's seen unless the thread was + already in the midst of dying when the engine attached. Many tracing + engines will have no interest in when a parent reaps a dead process, + and nothing they want to do with a zombie thread once it dies; for + them, the report_death callback is the natural + place to clean up data structures and detach. To facilitate writing + such engines robustly, given the asynchrony of + SIGKILL, and without error-prone manual + implementation of synchronization schemes, the + utrace infrastructure provides some special + guarantees about the report_death and + report_reap callbacks. It still takes some care + to be sure your tracing engine is robust to tear-down races, but these + rules make it reasonably straightforward and concise to handle a lot of + corner cases correctly. + + + + Engine and task pointers + + The first sort of guarantee concerns the core data structures + themselves. struct utrace_engine is + a reference-counted data structure. While you hold a reference, an + engine pointer will always stay valid so that you can safely pass it to + any utrace call. Each call to + utrace_attach_task or + utrace_attach_pid returns an engine pointer with a + reference belonging to the caller. You own that reference until you + drop it using utrace_engine_put. There is an + implicit reference on the engine while it is attached. So if you drop + your only reference, and then use + utrace_attach_task without + UTRACE_ATTACH_CREATE to look up that same engine, + you will get the same pointer with a new reference to replace the one + you dropped, just like calling utrace_engine_get. + When an engine has been detached, either explicitly with + UTRACE_DETACH or implicitly after + report_reap, then any references you hold are all + that keep the old engine pointer alive. + + + + There is nothing a kernel module can do to keep a struct + task_struct alive outside of + rcu_read_lock. When the task dies and is reaped + by its parent (or itself), that structure can be freed so that any + dangling pointers you have stored become invalid. + utrace will not prevent this, but it can + help you detect it safely. By definition, a task that has been reaped + has had all its engines detached. All + utrace calls can be safely called on a + detached engine if the caller holds a reference on that engine pointer, + even if the task pointer passed in the call is invalid. All calls + return -ESRCH for a detached engine, which tells + you that the task pointer you passed could be invalid now. Since + utrace_control and + utrace_set_events do not block, you can call those + inside a rcu_read_lock section and be sure after + they don't return -ESRCH that the task pointer is + still valid until rcu_read_unlock. The + infrastructure never holds task references of its own. Though neither + rcu_read_lock nor any other lock is held while + making a callback, it's always guaranteed that the struct + task_struct and the struct + utrace_engine passed as arguments remain valid + until the callback function returns. + + + + The common means for safely holding task pointers that is available to + kernel modules is to use struct pid, which + permits put_pid from kernel modules. When using + that, the calls utrace_attach_pid, + utrace_control_pid, + utrace_set_events_pid, and + utrace_barrier_pid are available. + + + + + + Serialization of <constant>DEATH</constant> and <constant>REAP</constant> + + + The second guarantee is the serialization of + DEATH and REAP event + callbacks for a given thread. The actual reaping by the parent + (release_task call) can occur simultaneously + while the thread is still doing the final steps of dying, including + the report_death callback. If a tracing engine + has requested both DEATH and + REAP event reports, it's guaranteed that the + report_reap callback will not be made until + after the report_death callback has returned. + If the report_death callback itself detaches + from the thread, then the report_reap callback + will never be made. Thus it is safe for a + report_death callback to clean up data + structures and detach. + + + + Interlock with final callbacks + + The final sort of guarantee is that a tracing engine will know for sure + whether or not the report_death and/or + report_reap callbacks will be made for a certain + thread. These tear-down races are disambiguated by the error return + values of utrace_set_events and + utrace_control. Normally + utrace_control called with + UTRACE_DETACH returns zero, and this means that no + more callbacks will be made. If the thread is in the midst of dying, + it returns -EALREADY to indicate that the + report_death callback may already be in progress; + when you get this error, you know that any cleanup your + report_death callback does is about to happen or + has just happened--note that if the report_death + callback does not detach, the engine remains attached until the thread + gets reaped. If the thread is in the midst of being reaped, + utrace_control returns -ESRCH + to indicate that the report_reap callback may + already be in progress; this means the engine is implicitly detached + when the callback completes. This makes it possible for a tracing + engine that has decided asynchronously to detach from a thread to + safely clean up its data structures, knowing that no + report_death or report_reap + callback will try to do the same. utrace_detach + returns -ESRCH when the struct + utrace_engine has already been detached, but is + still a valid pointer because of its reference count. A tracing engine + can use this to safely synchronize its own independent multiple threads + of control with each other and with its event callbacks that detach. + + + + In the same vein, utrace_set_events normally + returns zero; if the target thread was stopped before the call, then + after a successful call, no event callbacks not requested in the new + flags will be made. It fails with -EALREADY if + you try to clear UTRACE_EVENT(DEATH) when the + report_death callback may already have begun, if + you try to clear UTRACE_EVENT(REAP) when the + report_reap callback may already have begun, or if + you try to newly set UTRACE_EVENT(DEATH) or + UTRACE_EVENT(QUIESCE) when the target is already + dead or dying. Like utrace_control, it returns + -ESRCH when the thread has already been detached + (including forcible detach on reaping). This lets the tracing engine + know for sure which event callbacks it will or won't see after + utrace_set_events has returned. By checking for + errors, it can know whether to clean up its data structures immediately + or to let its callbacks do the work. + + + + Using <function>utrace_barrier</function> + + When a thread is safely stopped, calling + utrace_control with UTRACE_DETACH + or calling utrace_set_events to disable some events + ensures synchronously that your engine won't get any more of the callbacks + that have been disabled (none at all when detaching). But these can also + be used while the thread is not stopped, when it might be simultaneously + making a callback to your engine. For this situation, these calls return + -EINPROGRESS when it's possible a callback is in + progress. If you are not prepared to have your old callbacks still run, + then you can synchronize to be sure all the old callbacks are finished, + using utrace_barrier. This is necessary if the + kernel module containing your callback code is going to be unloaded. + + + After using UTRACE_DETACH once, further calls to + utrace_control with the same engine pointer will + return -ESRCH. In contrast, after getting + -EINPROGRESS from + utrace_set_events, you can call + utrace_set_events again later and if it returns zero + then know the old callbacks have finished. + + + Unlike all other calls, utrace_barrier (and + utrace_barrier_pid) will accept any engine pointer you + hold a reference on, even if UTRACE_DETACH has already + been used. After any utrace_control or + utrace_set_events call (these do not block), you can + call utrace_barrier to block until callbacks have + finished. This returns -ESRCH only if the engine is + completely detached (finished all callbacks). Otherwise it waits + until the thread is definitely not in the midst of a callback to this + engine and then returns zero, but can return + -ERESTARTSYS if its wait is interrupted. + + + + + + + +utrace core API + + + The utrace API is declared in <linux/utrace.h>. + + +!Iinclude/linux/utrace.h +!Ekernel/utrace.c + + + +Machine State + + + The task_current_syscall function can be used on any + valid struct task_struct at any time, and does + not even require that utrace_attach_task was used at all. + + + + The other ways to access the registers and other machine-dependent state of + a task can only be used on a task that is at a known safe point. The safe + points are all the places where utrace_set_events can + request callbacks (except for the DEATH and + REAP events). So at any event callback, it is safe to + examine current. + + + + One task can examine another only after a callback in the target task that + returns UTRACE_STOP so that task will not return to user + mode after the safe point. This guarantees that the task will not resume + until the same engine uses utrace_control, unless the + task dies suddenly. To examine safely, one must use a pair of calls to + utrace_prepare_examine and + utrace_finish_examine surrounding the calls to + struct user_regset functions or direct examination + of task data structures. utrace_prepare_examine returns + an error if the task is not properly stopped and not dead. After a + successful examination, the paired utrace_finish_examine + call returns an error if the task ever woke up during the examination. If + so, any data gathered may be scrambled and should be discarded. This means + there was a spurious wake-up (which should not happen), or a sudden death. + + +<structname>struct user_regset</structname> + + + The struct user_regset API + is declared in <linux/regset.h>. + + +!Finclude/linux/regset.h + + + + + <filename>System Call Information</filename> + + + This function is declared in <linux/ptrace.h>. + + +!Elib/syscall.c + + + +<filename>System Call Tracing</filename> + + + The arch API for system call information is declared in + <asm/syscall.h>. + Each of these calls can be used only at system call entry tracing, + or can be used only at system call exit and the subsequent safe points + before returning to user mode. + At system call entry tracing means either during a + report_syscall_entry callback, + or any time after that callback has returned UTRACE_STOP. + + +!Finclude/asm-generic/syscall.h + + + + + +Kernel Internals + + + This chapter covers the interface to the tracing infrastructure + from the core of the kernel and the architecture-specific code. + This is for maintainers of the kernel and arch code, and not relevant + to using the tracing facilities described in preceding chapters. + + +Core Calls In + + + These calls are declared in <linux/tracehook.h>. + The core kernel calls these functions at various important places. + + +!Finclude/linux/tracehook.h + + + +Architecture Calls Out + + + An arch that has done all these things sets + CONFIG_HAVE_ARCH_TRACEHOOK. + This is required to enable the utrace code. + + +<filename><asm/ptrace.h></filename> + + + An arch defines these in <asm/ptrace.h> + if it supports hardware single-step or block-step features. + + +!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step +!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step +!Finclude/linux/ptrace.h user_disable_single_step + + + + + <filename><asm/syscall.h></filename> + + + An arch provides <asm/syscall.h> that + defines these as inlines, or declares them as exported functions. + These interfaces are described in . + + + + + + <filename><linux/tracehook.h></filename> + + + An arch must define TIF_NOTIFY_RESUME + and TIF_SYSCALL_TRACE + in its <asm/thread_info.h>. + The arch code must call the following functions, all declared + in <linux/tracehook.h> and + described in : + + + + tracehook_notify_resume + + + tracehook_report_syscall_entry + + + tracehook_report_syscall_exit + + + tracehook_signal_handler + + + + + + + + + + + + --- V1/fs/proc/array.c~__UTRACE 2009-11-20 11:36:46.000000000 +0100 +++ V1/fs/proc/array.c 2009-11-22 22:54:44.000000000 +0100 @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -189,6 +190,8 @@ static inline void task_state(struct seq cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); + task_utrace_proc_status(m, p); + task_lock(p); if (p->files) fdt = files_fdtable(p->files); --- V1/include/linux/sched.h~__UTRACE 2009-11-22 21:43:20.000000000 +0100 +++ V1/include/linux/sched.h 2009-11-22 22:54:44.000000000 +0100 @@ -1393,6 +1393,11 @@ struct task_struct { #endif seccomp_t seccomp; +#ifdef CONFIG_UTRACE + struct utrace *utrace; + unsigned long utrace_flags; +#endif + /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; --- V1/include/linux/tracehook.h~__UTRACE 2009-11-22 21:01:33.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-22 22:54:44.000000000 +0100 @@ -49,6 +49,7 @@ #include #include #include +#include struct linux_binprm; /** @@ -63,6 +64,8 @@ struct linux_binprm; */ static inline int tracehook_expect_breakpoints(struct task_struct *task) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -111,6 +114,9 @@ static inline void ptrace_report_syscall static inline __must_check int tracehook_report_syscall_entry( struct pt_regs *regs) { + if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && + utrace_report_syscall_entry(regs)) + return 1; ptrace_report_syscall(regs); return 0; } @@ -134,6 +140,9 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); @@ -201,6 +210,8 @@ static inline void tracehook_report_exec struct linux_binprm *bprm, struct pt_regs *regs) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) + utrace_report_exec(fmt, bprm, regs); if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && unlikely(task_ptrace(current) & PT_PTRACED)) send_sig(SIGTRAP, current, 0); @@ -218,10 +229,37 @@ static inline void tracehook_report_exec */ static inline void tracehook_report_exit(long *exit_code) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) + utrace_report_exit(exit_code); ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); } /** + * tracehook_init_task - task_struct has just been copied + * @task: new &struct task_struct just copied from parent + * + * Called from do_fork() when @task has just been duplicated. + * After this, @task will be passed to tracehook_free_task() + * even if the rest of its setup fails before it is fully created. + */ +static inline void tracehook_init_task(struct task_struct *task) +{ + utrace_init_task(task); +} + +/** + * tracehook_free_task - task_struct is being freed + * @task: dead &struct task_struct being freed + * + * Called from free_task() when @task is no longer in use. + */ +static inline void tracehook_free_task(struct task_struct *task) +{ + if (task_utrace_struct(task)) + utrace_free_task(task); +} + +/** * tracehook_prepare_clone - prepare for new child to be cloned * @clone_flags: %CLONE_* flags from clone/fork/vfork system call * @@ -285,6 +323,8 @@ static inline void tracehook_report_clon unsigned long clone_flags, pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) + utrace_report_clone(clone_flags, child); if (unlikely(task_ptrace(child))) { /* * It doesn't matter who attached/attaching to this @@ -317,6 +357,9 @@ static inline void tracehook_report_clon pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && + (clone_flags & CLONE_VFORK)) + utrace_finish_vfork(current); if (unlikely(trace)) ptrace_event(0, trace, pid); } @@ -351,6 +394,10 @@ static inline void tracehook_report_vfor */ static inline void tracehook_prepare_release_task(struct task_struct *task) { + /* see utrace_add_engine() about this barrier */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_release_task(task); } /** @@ -365,6 +412,7 @@ static inline void tracehook_prepare_rel static inline void tracehook_finish_release_task(struct task_struct *task) { ptrace_release_task(task); + BUG_ON(task->exit_state != EXIT_DEAD); } /** @@ -386,6 +434,8 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } @@ -403,6 +453,8 @@ static inline void tracehook_signal_hand static inline int tracehook_consider_ignored_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -422,6 +474,9 @@ static inline int tracehook_consider_ign static inline int tracehook_consider_fatal_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | + UTRACE_EVENT(SIGNAL_CORE)))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -436,6 +491,8 @@ static inline int tracehook_consider_fat */ static inline int tracehook_force_sigpending(void) { + if (unlikely(task_utrace_flags(current))) + return utrace_interrupt_pending(); return 0; } @@ -465,6 +522,8 @@ static inline int tracehook_get_signal(s siginfo_t *info, struct k_sigaction *return_ka) { + if (unlikely(task_utrace_flags(task))) + return utrace_get_signal(task, regs, info, return_ka); return 0; } @@ -492,6 +551,8 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { + if (task_utrace_flags(current) & UTRACE_EVENT(JCTL)) + utrace_report_jctl(notify, why); return notify ?: task_ptrace(current) ? why : 0; } @@ -502,6 +563,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_stop(); } #define DEATH_REAP -1 @@ -524,6 +587,8 @@ static inline void tracehook_finish_jctl static inline int tracehook_notify_death(struct task_struct *task, void **death_cookie, int group_dead) { + *death_cookie = task_utrace_struct(task); + if (task_detached(task)) return task->ptrace ? SIGCHLD : DEATH_REAP; @@ -560,6 +625,20 @@ static inline void tracehook_report_deat int signal, void *death_cookie, int group_dead) { + /* + * This barrier ensures that our caller's setting of + * @task->exit_state precedes checking @task->utrace_flags here. + * If utrace_set_events() was just called to enable + * UTRACE_EVENT(DEATH), then we are obliged to call + * utrace_report_death() and not miss it. utrace_set_events() + * uses tasklist_lock to synchronize enabling the bit with the + * actual change to @task->exit_state, but we need this barrier + * to be sure we see a flags change made just before our caller + * took the tasklist_lock. + */ + smp_mb(); + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) + utrace_report_death(task, death_cookie, group_dead, signal); } #ifdef TIF_NOTIFY_RESUME @@ -589,10 +668,20 @@ static inline void set_notify_resume(str * asynchronously, this will be called again before we return to * user mode. * - * Called without locks. + * Called without locks. However, on some machines this may be + * called with interrupts disabled. */ static inline void tracehook_notify_resume(struct pt_regs *regs) { + struct task_struct *task = current; + /* + * This pairs with the barrier implicit in set_notify_resume(). + * It ensures that we read the nonzero utrace_flags set before + * set_notify_resume() was called by utrace setup. + */ + smp_rmb(); + if (task_utrace_flags(task)) + utrace_resume(task, regs); } #endif /* TIF_NOTIFY_RESUME */ --- /dev/null 2009-11-22 14:49:16.630265461 +0100 +++ V1/include/linux/utrace.h 2009-11-22 22:54:44.000000000 +0100 @@ -0,0 +1,729 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + * + * This interface allows for notification of interesting events in a + * thread. It also mediates access to thread state such as registers. + * Multiple unrelated users can be associated with a single thread. + * We call each of these a tracing engine. + * + * A tracing engine starts by calling utrace_attach_task() or + * utrace_attach_pid() on the chosen thread, passing in a set of hooks + * (&struct utrace_engine_ops), and some associated data. This produces a + * &struct utrace_engine, which is the handle used for all other + * operations. An attached engine has its ops vector, its data, and an + * event mask controlled by utrace_set_events(). + * + * For each event bit that is set, that engine will get the + * appropriate ops->report_*() callback when the event occurs. The + * &struct utrace_engine_ops need not provide callbacks for an event + * unless the engine sets one of the associated event bits. + */ + +#ifndef _LINUX_UTRACE_H +#define _LINUX_UTRACE_H 1 + +#include +#include +#include +#include + +struct linux_binprm; +struct pt_regs; +struct utrace; +struct user_regset; +struct user_regset_view; + +/* + * Event bits passed to utrace_set_events(). + * These appear in &struct task_struct. at utrace_flags + * and &struct utrace_engine. at flags. + */ +enum utrace_events { + _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ + _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ + _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ + _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ + _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ + _UTRACE_EVENT_DEATH, /* Thread has died. */ + _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ + _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ + _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ + _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ + _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ + _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ + _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ + _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ + _UTRACE_NEVENTS +}; +#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) + +/* + * All the kinds of signal events. + * These all use the @report_signal() callback. + */ +#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ + | UTRACE_EVENT(SIGNAL_IGN) \ + | UTRACE_EVENT(SIGNAL_STOP) \ + | UTRACE_EVENT(SIGNAL_TERM) \ + | UTRACE_EVENT(SIGNAL_CORE)) +/* + * Both kinds of syscall events; these call the @report_syscall_entry() + * and @report_syscall_exit() callbacks, respectively. + */ +#define UTRACE_EVENT_SYSCALL \ + (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) + +/* + * The event reports triggered synchronously by task death. + */ +#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) + +/* + * Hooks in call these entry points to the + * utrace dispatch. They are weak references here only so + * tracehook.h doesn't need to #ifndef CONFIG_UTRACE them to + * avoid external references in case of unoptimized compilation. + */ +void utrace_free_task(struct task_struct *) + __attribute__((weak)); +bool utrace_interrupt_pending(void) + __attribute__((weak)); +void utrace_resume(struct task_struct *, struct pt_regs *) + __attribute__((weak)); +void utrace_finish_stop(void) + __attribute__((weak)); +int utrace_get_signal(struct task_struct *, struct pt_regs *, + siginfo_t *, struct k_sigaction *) + __attribute__((weak)); +void utrace_report_clone(unsigned long, struct task_struct *) + __attribute__((weak)); +void utrace_finish_vfork(struct task_struct *) + __attribute__((weak)); +void utrace_report_exit(long *exit_code) + __attribute__((weak)); +void utrace_report_death(struct task_struct *, struct utrace *, bool, int) + __attribute__((weak)); +void utrace_report_jctl(int notify, int type) + __attribute__((weak)); +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs) + __attribute__((weak)); +bool utrace_report_syscall_entry(struct pt_regs *) + __attribute__((weak)); +void utrace_report_syscall_exit(struct pt_regs *) + __attribute__((weak)); +void utrace_signal_handler(struct task_struct *, int) + __attribute__((weak)); + +#ifndef CONFIG_UTRACE + +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return 0; +} +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + return NULL; +} +static inline void utrace_init_task(struct task_struct *child) +{ +} +static inline void utrace_release_task(struct task_struct *task) +{ +} + +static inline void task_utrace_proc_status(struct seq_file *m, + struct task_struct *p) +{ +} + +#else /* CONFIG_UTRACE */ + +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return task->utrace_flags; +} + +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + struct utrace *utrace; + + /* + * This barrier ensures that any prior load of task->utrace_flags + * is ordered before this load of task->utrace. We use those + * utrace_flags checks in the hot path to decide to call into + * the utrace code. The first attach installs task->utrace before + * setting task->utrace_flags nonzero, with a barrier between. + * See utrace_task_alloc(). + */ + smp_rmb(); + utrace = task->utrace; + + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ + return utrace; +} + +static inline void utrace_init_task(struct task_struct *task) +{ + task->utrace_flags = 0; + task->utrace = NULL; +} + +void utrace_release_task(struct task_struct *); +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); + + +/* + * Version number of the API defined in this file. This will change + * whenever a tracing engine's code would need some updates to keep + * working. We maintain this here for the benefit of tracing engine code + * that is developed concurrently with utrace API improvements before they + * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. + */ +#define UTRACE_API_VERSION 20090421 + +/** + * enum utrace_resume_action - engine's choice of action for a traced task + * @UTRACE_STOP: Stay quiescent after callbacks. + * @UTRACE_INTERRUPT: Make @report_signal() callback soon. + * @UTRACE_REPORT: Make some callback soon. + * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. + * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. + * @UTRACE_RESUME: Resume normally in user mode. + * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). + * + * See utrace_control() for detailed descriptions of each action. This is + * encoded in the @action argument and the return value for every callback + * with a &u32 return value. + * + * The order of these is important. When there is more than one engine, + * each supplies its choice and the smallest value prevails. + */ +enum utrace_resume_action { + UTRACE_STOP, + UTRACE_INTERRUPT, + UTRACE_REPORT, + UTRACE_SINGLESTEP, + UTRACE_BLOCKSTEP, + UTRACE_RESUME, + UTRACE_DETACH +}; +#define UTRACE_RESUME_MASK 0x07 + +/** + * utrace_resume_action - &enum utrace_resume_action from callback action + * @action: &u32 callback @action argument or return value + * + * This extracts the &enum utrace_resume_action from @action, + * which is the @action argument to a &struct utrace_engine_ops + * callback or the return value from one. + */ +static inline enum utrace_resume_action utrace_resume_action(u32 action) +{ + return action & UTRACE_RESUME_MASK; +} + +/** + * enum utrace_signal_action - disposition of signal + * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. + * @UTRACE_SIGNAL_IGN: Ignore the signal. + * @UTRACE_SIGNAL_TERM: Terminate the process. + * @UTRACE_SIGNAL_CORE: Terminate with core dump. + * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. + * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. + * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. + * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. + * + * This is encoded in the @action argument and the return value for + * a @report_signal() callback. It says what will happen to the + * signal described by the &siginfo_t parameter to the callback. + * + * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when + * a tracing report is being made before dequeuing any pending signal. + * If this is immediately after a signal handler has been set up, then + * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback + * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure + * it sees a %UTRACE_SIGNAL_HANDLER report. + */ +enum utrace_signal_action { + UTRACE_SIGNAL_DELIVER = 0x00, + UTRACE_SIGNAL_IGN = 0x10, + UTRACE_SIGNAL_TERM = 0x20, + UTRACE_SIGNAL_CORE = 0x30, + UTRACE_SIGNAL_STOP = 0x40, + UTRACE_SIGNAL_TSTP = 0x50, + UTRACE_SIGNAL_REPORT = 0x60, + UTRACE_SIGNAL_HANDLER = 0x70 +}; +#define UTRACE_SIGNAL_MASK 0xf0 +#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ + +/** + * utrace_signal_action - &enum utrace_signal_action from callback action + * @action: @report_signal callback @action argument or return value + * + * This extracts the &enum utrace_signal_action from @action, which + * is the @action argument to a @report_signal callback or the + * return value from one. + */ +static inline enum utrace_signal_action utrace_signal_action(u32 action) +{ + return action & UTRACE_SIGNAL_MASK; +} + +/** + * enum utrace_syscall_action - disposition of system call attempt + * @UTRACE_SYSCALL_RUN: Run the system call. + * @UTRACE_SYSCALL_ABORT: Don't run the system call. + * + * This is encoded in the @action argument and the return value for + * a @report_syscall_entry callback. + */ +enum utrace_syscall_action { + UTRACE_SYSCALL_RUN = 0x00, + UTRACE_SYSCALL_ABORT = 0x10 +}; +#define UTRACE_SYSCALL_MASK 0xf0 +#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ + +/** + * utrace_syscall_action - &enum utrace_syscall_action from callback action + * @action: @report_syscall_entry callback @action or return value + * + * This extracts the &enum utrace_syscall_action from @action, which + * is the @action argument to a @report_syscall_entry callback or the + * return value from one. + */ +static inline enum utrace_syscall_action utrace_syscall_action(u32 action) +{ + return action & UTRACE_SYSCALL_MASK; +} + +/* + * Flags for utrace_attach_task() and utrace_attach_pid(). + */ +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ +#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ +#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ +#define UTRACE_ATTACH_MATCH_MASK 0x000f + +/** + * struct utrace_engine - per-engine structure + * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() + * @data: engine-private &void * passed to utrace_attach_task() + * @flags: event mask set by utrace_set_events() plus internal flag bits + * + * The task itself never has to worry about engines detaching while + * it's doing event callbacks. These structures are removed from the + * task's active list only when it's stopped, or by the task itself. + * + * utrace_engine_get() and utrace_engine_put() maintain a reference count. + * When it drops to zero, the structure is freed. One reference is held + * implicitly while the engine is attached to its task. + */ +struct utrace_engine { +/* private: */ + struct kref kref; + void (*release)(void *); + struct list_head entry; + +/* public: */ + const struct utrace_engine_ops *ops; + void *data; + + unsigned long flags; +}; + +/** + * utrace_engine_get - acquire a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you get another. + */ +static inline void utrace_engine_get(struct utrace_engine *engine) +{ + kref_get(&engine->kref); +} + +void __utrace_engine_release(struct kref *); + +/** + * utrace_engine_put - release a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you lose that reference. + * If it was the last one, @engine becomes an invalid pointer. + */ +static inline void utrace_engine_put(struct utrace_engine *engine) +{ + kref_put(&engine->kref, __utrace_engine_release); +} + +/** + * struct utrace_engine_ops - tracing engine callbacks + * + * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. + * utrace_set_events() calls on @engine choose which callbacks will be made + * to @engine from @task. + * + * Most callbacks take an @action argument, giving the resume action + * chosen by other tracing engines. All callbacks take an @engine + * argument, and a @task argument, which is always equal to @current. + * For some calls, @action also includes bits specific to that event + * and utrace_resume_action() is used to extract the resume action. + * This shows what would happen if @engine wasn't there, or will if + * the callback's return value uses %UTRACE_RESUME. This always + * starts as %UTRACE_RESUME when no other tracing is being done on + * this task. + * + * All return values contain &enum utrace_resume_action bits. For + * some calls, other bits specific to that kind of event are added to + * the resume action bits with OR. These are the same bits used in + * the @action argument. The resume action returned by a callback + * does not override previous engines' choices, it only says what + * @engine wants done. What @task actually does is the action that's + * most constrained among the choices made by all attached engines. + * See utrace_control() for more information on the actions. + * + * When %UTRACE_STOP is used in @report_syscall_entry, then @task + * stops before attempting the system call. In this case, another + * @report_syscall_entry callback will follow after @task resumes if + * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback + * or passed to utrace_control(). In a second or later callback, + * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate + * a repeat callback still waiting to attempt the same system call + * invocation. This repeat callback gives each engine an opportunity + * to reexamine registers another engine might have changed while + * @task was held in %UTRACE_STOP. + * + * In other cases, the resume action does not take effect until @task + * is ready to check for signals and return to user mode. If there + * are more callbacks to be made, the last round of calls determines + * the final action. A @report_quiesce callback with @event zero, or + * a @report_signal callback, will always be the last one made before + * @task resumes. Only %UTRACE_STOP is "sticky"--if @engine returned + * %UTRACE_STOP then @task stays stopped unless @engine returns + * different from a following callback. + * + * The report_death() and report_reap() callbacks do not take @action + * arguments, and only %UTRACE_DETACH is meaningful in the return value + * from a report_death() callback. None of the resume actions applies + * to a dead thread. + * + * All @report_*() hooks are called with no locks held, in a generally + * safe environment when we will be returning to user mode soon (or just + * entered the kernel). It is fine to block for memory allocation and + * the like, but all hooks are asynchronous and must not block on + * external events! If you want the thread to block, use %UTRACE_STOP + * in your hook's return value; then later wake it up with utrace_control(). + * + * @report_quiesce: + * Requested by %UTRACE_EVENT(%QUIESCE). + * This does not indicate any event, but just that @task (the current + * thread) is in a safe place for examination. This call is made + * before each specific event callback, except for @report_reap. + * The @event argument gives the %UTRACE_EVENT(@which) value for + * the event occurring. This callback might be made for events @engine + * has not requested, if some other engine is tracing the event; + * calling utrace_set_events() call here can request the immediate + * callback for this occurrence of @event. @event is zero when there + * is no other event, @task is now ready to check for signals and + * return to user mode, and some engine has used %UTRACE_REPORT or + * %UTRACE_INTERRUPT to request this callback. For this case, + * if @report_signal is not %NULL, the @report_quiesce callback + * may be replaced with a @report_signal callback passing + * %UTRACE_SIGNAL_REPORT in its @action argument, whenever @task is + * entering the signal-check path anyway. + * + * @report_signal: + * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). + * Use utrace_signal_action() and utrace_resume_action() on @action. + * The signal action is %UTRACE_SIGNAL_REPORT when some engine has + * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose + * to stop or to deliver an artificial signal, before pending signals. + * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just + * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this + * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by + * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly + * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the + * signal delivery. The other signal actions indicate a signal about + * to be delivered; the previous engine's return value sets the signal + * action seen by the the following engine's callback. The @info data + * can be changed at will, including @info->si_signo. The settings in + * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka + * is what was in force before other tracing engines intervened, and + * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or + * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info + * is left uninitialized and must be set completely by an engine that + * chooses to deliver a signal; if there was a previous @report_signal + * callback ending in %UTRACE_STOP and it was just resumed using + * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged + * from the previous callback. In this way, the original signal can + * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN + * and then found again when resuming @task with %UTRACE_INTERRUPT. + * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, + * and might be in @action if the previous engine returned it. This + * flag asks that the signal in @info be pushed back on @task's queue + * so that it will be seen again after whatever action is taken now. + * + * @report_clone: + * Requested by %UTRACE_EVENT(%CLONE). + * Event reported for parent, before the new task @child might run. + * @clone_flags gives the flags used in the clone system call, + * or equivalent flags for a fork() or vfork() system call. + * This function can use utrace_attach_task() on @child. It's guaranteed + * that asynchronous utrace_attach_task() calls will be ordered after + * any calls in @report_clone callbacks for the parent. Thus + * when using %UTRACE_ATTACH_EXCLUSIVE in the asynchronous calls, + * you can be sure that the parent's @report_clone callback has + * already attached to @child or chosen not to. Passing %UTRACE_STOP + * to utrace_control() on @child here keeps the child stopped before + * it ever runs in user mode, %UTRACE_REPORT or %UTRACE_INTERRUPT + * ensures a callback from @child before it starts in user mode. + * + * @report_jctl: + * Requested by %UTRACE_EVENT(%JCTL). + * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, + * indicating whether we are stopping or resuming now. If @notify + * is nonzero, @task is the last thread to stop and so will send + * %SIGCHLD to its parent after this callback; @notify reflects + * what the parent's %SIGCHLD has in @si_code, which can sometimes + * be %CLD_STOPPED even when @type is %CLD_CONTINUED. + * + * @report_exec: + * Requested by %UTRACE_EVENT(%EXEC). + * An execve system call has succeeded and the new program is about to + * start running. The initial user register state is handy to be tweaked + * directly in @regs. @fmt and @bprm gives the details of this exec. + * + * @report_syscall_entry: + * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). + * Thread has entered the kernel to request a system call. + * The user register state is handy to be tweaked directly in @regs. + * The @action argument contains an &enum utrace_syscall_action, + * use utrace_syscall_action() to extract it. The return value + * overrides the last engine's action for the system call. + * If the final action is %UTRACE_SYSCALL_ABORT, no system call + * is made. The details of the system call being attempted can + * be fetched here with syscall_get_nr() and syscall_get_arguments(). + * The parameter registers can be changed with syscall_set_arguments(). + * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. + * Use %UTRACE_REPORT in the return value to guarantee you get + * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case + * @task stops with %UTRACE_STOP before attempting the system call. + * + * @report_syscall_exit: + * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). + * Thread is about to leave the kernel after a system call request. + * The user register state is handy to be tweaked directly in @regs. + * The results of the system call attempt can be examined here using + * syscall_get_error() and syscall_get_return_value(). It is safe + * here to call syscall_set_return_value() or syscall_rollback(). + * + * @report_exit: + * Requested by %UTRACE_EVENT(%EXIT). + * Thread is exiting and cannot be prevented from doing so, + * but all its state is still live. The @code value will be + * the wait result seen by the parent, and can be changed by + * this engine or others. The @orig_code value is the real + * status, not changed by any tracing engine. Returning %UTRACE_STOP + * here keeps @task stopped before it cleans up its state and dies, + * so it can be examined by other processes. When @task is allowed + * to run, it will die and get to the @report_death callback. + * + * @report_death: + * Requested by %UTRACE_EVENT(%DEATH). + * Thread is really dead now. It might be reaped by its parent at + * any time, or self-reap immediately. Though the actual reaping + * may happen in parallel, a report_reap() callback will always be + * ordered after a report_death() callback. + * + * @report_reap: + * Requested by %UTRACE_EVENT(%REAP). + * Called when someone reaps the dead task (parent, init, or self). + * This means the parent called wait, or else this was a detached + * thread or a process whose parent ignores SIGCHLD. + * No more callbacks are made after this one. + * The engine is always detached. + * There is nothing more a tracing engine can do about this thread. + * After this callback, the @engine pointer will become invalid. + * The @task pointer may become invalid if get_task_struct() hasn't + * been used to keep it alive. + * An engine should always request this callback if it stores the + * @engine pointer or stores any pointer in @engine->data, so it + * can clean up its data structures. + * Unlike other callbacks, this can be called from the parent's context + * rather than from the traced thread itself--it must not delay the + * parent by blocking. + * + * @release: + * If not %NULL, this is called after the last utrace_engine_put() + * call for a &struct utrace_engine, which could be implicit after + * a %UTRACE_DETACH return from another callback. Its argument is + * the engine's @data member. + */ +struct utrace_engine_ops { + u32 (*report_quiesce)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event); + u32 (*report_signal)(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka); + u32 (*report_clone)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child); + u32 (*report_jctl)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + int type, int notify); + u32 (*report_exec)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs); + u32 (*report_syscall_entry)(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs); + u32 (*report_syscall_exit)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs); + u32 (*report_exit)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code); + u32 (*report_death)(struct utrace_engine *engine, + struct task_struct *task, + bool group_dead, int signal); + void (*report_reap)(struct utrace_engine *engine, + struct task_struct *task); + void (*release)(void *data); +}; + +/** + * struct utrace_examiner - private state for using utrace_prepare_examine() + * + * The members of &struct utrace_examiner are private to the implementation. + * This data type holds the state from a call to utrace_prepare_examine() + * to be used by a call to utrace_finish_examine(). + */ +struct utrace_examiner { +/* private: */ + long state; + unsigned long ncsw; +}; + +/* + * These are the exported entry points for tracing engines to use. + * See kernel/utrace.c for their kerneldoc comments with interface details. + */ +struct utrace_engine *utrace_attach_task(struct task_struct *, int, + const struct utrace_engine_ops *, + void *); +struct utrace_engine *utrace_attach_pid(struct pid *, int, + const struct utrace_engine_ops *, + void *); +int __must_check utrace_control(struct task_struct *, + struct utrace_engine *, + enum utrace_resume_action); +int __must_check utrace_set_events(struct task_struct *, + struct utrace_engine *, + unsigned long eventmask); +int __must_check utrace_barrier(struct task_struct *, + struct utrace_engine *); +int __must_check utrace_prepare_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); +int __must_check utrace_finish_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); + +/** + * utrace_control_pid - control a thread being traced by a tracing engine + * @pid: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is the same as utrace_control(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_control_pid( + struct pid *pid, struct utrace_engine *engine, + enum utrace_resume_action action) +{ + /* + * We don't bother with rcu_read_lock() here to protect the + * task_struct pointer, because utrace_control will return + * -ESRCH without looking at that pointer if the engine is + * already detached. A task_struct pointer can't die before + * all the engines are detached in release_task() first. + */ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); +} + +/** + * utrace_set_events_pid - choose which event reports a tracing engine gets + * @pid: thread to affect + * @engine: attached engine to affect + * @eventmask: new event mask + * + * This is the same as utrace_set_events(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_set_events_pid( + struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : + utrace_set_events(task, engine, eventmask); +} + +/** + * utrace_barrier_pid - synchronize with simultaneous tracing callbacks + * @pid: thread to affect + * @engine: engine to affect (can be detached) + * + * This is the same as utrace_barrier(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_barrier_pid(struct pid *pid, + struct utrace_engine *engine) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); +} + +#endif /* CONFIG_UTRACE */ + +#endif /* linux/utrace.h */ --- V1/init/Kconfig~__UTRACE 2009-11-11 22:41:26.000000000 +0100 +++ V1/init/Kconfig 2009-11-22 22:54:44.000000000 +0100 @@ -1205,6 +1205,15 @@ config STOP_MACHINE help Need stop_machine() primitive. +config UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + source "block/Kconfig" config PREEMPT_NOTIFIERS --- V1/kernel/fork.c~__UTRACE 2009-11-05 08:03:42.000000000 +0100 +++ V1/kernel/fork.c 2009-11-22 22:54:44.000000000 +0100 @@ -152,6 +152,7 @@ void free_task(struct task_struct *tsk) free_thread_info(tsk->stack); rt_mutex_debug_task_free(tsk); ftrace_graph_exit_task(tsk); + tracehook_free_task(tsk); free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -1018,6 +1019,8 @@ static struct task_struct *copy_process( if (!p) goto fork_out; + tracehook_init_task(p); + ftrace_graph_init_task(p); rt_mutex_init_task(p); --- V1/kernel/Makefile~__UTRACE 2009-11-22 22:20:55.000000000 +0100 +++ V1/kernel/Makefile 2009-11-22 22:54:44.000000000 +0100 @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += utrace.o obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o --- /dev/null 2009-11-22 14:49:16.630265461 +0100 +++ V1/kernel/utrace.c 2009-11-22 22:54:44.000000000 +0100 @@ -0,0 +1,2429 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Per-thread structure private to utrace implementation. + * If task_struct.utrace_flags is nonzero, task_struct.utrace + * has always been allocated first. Once allocated, it is + * never freed until free_task(). + * + * The common event reporting loops are done by the task making the + * report without ever taking any locks. To facilitate this, the two + * lists @attached and @attaching work together for smooth asynchronous + * attaching with low overhead. Modifying either list requires @lock. + * The @attaching list can be modified any time while holding @lock. + * New engines being attached always go on this list. + * + * The @attached list is what the task itself uses for its reporting + * loops. When the task itself is not quiescent, it can use the + * @attached list without taking any lock. Nobody may modify the list + * when the task is not quiescent. When it is quiescent, that means + * that it won't run again without taking @lock itself before using + * the list. + * + * At each place where we know the task is quiescent (or it's current), + * while holding @lock, we call splice_attaching(), below. This moves + * the @attaching list members on to the end of the @attached list. + * Since this happens at the start of any reporting pass, any new + * engines attached asynchronously go on the stable @attached list + * in time to have their callbacks seen. + */ +struct utrace { + spinlock_t lock; + struct list_head attached, attaching; + + struct task_struct *cloning; + + struct utrace_engine *reporting; + + enum utrace_resume_action resume:3; + unsigned int signal_handler:1; + unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ + unsigned int death:1; /* in utrace_report_death() now */ + unsigned int reap:1; /* release_task() has run */ + unsigned int pending_attach:1; /* need splice_attaching() */ +}; + +static struct kmem_cache *utrace_cachep; +static struct kmem_cache *utrace_engine_cachep; +static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ + +static int __init utrace_init(void) +{ + utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); + utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); + return 0; +} +module_init(utrace_init); + +/* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() + * governs installing the new pointer. If another one got in first, + * we just punt the new one we allocated. + * + * This returns false only in case of a memory allocation failure. + */ +static bool utrace_task_alloc(struct task_struct *task) +{ + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); + INIT_LIST_HEAD(&utrace->attached); + INIT_LIST_HEAD(&utrace->attaching); + utrace->resume = UTRACE_RESUME; + task_lock(task); + if (likely(!task->utrace)) { + /* + * This barrier makes sure the initialization of the struct + * precedes the installation of the pointer. This pairs + * with smp_read_barrier_depends() in task_utrace_struct(). + */ + smp_wmb(); + task->utrace = utrace; + } + task_unlock(task); + /* + * That unlock after storing task->utrace acts as a memory barrier + * ordering any subsequent task->utrace_flags store afterwards. + * This pairs with smp_rmb() in task_utrace_struct(). + */ + if (unlikely(task->utrace != utrace)) + kmem_cache_free(utrace_cachep, utrace); + return true; +} + +/* + * This is called via tracehook_free_task() from free_task() + * when @task is being deallocated. + */ +void utrace_free_task(struct task_struct *task) +{ + kmem_cache_free(utrace_cachep, task->utrace); +} + +/* + * This is called with @utrace->lock held when the task is safely + * quiescent, i.e. it won't consult utrace->attached without the lock. + * Move any engines attached asynchronously from @utrace->attaching + * onto the @utrace->attached list. + */ +static void splice_attaching(struct utrace *utrace) +{ + list_splice_tail_init(&utrace->attaching, &utrace->attached); + utrace->pending_attach = 0; +} + +/* + * This is the exported function used by the utrace_engine_put() inline. + */ +void __utrace_engine_release(struct kref *kref) +{ + struct utrace_engine *engine = container_of(kref, struct utrace_engine, + kref); + BUG_ON(!list_empty(&engine->entry)); + if (engine->release) + (*engine->release)(engine->data); + kmem_cache_free(utrace_engine_cachep, engine); +} +EXPORT_SYMBOL_GPL(__utrace_engine_release); + +static bool engine_matches(struct utrace_engine *engine, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) + return false; + if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) + return false; + return engine->ops && engine->ops != &utrace_detached_ops; +} + +static struct utrace_engine *matching_engine( + struct utrace *utrace, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine; + list_for_each_entry(engine, &utrace->attached, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + list_for_each_entry(engine, &utrace->attaching, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + return NULL; +} + +/* + * Called without locks, when we might be the first utrace engine to attach. + * If this is a newborn thread and we are not the creator, we have to wait + * for it. The creator gets the first chance to attach. The PF_STARTING + * flag is cleared after its report_clone hook has had a chance to run. + */ +static inline int utrace_attach_delay(struct task_struct *target) +{ + if ((target->flags & PF_STARTING) && + task_utrace_struct(current) && + task_utrace_struct(current)->cloning != target) + do { + schedule_timeout_interruptible(1); + if (signal_pending(current)) + return -ERESTARTNOINTR; + } while (target->flags & PF_STARTING); + + return 0; +} + +/* + * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. + */ +static int utrace_add_engine(struct task_struct *target, + struct utrace *utrace, + struct utrace_engine *engine, + int flags, + const struct utrace_engine_ops *ops, + void *data) +{ + int ret; + + spin_lock(&utrace->lock); + + ret = -EEXIST; + if ((flags & UTRACE_ATTACH_EXCLUSIVE) && + unlikely(matching_engine(utrace, flags, ops, data))) + goto unlock; + + /* + * In case we had no engines before, make sure that + * utrace_flags is not zero. + */ + ret = -ESRCH; + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); + /* + * If we race with tracehook_prepare_release_task() + * make sure that either it sees utrace_flags != 0 + * or we see exit_state == EXIT_DEAD. + */ + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + goto unlock; + } + } + + /* + * Put the new engine on the pending ->attaching list. + * Make sure it gets onto the ->attached list by the next + * time it's examined. Setting ->pending_attach ensures + * that start_report() takes the lock and splices the lists + * before the next new reporting pass. + * + * When target == current, it would be safe just to call + * splice_attaching() right here. But if we're inside a + * callback, that would mean the new engine also gets + * notified about the event that precipitated its own + * creation. This is not what the user wants. + */ + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + ret = 0; +unlock: + spin_unlock(&utrace->lock); + + return ret; +} + +/** + * utrace_attach_task - attach new engine, or look up an attached engine + * @target: thread to attach to + * @flags: flag bits combined with OR, see below + * @ops: callback table for new engine + * @data: engine private data pointer + * + * The caller must ensure that the @target thread does not get freed, + * i.e. hold a ref or be its parent. It is always safe to call this + * on @current, or on the @child pointer in a @report_clone callback. + * For most other cases, it's easier to use utrace_attach_pid() instead. + * + * UTRACE_ATTACH_CREATE: + * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you + * only look up an existing engine already attached to the thread. + * + * UTRACE_ATTACH_EXCLUSIVE: + * Attempting to attach a second (matching) engine fails with -%EEXIST. + * + * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. + * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. + * + * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA + * match the first among any engines attached to @target. That means that + * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there + * are any engines on @target at all. + */ +struct utrace_engine *utrace_attach_task( + struct task_struct *target, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { + if (unlikely(!utrace)) + return ERR_PTR(-ENOENT); + spin_lock(&utrace->lock); + engine = matching_engine(utrace, flags, ops, data); + if (engine) + utrace_engine_get(engine); + spin_unlock(&utrace->lock); + return engine ?: ERR_PTR(-ENOENT); + } + + if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) + return ERR_PTR(-EINVAL); + + if (unlikely(target->flags & PF_KTHREAD)) + /* + * Silly kernel, utrace is for users! + */ + return ERR_PTR(-EPERM); + + if (!utrace) { + if (unlikely(!utrace_task_alloc(target))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + + engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + + /* + * Initialize the new engine structure. It starts out with two + * refs: one ref to return, and one ref for being attached. + */ + kref_set(&engine->kref, 2); + engine->flags = 0; + engine->ops = ops; + engine->data = data; + engine->release = ops->release; + + ret = utrace_attach_delay(target); + if (likely(!ret)) + ret = utrace_add_engine(target, utrace, engine, + flags, ops, data); + + if (unlikely(ret)) { + kmem_cache_free(utrace_engine_cachep, engine); + engine = ERR_PTR(ret); + } + + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_task); + +/** + * utrace_attach_pid - attach new engine, or look up an attached engine + * @pid: &struct pid pointer representing thread to attach to + * @flags: flag bits combined with OR, see utrace_attach_task() + * @ops: callback table for new engine + * @data: engine private data pointer + * + * This is the same as utrace_attach_task(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +struct utrace_engine *utrace_attach_pid( + struct pid *pid, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine = ERR_PTR(-ESRCH); + struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); + if (task) { + engine = utrace_attach_task(task, flags, ops, data); + put_task_struct(task); + } + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_pid); + +/* + * When an engine is detached, the target thread may still see it and + * make callbacks until it quiesces. We install a special ops vector + * with these two callbacks. When the target thread quiesces, it can + * safely free the engine itself. For any event we will always get + * the report_quiesce() callback first, so we only need this one + * pointer to be set. The only exception is report_reap(), so we + * supply that callback too. + */ +static u32 utrace_detached_quiesce(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + return UTRACE_DETACH; +} + +static void utrace_detached_reap(struct utrace_engine *engine, + struct task_struct *task) +{ +} + +static const struct utrace_engine_ops utrace_detached_ops = { + .report_quiesce = &utrace_detached_quiesce, + .report_reap = &utrace_detached_reap +}; + +/* + * The caller has to hold a ref on the engine. If the attached flag is + * true (all but utrace_barrier() calls), the engine is supposed to be + * attached. If the attached flag is false (utrace_barrier() only), + * then return -ERESTARTSYS for an engine marked for detach but not yet + * fully detached. The task pointer can be invalid if the engine is + * detached. + * + * Get the utrace lock for the target task. + * Returns the struct if locked, or ERR_PTR(-errno). + * + * This has to be robust against races with: + * utrace_control(target, UTRACE_DETACH) calls + * UTRACE_DETACH after reports + * utrace_report_death + * utrace_release_task + */ +static struct utrace *get_utrace_lock(struct task_struct *target, + struct utrace_engine *engine, + bool attached) + __acquires(utrace->lock) +{ + struct utrace *utrace; + + rcu_read_lock(); + + /* + * If this engine was already detached, bail out before we look at + * the task_struct pointer at all. If it's detached after this + * check, then RCU is still keeping this task_struct pointer valid. + * + * The ops pointer is NULL when the engine is fully detached. + * It's &utrace_detached_ops when it's marked detached but still + * on the list. In the latter case, utrace_barrier() still works, + * since the target might be in the middle of an old callback. + */ + if (unlikely(!engine->ops)) { + rcu_read_unlock(); + return ERR_PTR(-ESRCH); + } + + if (unlikely(engine->ops == &utrace_detached_ops)) { + rcu_read_unlock(); + return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); + } + + utrace = task_utrace_struct(target); + spin_lock(&utrace->lock); + if (unlikely(!engine->ops) || + unlikely(engine->ops == &utrace_detached_ops)) { + /* + * By the time we got the utrace lock, + * it had been reaped or detached already. + */ + spin_unlock(&utrace->lock); + utrace = ERR_PTR(-ESRCH); + if (!attached && engine->ops == &utrace_detached_ops) + utrace = ERR_PTR(-ERESTARTSYS); + } + rcu_read_unlock(); + + return utrace; +} + +/* + * Now that we don't hold any locks, run through any + * detached engines and free their references. Each + * engine had one implicit ref while it was attached. + */ +static void put_detached_list(struct list_head *list) +{ + struct utrace_engine *engine, *next; + list_for_each_entry_safe(engine, next, list, entry) { + list_del_init(&engine->entry); + utrace_engine_put(engine); + } +} + +/* + * Called with utrace->lock held and utrace->reap set. + * Notify and clean up all engines, then free utrace. + */ +static void utrace_reap(struct task_struct *target, struct utrace *utrace) + __releases(utrace->lock) +{ + struct utrace_engine *engine, *next; + + /* utrace_add_engine() checks ->utrace_flags != 0 */ + target->utrace_flags = 0; + splice_attaching(utrace); + + /* + * Since we were called with @utrace->reap set, nobody can + * set/clear UTRACE_EVENT(REAP) in @engine->flags or change + * @engine->ops, and nobody can change @utrace->attached. + */ + spin_unlock(&utrace->lock); + + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->flags & UTRACE_EVENT(REAP)) + engine->ops->report_reap(engine, target); + + engine->ops = NULL; + engine->flags = 0; + list_del_init(&engine->entry); + + utrace_engine_put(engine); + } +} + + +/* + * Called by release_task. + */ +void utrace_release_task(struct task_struct *target) +{ + struct utrace *utrace = task_utrace_struct(target); + + spin_lock(&utrace->lock); + + utrace->reap = 1; + + /* + * If the target will do some final callbacks but hasn't + * finished them yet, we know because it clears these event + * bits after it's done. Instead of cleaning up here and + * requiring utrace_report_death() to cope with it, we delay + * the REAP report and the teardown until after the target + * finishes its death reports. + */ + + if (target->utrace_flags & _UTRACE_DEATH_EVENTS) + spin_unlock(&utrace->lock); + else + utrace_reap(target, utrace); /* Unlocks. */ +} + +/* + * We use an extra bit in utrace_engine.flags past the event bits, + * to record whether the engine is keeping the target thread stopped. + * + * This bit is set in task_struct.utrace_flags whenever it is set in any + * engine's flags. Only utrace_reset() resets it in utrace_flags. + */ +#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + +static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) +{ + engine->flags |= ENGINE_STOP; + task->utrace_flags |= ENGINE_STOP; +} + +static void clear_engine_wants_stop(struct utrace_engine *engine) +{ + engine->flags &= ~ENGINE_STOP; +} + +static bool engine_wants_stop(struct utrace_engine *engine) +{ + return (engine->flags & ENGINE_STOP) != 0; +} + +/** + * utrace_set_events - choose which event reports a tracing engine gets + * @target: thread to affect + * @engine: attached engine to affect + * @events: new event mask + * + * This changes the set of events for which @engine wants callbacks made. + * + * This fails with -%EALREADY and does nothing if you try to clear + * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have + * begun, if you try to clear %UTRACE_EVENT(%REAP) when the @report_reap + * callback may already have begun, or if you try to newly set + * %UTRACE_EVENT(%DEATH) or %UTRACE_EVENT(%QUIESCE) when @target is + * already dead or dying. + * + * This can fail with -%ESRCH when @target has already been detached, + * including forcible detach on reaping. + * + * If @target was stopped before the call, then after a successful call, + * no event callbacks not requested in @events will be made; if + * %UTRACE_EVENT(%QUIESCE) is included in @events, then a + * @report_quiesce callback will be made when @target resumes. + * + * If @target was not stopped and @events excludes some bits that were + * set before, this can return -%EINPROGRESS to indicate that @target + * may have been making some callback to @engine. When this returns + * zero, you can be sure that no event callbacks you've disabled in + * @events can be made. If @events only sets new bits that were not set + * before on @engine, then -%EINPROGRESS will never be returned. + * + * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). + * + * When @target is @current, -%EINPROGRESS is not returned. But note + * that a newly-created engine will not receive any callbacks related to + * an event notification already in progress. This call enables @events + * callbacks to be made as soon as @engine becomes eligible for any + * callbacks, see utrace_attach_task(). + * + * These rules provide for coherent synchronization based on %UTRACE_STOP, + * even when %SIGKILL is breaking its normal simple rules. + */ +int utrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long events) +{ + struct utrace *utrace; + unsigned long old_flags, old_utrace_flags; + int ret; + + /* + * We just ignore the internal bit, so callers can use + * engine->flags to seed bitwise ops for our argument. + */ + events &= ~ENGINE_STOP; + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + old_utrace_flags = target->utrace_flags; + old_flags = engine->flags & ~ENGINE_STOP; + + if (target->exit_state && + (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || + (utrace->death && + ((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) || + (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) { + spin_unlock(&utrace->lock); + return -EALREADY; + } + + /* + * When setting these flags, it's essential that we really + * synchronize with exit_notify(). They cannot be set after + * exit_notify() takes the tasklist_lock. By holding the read + * lock here while setting the flags, we ensure that the calls + * to tracehook_notify_death() and tracehook_report_death() will + * see the new flags. This ensures that utrace_release_task() + * knows positively that utrace_report_death() will be called or + * that it won't. + */ + if ((events & ~old_utrace_flags) & _UTRACE_DEATH_EVENTS) { + read_lock(&tasklist_lock); + if (unlikely(target->exit_state)) { + read_unlock(&tasklist_lock); + spin_unlock(&utrace->lock); + return -EALREADY; + } + target->utrace_flags |= events; + read_unlock(&tasklist_lock); + } + + engine->flags = events | (engine->flags & ENGINE_STOP); + target->utrace_flags |= events; + + if ((events & UTRACE_EVENT_SYSCALL) && + !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) + set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); + + ret = 0; + if ((old_flags & ~events) && target != current && + !task_is_stopped_or_traced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, + * pairing with the barrier in start_callback(). If + * @target has not yet hit finish_callback() to clear + * utrace->reporting, we might be in the middle of a + * callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_set_events); + +/* + * Asynchronously mark an engine as being detached. + * + * This must work while the target thread races with us doing + * start_callback(), defined below. It uses smp_rmb() between checking + * @engine->flags and using @engine->ops. Here we change @engine->ops + * first, then use smp_wmb() before changing @engine->flags. This ensures + * it can check the old flags before using the old ops, or check the old + * flags before using the new ops, or check the new flags before using the + * new ops, but can never check the new flags before using the old ops. + * Hence, utrace_detached_ops might be used with any old flags in place. + * It has report_quiesce() and report_reap() callbacks to handle all cases. + */ +static void mark_engine_detached(struct utrace_engine *engine) +{ + engine->ops = &utrace_detached_ops; + smp_wmb(); + engine->flags = UTRACE_EVENT(QUIESCE); +} + +/* + * Get @target to stop and return true if it is already stopped now. + * If we return false, it will make some event callback soonish. + * Called with @utrace locked. + */ +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) +{ + if (task_is_stopped(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); + if (likely(task_is_stopped(target))) + __set_task_state(target, TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + + return task_is_traced(target); +} + +/* + * If the target is not dead it should not be in tracing + * stop any more. Wake it unless it's in job control stop. + * + * Called with @utrace->lock held and @target in either TASK_TRACED or dead. + */ +static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) +{ + spin_lock_irq(&target->sighand->siglock); + if (target->signal->flags & SIGNAL_STOP_STOPPED || + target->signal->group_stop_count) + target->state = TASK_STOPPED; + else + wake_up_state(target, __TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); +} + +/* + * This is called when there might be some detached engines on the list or + * some stale bits in @task->utrace_flags. Clean them up and recompute the + * flags. Returns true if we're now fully detached. + * + * Called with @utrace->lock held, returns with it released. + * After this returns, @utrace might be freed if everything detached. + */ +static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + __releases(utrace->lock) +{ + struct utrace_engine *engine, *next; + unsigned long flags = 0; + LIST_HEAD(detached); + + splice_attaching(utrace); + + /* + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + * For any engine marked detached, remove it from the list. + * We'll collect them on the detached list. + */ + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->ops == &utrace_detached_ops) { + engine->ops = NULL; + list_move(&engine->entry, &detached); + } else { + flags |= engine->flags | UTRACE_EVENT(REAP); + } + } + + if (task->exit_state) { + /* + * Once it's already dead, we never install any flags + * except REAP. When ->exit_state is set and events + * like DEATH are not set, then they never can be set. + * This ensures that utrace_release_task() knows + * positively that utrace_report_death() can never run. + */ + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } + + if (!flags) { + /* + * No more engines, cleared out the utrace. + */ + utrace->resume = UTRACE_RESUME; + utrace->signal_handler = 0; + } + + if (task_is_traced(task) && !(flags & ENGINE_STOP)) + /* + * No more engines want it stopped. Wake it up. + */ + utrace_wakeup(task, utrace); + + /* + * In theory spin_lock() doesn't imply rcu_read_lock(). + * Once we clear ->utrace_flags this task_struct can go away + * because tracehook_prepare_release_task() path does not take + * utrace->lock when ->utrace_flags == 0. + */ + rcu_read_lock(); + task->utrace_flags = flags; + spin_unlock(&utrace->lock); + rcu_read_unlock(); + + put_detached_list(&detached); + + return !flags; +} + +void utrace_finish_stop(void) +{ + /* + * If we were task_is_traced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { + struct utrace *utrace = task_utrace_struct(current); + spin_unlock_wait(&utrace->lock); + } +} + +/* + * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. + */ +static void utrace_stop(struct task_struct *task, struct utrace *utrace, + enum utrace_resume_action action) +{ +relock: + spin_lock(&utrace->lock); + + if (action < utrace->resume) { + /* + * Ensure a reporting pass when we're resumed. + */ + utrace->resume = action; + if (action == UTRACE_INTERRUPT) + set_thread_flag(TIF_SIGPENDING); + else + set_thread_flag(TIF_NOTIFY_RESUME); + } + + /* + * If the ENGINE_STOP bit is clear in utrace_flags, that means + * utrace_reset() ran after we processed some UTRACE_STOP return + * values from callbacks to get here. If all engines have detached + * or resumed us, we don't stop. This check doesn't require + * siglock, but it should follow the interrupt/report bookkeeping + * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). + */ + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { + utrace_reset(task, utrace); + if (task->utrace_flags & ENGINE_STOP) + goto relock; + return; + } + + /* + * The siglock protects us against signals. As well as SIGKILL + * waking us up, we must synchronize with the signal bookkeeping + * for stop signals and SIGCONT. + */ + spin_lock_irq(&task->sighand->siglock); + + if (unlikely(__fatal_signal_pending(task))) { + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + return; + } + + __set_current_state(TASK_TRACED); + + /* + * If there is a group stop in progress, + * we must participate in the bookkeeping. + */ + if (unlikely(task->signal->group_stop_count) && + !--task->signal->group_stop_count) + task->signal->flags = SIGNAL_STOP_STOPPED; + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + + /* + * If ptrace is among the reasons for this stop, do its + * notification now. This could not just be done in + * ptrace's own event report callbacks because it has to + * be done after we are in TASK_TRACED. This makes the + * synchronization with ptrace_do_wait() work right. + */ + ptrace_notify_stop(task); + + schedule(); + + utrace_finish_stop(); + + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* + * While we were in TASK_TRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); +} + +/* + * You can't do anything to a dead task but detach it. + * If release_task() has been called, you can't do that. + * + * On the exit path, DEATH and QUIESCE event bits are set only + * before utrace_report_death() has taken the lock. At that point, + * the death report will come soon, so disallow detach until it's + * done. This prevents us from racing with it detaching itself. + * + * Called with utrace->lock held, when @target->exit_state is nonzero. + */ +static inline int utrace_control_dead(struct task_struct *target, + struct utrace *utrace, + enum utrace_resume_action action) +{ + if (action != UTRACE_DETACH || unlikely(utrace->reap)) + return -ESRCH; + + if (unlikely(utrace->death)) + /* + * We have already started the death report. We can't + * prevent the report_death and report_reap callbacks, + * so tell the caller they will happen. + */ + return -EALREADY; + + return 0; +} + +/** + * utrace_control - control a thread being traced by a tracing engine + * @target: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is how a tracing engine asks a traced thread to do something. + * This call is controlled by the @action argument, which has the + * same meaning as the &enum utrace_resume_action value returned by + * event reporting callbacks. + * + * If @target is already dead (@target->exit_state nonzero), + * all actions except %UTRACE_DETACH fail with -%ESRCH. + * + * The following sections describe each option for the @action argument. + * + * UTRACE_DETACH: + * + * After this, the @engine data structure is no longer accessible, + * and the thread might be reaped. The thread will start running + * again if it was stopped and no longer has any attached engines + * that want it stopped. + * + * If the @report_reap callback may already have begun, this fails + * with -%ESRCH. If the @report_death callback may already have + * begun, this fails with -%EALREADY. + * + * If @target is not already stopped, then a callback to this engine + * might be in progress or about to start on another CPU. If so, + * then this returns -%EINPROGRESS; the detach happens as soon as + * the pending callback is finished. To synchronize after an + * -%EINPROGRESS return, see utrace_barrier(). + * + * If @target is properly stopped before utrace_control() is called, + * then after successful return it's guaranteed that no more callbacks + * to the @engine->ops vector will be made. + * + * The only exception is %SIGKILL (and exec or group-exit by another + * thread in the group), which can cause asynchronous @report_death + * and/or @report_reap callbacks even when %UTRACE_STOP was used. + * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) + * + * UTRACE_STOP: + * + * This asks that @target stop running. This returns 0 only if + * @target is already stopped, either for tracing or for job + * control. Then @target will remain stopped until another + * utrace_control() call is made on @engine; @target can be woken + * only by %SIGKILL (or equivalent, such as exec or termination by + * another thread in the same thread group). + * + * This returns -%EINPROGRESS if @target is not already stopped. + * Then the effect is like %UTRACE_REPORT. A @report_quiesce or + * @report_signal callback will be made soon. Your callback can + * then return %UTRACE_STOP to keep @target stopped. + * + * This does not interrupt system calls in progress, including ones + * that sleep for a long time. For that, use %UTRACE_INTERRUPT. + * To interrupt system calls and then keep @target stopped, your + * @report_signal callback can return %UTRACE_STOP. + * + * UTRACE_RESUME: + * + * Just let @target continue running normally, reversing the effect + * of a previous %UTRACE_STOP. If another engine is keeping @target + * stopped, then it remains stopped until all engines let it resume. + * If @target was not stopped, this has no effect. + * + * UTRACE_REPORT: + * + * This is like %UTRACE_RESUME, but also ensures that there will be + * a @report_quiesce or @report_signal callback made soon. If + * @target had been stopped, then there will be a callback before it + * resumes running normally. If another engine is keeping @target + * stopped, then there might be no callbacks until all engines let + * it resume. + * + * Since this is meaningless unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_INTERRUPT: + * + * This is like %UTRACE_REPORT, but ensures that @target will make a + * @report_signal callback before it resumes or delivers signals. + * If @target was in a system call or about to enter one, work in + * progress will be interrupted as if by %SIGSTOP. If another + * engine is keeping @target stopped, then there might be no + * callbacks until all engines let it resume. + * + * This gives @engine an opportunity to introduce a forced signal + * disposition via its @report_signal callback. + * + * UTRACE_SINGLESTEP: + * + * It's invalid to use this unless arch_has_single_step() returned true. + * This is like %UTRACE_RESUME, but resumes for one user instruction only. + * + * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to + * utrace_control() or returning it from an event callback alone does + * not necessarily ensure that stepping will be enabled. If there are + * more callbacks made to any engine before returning to user mode, + * then the resume action is chosen only by the last set of callbacks. + * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the + * @report_quiesce callback with a zero event mask, or the + * @report_signal callback with %UTRACE_SIGNAL_REPORT. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_BLOCKSTEP: + * + * It's invalid to use this unless arch_has_block_step() returned true. + * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic + * block of user instructions. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another + * tracing engine is using %UTRACE_SINGLESTEP at the same time. + */ +int utrace_control(struct task_struct *target, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + struct utrace *utrace; + bool reset; + int ret; + + if (unlikely(action > UTRACE_DETACH)) + return -EINVAL; + + /* + * This is a sanity check for a programming error in the caller. + * Their request can only work properly in all cases by relying on + * a follow-up callback, but they didn't set one up! This check + * doesn't do locking, but it shouldn't matter. The caller has to + * be synchronously sure the callback is set up to be operating the + * interface properly. + */ + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) + return -EINVAL; + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + reset = task_is_traced(target); + ret = 0; + + /* + * ->exit_state can change under us, this doesn't matter. + * We do not care about ->exit_state in fact, but we do + * care about ->reap and ->death. If either flag is set, + * we must also see ->exit_state != 0. + */ + if (unlikely(target->exit_state)) { + ret = utrace_control_dead(target, utrace, action); + if (ret) { + spin_unlock(&utrace->lock); + return ret; + } + reset = true; + } + + switch (action) { + case UTRACE_STOP: + mark_engine_wants_stop(target, engine); + if (!reset && !utrace_do_stop(target, utrace)) + ret = -EINPROGRESS; + reset = false; + break; + + case UTRACE_DETACH: + if (engine_wants_stop(engine)) + target->utrace_flags &= ~ENGINE_STOP; + mark_engine_detached(engine); + reset = reset || utrace_do_stop(target, utrace); + if (!reset) { + /* + * As in utrace_set_events(), this barrier ensures + * that our engine->flags changes have hit before we + * examine utrace->reporting, pairing with the barrier + * in start_callback(). If @target has not yet hit + * finish_callback() to clear utrace->reporting, we + * might be in the middle of a callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + break; + + case UTRACE_RESUME: + /* + * This and all other cases imply resuming if stopped. + * There might not be another report before it just + * resumes, so make sure single-step is not left set. + */ + clear_engine_wants_stop(engine); + if (likely(reset)) + user_disable_single_step(target); + break; + + case UTRACE_BLOCKSTEP: + /* + * Resume from stopped, step one block. + * We fall through to treat it like UTRACE_SINGLESTEP. + */ + if (unlikely(!arch_has_block_step())) { + WARN_ON(1); + action = UTRACE_SINGLESTEP; + } + + case UTRACE_SINGLESTEP: + /* + * Resume from stopped, step one instruction. + * We fall through to the UTRACE_REPORT case. + */ + if (unlikely(!arch_has_single_step())) { + WARN_ON(1); + reset = false; + ret = -EOPNOTSUPP; + break; + } + + case UTRACE_REPORT: + /* + * Make the thread call tracehook_notify_resume() soon. + * But don't bother if it's already been interrupted. + * In that case, utrace_get_signal() will be reporting soon. + */ + clear_engine_wants_stop(engine); + if (action < utrace->resume) { + utrace->resume = action; + set_notify_resume(target); + } + break; + + case UTRACE_INTERRUPT: + /* + * Make the thread call tracehook_get_signal() soon. + */ + clear_engine_wants_stop(engine); + if (utrace->resume == UTRACE_INTERRUPT) + break; + utrace->resume = UTRACE_INTERRUPT; + + /* + * If it's not already stopped, interrupt it now. We need + * the siglock here in case it calls recalc_sigpending() + * and clears its own TIF_SIGPENDING. By taking the lock, + * we've serialized any later recalc_sigpending() after our + * setting of utrace->resume to force it on. + */ + if (reset) { + /* + * This is really just to keep the invariant that + * TIF_SIGPENDING is set with UTRACE_INTERRUPT. + * When it's stopped, we know it's always going + * through utrace_get_signal() and will recalculate. + */ + set_tsk_thread_flag(target, TIF_SIGPENDING); + } else { + struct sighand_struct *sighand; + unsigned long irqflags; + sighand = lock_task_sighand(target, &irqflags); + if (likely(sighand)) { + signal_wake_up(target, 0); + unlock_task_sighand(target, &irqflags); + } + } + break; + } + + /* + * Let the thread resume running. If it's not stopped now, + * there is nothing more we need to do. + */ + if (reset) + utrace_reset(target, utrace); + else + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_control); + +/** + * utrace_barrier - synchronize with simultaneous tracing callbacks + * @target: thread to affect + * @engine: engine to affect (can be detached) + * + * This blocks while @target might be in the midst of making a callback to + * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. + * A return value of zero means no callback from @target to @engine was + * in progress. Any effect of its return value (such as %UTRACE_STOP) has + * already been applied to @engine. + * + * It's not necessary to keep the @target pointer alive for this call. + * It's only necessary to hold a ref on @engine. This will return + * safely even if @target has been reaped and has no task refs. + * + * A successful return from utrace_barrier() guarantees its ordering + * with respect to utrace_set_events() and utrace_control() calls. If + * @target was not properly stopped, event callbacks just disabled might + * still be in progress; utrace_barrier() waits until there is no chance + * an unwanted callback can be in progress. + */ +int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) +{ + struct utrace *utrace; + int ret = -ERESTARTSYS; + + if (unlikely(target == current)) + return 0; + + do { + utrace = get_utrace_lock(target, engine, false); + if (unlikely(IS_ERR(utrace))) { + ret = PTR_ERR(utrace); + if (ret != -ERESTARTSYS) + break; + } else { + /* + * All engine state changes are done while + * holding the lock, i.e. before we get here. + * Since we have the lock, we only need to + * worry about @target making a callback. + * When it has entered start_callback() but + * not yet gotten to finish_callback(), we + * will see utrace->reporting == @engine. + * When @target doesn't take the lock, it uses + * barriers to order setting utrace->reporting + * before it examines the engine state. + */ + if (utrace->reporting != engine) + ret = 0; + spin_unlock(&utrace->lock); + if (!ret) + break; + } + schedule_timeout_interruptible(1); + } while (!signal_pending(current)); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_barrier); + +/* + * This is local state used for reporting loops, perhaps optimized away. + */ +struct utrace_report { + u32 result; + enum utrace_resume_action action; + enum utrace_resume_action resume_action; + bool detaches; + bool spurious; +}; + +#define INIT_REPORT(var) \ + struct utrace_report var = { \ + .action = UTRACE_RESUME, \ + .resume_action = UTRACE_RESUME, \ + .spurious = true \ + } + +/* + * We are now making the report, so clear the flag saying we need one. + * When there is a new attach, ->pending_attach is set just so we will + * know to do splice_attaching() here before the callback loop. + */ +static enum utrace_resume_action start_report(struct utrace *utrace) +{ + enum utrace_resume_action resume = utrace->resume; + if (utrace->pending_attach || + (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { + spin_lock(&utrace->lock); + splice_attaching(utrace); + resume = utrace->resume; + if (resume > UTRACE_INTERRUPT) + utrace->resume = UTRACE_RESUME; + spin_unlock(&utrace->lock); + } + return resume; +} + +static inline void finish_report_reset(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + if (unlikely(report->spurious || report->detaches)) { + spin_lock(&utrace->lock); + if (utrace_reset(task, utrace)) + report->action = UTRACE_RESUME; + } +} + +/* + * Complete a normal reporting pass, pairing with a start_report() call. + * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT + * returns from engine callbacks. If @will_not_stop is true and any + * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to + * ensure we stop before user mode. If there were no callbacks made, it + * will recompute @task->utrace_flags to avoid another false-positive. + */ +static void finish_report(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, bool will_not_stop) +{ + enum utrace_resume_action resume = report->action; + + if (resume == UTRACE_STOP) + resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; + + if (resume < utrace->resume) { + spin_lock(&utrace->lock); + utrace->resume = resume; + if (resume == UTRACE_INTERRUPT) + set_tsk_thread_flag(task, TIF_SIGPENDING); + else + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + spin_unlock(&utrace->lock); + } + + finish_report_reset(task, utrace, report); +} + +static inline void finish_callback_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + /* + * If utrace_control() was used, treat that like UTRACE_DETACH here. + */ + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { + engine->ops = &utrace_detached_ops; + report->detaches = true; + return; + } + + if (action < report->action) + report->action = action; + + if (action != UTRACE_STOP) { + if (action < report->resume_action) + report->resume_action = action; + + if (engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + clear_engine_wants_stop(engine); + spin_unlock(&utrace->lock); + } + + return; + } + + if (!engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + /* + * If utrace_control() came in and detached us + * before we got the lock, we must not stop now. + */ + if (unlikely(engine->ops == &utrace_detached_ops)) + report->detaches = true; + else + mark_engine_wants_stop(task, engine); + spin_unlock(&utrace->lock); + } +} + +/* + * Apply the return value of one engine callback to @report. + * Returns true if @engine detached and should not get any more callbacks. + */ +static bool finish_callback(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + u32 ret) +{ + report->result = ret & ~UTRACE_RESUME_MASK; + finish_callback_report(task, utrace, report, engine, + utrace_resume_action(ret)); + + /* + * Now that we have applied the effect of the return value, + * clear this so that utrace_barrier() can stop waiting. + * A subsequent utrace_control() can stop or resume @engine + * and know this was ordered after its callback's action. + * + * We don't need any barriers here because utrace_barrier() + * takes utrace->lock. If we touched engine->flags above, + * the lock guaranteed this change was before utrace_barrier() + * examined utrace->reporting. + */ + utrace->reporting = NULL; + + /* + * This is a good place to make sure tracing engines don't + * introduce too much latency under voluntary preemption. + */ + if (need_resched()) + cond_resched(); + + return engine->ops == &utrace_detached_ops; +} + +/* + * Start the callbacks for @engine to consider @event (a bit mask). + * This makes the report_quiesce() callback first. If @engine wants + * a specific callback for @event, we return the ops vector to use. + * If not, we return NULL. The return value from the ops->callback + * function called should be passed to finish_callback(). + */ +static const struct utrace_engine_ops *start_callback( + struct utrace *utrace, struct utrace_report *report, + struct utrace_engine *engine, struct task_struct *task, + unsigned long event) +{ + const struct utrace_engine_ops *ops; + unsigned long want; + + /* + * This barrier ensures that we've set utrace->reporting before + * we examine engine->flags or engine->ops. utrace_barrier() + * relies on this ordering to indicate that the effect of any + * utrace_control() and utrace_set_events() calls is in place + * by the time utrace->reporting can be seen to be NULL. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(). + * It makes sure that we never see the old ops vector with + * the new flags, in case the original vector had no report_quiesce. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if (want & UTRACE_EVENT(QUIESCE)) { + if (finish_callback(task, utrace, report, engine, + (*ops->report_quiesce)(report->action, + engine, task, + event))) + return NULL; + + /* + * finish_callback() reset utrace->reporting after the + * quiesce callback. Now we set it again (as above) + * before re-examining engine->flags, which could have + * been changed synchronously by ->report_quiesce or + * asynchronously by utrace_control() or utrace_set_events(). + */ + utrace->reporting = engine; + smp_mb(); + want = engine->flags; + } + + if (want & ENGINE_STOP) + report->action = UTRACE_STOP; + + if (want & event) { + report->spurious = false; + return ops; + } + + utrace->reporting = NULL; + return NULL; +} + +/* + * Do a normal reporting pass for engines interested in @event. + * @callback is the name of the member in the ops vector, and remaining + * args are the extras it takes after the standard three args. + */ +#define REPORT(task, utrace, report, event, callback, ...) \ + do { \ + start_report(utrace); \ + REPORT_CALLBACKS(, task, utrace, report, event, callback, \ + (report)->action, engine, current, \ + ## __VA_ARGS__); \ + finish_report(task, utrace, report, true); \ + } while (0) +#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ + do { \ + struct utrace_engine *engine; \ + const struct utrace_engine_ops *ops; \ + list_for_each_entry##rev(engine, &utrace->attached, entry) { \ + ops = start_callback(utrace, report, engine, task, \ + event); \ + if (!ops) \ + continue; \ + finish_callback(task, utrace, report, engine, \ + (*ops->callback)(__VA_ARGS__)); \ + } \ + } while (0) + +/* + * Called iff UTRACE_EVENT(EXEC) flag is set. + */ +void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), + report_exec, fmt, bprm, regs); +} + +static inline u32 do_report_syscall_entry(struct pt_regs *regs, + struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + u32 resume_report) +{ + start_report(utrace); + REPORT_CALLBACKS(_reverse, task, utrace, report, + UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, + resume_report | report->result | report->action, + engine, current, regs); + finish_report(task, utrace, report, false); + + if (report->action != UTRACE_STOP) + return 0; + + utrace_stop(task, utrace, report->resume_action); + + if (fatal_signal_pending(task)) { + /* + * We are continuing despite UTRACE_STOP because of a + * SIGKILL. Don't let the system call actually proceed. + */ + report->result = UTRACE_SYSCALL_ABORT; + } else if (utrace->resume <= UTRACE_REPORT) { + /* + * If we've been asked for another report after our stop, + * go back to report (and maybe stop) again before we run + * the system call. The second (and later) reports are + * marked with the UTRACE_SYSCALL_RESUMED flag so that + * engines know this is a second report at the same + * entry. This gives them the chance to examine the + * registers anew after they might have been changed + * while we were stopped. + */ + report->detaches = false; + report->spurious = true; + return UTRACE_SYSCALL_RESUMED; + } + + return 0; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. + * Return true to prevent the system call. + */ +bool utrace_report_syscall_entry(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + u32 resume_report = 0; + + do { + resume_report = do_report_syscall_entry(regs, task, utrace, + &report, resume_report); + } while (resume_report); + + return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. + */ +void utrace_report_syscall_exit(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), + report_syscall_exit, regs); +} + +/* + * Called iff UTRACE_EVENT(CLONE) flag is set. + * This notification call blocks the wake_up_new_task call on the child. + * So we must not quiesce here. tracehook_report_clone_complete will do + * a quiescence check momentarily. + */ +void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + /* + * We don't use the REPORT() macro here, because we need + * to clear utrace->cloning before finish_report(). + * After finish_report(), utrace can be a stale pointer + * in cases when report.action is still UTRACE_RESUME. + */ + start_report(utrace); + utrace->cloning = child; + + REPORT_CALLBACKS(, task, utrace, &report, + UTRACE_EVENT(CLONE), report_clone, + report.action, engine, task, clone_flags, child); + + utrace->cloning = NULL; + finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); + + /* + * For a vfork, we will go into an uninterruptible block waiting + * for the child. We need UTRACE_STOP to happen before this, not + * after. For CLONE_VFORK, utrace_finish_vfork() will be called. + */ + if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 1; + spin_unlock(&utrace->lock); + } +} + +/* + * We're called after utrace_report_clone() for a CLONE_VFORK. + * If UTRACE_STOP was left from the clone report, we stop here. + * After this, we'll enter the uninterruptible wait_for_completion() + * waiting for the child. + */ +void utrace_finish_vfork(struct task_struct *task) +{ + struct utrace *utrace = task_utrace_struct(task); + + if (utrace->vfork_stop) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 0; + spin_unlock(&utrace->lock); + utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ + } +} + +/* + * Called iff UTRACE_EVENT(JCTL) flag is set. + * + * Called with siglock held. + */ +void utrace_report_jctl(int notify, int what) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + spin_unlock_irq(&task->sighand->siglock); + + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), + report_jctl, what, notify); + + spin_lock_irq(&task->sighand->siglock); +} + +/* + * Called iff UTRACE_EVENT(EXIT) flag is set. + */ +void utrace_report_exit(long *exit_code) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + long orig_code = *exit_code; + + REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), + report_exit, orig_code, exit_code); + + if (report.action == UTRACE_STOP) + utrace_stop(task, utrace, report.resume_action); +} + +/* + * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. + * + * It is always possible that we are racing with utrace_release_task here. + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ +void utrace_report_death(struct task_struct *task, struct utrace *utrace, + bool group_dead, int signal) +{ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); + + /* + * We are presently considered "quiescent"--which is accurate + * inasmuch as we won't run any more user instructions ever again. + * But for utrace_control and utrace_set_events to be robust, they + * must be sure whether or not we will run any more callbacks. If + * a call comes in before we do, taking the lock here synchronizes + * us so we don't run any callbacks just disabled. Calls that come + * in while we're running the callbacks will see the exit.death + * flag and know that we are not yet fully quiescent for purposes + * of detach bookkeeping. + */ + spin_lock(&utrace->lock); + BUG_ON(utrace->death); + utrace->death = 1; + utrace->resume = UTRACE_RESUME; + splice_attaching(utrace); + spin_unlock(&utrace->lock); + + REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), + report_death, engine, task, group_dead, signal); + + spin_lock(&utrace->lock); + + /* + * After we unlock (possibly inside utrace_reap for callbacks) with + * this flag clear, competing utrace_control/utrace_set_events calls + * know that we've finished our callbacks and any detach bookkeeping. + */ + utrace->death = 0; + + if (utrace->reap) + /* + * utrace_release_task() was already called in parallel. + * We must complete its work now. + */ + utrace_reap(task, utrace); + else + utrace_reset(task, utrace); +} + +/* + * Finish the last reporting pass before returning to user mode. + */ +static void finish_resume_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + finish_report_reset(task, utrace, report); + + switch (report->action) { + case UTRACE_STOP: + utrace_stop(task, utrace, report->resume_action); + break; + + case UTRACE_INTERRUPT: + if (!signal_pending(task)) + set_tsk_thread_flag(task, TIF_SIGPENDING); + break; + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { + user_enable_block_step(task); + break; + } + + /* + * This means some callback is to blame for failing + * to check arch_has_block_step() itself. Warn and + * then fall through to treat it as SINGLESTEP. + */ + WARN_ON(1); + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) + user_enable_single_step(task); + else + /* + * This means some callback is to blame for failing + * to check arch_has_single_step() itself. Spew + * about it so the loser will fix his module. + */ + WARN_ON(1); + break; + + case UTRACE_REPORT: + case UTRACE_RESUME: + default: + user_disable_single_step(task); + break; + } +} + +/* + * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). + * We are close to user mode, and this is the place to report or stop. + * When we return, we're going to user mode or into the signals code. + */ +void utrace_resume(struct task_struct *task, struct pt_regs *regs) +{ + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + struct utrace_engine *engine; + + /* + * Some machines get here with interrupts disabled. The same arch + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ + local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal + * handler setup done but no report_signal following it. Clear + * the flag before we get to user so it doesn't confuse us later. + */ + if (unlikely(utrace->signal_handler)) { + spin_lock(&utrace->lock); + utrace->signal_handler = 0; + spin_unlock(&utrace->lock); + } + + /* + * Update our bookkeeping even if there are no callbacks made here. + */ + report.action = start_report(utrace); + + switch (report.action) { + case UTRACE_RESUME: + /* + * Anything we might have done was already handled by + * utrace_get_signal(), or this is an entirely spurious + * call. (The arch might use TIF_NOTIFY_RESUME for other + * purposes as well as calling us.) + */ + return; + case UTRACE_REPORT: + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) + break; + /* + * Do a simple reporting pass, with no specific + * callback after report_quiesce. + */ + report.action = UTRACE_RESUME; + list_for_each_entry(engine, &utrace->attached, entry) + start_callback(utrace, &report, engine, task, 0); + break; + default: + /* + * Even if this report was truly spurious, there is no need + * for utrace_reset() now. TIF_NOTIFY_RESUME was already + * cleared--it doesn't stay spuriously set. + */ + report.spurious = false; + break; + } + + /* + * Finish the report and either stop or get ready to resume. + * If utrace->resume was not UTRACE_REPORT, this applies its + * effect now (i.e. step or interrupt). + */ + finish_resume_report(task, utrace, &report); +} + +/* + * Return true if current has forced signal_pending(). + * + * This is called only when current->utrace_flags is nonzero, so we know + * that current->utrace must be set. It's not inlined in tracehook.h + * just so that struct utrace can stay opaque outside this file. + */ +bool utrace_interrupt_pending(void) +{ + return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; +} + +/* + * Take the siglock and push @info back on our queue. + * Returns with @task->sighand->siglock held. + */ +static void push_back_signal(struct task_struct *task, siginfo_t *info) + __acquires(task->sighand->siglock) +{ + struct sigqueue *q; + + if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ + spin_lock_irq(&task->sighand->siglock); + return; + } + + q = sigqueue_alloc(); + if (likely(q)) { + q->flags = 0; + copy_siginfo(&q->info, info); + } + + spin_lock_irq(&task->sighand->siglock); + + sigaddset(&task->pending.signal, info->si_signo); + if (likely(q)) + list_add(&q->list, &task->pending.list); + + set_tsk_thread_flag(task, TIF_SIGPENDING); +} + +/* + * This is the hook from the signals code, called with the siglock held. + * Here is the ideal place to stop. We also dequeue and intercept signals. + */ +int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + siginfo_t *info, struct k_sigaction *return_ka) + __releases(task->sighand->siglock) + __acquires(task->sighand->siglock) +{ + struct utrace *utrace; + struct k_sigaction *ka; + INIT_REPORT(report); + struct utrace_engine *engine; + const struct utrace_engine_ops *ops; + unsigned long event, want; + u32 ret; + int signr; + + utrace = task_utrace_struct(task); + if (utrace->resume < UTRACE_RESUME || + utrace->pending_attach || utrace->signal_handler) { + enum utrace_resume_action resume; + + /* + * We've been asked for an explicit report before we + * even check for pending signals. + */ + + spin_unlock_irq(&task->sighand->siglock); + + spin_lock(&utrace->lock); + + splice_attaching(utrace); + + report.result = utrace->signal_handler ? + UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; + utrace->signal_handler = 0; + + resume = utrace->resume; + utrace->resume = UTRACE_RESUME; + + spin_unlock(&utrace->lock); + + /* + * Make sure signal_pending() only returns true + * if there are real signals pending. + */ + if (signal_pending(task)) { + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); + } + + if (resume > UTRACE_REPORT) { + /* + * We only got here to process utrace->resume. + * Despite no callbacks, this report is not spurious. + */ + report.action = resume; + report.spurious = false; + finish_resume_report(task, utrace, &report); + return -1; + } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + /* + * We only got here to clear utrace->signal_handler. + */ + return -1; + } + + /* + * Do a reporting pass for no signal, just for EVENT(QUIESCE). + * The engine callbacks can fill in *info and *return_ka. + * We'll pass NULL for the @orig_ka argument to indicate + * that there was no original signal. + */ + event = 0; + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || + unlikely(task->signal->group_stop_count)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally + * or participate in group-stop. + */ + return 0; + } else { + /* + * Steal the next signal so we can let tracing engines + * examine it. From the signal number and sigaction, + * determine what normal delivery would do. If no + * engine perturbs it, we'll do that by returning the + * signal number after setting *return_ka. + */ + signr = dequeue_signal(task, &task->blocked, info); + if (signr == 0) + return signr; + BUG_ON(signr != info->si_signo); + + ka = &task->sighand->action[signr - 1]; + *return_ka = *ka; + + /* + * We are never allowed to interfere with SIGKILL. + * Just punt after filling in *return_ka for our caller. + */ + if (signr == SIGKILL) + return signr; + + if (ka->sa.sa_handler == SIG_IGN) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (ka->sa.sa_handler != SIG_DFL) { + event = UTRACE_EVENT(SIGNAL); + report.result = UTRACE_SIGNAL_DELIVER; + } else if (sig_kernel_coredump(signr)) { + event = UTRACE_EVENT(SIGNAL_CORE); + report.result = UTRACE_SIGNAL_CORE; + } else if (sig_kernel_ignore(signr)) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (signr == SIGSTOP) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_STOP; + } else if (sig_kernel_stop(signr)) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_TSTP; + } else { + event = UTRACE_EVENT(SIGNAL_TERM); + report.result = UTRACE_SIGNAL_TERM; + } + + /* + * Now that we know what event type this signal is, we + * can short-circuit if no engines care about those. + */ + if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) + return signr; + + /* + * We have some interested engines, so tell them about + * the signal and let them change its disposition. + */ + spin_unlock_irq(&task->sighand->siglock); + } + + /* + * This reporting pass chooses what signal disposition we'll act on. + */ + list_for_each_entry(engine, &utrace->attached, entry) { + /* + * See start_callback() comment about this barrier. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(), + * see start_callback() comments. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { + utrace->reporting = NULL; + continue; + } + + if (ops->report_signal) + ret = (*ops->report_signal)( + report.result | report.action, engine, task, + regs, info, ka, return_ka); + else + ret = (report.result | (*ops->report_quiesce)( + report.action, engine, task, event)); + + /* + * Avoid a tight loop reporting again and again if some + * engine is too stupid. + */ + switch (utrace_resume_action(ret)) { + default: + break; + case UTRACE_INTERRUPT: + case UTRACE_REPORT: + ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; + break; + } + + finish_callback(task, utrace, &report, engine, ret); + } + + /* + * We express the chosen action to the signals code in terms + * of a representative signal whose default action does it. + * Our caller uses our return value (signr) to decide what to + * do, but uses info->si_signo as the signal number to report. + */ + switch (utrace_signal_action(report.result)) { + case UTRACE_SIGNAL_TERM: + signr = SIGTERM; + break; + + case UTRACE_SIGNAL_CORE: + signr = SIGQUIT; + break; + + case UTRACE_SIGNAL_STOP: + signr = SIGSTOP; + break; + + case UTRACE_SIGNAL_TSTP: + signr = SIGTSTP; + break; + + case UTRACE_SIGNAL_DELIVER: + signr = info->si_signo; + + if (return_ka->sa.sa_handler == SIG_DFL) { + /* + * We'll do signr's normal default action. + * For ignore, we'll fall through below. + * For stop/death, break locks and returns it. + */ + if (likely(signr) && !sig_kernel_ignore(signr)) + break; + } else if (return_ka->sa.sa_handler != SIG_IGN && + likely(signr)) { + /* + * Complete the bookkeeping after the report. + * The handler will run. If an engine wanted to + * stop or step, then make sure we do another + * report after signal handler setup. + */ + if (report.action != UTRACE_RESUME) + report.action = UTRACE_INTERRUPT; + finish_report(task, utrace, &report, true); + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + /* + * We do the SA_ONESHOT work here since the + * normal path will only touch *return_ka now. + */ + if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { + return_ka->sa.sa_flags &= ~SA_ONESHOT; + if (likely(valid_signal(signr))) { + ka = &task->sighand->action[signr - 1]; + ka->sa.sa_handler = SIG_DFL; + } + } + + return signr; + } + + /* Fall through for an ignored signal. */ + + case UTRACE_SIGNAL_IGN: + case UTRACE_SIGNAL_REPORT: + default: + /* + * If the signal is being ignored, then we are on the way + * directly back to user mode. We can stop here, or step, + * as in utrace_resume(), above. After we've dealt with that, + * our caller will relock and come back through here. + */ + finish_resume_report(task, utrace, &report); + + if (unlikely(fatal_signal_pending(task))) { + /* + * The only reason we woke up now was because of a + * SIGKILL. Don't do normal dequeuing in case it + * might get a signal other than SIGKILL. That would + * perturb the death state so it might differ from + * what the debugger would have allowed to happen. + * Instead, pluck out just the SIGKILL to be sure + * we'll die immediately with nothing else different + * from the quiescent state the debugger wanted us in. + */ + sigset_t sigkill_only; + siginitsetinv(&sigkill_only, sigmask(SIGKILL)); + spin_lock_irq(&task->sighand->siglock); + signr = dequeue_signal(task, &sigkill_only, info); + BUG_ON(signr != SIGKILL); + *return_ka = task->sighand->action[SIGKILL - 1]; + return signr; + } + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { + push_back_signal(task, info); + spin_unlock_irq(&task->sighand->siglock); + } + + return -1; + } + + /* + * Complete the bookkeeping after the report. + * This sets utrace->resume if UTRACE_STOP was used. + */ + finish_report(task, utrace, &report, true); + + return_ka->sa.sa_handler = SIG_DFL; + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + if (sig_kernel_stop(signr)) + task->signal->flags |= SIGNAL_STOP_DEQUEUED; + + return signr; +} + +/* + * This gets called after a signal handler has been set up. + * We set a flag so the next report knows it happened. + * If we're already stepping, make sure we do a report_signal. + * If not, make sure we get into utrace_resume() where we can + * clear the signal_handler flag before resuming. + */ +void utrace_signal_handler(struct task_struct *task, int stepping) +{ + struct utrace *utrace = task_utrace_struct(task); + + spin_lock(&utrace->lock); + + utrace->signal_handler = 1; + if (utrace->resume > UTRACE_INTERRUPT) { + if (stepping) { + utrace->resume = UTRACE_INTERRUPT; + set_tsk_thread_flag(task, TIF_SIGPENDING); + } else if (utrace->resume == UTRACE_RESUME) { + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + } + } + + spin_unlock(&utrace->lock); +} + +/** + * utrace_prepare_examine - prepare to examine thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: temporary state, a &struct utrace_examiner pointer + * + * This call prepares to safely examine the thread @target using + * &struct user_regset calls, or direct access to thread-synchronous fields. + * + * When @target is current, this call is superfluous. When @target is + * another thread, it must be held stopped via %UTRACE_STOP by @engine. + * + * This call may block the caller until @target stays stopped, so it must + * be called only after the caller is sure @target is about to unschedule. + * This means a zero return from a utrace_control() call on @engine giving + * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to + * @engine that used %UTRACE_STOP in its return value. + * + * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was + * not used. If @target has started running again despite %UTRACE_STOP + * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. + * + * When this call returns zero, it's safe to use &struct user_regset + * calls and task_user_regset_view() on @target and to examine some of + * its fields directly. When the examination is complete, a + * utrace_finish_examine() call must follow to check whether it was + * completed safely. + */ +int utrace_prepare_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->exit_state)) + ret = -ESRCH; + else { + exam->state = target->state; + if (unlikely(exam->state == TASK_RUNNING)) + ret = -EAGAIN; + else + get_task_struct(target); + } + rcu_read_unlock(); + + if (likely(!ret)) { + exam->ncsw = wait_task_inactive(target, exam->state); + put_task_struct(target); + if (unlikely(!exam->ncsw)) + ret = -EAGAIN; + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_prepare_examine); + +/** + * utrace_finish_examine - complete an examination of thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: pointer passed to utrace_prepare_examine() call + * + * This call completes an examination on the thread @target begun by a + * paired utrace_prepare_examine() call with the same arguments that + * returned success (zero). + * + * When @target is current, this call is superfluous. When @target is + * another thread, this returns zero if @target has remained unscheduled + * since the paired utrace_prepare_examine() call returned zero. + * + * When this returns an error, any examination done since the paired + * utrace_prepare_examine() call is unreliable and the data extracted + * should be discarded. The error is -%EINVAL if @engine is not + * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. + */ +int utrace_finish_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->state != exam->state)) + ret = -EAGAIN; + else + get_task_struct(target); + rcu_read_unlock(); + + if (likely(!ret)) { + unsigned long ncsw = wait_task_inactive(target, exam->state); + if (unlikely(ncsw != exam->ncsw)) + ret = -EAGAIN; + put_task_struct(target); + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_finish_examine); + +/* + * This is declared in linux/regset.h and defined in machine-dependent + * code. We put the export here to ensure no machine forgets it. + */ +EXPORT_SYMBOL_GPL(task_user_regset_view); + +/* + * Called with rcu_read_lock() held. + */ +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) +{ + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} From oleg at redhat.com Sun Nov 22 22:12:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:27 +0100 Subject: [PATCH 1] ptrace: cleanup ptrace_init_task()->ptrace_link() path Message-ID: <20091122221227.GA8682@redhat.com> (already in mm: ptrace-cleanup-ptrace_init_task-ptrace_link-path.patch) No functional changes. ptrace_init_task() looks confusing, as if we always auto-attach when "bool ptrace" argument is true, while in fact we attach only if current is traced. Make the code more explicit and kill now unused ptrace_link(). Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/ptrace.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) --- V1/include/linux/ptrace.h~1_PTRACE_INIT_TASK 2009-06-19 01:12:47.000000000 +0200 +++ V1/include/linux/ptrace.h 2009-11-22 19:38:22.000000000 +0100 @@ -105,12 +105,7 @@ static inline int ptrace_reparented(stru { return child->real_parent != child->parent; } -static inline void ptrace_link(struct task_struct *child, - struct task_struct *new_parent) -{ - if (unlikely(child->ptrace)) - __ptrace_link(child, new_parent); -} + static inline void ptrace_unlink(struct task_struct *child) { if (unlikely(child->ptrace)) @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; - if (unlikely(ptrace)) { + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { child->ptrace = current->ptrace; - ptrace_link(child, current->parent); + __ptrace_link(child, current->parent); } } From oleg at redhat.com Sun Nov 22 22:12:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:30 +0100 Subject: [PATCH 2] signals: check ->group_stop_count after tracehook_get_signal() Message-ID: <20091122221230.GA8689@redhat.com> (already in mm: signals-check-group_stop_count-after-tracehook_get_signal.patch) Move the call to do_signal_stop() down, after tracehook call. This makes ->group_stop_count condition visible to tracers before do_signal_stop() will participate in this group-stop. Currently the patch has no effect, tracehook_get_signal() always returns 0. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- kernel/signal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) --- V1/kernel/signal.c~2_DO_SIGNAL_STOP_AFTER_TRACEHOOK 2009-11-22 19:45:54.000000000 +0100 +++ V1/kernel/signal.c 2009-11-22 19:46:41.000000000 +0100 @@ -1807,11 +1807,6 @@ relock: for (;;) { struct k_sigaction *ka; - - if (unlikely(signal->group_stop_count > 0) && - do_signal_stop(0)) - goto relock; - /* * Tracing can induce an artifical signal and choose sigaction. * The return value in @signr determines the default action, @@ -1823,6 +1818,10 @@ relock: if (unlikely(signr != 0)) ka = return_ka; else { + if (unlikely(signal->group_stop_count > 0) && + do_signal_stop(0)) + goto relock; + signr = dequeue_signal(current, ¤t->blocked, info); From oleg at redhat.com Sun Nov 22 22:12:33 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:33 +0100 Subject: [PATCH 3] ptrace: introduce user_single_step_siginfo() helper Message-ID: <20091122221233.GA8692@redhat.com> (already in mm: ptrace-introduce-user_single_step_siginfo-helper.patch) Suggested by Roland. Currently there is no way to synthesize a single-stepping trap in the arch-independent manner. This patch adds the default helper which fills siginfo_t, arch/ can can override it. Architetures which implement user_enable_single_step() should add user_single_step_siginfo() also. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/ptrace.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) --- V1/include/linux/ptrace.h~3_DEFAULT_HELPER 2009-11-22 20:09:15.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-22 20:10:37.000000000 +0100 @@ -273,6 +273,18 @@ static inline void user_enable_block_ste } #endif /* arch_has_block_step */ +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO +extern void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info); +#else +static inline void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; +} +#endif + #ifndef arch_ptrace_stop_needed /** * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called From oleg at redhat.com Sun Nov 22 22:12:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:35 +0100 Subject: [PATCH 4] ptrace: implement user_single_step_siginfo() Message-ID: <20091122221235.GA8695@redhat.com> (already in mm: ptrace-powerpc-implement-user_single_step_siginfo.patch) Suggested by Roland. Implement user_single_step_siginfo() for powerpc. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/powerpc/include/asm/ptrace.h | 2 ++ arch/powerpc/kernel/traps.c | 9 +++++++++ 2 files changed, 11 insertions(+) --- V1/arch/powerpc/include/asm/ptrace.h~4_PPC_HELPER 2009-06-16 17:01:38.000000000 +0200 +++ V1/arch/powerpc/include/asm/ptrace.h 2009-11-22 20:16:17.000000000 +0100 @@ -140,6 +140,8 @@ extern void user_enable_single_step(stru extern void user_enable_block_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *); +#define ARCH_HAS_USER_SINGLE_STEP_INFO + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ --- V1/arch/powerpc/kernel/traps.c~4_PPC_HELPER 2009-06-16 17:01:38.000000000 +0200 +++ V1/arch/powerpc/kernel/traps.c 2009-11-22 20:16:17.000000000 +0100 @@ -174,6 +174,15 @@ int die(const char *str, struct pt_regs return 0; } +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = TRAP_TRACE; + info->si_addr = (void __user *)regs->nip; +} + void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { siginfo_t info; From oleg at redhat.com Sun Nov 22 22:12:37 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:37 +0100 Subject: [PATCH 5] ptrace: change tracehook_report_syscall_exit() to handle stepping Message-ID: <20091122221237.GA8702@redhat.com> (already in mm: ptrace-change-tracehook_report_syscall_exit-to-handle-stepping.patch) Suggested by Roland. Change tracehook_report_syscall_exit() to look at step flag and send the trap signal if needed. This change affects ia64, microblaze, parisc, powerpc, sh. They pass nonzero "step" argument to tracehook but since it was ignored the tracee reports via ptrace_notify(), this is not right and not consistent. - PTRACE_SETSIGINFO doesn't work - if the tracer resumes the tracee with signr != 0 the new signal is generated rather than delivering it - If PT_TRACESYSGOOD is set the tracee reports the wrong exit_code I don't have a powerpc machine, but I think this test-case should see the difference: #include #include #include #include #include int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); getppid(); return 0; } assert(pid == wait(&status)); assert(ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == 0); assert(ptrace(PTRACE_SYSCALL, pid, 0,0) == 0); assert(pid == wait(&status)); assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); assert(pid == wait(&status)); if (status == 0x57F) return 0; printf("kernel bug: status=%X shouldn't have 0x80\n", status); return 1; } Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/tracehook.h | 7 +++++++ 1 file changed, 7 insertions(+) --- V1/include/linux/tracehook.h~5_TRACEHOOK_HANDLE_STEPPING 2009-09-24 21:38:54.000000000 +0200 +++ V1/include/linux/tracehook.h 2009-11-22 20:24:14.000000000 +0100 @@ -134,6 +134,13 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); + return; + } + ptrace_report_syscall(regs); } From oleg at redhat.com Sun Nov 22 22:12:39 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:39 +0100 Subject: [PATCH 6] ptrace: x86: implement user_single_step_siginfo() Message-ID: <20091122221239.GA8705@redhat.com> (already in mm: ptrace-x86-implement-user_single_step_siginfo.patch) Suggested by Roland. Implement user_single_step_siginfo() for x86. Extract this code from send_sigtrap(). Since x86 calls tracehook_report_syscall_exit(step => 0) the new helper is not used yet. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/x86/include/asm/ptrace.h | 2 ++ arch/x86/kernel/ptrace.c | 30 +++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) --- V1/arch/x86/include/asm/ptrace.h~6_X86_HELPER 2009-06-11 14:16:46.000000000 +0200 +++ V1/arch/x86/include/asm/ptrace.h 2009-11-22 20:26:48.000000000 +0100 @@ -230,6 +230,8 @@ extern void user_enable_block_step(struc #define arch_has_block_step() (boot_cpu_data.x86 >= 6) #endif +#define ARCH_HAS_USER_SINGLE_STEP_INFO + struct user_desc; extern int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *info); --- V1/arch/x86/kernel/ptrace.c~6_X86_HELPER 2009-09-23 21:12:01.000000000 +0200 +++ V1/arch/x86/kernel/ptrace.c 2009-11-22 20:26:48.000000000 +0100 @@ -1437,21 +1437,33 @@ const struct user_regset_view *task_user #endif } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, - int error_code, int si_code) +static void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, + struct siginfo *info) { - struct siginfo info; - tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; - memset(&info, 0, sizeof(info)); - info.si_signo = SIGTRAP; - info.si_code = si_code; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = si_code; + info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; +} - /* User-mode ip? */ - info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, + struct siginfo *info) +{ + fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); +} +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) +{ + struct siginfo info; + + fill_sigtrap_info(tsk, regs, error_code, si_code, &info); /* Send us the fake SIGTRAP */ force_sig_info(SIGTRAP, &info, tsk); } From oleg at redhat.com Sun Nov 22 22:12:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:42 +0100 Subject: [PATCH 7] ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping Message-ID: <20091122221242.GA8708@redhat.com> (already in mm: ptrace-x86-change-syscall_trace_leave-to-rely-on-tracehook-when-stepping.patch) Suggested by Roland. Unlike powepc, x86 always calls tracehook_report_syscall_exit(step) with step = 0, and sends the trap by hand. This results in unnecessary SIGTRAP when PTRACE_SINGLESTEP follows the syscall-exit stop. Change syscall_trace_leave() to pass the correct "step" argument to tracehook and remove the send_sigtrap() logic. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/x86/kernel/ptrace.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) --- V1/arch/x86/kernel/ptrace.c~7_X86_CONVERT_SYSCALL_LEAVE 2009-11-22 20:26:48.000000000 +0100 +++ V1/arch/x86/kernel/ptrace.c 2009-11-22 20:28:37.000000000 +0100 @@ -1528,29 +1528,22 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + bool step; + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->ax); - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); - /* * If TIF_SYSCALL_EMU is set, we only get here because of * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). * We already reported this syscall instruction in - * syscall_trace_enter(), so don't do any more now. - */ - if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) - return; - - /* - * If we are single-stepping, synthesize a trap to follow the - * system call instruction. + * syscall_trace_enter(). */ - if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) - send_sigtrap(current, regs, 0, TRAP_BRKPT); + step = unlikely(test_thread_flag(TIF_SINGLESTEP)) && + !test_thread_flag(TIF_SYSCALL_EMU); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } From oleg at redhat.com Sun Nov 22 22:12:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:44 +0100 Subject: [PATCH 8] tracehooks: kill some PT_PTRACED checks Message-ID: <20091122221244.GA8715@redhat.com> No functional changes, preparation for utrace-ptrace. task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill some PT_PTRACED checks in tracehook.h to ensure the result is the same with or without utrace which doesn't set PT_PTRACED. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- V1/include/linux/tracehook.h~8_TRACEHOOK_KILL_PTRACED_CHECKS 2009-11-22 20:24:14.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-22 20:43:09.000000000 +0100 @@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec( { int unsafe = 0; int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { + if (ptrace) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else @@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (task_ptrace(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { - return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; + return notify ?: task_ptrace(current) ? why : 0; } /** From oleg at redhat.com Sun Nov 22 22:12:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:46 +0100 Subject: [PATCH 9] tracehooks: check PT_PTRACED before reporting the single-step Message-ID: <20091122221246.GA8718@redhat.com> No functional changes, preparation for utrace-ptrace. tracehook_report_syscall_exit() and tracehook_signal_handler() assume that only ptrace can set TIF_SINGLESTEP. Currently this is true but we are going to change this, the stepping logic will be moved into utrace layer. Change this code to check PT_PTRACED, ptrace-utrace doesn't set it. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- V1/include/linux/tracehook.h~9_SIGNAL_HANDLER_CK_PTRACE 2009-11-22 20:43:09.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-22 21:01:33.000000000 +0100 @@ -134,7 +134,7 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { - if (step) { + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); @@ -386,7 +386,7 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { - if (stepping) + if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } From oleg at redhat.com Sun Nov 22 22:12:48 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:48 +0100 Subject: [PATCH 10] ptrace_signal: check PT_PTRACED before reporting a signal Message-ID: <20091122221248.GA8725@redhat.com> No functional changes, preparation for utrace-ptrace. Change ptrace_signal() to check PT_PTRACED instead of task_ptrace() != 0. Currently this is the same, PT_PTRACED must be always set if the task is ptraced. This change is needed to make sure ptrace_signal() does nothing if ptrace is implemented on top of utrace, eventually this code will be removed completely. Signed-off-by: Oleg Nesterov --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- V1/kernel/signal.c~10_PTRACE_SIGNAL_CK_PTRACED 2009-11-22 19:46:41.000000000 +0100 +++ V1/kernel/signal.c 2009-11-22 21:30:52.000000000 +0100 @@ -1731,7 +1731,7 @@ static int do_signal_stop(int signr) static int ptrace_signal(int signr, siginfo_t *info, struct pt_regs *regs, void *cookie) { - if (!task_ptrace(current)) + if (!(task_ptrace(current) & PT_PTRACED)) return signr; ptrace_signal_deliver(regs, cookie); From oleg at redhat.com Sun Nov 22 22:12:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:50 +0100 Subject: [PATCH 11] export __ptrace_detach() and do_notify_parent_cldstop() Message-ID: <20091122221250.GA8728@redhat.com> Export __ptrace_detach() and do_notify_parent_cldstop() for ptrace-utrace. Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 1 + include/linux/sched.h | 1 + kernel/ptrace.c | 2 +- kernel/signal.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) --- V1/include/linux/ptrace.h~11_EXPORT_2_HELPERS 2009-11-22 20:10:37.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-22 21:45:53.000000000 +0100 @@ -85,6 +85,7 @@ extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); +extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee); extern int ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); --- V1/include/linux/sched.h~11_EXPORT_2_HELPERS 2009-09-24 21:38:54.000000000 +0200 +++ V1/include/linux/sched.h 2009-11-22 21:43:20.000000000 +0100 @@ -2060,6 +2060,7 @@ extern int kill_pgrp(struct pid *pid, in extern int kill_pid(struct pid *pid, int sig, int priv); extern int kill_proc_info(int, struct siginfo *, pid_t); extern int do_notify_parent(struct task_struct *, int); +extern void do_notify_parent_cldstop(struct task_struct *, int); extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); --- V1/kernel/ptrace.c~11_EXPORT_2_HELPERS 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/ptrace.c 2009-11-22 21:50:11.000000000 +0100 @@ -271,7 +271,7 @@ static int ignoring_children(struct sigh * reap it now, in that case we must also wake up sub-threads sleeping in * do_wait(). */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) { __ptrace_unlink(p); --- V1/kernel/signal.c~11_EXPORT_2_HELPERS 2009-11-22 21:30:52.000000000 +0100 +++ V1/kernel/signal.c 2009-11-22 21:51:17.000000000 +0100 @@ -1461,7 +1461,7 @@ int do_notify_parent(struct task_struct return ret; } -static void do_notify_parent_cldstop(struct task_struct *tsk, int why) +void do_notify_parent_cldstop(struct task_struct *tsk, int why) { struct siginfo info; unsigned long flags; From oleg at redhat.com Sun Nov 22 22:12:53 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:53 +0100 Subject: [PATCH 12] reorder the code in kernel/ptrace.c Message-ID: <20091122221253.GA8731@redhat.com> No functional changes, preparation for the next patch. Move the code which can be shared with ptrace-utrace up, before __ptrace_link(). This way ptrace-utrace needs a single #ifdef in ptrace.c. --- kernel/ptrace.c | 556 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 278 insertions(+), 278 deletions(-) --- V1/kernel/ptrace.c~12_REORDER_PTRACE_C 2009-11-22 21:50:11.000000000 +0100 +++ V1/kernel/ptrace.c 2009-11-22 22:03:32.000000000 +0100 @@ -23,6 +23,284 @@ #include #include +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ /* * ptrace a task: make the debugger its new parent and @@ -117,53 +395,6 @@ int ptrace_check_attach(struct task_stru return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -243,57 +474,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; @@ -347,56 +527,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -457,7 +587,6 @@ static int ptrace_setsiginfo(struct task return error; } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -580,93 +709,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -718,47 +761,4 @@ int compat_ptrace_request(struct task_st return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Sun Nov 22 22:12:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 22 Nov 2009 23:12:56 +0100 Subject: [PATCH 13] implement utrace-ptrace Message-ID: <20091122221255.GA8739@redhat.com> The patch adds the new file, kernel/ptrace-utrace.c, which contains the new implementation of ptrace over utrace. This file is not compiled until we have CONFIG_UTRACE option, will be added by utrace.patch. --- include/linux/ptrace.h | 2 kernel/Makefile | 1 kernel/ptrace.c | 2 kernel/ptrace-utrace.c | 1118 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1122 insertions(+), 1 deletion(-) --- V1/include/linux/ptrace.h~13_UTRACE_PTRACE 2009-11-22 21:45:53.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-22 22:19:21.000000000 +0100 @@ -79,7 +79,7 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ - +extern void ptrace_notify_stop(struct task_struct *tracee); extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); --- V1/kernel/Makefile~13_UTRACE_PTRACE 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/Makefile 2009-11-22 22:20:55.000000000 +0100 @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ --- V1/kernel/ptrace.c~13_UTRACE_PTRACE 2009-11-22 22:03:32.000000000 +0100 +++ V1/kernel/ptrace.c 2009-11-22 22:16:18.000000000 +0100 @@ -302,6 +302,7 @@ asmlinkage long compat_sys_ptrace(compat } #endif /* CONFIG_COMPAT */ +#ifndef CONFIG_UTRACE /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -762,3 +763,4 @@ int compat_ptrace_request(struct task_st return ret; } #endif /* CONFIG_COMPAT */ +#endif /* CONFIG_UTRACE */ --- /dev/null 2009-11-22 14:49:16.630265461 +0100 +++ V1/kernel/ptrace-utrace.c 2009-11-21 22:15:51.000000000 +0100 @@ -0,0 +1,1118 @@ +/* + * linux/kernel/ptrace.c + * + * (C) Copyright 1999 Linus Torvalds + * + * Common interfaces for "ptrace()" which we do not want + * to continually duplicate across every architecture. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; + + int signr; + siginfo_t *siginfo; + + int stop_code; + unsigned long eventmsg; + + enum utrace_resume_action resume; +}; + +#define PT_UTRACED 0x00001000 + +#define PTRACE_O_SYSEMU 0x100 + +#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) +#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) +#define PTRACE_EVENT_SIGTRAP (3 << 16) +#define PTRACE_EVENT_SIGNAL (4 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF + +static inline bool ptrace_event_pending(struct ptrace_context *ctx) +{ + return ctx->stop_code != 0; +} + +static inline int get_stop_event(struct ptrace_context *ctx) +{ + return ctx->stop_code >> 8; +} + +static inline void set_stop_code(struct ptrace_context *ctx, int event) +{ + ctx->stop_code = (event << 8) | SIGTRAP; +} + +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) +{ + 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 *ctx; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + ctx = ptrace_context(engine); + if (unlikely(ctx->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. + */ + ctx->options = 0; + ctx->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + ctx->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 *ctx; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (unlikely(!ctx)) + return ERR_PTR(-ENOMEM); + + ctx->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, ctx); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(ctx); + } + + return engine; +} + +static inline int ptrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *ctx = 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; + + ctx->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_events(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; +} + +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 void ptrace_detach_task(struct task_struct *tracee, int sig) +{ + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; + + if (unlikely(IS_ERR(engine))) + return; + + if (sig) { + struct ptrace_context *ctx = ptrace_context(engine); + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL_EXIT: + if (voluntary) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (voluntary) + ctx->signr = sig; + ctx->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + ptrace_wake_up(tracee, engine, action, voluntary); + utrace_engine_put(engine); +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + ptrace_detach_task(tracee, 0); +} + +static u32 ptrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx) && + !signal_group_exit(task->signal)); + + set_stop_code(ctx, PTRACE_EVENT_EXIT); + ctx->eventmsg = *code; + + return UTRACE_STOP; +} + +static void ptrace_clone_attach(struct task_struct *parent, + struct task_struct *child, + int options) +{ + struct task_struct *tracer; + bool abort = true; + + if (unlikely(ptrace_attach_task(child, options))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); +} + +/* + * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). + * Called when we are going to emulate the stop before SYSCALL_EXIT. + */ +static void suppress_sigtrap(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) + user_disable_single_step(task); +} + +static u32 ptrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int event = 0; + + WARN_ON(ptrace_event_pending(ctx)); + + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { + if (ctx->options & PTRACE_O_TRACEVFORK) + event = PTRACE_EVENT_VFORK; + else if (ctx->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (ctx->options & PTRACE_O_TRACECLONE) + event = PTRACE_EVENT_CLONE; + } else if (ctx->options & PTRACE_O_TRACEFORK) { + event = PTRACE_EVENT_FORK; + } + /* + * Any of these reports implies auto-attaching the new child. + * So does CLONE_PTRACE, even with no event to report. + */ + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(parent, child, ctx->options); + + if (!event) + return UTRACE_RESUME; + + suppress_sigtrap(parent); + + set_stop_code(ctx, event); + ctx->eventmsg = child->pid; + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; +} + +static inline void set_syscall_code(struct ptrace_context *ctx, int event) +{ + set_stop_code(ctx, event); + if (ctx->options & PTRACE_O_TRACESYSGOOD) + ctx->stop_code |= 0x80; +} + +static u32 ptrace_report_syscall_entry(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (action & UTRACE_SYSCALL_RESUMED) { + /* + * We already reported the first time. + * Nothing more to do now. + */ + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + return utrace_syscall_action(action) | UTRACE_RESUME; + } + + WARN_ON(ptrace_event_pending(ctx)); + + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); + + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { + suppress_sigtrap(task); + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + } + + /* + * Stop now to report. We will get another callback after + * we resume, with the UTRACE_SYSCALL_RESUMED flag set. + */ + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + if (ctx->resume != UTRACE_RESUME) { + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && + ctx->resume != UTRACE_SINGLESTEP); + ctx->resume = UTRACE_RESUME; + + ctx->signr = SIGTRAP; + return UTRACE_INTERRUPT; + } + + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + return UTRACE_STOP; +} + +static u32 ptrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx)); + + if (!(ctx->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, task, 0); + return UTRACE_RESUME; + } + + suppress_sigtrap(task); + set_stop_code(ctx, PTRACE_EVENT_EXEC); + + return UTRACE_STOP; +} + +static void ptrace_send_sigtrap(struct task_struct *task, siginfo_t *info) +{ + user_single_step_siginfo(task, task_pt_regs(task), info); + force_sig_info(SIGTRAP, info, task); +} + +static enum utrace_signal_action resume_signal(struct task_struct *task, + struct ptrace_context *ctx, + struct k_sigaction *return_ka) +{ + siginfo_t *info = ctx->siginfo; + int signr = ctx->signr; + + ctx->siginfo = NULL; + ctx->signr = 0; + + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(&task->blocked, signr)) { + send_sig_info(signr, info, task); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[signr - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; +} + +static u32 ptrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct ptrace_context *ctx = ptrace_context(engine); + enum utrace_resume_action resume = ctx->resume; + + if (ptrace_event_pending(ctx)) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + if (WARN_ON(ctx->siginfo)) + ctx->siginfo = NULL; + + if (resume != UTRACE_RESUME) { + WARN_ON(resume != UTRACE_BLOCKSTEP && + resume != UTRACE_SINGLESTEP); + + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + case UTRACE_SIGNAL_REPORT: + if (!ctx->siginfo) { + if (ctx->signr) { + /* set by ptrace_resume(SYSCALL_EXIT) */ + WARN_ON(ctx->signr != SIGTRAP); + ptrace_send_sigtrap(task, info); + } + + return resume | UTRACE_SIGNAL_IGN; + } + + if (WARN_ON(ctx->siginfo != info)) + return resume | UTRACE_SIGNAL_IGN; + + return resume | resume_signal(task, ctx, return_ka); + + default: + break; + } + + WARN_ON(ctx->siginfo); + ctx->siginfo = info; + /* + * ctx->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); + + ctx->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; +} + +static u32 ptrace_report_quiesce(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + return event ? UTRACE_RESUME : ctx->resume; +} + +static void ptrace_release(void *data) +{ + kfree(data); +} + +static const struct utrace_engine_ops ptrace_utrace_ops = { + .report_signal = ptrace_report_signal, + .report_quiesce = ptrace_report_quiesce, + .report_exec = ptrace_report_exec, + .report_exit = ptrace_report_exit, + .report_clone = ptrace_report_clone, + .report_syscall_entry = ptrace_report_syscall_entry, + .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, +}; + +int ptrace_check_attach(struct task_struct *child, int kill) +{ + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret = -ESRCH; + + engine = ptrace_lookup_engine(child); + if (IS_ERR(engine)) + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + + if (!task_is_stopped_or_traced(child)) + goto out; + /* + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. + */ + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: + utrace_engine_put(engine); + return ret; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + retval = ptrace_attach_task(task, 0); + if (unlikely(retval)) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + + BUG_ON(task->ptrace); + task->ptrace = PT_UTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/* + * Performs checks and sets PT_UTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + bool detach = true; + int ret = ptrace_attach_task(current, 0); + + if (unlikely(ret)) + return ret; + + ret = -EPERM; + write_lock_irq(&tasklist_lock); + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_UTRACED; + __ptrace_link(current, current->real_parent); + detach = false; + } + write_unlock_irq(&tasklist_lock); + + if (detach) + ptrace_abort_attach(current); + return ret; +} + +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) +{ + bool detach, release; + + write_lock_irq(&tasklist_lock); + /* + * This tracee can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + detach = tracee->ptrace != 0; + release = false; + if (likely(detach)) + release = __ptrace_detach(current, tracee); + write_unlock_irq(&tasklist_lock); + + if (unlikely(release)) + release_task(tracee); + else if (likely(detach)) + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + for (;;) { + struct task_struct *tracee = NULL; + + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; + + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); + } +} + +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) +{ + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *ctx, + siginfo_t *info, bool write) +{ + unsigned long flags; + int err; + + switch (get_stop_event(ctx)) { + case 0: /* jctl stop */ + return -EINVAL; + + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *ctx->siginfo = *info; + else + *info = *ctx->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } + + return err; + + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } + + return 0; + } +} + +static void do_ptrace_notify_stop(struct ptrace_context *ctx, + struct task_struct *tracee) +{ + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ + tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; + WARN_ON(!tracee->exit_code); + + read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + preempt_enable_no_resched(); +} + +void ptrace_notify_stop(struct task_struct *tracee) +{ + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + + if (IS_ERR(engine)) + return; + + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); +} + +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) +{ + struct ptrace_context *ctx = ptrace_context(engine); + unsigned long events; + int action; + + ctx->options &= ~PTRACE_O_SYSEMU; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; + + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: + if (unlikely(!arch_has_block_step())) + return -EIO; + action = UTRACE_BLOCKSTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + ctx->options |= PTRACE_O_SYSEMU; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; + + case PTRACE_CONT: + break; + default: + return -EIO; + } + + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; + + return action; +} + +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_VFORK: + if (ctx->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + do_ptrace_notify_stop(ctx, tracee); + return 0; + } + + if (action != UTRACE_RESUME) { + /* + * single-stepping. UTRACE_SIGNAL_REPORT will + * synthesize a trap to follow the syscall insn. + */ + ctx->signr = SIGTRAP; + action = UTRACE_INTERRUPT; + } + break; + + case PTRACE_EVENT_SYSCALL_EXIT: + case PTRACE_EVENT_SYSCALL_ENTRY: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + ctx->signr = data; + break; + } + + ctx->resume = action; + ptrace_wake_up(tracee, engine, action, true); + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = generic_ptrace_pokedata(child, addr, data); + break; + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_set_options(child, engine, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(ptrace_context(engine)->eventmsg, + (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + + case PTRACE_KILL: + /* Ugly historical behaviour. */ + if (task_is_traced(child)) + ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); + ret = 0; + break; + + default: + ret = ptrace_resume(child, engine, request, data); + break; + } + + utrace_engine_put(engine); + return ret; +} + +#if defined CONFIG_COMPAT +#include + +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, + datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + utrace_engine_put(engine); + return ret; +} +#endif /* CONFIG_COMPAT */ From roland at redhat.com Mon Nov 23 00:32:06 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 22 Nov 2009 16:32:06 -0800 (PST) Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: Oleg Nesterov's message of Sunday, 22 November 2009 23:12:24 +0100 <20091122221224.GA8674@redhat.com> References: <20091122221224.GA8674@redhat.com> Message-ID: <20091123003206.7749C1334@magilla.sf.frob.com> > Roland, this is what I am going to send for review. Ok. > 1-7 are already in -mm tree, I am sending them to simplify the review. 2-7 were already in my tracehook branch, I added 1 there too. > 8-12 doesn't change the behaviour, simple preaparations. I've merged 8-11 into my tracehook branch too. > Perhaps we should send 8-10 to akpm right now? I'm not sure whether that would more useful. It's really up to you. IMHO those are not standalone cleanups like 2-7 (and even 1) are. Those are all just specific nits for this style of incrementalism where you have both ptrace implementations compilable at the same time. Whether and how to do that is part of the whole upstream review conversation about how to merge utrace and utrace-ptrace. So to me it makes more sense to have those travel as part of that whole series. IOW, for 1-7 it seems likely these will be merged without particular controversy (or interest) as worthwhile in their own right, whereas 8-10 are like 11-13+utrace.patch in only making any sense if they are all merged together. > NOTE! This series assumes utrace.patch comes next, after utrace-ptrace. > This way we can avoid "exclude_ptrace" hacks in ptrace.c, but I am not > sure this is good idea. Up to you. No, it's really up to the upstream reviewers and gatekeepers. > Just in case, please find below your utrace.patch re-diffed against this > series, it doesn't touch ptrace.c and comes with ptrace_notify_stop() > in utrace_stop(). Ok. Thanks, Roland From srikar at linux.vnet.ibm.com Mon Nov 23 04:59:47 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 23 Nov 2009 10:29:47 +0530 Subject: [PATCH 3] ptrace: introduce user_single_step_siginfo() helper In-Reply-To: <20091122221233.GA8692@redhat.com> References: <20091122221233.GA8692@redhat.com> Message-ID: <20091123045947.GA13014@linux.vnet.ibm.com> > > +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO > +extern void user_single_step_siginfo(struct task_struct *tsk, > + struct pt_regs *regs, siginfo_t *info); > +#else > +static inline void user_single_step_siginfo(struct task_struct *tsk, > + struct pt_regs *regs, siginfo_t *info) > +{ > + memset(info, 0, sizeof(*info)); > + info->si_signo = SIGTRAP; Is it possible to add si_code and si_addr info info->si_code = TRAP_TRACE; info->si_addr = instruction_pointer(regs); > +} > +#endif > + Thanks and Regards -Srikar From roland at redhat.com Mon Nov 23 05:04:42 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 22 Nov 2009 21:04:42 -0800 (PST) Subject: [PATCH 3] ptrace: introduce user_single_step_siginfo() helper In-Reply-To: Srikar Dronamraju's message of Monday, 23 November 2009 10:29:47 +0530 <20091123045947.GA13014@linux.vnet.ibm.com> References: <20091122221233.GA8692@redhat.com> <20091123045947.GA13014@linux.vnet.ibm.com> Message-ID: <20091123050442.E6C3A966@magilla.sf.frob.com> > Is it possible to add si_code and si_addr info > info->si_code = TRAP_TRACE; > info->si_addr = instruction_pointer(regs); This is exactly what arch-specific versions should do here. The choice of TRAP_TRACE is an arch detail, not a common default. Thanks, Roland From srikar at linux.vnet.ibm.com Mon Nov 23 05:58:37 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 23 Nov 2009 11:28:37 +0530 Subject: [PATCH 5] ptrace: change tracehook_report_syscall_exit() to handle stepping In-Reply-To: <20091122221237.GA8702@redhat.com> References: <20091122221237.GA8702@redhat.com> Message-ID: <20091123055837.GB13014@linux.vnet.ibm.com> Hi Oleg, > > I don't have a powerpc machine, but I think this test-case should > see the difference: On a powerpc machine, I did verify that the below test-case differs with your patch. Without the patch it would print the message "kernel bug: status=857F shouldn't have 0x80" > > #include > #include > #include > #include > #include > > int main(void) > { > int pid, status; > > if (!(pid = fork())) { > assert(ptrace(PTRACE_TRACEME) == 0); > kill(getpid(), SIGSTOP); > > getppid(); > > return 0; > } > > assert(pid == wait(&status)); > assert(ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == 0); > > assert(ptrace(PTRACE_SYSCALL, pid, 0,0) == 0); > assert(pid == wait(&status)); > > assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); > assert(pid == wait(&status)); > > if (status == 0x57F) > return 0; > > printf("kernel bug: status=%X shouldn't have 0x80\n", status); > return 1; > } From info at campaigns.canal-marketing.com Mon Nov 23 14:10:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?Luxe_Priv=E9?=) Date: Mon, 23 Nov 2009 15:10:00 +0100 Subject: =?iso-8859-1?q?Invitation_Vente_Priv=E9e?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Nov 23 17:33:19 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 23 Nov 2009 18:33:19 +0100 Subject: [PATCH 5] ptrace: change tracehook_report_syscall_exit() to handle stepping In-Reply-To: <20091123055837.GB13014@linux.vnet.ibm.com> References: <20091122221237.GA8702@redhat.com> <20091123055837.GB13014@linux.vnet.ibm.com> Message-ID: <20091123173319.GA15569@redhat.com> On 11/23, Srikar Dronamraju wrote: > > > I don't have a powerpc machine, but I think this test-case should > > see the difference: > > On a powerpc machine, I did verify that the below test-case differs with > your patch. Without the patch it would print the message > "kernel bug: status=857F shouldn't have 0x80" Great! Thanks a lot. Oleg. From oleg at redhat.com Mon Nov 23 20:18:15 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 23 Nov 2009 21:18:15 +0100 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091123003206.7749C1334@magilla.sf.frob.com> References: <20091122221224.GA8674@redhat.com> <20091123003206.7749C1334@magilla.sf.frob.com> Message-ID: <20091123201815.GA22985@redhat.com> On 11/22, Roland McGrath wrote: > > > Perhaps we should send 8-10 to akpm right now? > > I'm not sure whether that would more useful. It's really up to you. > IMHO those are not standalone cleanups like 2-7 (and even 1) are. > > So to me it > makes more sense to have those travel as part of that whole series. Yes, agreed. Oleg. From roland at redhat.com Mon Nov 23 20:39:54 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 23 Nov 2009 12:39:54 -0800 (PST) Subject: http://koji.fedoraproject.org/scratch/roland/task_1825649/ Message-ID: <20091123203954.A2DFFD8@magilla.sf.frob.com> At this URL find built rpms (x86_64 and i686 only) that you can install on a Fedora 12 (or rawhide, probably) system. These are the upstream kernel du jour with the current utrace-ptrace branch code (see rpm changelog for commit id). (I tried an f12-flavored build too, but it looks like the current upstream code does not build on ppc.) I tried ptrace-tests on this kernel. step-fork fails as expected, this kernel doesn't have that (utrace-unrelated) upstream fix. On i686, I get no other ptrace-tests failures. On x86_64, detach-sigkill-race consistently fails in tests/ but succeeds in biarch-tests/. Hmm, looks like that fails on stock F-12 kernel (i.e. vanilla ptrace) too, so not a regression. Thanks, Roland From mldireto at tudoemoferta.com.br Mon Nov 23 16:24:46 2009 From: mldireto at tudoemoferta.com.br (BR116 Moto Clube) Date: Mon, 23 Nov 2009 14:24:46 -0200 Subject: 13 Aniversario do Moto Clube BR116. Essa voce nao pode perder. Message-ID: <8f8f0e9649f7e476f4dca9430018f5fc@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Nov 23 21:01:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 23 Nov 2009 22:01:17 +0100 Subject: Q: UTRACE_SYSCALL_RESUMED logic In-Reply-To: <20091119011939.090171E2C@magilla.sf.frob.com> References: <20091118222211.GA13022@redhat.com> <20091119011939.090171E2C@magilla.sf.frob.com> Message-ID: <20091123210117.GA23346@redhat.com> On 11/18, Roland McGrath wrote: > > > In any case, what is the rationality? > > The rationale is that if you see utrace_resume_action(action)==UTRACE_STOP > in your callback, then you know another engine asked for stop Yes, but engine can't know if the next one is going to return UTRACE_STOP. > and you can > decide to return UTRACE_REPORT if you want to see the UTRACE_SYSCALL_RESUMED > notification after the other engine resumes. If you aren't delaying your > consideration of the event until the UTRACE_SYSCALL_RESUMED case because > you don't care, then you don't return UTRACE_REPORT and are not guaranteed > the second report. OK, thanks. But shouldn't utrace_report_syscall_entry() reset report->action = UTRACE_RESUME after do_report_syscall_entry()? If we stop, report->action remains UTRACE_STOP when we do the reporting loop. It is not clear to me why ptrace_report_syscall_entry() uses utrace_syscall_action() under "if (UTRACE_SYSCALL_RESUMED)". This looks a bit strange because it returns the "unconditional" UTRACE_SYSCALL_RUN below. IOW, if ptrace should obey to another engine's request to abort this syscall, the code should use utrace_syscall_action() consistently. OTOH, PTRACE_O_SYSEMU always aborts. Not sure I understand how different engines can be friendly to each other. In short: should we remove this utrace_syscall_action() or should we add another one instead? (I think the latter). Oleg. From oleg at redhat.com Mon Nov 23 21:43:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 23 Nov 2009 22:43:22 +0100 Subject: [PATCH 140] join PTRACE_EVENT_SYSCALL_XXX states Message-ID: <20091123214322.GA28918@redhat.com> No need to to use different ENTRY/EXIT syscall codes any longer. PTRACE_EVENT_SYSCALL_EXIT was introduced to emulate send_sigtrap() from syscall_trace_leave(), now we don't do this. --- kernel/ptrace-utrace.c | 25 +++++++++++-------------- 1 file changed, 11 insertions(+), 14 deletions(-) --- UTRACE-PTRACE/kernel/ptrace-utrace.c~140_PTRACE_EVENT_SYSCALL 2009-11-21 22:15:51.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace-utrace.c 2009-11-23 22:15:21.000000000 +0100 @@ -70,10 +70,9 @@ struct ptrace_context { #define PTRACE_O_SYSEMU 0x100 -#define PTRACE_EVENT_SYSCALL_ENTRY (1 << 16) -#define PTRACE_EVENT_SYSCALL_EXIT (2 << 16) -#define PTRACE_EVENT_SIGTRAP (3 << 16) -#define PTRACE_EVENT_SIGNAL (4 << 16) +#define PTRACE_EVENT_SYSCALL (1 << 16) +#define PTRACE_EVENT_SIGTRAP (2 << 16) +#define PTRACE_EVENT_SIGNAL (3 << 16) /* events visible to user-space */ #define PTRACE_EVENT_MASK 0xFFFF @@ -257,8 +256,7 @@ static void ptrace_detach_task(struct ta struct ptrace_context *ctx = ptrace_context(engine); switch (get_stop_event(ctx)) { - case PTRACE_EVENT_SYSCALL_ENTRY: - case PTRACE_EVENT_SYSCALL_EXIT: + case PTRACE_EVENT_SYSCALL: if (voluntary) send_sig_info(sig, SEND_SIG_PRIV, tracee); break; @@ -385,9 +383,9 @@ static u32 ptrace_report_clone(enum utra return UTRACE_STOP; } -static inline void set_syscall_code(struct ptrace_context *ctx, int event) +static inline void set_syscall_code(struct ptrace_context *ctx) { - set_stop_code(ctx, event); + set_stop_code(ctx, PTRACE_EVENT_SYSCALL); if (ctx->options & PTRACE_O_TRACESYSGOOD) ctx->stop_code |= 0x80; } @@ -411,7 +409,7 @@ static u32 ptrace_report_syscall_entry(u WARN_ON(ptrace_event_pending(ctx)); - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_ENTRY); + set_syscall_code(ctx); if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { suppress_sigtrap(task); @@ -444,7 +442,7 @@ static u32 ptrace_report_syscall_exit(en return UTRACE_INTERRUPT; } - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + set_syscall_code(ctx); return UTRACE_STOP; } @@ -954,7 +952,7 @@ static int ptrace_resume(struct task_str case PTRACE_EVENT_CLONE: case PTRACE_EVENT_VFORK_DONE: if (request == PTRACE_SYSCALL) { - set_syscall_code(ctx, PTRACE_EVENT_SYSCALL_EXIT); + set_syscall_code(ctx); do_ptrace_notify_stop(ctx, tracee); return 0; } @@ -963,14 +961,13 @@ static int ptrace_resume(struct task_str /* * single-stepping. UTRACE_SIGNAL_REPORT will * synthesize a trap to follow the syscall insn. - */ + */ ctx->signr = SIGTRAP; action = UTRACE_INTERRUPT; } break; - case PTRACE_EVENT_SYSCALL_EXIT: - case PTRACE_EVENT_SYSCALL_ENTRY: + case PTRACE_EVENT_SYSCALL: if (data) send_sig_info(data, SEND_SIG_PRIV, tracee); break; From roland at redhat.com Tue Nov 24 02:08:42 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 23 Nov 2009 18:08:42 -0800 (PST) Subject: Q: UTRACE_SYSCALL_RESUMED logic In-Reply-To: Oleg Nesterov's message of Monday, 23 November 2009 22:01:17 +0100 <20091123210117.GA23346@redhat.com> References: <20091118222211.GA13022@redhat.com> <20091119011939.090171E2C@magilla.sf.frob.com> <20091123210117.GA23346@redhat.com> Message-ID: <20091124020842.B35F9D8@magilla.sf.frob.com> > On 11/18, Roland McGrath wrote: > > > > > In any case, what is the rationality? > > > > The rationale is that if you see utrace_resume_action(action)==UTRACE_STOP > > in your callback, then you know another engine asked for stop > > Yes, but engine can't know if the next one is going to return > UTRACE_STOP. You can't know if the next one is going to change the registers and resume, either. That's just the general engine order issue. The only point of UTRACE_SYSCALL_RESUMED is to bring make it as possible to cooperate with a stop-modify-resume engine as it already is with a modify-in-callback engine. > OK, thanks. But shouldn't utrace_report_syscall_entry() reset > report->action = UTRACE_RESUME after do_report_syscall_entry()? > If we stop, report->action remains UTRACE_STOP when we do the > reporting loop. Yes, fixed. > It is not clear to me why ptrace_report_syscall_entry() uses > utrace_syscall_action() under "if (UTRACE_SYSCALL_RESUMED)". That is what a callback should do if it doesn't have a specific intent. Otherwise you clobber the choice made by a previous engine. > This looks a bit strange because it returns the "unconditional" > UTRACE_SYSCALL_RUN below. IOW, if ptrace should obey to another > engine's request to abort this syscall, the code should use > utrace_syscall_action() consistently. Yes, it should not change the incoming action for a ptrace syscall report. > OTOH, PTRACE_O_SYSEMU always aborts. Not sure I understand how > different engines can be friendly to each other. The "friendly" idea can only apply when an engine intends to be noninvasive to userland behavior. i.e., as the lone engine you would not perturb the default behavior, so as a second engine you should not perturb what the last engine chose. When the ptrace engine is doing SYSEMU, it intends to break the normal userland behavior. There is just inherently no way to be noninvasive about it. Thanks, Roland From caiqian at redhat.com Tue Nov 24 09:30:31 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Tue, 24 Nov 2009 04:30:31 -0500 (EST) Subject: GDB Testsuite Results with CONFIG_UTRACE In-Reply-To: <1938912364.504881259054812731.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1748594204.505051259055031396.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hello! The test was conducted on linux-2.6-utrace utrace-ptrace branch with and without CONFIG_UTRACE. The machine was an Intel x86_64 system. Biarch and other testing are under way. Here is the diff, and the results look similar. Detailed logs can be found at, http://people.redhat.com/~qcai/{noutrace,utrace}/ # diff -u noutrace/gdb.sum utrace/gdb.sum --- noutrace/gdb.sum 2009-11-24 04:11:05.439560175 -0500 +++ utrace/gdb.sum 2009-11-24 02:59:54.608446620 -0500 @@ -1,4 +1,4 @@ -Test Run By root on Tue Nov 24 03:19:40 2009 +Test Run By root on Tue Nov 24 02:20:46 2009 Native configuration is x86_64-unknown-linux-gnu === gdb tests === @@ -3773,7 +3773,7 @@ PASS: gdb.base/foll-fork.exp: default parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: explicit show parent follow, no catchpoints -PASS: gdb.base/foll-fork.exp: explicit parent follow, no catchpoints +FAIL: gdb.base/foll-fork.exp: (timeout) explicit parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow child PASS: gdb.base/foll-fork.exp: explicit show child follow, no catchpoints PASS: gdb.base/foll-fork.exp: explicit child follow, no catchpoints @@ -3795,7 +3795,7 @@ PASS: gdb.base/foll-fork.exp: explicit parent follow, tcatch fork PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: set follow parent, tbreak -FAIL: gdb.base/foll-fork.exp: (timeout) set follow parent, hit tbreak +PASS: gdb.base/foll-fork.exp: set follow parent, hit tbreak PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running ./gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child @@ -14583,7 +14583,7 @@ PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped, after setting file PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped bt -FAIL: gdb.threads/attachstop-mt.exp: attach3, exit leaves process stopped +PASS: gdb.threads/attachstop-mt.exp: attach3, exit leaves process stopped PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped, after setting file PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt @@ -14604,7 +14604,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) @@ -14619,7 +14619,7 @@ PASS: gdb.threads/bt-clone-stop.exp: run FAIL: gdb.threads/bt-clone-stop.exp: 0x0 entry found Running ./gdb.threads/current-lwp-dead.exp ... -PASS: gdb.threads/current-lwp-dead.exp: continue to breakpoint: fn_return +FAIL: gdb.threads/current-lwp-dead.exp: continue to breakpoint: fn_return Running ./gdb.threads/execl.exp ... PASS: gdb.threads/execl.exp: successfully compiled posix threads test case PASS: gdb.threads/execl.exp: set breakpoint at execl @@ -15258,13 +15258,13 @@ PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] PASS: gdb.threads/watchthreads.exp: watch args[1] -PASS: gdb.threads/watchthreads.exp: disable 2 -FAIL: gdb.threads/watchthreads.exp: threaded watch loop +PASS: gdb.threads/watchthreads.exp: disable 3 +PASS: gdb.threads/watchthreads.exp: threaded watch loop PASS: gdb.threads/watchthreads.exp: first watchpoint on args[0] hit PASS: gdb.threads/watchthreads.exp: first watchpoint on args[1] hit PASS: gdb.threads/watchthreads.exp: watchpoint on args[0] hit in thread PASS: gdb.threads/watchthreads.exp: watchpoint on args[1] hit in thread -FAIL: gdb.threads/watchthreads.exp: combination of threaded watchpoints = 30 +PASS: gdb.threads/watchthreads.exp: combination of threaded watchpoints = 30 Running ./gdb.threads/watchthreads-reorder.exp ... PASS: gdb.threads/watchthreads-reorder.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads-reorder.exp: reorder0: set can-use-hw-watchpoints 1 @@ -15472,8 +15472,8 @@ === gdb Summary === -# of expected passes 14229 -# of unexpected failures 402 +# of expected passes 14232 +# of unexpected failures 399 # of unexpected successes 2 # of expected failures 40 # of untested testcases 19 Thanks! CAI Qian From sales at africansafaris.co.ke Tue Nov 24 08:15:55 2009 From: sales at africansafaris.co.ke (African Safaris & Adventures) Date: Tue, 24 Nov 2009 11:15:55 +0300 Subject: Christmas Special 2009 Message-ID: <00c46353$40141$0ab34693760764@africa-4> An HTML attachment was scrubbed... URL: From ananth at in.ibm.com Tue Nov 24 09:40:28 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 24 Nov 2009 15:10:28 +0530 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091122221224.GA8674@redhat.com> References: <20091122221224.GA8674@redhat.com> Message-ID: <20091124094027.GB21843@in.ibm.com> Oleg, Roland, Here is the ptrace-tests results of a run of this patchset applied on 2.6.32-rc5 (rc8 barfs on boot, unrelated to utrace) on a POWER5 lpar: make check-TESTS make[3]: Entering directory `/home/ananth/utrace/ptrace-tests/tests' PASS: ptrace-on-job-control-stopped PASS: attach-wait-on-stopped PASS: detach-can-signal PASS: attach-into-signal PASS: attach-sigcont-wait PASS: sa-resethand-on-cont-signal PASS: ptrace-cont-sigstop-detach PASS: ptrace_event_clone PASS: tif-syscall-trace-after-detach PASS: event-exit-proc-maps PASS: event-exit-proc-environ SKIP: x86_64-ia32-gs SKIP: x86_64-gsbase SKIP: powerpc-altivec PASS: peekpokeusr PASS: watchpoint SKIP: block-step step-jump-cont: step-jump-cont.c:140: pokeuser: Assertion `l == 0' failed. /bin/sh: line 4: 9070 Aborted ${dir}$tst FAIL: step-jump-cont SKIP: step-jump-cont-strict PASS: ppc-dabr-race PASS: signal-loss PASS: step-into-handler SKIP: user-area-access SKIP: user-regs-peekpoke SKIP: erestartsys SKIP: erestart-debugger SKIP: step-to-breakpoint errno 14 (Bad address) syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. unexpected child status 67f FAIL: syscall-reset PASS: reparent-zombie PASS: step-simple SKIP: step-through-sigret PASS: stop-attach-then-wait PASS: detach-stopped PASS: clone-multi-ptrace PASS: clone-ptrace PASS: o_tracevfork PASS: o_tracevforkdone PASS: detach-parting-signal ======================================== 2 of 27 tests failed (11 tests were not run) Please report to utrace-devel at redhat.com ======================================== make[3]: *** [check-TESTS] Error 1 make[3]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make[2]: *** [check-am] Error 2 make[2]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make[1]: *** [check] Error 2 make[1]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make: *** [check-recursive] Error 1 Ananth From srikar at linux.vnet.ibm.com Tue Nov 24 11:31:41 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Tue, 24 Nov 2009 17:01:41 +0530 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091124094027.GB21843@in.ibm.com> References: <20091122221224.GA8674@redhat.com> <20091124094027.GB21843@in.ibm.com> Message-ID: <20091124113141.GA23653@linux.vnet.ibm.com> Hi Oleg, Roland, Ananth When I get the latest set of ptrace-tests by using. cvs -d :pserver:anoncvs:anoncvs at sources.redhat.com:/cvs/systemtap co ptrace-tests I get errors when I run make syscall-from-clone.c: In function ???main???: syscall-from-clone.c:127: error: storage size of ???regs??? isn???t known syscall-from-clone.c:202: error: ???PTRACE_GETREGS??? undeclared (first use in this function) syscall-from-clone.c:202: error: (Each undeclared identifier is reported only once syscall-from-clone.c:202: error: for each function it appears in.) cc1: warnings being treated as errors syscall-from-clone.c:127: warning: unused variable ???regs??? make[2]: *** [syscall-from-clone.o] Error 1 make[2]: Leaving directory `/home/srikar/work/ptrace-tests/tests' make[1]: *** [all] Error 2 make[1]: Leaving directory `/home/srikar/work/ptrace-tests/tests' make: *** [all-recursive] Error 1 I find that the errors are because there is no definition of user_regs_struct for powerpc. Something similar seems to be defined for x86. These errors occur even with upstream kernel. Hence can you confirm 1. Am I using the right source of ptrace-tests or has its location changed. 2. Are these new testcases x86 architecture specific? 3. Shouldn't arch/powerpc/include/asm/user.h not define user_regs_struct? -- Thanks and Regards Srikar From oleg at redhat.com Tue Nov 24 15:26:57 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 16:26:57 +0100 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091124094027.GB21843@in.ibm.com> References: <20091122221224.GA8674@redhat.com> <20091124094027.GB21843@in.ibm.com> Message-ID: <20091124152657.GA4352@redhat.com> On 11/24, Ananth N Mavinakayanahalli wrote: > > ... > step-jump-cont: step-jump-cont.c:140: pokeuser: Assertion `l == 0' > failed. > /bin/sh: line 4: 9070 Aborted ${dir}$tst > FAIL: step-jump-cont > > errno 14 (Bad address) > syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location > ()) == 38' failed. > unexpected child status 67f > FAIL: syscall-reset Ananth, thanks a lot. Could you please verify that unpatched kernel passes these tests? Also, could you run "make xcheck" to do more testing? Oleg. From oleg at redhat.com Tue Nov 24 20:01:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:27 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace Message-ID: <20091124200127.GA5751@redhat.com> Hello. This is the new iteration of Roland's utrace patch, this time with "rewrite-ptrace-via-utrace" + cleanups in utrace core. 1-7 are already in -mm tree, I am sending them to simplify the review. 8-12 don not change the behaviour, simple preparations. 13-14 add utrace-ptrace and utrace Please review. Oleg. From oleg at redhat.com Tue Nov 24 20:01:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:31 +0100 Subject: [RFC,PATCH 01/14] ptrace: cleanup ptrace_init_task()->ptrace_link() path Message-ID: <20091124200131.GA5754@redhat.com> (already in mm: ptrace-cleanup-ptrace_init_task-ptrace_link-path.patch) No functional changes. ptrace_init_task() looks confusing, as if we always auto-attach when "bool ptrace" argument is true, while in fact we attach only if current is traced. Make the code more explicit and kill now unused ptrace_link(). Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/ptrace.h | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) --- V1/include/linux/ptrace.h~1_PTRACE_INIT_TASK 2009-11-24 19:46:51.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-24 19:50:39.000000000 +0100 @@ -105,12 +105,7 @@ static inline int ptrace_reparented(stru { return child->real_parent != child->parent; } -static inline void ptrace_link(struct task_struct *child, - struct task_struct *new_parent) -{ - if (unlikely(child->ptrace)) - __ptrace_link(child, new_parent); -} + static inline void ptrace_unlink(struct task_struct *child) { if (unlikely(child->ptrace)) @@ -169,9 +164,9 @@ static inline void ptrace_init_task(stru INIT_LIST_HEAD(&child->ptraced); child->parent = child->real_parent; child->ptrace = 0; - if (unlikely(ptrace)) { + if (unlikely(ptrace) && (current->ptrace & PT_PTRACED)) { child->ptrace = current->ptrace; - ptrace_link(child, current->parent); + __ptrace_link(child, current->parent); } } From oleg at redhat.com Tue Nov 24 20:01:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:35 +0100 Subject: [RFC,PATCH 02/14] signals: check ->group_stop_count after tracehook_get_signal() Message-ID: <20091124200135.GA5761@redhat.com> (already in mm: signals-check-group_stop_count-after-tracehook_get_signal.patch) Move the call to do_signal_stop() down, after tracehook call. This makes ->group_stop_count condition visible to tracers before do_signal_stop() will participate in this group-stop. Currently the patch has no effect, tracehook_get_signal() always returns 0. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- kernel/signal.c | 9 ++++----- 1 file changed, 4 insertions(+), 5 deletions(-) --- V1/kernel/signal.c~2_DO_SIGNAL_STOP_AFTER_TRACEHOOK 2009-11-24 19:46:51.000000000 +0100 +++ V1/kernel/signal.c 2009-11-24 19:51:13.000000000 +0100 @@ -1807,11 +1807,6 @@ relock: for (;;) { struct k_sigaction *ka; - - if (unlikely(signal->group_stop_count > 0) && - do_signal_stop(0)) - goto relock; - /* * Tracing can induce an artifical signal and choose sigaction. * The return value in @signr determines the default action, @@ -1823,6 +1818,10 @@ relock: if (unlikely(signr != 0)) ka = return_ka; else { + if (unlikely(signal->group_stop_count > 0) && + do_signal_stop(0)) + goto relock; + signr = dequeue_signal(current, ¤t->blocked, info); From oleg at redhat.com Tue Nov 24 20:01:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:38 +0100 Subject: [RFC,PATCH 03/14] ptrace: introduce user_single_step_siginfo() helper Message-ID: <20091124200138.GA5764@redhat.com> (already in mm: ptrace-introduce-user_single_step_siginfo-helper.patch) Suggested by Roland. Currently there is no way to synthesize a single-stepping trap in the arch-independent manner. This patch adds the default helper which fills siginfo_t, arch/ can can override it. Architetures which implement user_enable_single_step() should add user_single_step_siginfo() also. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/ptrace.h | 12 ++++++++++++ 1 file changed, 12 insertions(+) --- V1/include/linux/ptrace.h~3_DEFAULT_HELPER 2009-11-24 19:50:39.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-24 19:51:28.000000000 +0100 @@ -273,6 +273,18 @@ static inline void user_enable_block_ste } #endif /* arch_has_block_step */ +#ifdef ARCH_HAS_USER_SINGLE_STEP_INFO +extern void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info); +#else +static inline void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; +} +#endif + #ifndef arch_ptrace_stop_needed /** * arch_ptrace_stop_needed - Decide whether arch_ptrace_stop() should be called From oleg at redhat.com Tue Nov 24 20:01:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:42 +0100 Subject: [RFC,PATCH 04/14] ptrace: implement user_single_step_siginfo() Message-ID: <20091124200142.GA5772@redhat.com> (already in mm: ptrace-powerpc-implement-user_single_step_siginfo.patch) Suggested by Roland. Implement user_single_step_siginfo() for powerpc. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/powerpc/include/asm/ptrace.h | 2 ++ arch/powerpc/kernel/traps.c | 9 +++++++++ 2 files changed, 11 insertions(+) --- V1/arch/powerpc/include/asm/ptrace.h~4_PPC_HELPER 2009-11-24 19:46:49.000000000 +0100 +++ V1/arch/powerpc/include/asm/ptrace.h 2009-11-24 19:51:41.000000000 +0100 @@ -140,6 +140,8 @@ extern void user_enable_single_step(stru extern void user_enable_block_step(struct task_struct *); extern void user_disable_single_step(struct task_struct *); +#define ARCH_HAS_USER_SINGLE_STEP_INFO + #endif /* __ASSEMBLY__ */ #endif /* __KERNEL__ */ --- V1/arch/powerpc/kernel/traps.c~4_PPC_HELPER 2009-11-24 19:46:49.000000000 +0100 +++ V1/arch/powerpc/kernel/traps.c 2009-11-24 19:51:41.000000000 +0100 @@ -174,6 +174,15 @@ int die(const char *str, struct pt_regs return 0; } +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, siginfo_t *info) +{ + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = TRAP_TRACE; + info->si_addr = (void __user *)regs->nip; +} + void _exception(int signr, struct pt_regs *regs, int code, unsigned long addr) { siginfo_t info; From oleg at redhat.com Tue Nov 24 20:01:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:45 +0100 Subject: [RFC,PATCH 05/14] ptrace: change tracehook_report_syscall_exit() to handle stepping Message-ID: <20091124200145.GA5779@redhat.com> (already in mm: ptrace-change-tracehook_report_syscall_exit-to-handle-stepping.patch) Suggested by Roland. Change tracehook_report_syscall_exit() to look at step flag and send the trap signal if needed. This change affects ia64, microblaze, parisc, powerpc, sh. They pass nonzero "step" argument to tracehook but since it was ignored the tracee reports via ptrace_notify(), this is not right and not consistent. - PTRACE_SETSIGINFO doesn't work - if the tracer resumes the tracee with signr != 0 the new signal is generated rather than delivering it - If PT_TRACESYSGOOD is set the tracee reports the wrong exit_code I don't have a powerpc machine, but I think this test-case should see the difference: #include #include #include #include #include int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); getppid(); return 0; } assert(pid == wait(&status)); assert(ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == 0); assert(ptrace(PTRACE_SYSCALL, pid, 0,0) == 0); assert(pid == wait(&status)); assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); assert(pid == wait(&status)); if (status == 0x57F) return 0; printf("kernel bug: status=%X shouldn't have 0x80\n", status); return 1; } Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- include/linux/tracehook.h | 7 +++++++ 1 file changed, 7 insertions(+) --- V1/include/linux/tracehook.h~5_TRACEHOOK_HANDLE_STEPPING 2009-11-24 19:46:49.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-24 19:52:10.000000000 +0100 @@ -134,6 +134,13 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (step) { + siginfo_t info; + user_single_step_siginfo(current, regs, &info); + force_sig_info(SIGTRAP, &info, current); + return; + } + ptrace_report_syscall(regs); } From oleg at redhat.com Tue Nov 24 20:01:49 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:49 +0100 Subject: [RFC, PATCH 06/14] ptrace: x86: implement user_single_step_siginfo() Message-ID: <20091124200149.GA5782@redhat.com> (already in mm: ptrace-x86-implement-user_single_step_siginfo.patch) Suggested by Roland. Implement user_single_step_siginfo() for x86. Extract this code from send_sigtrap(). Since x86 calls tracehook_report_syscall_exit(step => 0) the new helper is not used yet. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/x86/include/asm/ptrace.h | 2 ++ arch/x86/kernel/ptrace.c | 30 +++++++++++++++++++++--------- 2 files changed, 23 insertions(+), 9 deletions(-) --- V1/arch/x86/include/asm/ptrace.h~6_X86_HELPER 2009-11-24 19:46:48.000000000 +0100 +++ V1/arch/x86/include/asm/ptrace.h 2009-11-24 19:52:11.000000000 +0100 @@ -230,6 +230,8 @@ extern void user_enable_block_step(struc #define arch_has_block_step() (boot_cpu_data.x86 >= 6) #endif +#define ARCH_HAS_USER_SINGLE_STEP_INFO + struct user_desc; extern int do_get_thread_area(struct task_struct *p, int idx, struct user_desc __user *info); --- V1/arch/x86/kernel/ptrace.c~6_X86_HELPER 2009-11-24 19:46:48.000000000 +0100 +++ V1/arch/x86/kernel/ptrace.c 2009-11-24 19:52:11.000000000 +0100 @@ -1437,21 +1437,33 @@ const struct user_regset_view *task_user #endif } -void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, - int error_code, int si_code) +static void fill_sigtrap_info(struct task_struct *tsk, + struct pt_regs *regs, + int error_code, int si_code, + struct siginfo *info) { - struct siginfo info; - tsk->thread.trap_no = 1; tsk->thread.error_code = error_code; - memset(&info, 0, sizeof(info)); - info.si_signo = SIGTRAP; - info.si_code = si_code; + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = si_code; + info->si_addr = user_mode_vm(regs) ? (void __user *)regs->ip : NULL; +} - /* User-mode ip? */ - info.si_addr = user_mode_vm(regs) ? (void __user *) regs->ip : NULL; +void user_single_step_siginfo(struct task_struct *tsk, + struct pt_regs *regs, + struct siginfo *info) +{ + fill_sigtrap_info(tsk, regs, 0, TRAP_BRKPT, info); +} +void send_sigtrap(struct task_struct *tsk, struct pt_regs *regs, + int error_code, int si_code) +{ + struct siginfo info; + + fill_sigtrap_info(tsk, regs, error_code, si_code, &info); /* Send us the fake SIGTRAP */ force_sig_info(SIGTRAP, &info, tsk); } From oleg at redhat.com Tue Nov 24 20:01:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:52 +0100 Subject: [RFC,PATCH 07/14] ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping Message-ID: <20091124200152.GA5789@redhat.com> (already in mm: ptrace-x86-change-syscall_trace_leave-to-rely-on-tracehook-when-stepping.patch) Suggested by Roland. Unlike powepc, x86 always calls tracehook_report_syscall_exit(step) with step = 0, and sends the trap by hand. This results in unnecessary SIGTRAP when PTRACE_SINGLESTEP follows the syscall-exit stop. Change syscall_trace_leave() to pass the correct "step" argument to tracehook and remove the send_sigtrap() logic. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/x86/kernel/ptrace.c | 21 +++++++-------------- 1 file changed, 7 insertions(+), 14 deletions(-) --- V1/arch/x86/kernel/ptrace.c~7_X86_CONVERT_SYSCALL_LEAVE 2009-11-24 19:52:11.000000000 +0100 +++ V1/arch/x86/kernel/ptrace.c 2009-11-24 19:52:12.000000000 +0100 @@ -1528,29 +1528,22 @@ asmregparm long syscall_trace_enter(stru asmregparm void syscall_trace_leave(struct pt_regs *regs) { + bool step; + if (unlikely(current->audit_context)) audit_syscall_exit(AUDITSC_RESULT(regs->ax), regs->ax); if (unlikely(test_thread_flag(TIF_SYSCALL_TRACEPOINT))) trace_sys_exit(regs, regs->ax); - if (test_thread_flag(TIF_SYSCALL_TRACE)) - tracehook_report_syscall_exit(regs, 0); - /* * If TIF_SYSCALL_EMU is set, we only get here because of * TIF_SINGLESTEP (i.e. this is PTRACE_SYSEMU_SINGLESTEP). * We already reported this syscall instruction in - * syscall_trace_enter(), so don't do any more now. - */ - if (unlikely(test_thread_flag(TIF_SYSCALL_EMU))) - return; - - /* - * If we are single-stepping, synthesize a trap to follow the - * system call instruction. + * syscall_trace_enter(). */ - if (test_thread_flag(TIF_SINGLESTEP) && - tracehook_consider_fatal_signal(current, SIGTRAP)) - send_sigtrap(current, regs, 0, TRAP_BRKPT); + step = unlikely(test_thread_flag(TIF_SINGLESTEP)) && + !test_thread_flag(TIF_SYSCALL_EMU); + if (step || test_thread_flag(TIF_SYSCALL_TRACE)) + tracehook_report_syscall_exit(regs, step); } From oleg at redhat.com Tue Nov 24 20:01:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:01:56 +0100 Subject: [RFC,PATCH 08/14] tracehooks: kill some PT_PTRACED checks Message-ID: <20091124200156.GA5793@redhat.com> No functional changes, preparation for utrace-ptrace. task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill some PT_PTRACED checks in tracehook.h to ensure the result is the same with or without utrace which doesn't set PT_PTRACED. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- V1/include/linux/tracehook.h~8_TRACEHOOK_KILL_PTRACED_CHECKS 2009-11-24 19:52:10.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-24 20:29:07.000000000 +0100 @@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec( { int unsafe = 0; int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { + if (ptrace) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else @@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (task_ptrace(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { - return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; + return notify ?: task_ptrace(current) ? why : 0; } /** From oleg at redhat.com Tue Nov 24 20:02:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:00 +0100 Subject: [RFC,PATCH 09/14] tracehooks: check PT_PTRACED before reporting the single-step Message-ID: <20091124200200.GA5801@redhat.com> No functional changes, preparation for utrace-ptrace. tracehook_report_syscall_exit() and tracehook_signal_handler() assume that only ptrace can set TIF_SINGLESTEP. Currently this is true but we are going to change this, the stepping logic will be moved into utrace layer. Change this code to check PT_PTRACED, ptrace-utrace doesn't set it. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- V1/include/linux/tracehook.h~9_SIGNAL_HANDLER_CK_PTRACE 2009-11-24 20:29:07.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-24 20:30:15.000000000 +0100 @@ -134,7 +134,7 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { - if (step) { + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); @@ -386,7 +386,7 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { - if (stepping) + if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } From oleg at redhat.com Tue Nov 24 20:02:04 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:04 +0100 Subject: [RFC, PATCH 10/14] ptrace_signal: check PT_PTRACED before reporting a signal Message-ID: <20091124200204.GA5808@redhat.com> No functional changes, preparation for utrace-ptrace. Change ptrace_signal() to check PT_PTRACED instead of task_ptrace() != 0. Currently this is the same, PT_PTRACED must be always set if the task is ptraced. This change is needed to make sure ptrace_signal() does nothing if ptrace is implemented on top of utrace, eventually this code will be removed completely. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- V1/kernel/signal.c~10_PTRACE_SIGNAL_CK_PTRACED 2009-11-24 20:29:06.000000000 +0100 +++ V1/kernel/signal.c 2009-11-24 20:30:15.000000000 +0100 @@ -1731,7 +1731,7 @@ static int do_signal_stop(int signr) static int ptrace_signal(int signr, siginfo_t *info, struct pt_regs *regs, void *cookie) { - if (!task_ptrace(current)) + if (!(task_ptrace(current) & PT_PTRACED)) return signr; ptrace_signal_deliver(regs, cookie); From oleg at redhat.com Tue Nov 24 20:02:08 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:08 +0100 Subject: [RFC,PATCH 11/14] export __ptrace_detach() and do_notify_parent_cldstop() Message-ID: <20091124200208.GA5811@redhat.com> Export __ptrace_detach() and do_notify_parent_cldstop() for ptrace-utrace. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 1 + include/linux/sched.h | 1 + kernel/ptrace.c | 2 +- kernel/signal.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) --- V1/include/linux/ptrace.h~11_EXPORT_2_HELPERS 2009-11-24 20:27:24.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-24 20:30:16.000000000 +0100 @@ -85,6 +85,7 @@ extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); +extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee); extern int ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); --- V1/include/linux/sched.h~11_EXPORT_2_HELPERS 2009-11-24 20:27:24.000000000 +0100 +++ V1/include/linux/sched.h 2009-11-24 20:30:16.000000000 +0100 @@ -2060,6 +2060,7 @@ extern int kill_pgrp(struct pid *pid, in extern int kill_pid(struct pid *pid, int sig, int priv); extern int kill_proc_info(int, struct siginfo *, pid_t); extern int do_notify_parent(struct task_struct *, int); +extern void do_notify_parent_cldstop(struct task_struct *, int); extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); extern void force_sig(int, struct task_struct *); extern void force_sig_specific(int, struct task_struct *); --- V1/kernel/ptrace.c~11_EXPORT_2_HELPERS 2009-11-24 20:27:24.000000000 +0100 +++ V1/kernel/ptrace.c 2009-11-24 20:30:16.000000000 +0100 @@ -271,7 +271,7 @@ static int ignoring_children(struct sigh * reap it now, in that case we must also wake up sub-threads sleeping in * do_wait(). */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) { __ptrace_unlink(p); --- V1/kernel/signal.c~11_EXPORT_2_HELPERS 2009-11-24 20:30:15.000000000 +0100 +++ V1/kernel/signal.c 2009-11-24 20:30:16.000000000 +0100 @@ -1461,7 +1461,7 @@ int do_notify_parent(struct task_struct return ret; } -static void do_notify_parent_cldstop(struct task_struct *tsk, int why) +void do_notify_parent_cldstop(struct task_struct *tsk, int why) { struct siginfo info; unsigned long flags; From oleg at redhat.com Tue Nov 24 20:02:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:12 +0100 Subject: [RFC,PATCH 12/14] reorder the code in kernel/ptrace.c Message-ID: <20091124200212.GA5818@redhat.com> No functional changes, preparation for the next patch. Move the code which can be shared with ptrace-utrace up, before __ptrace_link(). This way ptrace-utrace needs a single #ifdef in ptrace.c. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- kernel/ptrace.c | 556 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 278 insertions(+), 278 deletions(-) --- V1/kernel/ptrace.c~12_REORDER_PTRACE_C 2009-11-24 20:30:16.000000000 +0100 +++ V1/kernel/ptrace.c 2009-11-24 20:30:16.000000000 +0100 @@ -23,6 +23,284 @@ #include #include +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ /* * ptrace a task: make the debugger its new parent and @@ -117,53 +395,6 @@ int ptrace_check_attach(struct task_stru return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -243,57 +474,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; @@ -347,56 +527,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -457,7 +587,6 @@ static int ptrace_setsiginfo(struct task return error; } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -580,93 +709,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -718,47 +761,4 @@ int compat_ptrace_request(struct task_st return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Tue Nov 24 20:02:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:16 +0100 Subject: [RFC,PATCH 13/14] implement utrace-ptrace Message-ID: <20091124200216.GA5825@redhat.com> The patch adds the new file, kernel/ptrace-utrace.c, which contains the new implementation of ptrace over utrace. This file is not compiled until we have CONFIG_UTRACE option, will be added by the next "utrace core" patch. It's supposed to be an invisible implementation change, nothing should change to userland when CONFIG_UTRACE is enabled. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 2 kernel/Makefile | 1 kernel/ptrace.c | 2 kernel/ptrace-utrace.c | 1115 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1119 insertions(+), 1 deletion(-) --- V1/include/linux/ptrace.h~13_UTRACE_PTRACE 2009-11-24 20:30:16.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-11-24 20:30:17.000000000 +0100 @@ -79,7 +79,7 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ - +extern void ptrace_notify_stop(struct task_struct *tracee); extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); --- V1/kernel/Makefile~13_UTRACE_PTRACE 2009-11-24 20:27:23.000000000 +0100 +++ V1/kernel/Makefile 2009-11-24 20:30:17.000000000 +0100 @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ --- V1/kernel/ptrace.c~13_UTRACE_PTRACE 2009-11-24 20:30:16.000000000 +0100 +++ V1/kernel/ptrace.c 2009-11-24 20:30:17.000000000 +0100 @@ -302,6 +302,7 @@ asmlinkage long compat_sys_ptrace(compat } #endif /* CONFIG_COMPAT */ +#ifndef CONFIG_UTRACE /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -762,3 +763,4 @@ int compat_ptrace_request(struct task_st return ret; } #endif /* CONFIG_COMPAT */ +#endif /* CONFIG_UTRACE */ --- /dev/null 2009-11-24 16:51:11.614043008 +0100 +++ V1/kernel/ptrace-utrace.c 2009-11-24 20:30:17.000000000 +0100 @@ -0,0 +1,1115 @@ +/* + * linux/kernel/ptrace.c + * + * (C) Copyright 1999 Linus Torvalds + * + * Common interfaces for "ptrace()" which we do not want + * to continually duplicate across every architecture. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; + + int signr; + siginfo_t *siginfo; + + int stop_code; + unsigned long eventmsg; + + enum utrace_resume_action resume; +}; + +#define PT_UTRACED 0x00001000 + +#define PTRACE_O_SYSEMU 0x100 + +#define PTRACE_EVENT_SYSCALL (1 << 16) +#define PTRACE_EVENT_SIGTRAP (2 << 16) +#define PTRACE_EVENT_SIGNAL (3 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF + +static inline bool ptrace_event_pending(struct ptrace_context *ctx) +{ + return ctx->stop_code != 0; +} + +static inline int get_stop_event(struct ptrace_context *ctx) +{ + return ctx->stop_code >> 8; +} + +static inline void set_stop_code(struct ptrace_context *ctx, int event) +{ + ctx->stop_code = (event << 8) | SIGTRAP; +} + +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) +{ + 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 *ctx; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + ctx = ptrace_context(engine); + if (unlikely(ctx->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. + */ + ctx->options = 0; + ctx->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + ctx->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 *ctx; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (unlikely(!ctx)) + return ERR_PTR(-ENOMEM); + + ctx->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, ctx); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(ctx); + } + + return engine; +} + +static inline int ptrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *ctx = 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; + + ctx->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_events(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; +} + +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 void ptrace_detach_task(struct task_struct *tracee, int sig) +{ + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; + + if (unlikely(IS_ERR(engine))) + return; + + if (sig) { + struct ptrace_context *ctx = ptrace_context(engine); + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_SYSCALL: + if (voluntary) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (voluntary) + ctx->signr = sig; + ctx->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + ptrace_wake_up(tracee, engine, action, voluntary); + utrace_engine_put(engine); +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + ptrace_detach_task(tracee, 0); +} + +static u32 ptrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx) && + !signal_group_exit(task->signal)); + + set_stop_code(ctx, PTRACE_EVENT_EXIT); + ctx->eventmsg = *code; + + return UTRACE_STOP; +} + +static void ptrace_clone_attach(struct task_struct *parent, + struct task_struct *child, + int options) +{ + struct task_struct *tracer; + bool abort = true; + + if (unlikely(ptrace_attach_task(child, options))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); +} + +/* + * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). + * Called when we are going to emulate the stop before SYSCALL_EXIT. + */ +static void suppress_sigtrap(struct task_struct *task) +{ + if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) + user_disable_single_step(task); +} + +static u32 ptrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int event = 0; + + WARN_ON(ptrace_event_pending(ctx)); + + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { + if (ctx->options & PTRACE_O_TRACEVFORK) + event = PTRACE_EVENT_VFORK; + else if (ctx->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (ctx->options & PTRACE_O_TRACECLONE) + event = PTRACE_EVENT_CLONE; + } else if (ctx->options & PTRACE_O_TRACEFORK) { + event = PTRACE_EVENT_FORK; + } + /* + * Any of these reports implies auto-attaching the new child. + * So does CLONE_PTRACE, even with no event to report. + */ + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(parent, child, ctx->options); + + if (!event) + return UTRACE_RESUME; + + suppress_sigtrap(parent); + + set_stop_code(ctx, event); + ctx->eventmsg = child->pid; + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; +} + +static inline void set_syscall_code(struct ptrace_context *ctx) +{ + set_stop_code(ctx, PTRACE_EVENT_SYSCALL); + if (ctx->options & PTRACE_O_TRACESYSGOOD) + ctx->stop_code |= 0x80; +} + +static u32 ptrace_report_syscall_entry(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (action & UTRACE_SYSCALL_RESUMED) { + /* + * We already reported the first time. + * Nothing more to do now. + */ + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + return utrace_syscall_action(action) | UTRACE_RESUME; + } + + WARN_ON(ptrace_event_pending(ctx)); + + set_syscall_code(ctx); + + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { + suppress_sigtrap(task); + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + } + + /* + * Stop now to report. We will get another callback after + * we resume, with the UTRACE_SYSCALL_RESUMED flag set. + */ + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + if (ctx->resume != UTRACE_RESUME) { + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && + ctx->resume != UTRACE_SINGLESTEP); + ctx->resume = UTRACE_RESUME; + + ctx->signr = SIGTRAP; + return UTRACE_INTERRUPT; + } + + set_syscall_code(ctx); + return UTRACE_STOP; +} + +static u32 ptrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx)); + + if (!(ctx->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, task, 0); + return UTRACE_RESUME; + } + + suppress_sigtrap(task); + set_stop_code(ctx, PTRACE_EVENT_EXEC); + + return UTRACE_STOP; +} + +static void ptrace_send_sigtrap(struct task_struct *task, siginfo_t *info) +{ + user_single_step_siginfo(task, task_pt_regs(task), info); + force_sig_info(SIGTRAP, info, task); +} + +static enum utrace_signal_action resume_signal(struct task_struct *task, + struct ptrace_context *ctx, + struct k_sigaction *return_ka) +{ + siginfo_t *info = ctx->siginfo; + int signr = ctx->signr; + + ctx->siginfo = NULL; + ctx->signr = 0; + + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(&task->blocked, signr)) { + send_sig_info(signr, info, task); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(&task->sighand->siglock); + *return_ka = task->sighand->action[signr - 1]; + spin_unlock_irq(&task->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; +} + +static u32 ptrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct ptrace_context *ctx = ptrace_context(engine); + enum utrace_resume_action resume = ctx->resume; + + if (ptrace_event_pending(ctx)) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + if (WARN_ON(ctx->siginfo)) + ctx->siginfo = NULL; + + if (resume != UTRACE_RESUME) { + WARN_ON(resume != UTRACE_BLOCKSTEP && + resume != UTRACE_SINGLESTEP); + + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + case UTRACE_SIGNAL_REPORT: + if (!ctx->siginfo) { + if (ctx->signr) { + /* set by ptrace_resume(SYSCALL_EXIT) */ + WARN_ON(ctx->signr != SIGTRAP); + ptrace_send_sigtrap(task, info); + } + + return resume | UTRACE_SIGNAL_IGN; + } + + if (WARN_ON(ctx->siginfo != info)) + return resume | UTRACE_SIGNAL_IGN; + + return resume | resume_signal(task, ctx, return_ka); + + default: + break; + } + + WARN_ON(ctx->siginfo); + ctx->siginfo = info; + /* + * ctx->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + utrace_control(task, engine, UTRACE_INTERRUPT); + + ctx->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; +} + +static u32 ptrace_report_quiesce(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + return event ? UTRACE_RESUME : ctx->resume; +} + +static void ptrace_release(void *data) +{ + kfree(data); +} + +static const struct utrace_engine_ops ptrace_utrace_ops = { + .report_signal = ptrace_report_signal, + .report_quiesce = ptrace_report_quiesce, + .report_exec = ptrace_report_exec, + .report_exit = ptrace_report_exit, + .report_clone = ptrace_report_clone, + .report_syscall_entry = ptrace_report_syscall_entry, + .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, +}; + +int ptrace_check_attach(struct task_struct *child, int kill) +{ + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret = -ESRCH; + + engine = ptrace_lookup_engine(child); + if (IS_ERR(engine)) + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + + if (!task_is_stopped_or_traced(child)) + goto out; + /* + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. + */ + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: + utrace_engine_put(engine); + return ret; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + retval = ptrace_attach_task(task, 0); + if (unlikely(retval)) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + + BUG_ON(task->ptrace); + task->ptrace = PT_UTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/* + * Performs checks and sets PT_UTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + bool detach = true; + int ret = ptrace_attach_task(current, 0); + + if (unlikely(ret)) + return ret; + + ret = -EPERM; + write_lock_irq(&tasklist_lock); + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_UTRACED; + __ptrace_link(current, current->real_parent); + detach = false; + } + write_unlock_irq(&tasklist_lock); + + if (detach) + ptrace_abort_attach(current); + return ret; +} + +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) +{ + bool detach, release; + + write_lock_irq(&tasklist_lock); + /* + * This tracee can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + detach = tracee->ptrace != 0; + release = false; + if (likely(detach)) + release = __ptrace_detach(current, tracee); + write_unlock_irq(&tasklist_lock); + + if (unlikely(release)) + release_task(tracee); + else if (likely(detach)) + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + for (;;) { + struct task_struct *tracee = NULL; + + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; + + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); + } +} + +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) +{ + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *ctx, + siginfo_t *info, bool write) +{ + unsigned long flags; + int err; + + switch (get_stop_event(ctx)) { + case 0: /* jctl stop */ + return -EINVAL; + + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *ctx->siginfo = *info; + else + *info = *ctx->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } + + return err; + + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } + + return 0; + } +} + +static void do_ptrace_notify_stop(struct ptrace_context *ctx, + struct task_struct *tracee) +{ + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ + tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; + WARN_ON(!tracee->exit_code); + + read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + preempt_enable_no_resched(); +} + +void ptrace_notify_stop(struct task_struct *tracee) +{ + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + + if (IS_ERR(engine)) + return; + + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); +} + +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) +{ + struct ptrace_context *ctx = ptrace_context(engine); + unsigned long events; + int action; + + ctx->options &= ~PTRACE_O_SYSEMU; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; + + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: + if (unlikely(!arch_has_block_step())) + return -EIO; + action = UTRACE_BLOCKSTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + ctx->options |= PTRACE_O_SYSEMU; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; + + case PTRACE_CONT: + break; + default: + return -EIO; + } + + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; + + return action; +} + +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_VFORK: + if (ctx->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(ctx); + do_ptrace_notify_stop(ctx, tracee); + return 0; + } + + if (action != UTRACE_RESUME) { + /* + * single-stepping. UTRACE_SIGNAL_REPORT will + * synthesize a trap to follow the syscall insn. + */ + ctx->signr = SIGTRAP; + action = UTRACE_INTERRUPT; + } + break; + + case PTRACE_EVENT_SYSCALL: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + ctx->signr = data; + break; + } + + ctx->resume = action; + ptrace_wake_up(tracee, engine, action, true); + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = generic_ptrace_pokedata(child, addr, data); + break; + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_set_options(child, engine, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(ptrace_context(engine)->eventmsg, + (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + + case PTRACE_KILL: + /* Ugly historical behaviour. */ + if (task_is_traced(child)) + ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); + ret = 0; + break; + + default: + ret = ptrace_resume(child, engine, request, data); + break; + } + + utrace_engine_put(engine); + return ret; +} + +#if defined CONFIG_COMPAT +#include + +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, + datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + utrace_engine_put(engine); + return ret; +} +#endif /* CONFIG_COMPAT */ From oleg at redhat.com Tue Nov 24 20:02:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:02:20 +0100 Subject: [RFC,PATCH 14/14] utrace core Message-ID: <20091124200220.GA5828@redhat.com> From: Roland McGrath This adds the utrace facility, a new modular interface in the kernel for implementing user thread tracing and debugging. This fits on top of the tracehook_* layer, so the new code is well-isolated. The new interface is in and the DocBook utrace book describes it. It allows for multiple separate tracing engines to work in parallel without interfering with each other. Higher-level tracing facilities can be implemented as loadable kernel modules using this layer. The new facility is made optional under CONFIG_UTRACE. It can only be enabled on machines that have all the prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. If CONFIG_UTRACE is set ptrace uses the utrace facilities, it can play nicely with other utrace-based things tracing the same threads. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- Documentation/DocBook/Makefile | 2 Documentation/DocBook/utrace.tmpl | 590 +++++++++ fs/proc/array.c | 3 include/linux/sched.h | 5 include/linux/tracehook.h | 91 + include/linux/utrace.h | 729 +++++++++++ init/Kconfig | 9 kernel/fork.c | 3 kernel/Makefile | 1 kernel/utrace.c | 2430 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 3861 insertions(+), 2 deletions(-) --- V1/Documentation/DocBook/Makefile~14_UTRACE 2009-11-24 20:27:22.000000000 +0100 +++ V1/Documentation/DocBook/Makefile 2009-11-24 20:30:17.000000000 +0100 @@ -9,7 +9,7 @@ DOCBOOKS := z8530book.xml mcabook.xml device-drivers.xml \ kernel-hacking.xml kernel-locking.xml deviceiobook.xml \ procfs-guide.xml writing_usb_driver.xml networking.xml \ - kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml \ + kernel-api.xml filesystems.xml lsm.xml usb.xml kgdb.xml utrace.xml \ gadget.xml libata.xml mtdnand.xml librs.xml rapidio.xml \ genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ mac80211.xml debugobjects.xml sh.xml regulator.xml \ --- /dev/null 2009-11-24 16:51:11.614043008 +0100 +++ V1/Documentation/DocBook/utrace.tmpl 2009-11-24 20:30:17.000000000 +0100 @@ -0,0 +1,590 @@ + + + + + + The utrace User Debugging Infrastructure + + + + + utrace concepts + + Introduction + + + utrace is infrastructure code for tracing + and controlling user threads. This is the foundation for writing + tracing engines, which can be loadable kernel modules. + + + + The basic actors in utrace are the thread + and the tracing engine. A tracing engine is some body of code that + calls into the <linux/utrace.h> + interfaces, represented by a struct + utrace_engine_ops. (Usually it's a kernel module, + though the legacy ptrace support is a tracing + engine that is not in a kernel module.) The interface operates on + individual threads (struct task_struct). + If an engine wants to treat several threads as a group, that is up + to its higher-level code. + + + + Tracing begins by attaching an engine to a thread, using + utrace_attach_task or + utrace_attach_pid. If successful, it returns a + pointer that is the handle used in all other calls. + + + + + Events and Callbacks + + + An attached engine does nothing by default. An engine makes something + happen by requesting callbacks via utrace_set_events + and poking the thread with utrace_control. + The synchronization issues related to these two calls + are discussed further below in . + + + + Events are specified using the macro + UTRACE_EVENT(type). + Each event type is associated with a callback in struct + utrace_engine_ops. A tracing engine can leave unused + callbacks NULL. The only callbacks required + are those used by the event flags it sets. + + + + Many engines can be attached to each thread. When a thread has an + event, each engine gets a callback if it has set the event flag for + that event type. For most events, engines are called in the order they + attached. Engines that attach after the event has occurred do not get + callbacks for that event. This includes any new engines just attached + by an existing engine's callback function. Once the sequence of + callbacks for that one event has completed, such new engines are then + eligible in the next sequence that starts when there is another event. + + + + Event reporting callbacks have details particular to the event type, + but are all called in similar environments and have the same + constraints. Callbacks are made from safe points, where no locks + are held, no special resources are pinned (usually), and the + user-mode state of the thread is accessible. So, callback code has + a pretty free hand. But to be a good citizen, callback code should + never block for long periods. It is fine to block in + kmalloc and the like, but never wait for i/o or + for user mode to do something. If you need the thread to wait, use + UTRACE_STOP and return from the callback + quickly. When your i/o finishes or whatever, you can use + utrace_control to resume the thread. + + + + The UTRACE_EVENT(SYSCALL_ENTRY) event is a special + case. While other events happen in the kernel when it will return to + user mode soon, this event happens when entering the kernel before it + will proceed with the work requested from user mode. Because of this + difference, the report_syscall_entry callback is + special in two ways. For this event, engines are called in reverse of + the normal order (this includes the report_quiesce + call that precedes a report_syscall_entry call). + This preserves the semantics that the last engine to attach is called + "closest to user mode"--the engine that is first to see a thread's user + state when it enters the kernel is also the last to see that state when + the thread returns to user mode. For the same reason, if these + callbacks use UTRACE_STOP (see the next section), + the thread stops immediately after callbacks rather than only when it's + ready to return to user mode; when allowed to resume, it will actually + attempt the system call indicated by the register values at that time. + + + + + Stopping Safely + + Writing well-behaved callbacks + + + Well-behaved callbacks are important to maintain two essential + properties of the interface. The first of these is that unrelated + tracing engines should not interfere with each other. If your engine's + event callback does not return quickly, then another engine won't get + the event notification in a timely manner. The second important + property is that tracing should be as noninvasive as possible to the + normal operation of the system overall and of the traced thread in + particular. That is, attached tracing engines should not perturb a + thread's behavior, except to the extent that changing its user-visible + state is explicitly what you want to do. (Obviously some perturbation + is unavoidable, primarily timing changes, ranging from small delays due + to the overhead of tracing, to arbitrary pauses in user code execution + when a user stops a thread with a debugger for examination.) Even when + you explicitly want the perturbation of making the traced thread block, + just blocking directly in your callback has more unwanted effects. For + example, the CLONE event callbacks are called when + the new child thread has been created but not yet started running; the + child can never be scheduled until the CLONE + tracing callbacks return. (This allows engines tracing the parent to + attach to the child.) If a CLONE event callback + blocks the parent thread, it also prevents the child thread from + running (even to process a SIGKILL). If what you + want is to make both the parent and child block, then use + utrace_attach_task on the child and then use + UTRACE_STOP on both threads. A more crucial + problem with blocking in callbacks is that it can prevent + SIGKILL from working. A thread that is blocking + due to UTRACE_STOP will still wake up and die + immediately when sent a SIGKILL, as all threads + should. Relying on the utrace + infrastructure rather than on private synchronization calls in event + callbacks is an important way to help keep tracing robustly + noninvasive. + + + + + Using <constant>UTRACE_STOP</constant> + + + To control another thread and access its state, it must be stopped + with UTRACE_STOP. This means that it is + stopped and won't start running again while we access it. When a + thread is not already stopped, utrace_control + returns -EINPROGRESS and an engine must wait + for an event callback when the thread is ready to stop. The thread + may be running on another CPU or may be blocked. When it is ready + to be examined, it will make callbacks to engines that set the + UTRACE_EVENT(QUIESCE) event bit. To wake up an + interruptible wait, use UTRACE_INTERRUPT. + + + + As long as some engine has used UTRACE_STOP and + not called utrace_control to resume the thread, + then the thread will remain stopped. SIGKILL + will wake it up, but it will not run user code. When the stop is + cleared with utrace_control or a callback + return value, the thread starts running again. + (See also .) + + + + + + + Tear-down Races + + Primacy of <constant>SIGKILL</constant> + + Ordinarily synchronization issues for tracing engines are kept fairly + straightforward by using UTRACE_STOP. You ask a + thread to stop, and then once it makes the + report_quiesce callback it cannot do anything else + that would result in another callback, until you let it with a + utrace_control call. This simple arrangement + avoids complex and error-prone code in each one of a tracing engine's + event callbacks to keep them serialized with the engine's other + operations done on that thread from another thread of control. + However, giving tracing engines complete power to keep a traced thread + stuck in place runs afoul of a more important kind of simplicity that + the kernel overall guarantees: nothing can prevent or delay + SIGKILL from making a thread die and release its + resources. To preserve this important property of + SIGKILL, it as a special case can break + UTRACE_STOP like nothing else normally can. This + includes both explicit SIGKILL signals and the + implicit SIGKILL sent to each other thread in the + same thread group by a thread doing an exec, or processing a fatal + signal, or making an exit_group system call. A + tracing engine can prevent a thread from beginning the exit or exec or + dying by signal (other than SIGKILL) if it is + attached to that thread, but once the operation begins, no tracing + engine can prevent or delay all other threads in the same thread group + dying. + + + + Final callbacks + + The report_reap callback is always the final event + in the life cycle of a traced thread. Tracing engines can use this as + the trigger to clean up their own data structures. The + report_death callback is always the penultimate + event a tracing engine might see; it's seen unless the thread was + already in the midst of dying when the engine attached. Many tracing + engines will have no interest in when a parent reaps a dead process, + and nothing they want to do with a zombie thread once it dies; for + them, the report_death callback is the natural + place to clean up data structures and detach. To facilitate writing + such engines robustly, given the asynchrony of + SIGKILL, and without error-prone manual + implementation of synchronization schemes, the + utrace infrastructure provides some special + guarantees about the report_death and + report_reap callbacks. It still takes some care + to be sure your tracing engine is robust to tear-down races, but these + rules make it reasonably straightforward and concise to handle a lot of + corner cases correctly. + + + + Engine and task pointers + + The first sort of guarantee concerns the core data structures + themselves. struct utrace_engine is + a reference-counted data structure. While you hold a reference, an + engine pointer will always stay valid so that you can safely pass it to + any utrace call. Each call to + utrace_attach_task or + utrace_attach_pid returns an engine pointer with a + reference belonging to the caller. You own that reference until you + drop it using utrace_engine_put. There is an + implicit reference on the engine while it is attached. So if you drop + your only reference, and then use + utrace_attach_task without + UTRACE_ATTACH_CREATE to look up that same engine, + you will get the same pointer with a new reference to replace the one + you dropped, just like calling utrace_engine_get. + When an engine has been detached, either explicitly with + UTRACE_DETACH or implicitly after + report_reap, then any references you hold are all + that keep the old engine pointer alive. + + + + There is nothing a kernel module can do to keep a struct + task_struct alive outside of + rcu_read_lock. When the task dies and is reaped + by its parent (or itself), that structure can be freed so that any + dangling pointers you have stored become invalid. + utrace will not prevent this, but it can + help you detect it safely. By definition, a task that has been reaped + has had all its engines detached. All + utrace calls can be safely called on a + detached engine if the caller holds a reference on that engine pointer, + even if the task pointer passed in the call is invalid. All calls + return -ESRCH for a detached engine, which tells + you that the task pointer you passed could be invalid now. Since + utrace_control and + utrace_set_events do not block, you can call those + inside a rcu_read_lock section and be sure after + they don't return -ESRCH that the task pointer is + still valid until rcu_read_unlock. The + infrastructure never holds task references of its own. Though neither + rcu_read_lock nor any other lock is held while + making a callback, it's always guaranteed that the struct + task_struct and the struct + utrace_engine passed as arguments remain valid + until the callback function returns. + + + + The common means for safely holding task pointers that is available to + kernel modules is to use struct pid, which + permits put_pid from kernel modules. When using + that, the calls utrace_attach_pid, + utrace_control_pid, + utrace_set_events_pid, and + utrace_barrier_pid are available. + + + + + + Serialization of <constant>DEATH</constant> and <constant>REAP</constant> + + + The second guarantee is the serialization of + DEATH and REAP event + callbacks for a given thread. The actual reaping by the parent + (release_task call) can occur simultaneously + while the thread is still doing the final steps of dying, including + the report_death callback. If a tracing engine + has requested both DEATH and + REAP event reports, it's guaranteed that the + report_reap callback will not be made until + after the report_death callback has returned. + If the report_death callback itself detaches + from the thread, then the report_reap callback + will never be made. Thus it is safe for a + report_death callback to clean up data + structures and detach. + + + + Interlock with final callbacks + + The final sort of guarantee is that a tracing engine will know for sure + whether or not the report_death and/or + report_reap callbacks will be made for a certain + thread. These tear-down races are disambiguated by the error return + values of utrace_set_events and + utrace_control. Normally + utrace_control called with + UTRACE_DETACH returns zero, and this means that no + more callbacks will be made. If the thread is in the midst of dying, + it returns -EALREADY to indicate that the + report_death callback may already be in progress; + when you get this error, you know that any cleanup your + report_death callback does is about to happen or + has just happened--note that if the report_death + callback does not detach, the engine remains attached until the thread + gets reaped. If the thread is in the midst of being reaped, + utrace_control returns -ESRCH + to indicate that the report_reap callback may + already be in progress; this means the engine is implicitly detached + when the callback completes. This makes it possible for a tracing + engine that has decided asynchronously to detach from a thread to + safely clean up its data structures, knowing that no + report_death or report_reap + callback will try to do the same. utrace_detach + returns -ESRCH when the struct + utrace_engine has already been detached, but is + still a valid pointer because of its reference count. A tracing engine + can use this to safely synchronize its own independent multiple threads + of control with each other and with its event callbacks that detach. + + + + In the same vein, utrace_set_events normally + returns zero; if the target thread was stopped before the call, then + after a successful call, no event callbacks not requested in the new + flags will be made. It fails with -EALREADY if + you try to clear UTRACE_EVENT(DEATH) when the + report_death callback may already have begun, if + you try to clear UTRACE_EVENT(REAP) when the + report_reap callback may already have begun, or if + you try to newly set UTRACE_EVENT(DEATH) or + UTRACE_EVENT(QUIESCE) when the target is already + dead or dying. Like utrace_control, it returns + -ESRCH when the thread has already been detached + (including forcible detach on reaping). This lets the tracing engine + know for sure which event callbacks it will or won't see after + utrace_set_events has returned. By checking for + errors, it can know whether to clean up its data structures immediately + or to let its callbacks do the work. + + + + Using <function>utrace_barrier</function> + + When a thread is safely stopped, calling + utrace_control with UTRACE_DETACH + or calling utrace_set_events to disable some events + ensures synchronously that your engine won't get any more of the callbacks + that have been disabled (none at all when detaching). But these can also + be used while the thread is not stopped, when it might be simultaneously + making a callback to your engine. For this situation, these calls return + -EINPROGRESS when it's possible a callback is in + progress. If you are not prepared to have your old callbacks still run, + then you can synchronize to be sure all the old callbacks are finished, + using utrace_barrier. This is necessary if the + kernel module containing your callback code is going to be unloaded. + + + After using UTRACE_DETACH once, further calls to + utrace_control with the same engine pointer will + return -ESRCH. In contrast, after getting + -EINPROGRESS from + utrace_set_events, you can call + utrace_set_events again later and if it returns zero + then know the old callbacks have finished. + + + Unlike all other calls, utrace_barrier (and + utrace_barrier_pid) will accept any engine pointer you + hold a reference on, even if UTRACE_DETACH has already + been used. After any utrace_control or + utrace_set_events call (these do not block), you can + call utrace_barrier to block until callbacks have + finished. This returns -ESRCH only if the engine is + completely detached (finished all callbacks). Otherwise it waits + until the thread is definitely not in the midst of a callback to this + engine and then returns zero, but can return + -ERESTARTSYS if its wait is interrupted. + + + + + + + +utrace core API + + + The utrace API is declared in <linux/utrace.h>. + + +!Iinclude/linux/utrace.h +!Ekernel/utrace.c + + + +Machine State + + + The task_current_syscall function can be used on any + valid struct task_struct at any time, and does + not even require that utrace_attach_task was used at all. + + + + The other ways to access the registers and other machine-dependent state of + a task can only be used on a task that is at a known safe point. The safe + points are all the places where utrace_set_events can + request callbacks (except for the DEATH and + REAP events). So at any event callback, it is safe to + examine current. + + + + One task can examine another only after a callback in the target task that + returns UTRACE_STOP so that task will not return to user + mode after the safe point. This guarantees that the task will not resume + until the same engine uses utrace_control, unless the + task dies suddenly. To examine safely, one must use a pair of calls to + utrace_prepare_examine and + utrace_finish_examine surrounding the calls to + struct user_regset functions or direct examination + of task data structures. utrace_prepare_examine returns + an error if the task is not properly stopped and not dead. After a + successful examination, the paired utrace_finish_examine + call returns an error if the task ever woke up during the examination. If + so, any data gathered may be scrambled and should be discarded. This means + there was a spurious wake-up (which should not happen), or a sudden death. + + +<structname>struct user_regset</structname> + + + The struct user_regset API + is declared in <linux/regset.h>. + + +!Finclude/linux/regset.h + + + + + <filename>System Call Information</filename> + + + This function is declared in <linux/ptrace.h>. + + +!Elib/syscall.c + + + +<filename>System Call Tracing</filename> + + + The arch API for system call information is declared in + <asm/syscall.h>. + Each of these calls can be used only at system call entry tracing, + or can be used only at system call exit and the subsequent safe points + before returning to user mode. + At system call entry tracing means either during a + report_syscall_entry callback, + or any time after that callback has returned UTRACE_STOP. + + +!Finclude/asm-generic/syscall.h + + + + + +Kernel Internals + + + This chapter covers the interface to the tracing infrastructure + from the core of the kernel and the architecture-specific code. + This is for maintainers of the kernel and arch code, and not relevant + to using the tracing facilities described in preceding chapters. + + +Core Calls In + + + These calls are declared in <linux/tracehook.h>. + The core kernel calls these functions at various important places. + + +!Finclude/linux/tracehook.h + + + +Architecture Calls Out + + + An arch that has done all these things sets + CONFIG_HAVE_ARCH_TRACEHOOK. + This is required to enable the utrace code. + + +<filename><asm/ptrace.h></filename> + + + An arch defines these in <asm/ptrace.h> + if it supports hardware single-step or block-step features. + + +!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step +!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step +!Finclude/linux/ptrace.h user_disable_single_step + + + + + <filename><asm/syscall.h></filename> + + + An arch provides <asm/syscall.h> that + defines these as inlines, or declares them as exported functions. + These interfaces are described in . + + + + + + <filename><linux/tracehook.h></filename> + + + An arch must define TIF_NOTIFY_RESUME + and TIF_SYSCALL_TRACE + in its <asm/thread_info.h>. + The arch code must call the following functions, all declared + in <linux/tracehook.h> and + described in : + + + + tracehook_notify_resume + + + tracehook_report_syscall_entry + + + tracehook_report_syscall_exit + + + tracehook_signal_handler + + + + + + + + + + + + --- V1/fs/proc/array.c~14_UTRACE 2009-11-24 20:27:22.000000000 +0100 +++ V1/fs/proc/array.c 2009-11-24 20:30:17.000000000 +0100 @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -189,6 +190,8 @@ static inline void task_state(struct seq cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); + task_utrace_proc_status(m, p); + task_lock(p); if (p->files) fdt = files_fdtable(p->files); --- V1/include/linux/sched.h~14_UTRACE 2009-11-24 20:30:16.000000000 +0100 +++ V1/include/linux/sched.h 2009-11-24 20:30:17.000000000 +0100 @@ -1393,6 +1393,11 @@ struct task_struct { #endif seccomp_t seccomp; +#ifdef CONFIG_UTRACE + struct utrace *utrace; + unsigned long utrace_flags; +#endif + /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; --- V1/include/linux/tracehook.h~14_UTRACE 2009-11-24 20:30:15.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-11-24 20:30:17.000000000 +0100 @@ -49,6 +49,7 @@ #include #include #include +#include struct linux_binprm; /** @@ -63,6 +64,8 @@ struct linux_binprm; */ static inline int tracehook_expect_breakpoints(struct task_struct *task) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -111,6 +114,9 @@ static inline void ptrace_report_syscall static inline __must_check int tracehook_report_syscall_entry( struct pt_regs *regs) { + if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && + utrace_report_syscall_entry(regs)) + return 1; ptrace_report_syscall(regs); return 0; } @@ -134,6 +140,9 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); @@ -201,6 +210,8 @@ static inline void tracehook_report_exec struct linux_binprm *bprm, struct pt_regs *regs) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) + utrace_report_exec(fmt, bprm, regs); if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && unlikely(task_ptrace(current) & PT_PTRACED)) send_sig(SIGTRAP, current, 0); @@ -218,10 +229,37 @@ static inline void tracehook_report_exec */ static inline void tracehook_report_exit(long *exit_code) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) + utrace_report_exit(exit_code); ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); } /** + * tracehook_init_task - task_struct has just been copied + * @task: new &struct task_struct just copied from parent + * + * Called from do_fork() when @task has just been duplicated. + * After this, @task will be passed to tracehook_free_task() + * even if the rest of its setup fails before it is fully created. + */ +static inline void tracehook_init_task(struct task_struct *task) +{ + utrace_init_task(task); +} + +/** + * tracehook_free_task - task_struct is being freed + * @task: dead &struct task_struct being freed + * + * Called from free_task() when @task is no longer in use. + */ +static inline void tracehook_free_task(struct task_struct *task) +{ + if (task_utrace_struct(task)) + utrace_free_task(task); +} + +/** * tracehook_prepare_clone - prepare for new child to be cloned * @clone_flags: %CLONE_* flags from clone/fork/vfork system call * @@ -285,6 +323,8 @@ static inline void tracehook_report_clon unsigned long clone_flags, pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) + utrace_report_clone(clone_flags, child); if (unlikely(task_ptrace(child))) { /* * It doesn't matter who attached/attaching to this @@ -317,6 +357,9 @@ static inline void tracehook_report_clon pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && + (clone_flags & CLONE_VFORK)) + utrace_finish_vfork(current); if (unlikely(trace)) ptrace_event(0, trace, pid); } @@ -351,6 +394,10 @@ static inline void tracehook_report_vfor */ static inline void tracehook_prepare_release_task(struct task_struct *task) { + /* see utrace_add_engine() about this barrier */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_release_task(task); } /** @@ -365,6 +412,7 @@ static inline void tracehook_prepare_rel static inline void tracehook_finish_release_task(struct task_struct *task) { ptrace_release_task(task); + BUG_ON(task->exit_state != EXIT_DEAD); } /** @@ -386,6 +434,8 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } @@ -403,6 +453,8 @@ static inline void tracehook_signal_hand static inline int tracehook_consider_ignored_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -422,6 +474,9 @@ static inline int tracehook_consider_ign static inline int tracehook_consider_fatal_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | + UTRACE_EVENT(SIGNAL_CORE)))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -436,6 +491,8 @@ static inline int tracehook_consider_fat */ static inline int tracehook_force_sigpending(void) { + if (unlikely(task_utrace_flags(current))) + return utrace_interrupt_pending(); return 0; } @@ -465,6 +522,8 @@ static inline int tracehook_get_signal(s siginfo_t *info, struct k_sigaction *return_ka) { + if (unlikely(task_utrace_flags(task))) + return utrace_get_signal(task, regs, info, return_ka); return 0; } @@ -492,6 +551,8 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { + if (task_utrace_flags(current) & UTRACE_EVENT(JCTL)) + utrace_report_jctl(notify, why); return notify ?: task_ptrace(current) ? why : 0; } @@ -502,6 +563,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_stop(); } #define DEATH_REAP -1 @@ -524,6 +587,8 @@ static inline void tracehook_finish_jctl static inline int tracehook_notify_death(struct task_struct *task, void **death_cookie, int group_dead) { + *death_cookie = task_utrace_struct(task); + if (task_detached(task)) return task->ptrace ? SIGCHLD : DEATH_REAP; @@ -560,6 +625,20 @@ static inline void tracehook_report_deat int signal, void *death_cookie, int group_dead) { + /* + * This barrier ensures that our caller's setting of + * @task->exit_state precedes checking @task->utrace_flags here. + * If utrace_set_events() was just called to enable + * UTRACE_EVENT(DEATH), then we are obliged to call + * utrace_report_death() and not miss it. utrace_set_events() + * uses tasklist_lock to synchronize enabling the bit with the + * actual change to @task->exit_state, but we need this barrier + * to be sure we see a flags change made just before our caller + * took the tasklist_lock. + */ + smp_mb(); + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) + utrace_report_death(task, death_cookie, group_dead, signal); } #ifdef TIF_NOTIFY_RESUME @@ -589,10 +668,20 @@ static inline void set_notify_resume(str * asynchronously, this will be called again before we return to * user mode. * - * Called without locks. + * Called without locks. However, on some machines this may be + * called with interrupts disabled. */ static inline void tracehook_notify_resume(struct pt_regs *regs) { + struct task_struct *task = current; + /* + * This pairs with the barrier implicit in set_notify_resume(). + * It ensures that we read the nonzero utrace_flags set before + * set_notify_resume() was called by utrace setup. + */ + smp_rmb(); + if (task_utrace_flags(task)) + utrace_resume(task, regs); } #endif /* TIF_NOTIFY_RESUME */ --- /dev/null 2009-11-24 16:51:11.614043008 +0100 +++ V1/include/linux/utrace.h 2009-11-24 20:30:17.000000000 +0100 @@ -0,0 +1,729 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + * + * This interface allows for notification of interesting events in a + * thread. It also mediates access to thread state such as registers. + * Multiple unrelated users can be associated with a single thread. + * We call each of these a tracing engine. + * + * A tracing engine starts by calling utrace_attach_task() or + * utrace_attach_pid() on the chosen thread, passing in a set of hooks + * (&struct utrace_engine_ops), and some associated data. This produces a + * &struct utrace_engine, which is the handle used for all other + * operations. An attached engine has its ops vector, its data, and an + * event mask controlled by utrace_set_events(). + * + * For each event bit that is set, that engine will get the + * appropriate ops->report_*() callback when the event occurs. The + * &struct utrace_engine_ops need not provide callbacks for an event + * unless the engine sets one of the associated event bits. + */ + +#ifndef _LINUX_UTRACE_H +#define _LINUX_UTRACE_H 1 + +#include +#include +#include +#include + +struct linux_binprm; +struct pt_regs; +struct utrace; +struct user_regset; +struct user_regset_view; + +/* + * Event bits passed to utrace_set_events(). + * These appear in &struct task_struct. at utrace_flags + * and &struct utrace_engine. at flags. + */ +enum utrace_events { + _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ + _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ + _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ + _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ + _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ + _UTRACE_EVENT_DEATH, /* Thread has died. */ + _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ + _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ + _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ + _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ + _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ + _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ + _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ + _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ + _UTRACE_NEVENTS +}; +#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) + +/* + * All the kinds of signal events. + * These all use the @report_signal() callback. + */ +#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ + | UTRACE_EVENT(SIGNAL_IGN) \ + | UTRACE_EVENT(SIGNAL_STOP) \ + | UTRACE_EVENT(SIGNAL_TERM) \ + | UTRACE_EVENT(SIGNAL_CORE)) +/* + * Both kinds of syscall events; these call the @report_syscall_entry() + * and @report_syscall_exit() callbacks, respectively. + */ +#define UTRACE_EVENT_SYSCALL \ + (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) + +/* + * The event reports triggered synchronously by task death. + */ +#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) + +/* + * Hooks in call these entry points to the + * utrace dispatch. They are weak references here only so + * tracehook.h doesn't need to #ifndef CONFIG_UTRACE them to + * avoid external references in case of unoptimized compilation. + */ +void utrace_free_task(struct task_struct *) + __attribute__((weak)); +bool utrace_interrupt_pending(void) + __attribute__((weak)); +void utrace_resume(struct task_struct *, struct pt_regs *) + __attribute__((weak)); +void utrace_finish_stop(void) + __attribute__((weak)); +int utrace_get_signal(struct task_struct *, struct pt_regs *, + siginfo_t *, struct k_sigaction *) + __attribute__((weak)); +void utrace_report_clone(unsigned long, struct task_struct *) + __attribute__((weak)); +void utrace_finish_vfork(struct task_struct *) + __attribute__((weak)); +void utrace_report_exit(long *exit_code) + __attribute__((weak)); +void utrace_report_death(struct task_struct *, struct utrace *, bool, int) + __attribute__((weak)); +void utrace_report_jctl(int notify, int type) + __attribute__((weak)); +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs) + __attribute__((weak)); +bool utrace_report_syscall_entry(struct pt_regs *) + __attribute__((weak)); +void utrace_report_syscall_exit(struct pt_regs *) + __attribute__((weak)); +void utrace_signal_handler(struct task_struct *, int) + __attribute__((weak)); + +#ifndef CONFIG_UTRACE + +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return 0; +} +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + return NULL; +} +static inline void utrace_init_task(struct task_struct *child) +{ +} +static inline void utrace_release_task(struct task_struct *task) +{ +} + +static inline void task_utrace_proc_status(struct seq_file *m, + struct task_struct *p) +{ +} + +#else /* CONFIG_UTRACE */ + +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return task->utrace_flags; +} + +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + struct utrace *utrace; + + /* + * This barrier ensures that any prior load of task->utrace_flags + * is ordered before this load of task->utrace. We use those + * utrace_flags checks in the hot path to decide to call into + * the utrace code. The first attach installs task->utrace before + * setting task->utrace_flags nonzero, with a barrier between. + * See utrace_task_alloc(). + */ + smp_rmb(); + utrace = task->utrace; + + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ + return utrace; +} + +static inline void utrace_init_task(struct task_struct *task) +{ + task->utrace_flags = 0; + task->utrace = NULL; +} + +void utrace_release_task(struct task_struct *); +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); + + +/* + * Version number of the API defined in this file. This will change + * whenever a tracing engine's code would need some updates to keep + * working. We maintain this here for the benefit of tracing engine code + * that is developed concurrently with utrace API improvements before they + * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. + */ +#define UTRACE_API_VERSION 20090421 + +/** + * enum utrace_resume_action - engine's choice of action for a traced task + * @UTRACE_STOP: Stay quiescent after callbacks. + * @UTRACE_INTERRUPT: Make @report_signal() callback soon. + * @UTRACE_REPORT: Make some callback soon. + * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. + * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. + * @UTRACE_RESUME: Resume normally in user mode. + * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). + * + * See utrace_control() for detailed descriptions of each action. This is + * encoded in the @action argument and the return value for every callback + * with a &u32 return value. + * + * The order of these is important. When there is more than one engine, + * each supplies its choice and the smallest value prevails. + */ +enum utrace_resume_action { + UTRACE_STOP, + UTRACE_INTERRUPT, + UTRACE_REPORT, + UTRACE_SINGLESTEP, + UTRACE_BLOCKSTEP, + UTRACE_RESUME, + UTRACE_DETACH +}; +#define UTRACE_RESUME_MASK 0x07 + +/** + * utrace_resume_action - &enum utrace_resume_action from callback action + * @action: &u32 callback @action argument or return value + * + * This extracts the &enum utrace_resume_action from @action, + * which is the @action argument to a &struct utrace_engine_ops + * callback or the return value from one. + */ +static inline enum utrace_resume_action utrace_resume_action(u32 action) +{ + return action & UTRACE_RESUME_MASK; +} + +/** + * enum utrace_signal_action - disposition of signal + * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. + * @UTRACE_SIGNAL_IGN: Ignore the signal. + * @UTRACE_SIGNAL_TERM: Terminate the process. + * @UTRACE_SIGNAL_CORE: Terminate with core dump. + * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. + * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. + * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. + * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. + * + * This is encoded in the @action argument and the return value for + * a @report_signal() callback. It says what will happen to the + * signal described by the &siginfo_t parameter to the callback. + * + * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when + * a tracing report is being made before dequeuing any pending signal. + * If this is immediately after a signal handler has been set up, then + * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback + * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure + * it sees a %UTRACE_SIGNAL_HANDLER report. + */ +enum utrace_signal_action { + UTRACE_SIGNAL_DELIVER = 0x00, + UTRACE_SIGNAL_IGN = 0x10, + UTRACE_SIGNAL_TERM = 0x20, + UTRACE_SIGNAL_CORE = 0x30, + UTRACE_SIGNAL_STOP = 0x40, + UTRACE_SIGNAL_TSTP = 0x50, + UTRACE_SIGNAL_REPORT = 0x60, + UTRACE_SIGNAL_HANDLER = 0x70 +}; +#define UTRACE_SIGNAL_MASK 0xf0 +#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ + +/** + * utrace_signal_action - &enum utrace_signal_action from callback action + * @action: @report_signal callback @action argument or return value + * + * This extracts the &enum utrace_signal_action from @action, which + * is the @action argument to a @report_signal callback or the + * return value from one. + */ +static inline enum utrace_signal_action utrace_signal_action(u32 action) +{ + return action & UTRACE_SIGNAL_MASK; +} + +/** + * enum utrace_syscall_action - disposition of system call attempt + * @UTRACE_SYSCALL_RUN: Run the system call. + * @UTRACE_SYSCALL_ABORT: Don't run the system call. + * + * This is encoded in the @action argument and the return value for + * a @report_syscall_entry callback. + */ +enum utrace_syscall_action { + UTRACE_SYSCALL_RUN = 0x00, + UTRACE_SYSCALL_ABORT = 0x10 +}; +#define UTRACE_SYSCALL_MASK 0xf0 +#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ + +/** + * utrace_syscall_action - &enum utrace_syscall_action from callback action + * @action: @report_syscall_entry callback @action or return value + * + * This extracts the &enum utrace_syscall_action from @action, which + * is the @action argument to a @report_syscall_entry callback or the + * return value from one. + */ +static inline enum utrace_syscall_action utrace_syscall_action(u32 action) +{ + return action & UTRACE_SYSCALL_MASK; +} + +/* + * Flags for utrace_attach_task() and utrace_attach_pid(). + */ +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ +#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ +#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ +#define UTRACE_ATTACH_MATCH_MASK 0x000f + +/** + * struct utrace_engine - per-engine structure + * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() + * @data: engine-private &void * passed to utrace_attach_task() + * @flags: event mask set by utrace_set_events() plus internal flag bits + * + * The task itself never has to worry about engines detaching while + * it's doing event callbacks. These structures are removed from the + * task's active list only when it's stopped, or by the task itself. + * + * utrace_engine_get() and utrace_engine_put() maintain a reference count. + * When it drops to zero, the structure is freed. One reference is held + * implicitly while the engine is attached to its task. + */ +struct utrace_engine { +/* private: */ + struct kref kref; + void (*release)(void *); + struct list_head entry; + +/* public: */ + const struct utrace_engine_ops *ops; + void *data; + + unsigned long flags; +}; + +/** + * utrace_engine_get - acquire a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you get another. + */ +static inline void utrace_engine_get(struct utrace_engine *engine) +{ + kref_get(&engine->kref); +} + +void __utrace_engine_release(struct kref *); + +/** + * utrace_engine_put - release a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you lose that reference. + * If it was the last one, @engine becomes an invalid pointer. + */ +static inline void utrace_engine_put(struct utrace_engine *engine) +{ + kref_put(&engine->kref, __utrace_engine_release); +} + +/** + * struct utrace_engine_ops - tracing engine callbacks + * + * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. + * utrace_set_events() calls on @engine choose which callbacks will be made + * to @engine from @task. + * + * Most callbacks take an @action argument, giving the resume action + * chosen by other tracing engines. All callbacks take an @engine + * argument, and a @task argument, which is always equal to @current. + * For some calls, @action also includes bits specific to that event + * and utrace_resume_action() is used to extract the resume action. + * This shows what would happen if @engine wasn't there, or will if + * the callback's return value uses %UTRACE_RESUME. This always + * starts as %UTRACE_RESUME when no other tracing is being done on + * this task. + * + * All return values contain &enum utrace_resume_action bits. For + * some calls, other bits specific to that kind of event are added to + * the resume action bits with OR. These are the same bits used in + * the @action argument. The resume action returned by a callback + * does not override previous engines' choices, it only says what + * @engine wants done. What @task actually does is the action that's + * most constrained among the choices made by all attached engines. + * See utrace_control() for more information on the actions. + * + * When %UTRACE_STOP is used in @report_syscall_entry, then @task + * stops before attempting the system call. In this case, another + * @report_syscall_entry callback will follow after @task resumes if + * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback + * or passed to utrace_control(). In a second or later callback, + * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate + * a repeat callback still waiting to attempt the same system call + * invocation. This repeat callback gives each engine an opportunity + * to reexamine registers another engine might have changed while + * @task was held in %UTRACE_STOP. + * + * In other cases, the resume action does not take effect until @task + * is ready to check for signals and return to user mode. If there + * are more callbacks to be made, the last round of calls determines + * the final action. A @report_quiesce callback with @event zero, or + * a @report_signal callback, will always be the last one made before + * @task resumes. Only %UTRACE_STOP is "sticky"--if @engine returned + * %UTRACE_STOP then @task stays stopped unless @engine returns + * different from a following callback. + * + * The report_death() and report_reap() callbacks do not take @action + * arguments, and only %UTRACE_DETACH is meaningful in the return value + * from a report_death() callback. None of the resume actions applies + * to a dead thread. + * + * All @report_*() hooks are called with no locks held, in a generally + * safe environment when we will be returning to user mode soon (or just + * entered the kernel). It is fine to block for memory allocation and + * the like, but all hooks are asynchronous and must not block on + * external events! If you want the thread to block, use %UTRACE_STOP + * in your hook's return value; then later wake it up with utrace_control(). + * + * @report_quiesce: + * Requested by %UTRACE_EVENT(%QUIESCE). + * This does not indicate any event, but just that @task (the current + * thread) is in a safe place for examination. This call is made + * before each specific event callback, except for @report_reap. + * The @event argument gives the %UTRACE_EVENT(@which) value for + * the event occurring. This callback might be made for events @engine + * has not requested, if some other engine is tracing the event; + * calling utrace_set_events() call here can request the immediate + * callback for this occurrence of @event. @event is zero when there + * is no other event, @task is now ready to check for signals and + * return to user mode, and some engine has used %UTRACE_REPORT or + * %UTRACE_INTERRUPT to request this callback. For this case, + * if @report_signal is not %NULL, the @report_quiesce callback + * may be replaced with a @report_signal callback passing + * %UTRACE_SIGNAL_REPORT in its @action argument, whenever @task is + * entering the signal-check path anyway. + * + * @report_signal: + * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). + * Use utrace_signal_action() and utrace_resume_action() on @action. + * The signal action is %UTRACE_SIGNAL_REPORT when some engine has + * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose + * to stop or to deliver an artificial signal, before pending signals. + * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just + * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this + * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by + * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly + * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the + * signal delivery. The other signal actions indicate a signal about + * to be delivered; the previous engine's return value sets the signal + * action seen by the the following engine's callback. The @info data + * can be changed at will, including @info->si_signo. The settings in + * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka + * is what was in force before other tracing engines intervened, and + * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or + * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info + * is left uninitialized and must be set completely by an engine that + * chooses to deliver a signal; if there was a previous @report_signal + * callback ending in %UTRACE_STOP and it was just resumed using + * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged + * from the previous callback. In this way, the original signal can + * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN + * and then found again when resuming @task with %UTRACE_INTERRUPT. + * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, + * and might be in @action if the previous engine returned it. This + * flag asks that the signal in @info be pushed back on @task's queue + * so that it will be seen again after whatever action is taken now. + * + * @report_clone: + * Requested by %UTRACE_EVENT(%CLONE). + * Event reported for parent, before the new task @child might run. + * @clone_flags gives the flags used in the clone system call, + * or equivalent flags for a fork() or vfork() system call. + * This function can use utrace_attach_task() on @child. It's guaranteed + * that asynchronous utrace_attach_task() calls will be ordered after + * any calls in @report_clone callbacks for the parent. Thus + * when using %UTRACE_ATTACH_EXCLUSIVE in the asynchronous calls, + * you can be sure that the parent's @report_clone callback has + * already attached to @child or chosen not to. Passing %UTRACE_STOP + * to utrace_control() on @child here keeps the child stopped before + * it ever runs in user mode, %UTRACE_REPORT or %UTRACE_INTERRUPT + * ensures a callback from @child before it starts in user mode. + * + * @report_jctl: + * Requested by %UTRACE_EVENT(%JCTL). + * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, + * indicating whether we are stopping or resuming now. If @notify + * is nonzero, @task is the last thread to stop and so will send + * %SIGCHLD to its parent after this callback; @notify reflects + * what the parent's %SIGCHLD has in @si_code, which can sometimes + * be %CLD_STOPPED even when @type is %CLD_CONTINUED. + * + * @report_exec: + * Requested by %UTRACE_EVENT(%EXEC). + * An execve system call has succeeded and the new program is about to + * start running. The initial user register state is handy to be tweaked + * directly in @regs. @fmt and @bprm gives the details of this exec. + * + * @report_syscall_entry: + * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). + * Thread has entered the kernel to request a system call. + * The user register state is handy to be tweaked directly in @regs. + * The @action argument contains an &enum utrace_syscall_action, + * use utrace_syscall_action() to extract it. The return value + * overrides the last engine's action for the system call. + * If the final action is %UTRACE_SYSCALL_ABORT, no system call + * is made. The details of the system call being attempted can + * be fetched here with syscall_get_nr() and syscall_get_arguments(). + * The parameter registers can be changed with syscall_set_arguments(). + * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. + * Use %UTRACE_REPORT in the return value to guarantee you get + * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case + * @task stops with %UTRACE_STOP before attempting the system call. + * + * @report_syscall_exit: + * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). + * Thread is about to leave the kernel after a system call request. + * The user register state is handy to be tweaked directly in @regs. + * The results of the system call attempt can be examined here using + * syscall_get_error() and syscall_get_return_value(). It is safe + * here to call syscall_set_return_value() or syscall_rollback(). + * + * @report_exit: + * Requested by %UTRACE_EVENT(%EXIT). + * Thread is exiting and cannot be prevented from doing so, + * but all its state is still live. The @code value will be + * the wait result seen by the parent, and can be changed by + * this engine or others. The @orig_code value is the real + * status, not changed by any tracing engine. Returning %UTRACE_STOP + * here keeps @task stopped before it cleans up its state and dies, + * so it can be examined by other processes. When @task is allowed + * to run, it will die and get to the @report_death callback. + * + * @report_death: + * Requested by %UTRACE_EVENT(%DEATH). + * Thread is really dead now. It might be reaped by its parent at + * any time, or self-reap immediately. Though the actual reaping + * may happen in parallel, a report_reap() callback will always be + * ordered after a report_death() callback. + * + * @report_reap: + * Requested by %UTRACE_EVENT(%REAP). + * Called when someone reaps the dead task (parent, init, or self). + * This means the parent called wait, or else this was a detached + * thread or a process whose parent ignores SIGCHLD. + * No more callbacks are made after this one. + * The engine is always detached. + * There is nothing more a tracing engine can do about this thread. + * After this callback, the @engine pointer will become invalid. + * The @task pointer may become invalid if get_task_struct() hasn't + * been used to keep it alive. + * An engine should always request this callback if it stores the + * @engine pointer or stores any pointer in @engine->data, so it + * can clean up its data structures. + * Unlike other callbacks, this can be called from the parent's context + * rather than from the traced thread itself--it must not delay the + * parent by blocking. + * + * @release: + * If not %NULL, this is called after the last utrace_engine_put() + * call for a &struct utrace_engine, which could be implicit after + * a %UTRACE_DETACH return from another callback. Its argument is + * the engine's @data member. + */ +struct utrace_engine_ops { + u32 (*report_quiesce)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event); + u32 (*report_signal)(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka); + u32 (*report_clone)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child); + u32 (*report_jctl)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + int type, int notify); + u32 (*report_exec)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs); + u32 (*report_syscall_entry)(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs); + u32 (*report_syscall_exit)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs); + u32 (*report_exit)(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code); + u32 (*report_death)(struct utrace_engine *engine, + struct task_struct *task, + bool group_dead, int signal); + void (*report_reap)(struct utrace_engine *engine, + struct task_struct *task); + void (*release)(void *data); +}; + +/** + * struct utrace_examiner - private state for using utrace_prepare_examine() + * + * The members of &struct utrace_examiner are private to the implementation. + * This data type holds the state from a call to utrace_prepare_examine() + * to be used by a call to utrace_finish_examine(). + */ +struct utrace_examiner { +/* private: */ + long state; + unsigned long ncsw; +}; + +/* + * These are the exported entry points for tracing engines to use. + * See kernel/utrace.c for their kerneldoc comments with interface details. + */ +struct utrace_engine *utrace_attach_task(struct task_struct *, int, + const struct utrace_engine_ops *, + void *); +struct utrace_engine *utrace_attach_pid(struct pid *, int, + const struct utrace_engine_ops *, + void *); +int __must_check utrace_control(struct task_struct *, + struct utrace_engine *, + enum utrace_resume_action); +int __must_check utrace_set_events(struct task_struct *, + struct utrace_engine *, + unsigned long eventmask); +int __must_check utrace_barrier(struct task_struct *, + struct utrace_engine *); +int __must_check utrace_prepare_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); +int __must_check utrace_finish_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); + +/** + * utrace_control_pid - control a thread being traced by a tracing engine + * @pid: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is the same as utrace_control(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_control_pid( + struct pid *pid, struct utrace_engine *engine, + enum utrace_resume_action action) +{ + /* + * We don't bother with rcu_read_lock() here to protect the + * task_struct pointer, because utrace_control will return + * -ESRCH without looking at that pointer if the engine is + * already detached. A task_struct pointer can't die before + * all the engines are detached in release_task() first. + */ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); +} + +/** + * utrace_set_events_pid - choose which event reports a tracing engine gets + * @pid: thread to affect + * @engine: attached engine to affect + * @eventmask: new event mask + * + * This is the same as utrace_set_events(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_set_events_pid( + struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : + utrace_set_events(task, engine, eventmask); +} + +/** + * utrace_barrier_pid - synchronize with simultaneous tracing callbacks + * @pid: thread to affect + * @engine: engine to affect (can be detached) + * + * This is the same as utrace_barrier(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_barrier_pid(struct pid *pid, + struct utrace_engine *engine) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); +} + +#endif /* CONFIG_UTRACE */ + +#endif /* linux/utrace.h */ --- V1/init/Kconfig~14_UTRACE 2009-11-24 20:27:22.000000000 +0100 +++ V1/init/Kconfig 2009-11-24 20:46:05.000000000 +0100 @@ -295,6 +295,15 @@ config AUDIT logging of avc messages output). Does not do system-call auditing without CONFIG_AUDITSYSCALL. +config UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + config AUDITSYSCALL bool "Enable system-call auditing support" depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH) --- V1/kernel/fork.c~14_UTRACE 2009-11-24 20:27:22.000000000 +0100 +++ V1/kernel/fork.c 2009-11-24 20:30:17.000000000 +0100 @@ -152,6 +152,7 @@ void free_task(struct task_struct *tsk) free_thread_info(tsk->stack); rt_mutex_debug_task_free(tsk); ftrace_graph_exit_task(tsk); + tracehook_free_task(tsk); free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -1018,6 +1019,8 @@ static struct task_struct *copy_process( if (!p) goto fork_out; + tracehook_init_task(p); + ftrace_graph_init_task(p); rt_mutex_init_task(p); --- V1/kernel/Makefile~14_UTRACE 2009-11-24 20:30:17.000000000 +0100 +++ V1/kernel/Makefile 2009-11-24 20:30:17.000000000 +0100 @@ -68,6 +68,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += utrace.o obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o --- /dev/null 2009-11-24 16:51:11.614043008 +0100 +++ V1/kernel/utrace.c 2009-11-24 20:30:17.000000000 +0100 @@ -0,0 +1,2430 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Per-thread structure private to utrace implementation. + * If task_struct.utrace_flags is nonzero, task_struct.utrace + * has always been allocated first. Once allocated, it is + * never freed until free_task(). + * + * The common event reporting loops are done by the task making the + * report without ever taking any locks. To facilitate this, the two + * lists @attached and @attaching work together for smooth asynchronous + * attaching with low overhead. Modifying either list requires @lock. + * The @attaching list can be modified any time while holding @lock. + * New engines being attached always go on this list. + * + * The @attached list is what the task itself uses for its reporting + * loops. When the task itself is not quiescent, it can use the + * @attached list without taking any lock. Nobody may modify the list + * when the task is not quiescent. When it is quiescent, that means + * that it won't run again without taking @lock itself before using + * the list. + * + * At each place where we know the task is quiescent (or it's current), + * while holding @lock, we call splice_attaching(), below. This moves + * the @attaching list members on to the end of the @attached list. + * Since this happens at the start of any reporting pass, any new + * engines attached asynchronously go on the stable @attached list + * in time to have their callbacks seen. + */ +struct utrace { + spinlock_t lock; + struct list_head attached, attaching; + + struct task_struct *cloning; + + struct utrace_engine *reporting; + + enum utrace_resume_action resume:3; + unsigned int signal_handler:1; + unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ + unsigned int death:1; /* in utrace_report_death() now */ + unsigned int reap:1; /* release_task() has run */ + unsigned int pending_attach:1; /* need splice_attaching() */ +}; + +static struct kmem_cache *utrace_cachep; +static struct kmem_cache *utrace_engine_cachep; +static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ + +static int __init utrace_init(void) +{ + utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); + utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); + return 0; +} +module_init(utrace_init); + +/* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() + * governs installing the new pointer. If another one got in first, + * we just punt the new one we allocated. + * + * This returns false only in case of a memory allocation failure. + */ +static bool utrace_task_alloc(struct task_struct *task) +{ + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); + INIT_LIST_HEAD(&utrace->attached); + INIT_LIST_HEAD(&utrace->attaching); + utrace->resume = UTRACE_RESUME; + task_lock(task); + if (likely(!task->utrace)) { + /* + * This barrier makes sure the initialization of the struct + * precedes the installation of the pointer. This pairs + * with smp_read_barrier_depends() in task_utrace_struct(). + */ + smp_wmb(); + task->utrace = utrace; + } + task_unlock(task); + /* + * That unlock after storing task->utrace acts as a memory barrier + * ordering any subsequent task->utrace_flags store afterwards. + * This pairs with smp_rmb() in task_utrace_struct(). + */ + if (unlikely(task->utrace != utrace)) + kmem_cache_free(utrace_cachep, utrace); + return true; +} + +/* + * This is called via tracehook_free_task() from free_task() + * when @task is being deallocated. + */ +void utrace_free_task(struct task_struct *task) +{ + kmem_cache_free(utrace_cachep, task->utrace); +} + +/* + * This is called with @utrace->lock held when the task is safely + * quiescent, i.e. it won't consult utrace->attached without the lock. + * Move any engines attached asynchronously from @utrace->attaching + * onto the @utrace->attached list. + */ +static void splice_attaching(struct utrace *utrace) +{ + list_splice_tail_init(&utrace->attaching, &utrace->attached); + utrace->pending_attach = 0; +} + +/* + * This is the exported function used by the utrace_engine_put() inline. + */ +void __utrace_engine_release(struct kref *kref) +{ + struct utrace_engine *engine = container_of(kref, struct utrace_engine, + kref); + BUG_ON(!list_empty(&engine->entry)); + if (engine->release) + (*engine->release)(engine->data); + kmem_cache_free(utrace_engine_cachep, engine); +} +EXPORT_SYMBOL_GPL(__utrace_engine_release); + +static bool engine_matches(struct utrace_engine *engine, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) + return false; + if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) + return false; + return engine->ops && engine->ops != &utrace_detached_ops; +} + +static struct utrace_engine *matching_engine( + struct utrace *utrace, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine; + list_for_each_entry(engine, &utrace->attached, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + list_for_each_entry(engine, &utrace->attaching, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + return NULL; +} + +/* + * Called without locks, when we might be the first utrace engine to attach. + * If this is a newborn thread and we are not the creator, we have to wait + * for it. The creator gets the first chance to attach. The PF_STARTING + * flag is cleared after its report_clone hook has had a chance to run. + */ +static inline int utrace_attach_delay(struct task_struct *target) +{ + if ((target->flags & PF_STARTING) && + task_utrace_struct(current) && + task_utrace_struct(current)->cloning != target) + do { + schedule_timeout_interruptible(1); + if (signal_pending(current)) + return -ERESTARTNOINTR; + } while (target->flags & PF_STARTING); + + return 0; +} + +/* + * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. + */ +static int utrace_add_engine(struct task_struct *target, + struct utrace *utrace, + struct utrace_engine *engine, + int flags, + const struct utrace_engine_ops *ops, + void *data) +{ + int ret; + + spin_lock(&utrace->lock); + + ret = -EEXIST; + if ((flags & UTRACE_ATTACH_EXCLUSIVE) && + unlikely(matching_engine(utrace, flags, ops, data))) + goto unlock; + + /* + * In case we had no engines before, make sure that + * utrace_flags is not zero. + */ + ret = -ESRCH; + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); + /* + * If we race with tracehook_prepare_release_task() + * make sure that either it sees utrace_flags != 0 + * or we see exit_state == EXIT_DEAD. + */ + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + goto unlock; + } + } + + /* + * Put the new engine on the pending ->attaching list. + * Make sure it gets onto the ->attached list by the next + * time it's examined. Setting ->pending_attach ensures + * that start_report() takes the lock and splices the lists + * before the next new reporting pass. + * + * When target == current, it would be safe just to call + * splice_attaching() right here. But if we're inside a + * callback, that would mean the new engine also gets + * notified about the event that precipitated its own + * creation. This is not what the user wants. + */ + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + ret = 0; +unlock: + spin_unlock(&utrace->lock); + + return ret; +} + +/** + * utrace_attach_task - attach new engine, or look up an attached engine + * @target: thread to attach to + * @flags: flag bits combined with OR, see below + * @ops: callback table for new engine + * @data: engine private data pointer + * + * The caller must ensure that the @target thread does not get freed, + * i.e. hold a ref or be its parent. It is always safe to call this + * on @current, or on the @child pointer in a @report_clone callback. + * For most other cases, it's easier to use utrace_attach_pid() instead. + * + * UTRACE_ATTACH_CREATE: + * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you + * only look up an existing engine already attached to the thread. + * + * UTRACE_ATTACH_EXCLUSIVE: + * Attempting to attach a second (matching) engine fails with -%EEXIST. + * + * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. + * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. + * + * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA + * match the first among any engines attached to @target. That means that + * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there + * are any engines on @target at all. + */ +struct utrace_engine *utrace_attach_task( + struct task_struct *target, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { + if (unlikely(!utrace)) + return ERR_PTR(-ENOENT); + spin_lock(&utrace->lock); + engine = matching_engine(utrace, flags, ops, data); + if (engine) + utrace_engine_get(engine); + spin_unlock(&utrace->lock); + return engine ?: ERR_PTR(-ENOENT); + } + + if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) + return ERR_PTR(-EINVAL); + + if (unlikely(target->flags & PF_KTHREAD)) + /* + * Silly kernel, utrace is for users! + */ + return ERR_PTR(-EPERM); + + if (!utrace) { + if (unlikely(!utrace_task_alloc(target))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + + engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + + /* + * Initialize the new engine structure. It starts out with two + * refs: one ref to return, and one ref for being attached. + */ + kref_set(&engine->kref, 2); + engine->flags = 0; + engine->ops = ops; + engine->data = data; + engine->release = ops->release; + + ret = utrace_attach_delay(target); + if (likely(!ret)) + ret = utrace_add_engine(target, utrace, engine, + flags, ops, data); + + if (unlikely(ret)) { + kmem_cache_free(utrace_engine_cachep, engine); + engine = ERR_PTR(ret); + } + + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_task); + +/** + * utrace_attach_pid - attach new engine, or look up an attached engine + * @pid: &struct pid pointer representing thread to attach to + * @flags: flag bits combined with OR, see utrace_attach_task() + * @ops: callback table for new engine + * @data: engine private data pointer + * + * This is the same as utrace_attach_task(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +struct utrace_engine *utrace_attach_pid( + struct pid *pid, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine = ERR_PTR(-ESRCH); + struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); + if (task) { + engine = utrace_attach_task(task, flags, ops, data); + put_task_struct(task); + } + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_pid); + +/* + * When an engine is detached, the target thread may still see it and + * make callbacks until it quiesces. We install a special ops vector + * with these two callbacks. When the target thread quiesces, it can + * safely free the engine itself. For any event we will always get + * the report_quiesce() callback first, so we only need this one + * pointer to be set. The only exception is report_reap(), so we + * supply that callback too. + */ +static u32 utrace_detached_quiesce(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + unsigned long event) +{ + return UTRACE_DETACH; +} + +static void utrace_detached_reap(struct utrace_engine *engine, + struct task_struct *task) +{ +} + +static const struct utrace_engine_ops utrace_detached_ops = { + .report_quiesce = &utrace_detached_quiesce, + .report_reap = &utrace_detached_reap +}; + +/* + * The caller has to hold a ref on the engine. If the attached flag is + * true (all but utrace_barrier() calls), the engine is supposed to be + * attached. If the attached flag is false (utrace_barrier() only), + * then return -ERESTARTSYS for an engine marked for detach but not yet + * fully detached. The task pointer can be invalid if the engine is + * detached. + * + * Get the utrace lock for the target task. + * Returns the struct if locked, or ERR_PTR(-errno). + * + * This has to be robust against races with: + * utrace_control(target, UTRACE_DETACH) calls + * UTRACE_DETACH after reports + * utrace_report_death + * utrace_release_task + */ +static struct utrace *get_utrace_lock(struct task_struct *target, + struct utrace_engine *engine, + bool attached) + __acquires(utrace->lock) +{ + struct utrace *utrace; + + rcu_read_lock(); + + /* + * If this engine was already detached, bail out before we look at + * the task_struct pointer at all. If it's detached after this + * check, then RCU is still keeping this task_struct pointer valid. + * + * The ops pointer is NULL when the engine is fully detached. + * It's &utrace_detached_ops when it's marked detached but still + * on the list. In the latter case, utrace_barrier() still works, + * since the target might be in the middle of an old callback. + */ + if (unlikely(!engine->ops)) { + rcu_read_unlock(); + return ERR_PTR(-ESRCH); + } + + if (unlikely(engine->ops == &utrace_detached_ops)) { + rcu_read_unlock(); + return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); + } + + utrace = task_utrace_struct(target); + spin_lock(&utrace->lock); + if (unlikely(!engine->ops) || + unlikely(engine->ops == &utrace_detached_ops)) { + /* + * By the time we got the utrace lock, + * it had been reaped or detached already. + */ + spin_unlock(&utrace->lock); + utrace = ERR_PTR(-ESRCH); + if (!attached && engine->ops == &utrace_detached_ops) + utrace = ERR_PTR(-ERESTARTSYS); + } + rcu_read_unlock(); + + return utrace; +} + +/* + * Now that we don't hold any locks, run through any + * detached engines and free their references. Each + * engine had one implicit ref while it was attached. + */ +static void put_detached_list(struct list_head *list) +{ + struct utrace_engine *engine, *next; + list_for_each_entry_safe(engine, next, list, entry) { + list_del_init(&engine->entry); + utrace_engine_put(engine); + } +} + +/* + * Called with utrace->lock held and utrace->reap set. + * Notify and clean up all engines, then free utrace. + */ +static void utrace_reap(struct task_struct *target, struct utrace *utrace) + __releases(utrace->lock) +{ + struct utrace_engine *engine, *next; + + /* utrace_add_engine() checks ->utrace_flags != 0 */ + target->utrace_flags = 0; + splice_attaching(utrace); + + /* + * Since we were called with @utrace->reap set, nobody can + * set/clear UTRACE_EVENT(REAP) in @engine->flags or change + * @engine->ops, and nobody can change @utrace->attached. + */ + spin_unlock(&utrace->lock); + + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->flags & UTRACE_EVENT(REAP)) + engine->ops->report_reap(engine, target); + + engine->ops = NULL; + engine->flags = 0; + list_del_init(&engine->entry); + + utrace_engine_put(engine); + } +} + + +/* + * Called by release_task. + */ +void utrace_release_task(struct task_struct *target) +{ + struct utrace *utrace = task_utrace_struct(target); + + spin_lock(&utrace->lock); + + utrace->reap = 1; + + /* + * If the target will do some final callbacks but hasn't + * finished them yet, we know because it clears these event + * bits after it's done. Instead of cleaning up here and + * requiring utrace_report_death() to cope with it, we delay + * the REAP report and the teardown until after the target + * finishes its death reports. + */ + + if (target->utrace_flags & _UTRACE_DEATH_EVENTS) + spin_unlock(&utrace->lock); + else + utrace_reap(target, utrace); /* Unlocks. */ +} + +/* + * We use an extra bit in utrace_engine.flags past the event bits, + * to record whether the engine is keeping the target thread stopped. + * + * This bit is set in task_struct.utrace_flags whenever it is set in any + * engine's flags. Only utrace_reset() resets it in utrace_flags. + */ +#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + +static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) +{ + engine->flags |= ENGINE_STOP; + task->utrace_flags |= ENGINE_STOP; +} + +static void clear_engine_wants_stop(struct utrace_engine *engine) +{ + engine->flags &= ~ENGINE_STOP; +} + +static bool engine_wants_stop(struct utrace_engine *engine) +{ + return (engine->flags & ENGINE_STOP) != 0; +} + +/** + * utrace_set_events - choose which event reports a tracing engine gets + * @target: thread to affect + * @engine: attached engine to affect + * @events: new event mask + * + * This changes the set of events for which @engine wants callbacks made. + * + * This fails with -%EALREADY and does nothing if you try to clear + * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have + * begun, if you try to clear %UTRACE_EVENT(%REAP) when the @report_reap + * callback may already have begun, or if you try to newly set + * %UTRACE_EVENT(%DEATH) or %UTRACE_EVENT(%QUIESCE) when @target is + * already dead or dying. + * + * This can fail with -%ESRCH when @target has already been detached, + * including forcible detach on reaping. + * + * If @target was stopped before the call, then after a successful call, + * no event callbacks not requested in @events will be made; if + * %UTRACE_EVENT(%QUIESCE) is included in @events, then a + * @report_quiesce callback will be made when @target resumes. + * + * If @target was not stopped and @events excludes some bits that were + * set before, this can return -%EINPROGRESS to indicate that @target + * may have been making some callback to @engine. When this returns + * zero, you can be sure that no event callbacks you've disabled in + * @events can be made. If @events only sets new bits that were not set + * before on @engine, then -%EINPROGRESS will never be returned. + * + * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). + * + * When @target is @current, -%EINPROGRESS is not returned. But note + * that a newly-created engine will not receive any callbacks related to + * an event notification already in progress. This call enables @events + * callbacks to be made as soon as @engine becomes eligible for any + * callbacks, see utrace_attach_task(). + * + * These rules provide for coherent synchronization based on %UTRACE_STOP, + * even when %SIGKILL is breaking its normal simple rules. + */ +int utrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long events) +{ + struct utrace *utrace; + unsigned long old_flags, old_utrace_flags; + int ret; + + /* + * We just ignore the internal bit, so callers can use + * engine->flags to seed bitwise ops for our argument. + */ + events &= ~ENGINE_STOP; + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + old_utrace_flags = target->utrace_flags; + old_flags = engine->flags & ~ENGINE_STOP; + + if (target->exit_state && + (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || + (utrace->death && + ((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) || + (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) { + spin_unlock(&utrace->lock); + return -EALREADY; + } + + /* + * When setting these flags, it's essential that we really + * synchronize with exit_notify(). They cannot be set after + * exit_notify() takes the tasklist_lock. By holding the read + * lock here while setting the flags, we ensure that the calls + * to tracehook_notify_death() and tracehook_report_death() will + * see the new flags. This ensures that utrace_release_task() + * knows positively that utrace_report_death() will be called or + * that it won't. + */ + if ((events & ~old_utrace_flags) & _UTRACE_DEATH_EVENTS) { + read_lock(&tasklist_lock); + if (unlikely(target->exit_state)) { + read_unlock(&tasklist_lock); + spin_unlock(&utrace->lock); + return -EALREADY; + } + target->utrace_flags |= events; + read_unlock(&tasklist_lock); + } + + engine->flags = events | (engine->flags & ENGINE_STOP); + target->utrace_flags |= events; + + if ((events & UTRACE_EVENT_SYSCALL) && + !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) + set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); + + ret = 0; + if ((old_flags & ~events) && target != current && + !task_is_stopped_or_traced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, + * pairing with the barrier in start_callback(). If + * @target has not yet hit finish_callback() to clear + * utrace->reporting, we might be in the middle of a + * callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_set_events); + +/* + * Asynchronously mark an engine as being detached. + * + * This must work while the target thread races with us doing + * start_callback(), defined below. It uses smp_rmb() between checking + * @engine->flags and using @engine->ops. Here we change @engine->ops + * first, then use smp_wmb() before changing @engine->flags. This ensures + * it can check the old flags before using the old ops, or check the old + * flags before using the new ops, or check the new flags before using the + * new ops, but can never check the new flags before using the old ops. + * Hence, utrace_detached_ops might be used with any old flags in place. + * It has report_quiesce() and report_reap() callbacks to handle all cases. + */ +static void mark_engine_detached(struct utrace_engine *engine) +{ + engine->ops = &utrace_detached_ops; + smp_wmb(); + engine->flags = UTRACE_EVENT(QUIESCE); +} + +/* + * Get @target to stop and return true if it is already stopped now. + * If we return false, it will make some event callback soonish. + * Called with @utrace locked. + */ +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) +{ + if (task_is_stopped(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); + if (likely(task_is_stopped(target))) + __set_task_state(target, TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + + return task_is_traced(target); +} + +/* + * If the target is not dead it should not be in tracing + * stop any more. Wake it unless it's in job control stop. + * + * Called with @utrace->lock held and @target in either TASK_TRACED or dead. + */ +static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) +{ + spin_lock_irq(&target->sighand->siglock); + if (target->signal->flags & SIGNAL_STOP_STOPPED || + target->signal->group_stop_count) + target->state = TASK_STOPPED; + else + wake_up_state(target, __TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); +} + +/* + * This is called when there might be some detached engines on the list or + * some stale bits in @task->utrace_flags. Clean them up and recompute the + * flags. Returns true if we're now fully detached. + * + * Called with @utrace->lock held, returns with it released. + * After this returns, @utrace might be freed if everything detached. + */ +static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + __releases(utrace->lock) +{ + struct utrace_engine *engine, *next; + unsigned long flags = 0; + LIST_HEAD(detached); + + splice_attaching(utrace); + + /* + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + * For any engine marked detached, remove it from the list. + * We'll collect them on the detached list. + */ + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->ops == &utrace_detached_ops) { + engine->ops = NULL; + list_move(&engine->entry, &detached); + } else { + flags |= engine->flags | UTRACE_EVENT(REAP); + } + } + + if (task->exit_state) { + /* + * Once it's already dead, we never install any flags + * except REAP. When ->exit_state is set and events + * like DEATH are not set, then they never can be set. + * This ensures that utrace_release_task() knows + * positively that utrace_report_death() can never run. + */ + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } + + if (!flags) { + /* + * No more engines, cleared out the utrace. + */ + utrace->resume = UTRACE_RESUME; + utrace->signal_handler = 0; + } + + if (task_is_traced(task) && !(flags & ENGINE_STOP)) + /* + * No more engines want it stopped. Wake it up. + */ + utrace_wakeup(task, utrace); + + /* + * In theory spin_lock() doesn't imply rcu_read_lock(). + * Once we clear ->utrace_flags this task_struct can go away + * because tracehook_prepare_release_task() path does not take + * utrace->lock when ->utrace_flags == 0. + */ + rcu_read_lock(); + task->utrace_flags = flags; + spin_unlock(&utrace->lock); + rcu_read_unlock(); + + put_detached_list(&detached); + + return !flags; +} + +void utrace_finish_stop(void) +{ + /* + * If we were task_is_traced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { + struct utrace *utrace = task_utrace_struct(current); + spin_unlock_wait(&utrace->lock); + } +} + +/* + * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. + */ +static void utrace_stop(struct task_struct *task, struct utrace *utrace, + enum utrace_resume_action action) +{ +relock: + spin_lock(&utrace->lock); + + if (action < utrace->resume) { + /* + * Ensure a reporting pass when we're resumed. + */ + utrace->resume = action; + if (action == UTRACE_INTERRUPT) + set_thread_flag(TIF_SIGPENDING); + else + set_thread_flag(TIF_NOTIFY_RESUME); + } + + /* + * If the ENGINE_STOP bit is clear in utrace_flags, that means + * utrace_reset() ran after we processed some UTRACE_STOP return + * values from callbacks to get here. If all engines have detached + * or resumed us, we don't stop. This check doesn't require + * siglock, but it should follow the interrupt/report bookkeeping + * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). + */ + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { + utrace_reset(task, utrace); + if (task->utrace_flags & ENGINE_STOP) + goto relock; + return; + } + + /* + * The siglock protects us against signals. As well as SIGKILL + * waking us up, we must synchronize with the signal bookkeeping + * for stop signals and SIGCONT. + */ + spin_lock_irq(&task->sighand->siglock); + + if (unlikely(__fatal_signal_pending(task))) { + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + return; + } + + __set_current_state(TASK_TRACED); + + /* + * If there is a group stop in progress, + * we must participate in the bookkeeping. + */ + if (unlikely(task->signal->group_stop_count) && + !--task->signal->group_stop_count) + task->signal->flags = SIGNAL_STOP_STOPPED; + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + + /* + * If ptrace is among the reasons for this stop, do its + * notification now. This could not just be done in + * ptrace's own event report callbacks because it has to + * be done after we are in TASK_TRACED. This makes the + * synchronization with ptrace_do_wait() work right. + */ + ptrace_notify_stop(task); + + schedule(); + + utrace_finish_stop(); + + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* + * While we were in TASK_TRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); +} + +/* + * You can't do anything to a dead task but detach it. + * If release_task() has been called, you can't do that. + * + * On the exit path, DEATH and QUIESCE event bits are set only + * before utrace_report_death() has taken the lock. At that point, + * the death report will come soon, so disallow detach until it's + * done. This prevents us from racing with it detaching itself. + * + * Called with utrace->lock held, when @target->exit_state is nonzero. + */ +static inline int utrace_control_dead(struct task_struct *target, + struct utrace *utrace, + enum utrace_resume_action action) +{ + if (action != UTRACE_DETACH || unlikely(utrace->reap)) + return -ESRCH; + + if (unlikely(utrace->death)) + /* + * We have already started the death report. We can't + * prevent the report_death and report_reap callbacks, + * so tell the caller they will happen. + */ + return -EALREADY; + + return 0; +} + +/** + * utrace_control - control a thread being traced by a tracing engine + * @target: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is how a tracing engine asks a traced thread to do something. + * This call is controlled by the @action argument, which has the + * same meaning as the &enum utrace_resume_action value returned by + * event reporting callbacks. + * + * If @target is already dead (@target->exit_state nonzero), + * all actions except %UTRACE_DETACH fail with -%ESRCH. + * + * The following sections describe each option for the @action argument. + * + * UTRACE_DETACH: + * + * After this, the @engine data structure is no longer accessible, + * and the thread might be reaped. The thread will start running + * again if it was stopped and no longer has any attached engines + * that want it stopped. + * + * If the @report_reap callback may already have begun, this fails + * with -%ESRCH. If the @report_death callback may already have + * begun, this fails with -%EALREADY. + * + * If @target is not already stopped, then a callback to this engine + * might be in progress or about to start on another CPU. If so, + * then this returns -%EINPROGRESS; the detach happens as soon as + * the pending callback is finished. To synchronize after an + * -%EINPROGRESS return, see utrace_barrier(). + * + * If @target is properly stopped before utrace_control() is called, + * then after successful return it's guaranteed that no more callbacks + * to the @engine->ops vector will be made. + * + * The only exception is %SIGKILL (and exec or group-exit by another + * thread in the group), which can cause asynchronous @report_death + * and/or @report_reap callbacks even when %UTRACE_STOP was used. + * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) + * + * UTRACE_STOP: + * + * This asks that @target stop running. This returns 0 only if + * @target is already stopped, either for tracing or for job + * control. Then @target will remain stopped until another + * utrace_control() call is made on @engine; @target can be woken + * only by %SIGKILL (or equivalent, such as exec or termination by + * another thread in the same thread group). + * + * This returns -%EINPROGRESS if @target is not already stopped. + * Then the effect is like %UTRACE_REPORT. A @report_quiesce or + * @report_signal callback will be made soon. Your callback can + * then return %UTRACE_STOP to keep @target stopped. + * + * This does not interrupt system calls in progress, including ones + * that sleep for a long time. For that, use %UTRACE_INTERRUPT. + * To interrupt system calls and then keep @target stopped, your + * @report_signal callback can return %UTRACE_STOP. + * + * UTRACE_RESUME: + * + * Just let @target continue running normally, reversing the effect + * of a previous %UTRACE_STOP. If another engine is keeping @target + * stopped, then it remains stopped until all engines let it resume. + * If @target was not stopped, this has no effect. + * + * UTRACE_REPORT: + * + * This is like %UTRACE_RESUME, but also ensures that there will be + * a @report_quiesce or @report_signal callback made soon. If + * @target had been stopped, then there will be a callback before it + * resumes running normally. If another engine is keeping @target + * stopped, then there might be no callbacks until all engines let + * it resume. + * + * Since this is meaningless unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_INTERRUPT: + * + * This is like %UTRACE_REPORT, but ensures that @target will make a + * @report_signal callback before it resumes or delivers signals. + * If @target was in a system call or about to enter one, work in + * progress will be interrupted as if by %SIGSTOP. If another + * engine is keeping @target stopped, then there might be no + * callbacks until all engines let it resume. + * + * This gives @engine an opportunity to introduce a forced signal + * disposition via its @report_signal callback. + * + * UTRACE_SINGLESTEP: + * + * It's invalid to use this unless arch_has_single_step() returned true. + * This is like %UTRACE_RESUME, but resumes for one user instruction only. + * + * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to + * utrace_control() or returning it from an event callback alone does + * not necessarily ensure that stepping will be enabled. If there are + * more callbacks made to any engine before returning to user mode, + * then the resume action is chosen only by the last set of callbacks. + * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the + * @report_quiesce callback with a zero event mask, or the + * @report_signal callback with %UTRACE_SIGNAL_REPORT. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_BLOCKSTEP: + * + * It's invalid to use this unless arch_has_block_step() returned true. + * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic + * block of user instructions. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another + * tracing engine is using %UTRACE_SINGLESTEP at the same time. + */ +int utrace_control(struct task_struct *target, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + struct utrace *utrace; + bool reset; + int ret; + + if (unlikely(action > UTRACE_DETACH)) + return -EINVAL; + + /* + * This is a sanity check for a programming error in the caller. + * Their request can only work properly in all cases by relying on + * a follow-up callback, but they didn't set one up! This check + * doesn't do locking, but it shouldn't matter. The caller has to + * be synchronously sure the callback is set up to be operating the + * interface properly. + */ + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) + return -EINVAL; + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + reset = task_is_traced(target); + ret = 0; + + /* + * ->exit_state can change under us, this doesn't matter. + * We do not care about ->exit_state in fact, but we do + * care about ->reap and ->death. If either flag is set, + * we must also see ->exit_state != 0. + */ + if (unlikely(target->exit_state)) { + ret = utrace_control_dead(target, utrace, action); + if (ret) { + spin_unlock(&utrace->lock); + return ret; + } + reset = true; + } + + switch (action) { + case UTRACE_STOP: + mark_engine_wants_stop(target, engine); + if (!reset && !utrace_do_stop(target, utrace)) + ret = -EINPROGRESS; + reset = false; + break; + + case UTRACE_DETACH: + if (engine_wants_stop(engine)) + target->utrace_flags &= ~ENGINE_STOP; + mark_engine_detached(engine); + reset = reset || utrace_do_stop(target, utrace); + if (!reset) { + /* + * As in utrace_set_events(), this barrier ensures + * that our engine->flags changes have hit before we + * examine utrace->reporting, pairing with the barrier + * in start_callback(). If @target has not yet hit + * finish_callback() to clear utrace->reporting, we + * might be in the middle of a callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + break; + + case UTRACE_RESUME: + /* + * This and all other cases imply resuming if stopped. + * There might not be another report before it just + * resumes, so make sure single-step is not left set. + */ + clear_engine_wants_stop(engine); + if (likely(reset)) + user_disable_single_step(target); + break; + + case UTRACE_BLOCKSTEP: + /* + * Resume from stopped, step one block. + * We fall through to treat it like UTRACE_SINGLESTEP. + */ + if (unlikely(!arch_has_block_step())) { + WARN_ON(1); + action = UTRACE_SINGLESTEP; + } + + case UTRACE_SINGLESTEP: + /* + * Resume from stopped, step one instruction. + * We fall through to the UTRACE_REPORT case. + */ + if (unlikely(!arch_has_single_step())) { + WARN_ON(1); + reset = false; + ret = -EOPNOTSUPP; + break; + } + + case UTRACE_REPORT: + /* + * Make the thread call tracehook_notify_resume() soon. + * But don't bother if it's already been interrupted. + * In that case, utrace_get_signal() will be reporting soon. + */ + clear_engine_wants_stop(engine); + if (action < utrace->resume) { + utrace->resume = action; + set_notify_resume(target); + } + break; + + case UTRACE_INTERRUPT: + /* + * Make the thread call tracehook_get_signal() soon. + */ + clear_engine_wants_stop(engine); + if (utrace->resume == UTRACE_INTERRUPT) + break; + utrace->resume = UTRACE_INTERRUPT; + + /* + * If it's not already stopped, interrupt it now. We need + * the siglock here in case it calls recalc_sigpending() + * and clears its own TIF_SIGPENDING. By taking the lock, + * we've serialized any later recalc_sigpending() after our + * setting of utrace->resume to force it on. + */ + if (reset) { + /* + * This is really just to keep the invariant that + * TIF_SIGPENDING is set with UTRACE_INTERRUPT. + * When it's stopped, we know it's always going + * through utrace_get_signal() and will recalculate. + */ + set_tsk_thread_flag(target, TIF_SIGPENDING); + } else { + struct sighand_struct *sighand; + unsigned long irqflags; + sighand = lock_task_sighand(target, &irqflags); + if (likely(sighand)) { + signal_wake_up(target, 0); + unlock_task_sighand(target, &irqflags); + } + } + break; + } + + /* + * Let the thread resume running. If it's not stopped now, + * there is nothing more we need to do. + */ + if (reset) + utrace_reset(target, utrace); + else + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_control); + +/** + * utrace_barrier - synchronize with simultaneous tracing callbacks + * @target: thread to affect + * @engine: engine to affect (can be detached) + * + * This blocks while @target might be in the midst of making a callback to + * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. + * A return value of zero means no callback from @target to @engine was + * in progress. Any effect of its return value (such as %UTRACE_STOP) has + * already been applied to @engine. + * + * It's not necessary to keep the @target pointer alive for this call. + * It's only necessary to hold a ref on @engine. This will return + * safely even if @target has been reaped and has no task refs. + * + * A successful return from utrace_barrier() guarantees its ordering + * with respect to utrace_set_events() and utrace_control() calls. If + * @target was not properly stopped, event callbacks just disabled might + * still be in progress; utrace_barrier() waits until there is no chance + * an unwanted callback can be in progress. + */ +int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) +{ + struct utrace *utrace; + int ret = -ERESTARTSYS; + + if (unlikely(target == current)) + return 0; + + do { + utrace = get_utrace_lock(target, engine, false); + if (unlikely(IS_ERR(utrace))) { + ret = PTR_ERR(utrace); + if (ret != -ERESTARTSYS) + break; + } else { + /* + * All engine state changes are done while + * holding the lock, i.e. before we get here. + * Since we have the lock, we only need to + * worry about @target making a callback. + * When it has entered start_callback() but + * not yet gotten to finish_callback(), we + * will see utrace->reporting == @engine. + * When @target doesn't take the lock, it uses + * barriers to order setting utrace->reporting + * before it examines the engine state. + */ + if (utrace->reporting != engine) + ret = 0; + spin_unlock(&utrace->lock); + if (!ret) + break; + } + schedule_timeout_interruptible(1); + } while (!signal_pending(current)); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_barrier); + +/* + * This is local state used for reporting loops, perhaps optimized away. + */ +struct utrace_report { + u32 result; + enum utrace_resume_action action; + enum utrace_resume_action resume_action; + bool detaches; + bool spurious; +}; + +#define INIT_REPORT(var) \ + struct utrace_report var = { \ + .action = UTRACE_RESUME, \ + .resume_action = UTRACE_RESUME, \ + .spurious = true \ + } + +/* + * We are now making the report, so clear the flag saying we need one. + * When there is a new attach, ->pending_attach is set just so we will + * know to do splice_attaching() here before the callback loop. + */ +static enum utrace_resume_action start_report(struct utrace *utrace) +{ + enum utrace_resume_action resume = utrace->resume; + if (utrace->pending_attach || + (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { + spin_lock(&utrace->lock); + splice_attaching(utrace); + resume = utrace->resume; + if (resume > UTRACE_INTERRUPT) + utrace->resume = UTRACE_RESUME; + spin_unlock(&utrace->lock); + } + return resume; +} + +static inline void finish_report_reset(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + if (unlikely(report->spurious || report->detaches)) { + spin_lock(&utrace->lock); + if (utrace_reset(task, utrace)) + report->action = UTRACE_RESUME; + } +} + +/* + * Complete a normal reporting pass, pairing with a start_report() call. + * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT + * returns from engine callbacks. If @will_not_stop is true and any + * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to + * ensure we stop before user mode. If there were no callbacks made, it + * will recompute @task->utrace_flags to avoid another false-positive. + */ +static void finish_report(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, bool will_not_stop) +{ + enum utrace_resume_action resume = report->action; + + if (resume == UTRACE_STOP) + resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; + + if (resume < utrace->resume) { + spin_lock(&utrace->lock); + utrace->resume = resume; + if (resume == UTRACE_INTERRUPT) + set_tsk_thread_flag(task, TIF_SIGPENDING); + else + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + spin_unlock(&utrace->lock); + } + + finish_report_reset(task, utrace, report); +} + +static inline void finish_callback_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + /* + * If utrace_control() was used, treat that like UTRACE_DETACH here. + */ + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { + engine->ops = &utrace_detached_ops; + report->detaches = true; + return; + } + + if (action < report->action) + report->action = action; + + if (action != UTRACE_STOP) { + if (action < report->resume_action) + report->resume_action = action; + + if (engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + clear_engine_wants_stop(engine); + spin_unlock(&utrace->lock); + } + + return; + } + + if (!engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + /* + * If utrace_control() came in and detached us + * before we got the lock, we must not stop now. + */ + if (unlikely(engine->ops == &utrace_detached_ops)) + report->detaches = true; + else + mark_engine_wants_stop(task, engine); + spin_unlock(&utrace->lock); + } +} + +/* + * Apply the return value of one engine callback to @report. + * Returns true if @engine detached and should not get any more callbacks. + */ +static bool finish_callback(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + u32 ret) +{ + report->result = ret & ~UTRACE_RESUME_MASK; + finish_callback_report(task, utrace, report, engine, + utrace_resume_action(ret)); + + /* + * Now that we have applied the effect of the return value, + * clear this so that utrace_barrier() can stop waiting. + * A subsequent utrace_control() can stop or resume @engine + * and know this was ordered after its callback's action. + * + * We don't need any barriers here because utrace_barrier() + * takes utrace->lock. If we touched engine->flags above, + * the lock guaranteed this change was before utrace_barrier() + * examined utrace->reporting. + */ + utrace->reporting = NULL; + + /* + * This is a good place to make sure tracing engines don't + * introduce too much latency under voluntary preemption. + */ + if (need_resched()) + cond_resched(); + + return engine->ops == &utrace_detached_ops; +} + +/* + * Start the callbacks for @engine to consider @event (a bit mask). + * This makes the report_quiesce() callback first. If @engine wants + * a specific callback for @event, we return the ops vector to use. + * If not, we return NULL. The return value from the ops->callback + * function called should be passed to finish_callback(). + */ +static const struct utrace_engine_ops *start_callback( + struct utrace *utrace, struct utrace_report *report, + struct utrace_engine *engine, struct task_struct *task, + unsigned long event) +{ + const struct utrace_engine_ops *ops; + unsigned long want; + + /* + * This barrier ensures that we've set utrace->reporting before + * we examine engine->flags or engine->ops. utrace_barrier() + * relies on this ordering to indicate that the effect of any + * utrace_control() and utrace_set_events() calls is in place + * by the time utrace->reporting can be seen to be NULL. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(). + * It makes sure that we never see the old ops vector with + * the new flags, in case the original vector had no report_quiesce. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if (want & UTRACE_EVENT(QUIESCE)) { + if (finish_callback(task, utrace, report, engine, + (*ops->report_quiesce)(report->action, + engine, task, + event))) + return NULL; + + /* + * finish_callback() reset utrace->reporting after the + * quiesce callback. Now we set it again (as above) + * before re-examining engine->flags, which could have + * been changed synchronously by ->report_quiesce or + * asynchronously by utrace_control() or utrace_set_events(). + */ + utrace->reporting = engine; + smp_mb(); + want = engine->flags; + } + + if (want & ENGINE_STOP) + report->action = UTRACE_STOP; + + if (want & event) { + report->spurious = false; + return ops; + } + + utrace->reporting = NULL; + return NULL; +} + +/* + * Do a normal reporting pass for engines interested in @event. + * @callback is the name of the member in the ops vector, and remaining + * args are the extras it takes after the standard three args. + */ +#define REPORT(task, utrace, report, event, callback, ...) \ + do { \ + start_report(utrace); \ + REPORT_CALLBACKS(, task, utrace, report, event, callback, \ + (report)->action, engine, current, \ + ## __VA_ARGS__); \ + finish_report(task, utrace, report, true); \ + } while (0) +#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ + do { \ + struct utrace_engine *engine; \ + const struct utrace_engine_ops *ops; \ + list_for_each_entry##rev(engine, &utrace->attached, entry) { \ + ops = start_callback(utrace, report, engine, task, \ + event); \ + if (!ops) \ + continue; \ + finish_callback(task, utrace, report, engine, \ + (*ops->callback)(__VA_ARGS__)); \ + } \ + } while (0) + +/* + * Called iff UTRACE_EVENT(EXEC) flag is set. + */ +void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), + report_exec, fmt, bprm, regs); +} + +static inline u32 do_report_syscall_entry(struct pt_regs *regs, + struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + u32 resume_report) +{ + start_report(utrace); + REPORT_CALLBACKS(_reverse, task, utrace, report, + UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, + resume_report | report->result | report->action, + engine, current, regs); + finish_report(task, utrace, report, false); + + if (report->action != UTRACE_STOP) + return 0; + + utrace_stop(task, utrace, report->resume_action); + + if (fatal_signal_pending(task)) { + /* + * We are continuing despite UTRACE_STOP because of a + * SIGKILL. Don't let the system call actually proceed. + */ + report->result = UTRACE_SYSCALL_ABORT; + } else if (utrace->resume <= UTRACE_REPORT) { + /* + * If we've been asked for another report after our stop, + * go back to report (and maybe stop) again before we run + * the system call. The second (and later) reports are + * marked with the UTRACE_SYSCALL_RESUMED flag so that + * engines know this is a second report at the same + * entry. This gives them the chance to examine the + * registers anew after they might have been changed + * while we were stopped. + */ + report->detaches = false; + report->spurious = true; + report->action = report->resume_action = UTRACE_RESUME; + return UTRACE_SYSCALL_RESUMED; + } + + return 0; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. + * Return true to prevent the system call. + */ +bool utrace_report_syscall_entry(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + u32 resume_report = 0; + + do { + resume_report = do_report_syscall_entry(regs, task, utrace, + &report, resume_report); + } while (resume_report); + + return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. + */ +void utrace_report_syscall_exit(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), + report_syscall_exit, regs); +} + +/* + * Called iff UTRACE_EVENT(CLONE) flag is set. + * This notification call blocks the wake_up_new_task call on the child. + * So we must not quiesce here. tracehook_report_clone_complete will do + * a quiescence check momentarily. + */ +void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + /* + * We don't use the REPORT() macro here, because we need + * to clear utrace->cloning before finish_report(). + * After finish_report(), utrace can be a stale pointer + * in cases when report.action is still UTRACE_RESUME. + */ + start_report(utrace); + utrace->cloning = child; + + REPORT_CALLBACKS(, task, utrace, &report, + UTRACE_EVENT(CLONE), report_clone, + report.action, engine, task, clone_flags, child); + + utrace->cloning = NULL; + finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); + + /* + * For a vfork, we will go into an uninterruptible block waiting + * for the child. We need UTRACE_STOP to happen before this, not + * after. For CLONE_VFORK, utrace_finish_vfork() will be called. + */ + if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 1; + spin_unlock(&utrace->lock); + } +} + +/* + * We're called after utrace_report_clone() for a CLONE_VFORK. + * If UTRACE_STOP was left from the clone report, we stop here. + * After this, we'll enter the uninterruptible wait_for_completion() + * waiting for the child. + */ +void utrace_finish_vfork(struct task_struct *task) +{ + struct utrace *utrace = task_utrace_struct(task); + + if (utrace->vfork_stop) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 0; + spin_unlock(&utrace->lock); + utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ + } +} + +/* + * Called iff UTRACE_EVENT(JCTL) flag is set. + * + * Called with siglock held. + */ +void utrace_report_jctl(int notify, int what) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + spin_unlock_irq(&task->sighand->siglock); + + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), + report_jctl, what, notify); + + spin_lock_irq(&task->sighand->siglock); +} + +/* + * Called iff UTRACE_EVENT(EXIT) flag is set. + */ +void utrace_report_exit(long *exit_code) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + long orig_code = *exit_code; + + REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), + report_exit, orig_code, exit_code); + + if (report.action == UTRACE_STOP) + utrace_stop(task, utrace, report.resume_action); +} + +/* + * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. + * + * It is always possible that we are racing with utrace_release_task here. + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ +void utrace_report_death(struct task_struct *task, struct utrace *utrace, + bool group_dead, int signal) +{ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); + + /* + * We are presently considered "quiescent"--which is accurate + * inasmuch as we won't run any more user instructions ever again. + * But for utrace_control and utrace_set_events to be robust, they + * must be sure whether or not we will run any more callbacks. If + * a call comes in before we do, taking the lock here synchronizes + * us so we don't run any callbacks just disabled. Calls that come + * in while we're running the callbacks will see the exit.death + * flag and know that we are not yet fully quiescent for purposes + * of detach bookkeeping. + */ + spin_lock(&utrace->lock); + BUG_ON(utrace->death); + utrace->death = 1; + utrace->resume = UTRACE_RESUME; + splice_attaching(utrace); + spin_unlock(&utrace->lock); + + REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), + report_death, engine, task, group_dead, signal); + + spin_lock(&utrace->lock); + + /* + * After we unlock (possibly inside utrace_reap for callbacks) with + * this flag clear, competing utrace_control/utrace_set_events calls + * know that we've finished our callbacks and any detach bookkeeping. + */ + utrace->death = 0; + + if (utrace->reap) + /* + * utrace_release_task() was already called in parallel. + * We must complete its work now. + */ + utrace_reap(task, utrace); + else + utrace_reset(task, utrace); +} + +/* + * Finish the last reporting pass before returning to user mode. + */ +static void finish_resume_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + finish_report_reset(task, utrace, report); + + switch (report->action) { + case UTRACE_STOP: + utrace_stop(task, utrace, report->resume_action); + break; + + case UTRACE_INTERRUPT: + if (!signal_pending(task)) + set_tsk_thread_flag(task, TIF_SIGPENDING); + break; + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { + user_enable_block_step(task); + break; + } + + /* + * This means some callback is to blame for failing + * to check arch_has_block_step() itself. Warn and + * then fall through to treat it as SINGLESTEP. + */ + WARN_ON(1); + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) + user_enable_single_step(task); + else + /* + * This means some callback is to blame for failing + * to check arch_has_single_step() itself. Spew + * about it so the loser will fix his module. + */ + WARN_ON(1); + break; + + case UTRACE_REPORT: + case UTRACE_RESUME: + default: + user_disable_single_step(task); + break; + } +} + +/* + * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). + * We are close to user mode, and this is the place to report or stop. + * When we return, we're going to user mode or into the signals code. + */ +void utrace_resume(struct task_struct *task, struct pt_regs *regs) +{ + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + struct utrace_engine *engine; + + /* + * Some machines get here with interrupts disabled. The same arch + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ + local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal + * handler setup done but no report_signal following it. Clear + * the flag before we get to user so it doesn't confuse us later. + */ + if (unlikely(utrace->signal_handler)) { + spin_lock(&utrace->lock); + utrace->signal_handler = 0; + spin_unlock(&utrace->lock); + } + + /* + * Update our bookkeeping even if there are no callbacks made here. + */ + report.action = start_report(utrace); + + switch (report.action) { + case UTRACE_RESUME: + /* + * Anything we might have done was already handled by + * utrace_get_signal(), or this is an entirely spurious + * call. (The arch might use TIF_NOTIFY_RESUME for other + * purposes as well as calling us.) + */ + return; + case UTRACE_REPORT: + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) + break; + /* + * Do a simple reporting pass, with no specific + * callback after report_quiesce. + */ + report.action = UTRACE_RESUME; + list_for_each_entry(engine, &utrace->attached, entry) + start_callback(utrace, &report, engine, task, 0); + break; + default: + /* + * Even if this report was truly spurious, there is no need + * for utrace_reset() now. TIF_NOTIFY_RESUME was already + * cleared--it doesn't stay spuriously set. + */ + report.spurious = false; + break; + } + + /* + * Finish the report and either stop or get ready to resume. + * If utrace->resume was not UTRACE_REPORT, this applies its + * effect now (i.e. step or interrupt). + */ + finish_resume_report(task, utrace, &report); +} + +/* + * Return true if current has forced signal_pending(). + * + * This is called only when current->utrace_flags is nonzero, so we know + * that current->utrace must be set. It's not inlined in tracehook.h + * just so that struct utrace can stay opaque outside this file. + */ +bool utrace_interrupt_pending(void) +{ + return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; +} + +/* + * Take the siglock and push @info back on our queue. + * Returns with @task->sighand->siglock held. + */ +static void push_back_signal(struct task_struct *task, siginfo_t *info) + __acquires(task->sighand->siglock) +{ + struct sigqueue *q; + + if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ + spin_lock_irq(&task->sighand->siglock); + return; + } + + q = sigqueue_alloc(); + if (likely(q)) { + q->flags = 0; + copy_siginfo(&q->info, info); + } + + spin_lock_irq(&task->sighand->siglock); + + sigaddset(&task->pending.signal, info->si_signo); + if (likely(q)) + list_add(&q->list, &task->pending.list); + + set_tsk_thread_flag(task, TIF_SIGPENDING); +} + +/* + * This is the hook from the signals code, called with the siglock held. + * Here is the ideal place to stop. We also dequeue and intercept signals. + */ +int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + siginfo_t *info, struct k_sigaction *return_ka) + __releases(task->sighand->siglock) + __acquires(task->sighand->siglock) +{ + struct utrace *utrace; + struct k_sigaction *ka; + INIT_REPORT(report); + struct utrace_engine *engine; + const struct utrace_engine_ops *ops; + unsigned long event, want; + u32 ret; + int signr; + + utrace = task_utrace_struct(task); + if (utrace->resume < UTRACE_RESUME || + utrace->pending_attach || utrace->signal_handler) { + enum utrace_resume_action resume; + + /* + * We've been asked for an explicit report before we + * even check for pending signals. + */ + + spin_unlock_irq(&task->sighand->siglock); + + spin_lock(&utrace->lock); + + splice_attaching(utrace); + + report.result = utrace->signal_handler ? + UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; + utrace->signal_handler = 0; + + resume = utrace->resume; + utrace->resume = UTRACE_RESUME; + + spin_unlock(&utrace->lock); + + /* + * Make sure signal_pending() only returns true + * if there are real signals pending. + */ + if (signal_pending(task)) { + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); + } + + if (resume > UTRACE_REPORT) { + /* + * We only got here to process utrace->resume. + * Despite no callbacks, this report is not spurious. + */ + report.action = resume; + report.spurious = false; + finish_resume_report(task, utrace, &report); + return -1; + } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + /* + * We only got here to clear utrace->signal_handler. + */ + return -1; + } + + /* + * Do a reporting pass for no signal, just for EVENT(QUIESCE). + * The engine callbacks can fill in *info and *return_ka. + * We'll pass NULL for the @orig_ka argument to indicate + * that there was no original signal. + */ + event = 0; + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || + unlikely(task->signal->group_stop_count)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally + * or participate in group-stop. + */ + return 0; + } else { + /* + * Steal the next signal so we can let tracing engines + * examine it. From the signal number and sigaction, + * determine what normal delivery would do. If no + * engine perturbs it, we'll do that by returning the + * signal number after setting *return_ka. + */ + signr = dequeue_signal(task, &task->blocked, info); + if (signr == 0) + return signr; + BUG_ON(signr != info->si_signo); + + ka = &task->sighand->action[signr - 1]; + *return_ka = *ka; + + /* + * We are never allowed to interfere with SIGKILL. + * Just punt after filling in *return_ka for our caller. + */ + if (signr == SIGKILL) + return signr; + + if (ka->sa.sa_handler == SIG_IGN) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (ka->sa.sa_handler != SIG_DFL) { + event = UTRACE_EVENT(SIGNAL); + report.result = UTRACE_SIGNAL_DELIVER; + } else if (sig_kernel_coredump(signr)) { + event = UTRACE_EVENT(SIGNAL_CORE); + report.result = UTRACE_SIGNAL_CORE; + } else if (sig_kernel_ignore(signr)) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (signr == SIGSTOP) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_STOP; + } else if (sig_kernel_stop(signr)) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_TSTP; + } else { + event = UTRACE_EVENT(SIGNAL_TERM); + report.result = UTRACE_SIGNAL_TERM; + } + + /* + * Now that we know what event type this signal is, we + * can short-circuit if no engines care about those. + */ + if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) + return signr; + + /* + * We have some interested engines, so tell them about + * the signal and let them change its disposition. + */ + spin_unlock_irq(&task->sighand->siglock); + } + + /* + * This reporting pass chooses what signal disposition we'll act on. + */ + list_for_each_entry(engine, &utrace->attached, entry) { + /* + * See start_callback() comment about this barrier. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(), + * see start_callback() comments. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { + utrace->reporting = NULL; + continue; + } + + if (ops->report_signal) + ret = (*ops->report_signal)( + report.result | report.action, engine, task, + regs, info, ka, return_ka); + else + ret = (report.result | (*ops->report_quiesce)( + report.action, engine, task, event)); + + /* + * Avoid a tight loop reporting again and again if some + * engine is too stupid. + */ + switch (utrace_resume_action(ret)) { + default: + break; + case UTRACE_INTERRUPT: + case UTRACE_REPORT: + ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; + break; + } + + finish_callback(task, utrace, &report, engine, ret); + } + + /* + * We express the chosen action to the signals code in terms + * of a representative signal whose default action does it. + * Our caller uses our return value (signr) to decide what to + * do, but uses info->si_signo as the signal number to report. + */ + switch (utrace_signal_action(report.result)) { + case UTRACE_SIGNAL_TERM: + signr = SIGTERM; + break; + + case UTRACE_SIGNAL_CORE: + signr = SIGQUIT; + break; + + case UTRACE_SIGNAL_STOP: + signr = SIGSTOP; + break; + + case UTRACE_SIGNAL_TSTP: + signr = SIGTSTP; + break; + + case UTRACE_SIGNAL_DELIVER: + signr = info->si_signo; + + if (return_ka->sa.sa_handler == SIG_DFL) { + /* + * We'll do signr's normal default action. + * For ignore, we'll fall through below. + * For stop/death, break locks and returns it. + */ + if (likely(signr) && !sig_kernel_ignore(signr)) + break; + } else if (return_ka->sa.sa_handler != SIG_IGN && + likely(signr)) { + /* + * Complete the bookkeeping after the report. + * The handler will run. If an engine wanted to + * stop or step, then make sure we do another + * report after signal handler setup. + */ + if (report.action != UTRACE_RESUME) + report.action = UTRACE_INTERRUPT; + finish_report(task, utrace, &report, true); + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + /* + * We do the SA_ONESHOT work here since the + * normal path will only touch *return_ka now. + */ + if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { + return_ka->sa.sa_flags &= ~SA_ONESHOT; + if (likely(valid_signal(signr))) { + ka = &task->sighand->action[signr - 1]; + ka->sa.sa_handler = SIG_DFL; + } + } + + return signr; + } + + /* Fall through for an ignored signal. */ + + case UTRACE_SIGNAL_IGN: + case UTRACE_SIGNAL_REPORT: + default: + /* + * If the signal is being ignored, then we are on the way + * directly back to user mode. We can stop here, or step, + * as in utrace_resume(), above. After we've dealt with that, + * our caller will relock and come back through here. + */ + finish_resume_report(task, utrace, &report); + + if (unlikely(fatal_signal_pending(task))) { + /* + * The only reason we woke up now was because of a + * SIGKILL. Don't do normal dequeuing in case it + * might get a signal other than SIGKILL. That would + * perturb the death state so it might differ from + * what the debugger would have allowed to happen. + * Instead, pluck out just the SIGKILL to be sure + * we'll die immediately with nothing else different + * from the quiescent state the debugger wanted us in. + */ + sigset_t sigkill_only; + siginitsetinv(&sigkill_only, sigmask(SIGKILL)); + spin_lock_irq(&task->sighand->siglock); + signr = dequeue_signal(task, &sigkill_only, info); + BUG_ON(signr != SIGKILL); + *return_ka = task->sighand->action[SIGKILL - 1]; + return signr; + } + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { + push_back_signal(task, info); + spin_unlock_irq(&task->sighand->siglock); + } + + return -1; + } + + /* + * Complete the bookkeeping after the report. + * This sets utrace->resume if UTRACE_STOP was used. + */ + finish_report(task, utrace, &report, true); + + return_ka->sa.sa_handler = SIG_DFL; + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + if (sig_kernel_stop(signr)) + task->signal->flags |= SIGNAL_STOP_DEQUEUED; + + return signr; +} + +/* + * This gets called after a signal handler has been set up. + * We set a flag so the next report knows it happened. + * If we're already stepping, make sure we do a report_signal. + * If not, make sure we get into utrace_resume() where we can + * clear the signal_handler flag before resuming. + */ +void utrace_signal_handler(struct task_struct *task, int stepping) +{ + struct utrace *utrace = task_utrace_struct(task); + + spin_lock(&utrace->lock); + + utrace->signal_handler = 1; + if (utrace->resume > UTRACE_INTERRUPT) { + if (stepping) { + utrace->resume = UTRACE_INTERRUPT; + set_tsk_thread_flag(task, TIF_SIGPENDING); + } else if (utrace->resume == UTRACE_RESUME) { + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + } + } + + spin_unlock(&utrace->lock); +} + +/** + * utrace_prepare_examine - prepare to examine thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: temporary state, a &struct utrace_examiner pointer + * + * This call prepares to safely examine the thread @target using + * &struct user_regset calls, or direct access to thread-synchronous fields. + * + * When @target is current, this call is superfluous. When @target is + * another thread, it must be held stopped via %UTRACE_STOP by @engine. + * + * This call may block the caller until @target stays stopped, so it must + * be called only after the caller is sure @target is about to unschedule. + * This means a zero return from a utrace_control() call on @engine giving + * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to + * @engine that used %UTRACE_STOP in its return value. + * + * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was + * not used. If @target has started running again despite %UTRACE_STOP + * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. + * + * When this call returns zero, it's safe to use &struct user_regset + * calls and task_user_regset_view() on @target and to examine some of + * its fields directly. When the examination is complete, a + * utrace_finish_examine() call must follow to check whether it was + * completed safely. + */ +int utrace_prepare_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->exit_state)) + ret = -ESRCH; + else { + exam->state = target->state; + if (unlikely(exam->state == TASK_RUNNING)) + ret = -EAGAIN; + else + get_task_struct(target); + } + rcu_read_unlock(); + + if (likely(!ret)) { + exam->ncsw = wait_task_inactive(target, exam->state); + put_task_struct(target); + if (unlikely(!exam->ncsw)) + ret = -EAGAIN; + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_prepare_examine); + +/** + * utrace_finish_examine - complete an examination of thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: pointer passed to utrace_prepare_examine() call + * + * This call completes an examination on the thread @target begun by a + * paired utrace_prepare_examine() call with the same arguments that + * returned success (zero). + * + * When @target is current, this call is superfluous. When @target is + * another thread, this returns zero if @target has remained unscheduled + * since the paired utrace_prepare_examine() call returned zero. + * + * When this returns an error, any examination done since the paired + * utrace_prepare_examine() call is unreliable and the data extracted + * should be discarded. The error is -%EINVAL if @engine is not + * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. + */ +int utrace_finish_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->state != exam->state)) + ret = -EAGAIN; + else + get_task_struct(target); + rcu_read_unlock(); + + if (likely(!ret)) { + unsigned long ncsw = wait_task_inactive(target, exam->state); + if (unlikely(ncsw != exam->ncsw)) + ret = -EAGAIN; + put_task_struct(target); + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_finish_examine); + +/* + * This is declared in linux/regset.h and defined in machine-dependent + * code. We put the export here to ensure no machine forgets it. + */ +EXPORT_SYMBOL_GPL(task_user_regset_view); + +/* + * Called with rcu_read_lock() held. + */ +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) +{ + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} From andi at firstfloor.org Tue Nov 24 20:32:27 2009 From: andi at firstfloor.org (Andi Kleen) Date: Tue, 24 Nov 2009 21:32:27 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124200220.GA5828@redhat.com> (Oleg Nesterov's message of "Tue, 24 Nov 2009 21:02:20 +0100") References: <20091124200220.GA5828@redhat.com> Message-ID: <87my2bwtno.fsf@basil.nowhere.org> Oleg Nesterov writes: > From: Roland McGrath > > This adds the utrace facility, a new modular interface in the kernel > for implementing user thread tracing and debugging. This fits on top > of the tracehook_* layer, so the new code is well-isolated. Could we just drop the tracehook layer if this finally merged and call the low level functions directly? It might have been reasonably early on when it was still out of tree, but longer term when it's integrated having strange opaque hooks like that just makes the coder harder to read and maintain. -Andi -- ak at linux.intel.com -- Speaking for myself only. From oleg at redhat.com Tue Nov 24 20:41:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 21:41:52 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <87my2bwtno.fsf@basil.nowhere.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> Message-ID: <20091124204152.GA9131@redhat.com> On 11/24, Andi Kleen wrote: > > Oleg Nesterov writes: > > > From: Roland McGrath > > > > This adds the utrace facility, a new modular interface in the kernel > > for implementing user thread tracing and debugging. This fits on top > > of the tracehook_* layer, so the new code is well-isolated. > > Could we just drop the tracehook layer if this finally merged > and call the low level functions directly? Not sure I understand. Tracehooks are trivial inline wrappers on top utrace calls, > It might have been reasonably early on when it was still out of tree, > but longer term when it's integrated having strange opaque hooks > like that just makes the coder harder to read and maintain. Well, I don't think the code will be better if we remove tracehooks. For example. tracehook_report_syscall_entry() has a lot of callers in arch/, each callsite should be changed to do if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && utrace_report_syscall_entry(regs)) ret = -1; // this depends on machine instead of simply calling tracehook_report_syscall_entry(). What is the point? But again, perhaps I misunderstood you. Oleg. From andi at firstfloor.org Tue Nov 24 21:26:19 2009 From: andi at firstfloor.org (Andi Kleen) Date: Tue, 24 Nov 2009 22:26:19 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124204152.GA9131@redhat.com> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> Message-ID: <20091124212619.GB29096@one.firstfloor.org> On Tue, Nov 24, 2009 at 09:41:52PM +0100, Oleg Nesterov wrote: > On 11/24, Andi Kleen wrote: > > > > Oleg Nesterov writes: > > > > > From: Roland McGrath > > > > > > This adds the utrace facility, a new modular interface in the kernel > > > for implementing user thread tracing and debugging. This fits on top > > > of the tracehook_* layer, so the new code is well-isolated. > > > > Could we just drop the tracehook layer if this finally merged > > and call the low level functions directly? > > Not sure I understand. Tracehooks are trivial inline wrappers on > top utrace calls, Yes that's the problem -- they are unnecessary obfuscation when you can just call directly. > > > It might have been reasonably early on when it was still out of tree, > > but longer term when it's integrated having strange opaque hooks > > like that just makes the coder harder to read and maintain. > > Well, I don't think the code will be better if we remove tracehooks. > > For example. tracehook_report_syscall_entry() has a lot of callers > in arch/, each callsite should be changed to do > > if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && > utrace_report_syscall_entry(regs)) > ret = -1; // this depends on machine > > instead of simply calling tracehook_report_syscall_entry(). That should be in the utrace code? I don't have a problem with having common code somewhere, just not a whole layer whose only purpose seems to be obfuscation. > What is the point? Less code obfuscation. When it's a utrace call, call it a utrace call, not something else. -Andi -- ak at linux.intel.com -- Speaking for myself only. From fche at redhat.com Tue Nov 24 21:31:05 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 24 Nov 2009 16:31:05 -0500 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124212619.GB29096@one.firstfloor.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> Message-ID: <20091124213105.GG29296@redhat.com> Hi - On Tue, Nov 24, 2009 at 10:26:19PM +0100, Andi Kleen wrote: > [...] > > For example. tracehook_report_syscall_entry() has a lot of callers > > in arch/, each callsite should be changed to do > > > > if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && > > utrace_report_syscall_entry(regs)) > > ret = -1; // this depends on machine > > > > instead of simply calling tracehook_report_syscall_entry(). > > That should be in the utrace code? > > I don't have a problem with having common code somewhere, > just not a whole layer whose only purpose seems to be obfuscation. One man's obfuscation is another man's abstraction. Would you be satisfied if "tracehook_" was renamed "utracehook_"? - FChE From andi at firstfloor.org Tue Nov 24 21:34:22 2009 From: andi at firstfloor.org (Andi Kleen) Date: Tue, 24 Nov 2009 22:34:22 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124213105.GG29296@redhat.com> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> <20091124213105.GG29296@redhat.com> Message-ID: <20091124213422.GC29096@one.firstfloor.org> > One man's obfuscation is another man's abstraction. > Would you be satisfied if "tracehook_" was renamed "utracehook_"? I would prefer if there were no thin inlines, and the functions should have a name clearly indicating for which subsystem they are for. -Andi -- ak at linux.intel.com -- Speaking for myself only. From oleg at redhat.com Tue Nov 24 21:44:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 24 Nov 2009 22:44:50 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124212619.GB29096@one.firstfloor.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> Message-ID: <20091124214450.GA12828@redhat.com> (restore cc's) On 11/24, Andi Kleen wrote: > > On Tue, Nov 24, 2009 at 09:41:52PM +0100, Oleg Nesterov wrote: > > On 11/24, Andi Kleen wrote: > > > > > > Oleg Nesterov writes: > > > > > > > From: Roland McGrath > > > > > > > > This adds the utrace facility, a new modular interface in the kernel > > > > for implementing user thread tracing and debugging. This fits on top > > > > of the tracehook_* layer, so the new code is well-isolated. > > > > > > Could we just drop the tracehook layer if this finally merged > > > and call the low level functions directly? > > > > Not sure I understand. Tracehooks are trivial inline wrappers on > > top utrace calls, > > Yes that's the problem -- they are unnecessary obfuscation > when you can just call directly. This is subjective, but personally I disagree. Contrary, imho it is good that tracehook hides the (simple) details. I do not understand why the reader of, say, do_fork() should see the contents of tracehook_report_clone_complete(). This will complicate the understanding. Those people who want to understand/change fork() do not care about utrace/ptrace usually. And please note that it is much, much easier to change this code when it lives in tracehooks.h instead of sched.c/signal.c/etc. > > What is the point? > > Less code obfuscation. > > When it's a utrace call, call it a utrace call, not something else. Why do you think this is obfuscation? Well, we can rename these helpers, s/tracehook_/utrace_/, but I don't see how this can make the code more readable. Oleg. From ananth at in.ibm.com Wed Nov 25 04:33:50 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Wed, 25 Nov 2009 10:03:50 +0530 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091124152657.GA4352@redhat.com> References: <20091122221224.GA8674@redhat.com> <20091124094027.GB21843@in.ibm.com> <20091124152657.GA4352@redhat.com> Message-ID: <20091125043350.GA2660@in.ibm.com> On Tue, Nov 24, 2009 at 04:26:57PM +0100, Oleg Nesterov wrote: > On 11/24, Ananth N Mavinakayanahalli wrote: > > > > ... > > step-jump-cont: step-jump-cont.c:140: pokeuser: Assertion `l == 0' > > failed. > > /bin/sh: line 4: 9070 Aborted ${dir}$tst > > FAIL: step-jump-cont > > > > errno 14 (Bad address) > > syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location > > ()) == 38' failed. > > unexpected child status 67f > > FAIL: syscall-reset > > Ananth, thanks a lot. Hi Oleg, > Could you please verify that unpatched kernel passes these tests? There is one additional failure [1] on an unpatched kernel -- so the ptrace/utrace is better :-) > Also, could you run "make xcheck" to do more testing? The output I provided was for a 'make check xcheck' run. Ananth [1] step-jump-cont: step-jump-cont.c:140: pokeuser: Assertion `l == 0' failed. /bin/sh: line 4: 16407 Aborted ${dir}$tst FAIL: step-jump-cont ... errno 14 (Bad address) syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. unexpected child status 67f FAIL: syscall-reset ... FAIL: detach-stopped ... ======================================== 3 of 27 tests failed (11 tests were not run) Please report to utrace-devel at redhat.com ======================================== make[3]: *** [check-TESTS] Error 1 make[3]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make[2]: *** [check-am] Error 2 make[2]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make[1]: *** [check] Error 2 make[1]: Leaving directory `/home/ananth/utrace/ptrace-tests/tests' make: *** [check-recursive] Error 1 From ananth at in.ibm.com Wed Nov 25 08:03:42 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Wed, 25 Nov 2009 13:33:42 +0530 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091124200127.GA5751@redhat.com> References: <20091124200127.GA5751@redhat.com> Message-ID: <20091125080342.GD2660@in.ibm.com> On Tue, Nov 24, 2009 at 09:01:27PM +0100, Oleg Nesterov wrote: > Hello. > > This is the new iteration of Roland's utrace patch, this time > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. > > 1-7 are already in -mm tree, I am sending them to simplify the > review. > > 8-12 don not change the behaviour, simple preparations. > > 13-14 add utrace-ptrace and utrace Oleg, I ran the ptrace-tests testsuite [1] on powerpc on the vanilla ptrace and then with ptrace/utrace. The results for ptrace/utrace look better :-) All tests are 'make check xcheck'. Ananth [1] cvs?-d?:pserver:anoncvs:anoncvs at sources.redhat.com:/cvs/systemtap?co?ptrace-tests --------- Vanilla ptrace: PASS: ptrace-on-job-control-stopped PASS: attach-wait-on-stopped PASS: detach-can-signal PASS: attach-into-signal PASS: attach-sigcont-wait PASS: sa-resethand-on-cont-signal PASS: ptrace_cont-defeats-sigblock PASS: ptrace-cont-sigstop-detach PASS: ptrace_event_clone PASS: tif-syscall-trace-after-detach PASS: event-exit-proc-maps PASS: event-exit-proc-environ SKIP: x86_64-ia32-gs SKIP: x86_64-gsbase PASS: powerpc-altivec PASS: peekpokeusr PASS: watchpoint PASS: block-step PASS: step-jump-cont SKIP: step-jump-cont-strict PASS: ppc-dabr-race PASS: signal-loss PASS: step-into-handler SKIP: user-area-access PASS: user-regs-peekpoke PASS: erestartsys SKIP: erestart-debugger SKIP: step-to-breakpoint errno 14 (Bad address) syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. unexpected child status 67f FAIL: syscall-reset PASS: reparent-zombie PASS: step-simple SKIP: step-through-sigret PASS: stop-attach-then-wait FAIL: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace PASS: o_tracevfork PASS: o_tracevforkdone PASS: detach-parting-signal PASS: detach-sigkill-race PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping FAIL: stopped-attach-transparency SKIP: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit SKIP: syscall-from-clone step-from-clone: step-from-clone.c:195: main: Assertion `(status >> 8) == 5' failed. step-from-clone: step-from-clone.c:119: handler_fail: Assertion `0' failed. /bin/sh: line 5: 19825 Aborted ${dir}$tst FAIL: step-from-clone step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. /bin/sh: line 5: 19832 Aborted ${dir}$tst FAIL: step-fork ======================================== 5 of 41 tests failed (10 tests were not run) Please report to utrace-devel at redhat.com ======================================== make[3]: *** [check-TESTS] Error 1 make[3]: Leaving directory `/home/ananth/ptrace-tests/tests' make[2]: *** [check-am] Error 2 make[2]: Leaving directory `/home/ananth/ptrace-tests/tests' make[1]: *** [check] Error 2 make[1]: Leaving directory `/home/ananth/ptrace-tests/tests' make: *** [check-recursive] Error 1 --------- ptrace over utrace: PASS: ptrace-on-job-control-stopped PASS: attach-wait-on-stopped PASS: detach-can-signal PASS: attach-into-signal PASS: attach-sigcont-wait PASS: sa-resethand-on-cont-signal PASS: ptrace_cont-defeats-sigblock PASS: ptrace-cont-sigstop-detach PASS: ptrace_event_clone PASS: tif-syscall-trace-after-detach PASS: event-exit-proc-maps PASS: event-exit-proc-environ SKIP: x86_64-ia32-gs SKIP: x86_64-gsbase PASS: powerpc-altivec PASS: peekpokeusr PASS: watchpoint PASS: block-step PASS: step-jump-cont SKIP: step-jump-cont-strict PASS: ppc-dabr-race PASS: signal-loss PASS: step-into-handler SKIP: user-area-access PASS: user-regs-peekpoke PASS: erestartsys SKIP: erestart-debugger SKIP: step-to-breakpoint errno 14 (Bad address) syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. unexpected child status 67f FAIL: syscall-reset PASS: reparent-zombie PASS: step-simple SKIP: step-through-sigret PASS: stop-attach-then-wait PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace PASS: o_tracevfork PASS: o_tracevforkdone PASS: detach-parting-signal PASS: detach-sigkill-race PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping PASS: stopped-attach-transparency SKIP: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit SKIP: syscall-from-clone SKIP: step-from-clone step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. /bin/sh: line 5: 24803 Aborted ${dir}$tst FAIL: step-fork ======================================== 2 of 40 tests failed (11 tests were not run) Please report to utrace-devel at redhat.com ======================================== make[3]: *** [check-TESTS] Error 1 make[3]: Leaving directory `/home/ananth/ptrace-tests/tests' make[2]: *** [check-am] Error 2 make[2]: Leaving directory `/home/ananth/ptrace-tests/tests' make[1]: *** [check] Error 2 make[1]: Leaving directory `/home/ananth/ptrace-tests/tests' make: *** [check-recursive] Error 1 From caiqian at redhat.com Wed Nov 25 08:41:04 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Wed, 25 Nov 2009 03:41:04 -0500 (EST) Subject: GDB Testsuite Results with CONFIG_UTRACE i686 In-Reply-To: <452574467.573711259138291401.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hello! Those are the test results on i686 F12 hosts with and without CONFIG_UTRACE. Interesting thing is that the results on quite different on two Intel hosts. gdb.sum is from without CONFIG_UTRACE. Thanks! CAI Qian ProLiant DL360 G4p (Intel) diff -u gdb.sum gdb-utrace.sum --- gdb.sum 2009-11-25 16:11:35.000000000 +0800 +++ gdb-utrace.sum 2009-11-25 16:10:45.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Tue Nov 24 23:58:53 2009 +Test Run By root on Tue Nov 24 23:26:57 2009 Native configuration is i686-pc-linux-gnu === gdb tests === @@ -748,8 +748,8 @@ PASS: gdb.base/bigcore.exp: tbreak 269 PASS: gdb.base/bigcore.exp: continue PASS: gdb.base/bigcore.exp: next -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap PASS: gdb.base/bigcore.exp: save heap size PASS: gdb.base/bigcore.exp: grab pid PASS: gdb.base/bigcore.exp: signal SIGABRT @@ -3718,7 +3718,7 @@ PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running ./gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child -PASS: gdb.base/follow-child.exp: break +FAIL: gdb.base/follow-child.exp: break Running ./gdb.base/foll-vfork.exp ... PASS: gdb.base/foll-vfork.exp: set verbose PASS: gdb.base/foll-vfork.exp: insert first vfork catchpoint @@ -13850,18 +13850,18 @@ PASS: gdb.pie/break.exp: breakpoint at start of multi line if conditional PASS: gdb.pie/break.exp: breakpoint at start of multi line while conditional PASS: gdb.pie/break.exp: breakpoint info -PASS: gdb.pie/break.exp: run until function breakpoint -PASS: gdb.pie/break.exp: run until breakpoint set at a line number -PASS: gdb.pie/break.exp: run until file:function(6) breakpoint -PASS: gdb.pie/break.exp: run until file:function(5) breakpoint -PASS: gdb.pie/break.exp: run until file:function(4) breakpoint -PASS: gdb.pie/break.exp: run until file:function(3) breakpoint -PASS: gdb.pie/break.exp: run until file:function(2) breakpoint -PASS: gdb.pie/break.exp: run until file:function(1) breakpoint -PASS: gdb.pie/break.exp: run until quoted breakpoint -PASS: gdb.pie/break.exp: run until file:linenum breakpoint +FAIL: gdb.pie/break.exp: run until function breakpoint +FAIL: gdb.pie/break.exp: run until breakpoint set at a line number +FAIL: gdb.pie/break.exp: run until file:function(6) breakpoint +FAIL: gdb.pie/break.exp: run until file:function(5) breakpoint +FAIL: gdb.pie/break.exp: run until file:function(4) breakpoint +FAIL: gdb.pie/break.exp: run until file:function(3) breakpoint +FAIL: gdb.pie/break.exp: run until file:function(2) breakpoint +FAIL: gdb.pie/break.exp: run until file:function(1) breakpoint +FAIL: gdb.pie/break.exp: run until quoted breakpoint +FAIL: gdb.pie/break.exp: run until file:linenum breakpoint (the program is no longer running) PASS: gdb.pie/break.exp: breakpoint offset +1 -PASS: gdb.pie/break.exp: step onto breakpoint +FAIL: gdb.pie/break.exp: step onto breakpoint (the program is no longer running) PASS: gdb.pie/break.exp: Temporary breakpoint function PASS: gdb.pie/break.exp: Temporary breakpoint function in file PASS: gdb.pie/break.exp: Temporary breakpoint line number #1 @@ -15465,8 +15465,8 @@ === gdb Summary === -# of expected passes 14562 -# of unexpected failures 115 +# of expected passes 14550 +# of unexpected failures 127 # of expected failures 40 # of untested testcases 18 # of unsupported tests 7 HP Workstation XW4200 (Intel) $ diff -u gdb.sum gdb-utrace.sum --- gdb.sum 2009-11-25 16:17:09.000000000 +0800 +++ gdb-utrace.sum 2009-11-25 16:16:51.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 01:02:04 2009 +Test Run By root on Wed Nov 25 00:26:48 2009 Native configuration is i686-pc-linux-gnu === gdb tests === @@ -748,8 +748,8 @@ PASS: gdb.base/bigcore.exp: tbreak 269 PASS: gdb.base/bigcore.exp: continue PASS: gdb.base/bigcore.exp: next -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap PASS: gdb.base/bigcore.exp: save heap size PASS: gdb.base/bigcore.exp: grab pid PASS: gdb.base/bigcore.exp: signal SIGABRT @@ -3718,7 +3718,7 @@ PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running ./gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child -FAIL: gdb.base/follow-child.exp: break +PASS: gdb.base/follow-child.exp: break Running ./gdb.base/foll-vfork.exp ... PASS: gdb.base/foll-vfork.exp: set verbose PASS: gdb.base/foll-vfork.exp: insert first vfork catchpoint @@ -13850,18 +13850,18 @@ PASS: gdb.pie/break.exp: breakpoint at start of multi line if conditional PASS: gdb.pie/break.exp: breakpoint at start of multi line while conditional PASS: gdb.pie/break.exp: breakpoint info -FAIL: gdb.pie/break.exp: run until function breakpoint -FAIL: gdb.pie/break.exp: run until breakpoint set at a line number -FAIL: gdb.pie/break.exp: run until file:function(6) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(5) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(4) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(3) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(2) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(1) breakpoint -FAIL: gdb.pie/break.exp: run until quoted breakpoint -FAIL: gdb.pie/break.exp: run until file:linenum breakpoint (the program is no longer running) +PASS: gdb.pie/break.exp: run until function breakpoint +PASS: gdb.pie/break.exp: run until breakpoint set at a line number +PASS: gdb.pie/break.exp: run until file:function(6) breakpoint +PASS: gdb.pie/break.exp: run until file:function(5) breakpoint +PASS: gdb.pie/break.exp: run until file:function(4) breakpoint +PASS: gdb.pie/break.exp: run until file:function(3) breakpoint +PASS: gdb.pie/break.exp: run until file:function(2) breakpoint +PASS: gdb.pie/break.exp: run until file:function(1) breakpoint +PASS: gdb.pie/break.exp: run until quoted breakpoint +PASS: gdb.pie/break.exp: run until file:linenum breakpoint PASS: gdb.pie/break.exp: breakpoint offset +1 -FAIL: gdb.pie/break.exp: step onto breakpoint (the program is no longer running) +PASS: gdb.pie/break.exp: step onto breakpoint PASS: gdb.pie/break.exp: Temporary breakpoint function PASS: gdb.pie/break.exp: Temporary breakpoint function in file PASS: gdb.pie/break.exp: Temporary breakpoint line number #1 @@ -14588,8 +14588,8 @@ PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt PASS: gdb.threads/attachstop-mt.exp: continue (attach4 continue) -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping Running ./gdb.threads/attach-stopped.exp ... PASS: gdb.threads/attach-stopped.exp: nonthreaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: nonthreaded: attach1 to stopped, after setting file @@ -15251,7 +15251,7 @@ PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] PASS: gdb.threads/watchthreads.exp: watch args[1] -PASS: gdb.threads/watchthreads.exp: disable 2 +PASS: gdb.threads/watchthreads.exp: disable 3 PASS: gdb.threads/watchthreads.exp: threaded watch loop PASS: gdb.threads/watchthreads.exp: first watchpoint on args[0] hit PASS: gdb.threads/watchthreads.exp: first watchpoint on args[1] hit @@ -15465,8 +15465,8 @@ === gdb Summary === -# of expected passes 14549 -# of unexpected failures 127 +# of expected passes 14559 +# of unexpected failures 117 # of expected failures 40 # of untested testcases 18 # of unsupported tests 7 ProLiant DL585 G2 (AMD) $ diff -u gdb.sum gdb-utrace.sum --- gdb.sum 2009-11-25 16:13:42.000000000 +0800 +++ gdb-utrace.sum 2009-11-25 16:13:09.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 02:31:59 2009 +Test Run By root on Wed Nov 25 01:55:40 2009 Native configuration is i686-pc-linux-gnu === gdb tests === @@ -748,8 +748,8 @@ PASS: gdb.base/bigcore.exp: tbreak 269 PASS: gdb.base/bigcore.exp: continue PASS: gdb.base/bigcore.exp: next -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap PASS: gdb.base/bigcore.exp: save heap size PASS: gdb.base/bigcore.exp: grab pid PASS: gdb.base/bigcore.exp: signal SIGABRT @@ -12831,7 +12831,7 @@ PASS: gdb.mi/mi-nsmoribund.exp: resume all, thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: hit thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: thread state: all running except the breakpoint thread -FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop +PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally Running ./gdb.mi/mi-nsthrexec.exp ... PASS: gdb.mi/mi-nsthrexec.exp: successfully compiled posix threads test case PASS: gdb.mi/mi-nsthrexec.exp: breakpoint at main @@ -14583,13 +14583,13 @@ PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped, after setting file PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach3 to stopped bt -FAIL: gdb.threads/attachstop-mt.exp: attach3, exit leaves process stopped +PASS: gdb.threads/attachstop-mt.exp: attach3, exit leaves process stopped PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped, after setting file PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt PASS: gdb.threads/attachstop-mt.exp: continue (attach4 continue) -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping Running ./gdb.threads/attach-stopped.exp ... PASS: gdb.threads/attach-stopped.exp: nonthreaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: nonthreaded: attach1 to stopped, after setting file @@ -15246,7 +15246,7 @@ PASS: gdb.threads/watchthreads2.exp: all threads started PASS: gdb.threads/watchthreads2.exp: watch x PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 -PASS: gdb.threads/watchthreads2.exp: all threads incremented x +KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) Running ./gdb.threads/watchthreads.exp ... PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] @@ -15465,7 +15465,7 @@ === gdb Summary === -# of expected passes 14559 +# of expected passes 14558 # of unexpected failures 118 # of expected failures 40 # of untested testcases 18 From andi at firstfloor.org Wed Nov 25 08:46:17 2009 From: andi at firstfloor.org (Andi Kleen) Date: Wed, 25 Nov 2009 09:46:17 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124214450.GA12828@redhat.com> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> <20091124214450.GA12828@redhat.com> Message-ID: <20091125084617.GD29096@one.firstfloor.org> > This is subjective, but personally I disagree. Contrary, imho it > is good that tracehook hides the (simple) details. I do not understand > why the reader of, say, do_fork() should see the contents of > tracehook_report_clone_complete(). This will complicate the understanding. Someone who has to debug or review fork needs to know what's going on. Yes they can find out by going through inlines, but that just costs more time and distracts from the actual problem. > Those people who want to understand/change fork() do not care about > utrace/ptrace usually. > > And please note that it is much, much easier to change this code > when it lives in tracehooks.h instead of sched.c/signal.c/etc. The problem is that when you have to trace this code when something goes wrong the extra layer just holds you up. For debugging usually abstraction is a bad idea. My experience is also that in general such extra "abstraction layers" are frowned upon in Linux kernel code style. For example when new vendor drivers are submitted for hardware like NICs etc, they frequently tend to have all kinds of "abstraction layers". Typically the first step to linuxify them is to get rid of those. This makes the code more readable, shorter, better to debug and read. Another classic example is: lock_foo() is frowned upon (Linus tends to always complain about that), rather prefer spin_lock(&foo_lock) or mutex_lock(&foo_lock) that makes it clear what's going on. I don't see why this should be any different for utrace. > > Less code obfuscation. > > > > When it's a utrace call, call it a utrace call, not something else. > > Why do you think this is obfuscation? Well, we can rename these > helpers, s/tracehook_/utrace_/, but I don't see how this can make > the code more readable. Because the inlines do not add anything to functionality and actually hide what the code does, that is obfuscation. For you it might be obvious because you've been hacking that code for quite some time, but for someone who is not in your position that's different. -Andi -- ak at linux.intel.com -- Speaking for myself only. From jan.kratochvil at redhat.com Wed Nov 25 08:57:01 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 25 Nov 2009 09:57:01 +0100 Subject: GDB Testsuite Results with CONFIG_UTRACE i686 In-Reply-To: <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <452574467.573711259138291401.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091125085701.GA25895@host0.dyn.jankratochvil.net> Hi, the gdb.pie/break.exp change would be worth checking more but this is based on the old PIE patch with various known problems and for RHEL-6 there will be a different/new PIE patch implementation. Also the gdb.base/bigcore.exp and gdb.base/follow-child.exp changes would be worth checking if the change is stable across multiple runs of the specific testcase. You can also check gdb.log differences, sometimes it is apparent the change is OK. Otherwise if the change is stable across multiple runs and it is not obvious to you why it did change as you already have the machine ready could you please provide the hostname/password/etc. there? Thanks, Jan From ananth at in.ibm.com Wed Nov 25 08:59:11 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Wed, 25 Nov 2009 14:29:11 +0530 Subject: GDB Testsuite Results on POWERPC In-Reply-To: <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <452574467.573711259138291401.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091125085911.GE2660@in.ibm.com> Hi, Here is the summary of GDB testsuite runs on a vanilla kernel and one with ptrace over utrace on a powerpc machine: Vanilla ptrace: === gdb Summary === # of expected passes 13970 # of unexpected failures 52 # of unexpected successes 2 # of expected failures 40 # of untested testcases 8 # of unresolved testcases 125 # of unsupported tests 55 runtest completed at Wed Nov 25 14:02:52 2009 Ptrace over utrace: === gdb Summary === # of expected passes 13970 # of unexpected failures 52 # of unexpected successes 2 # of expected failures 40 # of untested testcases 8 # of unresolved testcases 125 # of unsupported tests 55 runtest completed at Wed Nov 25 14:21:52 2009 Essentially, there is *no* change in any of the numbers with and without ptrace over utrace. Regards, Ananth From jan.kratochvil at redhat.com Wed Nov 25 09:02:22 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 25 Nov 2009 10:02:22 +0100 Subject: GDB Testsuite Results on POWERPC In-Reply-To: <20091125085911.GE2660@in.ibm.com> References: <452574467.573711259138291401.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091125085911.GE2660@in.ibm.com> Message-ID: <20091125090222.GA26203@host0.dyn.jankratochvil.net> On Wed, 25 Nov 2009 09:59:11 +0100, Ananth N Mavinakayanahalli wrote: > Essentially, there is *no* change in any of the numbers with and without > ptrace over utrace. While it is probable so please rather check diff of the *.sum files as some of the results are fuzzy and - in a rare possibility - two results changing FAIL->PASS and PASS->FAIL will not show in this summary. Thanks, Jan From ananth at in.ibm.com Wed Nov 25 10:03:18 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Wed, 25 Nov 2009 15:33:18 +0530 Subject: GDB Testsuite Results on POWERPC In-Reply-To: <20091125090222.GA26203@host0.dyn.jankratochvil.net> References: <452574467.573711259138291401.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <83090751.573811259138464325.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091125085911.GE2660@in.ibm.com> <20091125090222.GA26203@host0.dyn.jankratochvil.net> Message-ID: <20091125100318.GF2660@in.ibm.com> On Wed, Nov 25, 2009 at 10:02:22AM +0100, Jan Kratochvil wrote: > On Wed, 25 Nov 2009 09:59:11 +0100, Ananth N Mavinakayanahalli wrote: > > Essentially, there is *no* change in any of the numbers with and without > > ptrace over utrace. > > While it is probable so please rather check diff of the *.sum files as some of > the results are fuzzy and - in a rare possibility - two results changing > FAIL->PASS and PASS->FAIL will not show in this summary. Jan, The diff is as below: --- vanilla-gdb.sum 2009-11-25 15:28:47.885380052 +0530 +++ pt-gdb.sum 2009-11-25 15:20:42.838419047 +0530 @@ -1,4 +1,4 @@ -Test Run By ananth on Wed Nov 25 15:22:46 2009 +Test Run By ananth on Wed Nov 25 14:17:54 2009 Native configuration is powerpc64-unknown-linux-gnu === gdb tests === @@ -7602,7 +7602,7 @@ PASS: gdb.base/sigbpt.exp: stepi bp at s PASS: gdb.base/sigbpt.exp: stepi bp at segv; continue to keeper PASS: gdb.base/sigbpt.exp: stepi bp at segv; nopass SIGSEGV PASS: gdb.base/sigbpt.exp: stepi bp at segv; set breakpoint 0 of 1 -PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler +PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler (at breakpoint) PASS: gdb.base/sigbpt.exp: stepi bp at segv; clear breakpoint 0 of 1 PASS: gdb.base/sigbpt.exp: rerun to main PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; pass SIGSEGV @@ -7610,7 +7610,7 @@ PASS: gdb.base/sigbpt.exp: stepi bp befo PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; nopass SIGSEGV PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; set breakpoint 0 of 2 PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; set breakpoint 1 of 2 -PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; stepi out of handler +PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; stepi out of handler (at breakpoint) PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; clear breakpoint 0 of 2 PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; clear breakpoint 1 of 2 PASS: gdb.base/sigbpt.exp: rerun to main Ananth From caiqian at redhat.com Wed Nov 25 10:23:55 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Wed, 25 Nov 2009 05:23:55 -0500 (EST) Subject: GDB Testsuite Results with CONFIG_UTRACE i686 In-Reply-To: <710806079.577081259144344563.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1444001049.577351259144635614.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> ----- "Jan Kratochvil" ??? > Hi, > > the gdb.pie/break.exp change would be worth checking more but this is > based on the old PIE patch with various known problems and for RHEL-6 there > will be a different/new PIE patch implementation. > > Also the gdb.base/bigcore.exp and gdb.base/follow-child.exp changes > would be worth checking if the change is stable across multiple runs of the > specific testcase. > > You can also check gdb.log differences, sometimes it is apparent the > change is OK. Otherwise if the change is stable across multiple runs and it is > not obvious to you why it did change as you already have the machine ready > could you please provide the hostname/password/etc. there? All the gdb.log and gdb.sum can be found here. http://people.redhat.com/qcai/kratochvil/ The machines have been returned after the tests done. I will ping you when I have them ready. Thanks! CAI Qian From oleg at redhat.com Wed Nov 25 14:55:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 25 Nov 2009 15:55:56 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091125084617.GD29096@one.firstfloor.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> <20091124214450.GA12828@redhat.com> <20091125084617.GD29096@one.firstfloor.org> Message-ID: <20091125145556.GA5394@redhat.com> On 11/25, Andi Kleen wrote: > > > This is subjective, but personally I disagree. Contrary, imho it > > is good that tracehook hides the (simple) details. I do not understand > > why the reader of, say, do_fork() should see the contents of > > tracehook_report_clone_complete(). This will complicate the understanding. > > Someone who has to debug or review fork needs to know what's going on. > > Yes they can find out by going through inlines, but that > just costs more time and distracts from the actual problem. > > > Those people who want to understand/change fork() do not care about > > utrace/ptrace usually. > > > > And please note that it is much, much easier to change this code > > when it lives in tracehooks.h instead of sched.c/signal.c/etc. > > The problem is that when you have to trace this code when something > goes wrong the extra layer just holds you up. For debugging usually > abstraction is a bad idea. > > My experience is also that in general such extra "abstraction layers" > are frowned upon in Linux kernel code style. For example when new > vendor drivers are submitted for hardware like NICs etc, > they frequently tend to have all kinds of "abstraction layers". > Typically the first step to linuxify them is to get rid of those. > > This makes the code more readable, shorter, better to debug and read. OK, let's try to remove these helpers. Let's take a random one, tracehook_report_exec(). The current code in search_binary_handler: if (retval >= 0) { if (depth == 0) tracehook_report_exec(fmt, bprm, regs); put_binfmt(fmt); allow_write_access(bprm->file); if (bprm->file) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; proc_exec_connector(current); return retval; } becomes: if (retval >= 0) { if (depth == 0) { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) utrace_report_exec(fmt, bprm, regs); if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && unlikely(task_ptrace(current) & PT_PTRACED)) send_sig(SIGTRAP, current, 0); } put_binfmt(fmt); allow_write_access(bprm->file); if (bprm->file) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; proc_exec_connector(current); return retval; } Cleanup? I don't think so. OK, when CONFIG_UTRACE goes away, we can kill a lot of old code, and in tracehooks too. So the code above becomes if (retval >= 0) { if (depth == 0) { if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) utrace_report_exec(fmt, bprm, regs); } put_binfmt(fmt); allow_write_access(bprm->file); if (bprm->file) fput(bprm->file); bprm->file = NULL; current->did_exec = 1; proc_exec_connector(current); return retval; } Much better. But in this case please note that most of tracehooks just do: if (unlikely(task_utrace_flags(current) & SOME_EVENT)) utrace_report_some_event(); I really don't understand why we shouldn't have (trivial!) helpers for this. (As for naming - personally I do not care at all ;) You can argue that some tracehooks (say, exit_notify() path) can be simplified. Yes, we are going to do this. And again, when CONFIG_UTRACE goes away, we can just kill some tracehooks. Say, most of them in do_fork() path. > Because the inlines do not add anything to functionality and actually > hide what the code does, that is obfuscation. This applies to any function. As for tracehooks, they mostly hide "if (task_utrace_flags(current))" check and nothing more. > For you it might be obvious > because you've been hacking that code for quite some time, but for > someone who is not in your position that's different. Yes, this is true. Let me repeat, I know that this is subjective and I am biased. Oleg. From oleg at redhat.com Wed Nov 25 15:40:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 25 Nov 2009 16:40:52 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125080342.GD2660@in.ibm.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> Message-ID: <20091125154052.GA6734@redhat.com> On 11/25, Ananth N Mavinakayanahalli wrote: > > I ran the ptrace-tests testsuite [1] on powerpc on the vanilla ptrace > and then with ptrace/utrace. The results for ptrace/utrace look better > :-) Great! thanks a lot Ananth for doing this. ptrace-utrace still fails 2 tests, > FAIL: syscall-reset I'll take a look later. Since unpatched kernel fails this test too I am not going to worry right now. I think this is ppc specific, x86 passes this test. > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > /bin/sh: line 5: 24803 Aborted ${dir}$tst > FAIL: step-fork This is expected. Should be fixed by ptrace-copy_process-should-disable-stepping.patch in -mm tree. (I am attaching this patch below just in case) I din't mention this patch in this series because this bug is "ortogonal" to utrace/ptrace. Oleg. ------------------------------------------------------ If the tracee calls fork() after PTRACE_SINGLESTEP, the forked child starts with TIF_SINGLESTEP/X86_EFLAGS_TF bits copied from ptraced parent. This is not right, especially when the new child is not auto-attaced: in this case it is killed by SIGTRAP. Change copy_process() to call user_disable_single_step(). Tested on x86. Test-case: #include #include #include #include #include #include int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!fork()) { /* kernel bug: this child will be killed by SIGTRAP */ printf("Hello world\n"); return 43; } wait(&status); return WEXITSTATUS(status); } for (;;) { assert(pid == wait(&status)); if (WIFEXITED(status)) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } assert(WEXITSTATUS(status) == 43); return 0; } Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath Signed-off-by: Andrew Morton --- diff -puN kernel/fork.c~ptrace-copy_process-should-disable-stepping kernel/fork.c --- a/kernel/fork.c~ptrace-copy_process-should-disable-stepping +++ a/kernel/fork.c @@ -1203,9 +1203,10 @@ static struct task_struct *copy_process( p->sas_ss_sp = p->sas_ss_size = 0; /* - * Syscall tracing should be turned off in the child regardless - * of CLONE_PTRACE. + * Syscall tracing and stepping should be turned off in the + * child regardless of CLONE_PTRACE. */ + user_disable_single_step(p); clear_tsk_thread_flag(p, TIF_SYSCALL_TRACE); #ifdef TIF_SYSCALL_EMU clear_tsk_thread_flag(p, TIF_SYSCALL_EMU); From mingo at elte.hu Wed Nov 25 16:00:32 2009 From: mingo at elte.hu (Ingo Molnar) Date: Wed, 25 Nov 2009 17:00:32 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091125145556.GA5394@redhat.com> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> <20091124204152.GA9131@redhat.com> <20091124212619.GB29096@one.firstfloor.org> <20091124214450.GA12828@redhat.com> <20091125084617.GD29096@one.firstfloor.org> <20091125145556.GA5394@redhat.com> Message-ID: <20091125160032.GB9456@elte.hu> * Oleg Nesterov wrote: > Much better. But in this case please note that most of tracehooks just > do: > > if (unlikely(task_utrace_flags(current) & SOME_EVENT)) > utrace_report_some_event(); > > I really don't understand why we shouldn't have (trivial!) helpers for > this. (As for naming - personally I do not care at all ;) We prefer helpers in most such cases - especially when in the normal case the helper has no side effects - as here. Then we want to compress all such reporting/callback as much as possible. Using helpers to abstract away functionality is one of the basic elements of writing clean kernel code. Ingo From newsletter at usbportugal.com Wed Nov 25 16:46:48 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Wed, 25 Nov 2009 17:46:48 +0100 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_48?= Message-ID: <92a12aa3020b3f9f11e4881f061722eb@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From teacoffee-house at wht-news2.com Wed Nov 25 17:04:51 2009 From: teacoffee-house at wht-news2.com (=?windows-1252?Q?Tea_&_Coffee_House?=) Date: Wed, 25 Nov 2009 17:04:51 -0000 Subject: =?windows-1252?q?Este_Natal_ofere=E7a_um_presente_original_ao_ma?= =?windows-1252?q?is_baixo_custo=2E=2E=2E?= Message-ID: <60eb926a4f0c82af939a8a1c0012f9e7@wht-news2.com> Newsletter Tea & Coffee House ? Se n?o consegue visualizar a newsletter clique aqui. ? ? ? ? Aten??o: para nos contactar n?o dever? responder a este e-mail. Dever? enviar um email para mail at teacoffee-house.com. Caso n?o pretenda receber mais Newsletters Tea & Coffee House, envie-nos um e-mail para remover at teacoffee-house.com com "retirar" no assunto. ? -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: newsletter.jpg Type: image/jpeg Size: 146806 bytes Desc: not available URL: From vendas at mardeb.com.br Wed Nov 25 19:26:08 2009 From: vendas at mardeb.com.br (Piero Jimenez) Date: Wed, 25 Nov 2009 19:26:08 GMT Subject: TINTAS INDUSTRIAIS LACA E ESMALTE SINTETICO Message-ID: <20091125192350.C7C703545A4@mhu16mtaz-tvt-spo.fly.com.br> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Nov 25 20:23:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 25 Nov 2009 21:23:22 +0100 Subject: utrace-ptrace && gdb testsuite tesults Message-ID: <20091125202322.GA30476@redhat.com> First of all, thanks Ananth and Cai for help! Jan, I need your help ;) looking at different reports I can't understand how to interpret them. To the point, I do not understand if the overall results are good or bad. The first question, are these tests supposed to be "stable"? For example, > Those are the test results on i686 F12 hosts with and without > CONFIG_UTRACE. Interesting thing is that the results on quite > different on two Intel hosts. Yes! I'd say the results are just "reversed". We have some PASS->FAIL changes on "ProLiant DL360 G4p", and on "HP Workstation XW4200" machine the _same_ tests show FAIL->PASS change. I can't imagine how utrace-ptrace can explain this difference if results are stable. I spent several hours trying to figure out how can I fix the failures, but since I never used gdb this is very much nontrivial to me. Because I just don't understand whats going on and what any particular test actually does. So. Given that the number of test is huge, and (I guess) we can't hope utrace-ptrace can pass 100% of tests, I am asking you to tell me which failures are "important". Then I'll try to fix them (most probably I will ask a lot of stupid questions before I will be able to do this ;). IOW. Only you and Roland can say whether utrace-ptrace is ready for use from gdb-testsuite's pov. Please tell me which failures should be fixed to conclude that utrace-ptrace "works". Oleg. From oleg at redhat.com Wed Nov 25 20:44:00 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 25 Nov 2009 21:44:00 +0100 Subject: [PATCH] utrace: trivial, move CONFIG_UTRACE into "General setup" Message-ID: <20091125204400.GA31632@redhat.com> Move CONFIG_UTRACE from the topmost menu into "General setup", near "Auditing support". (this matches the patch we sent for review) Signed-off-by: Oleg Nesterov --- init/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) --- UTRACE-PTRACE/init/Kconfig~MOVE_CONFIG_UTRACE 2009-11-22 17:05:10.000000000 +0100 +++ UTRACE-PTRACE/init/Kconfig 2009-11-24 20:34:08.000000000 +0100 @@ -295,6 +295,15 @@ config AUDIT logging of avc messages output). Does not do system-call auditing without CONFIG_AUDITSYSCALL. +config UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + config AUDITSYSCALL bool "Enable system-call auditing support" depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH) @@ -1205,15 +1214,6 @@ config STOP_MACHINE help Need stop_machine() primitive. -config UTRACE - bool "Infrastructure for tracing and debugging user processes" - depends on EXPERIMENTAL - depends on HAVE_ARCH_TRACEHOOK - help - Enable the utrace process tracing interface. This is an internal - kernel interface exported to kernel modules, to track events in - user threads, extract and change user thread state. - source "block/Kconfig" config PREEMPT_NOTIFIERS From jan.kratochvil at redhat.com Wed Nov 25 20:56:24 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 25 Nov 2009 21:56:24 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091125202322.GA30476@redhat.com> References: <20091125202322.GA30476@redhat.com> Message-ID: <20091125205624.GA32198@host0.dyn.jankratochvil.net> On Wed, 25 Nov 2009 21:23:22 +0100, Oleg Nesterov wrote: > The first question, are these tests supposed to be "stable"? No. There is no written down set of testcases with unstable results. > can explain this difference if results are stable. they are not. > I am asking you to tell me which failures are "important". In general everything where is a word "thread" has unstable results and "nonstop" tests are also a bit unstable. > Then I'll try to fix them (most probably I will ask a lot of stupid > questions before I will be able to do this ;). There are IMO/hopefully very few cases tested by the gdb testsuite and still not covered by the ptrace-testsuite, I even do not much expect we will see again a new utrace regression caught by the gdb testsuite && uncaught by the ptrace-testsuite. > IOW. Only you and Roland can say whether utrace-ptrace is ready > for use from gdb-testsuite's pov. Please tell me which failures > should be fixed to conclude that utrace-ptrace "works". Please point at some built or easily buildable kernel .rpm first. Regards, Jan From roland at redhat.com Wed Nov 25 21:17:15 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 25 Nov 2009 13:17:15 -0800 (PST) Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: Jan Kratochvil's message of Wednesday, 25 November 2009 21:56:24 +0100 <20091125205624.GA32198@host0.dyn.jankratochvil.net> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> Message-ID: <20091125211715.97781D360@magilla.sf.frob.com> > In general everything where is a word "thread" has unstable results and > "nonstop" tests are also a bit unstable. So where exactly is the problem in these cases? Are the tests overly timing-sensitive where there is no actual behavior bug? Or is gdb overly timing-sensitive where there is no actual kernel bug? Or is it just unknown, and might be a kernel bug after all (even an undiagnosed one in vanilla kernels)? > There are IMO/hopefully very few cases tested by the gdb testsuite and still > not covered by the ptrace-testsuite, I even do not much expect we will see > again a new utrace regression caught by the gdb testsuite && uncaught by the > ptrace-testsuite. That's certainly good to hear. If you are pretty confident about that, then I am quite happy to consider nonregression on all of ptrace-tests the sole gating test for kernel changes. We just don't want to wind up having other upstream reviewers notice a regression using gdb that we didn't notice before we submitted a kernel change. > Please point at some built or easily buildable kernel .rpm first. http://kojipkgs.fedoraproject.org/scratch/roland/task_1825649/ Thanks, Roland From hch at infradead.org Wed Nov 25 21:48:18 2009 From: hch at infradead.org (Christoph Hellwig) Date: Wed, 25 Nov 2009 16:48:18 -0500 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091124200127.GA5751@redhat.com> References: <20091124200127.GA5751@redhat.com> Message-ID: <20091125214818.GA4916@infradead.org> On Tue, Nov 24, 2009 at 09:01:27PM +0100, Oleg Nesterov wrote: > Hello. > > This is the new iteration of Roland's utrace patch, this time > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. > > 1-7 are already in -mm tree, I am sending them to simplify the > review. > > 8-12 don not change the behaviour, simple preparations. > > 13-14 add utrace-ptrace and utrace Skipped over it very, very briefly. One thing I really hate about this is that it introduces two ptrace implementation by adding the new one without removing the old one. Given that's it's pretty much too later for the 2.6.33 cycle anyway I'd suggest you make sure the remaining two major architectures (arm and mips) get converted, and if the remaining minor architectures don't manage to get their homework done they're left without ptrace. The other thing is that this patchset really doesn't quite justify utrace. It's growing a lot more code without actually growing any useful functionality. What about all those other utrace killer features that have been promised for a long time? From hch at infradead.org Wed Nov 25 21:50:18 2009 From: hch at infradead.org (Christoph Hellwig) Date: Wed, 25 Nov 2009 16:50:18 -0500 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <87my2bwtno.fsf@basil.nowhere.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> Message-ID: <20091125215018.GB4916@infradead.org> On Tue, Nov 24, 2009 at 09:32:27PM +0100, Andi Kleen wrote: > Oleg Nesterov writes: > > > From: Roland McGrath > > > > This adds the utrace facility, a new modular interface in the kernel > > for implementing user thread tracing and debugging. This fits on top > > of the tracehook_* layer, so the new code is well-isolated. > > Could we just drop the tracehook layer if this finally merged > and call the low level functions directly? > > It might have been reasonably early on when it was still out of tree, > but longer term when it's integrated having strange opaque hooks > like that just makes the coder harder to read and maintain. I agree that linux/tracehook.h as a separate layer is pretty annoying, but a lot of the helper actually are quite useful. I'd suggest to throw a patch ontop of the series to rename all the useful macros to utrace_ and move them into utrace.h and just remove those that are really trivial wrappers. From jan.kratochvil at redhat.com Wed Nov 25 22:30:37 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Wed, 25 Nov 2009 23:30:37 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091125211715.97781D360@magilla.sf.frob.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> Message-ID: <20091125223037.GA2773@host0.dyn.jankratochvil.net> On Wed, 25 Nov 2009 22:17:15 +0100, Roland McGrath wrote: > > In general everything where is a word "thread" has unstable results and > > "nonstop" tests are also a bit unstable. > > So where exactly is the problem in these cases? Are the tests overly > timing-sensitive where there is no actual behavior bug? Or is gdb overly > timing-sensitive where there is no actual kernel bug? Or is it just > unknown, and might be a kernel bug after all (even an undiagnosed one in > vanilla kernels)? gdb.server/server-run.exp: gdbserver contains data overflow/corruption, occasionally it crashes, occasionally passes. gdb.mi/mi-nonstop-exit.exp: Some race in GDB non-stop code. gdb.threads/attach-stopped.exp: Race in the testcase (I think so). etc. But in most cases I do not know, gdb.log is commonly not enough to find the problem and when it is not reproducible on the 2nd..nth run... But I+upstream already caught many races but still a lot of them remains. > > There are IMO/hopefully very few cases tested by the gdb testsuite and still > > not covered by the ptrace-testsuite, I even do not much expect we will see > > again a new utrace regression caught by the gdb testsuite && uncaught by the > > ptrace-testsuite. > > That's certainly good to hear. If you are pretty confident about that, > then I am quite happy to consider nonregression on all of ptrace-tests the > sole gating test for kernel changes. We just don't want to wind up having > other upstream reviewers notice a regression using gdb that we didn't > notice before we submitted a kernel change. I did not verify the GDB codebase for all the ptrace calls in any way. If it is a kernel patch submit after long development period it is probably still worth checking it against GDB. > > Please point at some built or easily buildable kernel .rpm first. > > http://kojipkgs.fedoraproject.org/scratch/roland/task_1825649/ OK, taken for reverification. Regards, Jan From oleg at redhat.com Wed Nov 25 22:28:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 25 Nov 2009 23:28:54 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125214818.GA4916@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> Message-ID: <20091125222854.GA2283@redhat.com> On 11/25, Christoph Hellwig wrote: > > On Tue, Nov 24, 2009 at 09:01:27PM +0100, Oleg Nesterov wrote: > > Hello. > > > > This is the new iteration of Roland's utrace patch, this time > > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. > > > > 1-7 are already in -mm tree, I am sending them to simplify the > > review. > > > > 8-12 don not change the behaviour, simple preparations. > > > > 13-14 add utrace-ptrace and utrace > > Skipped over it very, very briefly. One thing I really hate about this > is that it introduces two ptrace implementation by adding the new one > without removing the old one. Yes, we obviously need the old one when CONFIG_UTRACE is not enabled. So, I'd like to try to restate: one thing we all really hate is that CONFIG_UTRACE exists. > Given that's it's pretty much too later > for the 2.6.33 cycle anyway I'd suggest you make sure the remaining > two major architectures (arm and mips) get converted, and if the > remaining minor architectures don't manage to get their homework done > they're left without ptrace. Well, I can't comment this. I mean, I can't judge. > The other thing is that this patchset really doesn't quite justify > utrace. It's growing a lot more code without actually growing any > useful functionality. This should be clarified. I don't think ptrace-utrace adds a lot more code compared to the old ptrace. Note that we can kill a lot of old code once CONFIG_UTRACE goes away. ptrace_signal(), ptrace_notify(), even task_struct->almost_all_ptrace_related can go away. kernel/utrace.c does add 12280 bytes (on my machine), yes. > What about all those other utrace killer > features that have been promised for a long time? It is not clear how we can expect the new "killer" modules/applications which use utrace before we merge it. We already have some users, say, systemtap. But I don not know what can be counted as a "really killer" application of utrace. Oleg. From jan.kratochvil at redhat.com Wed Nov 25 23:37:28 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Thu, 26 Nov 2009 00:37:28 +0100 Subject: [PATCH 1-13] utrace-ptrace V1, for internal review In-Reply-To: <20091124113141.GA23653@linux.vnet.ibm.com> References: <20091122221224.GA8674@redhat.com> <20091124094027.GB21843@in.ibm.com> <20091124113141.GA23653@linux.vnet.ibm.com> Message-ID: <20091125233728.GA12807@host0.dyn.jankratochvil.net> On Tue, 24 Nov 2009 12:31:41 +0100, Srikar Dronamraju wrote: > When I get the latest set of ptrace-tests by using. > cvs -d :pserver:anoncvs:anoncvs at sources.redhat.com:/cvs/systemtap co ptrace-tests .... > 1. Am I using the right source of ptrace-tests or has its location > changed. It is right, webpage at: http://sourceware.org/systemtap/wiki/utrace/tests > 2. Are these new testcases x86 architecture specific? step-from-clone + syscall-from-clone Fixed/checked-in, now they SKIP (rc 77) on unsupported arches. New support for ppc/ppc64 PASSes. New support for s390/s390x FAILs (kernel-2.6.18-164.6.1.el5.s390x). orig_gpr2 seems to be errorneously set to the retval (gprs[2]). > 3. Shouldn't arch/powerpc/include/asm/user.h not define > user_regs_struct? Not sure why but ppc uses `struct pt_regs'. Thanks, Jan From caiqian at redhat.com Thu Nov 26 02:52:53 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Wed, 25 Nov 2009 21:52:53 -0500 (EST) Subject: GDB Testsuite Results for CONFIG_UTRACE with biarch In-Reply-To: <392404382.631051259203814803.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1750723075.631071259203973853.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hello! Please find biarch testing results with or without CONFIG_UTRACE below from 2 Intel and 1 AMD CPU F12 x86_64 systems. gdb-32.sum was for 32-bit run with 32-bit GDB; while gdb-64.sum was for 32-bit run with 64-bit GDB. All logs can be found at, http://people.redhat.com/qcai/kratochvil/ Thanks! CAI Qian Dell PowerEdge 2850 (Intel) $ diff -u noutrace/gdb-32.sum utrace/gdb-32.sum --- noutrace/gdb-32.sum 2009-11-26 10:00:51.000000000 +0800 +++ utrace/gdb-32.sum 2009-11-26 09:58:52.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 13:25:22 2009 +Test Run By root on Wed Nov 25 12:10:24 2009 Native configuration is i686-redhat-linux-gnu === gdb tests === @@ -5030,7 +5030,7 @@ PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child -FAIL: gdb.base/follow-child.exp: break +PASS: gdb.base/follow-child.exp: break Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/foll-vfork.exp ... PASS: gdb.base/foll-vfork.exp: set verbose PASS: gdb.base/foll-vfork.exp: insert first vfork catchpoint @@ -13463,7 +13463,7 @@ FAIL: gdb.java/jnpe.exp: run java next-over-throw FAIL: gdb.java/jnpe.exp: check for unwinder hook in java PASS: gdb.java/jnpe.exp: disable SIGSEGV for next-over-NPE -PASS: gdb.java/jnpe.exp: next over NPE +FAIL: gdb.java/jnpe.exp: next over NPE Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.java/jprint.exp ... PASS: gdb.java/jprint.exp: set print sevenbit-strings PASS: gdb.java/jprint.exp: set language to "java" @@ -16270,8 +16270,8 @@ PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt PASS: gdb.threads/attachstop-mt.exp: continue (attach4 continue) -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/attach-stopped.exp ... PASS: gdb.threads/attach-stopped.exp: nonthreaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: nonthreaded: attach1 to stopped, after setting file @@ -16286,7 +16286,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) @@ -16919,7 +16919,7 @@ PASS: gdb.threads/watchthreads2.exp: all threads started PASS: gdb.threads/watchthreads2.exp: watch x PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 -KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) +PASS: gdb.threads/watchthreads2.exp: all threads incremented x Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/watchthreads.exp ... PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] @@ -17139,7 +17139,7 @@ === gdb Summary === # of expected passes 14542 -# of unexpected failures 313 +# of unexpected failures 314 # of expected failures 40 # of untested testcases 3 # of unresolved testcases 2 $ diff -u noutrace/gdb-64.sum utrace/gdb-64.sum --- noutrace/gdb-64.sum 2009-11-26 10:00:35.000000000 +0800 +++ utrace/gdb-64.sum 2009-11-26 09:58:11.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 12:42:06 2009 +Test Run By root on Wed Nov 25 11:37:04 2009 Native configuration is x86_64-redhat-linux-gnu === gdb tests === @@ -5667,8 +5667,8 @@ UNRESOLVED: gdb.base/interrupt.exp: Send Control-C, second time ERROR: Undefined command "signal SIGINT". UNRESOLVED: gdb.base/interrupt.exp: signal SIGINT -FAIL: gdb.base/interrupt.exp: echo more data (timeout) -FAIL: gdb.base/interrupt.exp: send end of file +PASS: gdb.base/interrupt.exp: echo more data +FAIL: gdb.base/interrupt.exp: send end of file (eof) Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/jump.exp ... PASS: gdb.base/jump.exp: break before jump to non-call PASS: gdb.base/jump.exp: jump to non-call @@ -13452,7 +13452,7 @@ PASS: gdb.gdb/selftest.exp: Set xgdb prompt PASS: gdb.gdb/selftest.exp: send ^C to child process FAIL: gdb.gdb/selftest.exp: send SIGINT signal to child process (timeout) -PASS: gdb.gdb/selftest.exp: backtrace through signal handler +FAIL: gdb.gdb/selftest.exp: backtrace through signal handler Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.gdb/xfullpath.exp ... PASS: gdb.gdb/xfullpath.exp: breakpoint in captured_main PASS: gdb.gdb/xfullpath.exp: run until breakpoint at captured_main @@ -16055,36 +16055,8 @@ PASS: gdb.server/server-mon.exp: monitor set remote-debug 1 PASS: gdb.server/server-mon.exp: monitor set remote-debug 0 Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.server/server-run.exp ... -ERROR: tcl error sourcing /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.server/server-run.exp. -ERROR: : spawn id exp6 not open - while executing -"expect_background -nobrace -i exp6 full_buffer { } eof { - # The spawn ID is already closed now (but not yet waited for). - wait -i $expect_out(..." - invoked from within -"expect_background { - -i $server_spawn_id - full_buffer { } - eof { - # The spawn ID is already closed now (but not yet waited for). - wait -i $exp..." - (procedure "gdbserver_start" line 67) - invoked from within -"gdbserver_start "" $arguments" - (procedure "gdbserver_spawn" line 11) - invoked from within -"gdbserver_spawn $child_args" - (procedure "gdbserver_run" line 20) - invoked from within -"gdbserver_run """ - (file "/rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.server/server-run.exp" line 38) - invoked from within -"source /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.server/server-run.exp" - ("uplevel" body line 1) - invoked from within -"uplevel #0 source /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.server/server-run.exp" - invoked from within -"catch "uplevel #0 source $test_file_name"" +PASS: gdb.server/server-run.exp: loaded dynamic linker +PASS: gdb.server/server-run.exp: continue to main Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.stabs/exclfwd.exp ... PASS: gdb.stabs/exclfwd.exp: ptype v1 PASS: gdb.stabs/exclfwd.exp: ptype v2 @@ -16330,7 +16302,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) @@ -16963,7 +16935,7 @@ PASS: gdb.threads/watchthreads2.exp: all threads started PASS: gdb.threads/watchthreads2.exp: watch x PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 -PASS: gdb.threads/watchthreads2.exp: all threads incremented x +KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/watchthreads.exp ... PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] @@ -17182,8 +17154,8 @@ === gdb Summary === -# of expected passes 14687 -# of unexpected failures 121 +# of expected passes 14689 +# of unexpected failures 120 # of expected failures 40 # of untested testcases 5 # of unresolved testcases 2 Dell PowerEdge SC1435 (AMD) $ diff -u noutrace/gdb-32.sum utrace/gdb-32.sum --- noutrace/gdb-32.sum 2009-11-26 10:05:39.000000000 +0800 +++ utrace/gdb-32.sum 2009-11-26 10:03:08.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 19:08:49 2009 +Test Run By root on Wed Nov 25 18:12:23 2009 Native configuration is i686-redhat-linux-gnu === gdb tests === @@ -5026,7 +5026,7 @@ PASS: gdb.base/foll-fork.exp: explicit parent follow, tcatch fork PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: set follow parent, tbreak -FAIL: gdb.base/foll-fork.exp: (timeout) set follow parent, hit tbreak +PASS: gdb.base/foll-fork.exp: set follow parent, hit tbreak PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child @@ -10132,7 +10132,7 @@ PASS: gdb.base/structs.exp: advance to fun for return; return 2 structs-tf-td PASS: gdb.base/structs.exp: zed L for return; return 2 structs-tf-td PASS: gdb.base/structs.exp: return foo; return 2 structs-tf-td -PASS: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td +FAIL: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td PASS: gdb.base/structs.exp: advance to fun for finish; return 2 structs-tf-td PASS: gdb.base/structs.exp: zed L for finish; return 2 structs-tf-td PASS: gdb.base/structs.exp: finish foo; return 2 structs-tf-td @@ -13463,7 +13463,7 @@ FAIL: gdb.java/jnpe.exp: run java next-over-throw FAIL: gdb.java/jnpe.exp: check for unwinder hook in java PASS: gdb.java/jnpe.exp: disable SIGSEGV for next-over-NPE -PASS: gdb.java/jnpe.exp: next over NPE +FAIL: gdb.java/jnpe.exp: next over NPE Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.java/jprint.exp ... PASS: gdb.java/jprint.exp: set print sevenbit-strings PASS: gdb.java/jprint.exp: set language to "java" @@ -16270,8 +16270,8 @@ PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt PASS: gdb.threads/attachstop-mt.exp: continue (attach4 continue) -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/attach-stopped.exp ... PASS: gdb.threads/attach-stopped.exp: nonthreaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: nonthreaded: attach1 to stopped, after setting file @@ -16286,7 +16286,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) @@ -16919,7 +16919,7 @@ PASS: gdb.threads/watchthreads2.exp: all threads started PASS: gdb.threads/watchthreads2.exp: watch x PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 -KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) +PASS: gdb.threads/watchthreads2.exp: all threads incremented x Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/watchthreads.exp ... PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] @@ -17138,8 +17138,8 @@ === gdb Summary === -# of expected passes 14541 -# of unexpected failures 314 +# of expected passes 14540 +# of unexpected failures 316 # of expected failures 40 # of untested testcases 3 # of unresolved testcases 2 $ diff -u noutrace/gdb-64.sum utrace/gdb-64.sum --- noutrace/gdb-64.sum 2009-11-26 10:04:59.000000000 +0800 +++ utrace/gdb-64.sum 2009-11-26 10:02:48.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 18:39:10 2009 +Test Run By root on Wed Nov 25 17:23:18 2009 Native configuration is x86_64-redhat-linux-gnu === gdb tests === @@ -2077,8 +2077,8 @@ PASS: gdb.base/bigcore.exp: tbreak 269 PASS: gdb.base/bigcore.exp: continue PASS: gdb.base/bigcore.exp: next -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap PASS: gdb.base/bigcore.exp: save heap size PASS: gdb.base/bigcore.exp: grab pid PASS: gdb.base/bigcore.exp: signal SIGABRT @@ -5018,7 +5018,7 @@ PASS: gdb.base/foll-fork.exp: insert first fork catchpoint PASS: gdb.base/foll-fork.exp: continue to first fork catchpoint PASS: gdb.base/foll-fork.exp: default show parent follow, no catchpoints -PASS: gdb.base/foll-fork.exp: default parent follow, no catchpoints +FAIL: gdb.base/foll-fork.exp: (timeout) default parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: explicit show parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: explicit parent follow, no catchpoints @@ -5667,8 +5667,8 @@ UNRESOLVED: gdb.base/interrupt.exp: Send Control-C, second time ERROR: Undefined command "signal SIGINT". UNRESOLVED: gdb.base/interrupt.exp: signal SIGINT -PASS: gdb.base/interrupt.exp: echo more data -FAIL: gdb.base/interrupt.exp: send end of file (eof) +FAIL: gdb.base/interrupt.exp: echo more data (timeout) +FAIL: gdb.base/interrupt.exp: send end of file Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/jump.exp ... PASS: gdb.base/jump.exp: break before jump to non-call PASS: gdb.base/jump.exp: jump to non-call @@ -10151,7 +10151,7 @@ PASS: gdb.base/structs.exp: advance to fun for return; return 2 structs-tf-td PASS: gdb.base/structs.exp: zed L for return; return 2 structs-tf-td PASS: gdb.base/structs.exp: return foo; return 2 structs-tf-td -FAIL: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td +PASS: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td PASS: gdb.base/structs.exp: advance to fun for finish; return 2 structs-tf-td PASS: gdb.base/structs.exp: zed L for finish; return 2 structs-tf-td PASS: gdb.base/structs.exp: finish foo; return 2 structs-tf-td @@ -14489,7 +14489,7 @@ PASS: gdb.mi/mi-nsmoribund.exp: resume all, thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: hit thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: thread state: all running except the breakpoint thread -PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally +FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.mi/mi-nsthrexec.exp ... PASS: gdb.mi/mi-nsthrexec.exp: successfully compiled posix threads test case PASS: gdb.mi/mi-nsthrexec.exp: breakpoint at main @@ -17154,8 +17154,8 @@ === gdb Summary === -# of expected passes 14690 -# of unexpected failures 120 +# of expected passes 14688 +# of unexpected failures 122 # of expected failures 40 # of untested testcases 5 # of unresolved testcases 2 HP ProLiant ML370 G5 (Intel) $ diff -u noutrace/gdb-32.sum utrace/gdb-32.sum --- noutrace/gdb-32.sum 2009-11-26 10:34:34.000000000 +0800 +++ utrace/gdb-32.sum 2009-11-26 10:13:09.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 16:40:07 2009 +Test Run By root on Wed Nov 25 12:27:32 2009 Native configuration is i686-redhat-linux-gnu === gdb tests === @@ -16924,7 +16924,7 @@ PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] PASS: gdb.threads/watchthreads.exp: watch args[1] -PASS: gdb.threads/watchthreads.exp: disable 2 +PASS: gdb.threads/watchthreads.exp: disable 3 PASS: gdb.threads/watchthreads.exp: threaded watch loop PASS: gdb.threads/watchthreads.exp: first watchpoint on args[0] hit PASS: gdb.threads/watchthreads.exp: first watchpoint on args[1] hit $ diff -u noutrace/gdb-64.sum utrace/gdb-64.sum --- noutrace/gdb-64.sum 2009-11-26 10:34:48.000000000 +0800 +++ utrace/gdb-64.sum 2009-11-26 10:12:37.000000000 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Wed Nov 25 16:00:40 2009 +Test Run By root on Wed Nov 25 11:34:16 2009 Native configuration is x86_64-redhat-linux-gnu === gdb tests === @@ -2077,8 +2077,8 @@ PASS: gdb.base/bigcore.exp: tbreak 269 PASS: gdb.base/bigcore.exp: continue PASS: gdb.base/bigcore.exp: next -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap PASS: gdb.base/bigcore.exp: save heap size PASS: gdb.base/bigcore.exp: grab pid PASS: gdb.base/bigcore.exp: signal SIGABRT @@ -5018,7 +5018,7 @@ PASS: gdb.base/foll-fork.exp: insert first fork catchpoint PASS: gdb.base/foll-fork.exp: continue to first fork catchpoint PASS: gdb.base/foll-fork.exp: default show parent follow, no catchpoints -PASS: gdb.base/foll-fork.exp: default parent follow, no catchpoints +FAIL: gdb.base/foll-fork.exp: (timeout) default parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: explicit show parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: explicit parent follow, no catchpoints @@ -5047,7 +5047,7 @@ PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/follow-child.exp ... PASS: gdb.base/follow-child.exp: set follow-fork-mode child -FAIL: gdb.base/follow-child.exp: break +PASS: gdb.base/follow-child.exp: break Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.base/foll-vfork.exp ... PASS: gdb.base/foll-vfork.exp: set verbose PASS: gdb.base/foll-vfork.exp: insert first vfork catchpoint @@ -13483,7 +13483,7 @@ FAIL: gdb.java/jnpe.exp: run java next-over-throw FAIL: gdb.java/jnpe.exp: check for unwinder hook in java PASS: gdb.java/jnpe.exp: disable SIGSEGV for next-over-NPE -PASS: gdb.java/jnpe.exp: next over NPE +FAIL: gdb.java/jnpe.exp: next over NPE Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.java/jprint.exp ... PASS: gdb.java/jprint.exp: set print sevenbit-strings PASS: gdb.java/jprint.exp: set language to "java" @@ -16286,8 +16286,8 @@ PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped switch thread PASS: gdb.threads/attachstop-mt.exp: attach4 to stopped bt PASS: gdb.threads/attachstop-mt.exp: continue (attach4 continue) -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping Running /rpmbuild/BUILD/gdb-7.0/gdb/testsuite/gdb.threads/attach-stopped.exp ... PASS: gdb.threads/attach-stopped.exp: nonthreaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: nonthreaded: attach1 to stopped, after setting file @@ -16302,7 +16302,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) @@ -16940,7 +16940,7 @@ PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] PASS: gdb.threads/watchthreads.exp: watch args[1] -PASS: gdb.threads/watchthreads.exp: disable 3 +PASS: gdb.threads/watchthreads.exp: disable 2 PASS: gdb.threads/watchthreads.exp: threaded watch loop PASS: gdb.threads/watchthreads.exp: first watchpoint on args[0] hit PASS: gdb.threads/watchthreads.exp: first watchpoint on args[1] hit @@ -17154,8 +17154,8 @@ === gdb Summary === -# of expected passes 14690 -# of unexpected failures 120 +# of expected passes 14688 +# of unexpected failures 122 # of expected failures 40 # of untested testcases 5 # of unresolved testcases 2 From srikar at linux.vnet.ibm.com Thu Nov 26 07:07:47 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Thu, 26 Nov 2009 12:37:47 +0530 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125214818.GA4916@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> Message-ID: <20091126070747.GA30231@linux.vnet.ibm.com> Hi Christoph, > > The other thing is that this patchset really doesn't quite justify > utrace. It's growing a lot more code without actually growing any > useful functionality. What about all those other utrace killer > features that have been promised for a long time? > We are working on in-kernel gdbstub which was one of the features that you had asked for. gdbstub does pass unit tests; but we are looking at some way to hack the GDB testsuite to run its regression tests. Once we are able to run the GDB testsuite and utrace is part of some upstream tree, we plan to post these patches to LKML for comments. gdbstub uses utrace and uprobes underneath. Uprobes was rewritten to remove issues that LKML developers had opposed. Uprobes also has its own ftrace plugin to use uprobes. Currently in-kernel gdbstub is hosted by Frank Ch. Eigler over here: git://web.elastic.org/~fche/utrace-ext.git branch name utrace-gdbstub-uprobes -- Regards Srikar From ananth at in.ibm.com Thu Nov 26 07:53:35 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Thu, 26 Nov 2009 13:23:35 +0530 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125154052.GA6734@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> Message-ID: <20091126075335.GA18508@in.ibm.com> On Wed, Nov 25, 2009 at 04:40:52PM +0100, Oleg Nesterov wrote: > On 11/25, Ananth N Mavinakayanahalli wrote: > > > > I ran the ptrace-tests testsuite [1] on powerpc on the vanilla ptrace > > and then with ptrace/utrace. The results for ptrace/utrace look better > > :-) > > Great! thanks a lot Ananth for doing this. > > ptrace-utrace still fails 2 tests, > > > FAIL: syscall-reset > > I'll take a look later. Since unpatched kernel fails this test too > I am not going to worry right now. I think this is ppc specific, x86 > passes this test. > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > /bin/sh: line 5: 24803 Aborted ${dir}$tst > > FAIL: step-fork > > This is expected. Should be fixed by > > ptrace-copy_process-should-disable-stepping.patch > > in -mm tree. (I am attaching this patch below just in case) > I din't mention this patch in this series because this bug > is "ortogonal" to utrace/ptrace. Oleg, The patch doesn't seem to fix the issue on powerpc: step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. /bin/sh: line 5: 17325 Aborted ${dir}$tst FAIL: step-fork Ananth From mingo at elte.hu Thu Nov 26 09:10:52 2009 From: mingo at elte.hu (Ingo Molnar) Date: Thu, 26 Nov 2009 10:10:52 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125214818.GA4916@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> Message-ID: <20091126091052.GF1389@elte.hu> * Christoph Hellwig wrote: > [...] Given that's it's pretty much too later for the 2.6.33 cycle > anyway I'd suggest you make sure the remaining two major architectures > (arm and mips) get converted, and if the remaining minor architectures > don't manage to get their homework done they're left without ptrace. I suspect the opinion of the ptrace maintainers matters heavily whether it's appropriate for v2.6.33. You are not going to maintain this, they are. Regarding porting it to even more architectures - that's pretty much the worst idea possible. It increases maintenance and testing overhead by exploding the test matrix, while giving little to end result. Plus the worst effect of it is that it becomes even more intrusive and even harder (and riskier) to merge. So dont do that. The best strategy is to concentrate on just one or two well-tested architectures, and then grow to other architectures gradually. Like we've done it for basically all big kernel features in the past 10 years (that had non-trivial arch dependencies), with no exception that i can remember. Thanks, Ingo From hch at infradead.org Thu Nov 26 10:47:22 2009 From: hch at infradead.org (Christoph Hellwig) Date: Thu, 26 Nov 2009 05:47:22 -0500 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091126091052.GF1389@elte.hu> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> Message-ID: <20091126104722.GA8316@infradead.org> On Thu, Nov 26, 2009 at 10:10:52AM +0100, Ingo Molnar wrote: > > [...] Given that's it's pretty much too later for the 2.6.33 cycle > > anyway I'd suggest you make sure the remaining two major architectures > > (arm and mips) get converted, and if the remaining minor architectures > > don't manage to get their homework done they're left without ptrace. > > I suspect the opinion of the ptrace maintainers matters heavily whether > it's appropriate for v2.6.33. You are not going to maintain this, they > are. I am whoever like many others going to use it. And throwing in new code a few days before the merge window closes and thus not getting any of the broad -next test coverage is a pretty bad idea. In the end it will be the maintainers ruling but that doesn't make it a good idea from the engineering point of view. > Regarding porting it to even more architectures - that's pretty much the > worst idea possible. It increases maintenance and testing overhead by > exploding the test matrix, while giving little to end result. Plus the > worst effect of it is that it becomes even more intrusive and even > harder (and riskier) to merge. But it doesn't. Take a look at what these patches actually do, they basically introduce a new utrace layer, and (conditionally) rewrite ptrace to use it. The arch support isn't actually part of these patches directly but rather the cleanup of the underlying arch ptrace code to use regsets, tracehooks and co so that the new ptrace code can use. What the patches in the current form do is to introduce two different ptrace implementations, with one used on the architectures getting most testing and another secondary one for left over embedded or dead architectures with horrible results. So removing the old one is much better. The arm ptrace rewrite has already been posted by Roland, btw including some feedback from Russell, but nothing really happened to it. From mingo at elte.hu Thu Nov 26 12:24:41 2009 From: mingo at elte.hu (Ingo Molnar) Date: Thu, 26 Nov 2009 13:24:41 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091126104722.GA8316@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> Message-ID: <20091126122441.GC15189@elte.hu> * Christoph Hellwig wrote: > On Thu, Nov 26, 2009 at 10:10:52AM +0100, Ingo Molnar wrote: > > > [...] Given that's it's pretty much too later for the 2.6.33 cycle > > > anyway I'd suggest you make sure the remaining two major architectures > > > (arm and mips) get converted, and if the remaining minor architectures > > > don't manage to get their homework done they're left without ptrace. > > > > I suspect the opinion of the ptrace maintainers matters heavily whether > > it's appropriate for v2.6.33. You are not going to maintain this, they > > are. > > I am whoever like many others going to use it. And throwing in new > code a few days before the merge window closes [...] FYI, the merge window has not opened yet, so it cannot close in a few days. > [...] and thus not getting any of the broad -next test coverage is a > pretty bad idea. In the end it will be the maintainers ruling but > that doesn't make it a good idea from the engineering point of view. FYI, it's been in -mm, that's where it's maintained. > > Regarding porting it to even more architectures - that's pretty much > > the worst idea possible. It increases maintenance and testing > > overhead by exploding the test matrix, while giving little to end > > result. Plus the worst effect of it is that it becomes even more > > intrusive and even harder (and riskier) to merge. > > But it doesn't. Take a look at what these patches actually do, they > basically introduce a new utrace layer, and (conditionally) rewrite > ptrace to use it. The arch support isn't actually part of these > patches directly but rather the cleanup of the underlying arch ptrace > code to use regsets, tracehooks and co so that the new ptrace code can > use. ( I am aware of its design, i merged the original tracehook patches for x86. ) > What the patches in the current form do is to introduce two different > ptrace implementations, with one used on the architectures getting > most testing and another secondary one for left over embedded or dead > architectures with horrible results. So removing the old one is much > better. The arm ptrace rewrite has already been posted by Roland, btw > including some feedback from Russell, but nothing really happened to > it. Yes. Which is a further argument to not do it like that but to do one arch at a time. Trying to do too much at once is bad engineering. Ingo From peterz at infradead.org Thu Nov 26 12:55:52 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Thu, 26 Nov 2009 13:55:52 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091126070747.GA30231@linux.vnet.ibm.com> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126070747.GA30231@linux.vnet.ibm.com> Message-ID: <1259240152.4273.83.camel@twins> On Thu, 2009-11-26 at 12:37 +0530, Srikar Dronamraju wrote: > Hi Christoph, > > > > > The other thing is that this patchset really doesn't quite justify > > utrace. It's growing a lot more code without actually growing any > > useful functionality. What about all those other utrace killer > > features that have been promised for a long time? > > > > We are working on in-kernel gdbstub which was one of the features that > you had asked for. gdbstub does pass unit tests; but we are looking at > some way to hack the GDB testsuite to run its regression tests. Once we > are able to run the GDB testsuite and utrace is part of some upstream > tree, we plan to post these patches to LKML for comments. gdbstub uses > utrace and uprobes underneath. Uprobes was rewritten to remove issues > that LKML developers had opposed. Uprobes also has its own ftrace plugin > to use uprobes. > > Currently in-kernel gdbstub is hosted by Frank Ch. Eigler over here: > git://web.elastic.org/~fche/utrace-ext.git > branch name utrace-gdbstub-uprobes If its anywhere near functioning it would have made sense to send it out as an RFC patch-set right along with the utrace one. From caiqian at redhat.com Thu Nov 26 13:31:15 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Thu, 26 Nov 2009 08:31:15 -0500 (EST) Subject: Ptrace Testsuite Results for CONFIG_UTRACE In-Reply-To: <756597176.644251259241866436.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <2004347315.644611259242275867.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hello! Please find below results by using the latest ptrace testsuite with and without CONFIG_UTRACE. Overall, There did not look like some regression. The failures were getting less with the ptrace-utrace patchset applied. There are some tests failed for both kernels. * detach-sigkill-race * clone-multi-ptrace * step-fork Thanks! CAI Qian HP XW6600 Workstation (x86_64 Intel CPU) * make check --- noutrace/check 2009-11-26 20:55:15.000000000 +0800 +++ utrace/check 2009-11-26 20:53:10.000000000 +0800 @@ -31,18 +31,20 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace PASS: o_tracevfork PASS: o_tracevforkdone PASS: detach-parting-signal +detach-sigkill-race: detach-sigkill-race.c:167: reproduce: Unexpected error: No such process. +detach-sigkill-race: detach-sigkill-race.c:106: handler_fail: Assertion `0' failed. FAIL: detach-sigkill-race PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap PASS: highmem-debugger PASS: sigint-before-syscall-exit @@ -50,8 +52,7 @@ PASS: step-from-clone FAIL: step-fork ======================================== -4 of 47 tests failed +2 of 47 tests failed (4 tests were not run) * make check-biarch --- noutrace/check-biarch 2009-11-26 20:55:37.000000000 +0800 +++ utrace/check-biarch 2009-11-26 20:53:03.000000000 +0800 @@ -31,7 +31,7 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace @@ -42,7 +42,7 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit @@ -50,7 +50,7 @@ PASS: step-from-clone FAIL: step-fork ======================================== -3 of 44 tests failed +1 of 44 tests failed (7 tests were not run) * make xcheck and make xcheck-biarch results are identical. PASS: clone-get-signal PASS: ppc-ptrace-exec-full-regs PASS: x86_64-cs SKIP: user-area-padding PASS: reparent-zombie-clone ==================== All 6 tests passed (1 test was not run) ==================== HP XW9400 Workstation (x86_64 AMD CPU) * make check (both FAIL: detach-sigkill-race) --- noutrace/check 2009-11-26 21:14:12.000000000 +0800 +++ utrace/check 2009-11-26 20:57:37.000000000 +0800 @@ -31,11 +31,11 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 clone-multi-ptrace: clone-multi-ptrace.c:205: try_to_reproduce: Assertion `((((__extension__ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8) == 5' failed. clone-multi-ptrace: clone-multi-ptrace.c:101: handler_fail: Assertion `0' failed. -/bin/sh: line 5: 13519 Aborted ${dir}$tst +/bin/sh: line 5: 13183 Aborted ${dir}$tst FAIL: clone-multi-ptrace PASS: clone-ptrace PASS: o_tracevfork @@ -45,7 +45,7 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap PASS: highmem-debugger PASS: sigint-before-syscall-exit @@ -53,7 +53,7 @@ PASS: step-from-clone FAIL: step-fork ======================================== -5 of 47 tests failed +3 of 47 tests failed * make check-biarch --- noutrace/check-biarch 2009-11-26 20:59:53.000000000 +0800 +++ utrace/check-biarch 2009-11-26 20:57:56.000000000 +0800 @@ -31,7 +31,7 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace @@ -42,7 +42,7 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit @@ -50,7 +50,7 @@ PASS: step-from-clone FAIL: step-fork ======================================== -3 of 44 tests failed +1 of 44 tests failed * make xcheck and make xcheck-biarch results are identical. PASS: late-ptrace-may-attach-check PASS: tracer-lockup-on-sighandler-kill PASS: clone-get-signal PASS: ppc-ptrace-exec-full-regs PASS: x86_64-cs SKIP: user-area-padding PASS: reparent-zombie-clone ==================== All 6 tests passed (1 test was not run) ==================== Dell PowerEdge 1650 (i686 Intel CPU) * make check --- noutrace/check 2009-11-26 21:02:59.000000000 +0800 +++ utrace/check 2009-11-26 21:01:56.000000000 +0800 @@ -1,4 +1,4 @@ +PASS: ptrace-on-job-control-stopped PASS: attach-wait-on-stopped PASS: detach-can-signal PASS: attach-into-signal @@ -31,7 +31,7 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace @@ -42,7 +42,7 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit @@ -50,9 +50,8 @@ PASS: step-from-clone FAIL: step-fork ======================================== -3 of 44 tests failed +1 of 44 tests failed * make xcheck (the results are identical) PASS: late-ptrace-may-attach-check PASS: tracer-lockup-on-sighandler-kill PASS: clone-get-signal PASS: ppc-ptrace-exec-full-regs ./x86_64-cs: WIFSTOPPED - WSTOPSIG = 4 PASS: x86_64-cs SKIP: user-area-padding PASS: reparent-zombie-clone ==================== All 6 tests passed (1 test was not run) ==================== Dell PowerEdge SC1435 (i686 Intel CPU) * make check --- noutrace/check 2009-11-26 21:05:34.000000000 +0800 +++ utrace/check 2009-11-26 21:04:39.000000000 +0800 @@ -31,7 +31,7 @@ PASS: step-simple PASS: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace @@ -42,7 +42,7 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency PASS: erestartsys-trap SKIP: highmem-debugger PASS: sigint-before-syscall-exit @@ -50,7 +50,7 @@ PASS: step-from-clone FAIL: step-fork ======================================== -3 of 44 tests failed +1 of 44 tests failed (7 tests were not run) * make xcheck (the results are identical) PASS: late-ptrace-may-attach-check PASS: tracer-lockup-on-sighandler-kill PASS: clone-get-signal PASS: ppc-ptrace-exec-full-regs ./x86_64-cs: WIFSTOPPED - WSTOPSIG = 4 PASS: x86_64-cs SKIP: user-area-padding PASS: reparent-zombie-clone ==================== All 6 tests passed (1 test was not run) ==================== From oleg at redhat.com Thu Nov 26 14:27:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 15:27:45 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091126104722.GA8316@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> Message-ID: <20091126142745.GA4382@redhat.com> On 11/26, Christoph Hellwig wrote: > > What the patches in the current form do is to introduce two different > ptrace implementations, with one used on the architectures getting most > testing and another secondary one for left over embedded or dead > architectures with horrible results. Yes, nobody likes 2 implementations. I guess Roland and me hate CONFIG_UTRACE much more than anybody else. > So removing the old one is much > better. I am in no position to discuss this option. It is very easy to remove the old code and break !HAVE_ARCH_TRACEHOOK architectures. Although personally I am not sure this is practical. If we merge utrace, perhaps we will get more attention from maintainers, the old code will be "officially" deprecated/obsolete. I sent some trivial initial changes in arch/um/ a long ago, the patch was silently ignored. Even if I was able to fix arch/xxx myself, I don't understand how can I send the patches to maintainers until utrace is already merged in -mm at least. Oleg. From msamson at oomc.com Thu Nov 26 14:22:22 2009 From: msamson at oomc.com (Peggy Randall) Date: Thu, 26 Nov 2009 23:22:22 +0900 Subject: World of pilules! Message-ID: <001c01ca6ea3$de9a76f0$c13a3939@microsofa54d21hdotiq> New generation extra-strength med, for the treatment of ED only in men. http://vzrg.buxmybgopa.com/ From oleg at redhat.com Thu Nov 26 14:50:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 15:50:51 +0100 Subject: powerpc: fork && stepping (Was: [RFC,PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126075335.GA18508@in.ibm.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> Message-ID: <20091126145051.GB4382@redhat.com> I changed the subject. This bug has nothing to do with utrace, the kernel fails with or without these changes. On 11/26, Ananth N Mavinakayanahalli wrote: > > On Wed, Nov 25, 2009 at 04:40:52PM +0100, Oleg Nesterov wrote: > > On 11/25, Ananth N Mavinakayanahalli wrote: > > > > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > > /bin/sh: line 5: 24803 Aborted ${dir}$tst > > > FAIL: step-fork > > > > This is expected. Should be fixed by > > > > ptrace-copy_process-should-disable-stepping.patch > > > > in -mm tree. (I am attaching this patch below just in case) > > I din't mention this patch in this series because this bug > > is "ortogonal" to utrace/ptrace. > > The patch doesn't seem to fix the issue on powerpc: > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > /bin/sh: line 5: 17325 Aborted ${dir}$tst > FAIL: step-fork Good to know, thanks again Ananth. I'll take a look. Since I know nothing about powerpc, I can't promise the quick fix ;) The bug was found by code inspection, but the fix is not trivial because it depends on arch/, and it turns out the arch-independent fix in ptrace-copy_process-should-disable-stepping.patch http://marc.info/?l=linux-mm-commits&m=125789789322573 doesn't work. Ananth, could you please run the test-case from the changelog below ? I do not really expect this can help, but just in case. Oleg. #include #include #include #include #include #include int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!fork()) { /* kernel bug: this child will be killed by SIGTRAP */ printf("Hello world\n"); return 43; } wait(&status); return WEXITSTATUS(status); } for (;;) { assert(pid == wait(&status)); if (WIFEXITED(status)) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } assert(WEXITSTATUS(status) == 43); return 0; } From oleg at redhat.com Thu Nov 26 17:25:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 18:25:24 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126145051.GB4382@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> Message-ID: <20091126172524.GA14768@redhat.com> On 11/26, Oleg Nesterov wrote: > > On 11/26, Ananth N Mavinakayanahalli wrote: > > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > /bin/sh: line 5: 17325 Aborted ${dir}$tst > > FAIL: step-fork > > Good to know, thanks again Ananth. > > I'll take a look. Since I know nothing about powerpc, I can't > promise the quick fix ;) > > The bug was found by code inspection, but the fix is not trivial > because it depends on arch/, and it turns out the arch-independent > fix in > > ptrace-copy_process-should-disable-stepping.patch > http://marc.info/?l=linux-mm-commits&m=125789789322573 > > doesn't work. Just noticed the test-case fails in handler_fail(). Most probably this means it is killed by SIGALRM because either parent or child hang in wait(). Perhaps we have another (ppc specific?) bug, but currently I do not understand how this is possible, this should not be arch-dependent. Oleg. From metalstamper23434 at yahoo.com Thu Nov 26 17:34:45 2009 From: metalstamper23434 at yahoo.com (Alizee) Date: Fri, 27 Nov 2009 01:34:45 +0800 Subject: I wish you Merry Christmas Message-ID: <17E2A95D26BFF7C505C2B563EDF026F6@toplszb> Dear friends : Nearly Christmas , May the joy and warmth of Christmas fill your home with happiness. I have the pleasure of contacting with you today. We get your inquiry in internet and now we would like to have a brief introduction about our product for your understanding. Handbag set free women?s desire.A handbag represent more than functionality.Then you can?t miss Gucci handbags . Interlock GG logo is the most traditional character of Gucci, no matter where you are, you can find this outstanding symbol. Not only Gucci handbags are sought-after, but also Louis Vuitton, Chanel, Fendi, Marc Jacobs, Dior and other designer handbags are popular in our website http://replica-china.net. How fabulous they are! What is timeless and what is posh? No need to say too much, designer handbags can fulfill all your need, Your orders are also warmly welcomed, it is our commitment to satisfy your requirement, please trust that we will be your reliable business partner for our good reputation, good quality and competitive price! If you are interested, please feel free to contact us or visit our website: http://replica-china.net. Thanks & best regards, Replica-China.Net Market / Customer Service CEO Alizee Sincerely. -------------- next part -------------- An HTML attachment was scrubbed... URL: From vfalico at redhat.com Thu Nov 26 18:22:26 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Thu, 26 Nov 2009 19:22:26 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126172524.GA14768@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> Message-ID: <20091126182226.GF12355@darkmag.usersys.redhat.com> On Thu, Nov 26, 2009 at 06:25:24PM +0100, Oleg Nesterov wrote: > On 11/26, Oleg Nesterov wrote: > > > > On 11/26, Ananth N Mavinakayanahalli wrote: > > > > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > > /bin/sh: line 5: 17325 Aborted ${dir}$tst > > > FAIL: step-fork > > > > Good to know, thanks again Ananth. > > > > I'll take a look. Since I know nothing about powerpc, I can't > > promise the quick fix ;) > > > > The bug was found by code inspection, but the fix is not trivial > > because it depends on arch/, and it turns out the arch-independent > > fix in > > > > ptrace-copy_process-should-disable-stepping.patch > > http://marc.info/?l=linux-mm-commits&m=125789789322573 > > > > doesn't work. > > Just noticed the test-case fails in handler_fail(). Most probably > this means it is killed by SIGALRM because either parent or child > hang in wait(). Perhaps we have another (ppc specific?) bug, but > currently I do not understand how this is possible, this should > not be arch-dependent. I can confirm that we have another bug on ppc arch. The test case below is spinning forever, #include #include #include #include #include #include int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!fork()) return 0; printf("fork passed..\n"); return 0; } for (;;) { assert(pid == wait(&status)); if (WIFEXITED(status)) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } printf("Parent exit.\n"); return 0; } it doesn't hang, the parent is spinning around for, the test case isn't printing anything. Seems like fork() can't complete under PTRACE_SINGLESTEP. -- Veaceslav From oleg at redhat.com Thu Nov 26 20:23:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 21:23:12 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126182226.GF12355@darkmag.usersys.redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> Message-ID: <20091126202312.GA21945@redhat.com> Veaceslav doesn't have the time to continue, but he gave me access to rhts machine ;) The kernel is 2.6.31.6 btw. On 11/26, Veaceslav Falico wrote: > > > Just noticed the test-case fails in handler_fail(). Most probably > > this means it is killed by SIGALRM because either parent or child > > hang in wait(). Perhaps we have another (ppc specific?) bug, but > > currently I do not understand how this is possible, this should > > not be arch-dependent. > > I can confirm that we have another bug on ppc arch. The test case below > is spinning forever, > > [...] > > it doesn't hang, the parent is spinning around for, the test case > isn't printing anything. Seems like fork() can't complete under > PTRACE_SINGLESTEP. Yep, thanks a lot Veaceslav. I modified this test-case to print si_addr: int main(void) { int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!fork()) return 0; printf("fork passed..\n"); return 0; } for (;;) { siginfo_t info; assert(pid == wait(&status)); assert(status = 0x57f); assert(ptrace(PTRACE_GETSIGINFO, pid, 0,&info) == 0); printf("%p\n", info.si_addr); if (WIFEXITED(status)) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } printf("Parent exit.\n"); return 0; } the output is: ... 0xfedf880 0xfedf884 ... 0xfedf96c 0xfedf970 this is fork which calls __GI__IO_list_lock Dump of assembler code for function fork: 0x0fedf880 : mflr r0 ... 0x0fedf96c : li r28,0 0x0fedf970 : bl 0xfeacce0 <__GI__IO_list_lock> Then it loops inside __GI__IO_list_lock ... 0xfeacd24 0xfeacd28 0xfeacd2c 0xfeacd30 0xfeacd34 0xfeacd24 0xfeacd28 0xfeacd2c 0xfeacd30 0xfeacd34 0xfeacd24 0xfeacd28 0xfeacd2c 0xfeacd30 0xfeacd34 ... and so on forever, Dump of assembler code for function __GI__IO_list_lock: 0x0feacce0 <__GI__IO_list_lock+0>: mflr r0 0x0feacce4 <__GI__IO_list_lock+4>: stwu r1,-32(r1) 0x0feacce8 <__GI__IO_list_lock+8>: li r11,0 0x0feaccec <__GI__IO_list_lock+12>: bcl- 20,4*cr7+so,0xfeaccf0 <__GI__IO_list_lock+16> 0x0feaccf0 <__GI__IO_list_lock+16>: li r9,1 0x0feaccf4 <__GI__IO_list_lock+20>: stw r0,36(r1) 0x0feaccf8 <__GI__IO_list_lock+24>: stw r30,24(r1) 0x0feaccfc <__GI__IO_list_lock+28>: mflr r30 0x0feacd00 <__GI__IO_list_lock+32>: stw r31,28(r1) 0x0feacd04 <__GI__IO_list_lock+36>: stw r29,20(r1) 0x0feacd08 <__GI__IO_list_lock+40>: addi r29,r2,-29824 0x0feacd0c <__GI__IO_list_lock+44>: addis r30,r30,16 0x0feacd10 <__GI__IO_list_lock+48>: addi r30,r30,13060 0x0feacd14 <__GI__IO_list_lock+52>: lwz r31,-6436(r30) 0x0feacd18 <__GI__IO_list_lock+56>: lwz r0,8(r31) 0x0feacd1c <__GI__IO_list_lock+60>: cmpw cr7,r0,r29 0x0feacd20 <__GI__IO_list_lock+64>: beq- cr7,0xfeacd4c <__GI__IO_list_lock+108> beg-> 0x0feacd24 <__GI__IO_list_lock+68>: lwarx r0,0,r31 0x0feacd28 <__GI__IO_list_lock+72>: cmpw r0,r11 0x0feacd2c <__GI__IO_list_lock+76>: bne- 0xfeacd38 <__GI__IO_list_lock+88> 0x0feacd30 <__GI__IO_list_lock+80>: stwcx. r9,0,r31 end-> 0x0feacd34 <__GI__IO_list_lock+84>: bne+ 0xfeacd24 <__GI__IO_list_lock+68> I don't even know whether this is user-space bug or kernel bug, the asm above is the black magic for me. Anyone who knows something about powerpc can give me a hint? Oleg. From oleg at redhat.com Thu Nov 26 21:04:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 22:04:58 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126202312.GA21945@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> Message-ID: <20091126210458.GA24597@redhat.com> On 11/26, Oleg Nesterov wrote: > > Then it loops inside __GI__IO_list_lock > > 0xfeacd24 > 0xfeacd28 > 0xfeacd2c > 0xfeacd30 > 0xfeacd34 > ... > > and so on forever, > > Dump of assembler code for function __GI__IO_list_lock: > 0x0feacce0 <__GI__IO_list_lock+0>: mflr r0 > 0x0feacce4 <__GI__IO_list_lock+4>: stwu r1,-32(r1) > 0x0feacce8 <__GI__IO_list_lock+8>: li r11,0 > 0x0feaccec <__GI__IO_list_lock+12>: bcl- 20,4*cr7+so,0xfeaccf0 <__GI__IO_list_lock+16> > 0x0feaccf0 <__GI__IO_list_lock+16>: li r9,1 > 0x0feaccf4 <__GI__IO_list_lock+20>: stw r0,36(r1) > 0x0feaccf8 <__GI__IO_list_lock+24>: stw r30,24(r1) > 0x0feaccfc <__GI__IO_list_lock+28>: mflr r30 > 0x0feacd00 <__GI__IO_list_lock+32>: stw r31,28(r1) > 0x0feacd04 <__GI__IO_list_lock+36>: stw r29,20(r1) > 0x0feacd08 <__GI__IO_list_lock+40>: addi r29,r2,-29824 > 0x0feacd0c <__GI__IO_list_lock+44>: addis r30,r30,16 > 0x0feacd10 <__GI__IO_list_lock+48>: addi r30,r30,13060 > 0x0feacd14 <__GI__IO_list_lock+52>: lwz r31,-6436(r30) > 0x0feacd18 <__GI__IO_list_lock+56>: lwz r0,8(r31) > 0x0feacd1c <__GI__IO_list_lock+60>: cmpw cr7,r0,r29 > 0x0feacd20 <__GI__IO_list_lock+64>: beq- cr7,0xfeacd4c <__GI__IO_list_lock+108> > > beg-> 0x0feacd24 <__GI__IO_list_lock+68>: lwarx r0,0,r31 > 0x0feacd28 <__GI__IO_list_lock+72>: cmpw r0,r11 > 0x0feacd2c <__GI__IO_list_lock+76>: bne- 0xfeacd38 <__GI__IO_list_lock+88> > 0x0feacd30 <__GI__IO_list_lock+80>: stwcx. r9,0,r31 > end-> 0x0feacd34 <__GI__IO_list_lock+84>: bne+ 0xfeacd24 <__GI__IO_list_lock+68> > > I don't even know whether this is user-space bug or kernel bug, > the asm above is the black magic for me. When I use gdb to step over __GI__IO_list_lock(), it doesn't loop. I straced gdb and noticed that when the trace reaches 0x0feacd24: lwarx r0,0,r31 gdb does PTRACE_CONT, not PTRACE_SINGLESTEP. After that the child stops at 0x0feacd38, the next insn (isync). > Anyone who knows something about powerpc can give me a hint? Please ;) Oleg. From paulus at samba.org Thu Nov 26 21:53:12 2009 From: paulus at samba.org (Paul Mackerras) Date: Fri, 27 Nov 2009 08:53:12 +1100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126202312.GA21945@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> Message-ID: <19214.63688.860929.962005@cargo.ozlabs.ibm.com> Oleg Nesterov writes: > 0xfeacd24 > 0xfeacd28 > 0xfeacd2c > 0xfeacd30 > 0xfeacd34 > ... > > and so on forever, ... > beg-> 0x0feacd24 <__GI__IO_list_lock+68>: lwarx r0,0,r31 > 0x0feacd28 <__GI__IO_list_lock+72>: cmpw r0,r11 > 0x0feacd2c <__GI__IO_list_lock+76>: bne- 0xfeacd38 <__GI__IO_list_lock+88> > 0x0feacd30 <__GI__IO_list_lock+80>: stwcx. r9,0,r31 > end-> 0x0feacd34 <__GI__IO_list_lock+84>: bne+ 0xfeacd24 <__GI__IO_list_lock+68> > > I don't even know whether this is user-space bug or kernel bug, > the asm above is the black magic for me. The lwarx and stwcx. work together to do an atomic update to the word whose address is in r31. They are like LL (load-linked) and SC (store-conditional) on other architectures such as alpha. Basically the lwarx creates an internal "reservation" on the word pointed to by r31 and loads its value into r0. The stwcx. stores into that word but only if the reservation still exists. The reservation gets cleared (in hardware) if any other cpu writes to that word in the meantime. If the reservation did get cleared, the bne (branch if not equal) instruction will be taken and we loop around to try again. There is a difficulty when single-stepping through such a sequence because the process of taking the single-step exception and returning will clear the reservation. Thus if you single-step through that sequence it will never succeed. I believe gdb has code to recognize this kind of sequence and run through it without stopping until after the bne, precisely to avoid this problem. Paul. From schwab at linux-m68k.org Thu Nov 26 22:40:02 2009 From: schwab at linux-m68k.org (Andreas Schwab) Date: Thu, 26 Nov 2009 23:40:02 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <19214.63688.860929.962005@cargo.ozlabs.ibm.com> (Paul Mackerras's message of "Fri, 27 Nov 2009 08:53:12 +1100") References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> Message-ID: Paul Mackerras writes: > I believe gdb has code to recognize this kind of sequence and run > through it without stopping until after the bne, precisely to avoid > this problem. See gdb/rs6000-tdep.c:ppc_deal_with_atomic_sequence. Andreas. -- Andreas Schwab, schwab at linux-m68k.org GPG Key fingerprint = 58CA 54C7 6D53 942B 1756 01D3 44D5 214B 8276 4ED5 "And now for something completely different." From oleg at redhat.com Thu Nov 26 22:37:03 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 26 Nov 2009 23:37:03 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <19214.63688.860929.962005@cargo.ozlabs.ibm.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> Message-ID: <20091126223703.GA28556@redhat.com> On 11/27, Paul Mackerras wrote: > > Oleg Nesterov writes: > > > 0xfeacd24 > > 0xfeacd28 > > 0xfeacd2c > > 0xfeacd30 > > 0xfeacd34 > > ... > > > > and so on forever, > ... > > beg-> 0x0feacd24 <__GI__IO_list_lock+68>: lwarx r0,0,r31 > > 0x0feacd28 <__GI__IO_list_lock+72>: cmpw r0,r11 > > 0x0feacd2c <__GI__IO_list_lock+76>: bne- 0xfeacd38 <__GI__IO_list_lock+88> > > 0x0feacd30 <__GI__IO_list_lock+80>: stwcx. r9,0,r31 > > end-> 0x0feacd34 <__GI__IO_list_lock+84>: bne+ 0xfeacd24 <__GI__IO_list_lock+68> > > > > I don't even know whether this is user-space bug or kernel bug, > > the asm above is the black magic for me. > > The lwarx and stwcx. work together to do an atomic update to the word > whose address is in r31. They are like LL (load-linked) and SC > (store-conditional) on other architectures such as alpha. Basically > the lwarx creates an internal "reservation" on the word pointed to by > r31 and loads its value into r0. The stwcx. stores into that word but > only if the reservation still exists. The reservation gets cleared > (in hardware) if any other cpu writes to that word in the meantime. > If the reservation did get cleared, the bne (branch if not equal) > instruction will be taken and we loop around to try again. > > There is a difficulty when single-stepping through such a sequence > because the process of taking the single-step exception and returning > will clear the reservation. Thus if you single-step through that > sequence it will never succeed. I believe gdb has code to recognize > this kind of sequence and run through it without stopping until after > the bne, precisely to avoid this problem. Thanks! This explains everything, I think. Could you look at this ptrace-copy_process-should-disable-stepping.patch http://marc.info/?l=linux-mm-commits&m=125789789322573 patch? It is not clear to me how we can modify the test-case to verify it fixes the original problem for powerpc. At least, do you think this patch is good for powerpc ? Oleg. From ananth at in.ibm.com Fri Nov 27 05:39:25 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Fri, 27 Nov 2009 11:09:25 +0530 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126145051.GB4382@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> Message-ID: <20091127053925.GA8135@in.ibm.com> On Thu, Nov 26, 2009 at 03:50:51PM +0100, Oleg Nesterov wrote: > I changed the subject. This bug has nothing to do with utrace, > the kernel fails with or without these changes. > > On 11/26, Ananth N Mavinakayanahalli wrote: > > > > On Wed, Nov 25, 2009 at 04:40:52PM +0100, Oleg Nesterov wrote: > > > On 11/25, Ananth N Mavinakayanahalli wrote: > > > > > > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > > > /bin/sh: line 5: 24803 Aborted ${dir}$tst > > > > FAIL: step-fork > > > > > > This is expected. Should be fixed by > > > > > > ptrace-copy_process-should-disable-stepping.patch > > > > > > in -mm tree. (I am attaching this patch below just in case) > > > I din't mention this patch in this series because this bug > > > is "ortogonal" to utrace/ptrace. > > > > The patch doesn't seem to fix the issue on powerpc: > > > > step-fork: step-fork.c:56: handler_fail: Assertion `0' failed. > > /bin/sh: line 5: 17325 Aborted ${dir}$tst > > FAIL: step-fork > > Good to know, thanks again Ananth. > > I'll take a look. Since I know nothing about powerpc, I can't > promise the quick fix ;) > > The bug was found by code inspection, but the fix is not trivial > because it depends on arch/, and it turns out the arch-independent > fix in > > ptrace-copy_process-should-disable-stepping.patch > http://marc.info/?l=linux-mm-commits&m=125789789322573 > > doesn't work. > > Ananth, could you please run the test-case from the changelog > below ? I do not really expect this can help, but just in case. Right, it doesn't help :-( GDB shows that the parent is forever struck at wait(). Ananth From sam4560123 at sina.com Fri Nov 27 06:56:30 2009 From: sam4560123 at sina.com (=?utf-8?B?5a696aqP572R?=) Date: Fri, 27 Nov 2009 14:56:30 +0800 Subject: =?utf-8?b?572R5LiK56ys5LiA5Lit5LuL5Lqk5piT5bmz5Y+w?= Message-ID: <20091126.OQOUBLAJRBZTTHVO@sina.com> ??v -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: swqf-1.jpg Type: image/jpeg Size: 131229 bytes Desc: not available URL: From ananth at in.ibm.com Fri Nov 27 11:26:22 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Fri, 27 Nov 2009 16:56:22 +0530 Subject: [QUERY] signal_struct->count/live Message-ID: <20091127112622.GB8135@in.ibm.com> Oleg, I am confused as to why we need two atomics count and live in signal_struct. report_death() uses ->live as the group_dead indicator, while there are places (like the scheduler) which uses ->count as the nr_threads indicator. I tried git blame to see if it remembers why, but the addition predates 2.6.12 and so it does not know. Could you please shed some light on this? Ananth From hch at infradead.org Fri Nov 27 14:04:39 2009 From: hch at infradead.org (Christoph Hellwig) Date: Fri, 27 Nov 2009 09:04:39 -0500 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091126122441.GC15189@elte.hu> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> <20091126122441.GC15189@elte.hu> Message-ID: <20091127140439.GA17000@infradead.org> On Thu, Nov 26, 2009 at 01:24:41PM +0100, Ingo Molnar wrote: > FYI, the merge window has not opened yet, so it cannot close in a few > days. subsystems merged window, not Linus'. > > > [...] and thus not getting any of the broad -next test coverage is a > > pretty bad idea. In the end it will be the maintainers ruling but > > that doesn't make it a good idea from the engineering point of view. > > FYI, it's been in -mm, that's where it's maintained. None of the recent mm snapshots has anything utrace related in there, just a few ptrace patches from Oleg (which are in this series but a very small part of it) and certainly not all this new code that is pretty recent (take a look at the utrace list for the development). > Yes. Which is a further argument to not do it like that but to do one > arch at a time. Trying to do too much at once is bad engineering. I'm not sure why you're trying to pick fights here, but no one has said about doing it all in once. The point I'm trying to make is that it's pretty bad to keep parallel ptrace implementations, and we should settle on one. A pre-requisite of using the new once genericly is to have the architecture ptrace code updated. I think arm and mips are the two only relevant ones still missing, so updating them and killing the other ones is easy. If you think keeping the two ptrace implementations is fine argue for that directly, but please stick to the technical points instead of just fighting for fightings sake. From vfalico at redhat.com Fri Nov 27 14:11:09 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Fri, 27 Nov 2009 15:11:09 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091125211715.97781D360@magilla.sf.frob.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> Message-ID: <20091127141109.GB27137@darkmag.usersys.redhat.com> On Wed, Nov 25, 2009 at 01:17:15PM -0800, Roland McGrath wrote: > > That's certainly good to hear. If you are pretty confident about that, > then I am quite happy to consider nonregression on all of ptrace-tests the > sole gating test for kernel changes. We just don't want to wind up having > other upstream reviewers notice a regression using gdb that we didn't > notice before we submitted a kernel change. > I've just done 'make check' twice on unpatched kernel, and found that the results are not stable: --- gdb.sum 2009-11-27 09:54:14.000000000 +0100 +++ gdb.sum2 2009-11-27 10:51:42.000000000 +0100 @@ -1,4 +1,4 @@ -Test Run By root on Thu Nov 26 18:52:09 2009 +Test Run By root on Fri Nov 27 09:54:33 2009 Native configuration is i686-pc-linux-gnu === gdb tests === @@ -3537,12 +3537,12 @@ PASS: gdb.base/foll-fork.exp: unpatch ch PASS: gdb.base/foll-fork.exp: unpatch child, catch fork PASS: gdb.base/foll-fork.exp: unpatch child, breakpoint at exit call PASS: gdb.base/foll-fork.exp: unpatch child, set follow child -FAIL: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child (timeout) +PASS: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child PASS: gdb.base/foll-fork.exp: explicit parent follow, set tcatch fork PASS: gdb.base/foll-fork.exp: explicit parent follow, tcatch fork PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: set follow parent, tbreak -PASS: gdb.base/foll-fork.exp: set follow parent, hit tbreak +FAIL: gdb.base/foll-fork.exp: (timeout) set follow parent, hit tbreak PASS: gdb.base/foll-fork.exp: set follow parent, cleanup Running ./gdb.base/foll-vfork.exp ... PASS: gdb.base/foll-vfork.exp: set verbose @@ -12499,7 +12499,7 @@ PASS: gdb.mi/mi-nsmoribund.exp: thread s PASS: gdb.mi/mi-nsmoribund.exp: resume all, thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: hit thread specific breakpoint PASS: gdb.mi/mi-nsmoribund.exp: thread state: all running except the breakpoint thread -PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally +FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop Running ./gdb.mi/mi-nsthrexec.exp ... PASS: gdb.mi/mi-nsthrexec.exp: successfully compiled posix threads test case PASS: gdb.mi/mi-nsthrexec.exp: breakpoint at main @@ -14507,7 +14507,7 @@ PASS: gdb.threads/watchthreads2.exp: bre PASS: gdb.threads/watchthreads2.exp: all threads started PASS: gdb.threads/watchthreads2.exp: watch x PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 -KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) +PASS: gdb.threads/watchthreads2.exp: all threads incremented x Running ./gdb.threads/watchthreads.exp ... PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case PASS: gdb.threads/watchthreads.exp: watch args[0] @@ -14672,7 +14672,7 @@ UNSUPPORTED: gdb.xml/tdesc-xinclude.exp: === gdb Summary === # of expected passes 13854 -# of unexpected failures 75 +# of unexpected failures 76 # of expected failures 43 # of untested testcases 7 # of unsupported tests 59 -- Veaceslav From jan.kratochvil at redhat.com Fri Nov 27 14:20:02 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 27 Nov 2009 15:20:02 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091127141109.GB27137@darkmag.usersys.redhat.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091127141109.GB27137@darkmag.usersys.redhat.com> Message-ID: <20091127142002.GA1582@host0.dyn.jankratochvil.net> On Fri, 27 Nov 2009 15:11:09 +0100, Veaceslav Falico wrote: > -FAIL: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child (timeout) > +PASS: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child > -PASS: gdb.base/foll-fork.exp: set follow parent, hit tbreak > +FAIL: gdb.base/foll-fork.exp: (timeout) set follow parent, hit tbreak To be ignored, fixed upstream: http://sourceware.org/ml/gdb-patches/2009-11/msg00573.html > -PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally > +FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop > -KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) > +PASS: gdb.threads/watchthreads2.exp: all threads incremented x These are known to be unstable but there some known watch and non-stop problems so it may not even be a testcase-side bug. Therefore this test shows no changes/regressions. Regards, Jan From oleg at redhat.com Fri Nov 27 14:17:09 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Nov 2009 15:17:09 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091127140439.GA17000@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> <20091126122441.GC15189@elte.hu> <20091127140439.GA17000@infradead.org> Message-ID: <20091127141709.GA5137@redhat.com> On 11/27, Christoph Hellwig wrote: > > On Thu, Nov 26, 2009 at 01:24:41PM +0100, Ingo Molnar wrote: > > > > FYI, it's been in -mm, that's where it's maintained. > > None of the recent mm snapshots has anything utrace related in there, Well, not that I think this is important, but... Two weeks ago we asked Andrew do drop utrace-core.patch from -mm, it should be replaced by this updated version. Oleg. From oleg at redhat.com Fri Nov 27 14:34:05 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Nov 2009 15:34:05 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091127141109.GB27137@darkmag.usersys.redhat.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091127141109.GB27137@darkmag.usersys.redhat.com> Message-ID: <20091127143405.GB5137@redhat.com> On 11/27, Veaceslav Falico wrote: > > On Wed, Nov 25, 2009 at 01:17:15PM -0800, Roland McGrath wrote: > > > > That's certainly good to hear. If you are pretty confident about that, > > then I am quite happy to consider nonregression on all of ptrace-tests the > > sole gating test for kernel changes. We just don't want to wind up having > > other upstream reviewers notice a regression using gdb that we didn't > > notice before we submitted a kernel change. > > > > I've just done 'make check' twice on unpatched kernel, and found that the > results are not stable: > > --- gdb.sum 2009-11-27 09:54:14.000000000 +0100 > +++ gdb.sum2 2009-11-27 10:51:42.000000000 +0100 > @@ -1,4 +1,4 @@ > -Test Run By root on Thu Nov 26 18:52:09 2009 > +Test Run By root on Fri Nov 27 09:54:33 2009 > Native configuration is i686-pc-linux-gnu > > === gdb tests === > @@ -3537,12 +3537,12 @@ PASS: gdb.base/foll-fork.exp: unpatch ch > PASS: gdb.base/foll-fork.exp: unpatch child, catch fork > PASS: gdb.base/foll-fork.exp: unpatch child, breakpoint at exit call > PASS: gdb.base/foll-fork.exp: unpatch child, set follow child > -FAIL: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child (timeout) > +PASS: gdb.base/foll-fork.exp: unpatch child, unpatched parent breakpoints from child > PASS: gdb.base/foll-fork.exp: explicit parent follow, set tcatch fork > PASS: gdb.base/foll-fork.exp: explicit parent follow, tcatch fork > PASS: gdb.base/foll-fork.exp: set follow parent > PASS: gdb.base/foll-fork.exp: set follow parent, tbreak > -PASS: gdb.base/foll-fork.exp: set follow parent, hit tbreak > +FAIL: gdb.base/foll-fork.exp: (timeout) set follow parent, hit tbreak > PASS: gdb.base/foll-fork.exp: set follow parent, cleanup > Running ./gdb.base/foll-vfork.exp ... > PASS: gdb.base/foll-vfork.exp: set verbose > @@ -12499,7 +12499,7 @@ PASS: gdb.mi/mi-nsmoribund.exp: thread s > PASS: gdb.mi/mi-nsmoribund.exp: resume all, thread specific breakpoint > PASS: gdb.mi/mi-nsmoribund.exp: hit thread specific breakpoint > PASS: gdb.mi/mi-nsmoribund.exp: thread state: all running except the breakpoint thread > -PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally > +FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop > Running ./gdb.mi/mi-nsthrexec.exp ... > PASS: gdb.mi/mi-nsthrexec.exp: successfully compiled posix threads test case > PASS: gdb.mi/mi-nsthrexec.exp: breakpoint at main > @@ -14507,7 +14507,7 @@ PASS: gdb.threads/watchthreads2.exp: bre > PASS: gdb.threads/watchthreads2.exp: all threads started > PASS: gdb.threads/watchthreads2.exp: watch x > PASS: gdb.threads/watchthreads2.exp: set var test_ready = 1 > -KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) > +PASS: gdb.threads/watchthreads2.exp: all threads incremented x > Running ./gdb.threads/watchthreads.exp ... > PASS: gdb.threads/watchthreads.exp: successfully compiled posix threads test case > PASS: gdb.threads/watchthreads.exp: watch args[0] > @@ -14672,7 +14672,7 @@ UNSUPPORTED: gdb.xml/tdesc-xinclude.exp: > === gdb Summary === > > # of expected passes 13854 > -# of unexpected failures 75 > +# of unexpected failures 76 > # of expected failures 43 > # of untested testcases 7 > # of unsupported tests 59 Nice, thanks. So. I am going to conclude that, more or less, utrace-ptrace "passes" these tests. Jan, if you see something particular which needs more attention or should be fixed, please let me know. I'll try to investigate then. Oleg. From jan.kratochvil at redhat.com Fri Nov 27 14:43:56 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Fri, 27 Nov 2009 15:43:56 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091127143405.GB5137@redhat.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091127141109.GB27137@darkmag.usersys.redhat.com> <20091127143405.GB5137@redhat.com> Message-ID: <20091127144356.GA2699@host0.dyn.jankratochvil.net> On Fri, 27 Nov 2009 15:34:05 +0100, Oleg Nesterov wrote: > Jan, if you see something particular which needs more attention or should > be fixed, please let me know. I'll try to investigate then. I am still not finished with the verifications yesterday but so far no kernel behavior change has been proven and I doubt it will be. Going to reply today. The ppc kernel should be checked but I do not have built two non-utrace/utrace matching kernel rpms for it. Regards, Jan From oleg at redhat.com Fri Nov 27 15:05:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Nov 2009 16:05:31 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091127053925.GA8135@in.ibm.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091127053925.GA8135@in.ibm.com> Message-ID: <20091127150531.GE5137@redhat.com> On 11/27, Ananth N Mavinakayanahalli wrote: > > On Thu, Nov 26, 2009 at 03:50:51PM +0100, Oleg Nesterov wrote: > > > Ananth, could you please run the test-case from the changelog > > below ? I do not really expect this can help, but just in case. > > Right, it doesn't help :-( > > GDB shows that the parent is forever struck at wait(). Now this is interesting. Could you please double check the parent hangs in wait() ? This doesn't match the testing we did on powerpc machine with Veaceslav, and I hoped the problem was already resolved? Please see other emails in this thread. Hmm. Fortunately I still have the access to the testing machine. Yes, according to gdb it looks as if it "hangs" in wait(). This is not true. You can strace gdb itself, or look at xxx_ctxt_switches in /proc/pid_of_parent/status. Better yet, do not use gdb at all. Just strace (without -f) the parent, you should see it continues to trace the child and loops forever. Oleg. From oleg at redhat.com Fri Nov 27 15:15:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 27 Nov 2009 16:15:21 +0100 Subject: [QUERY] signal_struct->count/live In-Reply-To: <20091127112622.GB8135@in.ibm.com> References: <20091127112622.GB8135@in.ibm.com> Message-ID: <20091127151521.GF5137@redhat.com> On 11/27, Ananth N Mavinakayanahalli wrote: > > I am confused as to why we need two atomics count and live in signal_struct. > > report_death() uses ->live as the group_dead indicator, report_death? Perhaps you meant do_exit() ? > while there are > places (like the scheduler) which uses ->count as the nr_threads > indicator. > > I tried git blame to see if it remembers why, but the addition predates > 2.6.12 and so it does not know. > > Could you please shed some light on this? In short: signal->count must die. I was going to do this a long ago but never had the time. See also 4ab6c08336535f8c8e42cf45d7adeda882eff06e commit, this is the first step. Last time I did the grepping almost any usage of signal->count is not right. For example, __exit_signal() is correct, but it doesn't need to use ->count. Except: it is needed for things like get_nr_threads() in proc. In short: never use signal->count ;) Oleg. From vfalico at redhat.com Fri Nov 27 17:46:27 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Fri, 27 Nov 2009 18:46:27 +0100 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091126223703.GA28556@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> Message-ID: <20091127174627.GB26193@darkmag.usersys.redhat.com> On Thu, Nov 26, 2009 at 11:37:03PM +0100, Oleg Nesterov wrote: > > Could you look at this > > ptrace-copy_process-should-disable-stepping.patch > http://marc.info/?l=linux-mm-commits&m=125789789322573 > > patch? It is not clear to me how we can modify the test-case to > verify it fixes the original problem for powerpc. I modified the test-case, it confirms that ptrace-copy_process-should-disable-stepping.patch fixes the problem with TIF_SINGLESTEP copied by fork() on powerpc. Probably we need a similar fix for step-fork.c in ptrace-tests. Modified the original testcase to call fork via syscall(__NR_fork), to avoid the looping inside libc's fork() on powerpc. The parent singlesteps until he sees that the child has forked, after that the parent PTRACE_CONTs until the child exits. #include #include #include #include #include #include #include int main(void) { void *addr_after_fork = &&after_fork; int pid, status; if (!(pid = fork())) { assert(ptrace(PTRACE_TRACEME) == 0); kill(getpid(), SIGSTOP); if (!syscall(__NR_fork)) { /* kernel bug: this child will be killed by SIGTRAP */ printf("Hello world\n"); return 43; } after_fork: wait(&status); return WEXITSTATUS(status); } for (;;) { siginfo_t info; assert(pid == wait(&status)); assert(ptrace(PTRACE_GETSIGINFO, pid, 0,&info) == 0); if (info.si_addr == addr_after_fork) break; assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); } for (;;) { if (WIFEXITED(status)) break; assert(ptrace(PTRACE_CONT, pid, 0,0) == 0); assert(pid == wait(&status)); } assert(WEXITSTATUS(status) == 43); return 0; } -- Veaceslav From mingo at elte.hu Fri Nov 27 19:16:14 2009 From: mingo at elte.hu (Ingo Molnar) Date: Fri, 27 Nov 2009 20:16:14 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091127140439.GA17000@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> <20091126122441.GC15189@elte.hu> <20091127140439.GA17000@infradead.org> Message-ID: <20091127191614.GA30749@elte.hu> * Christoph Hellwig wrote: > > Yes. Which is a further argument to not do it like that but to do > > one arch at a time. Trying to do too much at once is bad > > engineering. > > I'm not sure why you're trying to pick fights here, [...] I am advocating proper engineering practices - not sure why you characterise it as 'picking fights'. > [...] but no one has said about doing it all in once. [...] To quote your mail in (<20091125214818.GA4916 at infradead.org>): > > [...] I'd suggest you make sure the remaining two major > > architectures (arm and mips) get converted [...] Spreading the impact of these changes to even more architectures is bad, for the reasons i outlined in my previous mail. Thanks, Ingo From ananth at in.ibm.com Sat Nov 28 07:06:02 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Sat, 28 Nov 2009 12:36:02 +0530 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091127150531.GE5137@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091127053925.GA8135@in.ibm.com> <20091127150531.GE5137@redhat.com> Message-ID: <20091128070602.GA23108@in.ibm.com> On Fri, Nov 27, 2009 at 04:05:31PM +0100, Oleg Nesterov wrote: > On 11/27, Ananth N Mavinakayanahalli wrote: > > > > On Thu, Nov 26, 2009 at 03:50:51PM +0100, Oleg Nesterov wrote: > > > > > Ananth, could you please run the test-case from the changelog > > > below ? I do not really expect this can help, but just in case. > > > > Right, it doesn't help :-( > > > > GDB shows that the parent is forever struck at wait(). > > Now this is interesting. Could you please double check the parent hangs > in wait() ? > > This doesn't match the testing we did on powerpc machine with Veaceslav, > and I hoped the problem was already resolved? > > Please see other emails in this thread. > > > Hmm. Fortunately I still have the access to the testing machine. > Yes, according to gdb it looks as if it "hangs" in wait(). This > is not true. You can strace gdb itself, or look at xxx_ctxt_switches > in /proc/pid_of_parent/status. > > Better yet, do not use gdb at all. Just strace (without -f) the parent, > you should see it continues to trace the child and loops forever. Yes, I can see it looping. However, Veaceslav's modified testcase in http://lkml.org/lkml/2009/11/27/215 passes on the machine with ptrace-copy_process-should-disable-stepping.patch. Ananth From ananth at in.ibm.com Sat Nov 28 07:23:52 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Sat, 28 Nov 2009 12:53:52 +0530 Subject: [QUERY] signal_struct->count/live In-Reply-To: <20091127151521.GF5137@redhat.com> References: <20091127112622.GB8135@in.ibm.com> <20091127151521.GF5137@redhat.com> Message-ID: <20091128072352.GC23108@in.ibm.com> On Fri, Nov 27, 2009 at 04:15:21PM +0100, Oleg Nesterov wrote: > On 11/27, Ananth N Mavinakayanahalli wrote: > > > > I am confused as to why we need two atomics count and live in signal_struct. > > > > report_death() uses ->live as the group_dead indicator, > > report_death? Perhaps you meant do_exit() ? Right, do_exit() and that is what is picked up by tracehook_report_death(), and in turn by report_death(). > > while there are > > places (like the scheduler) which uses ->count as the nr_threads > > indicator. > > > > I tried git blame to see if it remembers why, but the addition predates > > 2.6.12 and so it does not know. > > > > Could you please shed some light on this? > > In short: signal->count must die. I was going to do this a long ago > but never had the time. See also 4ab6c08336535f8c8e42cf45d7adeda882eff06e > commit, this is the first step. > > Last time I did the grepping almost any usage of signal->count is > not right. For example, __exit_signal() is correct, but it doesn't > need to use ->count. > > Except: it is needed for things like get_nr_threads() in proc. > > In short: never use signal->count ;) Thanks for the clarification Oleg. Ananth From ananth at in.ibm.com Sat Nov 28 07:30:50 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Sat, 28 Nov 2009 13:00:50 +0530 Subject: powerpc: fork && stepping (Was: [RFC, PATCH 0/14] utrace/ptrace) In-Reply-To: <20091127174627.GB26193@darkmag.usersys.redhat.com> References: <20091125080342.GD2660@in.ibm.com> <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> Message-ID: <20091128073049.GD23108@in.ibm.com> On Fri, Nov 27, 2009 at 06:46:27PM +0100, Veaceslav Falico wrote: > On Thu, Nov 26, 2009 at 11:37:03PM +0100, Oleg Nesterov wrote: > > > > Could you look at this > > > > ptrace-copy_process-should-disable-stepping.patch > > http://marc.info/?l=linux-mm-commits&m=125789789322573 > > > > patch? It is not clear to me how we can modify the test-case to > > verify it fixes the original problem for powerpc. > > I modified the test-case, it confirms that > ptrace-copy_process-should-disable-stepping.patch fixes the > problem with TIF_SINGLESTEP copied by fork() on powerpc. > > Probably we need a similar fix for step-fork.c in ptrace-tests. > > Modified the original testcase to call fork via syscall(__NR_fork), > to avoid the looping inside libc's fork() on powerpc. > The parent singlesteps until he sees that the child has forked, after > that the parent PTRACE_CONTs until the child exits. Thanks Veaceslav. This works: Index: ptrace-tests/tests/step-fork.c =================================================================== --- ptrace-tests.orig/tests/step-fork.c +++ ptrace-tests/tests/step-fork.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifndef PTRACE_SINGLESTEP @@ -78,7 +79,7 @@ main (int argc, char **argv) sigprocmask (SIG_BLOCK, &mask, NULL); ptrace (PTRACE_TRACEME); raise (SIGUSR1); - if (fork () == 0) + if (syscall(__NR_fork) == 0) { read (-1, NULL, 0); _exit (22); Oleg, With the above patch applied, syscall-reset is the only failure I see on powerpc: errno 14 (Bad address) syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. unexpected child status 67f FAIL: syscall-reset ... ======================================== 1 of 40 tests failed (11 tests were not run) Please report to utrace-devel at redhat.com ======================================== Ananth From ananth at in.ibm.com Sat Nov 28 08:09:59 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Sat, 28 Nov 2009 13:39:59 +0530 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091127144356.GA2699@host0.dyn.jankratochvil.net> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091127141109.GB27137@darkmag.usersys.redhat.com> <20091127143405.GB5137@redhat.com> <20091127144356.GA2699@host0.dyn.jankratochvil.net> Message-ID: <20091128080959.GE23108@in.ibm.com> On Fri, Nov 27, 2009 at 03:43:56PM +0100, Jan Kratochvil wrote: > On Fri, 27 Nov 2009 15:34:05 +0100, Oleg Nesterov wrote: > > Jan, if you see something particular which needs more attention or should > > be fixed, please let me know. I'll try to investigate then. > > I am still not finished with the verifications yesterday but so far no kernel > behavior change has been proven and I doubt it will be. Going to reply today. > > The ppc kernel should be checked but I do not have built two non-utrace/utrace > matching kernel rpms for it. Jan, I reran tests on a POWER6 machine with the single-step fix Oleg had cited on lkml. The diff between the two did not change: [ananth at mjs22lp1 ~]$ diff -upN vanilla-gdb.sum pt-gdb.sum --- vanilla-gdb.sum 2009-11-28 13:33:12.487477684 +0530 +++ pt-gdb.sum 2009-11-28 13:08:07.210531851 +0530 @@ -1,4 +1,4 @@ -Test Run By ananth on Sat Nov 28 13:28:05 2009 +Test Run By ananth on Sat Nov 28 13:03:02 2009 Native configuration is powerpc64-unknown-linux-gnu === gdb tests === @@ -7602,7 +7602,7 @@ PASS: gdb.base/sigbpt.exp: stepi bp at s PASS: gdb.base/sigbpt.exp: stepi bp at segv; continue to keeper PASS: gdb.base/sigbpt.exp: stepi bp at segv; nopass SIGSEGV PASS: gdb.base/sigbpt.exp: stepi bp at segv; set breakpoint 0 of 1 -PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler +PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler (at breakpoint) PASS: gdb.base/sigbpt.exp: stepi bp at segv; clear breakpoint 0 of 1 PASS: gdb.base/sigbpt.exp: rerun to main PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; pass SIGSEGV @@ -7610,7 +7610,7 @@ PASS: gdb.base/sigbpt.exp: stepi bp befo PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; nopass SIGSEGV PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; set breakpoint 0 of 2 PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; set breakpoint 1 of 2 -PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; stepi out of handler +PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; stepi out of handler (at breakpoint) PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; clear breakpoint 0 of 2 PASS: gdb.base/sigbpt.exp: stepi bp before and at segv; clear breakpoint 1 of 2 PASS: gdb.base/sigbpt.exp: rerun to main The summary for the runs remains identical: === gdb Summary === # of expected passes 13971 # of unexpected failures 51 # of unexpected successes 2 # of expected failures 40 # of untested testcases 8 # of unresolved testcases 125 # of unsupported tests 55 /home/ananth/gdb-7.0/gdb/testsuite/../../gdb/gdb version 7.0 -nw -nx Regards, Ananth From jan.kratochvil at redhat.com Sat Nov 28 10:42:14 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sat, 28 Nov 2009 11:42:14 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091128080959.GE23108@in.ibm.com> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091127141109.GB27137@darkmag.usersys.redhat.com> <20091127143405.GB5137@redhat.com> <20091127144356.GA2699@host0.dyn.jankratochvil.net> <20091128080959.GE23108@in.ibm.com> Message-ID: <20091128104214.GA17165@host0.dyn.jankratochvil.net> Ananth, On Sat, 28 Nov 2009 09:09:59 +0100, Ananth N Mavinakayanahalli wrote: > I reran tests on a POWER6 machine with the single-step fix Oleg had > cited on lkml. The diff between the two did not change: ... > -PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler > +PASS: gdb.base/sigbpt.exp: stepi bp at segv; stepi out of handler (at breakpoint) We do not check if GDB is happy with utrace or not. We check if there are any ptrace changes visible to the userland. Any such change should be either a known kernel ptrace bugfix visible on ptrace-testsuite or it is a change=regression by the utrace code. There is no perfect tool to check that but GDB is heuristically sensitive for such changes. If there is a stable change of testcase output between kernels it must be either a known kernel ptrace bugfix visible on ptrace-testsuite or it is a change=regression by the utrace code. (The third possibility is for example the two kernels were more different than just the utrace change as possibly in CAI Qian's testing - or that some subtle timing has changed producing different results in a stable way despite the result is in fact unstable.) One should first check gdb.log diff at this "stepi out of handler" place and if the reason is not obvious there then to manually investigate/debug it. Thanks, Jan From oleg at redhat.com Sat Nov 28 19:04:02 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 28 Nov 2009 20:04:02 +0100 Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091128190402.GA19374@redhat.com> (add cc's) On 11/27, caiqian at redhat.com wrote: > > I have consistently reproduced the failure with clone-multi-ptrace > with both the patched and unpatched F13 kernels. > > # ./clone-multi-ptrace > clone-multi-ptrace: clone-multi-ptrace.c:205: try_to_reproduce: Assertion `((((__extension__ (((union { __typeof(status) __in; int __i; }) { .__in = (status) }).__i))) & 0xff00) >> 8) == 5' failed. > clone-multi-ptrace: clone-multi-ptrace.c:101: handler_fail: Assertion `0' failed. > Aborted I can reproduce this on Jan's testing machine (thanks a lot Jan ;). This has nothing to do with ptrace, perhaps user-space bug. The test case fails because the traced traced gets SIGILL, but this happens even without ptrace. I distilled the code #include #include #include #include #include #include #include #define THREAD_NUM 2 #define STACK_SIZE (16 * 1024) static int thread_func(void *unused) { syscall(__NR_exit, 22); return 0; } void try_to_reproduce (void) { int pid, status, i; pid = fork(); if (pid == 0) { for (i = 0; i < THREAD_NUM; i++) clone(thread_func, malloc(STACK_SIZE) + STACK_SIZE, CLONE_VM | // only this flag is important CLONE_FS | CLONE_FILES | CLONE_SIGHAND | CLONE_THREAD | CLONE_SYSVSEM, NULL); usleep(1000); exit(0); } assert(pid == waitpid(pid, &status, 0)); if (WIFEXITED(status)) return; printf("\nERR!! status=%x\n", status); exit(1); } int main(void) { for (;;) { try_to_reproduce(); printf("."); } return 0; } and it quickly triggers the same problem. The subthread (and thus the whole child process) is killed by SIGILL, si_code == 2 (ILL_ILLOPN), the faulting instruction is "vmovdqa" in /lib64/ld-2.11.so:_dl_x86_64_restore_sse() Dump of assembler code for function _dl_x86_64_restore_sse: 0x0000003ad1e14950 <_dl_x86_64_restore_sse+0>: cmpl $0x0,0x20a5f9(%rip) # +0x3ad201ef50 0x0000003ad1e14957 <_dl_x86_64_restore_sse+7>: js 0x3ad1e149aa <_dl_x86_64_restore_sse+90> ---> 0x0000003ad1e14959 <_dl_x86_64_restore_sse+9>: vmovdqa %fs:0x80,%ymm0 0x0000003ad1e14963 <_dl_x86_64_restore_sse+19>: vmovdqa %fs:0xa0,%ymm1 0x0000003ad1e1496d <_dl_x86_64_restore_sse+29>: vmovdqa %fs:0xc0,%ymm2 0x0000003ad1e14977 <_dl_x86_64_restore_sse+39>: vmovdqa %fs:0xe0,%ymm3 0x0000003ad1e14981 <_dl_x86_64_restore_sse+49>: vmovdqa %fs:0x100,%ymm4 0x0000003ad1e1498b <_dl_x86_64_restore_sse+59>: vmovdqa %fs:0x120,%ymm5 0x0000003ad1e14995 <_dl_x86_64_restore_sse+69>: vmovdqa %fs:0x140,%ymm6 0x0000003ad1e1499f <_dl_x86_64_restore_sse+79>: vmovdqa %fs:0x160,%ymm7 0x0000003ad1e149a9 <_dl_x86_64_restore_sse+89>: retq 0x0000003ad1e149aa <_dl_x86_64_restore_sse+90>: movdqa %fs:0x80,%xmm0 Stack trace: #0 _dl_x86_64_restore_sse () at ../sysdeps/x86_64/dl-trampoline.S:222 222 vmovdqa %fs:RTLD_SAVESPACE_SSE+0*YMM_SIZE, %ymm0 #0 _dl_x86_64_restore_sse () at ../sysdeps/x86_64/dl-trampoline.S:222 #1 0x0000003ad1e0dbf5 in _dl_fixup (l=, reloc_arg=) at ../elf/dl-runtime.c:126 #2 0x0000003ad1e142e5 in _dl_runtime_resolve () at ../sysdeps/x86_64/dl-trampoline.S:41 #3 0x0000000000400855 in thread_func (unused=) at CLONE.c:14 #4 0x0000003ad22ddf3d in clone () at ../sysdeps/unix/sysv/linux/x86_64/clone.S:112 glibc-2.11-2.x86_64 kernel 2.6.31.5-127.fc12.x86_64 Oleg. From pavel at ucw.cz Sun Nov 29 08:59:58 2009 From: pavel at ucw.cz (Pavel Machek) Date: Sun, 29 Nov 2009 09:59:58 +0100 Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: <20091125214818.GA4916@infradead.org> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> Message-ID: <20091129085957.GF1530@ucw.cz> On Wed 2009-11-25 16:48:18, Christoph Hellwig wrote: > On Tue, Nov 24, 2009 at 09:01:27PM +0100, Oleg Nesterov wrote: > > Hello. > > > > This is the new iteration of Roland's utrace patch, this time > > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. > > > > 1-7 are already in -mm tree, I am sending them to simplify the > > review. > > > > 8-12 don not change the behaviour, simple preparations. > > > > 13-14 add utrace-ptrace and utrace > > Skipped over it very, very briefly. One thing I really hate about this > is that it introduces two ptrace implementation by adding the new one > without removing the old one. Given that's it's pretty much too later > for the 2.6.33 cycle anyway I'd suggest you make sure the remaining > two major architectures (arm and mips) get converted, and if the > remaining minor architectures don't manage to get their homework done > they're left without ptrace. I don't think introducing regressions to force people to rewrite code is a good way to go... Pavel -- (english) http://www.livejournal.com/~pavelmachek (cesky, pictures) http://atrey.karlin.mff.cuni.cz/~pavel/picture/horses/blog.html From oleg at redhat.com Sun Nov 29 19:28:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 29 Nov 2009 20:28:51 +0100 Subject: detach-sigkill-race failures with and without utrace patches In-Reply-To: <1845151563.661051259308473746.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <1845151563.661051259308473746.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091129192851.GA14771@redhat.com> On 11/27, CAI Qian wrote: > > I have been consistently reproduced detach-sigkill-race failures > on an x86_64 F12 box on the both patched and unpatched kernels. > > # uname -r > 2.6.32-0.53.rc8.496.fc13.x86_64 > > Are those expected? This can be explained by clone() bug too, so far I think this failure has nothing to do with ptrace. When I reproduced this failure, the subthread was killed by SIGILL in _dl_x86_64_restore_sse(), like it happens with the test-case I sent in another thread. Oleg. From oleg at redhat.com Sun Nov 29 21:07:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 29 Nov 2009 22:07:16 +0100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <20091128073049.GD23108@in.ibm.com> References: <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> Message-ID: <20091129210716.GA19205@redhat.com> On 11/28, Ananth N Mavinakayanahalli wrote: > > syscall-reset is the only failure I see on > powerpc: > > errno 14 (Bad address) > syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location > ()) == 38' failed. > unexpected child status 67f > FAIL: syscall-reset (to remind, it also fails without utrace) Once again, I know nothing about powerc, perhaps I misread the code, but I believe this test-case is just wrong on powerpc and should be fixed. On powerpc, syscall_get_nr() returns regs->gpr[0], this means this register is used to pass the syscall number. This matches do_syscall_trace_enter(), it returns regs->gpr[0] as a (possibly changed by tracer) syscall nr. arch/powerpc/kernel/entry_64.S does syscall_dotrace: bl .do_syscall_trace_enter mr r0,r3 // I guess, r3 = r0 ? ... b syscall_dotrace_cont syscall_dotrace_cont: syscall_dotrace_cont: cmpldi 0,r0,NR_syscalls bge- syscall_enosys syscall_enosys: li r3,-ENOSYS b syscall_exit Now return to the test-case, syscall-reset.c. The tracee does l = syscall (-23, 1, 2, 3) and stops. The tracer does #define RETREG offsetof(struct pt_regs, gpr[0]) #define NEWVAL ((long) ENOTTY) l = ptrace(PTRACE_PEEKUSER, child, RETREG, 0l); l == -23, this is correct, note syscall(-23) above. l = ptrace(PTRACE_POKEUSER, child, RETREG, NEWVAL); And expects the tracee will see NEWVAL==ENOTTY after return from the systame call. Of course this can't happen. We changed the syscall number, the new value is ENOTTY == 25 == __NR_stime, sys_stime() correctly returns -EFAULT. ----------------------------------------------------------------- If I change the test-case to use NEWVAL == 1000 (or any other value greater than NR_syscalls), then the tracee sees ENOSYS and this is correct too. But I do not see how it is possible to change the retcode on powerpc. Unlike x86, powepc doesn't set -ENOSYS "in advance", before doing do_syscall_trace_enter() logic. This means that if the tracer "cancels" syscall, r3 will be overwritten by syscall_enosys. This probably means the kernel should be fixed too, but I am not brave enough to change the asm which I can't understand ;) Oleg. From jan.kratochvil at redhat.com Sun Nov 29 22:39:59 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sun, 29 Nov 2009 23:39:59 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091125223037.GA2773@host0.dyn.jankratochvil.net> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091125223037.GA2773@host0.dyn.jankratochvil.net> Message-ID: <20091129223959.GA15480@host0.dyn.jankratochvil.net> On Wed, 25 Nov 2009 23:30:37 +0100, Jan Kratochvil wrote: > > > Please point at some built or easily buildable kernel .rpm first. > > > > http://kojipkgs.fedoraproject.org/scratch/roland/task_1825649/ > > OK, taken for reverification. Followed the differences found by Qian and verified none of them (did not verify the ppc suspicious one) has any regression in GDB testsuite. Regards, Jan From jan.kratochvil at redhat.com Sun Nov 29 22:40:23 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Sun, 29 Nov 2009 23:40:23 +0100 Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091129223959.GA15480@host0.dyn.jankratochvil.net> References: <20091125202322.GA30476@redhat.com> <20091125205624.GA32198@host0.dyn.jankratochvil.net> <20091125211715.97781D360@magilla.sf.frob.com> <20091125223037.GA2773@host0.dyn.jankratochvil.net> <20091129223959.GA15480@host0.dyn.jankratochvil.net> Message-ID: <20091129224023.GA15643@host0.dyn.jankratochvil.net> On Sun, 29 Nov 2009 23:39:59 +0100, Jan Kratochvil wrote: > Followed the differences found by Qian and verified none of them (did not > verify the ppc suspicious one) has any regression in GDB testsuite. Forgot the log FYI. Regards, Jan -result-2.6.31.5-127.fc12.x86_64/gdb +result-2.6.32-0.53.rc8.496.fc13.x86_64/gdb *attach*stop* generally unchecked, it should be covered by ptrace-testsuite and the GDB testcases are currently racy. -FAIL: gdb.base/follow-child.exp: break +PASS: gdb.base/follow-child.exp: break = unstable testcase, RH-specific, dropped as redundant to other testcases /root/jkratoch/redhat/gdb-7.0-3.fc12.src/gdb-7.0-m64/gdb/testsuite -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping = racy, ignored -PASS: gdb.base/foll-fork.exp: default parent follow, no catchpoints +FAIL: gdb.base/foll-fork.exp: (timeout) default parent follow, no catchpoints = racy, fixed the testcase upstream /root/jkratoch/redhat/gdb-7.0-3.fc12.src/gdb-7.0-m64/gdb/testsuite.unix.-m32 -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped = racy, ignored -FAIL: gdb.base/interrupt.exp: continue +PASS: gdb.base/interrupt.exp: continue FAIL: gdb.base/interrupt.exp: echo data (timeout) ERROR: Undefined command "". UNRESOLVED: gdb.base/interrupt.exp: Send Control-C, second time FAIL: gdb.base/interrupt.exp: signal SIGINT (the program is no longer running) -FAIL: gdb.base/interrupt.exp: echo more data (timeout) -FAIL: gdb.base/interrupt.exp: send end of file +PASS: gdb.base/interrupt.exp: echo more data +FAIL: gdb.base/interrupt.exp: send end of file (eof) = both kernels behave the same - correctly, updated erestart* tests set, for x86_64-x86_64-i386 (kernel-debugger-inferior) GDB needs a fix: http://sourceware.org/ml/gdb-patches/2009-11/msg00592.html -FAIL: gdb.server/ext-run.exp: get process list +PASS: gdb.server/ext-run.exp: get process list = upstream gdbserver data corruption -FAIL: gdb.java/jnpe.exp: next over NPE +PASS: gdb.java/jnpe.exp: next over NPE = fixed the testcase in archer /root/jkratoch/redhat/gdb-7.0-3.fc12.src/gdb-7.0-m32/gdb/testsuite.unix.-m32 -ERROR: Couldn't send info inferior 16 to GDB. -UNRESOLVED: gdb.base/multi-forks.exp: Did kill 16 +PASS: gdb.base/multi-forks.exp: Run to exit 11 = always ignored by me, IMO racy -PASS: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt -PASS: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping +FAIL: gdb.threads/attachstop-mt.exp: attach4 stop by interrupt (timeout) +FAIL: gdb.threads/attachstop-mt.exp: attach4, exit leaves process sleeping = racy, ignored -FAIL: gdb.cp/constructortest.exp: running to main in runto PASS: gdb.cp/constructortest.exp: breaking on A::A -FAIL: gdb.cp/constructortest.exp: continue to breakpoint: First line A -FAIL: gdb.cp/constructortest.exp: Verify in in-charge A::A -FAIL: gdb.cp/constructortest.exp: continue to breakpoint: First line A -FAIL: gdb.cp/constructortest.exp: Verify in not-in-charge A::A +PASS: gdb.cp/constructortest.exp: continue to breakpoint: First line A +PASS: gdb.cp/constructortest.exp: Verify in in-charge A::A +PASS: gdb.cp/constructortest.exp: continue to breakpoint: First line A +PASS: gdb.cp/constructortest.exp: Verify in not-in-charge A::A -FAIL: gdb.pie/break.exp: run until function breakpoint -FAIL: gdb.pie/break.exp: run until breakpoint set at a line number -FAIL: gdb.pie/break.exp: run until file:function(6) breakpoint -FAIL: gdb.pie/break.exp: run until file:function(5) breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until file:function(4) breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until file:function(3) breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until file:function(2) breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until file:function(1) breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until quoted breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: run until file:linenum breakpoint (the program is no longer running) -FAIL: gdb.pie/break.exp: breakpoint offset +1 -FAIL: gdb.pie/break.exp: step onto breakpoint (the program is no longer running) +PASS: gdb.pie/break.exp: run until function breakpoint +PASS: gdb.pie/break.exp: run until breakpoint set at a line number +PASS: gdb.pie/break.exp: run until file:function(6) breakpoint +PASS: gdb.pie/break.exp: run until file:function(5) breakpoint +PASS: gdb.pie/break.exp: run until file:function(4) breakpoint +PASS: gdb.pie/break.exp: run until file:function(3) breakpoint +PASS: gdb.pie/break.exp: run until file:function(2) breakpoint +PASS: gdb.pie/break.exp: run until file:function(1) breakpoint +PASS: gdb.pie/break.exp: run until quoted breakpoint +PASS: gdb.pie/break.exp: run until file:linenum breakpoint +PASS: gdb.pie/break.exp: breakpoint offset +1 +PASS: gdb.pie/break.exp: step onto breakpoint = ignored although the two kernels behaved differently - they place libraries of i386-on-x86_64-kernel PIE binaries differently, possibly different patchset besides the utrace/non-utrace; sent in off-list mail Message-ID: <20091127084920.GA20053 at host0.dyn.jankratochvil.net> ("Fedora kernels x86_64->i386 PIE libs change/regression") -PASS: gdb.base/bigcore.exp: extract next heap (stop at 50) -PASS: gdb.base/bigcore.exp: extract prev heap (stop at 50) +PASS: gdb.base/bigcore.exp: extract next heap +PASS: gdb.base/bigcore.exp: extract prev heap -Total of 4292375328 (0xffd87320) bytes bytes 53 chunks^M +Total of 4292422432 (0xffd92b20) bytes bytes 41 chunks^M = fixed the testcase upstream -PASS: gdb.threads/watchthreads.exp: disable 2 +PASS: gdb.threads/watchthreads.exp: disable 3 = racy, ignored -FAIL: gdb.mi/mi-nsmoribund.exp: unexpected stop +PASS: gdb.mi/mi-nsmoribund.exp: resume all, program exited normally = racy, ignored -PASS: gdb.threads/watchthreads2.exp: all threads incremented x +KFAIL: gdb.threads/watchthreads2.exp: gdb can drop watchpoints in multithreaded app (PRMS: gdb/10116) = racy, ignored -PASS: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td +FAIL: gdb.base/structs.exp: value foo returned; return 2 structs-tf-td = unstable testcase, fixed upstream FAIL: gdb.gdb/selftest.exp: send SIGINT signal to child process (timeout) -PASS: gdb.gdb/selftest.exp: backtrace through signal handler +FAIL: gdb.gdb/selftest.exp: backtrace through signal handler = ptrace unrelated, racy, bug invoked by packaging, fixed upstream From benh at kernel.crashing.org Sun Nov 29 23:15:01 2009 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Mon, 30 Nov 2009 10:15:01 +1100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <20091129210716.GA19205@redhat.com> References: <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> Message-ID: <1259536501.2076.39.camel@pasglop> On Sun, 2009-11-29 at 22:07 +0100, Oleg Nesterov wrote: > On 11/28, Ananth N Mavinakayanahalli wrote: > > > > syscall-reset is the only failure I see on > > powerpc: > > > > errno 14 (Bad address) > > syscall-reset: syscall-reset.c:95: main: Assertion `(*__errno_location > > ()) == 38' failed. > > unexpected child status 67f > > FAIL: syscall-reset > > (to remind, it also fails without utrace) > > Once again, I know nothing about powerc, perhaps I misread the code, > but I believe this test-case is just wrong on powerpc and should be > fixed. > > On powerpc, syscall_get_nr() returns regs->gpr[0], this means this > register is used to pass the syscall number. Correct. > This matches do_syscall_trace_enter(), it returns regs->gpr[0] as a > (possibly changed by tracer) syscall nr. > > arch/powerpc/kernel/entry_64.S does > > syscall_dotrace: > > bl .do_syscall_trace_enter > mr r0,r3 // I guess, r3 = r0 ? r3 is the return value from a function so this replaces the syscall number > ... > b syscall_dotrace_cont > > syscall_dotrace_cont: > > syscall_dotrace_cont: > > cmpldi 0,r0,NR_syscalls > bge- syscall_enosys > > syscall_enosys: > > li r3,-ENOSYS > b syscall_exit > > > Now return to the test-case, syscall-reset.c. The tracee does > l = syscall (-23, 1, 2, 3) and stops. > > The tracer does > > #define RETREG offsetof(struct pt_regs, gpr[0]) > #define NEWVAL ((long) ENOTTY) > > l = ptrace(PTRACE_PEEKUSER, child, RETREG, 0l); > > l == -23, this is correct, note syscall(-23) above. > > l = ptrace(PTRACE_POKEUSER, child, RETREG, NEWVAL); > > And expects the tracee will see NEWVAL==ENOTTY after return from > the systame call. > > Of course this can't happen. We changed the syscall number, the > new value is ENOTTY == 25 == __NR_stime, sys_stime() correctly > returns -EFAULT. > > ----------------------------------------------------------------- > > If I change the test-case to use NEWVAL == 1000 (or any other value > greater than NR_syscalls), then the tracee sees ENOSYS and this is > correct too. > > But I do not see how it is possible to change the retcode on powerpc. > Unlike x86, powepc doesn't set -ENOSYS "in advance", before doing > do_syscall_trace_enter() logic. This means that if the tracer "cancels" > syscall, r3 will be overwritten by syscall_enosys. > > This probably means the kernel should be fixed too, but I am not > brave enough to change the asm which I can't understand ;) Yes, the asm should be changed. I suppose we could check if the result of do_syscall_trace_enter is negative, and if it is, branch to the exit path using r3 as the error code. Would that be ok ? Something like this: diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S index 1175a85..7a88c88 100644 --- a/arch/powerpc/kernel/entry_32.S +++ b/arch/powerpc/kernel/entry_32.S @@ -419,6 +419,9 @@ syscall_dotrace: stw r0,_TRAP(r1) addi r3,r1,STACK_FRAME_OVERHEAD bl do_syscall_trace_enter + cmpwi cr0,r3,0 + blt ret_from_syscall + /* * Restore argument registers possibly just changed. * We use the return value of do_syscall_trace_enter diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S index 9763267..ec709a7 100644 --- a/arch/powerpc/kernel/entry_64.S +++ b/arch/powerpc/kernel/entry_64.S @@ -240,6 +240,9 @@ syscall_dotrace: bl .save_nvgprs addi r3,r1,STACK_FRAME_OVERHEAD bl .do_syscall_trace_enter + cmpdi cr0,r3,0 + blt syscall_exit + /* * Restore argument registers possibly just changed. * We use the return value of do_syscall_trace_enter Cheers, Ben. From benh at kernel.crashing.org Mon Nov 30 00:43:21 2009 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Mon, 30 Nov 2009 11:43:21 +1100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <1259536501.2076.39.camel@pasglop> References: <20091125154052.GA6734@redhat.com> <20091126075335.GA18508@in.ibm.com> <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> <1259536501.2076.39.camel@pasglop> Message-ID: <1259541801.2076.44.camel@pasglop> On Mon, 2009-11-30 at 10:15 +1100, Benjamin Herrenschmidt wrote: > Yes, the asm should be changed. I suppose we could check if the result > of do_syscall_trace_enter is negative, and if it is, branch to the exit > path using r3 as the error code. Would that be ok ? > > Something like this: Note however that there's a trace exit too and that's normally the right place to alter the result don't you think ? Cheers, Ben. > diff --git a/arch/powerpc/kernel/entry_32.S b/arch/powerpc/kernel/entry_32.S > index 1175a85..7a88c88 100644 > --- a/arch/powerpc/kernel/entry_32.S > +++ b/arch/powerpc/kernel/entry_32.S > @@ -419,6 +419,9 @@ syscall_dotrace: > stw r0,_TRAP(r1) > addi r3,r1,STACK_FRAME_OVERHEAD > bl do_syscall_trace_enter > + cmpwi cr0,r3,0 > + blt ret_from_syscall > + > /* > * Restore argument registers possibly just changed. > * We use the return value of do_syscall_trace_enter > diff --git a/arch/powerpc/kernel/entry_64.S b/arch/powerpc/kernel/entry_64.S > index 9763267..ec709a7 100644 > --- a/arch/powerpc/kernel/entry_64.S > +++ b/arch/powerpc/kernel/entry_64.S > @@ -240,6 +240,9 @@ syscall_dotrace: > bl .save_nvgprs > addi r3,r1,STACK_FRAME_OVERHEAD > bl .do_syscall_trace_enter > + cmpdi cr0,r3,0 > + blt syscall_exit > + > /* > * Restore argument registers possibly just changed. > * We use the return value of do_syscall_trace_enter > > > Cheers, > Ben. From roland at redhat.com Mon Nov 30 04:44:48 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 29 Nov 2009 20:44:48 -0800 (PST) Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: Oleg Nesterov's message of Saturday, 28 November 2009 20:04:02 +0100 <20091128190402.GA19374@redhat.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> Message-ID: <20091130044448.9D134D6D2@magilla.sf.frob.com> Please file this test case on bugzilla.redhat.com for Fedora 12 glibc. Thanks, Roland From divulgacao at refrimur.com Mon Nov 30 06:13:52 2009 From: divulgacao at refrimur.com (Refrimur) Date: Mon, 30 Nov 2009 04:13:52 -0200 Subject: REFRIMUR NOVEMBRO 2009. Message-ID: An HTML attachment was scrubbed... URL: From caiqian at redhat.com Mon Nov 30 08:39:00 2009 From: caiqian at redhat.com (CAI Qian) Date: Mon, 30 Nov 2009 03:39:00 -0500 (EST) Subject: utrace-ptrace && gdb testsuite tesults In-Reply-To: <20091129223959.GA15480@host0.dyn.jankratochvil.net> Message-ID: <465445424.696891259570340516.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Followed the differences found by Qian and verified none of them (did > not verify the ppc suspicious one) has any regression in GDB testsuite. I did not reproduce the original possible regression seen on ppc64 RHEL6 systems. The kernel was build directly from roland's git tree with and without CONFIG_UTRACE. $ diff -u noutrace/gdb-64.sum utrace/gdb-64.sum --- noutrace/gdb-64.sum 2009-11-30 16:29:16.793769391 +0800 +++ utrace/gdb-64.sum 2009-11-30 16:28:06.249892712 +0800 @@ -1,4 +1,4 @@ -Test Run By root on Mon Nov 30 02:27:53 2009 +Test Run By root on Mon Nov 30 02:27:59 2009 Native configuration is powerpc64-unknown-linux-gnu === gdb tests === @@ -4046,7 +4046,7 @@ PASS: gdb.base/foll-fork.exp: default parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow parent PASS: gdb.base/foll-fork.exp: explicit show parent follow, no catchpoints -PASS: gdb.base/foll-fork.exp: explicit parent follow, no catchpoints +FAIL: gdb.base/foll-fork.exp: (timeout) explicit parent follow, no catchpoints PASS: gdb.base/foll-fork.exp: set follow child PASS: gdb.base/foll-fork.exp: explicit show child follow, no catchpoints PASS: gdb.base/foll-fork.exp: explicit child follow, no catchpoints @@ -14764,7 +14764,7 @@ PASS: gdb.threads/attach-stopped.exp: threaded: set file, before attach1 to stopped process (re-read) PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach1 to stopped bt -FAIL: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped +PASS: gdb.threads/attach-stopped.exp: threaded: attach1, exit leaves process stopped PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped, after setting file PASS: gdb.threads/attach-stopped.exp: threaded: attach2 to stopped bt PASS: gdb.threads/attach-stopped.exp: continue (threaded: attach2 continue) I'll try to schedule it on a few other ppc64 systems to see if make any difference. CAI Qian From srikar at linux.vnet.ibm.com Mon Nov 30 12:03:45 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 30 Nov 2009 17:33:45 +0530 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. Message-ID: <20091130120345.GA18879@linux.vnet.ibm.com> Hi, This patch implements an in-kernel gdb stub. It provides an interface between gdb and Linux Kernel by implementing the remote serial protocol. This gdbstub uses utrace infrastructure. This patch provides register set access, signal mapping, process event handling, input/output operations. /proc//gdb was chosen as file for gdb to interact with the process through remote serial protocol. Hence users would have to use "target remote /proc//gdb" command on gdb prompt to start using this infrastructure. For Breakpointing support, gdbstub needs User space breakpointing layer and uprobes layer which will be posted later. Here is an illustration of what all this can do. $ pgrep zsh 8865 $ gdb /bin/zsh GNU gdb (GDB) 7.0.0.20091030 ..... ............... For bug reporting instructions, please see: ... Reading symbols from /bin/zsh...Reading symbols from /usr/lib/debug/bin/zsh.debug...done. (no debugging symbols found)...done. (gdb) target remote /proc/8865/gdb Remote debugging using /proc/8865/gdb .... ...... Loaded symbols for /usr/lib64/zsh/4.2.6/zsh/zle.so 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 (gdb) c Continuing. ^C Program received signal SIGINT, Interrupt. 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 (gdb) info registers rax 0xfffffffffffffe00 -512 rbx 0x6a01c8 6947272 rcx 0xffffffffffffffff -1 rdx 0x1 1 rsi 0x7fff507ad5ef 140734543615471 rdi 0xa 10 rbp 0x0 0x0 rsp 0x7fff507ad3e8 0x7fff507ad3e8 r8 0xffffffff 4294967295 r9 0xffffffff 4294967295 r10 0x7d 125 r11 0x246 582 r12 0x7f43b87a9398 139928834577304 r13 0x0 0 r14 0x0 0 r15 0xd 13 rip 0x3f1dec5f00 0x3f1dec5f00 <__read_nocancel+7> eflags 0x246 [ PF ZF IF ] cs 0x33 51 ss 0x2b 43 ds 0x0 0 es 0x0 0 fs 0x0 0 gs 0x0 0 fctrl 0x0 0 fstat 0x0 0 ftag 0x0 0 fiseg 0x0 0 fioff 0x0 0 foseg 0x0 0 fooff 0x0 0 fop 0x0 0 mxcsr 0x0 [ ] (gdb) bt #0 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 #1 0x00007f43b858a39f in raw_getkey (keytmout=0) at /usr/include/bits/unistd.h:35 #2 getkey (keytmout=0) at zle_main.c:610 #3 0x00007f43b8584bf1 in getkeybuf (km=0x0, funcp=0x7fff507ad718, strp=0x7fff507ad710) at zle_keymap.c:1313 #4 getkeymapcmd (km=0x0, funcp=0x7fff507ad718, strp=0x7fff507ad710) at zle_keymap.c:1275 #5 0x00007f43b8584ef0 in getkeycmd () at zle_keymap.c:1349 #6 0x00007f43b8588281 in zlecore () at zle_main.c:695 #7 0x00007f43b85888f8 in zleread (lp=, rp=, flags=, context=) at zle_main.c:863 #8 0x00000000004388a0 in inputline () at input.c:278 #9 ingetc () at input.c:214 #10 0x000000000043339d in ihgetc () at hist.c:241 #11 0x000000000044126b in gettok () at lex.c:631 #12 0x0000000000441a88 in yylex () at lex.c:347 #13 0x000000000045cec7 in parse_event () at parse.c:449 #14 0x0000000000437328 in loop (toplevel=1, justonce=0) at init.c:128 #15 0x0000000000438021 in zsh_main (argc=, argv=0x7fff507ae048) at init.c:1280 #16 0x0000003f1de1d994 in __libc_start_main (main=, argc=, ubp_av=, init=, fini=, rtld_fini=, stack_end=Could not find the frame base for "__libc_start_main". ) at libc-start.c:231 #17 0x000000000040cc09 in _start () (gdb) c Continuing. ^C Program received signal SIGINT, Interrupt. 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 (gdb) bt #0 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 #1 0x00007f43b858a39f in raw_getkey (keytmout=0) at /usr/include/bits/unistd.h:35 #2 getkey (keytmout=0) at zle_main.c:610 #3 0x00007f43b8584bf1 in getkeybuf (km=0x0, funcp=0x7fff507ad718, strp=0x7fff507ad710) at zle_keymap.c:1313 #4 getkeymapcmd (km=0x0, funcp=0x7fff507ad718, strp=0x7fff507ad710) at zle_keymap.c:1275 #5 0x00007f43b8584ef0 in getkeycmd () at zle_keymap.c:1349 #6 0x00007f43b8588281 in zlecore () at zle_main.c:695 #7 0x00007f43b85888f8 in zleread (lp=, rp=, flags=, context=) at zle_main.c:863 #8 0x00000000004388a0 in inputline () at input.c:278 #9 ingetc () at input.c:214 #10 0x000000000043339d in ihgetc () at hist.c:241 #11 0x000000000044126b in gettok () at lex.c:631 #12 0x0000000000441a88 in yylex () at lex.c:347 #13 0x000000000045cec7 in parse_event () at parse.c:449 #14 0x0000000000437328 in loop (toplevel=1, justonce=0) at init.c:128 #15 0x0000000000438021 in zsh_main (argc=, argv=0x7fff507ae048) at init.c:1280 #16 0x0000003f1de1d994 in __libc_start_main (main=, argc=, ubp_av=, init=, fini=, rtld_fini=, stack_end=Could not find the frame base for "__libc_start_main". ) at libc-start.c:231 #17 0x000000000040cc09 in _start () (gdb) b zrefresh Breakpoint 1 at 0x7f43b858f600: file zle_refresh.c, line 278. ### Note: This is (gdb) c Continuing. ^C Program received signal SIGINT, Interrupt. 0x0000003f1dec5f00 in __read_nocancel () from /lib64/libc.so.6 (gdb) info b Num Type Disp Enb Address What 1 breakpoint keep y in zrefresh at zle_refresh.c:278 #### HERE breakpoint is still pending because, gdbstub needs more support for #### breakpointing. (gdb) (gdb) q A debugging session is active. Inferior 1 [Remote target] will be killed. Quit anyway? (y or n) y $ pgrep zsh 8865 $ I request you to please review this and lets us know your comments. Signed-off-by: "Frank Ch. Eigler" Signed-off-by: Srikar Dronamraju --- fs/proc/base.c | 4 + include/linux/utrace.h | 4 + init/Kconfig | 26 +- kernel/Makefile | 1 + kernel/utrace-gdb.c | 1314 ++++++++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 1340 insertions(+), 9 deletions(-) diff --git a/fs/proc/base.c b/fs/proc/base.c index af643b5..98bf9b0 100644 --- a/fs/proc/base.c +++ b/fs/proc/base.c @@ -77,6 +77,7 @@ #include #include #include +#include #include #include #include @@ -2562,6 +2563,9 @@ static const struct pid_entry tgid_base_stuff[] = { #ifdef CONFIG_TASK_IO_ACCOUNTING INF("io", S_IRUGO, proc_tgid_io_accounting), #endif +#ifdef CONFIG_UTRACE_GDB + REG("gdb", S_IRUSR|S_IWUSR, proc_gdb_operations), +#endif }; static int proc_tgid_base_readdir(struct file * filp, diff --git a/include/linux/utrace.h b/include/linux/utrace.h index 23d934d..c78a365 100644 --- a/include/linux/utrace.h +++ b/include/linux/utrace.h @@ -726,4 +726,8 @@ static inline __must_check int utrace_barrier_pid(struct pid *pid, #endif /* CONFIG_UTRACE */ +#ifdef CONFIG_UTRACE_GDB +extern const struct file_operations proc_gdb_operations; +#endif + #endif /* linux/utrace.h */ diff --git a/init/Kconfig b/init/Kconfig index 10cbcf4..dd04f63 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -295,15 +295,6 @@ config AUDIT logging of avc messages output). Does not do system-call auditing without CONFIG_AUDITSYSCALL. -config UTRACE - bool "Infrastructure for tracing and debugging user processes" - depends on EXPERIMENTAL - depends on HAVE_ARCH_TRACEHOOK - help - Enable the utrace process tracing interface. This is an internal - kernel interface exported to kernel modules, to track events in - user threads, extract and change user thread state. - config AUDITSYSCALL bool "Enable system-call auditing support" depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH) @@ -1214,6 +1205,23 @@ config STOP_MACHINE help Need stop_machine() primitive. +menuconfig UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + +config UTRACE_GDB + bool "/proc//gdb file for gdb remote connection" + select UTRACE + default y + help + Enable the utrace-based /proc//gdb process debugging + interface, for connection using the gdb remote protocol. + source "block/Kconfig" config PREEMPT_NOTIFIERS diff --git a/kernel/Makefile b/kernel/Makefile index 8f41620..eb3679c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -69,6 +69,7 @@ obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o obj-$(CONFIG_UTRACE) += utrace.o +obj-$(CONFIG_UTRACE_GDB) += utrace-gdb.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ diff --git a/kernel/utrace-gdb.c b/kernel/utrace-gdb.c new file mode 100644 index 0000000..e721ae4 --- /dev/null +++ b/kernel/utrace-gdb.c @@ -0,0 +1,1314 @@ +/* + * utrace-based gdb remote protocol server for user processes + * + * Copyright (C) 2009 Red Hat, Inc. All rights reserved. + * Copyright (C) IBM Corporation, 2009 + * + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Frank Ch. Eigler + */ + +/* + * TODO list: + * + * floating-point register bank support for g/G/P/etc. packets + * multithreaded process support + * concurrent debugger support for same process + */ +#define DEBUG 1 + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * struct gdb_connection - Tracks one active gdb-process session. + */ + +#define GDB_BUFMAX 4096 +#define MAX_REG_WIDTH 16 /* Maximum Register Width */ + +struct gdb_connection { + pid_t target; + struct utrace_engine *engine; + + /* changed under output_mutex */ + int at_quiesce_do; + + /* set <=> at_quiesce_do = UTRACE_STOP */ + unsigned char stopcode[GDB_BUFMAX]; + int pass_signals; + int stop_signals; + /* XXX: per-thread later */ + + char output_buf[GDB_BUFMAX]; + size_t output_buf_size; + loff_t output_buf_read; + + /* Protects output_buf, at_quiesce_do */ + struct mutex output_mutex; + wait_queue_head_t output_wait; + + char input_buf[GDB_BUFMAX]; + size_t input_buf_size; + + /* Protects input_buf. */ + struct mutex input_mutex; + wait_queue_head_t input_wait; + + struct list_head link; +}; + +static LIST_HEAD(gdb_connections); +static DEFINE_MUTEX(gdb_connections_mutex); +static const struct utrace_engine_ops gdb_utrace_ops; + +/* ------------------------------------------------------------------------ */ + +/* + * Map from kernel-side signal numbers (include/asm/signal.h) to gdb + * remote protocol signal numbers (include/gdb/signals.h). + */ +unsigned gdb_signal_map[] = { + [SIGHUP] = 1, + [SIGINT] = 2, + [SIGQUIT] = 3, + [SIGILL] = 4, + [SIGTRAP] = 5, + [SIGABRT] = 6, + [SIGBUS] = 10, + [SIGFPE] = 8, + [SIGKILL] = 9, + [SIGUSR1] = 30, + [SIGSEGV] = 11, + [SIGUSR2] = 31, + [SIGPIPE] = 13, + [SIGALRM] = 14, + [SIGTERM] = 15, + [SIGCHLD] = 20, + [SIGCONT] = 19, + [SIGSTOP] = 17, + [SIGTSTP] = 18, + [SIGTTIN] = 21, + [SIGTTOU] = 22, + [SIGURG] = 16, + [SIGXCPU] = 24, + [SIGXFSZ] = 25, + [SIGVTALRM] = 26, + [SIGPROF] = 27, + [SIGWINCH] = 28, + [SIGIO] = 23, + [SIGPWR] = 32, + [SIGSYS] = 12, +}; + +/* + * Map the incoming signo to TARGET_SIGNAL_foo, if possible. If not, + * pass it through. + */ +static unsigned map_signal_kern2gdb(unsigned kernel_signo) +{ + if (kernel_signo < sizeof(gdb_signal_map) / sizeof(unsigned)) + return gdb_signal_map[kernel_signo] ? : kernel_signo; + return kernel_signo; +} + +static unsigned map_signal_gdb2kern(unsigned gdb_signo) +{ + unsigned i; + for (i = 0; i < sizeof(gdb_signal_map) / sizeof(unsigned); i++) + if (gdb_signal_map[i] == gdb_signo) + return i; + return gdb_signo; +} + +/* ------------------------------------------------------------------------ */ + +static unsigned byteme(unsigned char hex1, unsigned char hex2) +{ + return (isdigit(hex1) ? hex1 - '0' : tolower(hex1) - 'a' + 10) * 16 + + (isdigit(hex2) ? hex2 - '0' : tolower(hex2) - 'a' + 10); +} + +/* ------------------------------------------------------------------------ */ + +/* + * Begin a new packet. Add the $, and remember where we put it. Return + * the offset for later checksum addition via push_output_packet_end. + */ +static size_t push_output_packet_start(struct gdb_connection *p) +{ + size_t start = p->output_buf_size; + + BUG_ON(p->output_buf_size + 1 >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = '$'; + return start; +} + +/* Add a character to the output queue. Assumes output_mutex held. */ +static void push_output(struct gdb_connection *p, unsigned char c) +{ + /* + * We know some space must exist; we check for this in + * proc_gdb_write() for example. + */ + BUG_ON(p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = c; +} + +/* Lower case use due to http://sourceware.org/bugzilla/show_bug.cgi?id=9665 */ +static char hex[] = "0123456789abcdef"; + +/* Add a byte (hexified) to the output queue. Assumes output_mutex held. */ +static void push_output_hex(struct gdb_connection *p, unsigned char c) +{ + /* + * We know some space must exist; we check for this in + * proc_gdb_write() for example. + */ + BUG_ON(p->output_buf_size >= GDB_BUFMAX); + p->output_buf[p->output_buf_size++] = hex[(c & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(c & 0x0f) >> 0]; +} + +/* + * Finish the last packet. Starting after the given '$' offset, compute + * the checksum and append it. + */ +static void push_output_packet_end(struct gdb_connection *p, size_t start) +{ + unsigned char checksum = 0; + int i; + + BUG_ON(p->output_buf_size + 3 >= GDB_BUFMAX); + BUG_ON(p->output_buf[start] != '$'); + + for (i = start + 1; i < p->output_buf_size; i++) + checksum += p->output_buf[i]; + + p->output_buf[p->output_buf_size++] = '#'; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0xf0) >> 4]; + p->output_buf[p->output_buf_size++] = hex[(checksum & 0x0f) >> 0]; +} + +/* Add a complete packet payload to the output queue. */ +static void push_output_packet(struct gdb_connection *p, const char *s) +{ + size_t ss = strlen(s); + size_t start; + int i; + + start = push_output_packet_start(p); + for (i = 0; i < ss; i++) + push_output(p, s[i]); + push_output_packet_end(p, start); +} + +static inline struct gdb_connection *find_gdb_connection( + struct task_struct *task) +{ + struct gdb_connection *gc = NULL; + + mutex_lock(&gdb_connections_mutex); + list_for_each_entry(gc, &gdb_connections, link) { + if (gc->target == task_tgid_nr(task)) + goto out_connection; + } + +out_connection: + mutex_unlock(&gdb_connections_mutex); + return gc; +} + +/* utrace callbacks */ + +u32 gdb_utrace_report_quiesce(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, unsigned long event) +{ + struct gdb_connection *p = engine->data; + + pr_debug("report_quiesce %d event 0x%lx 0x%x->0x%x\n", task->pid, + event, action, p->at_quiesce_do); + + return p->at_quiesce_do; +} + +u32 gdb_utrace_report_clone(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *parent, + unsigned long clone_flags, + struct task_struct *child) +{ + pr_debug("report_clone %d->%d\n", parent->pid, child->pid); + + if (clone_flags & CLONE_THREAD) { + printk(KERN_WARNING + "unsupported multithreading on /proc/%d/gdb.\n", + task_pid_nr(parent)); + } + /* XXX: is there anything else to do here? */ + return UTRACE_RESUME; +} + +u32 gdb_utrace_report_exec(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + /* XXX: Model an exec as if it were an exit. */ + struct gdb_connection *p = engine->data; + + pr_debug("report_exec %d->%s\n", task->pid, task->comm); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_STOP; + snprintf(p->stopcode, GDB_BUFMAX, "W%02x", 0); + push_output_packet(p, p->stopcode); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + /* + * Suspend the exec operation, to ensure that the connected gdb + * receives the notification packet, and lets us go. + */ + return UTRACE_STOP; +} + +u32 gdb_utrace_report_signal(u32 action, + struct utrace_engine *engine, + struct task_struct *task, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct gdb_connection *p = engine->data; + u32 ret = action; + + mutex_lock(&p->output_mutex); + + pr_debug("report_signal %d (0x%x) skip %d stop %d\n", + task->pid, action, p->pass_signals, p->stop_signals); + + /* + * The target is about to receive a signal. There are several + * cases: + * + * 1) This is an ordinary signal. We UTRACE_STOP to notify gdb. + * + * 2a) This is a SIGTRAP arising from a singlestep arising from + * another tracing entity. Or a breakpoint is disarmed. + * We UTRACE_RESUME. + * + * 2b) This is a SIGTRAP but not from a singlestep. + * We UTRACE_STOP to pass it to gdb. + * + * Both case 2a, 2b are yet to be implemented. + * + * 3) This is a UTRACE_SIGNAL_REPORT our code injected to stop the + * process, as per UTRACE_INTERRUPT. + * We UTRACE_STOP | UTRACE_SIGNAL_IGN. + * + * 4) This is a signal our code injected on behalf of gdb via the + * C/S/I packets. We recognize this from p->pass_signals. + * We UTRACE_RESUME. + * + * 5) This is a UTRACE_SIGNAL_HANDLER event. UTRACE_RESUME. + */ + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: /* case 5 */ + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME | utrace_signal_action(action); + break; + + case UTRACE_SIGNAL_REPORT: + case UTRACE_SIGNAL_DELIVER: + case UTRACE_SIGNAL_IGN: /* XXX: bother notify? */ + case UTRACE_SIGNAL_TERM: + case UTRACE_SIGNAL_CORE: + case UTRACE_SIGNAL_STOP: + case UTRACE_SIGNAL_TSTP: + if (!orig_ka) { /* case 3 */ + /* This should be UTRACE_SIGNAL_REPORT */ + if (p->stop_signals > 0) { + p->stop_signals = 0; + /* Indicate as if thread received a SIGINT */ + snprintf(p->stopcode, GDB_BUFMAX, "S%02x", 2); + push_output_packet(p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + ret = UTRACE_STOP | UTRACE_SIGNAL_IGN; + } else + ret = p->at_quiesce_do | + utrace_signal_action(action); + + break; + } + if (p->pass_signals > 0) { /* case 4 */ + p->pass_signals--; + p->at_quiesce_do = UTRACE_RESUME; + ret = UTRACE_RESUME | utrace_signal_action(action); + } else { /* case 1 */ + snprintf(p->stopcode, GDB_BUFMAX, "S%02x", + map_signal_kern2gdb(info->si_signo)); + push_output_packet(p, p->stopcode); + p->at_quiesce_do = UTRACE_STOP; + ret = UTRACE_STOP | utrace_signal_action(action); + } + break; + } + + pr_debug("action 0x%x\n", ret); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + return ret; +} + +u32 gdb_utrace_report_exit(enum utrace_resume_action action, + struct utrace_engine *engine, + struct task_struct *task, + long orig_code, long *code) +{ + struct gdb_connection *p = engine->data; + + pr_debug("report_exit %d (%lx)\n", task->pid, orig_code); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_STOP; + snprintf(p->stopcode, GDB_BUFMAX, + "W%02x", (unsigned)(orig_code & 0xFF)); + push_output_packet(p, p->stopcode); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + + /* + * Suspend the exit operation, to ensure that the connected gdb + * receives the notification packet, and lets us go. + */ + return UTRACE_STOP; +} + +u32 gdb_utrace_report_death(struct utrace_engine *engine, + struct task_struct *task, bool group_dead, int signal) +{ + struct gdb_connection *p = engine->data; + + pr_debug("report_death %d (%d)\n", task->pid, signal); + + mutex_lock(&p->output_mutex); + + p->at_quiesce_do = UTRACE_DETACH; + snprintf(p->stopcode, GDB_BUFMAX, "X%2x", (unsigned)(signal & 0xFF)); + push_output_packet(p, p->stopcode); + + mutex_unlock(&p->output_mutex); + wake_up(&p->output_wait); + return UTRACE_DETACH; +} + +static const struct utrace_engine_ops gdb_utrace_ops = { + .report_quiesce = gdb_utrace_report_quiesce, + .report_signal = gdb_utrace_report_signal, + .report_death = gdb_utrace_report_death, + .report_exit = gdb_utrace_report_exit, + .report_exec = gdb_utrace_report_exec, + .report_clone = gdb_utrace_report_clone, + /* XXX: syscall trapping is also possible. */ +}; + +/* + * XXX: arch-dependent lookup of gdb remote protocol register + * numbering. The register numbers (user-side) & expected sizes come + * from gdb's regformats/FOO-linux.dat. The regset (kernel-side) + * numbers could come from offsetof/sizeof constructs based upon each + * arch's asm/user*.h. + */ + +struct gdb_map_regset { + unsigned pos; /* regset offset */ + unsigned count; /* regset byte count */ + unsigned rsn; /* regset number */ + unsigned bytes; /* gdb's view of register width; <= count */ +}; + +struct gdb_map_regset arch_i386_map_regset[] = { + [0] = { /* eax */ 6 * 4, 4, NT_PRSTATUS, 4,}, + [1] = { /* ecx */ 1 * 4, 4, NT_PRSTATUS, 4,}, + [2] = { /* edx */ 2 * 4, 4, NT_PRSTATUS, 4,}, + [3] = { /* ebx */ 0 * 4, 4, NT_PRSTATUS, 4,}, + [4] = { /* esp */ 15 * 4, 4, NT_PRSTATUS, 4,}, + [5] = { /* ebp */ 5 * 4, 4, NT_PRSTATUS, 4,}, + [6] = { /* esi */ 3 * 4, 4, NT_PRSTATUS, 4,}, + [7] = { /* edi */ 4 * 4, 4, NT_PRSTATUS, 4,}, + [8] = { /* eip */ 12 * 4, 4, NT_PRSTATUS, 4,}, + [9] = { /* eflags */ 14 * 4, 4, NT_PRSTATUS, 4,}, + [10] = { /* cs */ 13 * 4, 4, NT_PRSTATUS, 4,}, + [11] = { /* ss */ 16 * 4, 4, NT_PRSTATUS, 4,}, + [12] = { /* ds */ 7 * 4, 4, NT_PRSTATUS, 4,}, + [13] = { /* es */ 8 * 4, 4, NT_PRSTATUS, 4,}, + [14] = { /* fs */ 9 * 4, 4, NT_PRSTATUS, 4,}, + [15] = { /* gs */ 10 * 4, 4, NT_PRSTATUS, 4,}, + [16] = { /* st0 */ 0, 0, NT_PRFPREG, 10,}, + [17] = { /* st1 */ 0, 0, NT_PRFPREG, 10,}, + [18] = { /* st2 */ 0, 0, NT_PRFPREG, 10,}, + [19] = { /* st3 */ 0, 0, NT_PRFPREG, 10,}, + [20] = { /* st4 */ 0, 0, NT_PRFPREG, 10,}, + [21] = { /* st5 */ 0, 0, NT_PRFPREG, 10,}, + [22] = { /* st6 */ 0, 0, NT_PRFPREG, 10,}, + [23] = { /* st7 */ 0, 0, NT_PRFPREG, 10,}, + [24] = { /* fctrl */ 0, 0, NT_PRFPREG, 4,}, + [25] = { /* fstat */ 0, 0, NT_PRFPREG, 4,}, + [26] = { /* ftag */ 0, 0, NT_PRFPREG, 4,}, + [27] = { /* fiseg */ 0, 0, NT_PRFPREG, 4,}, + [28] = { /* fioff */ 0, 0, NT_PRFPREG, 4,}, + [29] = { /* foseg */ 0, 0, NT_PRFPREG, 4,}, + [30] = { /* fooff */ 0, 0, NT_PRFPREG, 4,}, + [31] = { /* fop */ 0, 0, NT_PRFPREG, 4,}, + [32] = { /* xmm0 */ 0, 0, NT_PRFPREG, 16,}, + [33] = { /* xmm1 */ 0, 0, NT_PRFPREG, 16,}, + [34] = { /* xmm2 */ 0, 0, NT_PRFPREG, 16,}, + [35] = { /* xmm3 */ 0, 0, NT_PRFPREG, 16,}, + [36] = { /* xmm4 */ 0, 0, NT_PRFPREG, 16,}, + [37] = { /* xmm5 */ 0, 0, NT_PRFPREG, 16,}, + [38] = { /* xmm6 */ 0, 0, NT_PRFPREG, 16,}, + [39] = { /* xmm7 */ 0, 0, NT_PRFPREG, 16,}, + [40] = { /* mxcsr */ 0, 0, NT_PRFPREG, 4,}, + [41] = { /* orig_eax */ 0, 0, NT_PRSTATUS, 4,}, +}; + +struct gdb_map_regset arch_x86_64_map_regset[] = { + [0] = { /* rax */ 10 * 8, 8, NT_PRSTATUS, 8,}, + [1] = { /* rbx */ 5 * 8, 8, NT_PRSTATUS, 8,}, + [2] = { /* rcx */ 11 * 8, 8, NT_PRSTATUS, 8,}, + [3] = { /* rdx */ 12 * 8, 8, NT_PRSTATUS, 8,}, + [4] = { /* rsi */ 13 * 8, 8, NT_PRSTATUS, 8,}, + [5] = { /* rdi */ 14 * 8, 8, NT_PRSTATUS, 8,}, + [6] = { /* rbp */ 4 * 8, 8, NT_PRSTATUS, 8,}, + [7] = { /* rsp */ 19 * 8, 8, NT_PRSTATUS, 8,}, + [8] = { /* r8 */ 9 * 8, 8, NT_PRSTATUS, 8,}, + [9] = { /* r9 */ 8 * 8, 8, NT_PRSTATUS, 8,}, + [10] = { /* r10 */ 7 * 8, 8, NT_PRSTATUS, 8,}, + [11] = { /* r11 */ 6 * 8, 8, NT_PRSTATUS, 8,}, + [12] = { /* r12 */ 3 * 8, 8, NT_PRSTATUS, 8,}, + [13] = { /* r13 */ 2 * 8, 8, NT_PRSTATUS, 8,}, + [14] = { /* r14 */ 1 * 8, 8, NT_PRSTATUS, 8,}, + [15] = { /* r15 */ 0 * 8, 8, NT_PRSTATUS, 8,}, + [16] = { /* rip */ 16 * 8, 8, NT_PRSTATUS, 8,}, + [17] = { /* flags */ 18 * 8, 8, NT_PRSTATUS, 4,}, + [18] = { /* cs */ 17 * 8, 8, NT_PRSTATUS, 4,}, + [19] = { /* ss */ 20 * 8, 8, NT_PRSTATUS, 4,}, + [20] = { /* ds */ 23 * 8, 8, NT_PRSTATUS, 4,}, + [21] = { /* es */ 24 * 8, 8, NT_PRSTATUS, 4,}, + [22] = { /* fs */ 25 * 8, 8, NT_PRSTATUS, 4,}, + [23] = { /* gs */ 26 * 8, 8, NT_PRSTATUS, 4,}, + [24] = { /* st0 */ 0, 0, NT_PRFPREG, 10,}, + [25] = { /* st1 */ 0, 0, NT_PRFPREG, 10,}, + [26] = { /* st2 */ 0, 0, NT_PRFPREG, 10,}, + [27] = { /* st3 */ 0, 0, NT_PRFPREG, 10,}, + [28] = { /* st4 */ 0, 0, NT_PRFPREG, 10,}, + [29] = { /* st5 */ 0, 0, NT_PRFPREG, 10,}, + [30] = { /* st6 */ 0, 0, NT_PRFPREG, 10,}, + [31] = { /* st7 */ 0, 0, NT_PRFPREG, 10,}, + [32] = { /* fctrl */ 0, 0, NT_PRFPREG, 4,}, + [33] = { /* fstat */ 0, 0, NT_PRFPREG, 4,}, + [34] = { /* ftag */ 0, 0, NT_PRFPREG, 4,}, + [35] = { /* fiseg */ 0, 0, NT_PRFPREG, 4,}, + [36] = { /* fioff */ 0, 0, NT_PRFPREG, 4,}, + [37] = { /* foseg */ 0, 0, NT_PRFPREG, 4,}, + [38] = { /* fooff */ 0, 0, NT_PRFPREG, 4,}, + [39] = { /* fop */ 0, 0, NT_PRFPREG, 4,}, + [40] = { /* xmm0 */ 0, 0, NT_PRFPREG, 16,}, + [41] = { /* xmm1 */ 0, 0, NT_PRFPREG, 16,}, + [42] = { /* xmm2 */ 0, 0, NT_PRFPREG, 16,}, + [43] = { /* xmm3 */ 0, 0, NT_PRFPREG, 16,}, + [44] = { /* xmm4 */ 0, 0, NT_PRFPREG, 16,}, + [45] = { /* xmm5 */ 0, 0, NT_PRFPREG, 16,}, + [46] = { /* xmm6 */ 0, 0, NT_PRFPREG, 16,}, + [47] = { /* xmm7 */ 0, 0, NT_PRFPREG, 16,}, + [48] = { /* xmm8 */ 0, 0, NT_PRFPREG, 16,}, + [49] = { /* xmm9 */ 0, 0, NT_PRFPREG, 16,}, + [50] = { /* xmm10 */ 0, 0, NT_PRFPREG, 16,}, + [51] = { /* xmm11 */ 0, 0, NT_PRFPREG, 16,}, + [52] = { /* xmm12 */ 0, 0, NT_PRFPREG, 16,}, + [53] = { /* xmm13 */ 0, 0, NT_PRFPREG, 16,}, + [54] = { /* xmm14 */ 0, 0, NT_PRFPREG, 16,}, + [55] = { /* xmm15 */ 0, 0, NT_PRFPREG, 16,}, + [56] = { /* mxcsr */ 0, 0, NT_PRFPREG, 4,}, + [57] = { /* orig_rax */ 15 * 8, 8, NT_PRSTATUS, 8,}, +}; + +static int gdb_remote_register_info(struct gdb_connection *p, + struct task_struct *task, + unsigned number, + unsigned *pos, unsigned *count, + unsigned *bytes) +{ + const struct user_regset_view *rs = task_user_regset_view(task); + int rsn = -1; + + if (rs == 0) + return -ENOENT; + +#define GMRSIZE (sizeof(struct gdb_map_regset)) + + if (rs->e_machine == EM_386) { + if (number < sizeof(arch_i386_map_regset) / GMRSIZE) { + *pos = arch_i386_map_regset[number].pos; + *count = arch_i386_map_regset[number].count; + *bytes = arch_i386_map_regset[number].bytes; + rsn = arch_i386_map_regset[number].rsn; + } + } else if (rs->e_machine == EM_X86_64) { + if (number < sizeof(arch_x86_64_map_regset) / GMRSIZE) { + *pos = arch_x86_64_map_regset[number].pos; + *count = arch_x86_64_map_regset[number].count; + *bytes = arch_x86_64_map_regset[number].bytes; + rsn = arch_x86_64_map_regset[number].rsn; + } + } + /* else ... rsn stays -1. */ +#undef GMRSIZE + + /* + * Now map to the per-architecture regset index, based on the + * elf core_note_type we found. + */ + if (rsn >= 0) { + unsigned j; + for (j = 0; j < rs->n; j++) { + if (rs->regsets[j].core_note_type == rsn) + return j; + } + } + + /* + * Invalid machines, register numbers, rsns, or unset rsns all + * fall through here. + */ + return -ENOENT; +} + +static inline int fetch_remote_register_info(struct gdb_connection *p, + struct task_struct *task, + int index, + unsigned *pos, + unsigned *count, + unsigned *bytes) +{ + int rsn; + + rsn = gdb_remote_register_info(p, task, index, pos, count, bytes); + pr_debug("gdb register %u => rsn %d p%u c%u b%u\n", index, rsn, + *pos, *count, *bytes); + if (rsn > 0) { + /* + * If we want to extract register data, make sure we're + * fetching at least that much. + */ + BUG_ON(*count > 0 && *count < *bytes); + /* Assert reg_contents size is right. */ + BUG_ON(MAX_REG_WIDTH < *bytes || MAX_REG_WIDTH < *count); + } + return rsn; +} + +static inline int get_set_regset_view(struct task_struct *task, + unsigned pos, unsigned count, + unsigned char *reg_contents, + int rsn, bool set) +{ + int rc; + const struct user_regset_view *rsv; + const struct user_regset *rs; + + if (!count) { + if (!set) + memset(reg_contents, 0, MAX_REG_WIDTH); + return 0; + } + + /* real register */ + if (set) + BUG_ON(count > MAX_REG_WIDTH); + + rsv = task_user_regset_view(task); + BUG_ON(rsn >= rsv->n); + rs = &rsv->regsets[rsn]; + + /* Extract the register values into reg_contents[]. */ + if (set) + rc = (rs->set)(task, rs, pos, count, reg_contents, NULL); + else + rc = (rs->get)(task, rs, pos, count, reg_contents, NULL); + + return rc; +} + +static inline void prepare_regset_set(struct gdb_connection *p, + unsigned char *reg_contents, + size_t *start, unsigned bytes) +{ + int j; + + /* + * 0-fill the register copy. + * XXX initialize it from rs->get() instead? + */ + memset(reg_contents, 0, MAX_REG_WIDTH); + + /* + * Hex-unconvert all the bytes. + * XXX: endianness adjust for count != bytes + */ + for (j = 0; j < bytes; j++) + reg_contents[j] = byteme(p->input_buf[*start + 2 * j], + p->input_buf[*start + 2 * j + 1]); + *start += 2 * bytes; +} + +/* + * Process an entire, checksum-confirmed $command# at the front of + * p->input_buf[]. The input and output mutexes are being held. + */ +static void handle_gdb_command_packet(struct gdb_connection *p, + struct task_struct *task) +{ + unsigned long arg1, arg2, arg3; + size_t op_start; + int rc = 0; + int i, j; + + pr_debug("gdb packet code %c\n", p->input_buf[1]); + + switch (p->input_buf[1]) { + case '?': + if (p->at_quiesce_do != UTRACE_STOP) { + /* shouldn't happen */ + p->stop_signals++; + rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + /* + * Note that we don't enqueue a reply packet here, + * but make gdb wait for a response from the + * utrace report_FOO callbacks. + */ + } else { + push_output_packet(p, p->stopcode); + } + break; + + case 'i': /* [ADDR[,NNN]] */ + case 's': /* [ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'c': /* [ADDR] */ + rc = sscanf(&p->input_buf[2], "%lx,%lx", &arg1, &arg2); + /* XXX: args ignored */ + p->stopcode[0] = '\0'; + p->at_quiesce_do = + ((p->input_buf[1] == 'c' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals++; + rc = utrace_control(task, p->engine, p->at_quiesce_do); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + break; + case 'C': /* SIG[;ADDR] */ + case 'S': /* SIG[;ADDR] */ + /* XXX: if !arch_has_single_step() ... then what? */ + case 'I': /* SIG[;ADDR[,NNN?]] */ + rc = sscanf(&p->input_buf[2], "%lx;%lx,%lx", &arg1, &arg2, + &arg3); + if (rc >= 1) /* SIG present */ + send_sig(map_signal_gdb2kern(arg1), task, 1); + + p->pass_signals++; + p->stopcode[0] = '\0'; + p->at_quiesce_do = + ((p->input_buf[1] == 'C' || !arch_has_single_step()) + ? UTRACE_RESUME : UTRACE_SINGLESTEP); + if (p->at_quiesce_do == UTRACE_SINGLESTEP) + p->stop_signals++; + + rc = utrace_control(task, p->engine, p->at_quiesce_do); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + + /* Response will come at next report_signal. */ + break; + case 'D': + push_output_packet(p, "OK"); + /* NB: proc_gdb_release() performs actual utrace detach. */ + break; + case 'g': + op_start = push_output_packet_start(p); + + /* + * GDB_BUFMAX stands for some random large number, + * known to be larger than the number of gdb indexed + * registers. + */ + for (i = 0; i < GDB_BUFMAX; i++) { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + int rsn; + unsigned char reg_contents[MAX_REG_WIDTH]; + + rsn = fetch_remote_register_info(p, task, i, + &rs_pos, &rs_count, &bytes); + if (rsn < 0) + break; + + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, false); + if (rc) + break; + + /* + * Hex-dump it. + * XXX: endianness adjust for count != bytes + */ + for (j = 0; j < bytes; j++) { + /* pr_debug("%02x", reg_contents[j]); */ + push_output_hex(p, reg_contents[j]); + } + /* pr_debug(")\n"); */ + + } + push_output_packet_end(p, op_start); + break; + case 'G': + i = 0; + op_start = 2; /* use as input pointer, past $G in command */ + while (p->input_buf[op_start] != '#' && + op_start < p->input_buf_size) { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + int rsn; + unsigned char reg_contents[MAX_REG_WIDTH]; + + rsn = fetch_remote_register_info(p, task, i, + &rs_pos, &rs_count, &bytes); + if (rsn < 0) + break; + + /* Remaining packet too short? */ + if ((op_start + 2 * bytes + 3) < p->input_buf_size) + break; + + prepare_regset_set(p, reg_contents, &op_start, bytes); + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, true); + if (rc) + break; + } + if (p->input_buf[op_start] == '#' && rc == 0) + push_output_packet(p, "OK"); + else + push_output_packet(p, "E01"); + + break; + case 'p': /* REG */ + push_output_packet(p, "E01"); + break; + case 'P': /* REG=VAL */ + /* `i' will index p->input_buf to consume VAL hex bytes. */ + rc = sscanf(&p->input_buf[2], "%lx=%n", &arg1, &i); + op_start = i + 2; /* Skip the leading $P also */ + if (rc != 1) { + push_output_packet(p, "E01"); + } else { + unsigned rs_count; + unsigned rs_pos; + unsigned bytes; + int rsn; + unsigned char reg_contents[MAX_REG_WIDTH]; + + rsn = fetch_remote_register_info(p, task, arg1, + &rs_pos, &rs_count, &bytes); + if (rsn < 0) + break; + + /* Remaining packet too short? */ + if ((op_start + 2 * bytes + 3) < p->input_buf_size) + break; + + prepare_regset_set(p, reg_contents, &op_start, bytes); + rc = get_set_regset_view(task, rs_pos, rs_count, + reg_contents, rsn, true); + WARN_ON(rc); + if (p->input_buf[op_start] == '#' && rc == 0) + push_output_packet(p, "OK"); + else + push_output_packet(p, "E01"); + } + break; + case 'm': /* ADDR,LENGTH */ + rc = sscanf(&p->input_buf[2], "%lx,%lx", &arg1, &arg2); + if (rc != 2) + push_output_packet(p, "E01"); + else { + size_t o = push_output_packet_start(p); + while (arg2 > 0) { + unsigned char value; + + /* + * Simply stop looping if requested length + * was too large. gdb will probably retry + * from this point on. + */ + if (p->output_buf_size + 5 > GDB_BUFMAX) + break; + + rc = access_process_vm(task, arg1, &value, 1, + 0); + if (rc != 1) + break; /* EFAULT */ + else + push_output_hex(p, value); + + arg1++; + arg2--; + } + push_output_packet_end(p, o); + } + break; + case 'M': /* ADDR,LENGTH:XX */ + /* `i' will index p->input_buf to consume XX hex bytes. */ + rc = sscanf(&p->input_buf[2], "%lx,%lx:%n", &arg1, &arg2, &i); + op_start = i + 2; /* Skip the leading $M also. */ + if (rc < 2) { + push_output_packet(p, "E01"); + break; + } + while (arg2 > 0) { + unsigned char value; + + /* + * Check that enough input bytes left for + * these two hex chars, plus the #XX checksum. + */ + if (i + 4 >= p->input_buf_size) + break; + + value = byteme(p->input_buf[i], p->input_buf[i + 1]); + rc = access_process_vm(task, arg1, &value, 1, 1); + if (rc != 1) + break; /* EFAULT */ + + i += 2; + arg1++; + arg2--; + } + if (arg2 != 0) + push_output_packet(p, "E02"); + else + push_output_packet(p, "OK"); + + break; + case 'Z': /* TYPE,ADDR,LENGTH */ + /* Not yet implemented */ + push_output_packet(p, "E03"); + break; + case 'z': /* TYPE,ADDR,LENGTH */ + /* Not yet implemented */ + push_output_packet(p, "E03"); + break; + + default: + push_output_packet(p, ""); + } +} + +/* ------------------------------------------------------------------------ */ + +/* gdb control callbacks */ + +#define get_proc_task(inode) get_pid_task(PROC_I((inode))->pid, PIDTYPE_PID) + +static int proc_gdb_open(struct inode *inode, struct file *filp) +{ + struct task_struct *task = get_proc_task(inode); + int ret = -EBUSY; + struct gdb_connection *p; + + pr_debug("opened /proc/%d/gdb\n", task->pid); + + /* Reject kernel threads. */ + if (task->flags & PF_KTHREAD) { + ret = -EINVAL; + goto out; + } + + /* Reject if connection is for other than tg-leader thread. */ + if (task_pid_nr(task) != task_tgid_nr(task)) { + ret = -EINVAL; + goto out; + } + + mutex_lock(&gdb_connections_mutex); + + /* + * Reject if a connection exists for the thread group + * leader. + */ + list_for_each_entry(p, &gdb_connections, link) { + if (p->target == task_tgid_nr(task)) { + ret = -EBUSY; + goto out_mutex; + } + } + /* (Don't unlock yet, to defeat a race of two concurrent opens.) */ + + p = kzalloc(sizeof(struct gdb_connection), GFP_KERNEL); + if (!p) { + ret = -ENOMEM; + goto out_mutex; + } + + /* Send initial ping to gdb. */ + push_output_packet(p, ""); + + mutex_init(&p->output_mutex); + init_waitqueue_head(&p->output_wait); + + mutex_init(&p->input_mutex); + init_waitqueue_head(&p->input_wait); + + /* + * NB: During attach, we don't want to bother the target. + * Soon though a send_sig will interrupt it. + */ + p->at_quiesce_do = UTRACE_RESUME; + p->target = task->tgid; + + p->engine = utrace_attach_task(task, + UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &gdb_utrace_ops, p); + if (IS_ERR(p->engine) || p->engine == NULL) { + ret = -EBUSY; + goto out_free; + } + + ret = utrace_set_events(task, p->engine, + UTRACE_EVENT_SIGNAL_ALL | + UTRACE_EVENT(QUIESCE) | + UTRACE_EVENT(DEATH) | + UTRACE_EVENT(EXIT) | + UTRACE_EVENT(EXEC) | UTRACE_EVENT(CLONE)); + pr_debug("utrace_set_events sent, ret=%d\n", ret); + utrace_engine_put(p->engine); + filp->private_data = p; + + INIT_LIST_HEAD(&p->link); + list_add_tail(&p->link, &gdb_connections); + + p->stop_signals++; + ret = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + + goto out_mutex; + +out_free: + kfree(p); +out_mutex: + mutex_unlock(&gdb_connections_mutex); +out: + return ret; +} + +static int proc_gdb_release(struct inode *inode, struct file *filp) +{ + struct task_struct *task = get_proc_task(inode); + struct gdb_connection *p = filp->private_data; + int ret = 0; + + mutex_lock(&gdb_connections_mutex); + if (task == NULL) { + /* Thread is already gone; report_death was already called. */ + pr_debug("gdb %d releasing old\n", p->target); + } else if (p->at_quiesce_do != UTRACE_DETACH) { + pr_debug("gdb %d releasing current\n", p->target); + + ret = utrace_set_events(task, p->engine, 0); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + + /* + * No more callbacks will be received! + * Detach implies Resume + */ + ret = utrace_control(task, p->engine, UTRACE_DETACH); + if (ret == -EINPROGRESS) + ret = utrace_barrier(task, p->engine); + } + + list_del(&p->link); + mutex_unlock(&gdb_connections_mutex); + + kfree(p); + return ret; +} + +static int proc_gdb_ioctl(struct inode *inode, struct file *file, + unsigned int cmd, unsigned long arg) +{ + /* + * XXX: GDB usually thinks that a file name for "target + * remote" implies a serial port with tty-ish ioctl's + * available. We pretend to accept them all. + */ + return 0; +} + +static ssize_t proc_gdb_read(struct file *filp, char __user * buf, + size_t count, loff_t *ppos) +{ + struct gdb_connection *p = filp->private_data; + struct task_struct *task; + int rc = 0; + size_t len; + + task = find_task_by_vpid(p->target); + if (!task) + return -EINVAL; + + if ((p->output_buf_size <= p->output_buf_read) && + filp->f_flags & O_NONBLOCK) + return -EAGAIN; + +again: + rc = wait_event_interruptible(p->output_wait, + (p->output_buf_size > + p->output_buf_read)); + if (rc) + goto out; + + mutex_lock(&p->output_mutex); + + if (p->output_buf_size <= p->output_buf_read) { + mutex_unlock(&p->output_mutex); + goto again; + } + len = min(count, (size_t) (p->output_buf_size - p->output_buf_read)); + if (copy_to_user(buf, &p->output_buf[p->output_buf_read], len)) { + rc = -EFAULT; + goto out_unlock; + } + + pr_debug("sent %u bytes (%ld left) data (%.*s)\n", + (unsigned)len, + ((long)p->output_buf_size - (long)p->output_buf_read) - len, + (int)len, &p->output_buf[p->output_buf_read]); + + p->output_buf_read += len; + rc = len; + + /* If whole packet is consumed, reset for next one. */ + BUG_ON(p->output_buf_read > p->output_buf_size); + if (p->output_buf_read == p->output_buf_size) { + p->output_buf_read = 0; + p->output_buf_size = 0; + } + +out_unlock: + mutex_unlock(&p->output_mutex); + +out: + return rc; +} + +static ssize_t proc_gdb_write(struct file *filp, const char __user * buf, + size_t count, loff_t *ppos) +{ + struct gdb_connection *p = filp->private_data; + size_t last_input_buf_size; + struct task_struct *task; + size_t len; + int ret = 0; + + task = find_task_by_vpid(p->target); + if (!task) + return -EINVAL; + +again: + ret = wait_event_interruptible(p->input_wait, + (p->input_buf_size < GDB_BUFMAX)); + if (ret) + goto out; + + mutex_lock(&p->input_mutex); + if (p->input_buf_size == GDB_BUFMAX) { + mutex_unlock(&p->input_mutex); + goto again; + } + mutex_lock(&p->output_mutex); + + /* We now know there is some room in the input buffer. Upon + entry, the input_buf will either be empty, or contain a + partial gdb request packet. */ + + /* Copy the data. */ + len = min(count, (size_t) (GDB_BUFMAX - p->input_buf_size)); + if (copy_from_user(&p->input_buf[p->input_buf_size], buf, len)) { + ret = -EFAULT; + goto out_unlock; + } + + /* + * pr_debug("received data %.*s\n", (int)len, + * &p->input_buf[p->input_buf_size]); + */ + + p->input_buf_size += len; + ret = len; + + /* + * Process any packets in the buffer to restore the incoming + * invariant. (Normal GDB will not send more than one packet before + * waiting for a response.) + */ + + /* + * We iterate until we can no longer shrink the input buffer. + * Usually we will not iterate more than once, since there may be + * one +/- ack byte and/or one gdb packet. + */ + last_input_buf_size = 0; + while (p->input_buf_size && p->input_buf_size != last_input_buf_size) { + last_input_buf_size = p->input_buf_size; + + if (p->input_buf[0] == '+') { + /* + * This must have been an ack to our + * previously output packet. + * Consume the input. + */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == '-') { + /* + * Whoops, a nak. Unfortunately, we don't + * handle transmission errors by + * retransmitting the last output_buf; it's + * already gone. OTOH we should not encounter + * transmission errors on a reliable channel + * such as a read syscall. + * Consume the input. + */ + printk(KERN_WARNING "Unexpected NAK received" + "on /proc/%d/gdb connection.\n", + task_pid_nr(task)); + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == 3) { /* ^C == INTR */ + int rc; /* NB: don't overwrite 'ret'. */ + pr_debug("received gdb interrupt\n"); + p->stop_signals++; + rc = utrace_control(task, p->engine, UTRACE_INTERRUPT); + if (rc == -EINPROGRESS) + rc = utrace_barrier(task, p->engine); + + /* + * p->at_quiesce_do will be set in + * report_signal(SIGNAL_REPORT). NB: this packet + * does not generate an +/- ack. Consume the input. + */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } else if (p->input_buf[0] == '$') { /* command packet */ + int j; + unsigned char checksum = 0; + unsigned char checksum2; + for (j = 1; j < p->input_buf_size - 2; j++) { + if (p->input_buf[j] != '#') { + checksum += p->input_buf[j]; + continue; + } + checksum2 = byteme(p->input_buf[j + 1], + p->input_buf[j + 2]); + pr_debug("received gdb packet %.*s\n", + j + 3, &p->input_buf[0]); + if (checksum == checksum2) { + push_output(p, '+'); + handle_gdb_command_packet(p, task); + } else + push_output(p, '-'); + + /* Consume the whole packet. */ + p->input_buf_size -= (j + 3); + memmove(&p->input_buf[0], &p->input_buf[j + 3], + p->input_buf_size); + break; + } /* End searching for end of packet */ + + /* + * We may not have found the # + * checksum. If so, leave the partial packet + * in input_buf. Since input_buf_size will + * not have decreased, the while() loop above + * will detect a fixpoint and exit. + * + * Alternately, there could be another gdb packet + * just behind the one we just consumed. In this + * we'll iterate one more time in this loop. + */ + } else { /* junk character */ + printk(KERN_WARNING "Unexpected character (%x) " + "received on /proc/%d/gdb connection.\n", + (int)p->input_buf[0], task_pid_nr(task)); + /* Consume the input. */ + memmove(&p->input_buf[0], &p->input_buf[1], + --p->input_buf_size); + } + } + +out_unlock: + /* Probably have more room in input_buf. */ + wake_up(&p->input_wait); + /* Probably have data in output_buf. */ + wake_up(&p->output_wait); + + mutex_unlock(&p->output_mutex); + mutex_unlock(&p->input_mutex); +out: + return ret; +} + +const struct file_operations proc_gdb_operations = { + .open = proc_gdb_open, + .read = proc_gdb_read, + .write = proc_gdb_write, + .release = proc_gdb_release, + .ioctl = proc_gdb_ioctl, +}; From peterz at infradead.org Mon Nov 30 12:09:12 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 30 Nov 2009 13:09:12 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130120345.GA18879@linux.vnet.ibm.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> Message-ID: <1259582952.20516.209.camel@laptop> On Mon, 2009-11-30 at 17:33 +0530, Srikar Dronamraju wrote: > This patch implements an in-kernel gdb stub. > It provides an interface between gdb and Linux Kernel by implementing > the remote serial protocol. This gdbstub uses utrace infrastructure. > This patch provides register set access, signal mapping, process event > handling, input/output operations. > > /proc//gdb was chosen as file for gdb to interact with the > process through remote serial protocol. > > Hence users would have to use "target remote /proc//gdb" command > on gdb prompt to start using this infrastructure. > > For Breakpointing support, gdbstub needs User space breakpointing > layer and uprobes layer which will be posted later. How does this compare to kgdb and related efforts? From srikar at linux.vnet.ibm.com Mon Nov 30 12:32:57 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 30 Nov 2009 18:02:57 +0530 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <1259582952.20516.209.camel@laptop> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> Message-ID: <20091130123257.GB18879@linux.vnet.ibm.com> * Peter Zijlstra [2009-11-30 13:09:12]: > On Mon, 2009-11-30 at 17:33 +0530, Srikar Dronamraju wrote: > > This patch implements an in-kernel gdb stub. > > It provides an interface between gdb and Linux Kernel by implementing > > the remote serial protocol. This gdbstub uses utrace infrastructure. > > This patch provides register set access, signal mapping, process event > > handling, input/output operations. > > > > /proc//gdb was chosen as file for gdb to interact with the > > process through remote serial protocol. > > > > Hence users would have to use "target remote /proc//gdb" command > > on gdb prompt to start using this infrastructure. > > > > For Breakpointing support, gdbstub needs User space breakpointing > > layer and uprobes layer which will be posted later. > > How does this compare to kgdb and related efforts? This is a In-kernel gdbstub to debug user space programs. This stub doesnt help in debugging kernel. Hence I am not sure how to compare kgdb gdbstub with this gdbstub. Can you please provide more pointers on what you were referring to? -- Thanks and Regards Srikar From peterz at infradead.org Mon Nov 30 12:41:47 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 30 Nov 2009 13:41:47 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130123257.GB18879@linux.vnet.ibm.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> Message-ID: <1259584907.20516.246.camel@laptop> On Mon, 2009-11-30 at 18:02 +0530, Srikar Dronamraju wrote: > * Peter Zijlstra [2009-11-30 13:09:12]: > > > On Mon, 2009-11-30 at 17:33 +0530, Srikar Dronamraju wrote: > > > This patch implements an in-kernel gdb stub. > > > It provides an interface between gdb and Linux Kernel by implementing > > > the remote serial protocol. This gdbstub uses utrace infrastructure. > > > This patch provides register set access, signal mapping, process event > > > handling, input/output operations. > > > > > > /proc//gdb was chosen as file for gdb to interact with the > > > process through remote serial protocol. > > > > > > Hence users would have to use "target remote /proc//gdb" command > > > on gdb prompt to start using this infrastructure. > > > > > > For Breakpointing support, gdbstub needs User space breakpointing > > > layer and uprobes layer which will be posted later. > > > > How does this compare to kgdb and related efforts? > > This is a In-kernel gdbstub to debug user space programs. > This stub doesnt help in debugging kernel. > > Hence I am not sure how to compare kgdb gdbstub with this gdbstub. > Can you please provide more pointers on what you were referring to? Well, not even that much was clear from your changelog, so I wasn't really sure wtf I was looking at. All it says was an in-kernel gdb stub, what other than to debug the kernel would you need in-kernel stubs for? So now my question is, what do you need an in-kernel stub to debug userspace for? In general, tell me about this patch thing, what does it do, why does it do it, and how does it improve on the current situation. Your changelog doesn't address any of those things, so wth are we supposed to think? From srikar at linux.vnet.ibm.com Mon Nov 30 13:19:28 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 30 Nov 2009 18:49:28 +0530 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <1259584907.20516.246.camel@laptop> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> Message-ID: <20091130131928.GC18879@linux.vnet.ibm.com> * Peter Zijlstra [2009-11-30 13:41:47]: > > > > This is a In-kernel gdbstub to debug user space programs. > > This stub doesnt help in debugging kernel. > > > > Hence I am not sure how to compare kgdb gdbstub with this gdbstub. > > Can you please provide more pointers on what you were referring to? > > Well, not even that much was clear from your changelog, so I wasn't > really sure wtf I was looking at. All it says was an in-kernel gdb stub, > what other than to debug the kernel would you need in-kernel stubs for? > > So now my question is, what do you need an in-kernel stub to debug > userspace for? > This stub would allow users use features provided by utrace but through a gdb interface. This idea was brought up in this year's Tracing roundtable at the Linux Foundation Collaboration summit, April 8-10 in San Francisco. Here is the link to the minutes of the meeting sent by Christoph Hellwig. http://www.mail-archive.com/utrace-devel at redhat.com/msg00830.html > In general, tell me about this patch thing, what does it do, why does it > do it, and how does it improve on the current situation. This is suppose to be one of the interfaces to use utrace, i.e Allow gdb to use utrace features without having to change gdb itself. Though there are not enough features in this patch, intentions include support multi-threaded debugging, concurrent debugger support for same process, syscall tracing. For Breakpoint support(not yet submitted to LKML), it would use execution out of line rather than the conventional inline-single stepping. I guess Christoph, Roland and Frank would be able to explain in a better fashion the rational and advantages of this stub over convential gdb. > > Your changelog doesn't address any of those things, so wth are we > supposed to think? Thanks for pointing out. -- Thanks and Regards Srikar From peterz at infradead.org Mon Nov 30 13:37:12 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 30 Nov 2009 14:37:12 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130131928.GC18879@linux.vnet.ibm.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> Message-ID: <1259588232.20516.307.camel@laptop> On Mon, 2009-11-30 at 18:49 +0530, Srikar Dronamraju wrote: > This is suppose to be one of the interfaces to use utrace, i.e Allow > gdb to use utrace features without having to change gdb itself. > Though there are not enough features in this patch, intentions include > support multi-threaded debugging, concurrent debugger support for same > process, syscall tracing. > > For Breakpoint support(not yet submitted to LKML), it would use > execution out of line rather than the conventional inline-single > stepping. > > I guess Christoph, Roland and Frank would be able to explain in a better > fashion the rational and advantages of this stub over convential gdb. Hmm,. wouldn't it make much more sense to extend the current kgdb stub to include userspace debugging, providing an all-in-one solution? I think it would be much more powerful to be able to observe the full software stack and not be limited by this user<->kernel barrier. (Provided the user has sufficient privileges of course). From srikar at linux.vnet.ibm.com Mon Nov 30 14:05:14 2009 From: srikar at linux.vnet.ibm.com (Srikar Dronamraju) Date: Mon, 30 Nov 2009 19:35:14 +0530 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <1259588232.20516.307.camel@laptop> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> Message-ID: <20091130140514.GD18879@linux.vnet.ibm.com> > > > > I guess Christoph, Roland and Frank would be able to explain in a better > > fashion the rational and advantages of this stub over convential gdb. > > Hmm,. wouldn't it make much more sense to extend the current kgdb stub > to include userspace debugging, providing an all-in-one solution? I see two limitations but I guess there could be ways to get over it. 1. gdb requiring file that needs to be debugged. I always thought it can either be a user program or a vmlinux file. gdb makes most of the information(i.e registers) from the remote protocol to display the backtrace, variable values and the like by reading this file. 2. Also I am not sure if gdb has a way to tell the remote to switch the context and provide information(registers) pertaining to the user mode/ kernel mode. There could be other limitations too that I may not be aware. > > I think it would be much more powerful to be able to observe the full > software stack and not be limited by this user<->kernel barrier. > > (Provided the user has sufficient privileges of course). In this implementation, the current user can debug his/her own processes. May be if we can debug both the context from same gdb then we might have to place restrictions.. -- Thanks and Regards Srikar > From fche at redhat.com Mon Nov 30 15:03:14 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Mon, 30 Nov 2009 10:03:14 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <1259588232.20516.307.camel@laptop> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> Message-ID: <20091130150314.GA10331@redhat.com> peterz wrote: > Hmm,. wouldn't it make much more sense to extend the current kgdb stub > to include userspace debugging, providing an all-in-one solution? > I think it would be much more powerful to be able to observe the full > software stack and not be limited by this user<->kernel barrier. There exist other tools for this broad a scope (systemtap being one), and present gdb is not well suited for this. That makes this idea an exciting potential for the future, but not a practical short-term goal. - FChE From peterz at infradead.org Mon Nov 30 15:11:36 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 30 Nov 2009 16:11:36 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130150314.GA10331@redhat.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> Message-ID: <1259593896.26472.89.camel@laptop> On Mon, 2009-11-30 at 10:03 -0500, Frank Ch. Eigler wrote: > peterz wrote: > > > Hmm,. wouldn't it make much more sense to extend the current kgdb stub > > to include userspace debugging, providing an all-in-one solution? > > I think it would be much more powerful to be able to observe the full > > software stack and not be limited by this user<->kernel barrier. > > There exist other tools for this broad a scope (systemtap being one), > and present gdb is not well suited for this. That makes this idea an > exciting potential for the future, but not a practical short-term > goal. Who's talking short-term? And if gdb is unsuited, it'll simply have to get fixed :-) From mingo at elte.hu Mon Nov 30 15:16:50 2009 From: mingo at elte.hu (Ingo Molnar) Date: Mon, 30 Nov 2009 16:16:50 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130150314.GA10331@redhat.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> Message-ID: <20091130151650.GA24316@elte.hu> * Frank Ch. Eigler wrote: > peterz wrote: > > > Hmm,. wouldn't it make much more sense to extend the current kgdb stub > > to include userspace debugging, providing an all-in-one solution? > > I think it would be much more powerful to be able to observe the full > > software stack and not be limited by this user<->kernel barrier. > > There exist other tools for this broad a scope (systemtap being one), > and present gdb is not well suited for this. That makes this idea an > exciting potential for the future, but not a practical short-term > goal. Well, but Peter's suggestion is the obvious next step - or even a necessary first step in my view. kgdb exists here and today in the kernel and you cannot just build a facility that doesnt replace it and doesnt integrate well with it. So if a unified user/kernel model for debugging is a 'long term' feature in your view then perhaps this framework (which introduces _extensive_ hooks all around the kernel) is not designed/approached in the right way and should not be merged in this form. Concentrating on 'other tools' just generates extensive dependencies on something that is lacking - making it even harder to implement unified debugging down the line. Thanks, Ingo From fche at redhat.com Mon Nov 30 15:29:10 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Mon, 30 Nov 2009 10:29:10 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130151650.GA24316@elte.hu> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> Message-ID: <20091130152910.GB10331@redhat.com> On Mon, Nov 30, 2009 at 04:16:50PM +0100, Ingo Molnar wrote: > [...] > kgdb exists here and today in the kernel and you cannot just build a > facility that doesnt replace it and doesnt integrate well with it. Surely you don't mean that: every non-kgdb facility in the kernel meets that definition, even all debugging-related facilities such as perf and ftrace. > So if a unified user/kernel model for debugging is a 'long term' > feature in your view then perhaps this framework (which introduces > _extensive_ hooks all around the kernel) is not designed/approached > in the right way and should not be merged in this form. Which "this framework" are you talking about? Please clarify what exactly you're trying to say. - FChE From oleg at redhat.com Mon Nov 30 17:07:26 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 30 Nov 2009 18:07:26 +0100 Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: <20091130044448.9D134D6D2@magilla.sf.frob.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> <20091130044448.9D134D6D2@magilla.sf.frob.com> Message-ID: <20091130170726.GA4421@redhat.com> On 11/29, Roland McGrath wrote: > > Please file this test case on bugzilla.redhat.com for Fedora 12 glibc. https://bugzilla.redhat.com/show_bug.cgi?id=542731 Oleg. From oleg at redhat.com Mon Nov 30 20:00:56 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 30 Nov 2009 21:00:56 +0100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <1259541801.2076.44.camel@pasglop> References: <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> <1259536501.2076.39.camel@pasglop> <1259541801.2076.44.camel@pasglop> Message-ID: <20091130200056.GA11764@redhat.com> On 11/30, Benjamin Herrenschmidt wrote: > > On Mon, 2009-11-30 at 10:15 +1100, Benjamin Herrenschmidt wrote: > > > Yes, the asm should be changed. I suppose we could check if the result > > of do_syscall_trace_enter is negative, and if it is, branch to the exit > > path using r3 as the error code. Would that be ok ? > > > > Something like this: > > Note however that there's a trace exit too and that's normally the right > place to alter the result don't you think ? Yes, the result can be changed when the tracee reports syscall-exit. Should powerpc allow this on syscall-entry? I do not know. x86 does, and we have this test-case which assumes powerpc should allow too. But when it comes to ptrace I can almost never know what was the supposed behaviour/api. Jan, Roland, what do you think? Oleg. From oleg at redhat.com Mon Nov 30 20:01:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 30 Nov 2009 21:01:36 +0100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <1259536501.2076.39.camel@pasglop> References: <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> <1259536501.2076.39.camel@pasglop> Message-ID: <20091130200136.GB11764@redhat.com> On 11/30, Benjamin Herrenschmidt wrote: > > On Sun, 2009-11-29 at 22:07 +0100, Oleg Nesterov wrote: > > > > If I change the test-case to use NEWVAL == 1000 (or any other value > > greater than NR_syscalls), then the tracee sees ENOSYS and this is > > correct too. > > > > But I do not see how it is possible to change the retcode on powerpc. > > Unlike x86, powepc doesn't set -ENOSYS "in advance", before doing > > do_syscall_trace_enter() logic. This means that if the tracer "cancels" > > syscall, r3 will be overwritten by syscall_enosys. > > > > This probably means the kernel should be fixed too, but I am not > > brave enough to change the asm which I can't understand ;) > > Yes, the asm should be changed. I suppose we could check if the result > of do_syscall_trace_enter is negative, and if it is, branch to the exit > path using r3 as the error code. Would that be ok ? > > Something like this: > > --- a/arch/powerpc/kernel/entry_64.S > +++ b/arch/powerpc/kernel/entry_64.S > @@ -240,6 +240,9 @@ syscall_dotrace: > bl .save_nvgprs > addi r3,r1,STACK_FRAME_OVERHEAD > bl .do_syscall_trace_enter > + cmpdi cr0,r3,0 > + blt syscall_exit > + Yes, but this doesn't allow to a) cancel this syscall and b) make it return a non-negative result to the tracee. Perhaps poweprc should set pt_regs->result = -ENOSYS before calling do_syscall_trace_enter() like x86 does ? (in this case syscall_exit() shouldn't change RESULT(r1)). This way the tracer can change both pt_regs->result and gpr[0] independently. Oleg. From pubcoolgift at lifecooler.com Tue Dec 1 04:26:18 2009 From: pubcoolgift at lifecooler.com (Coolgift) Date: Tue, 1 Dec 2009 04:26:18 -0000 Subject: =?windows-1252?q?Ofere=E7a_as_melhores_experi=EAncias_de_Portuga?= =?windows-1252?q?l_com_a_garantia_Lifecooler?= Message-ID: An HTML attachment was scrubbed... URL: From mingo at elte.hu Tue Dec 1 16:11:32 2009 From: mingo at elte.hu (Ingo Molnar) Date: Tue, 1 Dec 2009 17:11:32 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091130152910.GB10331@redhat.com> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> Message-ID: <20091201161132.GA24897@elte.hu> * Frank Ch. Eigler wrote: > On Mon, Nov 30, 2009 at 04:16:50PM +0100, Ingo Molnar wrote: > > [...] > > kgdb exists here and today in the kernel and you cannot just build a > > facility that doesnt replace it and doesnt integrate well with it. > > Surely you don't mean that: every non-kgdb facility in the kernel > meets that definition, even all debugging-related facilities such as > perf and ftrace. Those facilities are not overlapping with kgdb though so my point doesnt apply to them. An in-kernel gdb server sure overlaps/extends kgdb though. Btw., perf does meet that definition: it functionally replaces all facilities that it overlaps/extends - such as Oprofile. 'What about Oprofile?' was one of the first questions asked when we posted perf. 'What about kgdb?' is the first question to the in-kernel gdb stub submission here, for similar reasons. Ingo From vfalico at redhat.com Tue Dec 1 16:37:48 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Tue, 1 Dec 2009 17:37:48 +0100 Subject: [PATCH] ptrace-tests: fix step-fork.c on powerpc for ptrace-utrace Message-ID: <20091201163748.GA5635@darkmag.usersys.redhat.com> Instead of using fork(), call syscall(__NR_fork) in step-fork.c to avoid looping on powerpc arch in libc. Signed-off-by: Veaceslav Falico --- --- ptrace-tests/tests/step-fork.c 2009-12-01 17:17:14.000000000 +0100 +++ ptrace-tests/tests/step-fork.c 2009-12-01 17:25:12.000000000 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifndef PTRACE_SINGLESTEP @@ -78,7 +79,12 @@ main (int argc, char **argv) sigprocmask (SIG_BLOCK, &mask, NULL); ptrace (PTRACE_TRACEME); raise (SIGUSR1); - if (fork () == 0) + + /* + * We can't use fork() directly because on powerpc it loops inside libc on + * ptrace over utrace. See http://lkml.org/lkml/2009/11/28/11 + */ + if (syscall(__NR_fork) == 0) { read (-1, NULL, 0); _exit (22); From fche at redhat.com Tue Dec 1 17:00:02 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 1 Dec 2009 12:00:02 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091201161132.GA24897@elte.hu> References: <20091130120345.GA18879@linux.vnet.ibm.com> <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> Message-ID: <20091201170002.GD10331@redhat.com> Hi - On Tue, Dec 01, 2009 at 05:11:32PM +0100, Ingo Molnar wrote: > Those facilities are not overlapping with kgdb though so my point doesnt > apply to them. An in-kernel gdb server sure overlaps/extends kgdb > though. Only in name. One is highly invasive, for debugging the kernel across serial consoles. The other is highly noninvasive, for debugging user processes across normal userspace channels. They both happen to talk to gdb, but that's the end of the natural "overlap". Even if kgdb was extended to be able to manage userspace, and if gdb itself was extended to be able to use that same single channel, this would still not duplicate the use scenario for an ordinary user debugging his own processes. (Plus, in the future where at least gdb is applied toward kernel+user debugging, it is unlikely to be the case that this would need to be done *over a single channel*. A separate channel for kernel and separate channels for userspace programs are no less likely.) > Btw., perf does meet that definition: it functionally replaces all > facilities that it overlaps/extends - such as Oprofile. [...] (And they currently separately coexist.) - FChE From oleg at redhat.com Tue Dec 1 16:58:45 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Dec 2009 17:58:45 +0100 Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: <20091130170726.GA4421@redhat.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> <20091130044448.9D134D6D2@magilla.sf.frob.com> <20091130170726.GA4421@redhat.com> Message-ID: <20091201165845.GA9251@redhat.com> On 11/30, Oleg Nesterov wrote: > > On 11/29, Roland McGrath wrote: > > > > Please file this test case on bugzilla.redhat.com for Fedora 12 glibc. > > https://bugzilla.redhat.com/show_bug.cgi?id=542731 It was closed as NOTABUG, Andreas Schwab wrote: > > If you call clone directly you are responsible for setting up > the TLS area yourself. Very nice. If I understand correctly, this means clone(CLONE_VM) must not be used without CLONE_SETTLS, right? This in turn means clone(CLONE_VM) is not useable, afaics it is not possible to use CLONE_SETTLS in a more or less portable manner. Even arch/x86/ needs "struct user_desc *" or "long addr" depending on CONFIG_X86_32. And it used to work? I downloaded glibc-2.11, and afaics this was broken by Preserve SSE registers in runtime relocations on x86-64. commit: b48a267b8fbb885191a04cffdb4050a4d4c8a20b I do not understand glibc even remotely, but this lools like regression to me. I see nothing in the changelog or man page which explains that CLONE_VM requires CLONE_SETTLS now. So. Any ptrace test which uses clone() is broken, at least on x86_64. Jan, Roland, how should we fix this? We can rewrite the code to use pthread_create(), this should be trivial. Unfortunately, libpthread is not trivial, it can shadow the problem and complicate the testing. And the stupid question. If I create the subthread via pthread_create(), how can I know its tid? I grepped glibc-2.11, and afaics pthread_create returns the pointer to "struct pthread" which has "pid_t tid" but I can not find the helper which returns ->tid and "struct pthread" is not exported. Oleg. From mingo at elte.hu Tue Dec 1 17:09:54 2009 From: mingo at elte.hu (Ingo Molnar) Date: Tue, 1 Dec 2009 18:09:54 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091201170002.GD10331@redhat.com> References: <1259582952.20516.209.camel@laptop> <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> Message-ID: <20091201170954.GA4699@elte.hu> * Frank Ch. Eigler wrote: > Hi - > > On Tue, Dec 01, 2009 at 05:11:32PM +0100, Ingo Molnar wrote: > > > Those facilities are not overlapping with kgdb though so my point > > doesnt apply to them. An in-kernel gdb server sure overlaps/extends > > kgdb though. > > Only in name. One is highly invasive, for debugging the kernel across > serial consoles. The other is highly noninvasive, for debugging user > processes across normal userspace channels. They both happen to talk > to gdb, but that's the end of the natural "overlap". > > Even if kgdb was extended to be able to manage userspace, and if gdb > itself was extended to be able to use that same single channel, this > would still not duplicate the use scenario for an ordinary user > debugging his own processes. > > (Plus, in the future where at least gdb is applied toward kernel+user > debugging, it is unlikely to be the case that this would need to be > done *over a single channel*. A separate channel for kernel and > separate channels for userspace programs are no less likely.) Well nothing that you mention here changes our obvious suggestion that an in-kernel gdb stub should obviously either be a kgdb extension, or a replacement of it. We dont want to separate facilities for the same conceptual thing: examining application state (be that in user-space and kernel-space). > > Btw., perf does meet that definition: it functionally replaces all > > facilities that it overlaps/extends - such as Oprofile. [...] > > (And they currently separately coexist.) You didnt get my point apparently. Keeping the overlapped facility for compatibility (and general user inertia) is fine. Creating a new facility that doesnt do everything that the existing facility does, and not integrating it either, is not fine. Which was both Peter's and my point really. Ingo From vfalico at redhat.com Tue Dec 1 17:24:57 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Tue, 1 Dec 2009 18:24:57 +0100 Subject: [PATCH] ptrace-tests: fix step-fork.c on powerpc for ptrace-utrace In-Reply-To: <20091201163748.GA5635@darkmag.usersys.redhat.com> References: <20091201163748.GA5635@darkmag.usersys.redhat.com> Message-ID: <20091201172457.GB31242@darkmag.usersys.redhat.com> On Tue, Dec 01, 2009 at 05:37:48PM +0100, Veaceslav Falico wrote: > > - if (fork () == 0) > + > + /* > + * We can't use fork() directly because on powerpc it loops inside libc on > + * ptrace over utrace. See http://lkml.org/lkml/2009/11/28/11 > + */ > + if (syscall(__NR_fork) == 0) > { > read (-1, NULL, 0); > _exit (22); > Sorry, the comment is just wrong. I'll resend the patch in several minutes. -- Veaceslav From vfalico at redhat.com Tue Dec 1 17:38:27 2009 From: vfalico at redhat.com (Veaceslav Falico) Date: Tue, 1 Dec 2009 18:38:27 +0100 Subject: [PATCH v2] ptrace-tests: fix step-fork.c on powerpc for ptrace-utrace In-Reply-To: <20091201172457.GB31242@darkmag.usersys.redhat.com> References: <20091201163748.GA5635@darkmag.usersys.redhat.com> <20091201172457.GB31242@darkmag.usersys.redhat.com> Message-ID: <20091201173827.GC31242@darkmag.usersys.redhat.com> Instead of using fork(), call syscall(__NR_fork) in step-fork.c to avoid looping on powerpc arch in libc. Signed-off-by: Veaceslav Falico --- --- a/ptrace-tests/tests/step-fork.c 2009-12-01 17:17:14.000000000 +0100 +++ b/ptrace-tests/tests/step-fork.c 2009-12-01 18:35:15.000000000 +0100 @@ -29,6 +29,7 @@ #include #include #include +#include #include #ifndef PTRACE_SINGLESTEP @@ -78,7 +79,12 @@ main (int argc, char **argv) sigprocmask (SIG_BLOCK, &mask, NULL); ptrace (PTRACE_TRACEME); raise (SIGUSR1); - if (fork () == 0) + + /* + * Can't use fork() directly because on powerpc it loops inside libc under + * PTRACE_SINGLESTEP. See http://marc.info/?l=linux-kernel&m=125927241130695 + */ + if (syscall(__NR_fork) == 0) { read (-1, NULL, 0); _exit (22); From fche at redhat.com Tue Dec 1 17:45:34 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 1 Dec 2009 12:45:34 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091201170954.GA4699@elte.hu> References: <20091130123257.GB18879@linux.vnet.ibm.com> <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> Message-ID: <20091201174534.GE10331@redhat.com> Hi - > > Only in name. One is highly invasive, for debugging the kernel across > > serial consoles. The other is highly noninvasive, for debugging user > > processes across normal userspace channels. They both happen to talk > > to gdb, but that's the end of the natural "overlap". > [...] > Well nothing that you mention here changes our obvious suggestion that > an in-kernel gdb stub should obviously either be a kgdb extension, or a > replacement of it. Help me out here: by "kgdb extension" do you imagine "something new that an unprivileged user can use to debug his own process"? Or do you imagine a new userspace facility that single-steps the kernel? > We dont want to separate facilities for the same conceptual thing: > examining application state (be that in user-space and > kernel-space). This seems like a shallow sort of consistency. kgdb was added after ptrace existed -- why not extend ptrace instead to target the kernel? After all, it's "examining application state". The answer is that it doesn't make a heck of a lot of sense. > > > Btw., perf does meet that definition: it functionally replaces all > > > facilities that it overlaps/extends - such as Oprofile. [...] > > > > (And they currently separately coexist.) > > You didnt get my point apparently. Keeping the overlapped facility for > compatibility (and general user inertia) is fine. Creating a new > facility that doesnt do everything that the existing facility does, and > not integrating it either, is not fine. oprofile and perfctr are closer in concept than kgdb and ptrace, yet AFAIK perfctr doesn't "interface" to oprofile, except perhaps to the extent of resolving contention over the underlying physical resources. In any case this is not a great analogy. - FChE From roland at redhat.com Tue Dec 1 19:27:50 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 1 Dec 2009 11:27:50 -0800 (PST) Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: Oleg Nesterov's message of Monday, 30 November 2009 21:01:36 +0100 <20091130200136.GB11764@redhat.com> References: <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> <1259536501.2076.39.camel@pasglop> <20091130200136.GB11764@redhat.com> Message-ID: <20091201192750.4A1291DE@magilla.sf.frob.com> We don't really intend to impose any new requirements on the arch behavior here. It's up to the arch folks to decide. It does simplify life somewhat on x86 that you can change the registers at the syscall-entry stop and then after skipping the syscall, those registers will be unchanged from what you set. But it's never been that way on every other arch, and it doesn't need to be. The arch requirement on the tracehook_report_syscall_entry() return value handling is that it make the syscall not be run, and that the register state then left be compatible with using syscall_rollback() at the tracehook_report_syscall_exit() spot. As to what you get from ptrace explicitly fiddling with registers at syscall entry, that has always been arch-specific before and we haven't done anything to change that situation. On every arch, there is some way to change the syscall number to be run, and changing it to a known-bogus number (e.g. -1) makes sure no syscall runs. On every arch, it's possible at the tracehook_report_syscall_exit() spot to change the registers to exactly whatever you want userland to see. That's enough as it stands to make it possible to do whatever you want, some way or other. If the powerpc maintainers want to change the behavior here, that is fine by me. But there is no need for that just to satisfy general ptrace cleanups (or utrace). Normal concerns require that no such change break the ptrace behavior that userland could have relied on in the past. So off hand I don't see a reason to change at all. If every arch were to change so that registers changed at syscall-entry were left unmolested by aborting the syscall, then that might be a new consistency worth having. But short of that, I don't really see a benefit. All this implies that the ptrace-tests case relating to this needs to be tailored differently for powerpc and each other arch so it expects and verifies exactly the arch-specific behavior that's been seen in the past. Thanks, Roland From roland at redhat.com Tue Dec 1 19:39:40 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 1 Dec 2009 11:39:40 -0800 (PST) Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: Oleg Nesterov's message of Tuesday, 1 December 2009 17:58:45 +0100 <20091201165845.GA9251@redhat.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> <20091130044448.9D134D6D2@magilla.sf.frob.com> <20091130170726.GA4421@redhat.com> <20091201165845.GA9251@redhat.com> Message-ID: <20091201193940.154EF1DE@magilla.sf.frob.com> > So. Any ptrace test which uses clone() is broken, at least on x86_64. If you use clone() directly then you need to have the code run in that child be purely under your control. You can't use miscellaneous libc calls nor any libpthread calls, only ones you are sure do not require any thread setup. Given TLS, that means even using errno or anything that might set it. It also means any libc function that might use any TLS you don't know about, i.e. really anything beyond the pure computation calls like str*/mem*. It also means running any dynamic linker code, such as relying on dynamic linking without LD_BIND_NOW (or -Wl,-z,now at compile time). The only thing that changed about this recently in glibc is that even more code paths through the dynamic linker now happen to depend on thread setup. > Jan, Roland, how should we fix this? We can rewrite the code to use > pthread_create(), this should be trivial. Unfortunately, libpthread > is not trivial, it can shadow the problem and complicate the testing. We should avoid library code more thoroughly, not use more of it. As well as being complex, it also varies a lot across systems and interferes with using the same sources to translate to exact kernel-level testing across various people's development environments. I think the best bet is to link with -Wl,-z,now and then minimize the library code you rely on. (It really only matters to be extra careful about that for the code running in the clone child.) So you can use syscall() if you are not relying on its error-case behavior--if the system call fails, the function will set errno, which can rely on the TLS setup. > And the stupid question. If I create the subthread via pthread_create(), > how can I know its tid? I grepped glibc-2.11, and afaics pthread_create > returns the pointer to "struct pthread" which has "pid_t tid" but I can > not find the helper which returns ->tid and "struct pthread" is not > exported. There is no official exported way. You can use syscall(__NR_gettid). That kernel concept of a global thread ID number does not exist in pthreads, it is a detail of the Linux implementation. Thanks, Roland From peterz at infradead.org Tue Dec 1 19:54:02 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Tue, 01 Dec 2009 20:54:02 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091124200220.GA5828@redhat.com> References: <20091124200220.GA5828@redhat.com> Message-ID: <1259697242.1697.1075.camel@laptop> On Tue, 2009-11-24 at 21:02 +0100, Oleg Nesterov wrote: > + Final callbacks > + > + The report_reap callback is always the final event > + in the life cycle of a traced thread. Tracing engines can use this as > + the trigger to clean up their own data structures. The > + report_death callback is always the penultimate > + event a tracing engine might see; it's seen unless the thread was > + already in the midst of dying when the engine attached. Many tracing > + engines will have no interest in when a parent reaps a dead process, > + and nothing they want to do with a zombie thread once it dies; for > + them, the report_death callback is the natural > + place to clean up data structures and detach. To facilitate writing > + such engines robustly, given the asynchrony of > + SIGKILL, and without error-prone manual > + implementation of synchronization schemes, the > + utrace infrastructure provides some special > + guarantees about the report_death and > + report_reap callbacks. It still takes some care > + to be sure your tracing engine is robust to tear-down races, but these > + rules make it reasonably straightforward and concise to handle a lot of > + corner cases correctly. > + > + This above text seems inconsistent. First you say report_reap() is the final callback and should be used for cleanup, then you say report_death() is the penultimate callback but might not always happen and people would normally use that as cleanup. If we cannot rely on report_death() then I would suggest to simply recommend report_reap() as cleanup callback and leave it at that. > + > + There is nothing a kernel module can do to keep a struct > + task_struct alive outside of > + rcu_read_lock. Sure there is, get_task_struct() comes to mind. > When the task dies and is reaped > + by its parent (or itself), that structure can be freed so that any > + dangling pointers you have stored become invalid. > + utrace will not prevent this, but it can > + help you detect it safely. By definition, a task that has been reaped > + has had all its engines detached. All > + utrace calls can be safely called on a > + detached engine if the caller holds a reference on that engine pointer, > + even if the task pointer passed in the call is invalid. All calls > + return -ESRCH for a detached engine, which tells > + you that the task pointer you passed could be invalid now. Since > + utrace_control and > + utrace_set_events do not block, you can call those > + inside a rcu_read_lock section and be sure after > + they don't return -ESRCH that the task pointer is > + still valid until rcu_read_unlock. The > + infrastructure never holds task references of its own. And here you imply its existence. > Though neither > + rcu_read_lock nor any other lock is held while > + making a callback, it's always guaranteed that the struct > + task_struct and the struct > + utrace_engine passed as arguments remain valid > + until the callback function returns. > + > + > + > + The common means for safely holding task pointers that is available to > + kernel modules is to use struct pid, which > + permits put_pid from kernel modules. When using > + that, the calls utrace_attach_pid, > + utrace_control_pid, > + utrace_set_events_pid, and > + utrace_barrier_pid are available. > + The above seems weird to me at best... why hold a pid around when you can keep a ref on the task struct? A pid might get reused leaving you with a completely different task than you thought you had. > + > + > + > + > + Serialization of <constant>DEATH</constant> and <constant>REAP</constant> > + > + > + The second guarantee is the serialization of > + DEATH and REAP event > + callbacks for a given thread. The actual reaping by the parent > + (release_task call) can occur simultaneously > + while the thread is still doing the final steps of dying, including > + the report_death callback. If a tracing engine > + has requested both DEATH and > + REAP event reports, it's guaranteed that the > + report_reap callback will not be made until > + after the report_death callback has returned. > + If the report_death callback itself detaches > + from the thread, then the report_reap callback > + will never be made. Thus it is safe for a > + report_death callback to clean up data > + structures and detach. > + > + Right, except you cannot generally rely on this report_death() thing, so a trace engine needs to deal with the report_reap() thing anyway. > + Interlock with final callbacks > + > + The final sort of guarantee is that a tracing engine will know for sure > + whether or not the report_death and/or > + report_reap callbacks will be made for a certain > + thread. These tear-down races are disambiguated by the error return > + values of utrace_set_events and > + utrace_control. Normally > + utrace_control called with > + UTRACE_DETACH returns zero, and this means that no > + more callbacks will be made. If the thread is in the midst of dying, > + it returns -EALREADY to indicate that the > + report_death callback may already be in progress; > + when you get this error, you know that any cleanup your > + report_death callback does is about to happen or > + has just happened--note that if the report_death > + callback does not detach, the engine remains attached until the thread > + gets reaped. If the thread is in the midst of being reaped, > + utrace_control returns -ESRCH > + to indicate that the report_reap callback may > + already be in progress; this means the engine is implicitly detached > + when the callback completes. This makes it possible for a tracing > + engine that has decided asynchronously to detach from a thread to > + safely clean up its data structures, knowing that no > + report_death or report_reap > + callback will try to do the same. utrace_detach > + returns -ESRCH when the struct > + utrace_engine has already been detached, but is > + still a valid pointer because of its reference count. A tracing engine > + can use this to safely synchronize its own independent multiple threads > + of control with each other and with its event callbacks that detach. > + > + > + > + In the same vein, utrace_set_events normally > + returns zero; if the target thread was stopped before the call, then > + after a successful call, no event callbacks not requested in the new > + flags will be made. It fails with -EALREADY if > + you try to clear UTRACE_EVENT(DEATH) when the > + report_death callback may already have begun, if > + you try to clear UTRACE_EVENT(REAP) when the > + report_reap callback may already have begun, or if > + you try to newly set UTRACE_EVENT(DEATH) or > + UTRACE_EVENT(QUIESCE) when the target is already > + dead or dying. Like utrace_control, it returns > + -ESRCH when the thread has already been detached > + (including forcible detach on reaping). This lets the tracing engine > + know for sure which event callbacks it will or won't see after > + utrace_set_events has returned. By checking for > + errors, it can know whether to clean up its data structures immediately > + or to let its callbacks do the work. > + > + Hrmm, better mention this earlier, or at least refer to this when describing the above cleanup bits. > + > + One task can examine another only after a callback in the target task that > + returns UTRACE_STOP so that task will not return to user > + mode after the safe point. This guarantees that the task will not resume > + until the same engine uses utrace_control, unless the > + task dies suddenly. To examine safely, one must use a pair of calls to > + utrace_prepare_examine and > + utrace_finish_examine surrounding the calls to > + struct user_regset functions or direct examination > + of task data structures. utrace_prepare_examine returns > + an error if the task is not properly stopped and not dead. 'or' dead? > After a > + successful examination, the paired utrace_finish_examine > + call returns an error if the task ever woke up during the examination. If > + so, any data gathered may be scrambled and should be discarded. This means > + there was a spurious wake-up (which should not happen), or a sudden death. > + > @@ -351,6 +394,10 @@ static inline void tracehook_report_vfor > */ > static inline void tracehook_prepare_release_task(struct task_struct *task) > { > + /* see utrace_add_engine() about this barrier */ > + smp_mb(); > + if (task_utrace_flags(task)) > + utrace_release_task(task); > } OK, that seems to properly order ->exit_state vs ->utrace_flags, This site does: assign ->state mb observe ->utrace_flags and the other site does: assign ->utrace_flags mb observe ->exit_state > @@ -560,6 +625,20 @@ static inline void tracehook_report_deat > int signal, void *death_cookie, > int group_dead) > { > + /* > + * This barrier ensures that our caller's setting of > + * @task->exit_state precedes checking @task->utrace_flags here. > + * If utrace_set_events() was just called to enable > + * UTRACE_EVENT(DEATH), then we are obliged to call > + * utrace_report_death() and not miss it. utrace_set_events() > + * uses tasklist_lock to synchronize enabling the bit with the > + * actual change to @task->exit_state, but we need this barrier > + * to be sure we see a flags change made just before our caller > + * took the tasklist_lock. > + */ > + smp_mb(); > + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) > + utrace_report_death(task, death_cookie, group_dead, signal); > } I don't think its allowed to pair a mb with a lock-barrier, since the lock barriers are semi-permeable. > @@ -589,10 +668,20 @@ static inline void set_notify_resume(str > * asynchronously, this will be called again before we return to > * user mode. > * > - * Called without locks. > + * Called without locks. However, on some machines this may be > + * called with interrupts disabled. > */ > static inline void tracehook_notify_resume(struct pt_regs *regs) > { > + struct task_struct *task = current; > + /* > + * This pairs with the barrier implicit in set_notify_resume(). > + * It ensures that we read the nonzero utrace_flags set before > + * set_notify_resume() was called by utrace setup. > + */ > + smp_rmb(); > + if (task_utrace_flags(task)) > + utrace_resume(task, regs); > } Sending an IPI implies the mb? I seem to remember a discussion on that subject a while back, maybe add that do Documentation/memory-barriers.txt > +/* > + * Hooks in call these entry points to the > + * utrace dispatch. They are weak references here only so > + * tracehook.h doesn't need to #ifndef CONFIG_UTRACE them to > + * avoid external references in case of unoptimized compilation. > + */ > +void utrace_free_task(struct task_struct *) > + __attribute__((weak)); > +bool utrace_interrupt_pending(void) > + __attribute__((weak)); > +void utrace_resume(struct task_struct *, struct pt_regs *) > + __attribute__((weak)); > +void utrace_finish_stop(void) > + __attribute__((weak)); > +int utrace_get_signal(struct task_struct *, struct pt_regs *, > + siginfo_t *, struct k_sigaction *) > + __attribute__((weak)); > +void utrace_report_clone(unsigned long, struct task_struct *) > + __attribute__((weak)); > +void utrace_finish_vfork(struct task_struct *) > + __attribute__((weak)); > +void utrace_report_exit(long *exit_code) > + __attribute__((weak)); > +void utrace_report_death(struct task_struct *, struct utrace *, bool, int) > + __attribute__((weak)); > +void utrace_report_jctl(int notify, int type) > + __attribute__((weak)); > +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, > + struct pt_regs *regs) > + __attribute__((weak)); > +bool utrace_report_syscall_entry(struct pt_regs *) > + __attribute__((weak)); > +void utrace_report_syscall_exit(struct pt_regs *) > + __attribute__((weak)); > +void utrace_signal_handler(struct task_struct *, int) > + __attribute__((weak)); Can the compiler optimize away the callsite using weak functions like this? If not I think the normal static inline stubs make more sense. Also, what unoptimized compilation? > +static inline struct utrace *task_utrace_struct(struct task_struct *task) > +{ > + struct utrace *utrace; > + > + /* > + * This barrier ensures that any prior load of task->utrace_flags > + * is ordered before this load of task->utrace. We use those > + * utrace_flags checks in the hot path to decide to call into > + * the utrace code. The first attach installs task->utrace before > + * setting task->utrace_flags nonzero, with a barrier between. > + * See utrace_task_alloc(). > + */ > + smp_rmb(); > + utrace = task->utrace; > + > + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ > + return utrace; > +} I spot two barriers here, but only 1 over in utrace_task_alloc(), hmm? > +/* > + * Version number of the API defined in this file. This will change > + * whenever a tracing engine's code would need some updates to keep > + * working. We maintain this here for the benefit of tracing engine code > + * that is developed concurrently with utrace API improvements before they > + * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. > + */ > +#define UTRACE_API_VERSION 20090421 I don't think this is desired. Out-of-tree stuff just doesn't exist, plain pure and simple. > +enum utrace_resume_action { > + UTRACE_STOP, > + UTRACE_INTERRUPT, > + UTRACE_REPORT, > + UTRACE_SINGLESTEP, > + UTRACE_BLOCKSTEP, > + UTRACE_RESUME, > + UTRACE_DETACH > +}; > +#define UTRACE_RESUME_MASK 0x07 > +enum utrace_signal_action { > + UTRACE_SIGNAL_DELIVER = 0x00, > + UTRACE_SIGNAL_IGN = 0x10, > + UTRACE_SIGNAL_TERM = 0x20, > + UTRACE_SIGNAL_CORE = 0x30, > + UTRACE_SIGNAL_STOP = 0x40, > + UTRACE_SIGNAL_TSTP = 0x50, > + UTRACE_SIGNAL_REPORT = 0x60, > + UTRACE_SIGNAL_HANDLER = 0x70 > +}; > +#define UTRACE_SIGNAL_MASK 0xf0 > +#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ > +enum utrace_syscall_action { > + UTRACE_SYSCALL_RUN = 0x00, > + UTRACE_SYSCALL_ABORT = 0x10 > +}; > +#define UTRACE_SYSCALL_MASK 0xf0 > +#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ Right, so this lot doesn't seem very consistent. At the very least I would put signal action and syscall action into different ranges. > +/* > + * Flags for utrace_attach_task() and utrace_attach_pid(). > + */ > +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ > +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ > +#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ > +#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ > +#define UTRACE_ATTACH_MATCH_MASK 0x000f My OCD tells me these are ordered wrong :-) > +/** > + * struct utrace_engine - per-engine structure > + * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() > + * @data: engine-private &void * passed to utrace_attach_task() > + * @flags: event mask set by utrace_set_events() plus internal flag bits > + * > + * The task itself never has to worry about engines detaching while > + * it's doing event callbacks. These structures are removed from the > + * task's active list only when it's stopped, or by the task itself. > + * > + * utrace_engine_get() and utrace_engine_put() maintain a reference count. > + * When it drops to zero, the structure is freed. One reference is held > + * implicitly while the engine is attached to its task. > + */ > +struct utrace_engine { > +/* private: */ > + struct kref kref; > + void (*release)(void *); > + struct list_head entry; > + > +/* public: */ > + const struct utrace_engine_ops *ops; > + void *data; > + > + unsigned long flags; > +}; Sorry, the kernel is written in C, not C++. > +/** > + * struct utrace_engine_ops - tracing engine callbacks > + * > + * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. > + * utrace_set_events() calls on @engine choose which callbacks will be made > + * to @engine from @task. > + * > + * Most callbacks take an @action argument, giving the resume action > + * chosen by other tracing engines. All callbacks take an @engine > + * argument, and a @task argument, which is always equal to @current. Given that some functions have a lot of arguments (depleting regparam), isn't it more expensive to push current on the stack than it is to simply read it again? > + * For some calls, @action also includes bits specific to that event > + * and utrace_resume_action() is used to extract the resume action. > + * This shows what would happen if @engine wasn't there, or will if > + * the callback's return value uses %UTRACE_RESUME. This always > + * starts as %UTRACE_RESUME when no other tracing is being done on > + * this task. > + * > + * All return values contain &enum utrace_resume_action bits. For > + * some calls, other bits specific to that kind of event are added to > + * the resume action bits with OR. These are the same bits used in > + * the @action argument. > + */ > +struct utrace_engine_ops { > + u32 (*report_signal)(u32 action, > + struct utrace_engine *engine, > + struct task_struct *task, > + struct pt_regs *regs, > + siginfo_t *info, > + const struct k_sigaction *orig_ka, > + struct k_sigaction *return_ka); > + u32 (*report_clone)(enum utrace_resume_action action, > + struct utrace_engine *engine, > + struct task_struct *parent, > + unsigned long clone_flags, > + struct task_struct *child); > +}; Seems inconsistent on u32 vs enum utrace_resume_action. Why force enum utrace_resume_action into a u32? > +/** > + * struct utrace_examiner - private state for using utrace_prepare_examine() > + * > + * The members of &struct utrace_examiner are private to the implementation. > + * This data type holds the state from a call to utrace_prepare_examine() > + * to be used by a call to utrace_finish_examine(). > + */ > +struct utrace_examiner { > +/* private: */ > + long state; > + unsigned long ncsw; > +}; Again, its not C++, if you want a private state like that, use an opaque type, like: struct utrace_examiner; and only define the thing in utrace.c or something. > +static inline __must_check int utrace_control_pid( > + struct pid *pid, struct utrace_engine *engine, > + enum utrace_resume_action action) > +{ > + /* > + * We don't bother with rcu_read_lock() here to protect the > + * task_struct pointer, because utrace_control will return > + * -ESRCH without looking at that pointer if the engine is > + * already detached. A task_struct pointer can't die before > + * all the engines are detached in release_task() first. > + */ > + struct task_struct *task = pid_task(pid, PIDTYPE_PID); > + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); > +} Is that comment correct? Without rcu_read_lock() the pidhash can change under our feet and maybe cause funny things? Same for utrace_*_pid() it seems. Does pid_task() in generaly rely on havin rcu_read_lock() called? If so, a change in the implementation could break the assumptions here. > +/* > + * Per-thread structure private to utrace implementation. See, you do know how to do private in C ;-) > + */ > +struct utrace { > + spinlock_t lock; > + struct list_head attached, attaching; > + > + struct task_struct *cloning; > + > + struct utrace_engine *reporting; > + > + enum utrace_resume_action resume:3; > + unsigned int signal_handler:1; > + unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ > + unsigned int death:1; /* in utrace_report_death() now */ > + unsigned int reap:1; /* release_task() has run */ > + unsigned int pending_attach:1; /* need splice_attaching() */ > +}; Seems inconsistent in the bitfield type, also it feels like that 3 the 7 and the enum should be more tightly integrated, maybe add: UTRACE_RESUME_MAX #define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX)) #define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) And pick something consistent: u32, unsigned int or enum utrace_resume_action. > +/* > + * Set up @task.utrace for the first time. We can have races > + * between two utrace_attach_task() calls here. The task_lock() > + * governs installing the new pointer. If another one got in first, > + * we just punt the new one we allocated. > + * > + * This returns false only in case of a memory allocation failure. > + */ > +static bool utrace_task_alloc(struct task_struct *task) > +{ > + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); > + if (unlikely(!utrace)) > + return false; > + spin_lock_init(&utrace->lock); > + INIT_LIST_HEAD(&utrace->attached); > + INIT_LIST_HEAD(&utrace->attaching); > + utrace->resume = UTRACE_RESUME; > + task_lock(task); > + if (likely(!task->utrace)) { > + /* > + * This barrier makes sure the initialization of the struct > + * precedes the installation of the pointer. This pairs > + * with smp_read_barrier_depends() in task_utrace_struct(). > + */ > + smp_wmb(); > + task->utrace = utrace; > + } > + task_unlock(task); > + /* > + * That unlock after storing task->utrace acts as a memory barrier > + * ordering any subsequent task->utrace_flags store afterwards. > + * This pairs with smp_rmb() in task_utrace_struct(). > + */ > + if (unlikely(task->utrace != utrace)) > + kmem_cache_free(utrace_cachep, utrace); > + return true; > +} Again, not sure we can pair an UNLOCK-barrier with a RMB. In fact, both are NOPs on x86. > +static struct utrace_engine *matching_engine( > + struct utrace *utrace, int flags, > + const struct utrace_engine_ops *ops, void *data) > +{ > + struct utrace_engine *engine; > + list_for_each_entry(engine, &utrace->attached, entry) > + if (engine_matches(engine, flags, ops, data)) > + return engine; > + list_for_each_entry(engine, &utrace->attaching, entry) > + if (engine_matches(engine, flags, ops, data)) > + return engine; > + return NULL; > +} The function does a search, suggesting the function name ought to have something like find or search in it. > +/* > + * Called without locks, when we might be the first utrace engine to attach. > + * If this is a newborn thread and we are not the creator, we have to wait > + * for it. The creator gets the first chance to attach. The PF_STARTING > + * flag is cleared after its report_clone hook has had a chance to run. > + */ > +static inline int utrace_attach_delay(struct task_struct *target) > +{ > + if ((target->flags & PF_STARTING) && > + task_utrace_struct(current) && > + task_utrace_struct(current)->cloning != target) > + do { > + schedule_timeout_interruptible(1); > + if (signal_pending(current)) > + return -ERESTARTNOINTR; > + } while (target->flags & PF_STARTING); > + > + return 0; > +} Quite gross this.. can't we key off the tracehoook_report_clone_complete() and use a wakeup there? Does this really need the inline? Also, that if stmt really wants brackets. > +/* > + * Called with utrace->lock held and utrace->reap set. > + * Notify and clean up all engines, then free utrace. > + */ > +static void utrace_reap(struct task_struct *target, struct utrace *utrace) > + __releases(utrace->lock) > +{ > + struct utrace_engine *engine, *next; > + > + /* utrace_add_engine() checks ->utrace_flags != 0 */ > + target->utrace_flags = 0; > + splice_attaching(utrace); > + > + /* > + * Since we were called with @utrace->reap set, nobody can > + * set/clear UTRACE_EVENT(REAP) in @engine->flags or change > + * @engine->ops, and nobody can change @utrace->attached. > + */ > + spin_unlock(&utrace->lock); > + > + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > + if (engine->flags & UTRACE_EVENT(REAP)) > + engine->ops->report_reap(engine, target); > + > + engine->ops = NULL; > + engine->flags = 0; > + list_del_init(&engine->entry); > + > + utrace_engine_put(engine); > + } > +} Asymmetric locking like this is really better not done, and looking at the callsites its really no bother to clean that up, arguably even makes them saner. > +/* > + * Asynchronously mark an engine as being detached. > + * > + * This must work while the target thread races with us doing > + * start_callback(), defined below. It uses smp_rmb() between checking > + * @engine->flags and using @engine->ops. Here we change @engine->ops > + * first, then use smp_wmb() before changing @engine->flags. This ensures > + * it can check the old flags before using the old ops, or check the old > + * flags before using the new ops, or check the new flags before using the > + * new ops, but can never check the new flags before using the old ops. > + * Hence, utrace_detached_ops might be used with any old flags in place. > + * It has report_quiesce() and report_reap() callbacks to handle all cases. > + */ > +static void mark_engine_detached(struct utrace_engine *engine) > +{ > + engine->ops = &utrace_detached_ops; > + smp_wmb(); > + engine->flags = UTRACE_EVENT(QUIESCE); > +} It would be more readable to split that comment into two, one part going near the wmb, and leaving the top part describing the function, not hte implementation. The comments in general tend to be too long and verbose, split them up in to shorter 3-4 line paragraphs with clear subjects/points. Furthermore I'd add a function like: static struct utrace_engine_ops * get_utrace_ops(struct utrace_engine *engine, unsigned long *flags) { *flags = engine->flags; /* * This pairs with the barrier in mark_engine_detached(). * It makes sure that we never see the old ops vector with * the new flags, in case the original vector had no * report_quiesce. */ smp_rmb(); return engine->ops; } to take out and explicitly comment that common bit. Also, I'm not quite sure on why we play so many barrier games, looking at start_callback() we have 2 barriers in the callback loop, why not a per engine lock? > +/* > + * Get @target to stop and return true if it is already stopped now. > + * If we return false, it will make some event callback soonish. > + * Called with @utrace locked. > + */ > +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) > +{ > + if (task_is_stopped(target)) { > + /* > + * Stopped is considered quiescent; when it wakes up, it will > + * go through utrace_finish_stop() before doing anything else. > + */ > + spin_lock_irq(&target->sighand->siglock); > + if (likely(task_is_stopped(target))) > + __set_task_state(target, TASK_TRACED); > + spin_unlock_irq(&target->sighand->siglock); > + } else if (utrace->resume > UTRACE_REPORT) { > + utrace->resume = UTRACE_REPORT; > + set_notify_resume(target); > + } > + > + return task_is_traced(target); You could codify locking assumptions like here using: lockdep_assert_held(&utrace->lock); Saves a comment and actually validates the assumption. > +/* > + * This is called when there might be some detached engines on the list or > + * some stale bits in @task->utrace_flags. Clean them up and recompute the > + * flags. Returns true if we're now fully detached. > + * > + * Called with @utrace->lock held, returns with it released. > + * After this returns, @utrace might be freed if everything detached. > + */ > +static bool utrace_reset(struct task_struct *task, struct utrace *utrace) > + __releases(utrace->lock) > +{ > + struct utrace_engine *engine, *next; > + unsigned long flags = 0; > + LIST_HEAD(detached); > + > + splice_attaching(utrace); > + > + /* > + * Update the set of events of interest from the union > + * of the interests of the remaining tracing engines. > + * For any engine marked detached, remove it from the list. > + * We'll collect them on the detached list. > + */ > + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { > + if (engine->ops == &utrace_detached_ops) { > + engine->ops = NULL; > + list_move(&engine->entry, &detached); > + } else { > + flags |= engine->flags | UTRACE_EVENT(REAP); > + } > + } > + > + if (task->exit_state) { > + /* > + * Once it's already dead, we never install any flags > + * except REAP. When ->exit_state is set and events > + * like DEATH are not set, then they never can be set. > + * This ensures that utrace_release_task() knows > + * positively that utrace_report_death() can never run. > + */ > + BUG_ON(utrace->death); > + flags &= UTRACE_EVENT(REAP); > + } else if (!(flags & UTRACE_EVENT_SYSCALL) && > + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { > + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); > + } > + > + if (!flags) { > + /* > + * No more engines, cleared out the utrace. > + */ > + utrace->resume = UTRACE_RESUME; > + utrace->signal_handler = 0; > + } > + > + if (task_is_traced(task) && !(flags & ENGINE_STOP)) > + /* > + * No more engines want it stopped. Wake it up. > + */ > + utrace_wakeup(task, utrace); wants braces. > + /* > + * In theory spin_lock() doesn't imply rcu_read_lock(). > + * Once we clear ->utrace_flags this task_struct can go away > + * because tracehook_prepare_release_task() path does not take > + * utrace->lock when ->utrace_flags == 0. > + */ > + rcu_read_lock(); > + task->utrace_flags = flags; > + spin_unlock(&utrace->lock); > + rcu_read_unlock(); yuck! why not simply keep a task reference over the utrace_reset call? Also, that unlock really wants to be in the caller, things like: if (reset) utrace_reset() else spin_unlock(&utrace->lock) are just vile. > + put_detached_list(&detached); > + > + return !flags; > +} > +/* > + * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. > + * @task == current, @utrace == current->utrace, which is not locked. > + * Return true if we were woken up by SIGKILL even though some utrace > + * engine may still want us to stay stopped. > + */ > +static void utrace_stop(struct task_struct *task, struct utrace *utrace, > + enum utrace_resume_action action) > +{ > +relock: > + spin_lock(&utrace->lock); > + > + if (action < utrace->resume) { > + /* > + * Ensure a reporting pass when we're resumed. > + */ > + utrace->resume = action; > + if (action == UTRACE_INTERRUPT) > + set_thread_flag(TIF_SIGPENDING); > + else > + set_thread_flag(TIF_NOTIFY_RESUME); > + } > + > + /* > + * If the ENGINE_STOP bit is clear in utrace_flags, that means > + * utrace_reset() ran after we processed some UTRACE_STOP return > + * values from callbacks to get here. If all engines have detached > + * or resumed us, we don't stop. This check doesn't require > + * siglock, but it should follow the interrupt/report bookkeeping > + * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). > + */ > + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { > + utrace_reset(task, utrace); > + if (task->utrace_flags & ENGINE_STOP) > + goto relock; > + return; > + } > + > + /* > + * The siglock protects us against signals. As well as SIGKILL > + * waking us up, we must synchronize with the signal bookkeeping > + * for stop signals and SIGCONT. > + */ > + spin_lock_irq(&task->sighand->siglock); > + > + if (unlikely(__fatal_signal_pending(task))) { > + spin_unlock_irq(&task->sighand->siglock); > + spin_unlock(&utrace->lock); > + return; > + } > + > + __set_current_state(TASK_TRACED); > + > + /* > + * If there is a group stop in progress, > + * we must participate in the bookkeeping. > + */ > + if (unlikely(task->signal->group_stop_count) && > + !--task->signal->group_stop_count) > + task->signal->flags = SIGNAL_STOP_STOPPED; > + > + spin_unlock_irq(&task->sighand->siglock); > + spin_unlock(&utrace->lock); > + > + /* > + * If ptrace is among the reasons for this stop, do its > + * notification now. This could not just be done in > + * ptrace's own event report callbacks because it has to > + * be done after we are in TASK_TRACED. This makes the > + * synchronization with ptrace_do_wait() work right. > + */ > + ptrace_notify_stop(task); Well, this is a bit disappointing isn't it? So we cannot implement ptrace on utrace without special purpose hooks? > + schedule(); > + > + utrace_finish_stop(); > + > + /* > + * While in TASK_TRACED, we were considered "frozen enough". > + * Now that we woke up, it's crucial if we're supposed to be > + * frozen that we freeze now before running anything substantial. > + */ > + try_to_freeze(); > + > + /* > + * While we were in TASK_TRACED, complete_signal() considered > + * us "uninterested" in signal wakeups. Now make sure our > + * TIF_SIGPENDING state is correct for normal running. > + */ > + spin_lock_irq(&task->sighand->siglock); > + recalc_sigpending(); > + spin_unlock_irq(&task->sighand->siglock); > +} > +/** > + */ > +int utrace_control(struct task_struct *target, > + struct utrace_engine *engine, > + enum utrace_resume_action action) > +{ > + struct utrace *utrace; > + bool reset; > + int ret; > + > + if (unlikely(action > UTRACE_DETACH)) > + return -EINVAL; If you'd have added UTRACE_RESUME_MAX, you could have avoided the assumption DETACH is the last one. > + /* > + * This is a sanity check for a programming error in the caller. > + * Their request can only work properly in all cases by relying on > + * a follow-up callback, but they didn't set one up! This check > + * doesn't do locking, but it shouldn't matter. The caller has to > + * be synchronously sure the callback is set up to be operating the > + * interface properly. > + */ > + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && > + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) > + return -EINVAL; If its a programming error, WARN_ON might be appropriate, no point in being nice about it. > + utrace = get_utrace_lock(target, engine, true); > + if (unlikely(IS_ERR(utrace))) > + return PTR_ERR(utrace); > + > + reset = task_is_traced(target); > + ret = 0; > + > + /* > + * ->exit_state can change under us, this doesn't matter. > + * We do not care about ->exit_state in fact, but we do > + * care about ->reap and ->death. If either flag is set, > + * we must also see ->exit_state != 0. > + */ > + if (unlikely(target->exit_state)) { > + ret = utrace_control_dead(target, utrace, action); > + if (ret) { > + spin_unlock(&utrace->lock); > + return ret; > + } > + reset = true; > + } > + > + switch (action) { > + } > + > + /* > + * Let the thread resume running. If it's not stopped now, > + * there is nothing more we need to do. > + */ > + if (reset) > + utrace_reset(target, utrace); > + else > + spin_unlock(&utrace->lock); yuckness.. > + return ret; > +} > +EXPORT_SYMBOL_GPL(utrace_control); > + > +/** > + * utrace_barrier - synchronize with simultaneous tracing callbacks > + * @target: thread to affect > + * @engine: engine to affect (can be detached) > + * > + * This blocks while @target might be in the midst of making a callback to > + * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. > + * A return value of zero means no callback from @target to @engine was > + * in progress. Any effect of its return value (such as %UTRACE_STOP) has > + * already been applied to @engine. > + * > + * It's not necessary to keep the @target pointer alive for this call. > + * It's only necessary to hold a ref on @engine. This will return > + * safely even if @target has been reaped and has no task refs. > + * > + * A successful return from utrace_barrier() guarantees its ordering > + * with respect to utrace_set_events() and utrace_control() calls. If > + * @target was not properly stopped, event callbacks just disabled might > + * still be in progress; utrace_barrier() waits until there is no chance > + * an unwanted callback can be in progress. > + */ > +int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) > +{ > + struct utrace *utrace; > + int ret = -ERESTARTSYS; > + > + if (unlikely(target == current)) > + return 0; > + > + do { > + utrace = get_utrace_lock(target, engine, false); > + if (unlikely(IS_ERR(utrace))) { > + ret = PTR_ERR(utrace); > + if (ret != -ERESTARTSYS) > + break; > + } else { > + /* > + * All engine state changes are done while > + * holding the lock, i.e. before we get here. > + * Since we have the lock, we only need to > + * worry about @target making a callback. > + * When it has entered start_callback() but > + * not yet gotten to finish_callback(), we > + * will see utrace->reporting == @engine. > + * When @target doesn't take the lock, it uses > + * barriers to order setting utrace->reporting > + * before it examines the engine state. > + */ > + if (utrace->reporting != engine) > + ret = 0; > + spin_unlock(&utrace->lock); > + if (!ret) > + break; > + } > + schedule_timeout_interruptible(1); > + } while (!signal_pending(current)); Seriously ugly, again. Use a wakeup where appropriate. > + > + return ret; > +} > +EXPORT_SYMBOL_GPL(utrace_barrier); > +/* > + * We are now making the report, so clear the flag saying we need one. > + * When there is a new attach, ->pending_attach is set just so we will > + * know to do splice_attaching() here before the callback loop. > + */ > +static enum utrace_resume_action start_report(struct utrace *utrace) > +{ > + enum utrace_resume_action resume = utrace->resume; > + if (utrace->pending_attach || > + (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { > + spin_lock(&utrace->lock); > + splice_attaching(utrace); > + resume = utrace->resume; > + if (resume > UTRACE_INTERRUPT) > + utrace->resume = UTRACE_RESUME; > + spin_unlock(&utrace->lock); > + } > + return resume; > +} Its not entirely clear why we can check pending_attach outside of the utrace->lock and not be racy. > +static inline void finish_report_reset(struct task_struct *task, > + struct utrace *utrace, > + struct utrace_report *report) > +{ > + if (unlikely(report->spurious || report->detaches)) { > + spin_lock(&utrace->lock); > + if (utrace_reset(task, utrace)) > + report->action = UTRACE_RESUME; > + } > +} More asymmetric locking... > +static inline void finish_callback_report(struct task_struct *task, > + struct utrace *utrace, > + struct utrace_report *report, > + struct utrace_engine *engine, > + enum utrace_resume_action action) > +{ > + /* > + * If utrace_control() was used, treat that like UTRACE_DETACH here. > + */ > + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { > + engine->ops = &utrace_detached_ops; > + report->detaches = true; > + return; > + } > + > + if (action < report->action) > + report->action = action; > + > + if (action != UTRACE_STOP) { > + if (action < report->resume_action) > + report->resume_action = action; > + > + if (engine_wants_stop(engine)) { > + spin_lock(&utrace->lock); > + clear_engine_wants_stop(engine); > + spin_unlock(&utrace->lock); > + } Reads funny, but I guess it can only race the right way round? > + return; > + } > + > + if (!engine_wants_stop(engine)) { > + spin_lock(&utrace->lock); > + /* > + * If utrace_control() came in and detached us > + * before we got the lock, we must not stop now. > + */ > + if (unlikely(engine->ops == &utrace_detached_ops)) > + report->detaches = true; > + else > + mark_engine_wants_stop(task, engine); > + spin_unlock(&utrace->lock); > + } > +} I'm pretty sure that inline isn't really needed. > +/* > + * Apply the return value of one engine callback to @report. > + * Returns true if @engine detached and should not get any more callbacks. > + */ > +static bool finish_callback(struct task_struct *task, struct utrace *utrace, > + struct utrace_report *report, > + struct utrace_engine *engine, > + u32 ret) > +{ > + report->result = ret & ~UTRACE_RESUME_MASK; > + finish_callback_report(task, utrace, report, engine, > + utrace_resume_action(ret)); > + > + /* > + * Now that we have applied the effect of the return value, > + * clear this so that utrace_barrier() can stop waiting. > + * A subsequent utrace_control() can stop or resume @engine > + * and know this was ordered after its callback's action. > + * > + * We don't need any barriers here because utrace_barrier() > + * takes utrace->lock. If we touched engine->flags above, > + * the lock guaranteed this change was before utrace_barrier() > + * examined utrace->reporting. > + */ > + utrace->reporting = NULL; > + > + /* > + * This is a good place to make sure tracing engines don't > + * introduce too much latency under voluntary preemption. > + */ > + if (need_resched()) > + cond_resched(); Simply cond_resched() is sufficient, but that comment sucks, as it doesn't mention _why_ it is a good place. It seems to turn out that finish_callback() is always the last thing we do in the engine iterations in REPORT_CALLBACKS() and utrace_get_signal(). > + > + return engine->ops == &utrace_detached_ops; > +} > + > +/* > + * Start the callbacks for @engine to consider @event (a bit mask). > + * This makes the report_quiesce() callback first. If @engine wants > + * a specific callback for @event, we return the ops vector to use. > + * If not, we return NULL. The return value from the ops->callback > + * function called should be passed to finish_callback(). > + */ > +static const struct utrace_engine_ops *start_callback( > + struct utrace *utrace, struct utrace_report *report, > + struct utrace_engine *engine, struct task_struct *task, > + unsigned long event) > +{ > + const struct utrace_engine_ops *ops; > + unsigned long want; > + > + /* > + * This barrier ensures that we've set utrace->reporting before > + * we examine engine->flags or engine->ops. utrace_barrier() > + * relies on this ordering to indicate that the effect of any > + * utrace_control() and utrace_set_events() calls is in place > + * by the time utrace->reporting can be seen to be NULL. > + */ > + utrace->reporting = engine; > + smp_mb(); > + > + /* > + * This pairs with the barrier in mark_engine_detached(). > + * It makes sure that we never see the old ops vector with > + * the new flags, in case the original vector had no report_quiesce. > + */ > + want = engine->flags; > + smp_rmb(); > + ops = engine->ops; > + > + if (want & UTRACE_EVENT(QUIESCE)) { > + if (finish_callback(task, utrace, report, engine, > + (*ops->report_quiesce)(report->action, > + engine, task, > + event))) > + return NULL; > + > + /* > + * finish_callback() reset utrace->reporting after the > + * quiesce callback. Now we set it again (as above) > + * before re-examining engine->flags, which could have > + * been changed synchronously by ->report_quiesce or > + * asynchronously by utrace_control() or utrace_set_events(). > + */ > + utrace->reporting = engine; > + smp_mb(); > + want = engine->flags; > + } > + > + if (want & ENGINE_STOP) > + report->action = UTRACE_STOP; > + > + if (want & event) { > + report->spurious = false; > + return ops; > + } > + > + utrace->reporting = NULL; > + return NULL; > +} This function makes my head hurt... it would be very nice to see an obvious version and a set of patches obfuscating it, with numbers defending the obfuscation. > +/* > + * Do a normal reporting pass for engines interested in @event. > + * @callback is the name of the member in the ops vector, and remaining > + * args are the extras it takes after the standard three args. > + */ > +#define REPORT(task, utrace, report, event, callback, ...) \ > + do { \ > + start_report(utrace); \ > + REPORT_CALLBACKS(, task, utrace, report, event, callback, \ > + (report)->action, engine, current, \ > + ## __VA_ARGS__); \ > + finish_report(task, utrace, report, true); \ > + } while (0) > +#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ > + do { \ > + struct utrace_engine *engine; \ > + const struct utrace_engine_ops *ops; \ > + list_for_each_entry##rev(engine, &utrace->attached, entry) { \ > + ops = start_callback(utrace, report, engine, task, \ > + event); \ > + if (!ops) \ > + continue; \ > + finish_callback(task, utrace, report, engine, \ > + (*ops->callback)(__VA_ARGS__)); \ > + } \ > + } while (0) My OCD makes me tell you that these macros are defined in the wrong order. > +void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) > +{ > + struct task_struct *task = current; > + struct utrace *utrace = task_utrace_struct(task); > + INIT_REPORT(report); > + > + /* > + * We don't use the REPORT() macro here, because we need > + * to clear utrace->cloning before finish_report(). > + * After finish_report(), utrace can be a stale pointer > + * in cases when report.action is still UTRACE_RESUME. > + */ > + start_report(utrace); > + utrace->cloning = child; > + > + REPORT_CALLBACKS(, task, utrace, &report, > + UTRACE_EVENT(CLONE), report_clone, > + report.action, engine, task, clone_flags, child); > + > + utrace->cloning = NULL; > + finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); > + > + /* > + * For a vfork, we will go into an uninterruptible block waiting > + * for the child. We need UTRACE_STOP to happen before this, not > + * after. For CLONE_VFORK, utrace_finish_vfork() will be called. > + */ > + if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { > + spin_lock(&utrace->lock); > + utrace->vfork_stop = 1; > + spin_unlock(&utrace->lock); > + } So much optimization, weird locking, barriers and here you didn't use atomic bit ops? > +} > + > +/* > + * We're called after utrace_report_clone() for a CLONE_VFORK. > + * If UTRACE_STOP was left from the clone report, we stop here. > + * After this, we'll enter the uninterruptible wait_for_completion() > + * waiting for the child. > + */ > +void utrace_finish_vfork(struct task_struct *task) > +{ > + struct utrace *utrace = task_utrace_struct(task); > + > + if (utrace->vfork_stop) { > + spin_lock(&utrace->lock); > + utrace->vfork_stop = 0; > + spin_unlock(&utrace->lock); > + utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ > + } > +} I'm sure that XXX means something,... again that vfork_stop stuff can only race the right way about, right? > + > +/* > + * Called iff UTRACE_EVENT(JCTL) flag is set. > + * > + * Called with siglock held. > + */ > +void utrace_report_jctl(int notify, int what) > +{ > + struct task_struct *task = current; > + struct utrace *utrace = task_utrace_struct(task); > + INIT_REPORT(report); > + > + spin_unlock_irq(&task->sighand->siglock); > + > + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), > + report_jctl, what, notify); > + > + spin_lock_irq(&task->sighand->siglock); > +} So much documentation, and non of it says that the JCTL (funny name btw) callback is done holding siglock... tskk. > +/* > + * Finish the last reporting pass before returning to user mode. > + */ > +static void finish_resume_report(struct task_struct *task, > + struct utrace *utrace, > + struct utrace_report *report) > +{ > + finish_report_reset(task, utrace, report); > + > + switch (report->action) { > + case UTRACE_STOP: > + utrace_stop(task, utrace, report->resume_action); > + break; > + > + case UTRACE_INTERRUPT: > + if (!signal_pending(task)) > + set_tsk_thread_flag(task, TIF_SIGPENDING); > + break; > + > + case UTRACE_BLOCKSTEP: > + if (likely(arch_has_block_step())) { > + user_enable_block_step(task); > + break; > + } > + > + /* > + * This means some callback is to blame for failing > + * to check arch_has_block_step() itself. Warn and > + * then fall through to treat it as SINGLESTEP. > + */ > + WARN_ON(1); > + > + case UTRACE_SINGLESTEP: > + if (likely(arch_has_single_step())) > + user_enable_single_step(task); > + else > + /* > + * This means some callback is to blame for failing > + * to check arch_has_single_step() itself. Spew > + * about it so the loser will fix his module. > + */ > + WARN_ON(1); wants braces > + break; > + > + case UTRACE_REPORT: > + case UTRACE_RESUME: > + default: > + user_disable_single_step(task); > + break; > + } > +} > + > +/* > + * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). > + * We are close to user mode, and this is the place to report or stop. > + * When we return, we're going to user mode or into the signals code. > + */ > +void utrace_resume(struct task_struct *task, struct pt_regs *regs) > +{ > + struct utrace *utrace = task_utrace_struct(task); > + INIT_REPORT(report); > + struct utrace_engine *engine; > + > + /* > + * Some machines get here with interrupts disabled. The same arch > + * code path leads to calling into get_signal_to_deliver(), which > + * implicitly reenables them by virtue of spin_unlock_irq. > + */ > + local_irq_enable(); Hrmm, I would much prefer to fix up the calling conventions of tracehook_notify_resume() than to bury something like this in the guts of a tracehook user. > + /* > + * If this flag is still set it's because there was a signal > + * handler setup done but no report_signal following it. Clear > + * the flag before we get to user so it doesn't confuse us later. > + */ > + if (unlikely(utrace->signal_handler)) { > + spin_lock(&utrace->lock); > + utrace->signal_handler = 0; > + spin_unlock(&utrace->lock); > + } OK, so maybe you get to explain why this works.. > + > + /* > + * Update our bookkeeping even if there are no callbacks made here. > + */ > + report.action = start_report(utrace); > + > + switch (report.action) { > + case UTRACE_RESUME: > + /* > + * Anything we might have done was already handled by > + * utrace_get_signal(), or this is an entirely spurious > + * call. (The arch might use TIF_NOTIFY_RESUME for other > + * purposes as well as calling us.) > + */ > + return; > + case UTRACE_REPORT: > + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) > + break; > + /* > + * Do a simple reporting pass, with no specific > + * callback after report_quiesce. > + */ > + report.action = UTRACE_RESUME; > + list_for_each_entry(engine, &utrace->attached, entry) > + start_callback(utrace, &report, engine, task, 0); > + break; > + default: > + /* > + * Even if this report was truly spurious, there is no need > + * for utrace_reset() now. TIF_NOTIFY_RESUME was already > + * cleared--it doesn't stay spuriously set. > + */ > + report.spurious = false; > + break; > + } > + > + /* > + * Finish the report and either stop or get ready to resume. > + * If utrace->resume was not UTRACE_REPORT, this applies its > + * effect now (i.e. step or interrupt). > + */ > + finish_resume_report(task, utrace, &report); > +} > +/* > + * Take the siglock and push @info back on our queue. > + * Returns with @task->sighand->siglock held. > + */ > +static void push_back_signal(struct task_struct *task, siginfo_t *info) > + __acquires(task->sighand->siglock) > +{ > + struct sigqueue *q; > + > + if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ > + spin_lock_irq(&task->sighand->siglock); > + return; > + } > + > + q = sigqueue_alloc(); > + if (likely(q)) { > + q->flags = 0; > + copy_siginfo(&q->info, info); > + } > + > + spin_lock_irq(&task->sighand->siglock); > + > + sigaddset(&task->pending.signal, info->si_signo); > + if (likely(q)) > + list_add(&q->list, &task->pending.list); > + > + set_tsk_thread_flag(task, TIF_SIGPENDING); > +} Yes, exactly what we need, more funky locking.. /me gives up.. OK, so what this code needs is some serious restructuring and de-obfuscation, after that we can maybe get creative and add some of it back if the performance numbers agree. But there's too much ugly locking and barriers to be fully sane. Also the documentation needs more whitespace, its very hard to digest in its current form. I'll try and look at the actual state machine later, when my brain has recovered from this. From oleg at redhat.com Tue Dec 1 20:13:23 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Dec 2009 21:13:23 +0100 Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: <20091201193940.154EF1DE@magilla.sf.frob.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> <20091130044448.9D134D6D2@magilla.sf.frob.com> <20091130170726.GA4421@redhat.com> <20091201165845.GA9251@redhat.com> <20091201193940.154EF1DE@magilla.sf.frob.com> Message-ID: <20091201201323.GA19789@redhat.com> On 12/01, Roland McGrath wrote: > > > So. Any ptrace test which uses clone() is broken, at least on x86_64. > > If you use clone() directly then you need to have the code run in that > child be purely under your control. You can't use miscellaneous libc > calls nor any libpthread calls, only ones you are sure do not require > any thread setup. Yes, sure, this is clear. > The only thing that changed about this recently in glibc is that even > more code paths through the dynamic linker now happen to depend on > thread setup. Yes, I see. > > Jan, Roland, how should we fix this? We can rewrite the code to use > > pthread_create(), this should be trivial. Unfortunately, libpthread > > is not trivial, it can shadow the problem and complicate the testing. > > We should avoid library code more thoroughly, not use more of it. > As well as being complex, it also varies a lot across systems and > interferes with using the same sources to translate to exact > kernel-level testing across various people's development environments. Agreed. > I think the best bet is to link with -Wl,-z,now I think this should help. > and then minimize the > library code you rely on. (It really only matters to be extra careful > about that for the code running in the clone child.) So you can use > syscall() if you are not relying on its error-case behavior--if the > system call fails, the function will set errno, which can rely on the > TLS setup. IIRC, all ptrace-tests's sub-threads created by clone are very simple, they only do very basic systemcalls like pause/exit. The test-case I sent does syscall(__NR_exit) and nothing more, but I guess BIND_NOW should help. > > And the stupid question. If I create the subthread via pthread_create(), > > how can I know its tid? I grepped glibc-2.11, and afaics pthread_create > > returns the pointer to "struct pthread" which has "pid_t tid" but I can > > not find the helper which returns ->tid and "struct pthread" is not > > exported. > > There is no official exported way. You can use syscall(__NR_gettid). Yes, but this way the caller of pthread_create() should communicate with the sub-thread to know its tid, this is not suitable for ptrace tests. Oleg. From benh at kernel.crashing.org Tue Dec 1 20:17:47 2009 From: benh at kernel.crashing.org (Benjamin Herrenschmidt) Date: Wed, 02 Dec 2009 07:17:47 +1100 Subject: powerpc: syscall_dotrace() && retcode (Was: powerpc: fork && stepping) In-Reply-To: <20091201192750.4A1291DE@magilla.sf.frob.com> References: <20091126145051.GB4382@redhat.com> <20091126172524.GA14768@redhat.com> <20091126182226.GF12355@darkmag.usersys.redhat.com> <20091126202312.GA21945@redhat.com> <19214.63688.860929.962005@cargo.ozlabs.ibm.com> <20091126223703.GA28556@redhat.com> <20091127174627.GB26193@darkmag.usersys.redhat.com> <20091128073049.GD23108@in.ibm.com> <20091129210716.GA19205@redhat.com> <1259536501.2076.39.camel@pasglop> <20091130200136.GB11764@redhat.com> <20091201192750.4A1291DE@magilla.sf.frob.com> Message-ID: <1259698667.2076.935.camel@pasglop> On Tue, 2009-12-01 at 11:27 -0800, Roland McGrath wrote: > > If the powerpc maintainers want to change the behavior here, that is fine > by me. But there is no need for that just to satisfy general ptrace > cleanups (or utrace). Normal concerns require that no such change break > the ptrace behavior that userland could have relied on in the past. > > So off hand I don't see a reason to change at all. If every arch were to > change so that registers changed at syscall-entry were left unmolested by > aborting the syscall, then that might be a new consistency worth having. > But short of that, I don't really see a benefit. > > All this implies that the ptrace-tests case relating to this needs to be > tailored differently for powerpc and each other arch so it expects and > verifies exactly the arch-specific behavior that's been seen in the past. Ok thanks. I'm happy to not change it then, the risk of breaking some existing assumption is too high in my book. Cheers, Ben. From mingo at elte.hu Tue Dec 1 21:15:18 2009 From: mingo at elte.hu (Ingo Molnar) Date: Tue, 1 Dec 2009 22:15:18 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091201174534.GE10331@redhat.com> References: <1259584907.20516.246.camel@laptop> <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> Message-ID: <20091201211518.GA32376@elte.hu> * Frank Ch. Eigler wrote: > Hi - > > > > Only in name. One is highly invasive, for debugging the kernel across > > > serial consoles. The other is highly noninvasive, for debugging user > > > processes across normal userspace channels. They both happen to talk > > > to gdb, but that's the end of the natural "overlap". > > [...] > > > Well nothing that you mention here changes our obvious suggestion > > that an in-kernel gdb stub should obviously either be a kgdb > > extension, or a replacement of it. > > Help me out here: by "kgdb extension" do you imagine "something new > that an unprivileged user can use to debug his own process"? Or do > you imagine a new userspace facility that single-steps the kernel? Is this a trick question? Single-stepping the kernel on the same system [especially if it's an UP system] would certainly be a challenge ;-) What i mean is what i said: if you provide a new framework (especially if it's user visible - which both kgdb and the gdb stub is) you should either fully replace existing functionality or extend it. Overlapping it in an incomplete way is not useful to anyone. Extending kgdb to allow the use of it as if we used gdb locally would certainly be interesting - and then you could drop into the kernel anytime as well. But i'm not siding with any particular solution - i'm just seconding Peter's point that there's very clear overlap and inconsistency, and that ought to be resolved one way or another. > > We dont want to separate facilities for the same conceptual thing: > > examining application state (be that in user-space and > > kernel-space). > > This seems like a shallow sort of consistency. kgdb was added after > ptrace existed -- why not extend ptrace instead to target the kernel? > After all, it's "examining application state". The answer is that it > doesn't make a heck of a lot of sense. kgdb simply used gdb's preferred way of remote debugging. That's certainly the ugliest bit of it btw - but it's an externality to kgdb. Had it extended ptrace it wouldnt have gdb compatibility. So i think this example of yours is inapposite as well. Having said all that, i certainly subscribe to the view that neither kgdb nor ptrace is particularly cleanly done. So i wouldnt mind if something new existed that had a modern, flexible, extensible and generally pleasant interface and implementation. If you are heading in that direction, please let me know. > > > > Btw., perf does meet that definition: it functionally replaces all > > > > facilities that it overlaps/extends - such as Oprofile. [...] > > > > > > (And they currently separately coexist.) > > > > You didnt get my point apparently. Keeping the overlapped facility for > > compatibility (and general user inertia) is fine. Creating a new > > facility that doesnt do everything that the existing facility does, and > > not integrating it either, is not fine. > > oprofile and perfctr are closer in concept than kgdb and ptrace, yet > AFAIK perfctr doesn't "interface" to oprofile, except perhaps to the > extent of resolving contention over the underlying physical resources. > In any case this is not a great analogy. (FYI, 'perfctr' is a different project that has existed for years, i suspect you meant perf events?) perf replaces oprofile functionally. If the in-kernel gdb stub replaced kgdb functionally you'd hear no complaints from me. Ingo From oleg at redhat.com Tue Dec 1 22:08:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 1 Dec 2009 23:08:47 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1259697242.1697.1075.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> Message-ID: <20091201220847.GA25400@redhat.com> On 12/01, Peter Zijlstra wrote: > > On Tue, 2009-11-24 at 21:02 +0100, Oleg Nesterov wrote: > > > + > > + There is nothing a kernel module can do to keep a struct > > + task_struct alive outside of > > + rcu_read_lock. > > Sure there is, get_task_struct() comes to mind. it is not exported ;) Peter, I skipped other comments about the documentation, I never read it myself. Update: I skipped a lot more for today ;) > > @@ -351,6 +394,10 @@ static inline void tracehook_report_vfor > > */ > > static inline void tracehook_prepare_release_task(struct task_struct *task) > > { > > + /* see utrace_add_engine() about this barrier */ > > + smp_mb(); > > + if (task_utrace_flags(task)) > > + utrace_release_task(task); > > } > > OK, that seems to properly order ->exit_state vs ->utrace_flags, > > This site does: > > assign ->state > mb > observe ->utrace_flags > > and the other site does: > > assign ->utrace_flags > mb > observe ->exit_state Yes, we hope. > > @@ -560,6 +625,20 @@ static inline void tracehook_report_deat > > int signal, void *death_cookie, > > int group_dead) > > { > > + /* > > + * This barrier ensures that our caller's setting of > > + * @task->exit_state precedes checking @task->utrace_flags here. > > + * If utrace_set_events() was just called to enable > > + * UTRACE_EVENT(DEATH), then we are obliged to call > > + * utrace_report_death() and not miss it. utrace_set_events() > > + * uses tasklist_lock to synchronize enabling the bit with the > > + * actual change to @task->exit_state, but we need this barrier > > + * to be sure we see a flags change made just before our caller > > + * took the tasklist_lock. > > + */ > > + smp_mb(); > > + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) > > + utrace_report_death(task, death_cookie, group_dead, signal); > > } > > I don't think its allowed to pair a mb with a lock-barrier, since the > lock barriers are semi-permeable. Could you clarify? > > @@ -589,10 +668,20 @@ static inline void set_notify_resume(str > > * asynchronously, this will be called again before we return to > > * user mode. > > * > > - * Called without locks. > > + * Called without locks. However, on some machines this may be > > + * called with interrupts disabled. > > */ > > static inline void tracehook_notify_resume(struct pt_regs *regs) > > { > > + struct task_struct *task = current; > > + /* > > + * This pairs with the barrier implicit in set_notify_resume(). > > + * It ensures that we read the nonzero utrace_flags set before > > + * set_notify_resume() was called by utrace setup. > > + */ > > + smp_rmb(); > > + if (task_utrace_flags(task)) > > + utrace_resume(task, regs); > > } > > Sending an IPI implies the mb? Yes, but this has nothing to do with IPI. The caller, do_notify_resume(), does: clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume: if (task_utrace_flags(task)) utrace_resume(); We should not read task_utrace_flags() before we clear TIF_NOTIFY_RESUME. > > +static inline struct utrace *task_utrace_struct(struct task_struct *task) > > +{ > > + struct utrace *utrace; > > + > > + /* > > + * This barrier ensures that any prior load of task->utrace_flags > > + * is ordered before this load of task->utrace. We use those > > + * utrace_flags checks in the hot path to decide to call into > > + * the utrace code. The first attach installs task->utrace before > > + * setting task->utrace_flags nonzero, with a barrier between. > > + * See utrace_task_alloc(). > > + */ > > + smp_rmb(); > > + utrace = task->utrace; > > + > > + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ > > + return utrace; > > +} > > I spot two barriers here, but only 1 over in utrace_task_alloc(), hmm? smp_read_barrier_depends() pairs with utrace_task_alloc()->wmb(). smp_rmb() is needed for another reason. Suppose the code does: if (task_utrace_flags() & SOMETHING) do_something_with(task->utrace); if we race with utrace_attach_task(), we can see ->utrace_flags != 0 but task->utrace == NULL without rmb(). > > +struct utrace_engine { > > +/* private: */ > > + struct kref kref; > > + void (*release)(void *); > > + struct list_head entry; > > + > > +/* public: */ > > + const struct utrace_engine_ops *ops; > > + void *data; > > + > > + unsigned long flags; > > +}; > > Sorry, the kernel is written in C, not C++. Hmm. I almost never read the comments, but these 2 look very clear to me ;) > > + * Most callbacks take an @action argument, giving the resume action > > + * chosen by other tracing engines. All callbacks take an @engine > > + * argument, and a @task argument, which is always equal to @current. > > Given that some functions have a lot of arguments (depleting regparam), > isn't it more expensive to push current on the stack than it is to > simply read it again? Yes, perhaps. Only ->report_reap() really needs @task, it may be !current. > > +struct utrace_engine_ops { > > > + u32 (*report_signal)(u32 action, > > + struct utrace_engine *engine, > > + struct task_struct *task, > > + struct pt_regs *regs, > > + siginfo_t *info, > > + const struct k_sigaction *orig_ka, > > + struct k_sigaction *return_ka); > > > + u32 (*report_clone)(enum utrace_resume_action action, > > + struct utrace_engine *engine, > > + struct task_struct *parent, > > + unsigned long clone_flags, > > + struct task_struct *child); > > > +}; > > Seems inconsistent on u32 vs enum utrace_resume_action. Well, this u32 can hold utrace_resume_action | utrace_signal_action, for example. > > +struct utrace_examiner { > > +/* private: */ > > + long state; > > + unsigned long ncsw; > > +}; > > Again, its not C++, if you want a private state like that, use an opaque > type, like: > > struct utrace_examiner; > > and only define the thing in utrace.c or something. Then the caller of utrace_prepare_examine() has to alloc utrace_examiner somehow. I disagree here. But of course we can remove this comment. > > +static inline __must_check int utrace_control_pid( > > + struct pid *pid, struct utrace_engine *engine, > > + enum utrace_resume_action action) > > +{ > > + /* > > + * We don't bother with rcu_read_lock() here to protect the > > + * task_struct pointer, because utrace_control will return > > + * -ESRCH without looking at that pointer if the engine is > > + * already detached. A task_struct pointer can't die before > > + * all the engines are detached in release_task() first. > > + */ > > + struct task_struct *task = pid_task(pid, PIDTYPE_PID); > > + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); > > +} > > Is that comment correct? Without rcu_read_lock() the pidhash can change > under our feet and maybe cause funny things? If pid itself can't go away, it is always safe to use pid_task(). Yes, we can't trust the returned value, that is why utrace_control() verifies this task_struct* is still valid. > Does pid_task() in generaly rely on havin rcu_read_lock() called? See above. pid_task() itself doesn't need rcu_read_lock(), but without rcu lock around you can't simply use the result. > > +static bool utrace_task_alloc(struct task_struct *task) > > +{ > > + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); > > + if (unlikely(!utrace)) > > + return false; > > + spin_lock_init(&utrace->lock); > > + INIT_LIST_HEAD(&utrace->attached); > > + INIT_LIST_HEAD(&utrace->attaching); > > + utrace->resume = UTRACE_RESUME; > > + task_lock(task); > > + if (likely(!task->utrace)) { > > + /* > > + * This barrier makes sure the initialization of the struct > > + * precedes the installation of the pointer. This pairs > > + * with smp_read_barrier_depends() in task_utrace_struct(). > > + */ > > + smp_wmb(); > > + task->utrace = utrace; > > + } > > + task_unlock(task); > > + /* > > + * That unlock after storing task->utrace acts as a memory barrier > > + * ordering any subsequent task->utrace_flags store afterwards. > > + * This pairs with smp_rmb() in task_utrace_struct(). > > + */ > > + if (unlikely(task->utrace != utrace)) > > + kmem_cache_free(utrace_cachep, utrace); > > + return true; > > +} > > Again, not sure we can pair an UNLOCK-barrier with a RMB. In fact, both > are NOPs on x86. We can't. I think the comment is confusing. We need the barrier between setting "task->utrace = utrace" and changing ->utrace_flags. We have unlock+lock in between, this implies mb(). > > +static inline int utrace_attach_delay(struct task_struct *target) > > +{ > > + if ((target->flags & PF_STARTING) && > > + task_utrace_struct(current) && > > + task_utrace_struct(current)->cloning != target) > > + do { > > + schedule_timeout_interruptible(1); > > + if (signal_pending(current)) > > + return -ERESTARTNOINTR; > > + } while (target->flags & PF_STARTING); > > + > > + return 0; > > +} > > Quite gross this.. can't we key off the > tracehoook_report_clone_complete() and use a wakeup there? Yes, it would be very nice to avoid this schedule_timeout_interruptible(). But currently we don't see a simple solution, on the TODO list. But, to clarify, this case is very unlikely. > Furthermore I'd add a function like: > > static struct utrace_engine_ops * > get_utrace_ops(struct utrace_engine *engine, unsigned long *flags) > { > *flags = engine->flags; > /* > * This pairs with the barrier in mark_engine_detached(). > * It makes sure that we never see the old ops vector with > * the new flags, in case the original vector had no > * report_quiesce. > */ > smp_rmb(); > return engine->ops; > } > > to take out and explicitly comment that common bit. > > Also, I'm not quite sure on why we play so many barrier games, looking > at start_callback() we have 2 barriers in the callback loop, why not a > per engine lock? Exactly to avoid the lock, I guess ;) > > + /* > > + * In theory spin_lock() doesn't imply rcu_read_lock(). > > + * Once we clear ->utrace_flags this task_struct can go away > > + * because tracehook_prepare_release_task() path does not take > > + * utrace->lock when ->utrace_flags == 0. > > + */ > > + rcu_read_lock(); > > + task->utrace_flags = flags; > > + spin_unlock(&utrace->lock); > > + rcu_read_unlock(); > > yuck! > > why not simply keep a task reference over the utrace_reset call? Yes, we could use get_task_struct() instead. Not sure this would be more clean, though. > > +static void utrace_stop(struct task_struct *task, struct utrace *utrace, > > + enum utrace_resume_action action) > > ... > > + /* > > + * If ptrace is among the reasons for this stop, do its > > + * notification now. This could not just be done in > > + * ptrace's own event report callbacks because it has to > > + * be done after we are in TASK_TRACED. This makes the > > + * synchronization with ptrace_do_wait() work right. > > + */ > > + ptrace_notify_stop(task); > > Well, this is a bit disappointing isn't it? So we cannot implement > ptrace on utrace without special purpose hooks? Yes, currently we need the special hook for ptrace. Because ptrace is really special, no other engine should cooperate with do_wait/etc. That said, I agree. We need something more general which could be used by other engines too. > > +static enum utrace_resume_action start_report(struct utrace *utrace) > > +{ > > + enum utrace_resume_action resume = utrace->resume; > > + if (utrace->pending_attach || > > + (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { > > + spin_lock(&utrace->lock); > > + splice_attaching(utrace); > > + resume = utrace->resume; > > + if (resume > UTRACE_INTERRUPT) > > + utrace->resume = UTRACE_RESUME; > > + spin_unlock(&utrace->lock); > > + } > > + return resume; > > +} > > Its not entirely clear why we can check pending_attach outside of the > utrace->lock and not be racy. We can safely miss utrace->pending_attach here, or even read the "stale" utrace->resume. Both can be changed after start_report(). > > +static inline void finish_callback_report(struct task_struct *task, > > + struct utrace *utrace, > > + struct utrace_report *report, > > + struct utrace_engine *engine, > > + enum utrace_resume_action action) > > +{ > > + /* > > + * If utrace_control() was used, treat that like UTRACE_DETACH here. > > + */ > > + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { > > + engine->ops = &utrace_detached_ops; > > + report->detaches = true; > > + return; > > + } > > + > > + if (action < report->action) > > + report->action = action; > > + > > + if (action != UTRACE_STOP) { > > + if (action < report->resume_action) > > + report->resume_action = action; > > + > > + if (engine_wants_stop(engine)) { > > + spin_lock(&utrace->lock); > > + clear_engine_wants_stop(engine); > > + spin_unlock(&utrace->lock); > > + } > > Reads funny, but I guess it can only race the right way round? Not sure I understand... could you explain? > > + /* > > + * This is a good place to make sure tracing engines don't > > + * introduce too much latency under voluntary preemption. > > + */ > > + if (need_resched()) > > + cond_resched(); > > Simply cond_resched() is sufficient, but that comment sucks, as it > doesn't mention _why_ it is a good place. Hmm, I agree. > > + /* > > + * For a vfork, we will go into an uninterruptible block waiting > > + * for the child. We need UTRACE_STOP to happen before this, not > > + * after. For CLONE_VFORK, utrace_finish_vfork() will be called. > > + */ > > + if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { > > + spin_lock(&utrace->lock); > > + utrace->vfork_stop = 1; > > + spin_unlock(&utrace->lock); > > + } > > So much optimization, weird locking, barriers and here you didn't use > atomic bit ops? The point is, the state of the tracee must be "stable" under utrace->lock. As for ->vfork_stop in particular, it should die (imho) but we need further cleanups outside of utrace.c. > > +void utrace_finish_vfork(struct task_struct *task) > > +{ > > + struct utrace *utrace = task_utrace_struct(task); > > + > > + if (utrace->vfork_stop) { > > + spin_lock(&utrace->lock); > > + utrace->vfork_stop = 0; > > + spin_unlock(&utrace->lock); > > + utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ > > + } > > +} > > I'm sure that XXX means something,... again that vfork_stop stuff can > only race the right way about, right? UTRACE_RESUME is not exactly right, we have the pending patches but need more discussion. > > +void utrace_report_jctl(int notify, int what) > > +{ > > + struct task_struct *task = current; > > + struct utrace *utrace = task_utrace_struct(task); > > + INIT_REPORT(report); > > + > > + spin_unlock_irq(&task->sighand->siglock); > > + > > + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), > > + report_jctl, what, notify); > > + > > + spin_lock_irq(&task->sighand->siglock); > > +} > > So much documentation, and non of it says that the JCTL (funny name btw) > callback is done holding siglock... tskk. Not sure I understand, but we unlock ->siglock before REPORT(). If you mean that utrace_report_jctl() is called under ->siglock, then yes. Oleg. From roland at redhat.com Tue Dec 1 23:47:04 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 1 Dec 2009 15:47:04 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Andi Kleen's message of Tuesday, 24 November 2009 21:32:27 +0100 <87my2bwtno.fsf@basil.nowhere.org> References: <20091124200220.GA5828@redhat.com> <87my2bwtno.fsf@basil.nowhere.org> Message-ID: <20091201234704.40D4D86D@magilla.sf.frob.com> > Could we just drop the tracehook layer if this finally merged > and call the low level functions directly? We can certainly do appropriate streamlining cleanups later, by all means. The original purpose of the tracehook layer is simply this: A person hacking on core kernel code or arch code should not have to think about all the innards of tracing (ptrace, utrace, or anything else). If he comes across a tracehook_* call, he can just read its kernel-doc for explanation of its parameters, return value, what it expects about its context (locking et al), and what the semantic significance of making that particular call is. If changes to the core/arch code in question do not require changing any of those aspects, then said person need not consider tracing issues further. If a change to a function's calling interface or contextual assumptions looks warranted, then he knows he should discuss the details with some tracing-related folks (i.e. find tracehook.h in MAINTAINERS and thus get to me and Oleg). Likewise, a person hacking on tracing code should not have to think about every corner of interaction with the core code or arch code. Each tracehook_* call's kernel-doc comments say everything that matters about how and where it's called. If some of those details are problematic for what we want to do inside the tracing code, then we know we have to hash out the details with the maintainers of the core or arch code that makes those calls. Otherwise we can keep our focus on tracing infrastructure without spending time getting lost in arcane details of the arch or core kernel code. These two things seem permanently worthwhile to me: that the core and arch source code use simple function calls without open-coding any innards of the tracing infrastructure; and that these functions have clear and complete documentation about their calling interfaces and context (locking et al). I find it natural and convenient that such calls have a common prefix that makes it obvious to any reader of the core code what subsystem the call relates to. Beyond those ideas, I certainly don't care at all what the names of these functions are, what common prefix is used, or in which source files those declarations and kernel-doc comments appear. Thanks, Roland From roland at redhat.com Wed Dec 2 00:46:43 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 1 Dec 2009 16:46:43 -0800 (PST) Subject: [RFC,PATCH 0/14] utrace/ptrace In-Reply-To: Oleg Nesterov's message of Thursday, 26 November 2009 15:27:45 +0100 <20091126142745.GA4382@redhat.com> References: <20091124200127.GA5751@redhat.com> <20091125214818.GA4916@infradead.org> <20091126091052.GF1389@elte.hu> <20091126104722.GA8316@infradead.org> <20091126142745.GA4382@redhat.com> Message-ID: <20091202004643.C9B26258B@magilla.sf.frob.com> Note to all: I'm on the road this week (having had a holiday last week) and will be somewhat slow in replying on these threads, but I will be sure to get to them all. > Yes, nobody likes 2 implementations. I guess Roland and me hate > CONFIG_UTRACE much more than anybody else. :-) We both hate maintaining the old ptrace implementation, that is true! The other thing we hate is having our work delayed arbitrarily again and again to wait for the arch maintainers of arch's we don't use ourselves. Oleg and I have been trying to follow the advice we get on how to get this work merged in. When multiple gate-keepers give conflicting advice, we really don't know what to do next. Our interest is in whatever path smooths the merging of our work. We'd greatly prefer to spend our time hacking on our new code to make it better or different in cool and useful ways than to spend more time guessing what order of patches and rejuggling of the work will fit the changing whims of the next round of review. We don't want to rush anyone, like uninterested arch maintainers. We don't want to break anyone who doesn't care about our work (we do test for ptrace regressions but of course new code will always have new bugs so some instances of instability in the transition to a new ptrace implementation have to be expected no matter how hard we try). We just don't want to keep working out of tree. The advantage of making the new code optional is, obviously, that you can turn it off. That is, lagging arch's won't be broken, just unable to turn it on. And, anyone who doesn't want to try anything new yet can just turn it off and not be exposed to new code. The advantage of making the new code nonoptional is, obviously, that you can't turn it off. The old implementation will be gone and we won't have to maintain it any more (outside some -stable streams for a while). The kernel source will be cleaner with no optional old cruft code duplicating functionality. All ptrace users will be testing the new code, and so we'll find its bugs and gain confidence that it works solidly. Like I've said, we want to do whatever the people want. My concern about what Christoph has suggested is that it really seems like an open-ended delay depending on some arch people who are not even in the conversation. For anyone either who likes utrace or who is concerned about its details, the sooner we are working in-tree the sooner we can really hash it out thoroughly and get to having merged code that works well. As long as there is anything unfinished like arch work that we've decided is a gating event, then the review and hashing out of the new code itself does not seem to get very serious. (To wit, this thread is still talking about merge order and such, another long thread was about incidental trivia, and we've only just started to see a tiny bit of actual code review today.) Thanks, Roland From roland at redhat.com Wed Dec 2 05:44:59 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 1 Dec 2009 21:44:59 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Peter Zijlstra's message of Tuesday, 1 December 2009 20:54:02 +0100 <1259697242.1697.1075.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> Message-ID: <20091202054459.98AB5BD8F@magilla.sf.frob.com> > This above text seems inconsistent. First you say report_reap() is the > final callback and should be used for cleanup, then you say > report_death() is the penultimate callback but might not always happen > and people would normally use that as cleanup. > > If we cannot rely on report_death() then I would suggest to simply > recommend report_reap() as cleanup callback and leave it at that. I'm sorry the explanation was not clear to you. I'll try to make it clear now and then I'd appreciate your suggestions on how the documentation could be worded better. (I do appreciate your suggestion here but it's one based on an idea that's not factual, so I don't think we should follow it.) There is no "unreliable" aspect to it. If you call utrace_set_events() to ask for report_death() callbacks then you will get that callback for that task--guaranteed--unless utrace_set_events() returned an error code that tells you unambiguously that you could not get that callback. What's true is that report_reap() is the last callback you can ever get for a given task. If you had asked for report_death() callbacks, then you always get report_death() and if you've asked for both these callbacks then report_death() is always before report_reap(). (This is a special ordering guarantee, because in actuality the release_task() call that constitutes "reap" can happen in the parent simultaneously with the task's own exit path.) The one situation in which you cannot get report_death() is when the task was already dead when you called utrace_set_events(). In that case, it gives an error code as I mentioned above. Even in that situation, you can still ask to enable just the report_reap() callback. With either of these, if you enabled it successfully, then you are guaranteed to get it. When you get report_death() and are not interested in getting report_reap() afterwards, then you can return UTRACE_DETACH from report_death(). If you don't detach, then you will get report_reap() later too. The documentation mentions using report_death() to detach and clean up because many kinds of uses will have no interest in report_reap() at all. The only reason to get a report_reap() callback is if you are interested in tracking when a task's (real) parent reaps it with wait* calls, but usually people are only really interested in a task until it dies. > > + > > + There is nothing a kernel module can do to keep a struct > > + task_struct alive outside of > > + rcu_read_lock. > > Sure there is, get_task_struct() comes to mind. __put_task_struct() is not exported to modules and so put_task_struct() cannot be used by modules. > > + still valid until rcu_read_unlock. The > > + infrastructure never holds task references of its own. > > And here you imply its existence. [I take it this refers to the next quoted bit:] > > Though neither > > + rcu_read_lock nor any other lock is held while > > + making a callback, it's always guaranteed that the struct > > + task_struct and the struct > > + utrace_engine passed as arguments remain valid > > + until the callback function returns. No, we do not imply that the utrace infrastructure holds any task reference. The current task_struct is always live while it's running and until it's passed to release_task(). The task_struct passed to callbacks is current. That's all it means. The true facts are that utrace callbacks are all made in the current task except for report_reap(), which is made at the start of release_task(). So the kernel's core logic is holding a task reference at all times that utrace callbacks are made. If you really think it is clearer to explain that set of facts as "utrace holds a reference", then please suggest the exact wording you have in mind. > The above seems weird to me at best... why hold a pid around when you > can keep a ref on the task struct? A pid might get reused leaving you > with a completely different task than you thought you had. The *_pid interfaces are only there because put_pid() can be used by modules while put_task_struct() cannot. If we can make __put_task_struct() an exported symbol again, I would see no reason for these *_pid calls. > Right, except you cannot generally rely on this report_death() thing, so > a trace engine needs to deal with the report_reap() thing anyway. This is a false antecedent. I hope the explanation above made this subject clear to you. > > + Interlock with final callbacks [...] > Hrmm, better mention this earlier, or at least refer to this when > describing the above cleanup bits. This explanation is somewhat long and has its own whole section so as to be thoroughly explicit and clear. Do you think there should just be a cross reference here in the earlier mention of report_reap() and report_death()? Or do you think that the "Final callbacks" text should be merged together with the "Interlock" section? > > + an error if the task is not properly stopped and not dead. > > 'or' dead? Yes, fixed. Thanks! I've relied on Oleg to review and fix the barrier-related logic. So I'll leave it to him to hash out those parts of the review. > Can the compiler optimize away the callsite using weak functions like > this? If not I think the normal static inline stubs make more sense. I'm not sure I understand the question. If the !CONFIG_UTRACE case, this all boils down to "if (0) utrace_foo(...);" calls after constant folding. I think the compiler will always compile those out, but I'm not entirely sure about all old compilers or about -O0. > Also, what unoptimized compilation? If there really is none then I guess there isn't a problem. We can just drop these weak attributes and the dead calls will be optimized away before link time anyway. If we are not positive that is going to fly everywhere, then I have no objection to adding static inline stubs in the #else branch if you think that is preferable. > Right, so this lot doesn't seem very consistent. Please explain what kind of consistency you have in mind. I don't follow. > At the very least I would put signal action and syscall action into > different ranges. Those two can never be used in the same place. So I don't really understand that. It doesn't matter what their values are, so I don't have a problem with changing them to be disjoint. But I don't understand why it would be better in any way at all. > Sorry, the kernel is written in C, not C++. We know that perfectly well, and I haven't been able ascertain what benefit you gain by being snide. Our code follows the instructions in Documentation/kernel-doc-nano-HOWTO.txt, so if you have a complaint with that established practice recommened for the kernel please take it up with the appropriate maintainers. We're following what the kernel's own documentation tells us to do. If you use /** for a struct and omit @field for some fields, then you get warnings from make *docs. If you omit all the fields (because none are part of the documented API, such as in struct utrace_examiner), then you get a build error. So unless kernel-doc changes, the options are to follow its specified /* private: */ convention as we do now, to add a bunch of "@field: this is an internal field, do not touch it" comments, or to punt on kernel-doc for these structs. Which do you want? > Again, its not C++, if you want a private state like that, use an opaque > type, like: > > struct utrace_examiner; > > and only define the thing in utrace.c or something. Again, we are following the kernel-doc instructions for this situation. If you look at the uses of this type in the interface, you'll see that its purpose is to have the caller allocate the space. The only way to make it opaque would be to use a pointer type and do dynamic allocation inside some utrace.c function. That would be inane for holding two words needed momentarily during one caller's frame. > Given that some functions have a lot of arguments (depleting regparam), > isn't it more expensive to push current on the stack than it is to > simply read it again? Perhaps so. The only callback where the task argument is not current is report_reap(). That one already differs from the calling pattern of all the others because it has no return value. So I guess we could drop the task argument to all the "normal" report_* calls. I'll pick up with responding to the rest of your remarks as soon as I can. (Right now I have to prepare for an airplane early in the morning.) Thanks, Roland From cornel at upload-ro.ro Wed Dec 2 11:02:59 2009 From: cornel at upload-ro.ro (CURSURI GRATUITE ONLINE) Date: Wed, 2 Dec 2009 13:02:59 +0200 Subject: invitatie la cursuri gratuite online Message-ID: <20091202.YMAYYGSPOWYSMILW@upload-ro.ro> An HTML attachment was scrubbed... URL: From newsletter at brinde-companhia.com Wed Dec 2 16:29:23 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Wed, 2 Dec 2009 17:29:23 +0100 Subject: Colheita Especial... Message-ID: <11b4bc353ba1fda1de044c1cdf94f151@newsletter2.brinde-companhia.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Dec 2 18:34:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Dec 2009 19:34:46 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1259697242.1697.1075.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> Message-ID: <20091202183446.GA14799@redhat.com> On 12/01, Peter Zijlstra wrote: > > > +static inline __must_check int utrace_control_pid( > > + struct pid *pid, struct utrace_engine *engine, > > + enum utrace_resume_action action) > > +{ > > + /* > > + * We don't bother with rcu_read_lock() here to protect the > > + * task_struct pointer, because utrace_control will return > > + * -ESRCH without looking at that pointer if the engine is > > + * already detached. A task_struct pointer can't die before > > + * all the engines are detached in release_task() first. > > + */ > > + struct task_struct *task = pid_task(pid, PIDTYPE_PID); > > + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); > > +} > > Is that comment correct? Without rcu_read_lock() the pidhash can change > under our feet and maybe cause funny things? I already tried to answer, but I guess my email was not very clear. Let me try again. pid_task() by itself is safe, but yes, it is possible that utrace_control() is called with target == NULL, or this task_task was already freed/reused. utrace_control(target) path does not use target until it verifies it is safe to dereference it. get_utrace_lock() calls rcu_read_lock() and checks that engine->ops is not cleared (NULL or utrace_detached_ops). If we see the valid ->ops under rcu_read_lock() it is safe to dereference target, even if we race with release_task() we know that it has not passed utrace_release_task() yet, and thus we know call_rcu(delayed_put_task_struct) was not yet called _before_ we took rcu_read_lock(). If it is safe to dereference target, we can take utrace->lock. Once we take this lock (and re-check engine->ops) the task can't go away until we drop it, get_utrace_lock() drops rcu lock and returns with utrace->lock held. utrace_control() can safely play with target under utrace->lock. > > + /* > > + * If this flag is still set it's because there was a signal > > + * handler setup done but no report_signal following it. Clear > > + * the flag before we get to user so it doesn't confuse us later. > > + */ > > + if (unlikely(utrace->signal_handler)) { > > + spin_lock(&utrace->lock); > > + utrace->signal_handler = 0; > > + spin_unlock(&utrace->lock); > > + } > > OK, so maybe you get to explain why this works.. Missed this part yesterday. Well. ->signal_handler is set by handle_signal() when the signal was delivered to the tracee. This flag is checked by utrace_get_signal() to detect the stepping. But we should not return to user-mode with this flag set, that is why utrace_resume() clears it. However. This reminds me we were going to try to simplify this logic, I'll try to think about this. Oleg. From oleg at redhat.com Wed Dec 2 18:49:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 2 Dec 2009 19:49:38 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1259697242.1697.1075.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> Message-ID: <20091202184938.GB14799@redhat.com> On 12/01, Peter Zijlstra wrote: > > > +void utrace_resume(struct task_struct *task, struct pt_regs *regs) > > +{ > > + struct utrace *utrace = task_utrace_struct(task); > > + INIT_REPORT(report); > > + struct utrace_engine *engine; > > + > > + /* > > + * Some machines get here with interrupts disabled. The same arch > > + * code path leads to calling into get_signal_to_deliver(), which > > + * implicitly reenables them by virtue of spin_unlock_irq. > > + */ > > + local_irq_enable(); > > Hrmm, I would much prefer to fix up the calling conventions of > tracehook_notify_resume() than to bury something like this in the guts > of a tracehook user. Missed this part too. May be, I dunno... But in any case, imho it would be better to do this after we merge utrace, otherwise we need more subtle arch-dependent changes before. Oleg. From envoi at bdop89.info Thu Dec 3 11:05:46 2009 From: envoi at bdop89.info (Newzy) Date: Thu, 3 Dec 2009 13:05:46 +0200 Subject: Le Guide du Haut Management et son fichier gratuit Message-ID: <74d339de18c7766ec2b6cb1506b9c6b1@om4.market-products.com> An HTML attachment was scrubbed... URL: From news at maisservicos.com Fri Dec 4 00:30:15 2009 From: news at maisservicos.com (twingle) Date: Fri, 4 Dec 2009 00:30:15 +0000 Subject: Leiloes online a precos incriveis!!! Message-ID: <20091204003014.16D363F239@server17.nortenet.pt> NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From furbish at cpeck.net Fri Dec 4 06:16:54 2009 From: furbish at cpeck.net (Muller Y Janna) Date: 4 Dec 2009 00:16:54 -0600 Subject: Yes I have dental and medical lists Message-ID: Spesial Med Package 395.00 Complete Physician Database 788,114 in total * 17,482 emails Coverage in many different areas of medicine such as Endocrinology, Pathology, Urology, Neurology, Plastic Surgery, Psychiatry, Cardiology and much more Also included are the 6 bonus listed below: 1=7145 Hospitals*23,000 Administrators with Ph/fax and postal address. 2=Licensed Clinic/Dentist 597,959 Total Records*6,494 Emails*6,000 Fax Numbers. 3=US Pharmaceutical Company 47,000 employees in high-ranking positions Executive's Directory Names and email addresses of 4=Chiropractors*108,421 with phone, 3,414 emails and 6,553 fax numbers. 5=Acupuncture Database 23,988 records 1,826 emails 6=Alternative Medicine Clinics and Practitioners Database There are 1,141,602 total records with 29,320 emails and 38.935 fax numbers. For a datacard reply here Warren at bestbizlists.info contact rembox at bestbizlists.info for record exclusion. From oleg at redhat.com Fri Dec 4 17:25:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Dec 2009 18:25:35 +0100 Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <20091204163929.72FBE39C4B@pipsqueak.sf.frob.com> References: <1968871264.1037561259907568457.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1588725216.1042441259919625479.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091204110507.GA19019@redhat.com> <20091204144710.GA28748@redhat.com> <20091204163929.72FBE39C4B@pipsqueak.sf.frob.com> Message-ID: <20091204172535.GA4101@redhat.com> On 12/04, Roland McGrath wrote: > > > I think the problem is clear now. > > Ok. We should probably move this discussion to utrace-devel. Yes, I didn't notice we discuss this offlist... > > I forgot that there is another issue (iirc a bit discussed too). > > finish_callback_report() sets ->ops = utrace_detached_ops lockless! > > You'll have to remind me why this is a problem. Re: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops https://www.redhat.com/archives/utrace-devel/2009-October/msg00180.html We already discussed this, but forgot to finish. Do you agree with the patch? ------------------------------------------------------------------------------ [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless finish_callback_report() changes ->ops lockless. Imho this is not right "in general", the state of !EXIT_DEAD tracee must be stable under utrace->lock. And this can confuse ptrace_reuse_engine()->utrace_barrier() logic. utrace_barrier() can race with reporting loop and return 0 while engine was already detached or in the middle of detach. See also https://www.redhat.com/archives/utrace-devel/2009-October/msg00180.html Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~DONT_CHANGE_OPS_LOCKLESS 2009-11-24 17:20:33.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-12-04 17:10:37.000000000 +0100 @@ -1390,11 +1390,15 @@ static inline void finish_callback_repor struct utrace_engine *engine, enum utrace_resume_action action) { + if (action == UTRACE_DETACH) { + spin_lock(&utrace->lock); + engine->ops = &utrace_detached_ops; + spin_unlock(&utrace->lock); + } /* * If utrace_control() was used, treat that like UTRACE_DETACH here. */ - if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { - engine->ops = &utrace_detached_ops; + if (engine->ops == &utrace_detached_ops) { report->detaches = true; return; } From oleg at redhat.com Fri Dec 4 18:27:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 4 Dec 2009 19:27:18 +0100 Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <20091204172535.GA4101@redhat.com> References: <1968871264.1037561259907568457.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1588725216.1042441259919625479.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091204110507.GA19019@redhat.com> <20091204144710.GA28748@redhat.com> <20091204163929.72FBE39C4B@pipsqueak.sf.frob.com> <20091204172535.GA4101@redhat.com> Message-ID: <20091204182718.GA7153@redhat.com> Forgot to mention, I did a lot of testing on ppc machine and the patch helps, finally I was able to reproduce the problem. But I failed to install the kernel on Cai's machine, perhaps he could test the patch too ;) fighting with rhts machines is very tiresome and time consuming... I'll send the promised patch which kills supress_sigtrap() tomorrow, it needs testing/checking. On 12/04, Oleg Nesterov wrote: > > On 12/04, Roland McGrath wrote: > > > > > I think the problem is clear now. > > > > Ok. We should probably move this discussion to utrace-devel. > > Yes, I didn't notice we discuss this offlist... > > > > I forgot that there is another issue (iirc a bit discussed too). > > > finish_callback_report() sets ->ops = utrace_detached_ops lockless! > > > > You'll have to remind me why this is a problem. > > Re: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops > https://www.redhat.com/archives/utrace-devel/2009-October/msg00180.html > > We already discussed this, but forgot to finish. > > Do you agree with the patch? > > ------------------------------------------------------------------------------ > [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless > > finish_callback_report() changes ->ops lockless. Imho this is not > right "in general", the state of !EXIT_DEAD tracee must be stable > under utrace->lock. > > And this can confuse ptrace_reuse_engine()->utrace_barrier() logic. > utrace_barrier() can race with reporting loop and return 0 while > engine was already detached or in the middle of detach. > > See also https://www.redhat.com/archives/utrace-devel/2009-October/msg00180.html > > Signed-off-by: Oleg Nesterov > --- > > kernel/utrace.c | 8 ++++++-- > 1 file changed, 6 insertions(+), 2 deletions(-) > > --- UTRACE-PTRACE/kernel/utrace.c~DONT_CHANGE_OPS_LOCKLESS 2009-11-24 17:20:33.000000000 +0100 > +++ UTRACE-PTRACE/kernel/utrace.c 2009-12-04 17:10:37.000000000 +0100 > @@ -1390,11 +1390,15 @@ static inline void finish_callback_repor > struct utrace_engine *engine, > enum utrace_resume_action action) > { > + if (action == UTRACE_DETACH) { > + spin_lock(&utrace->lock); > + engine->ops = &utrace_detached_ops; > + spin_unlock(&utrace->lock); > + } > /* > * If utrace_control() was used, treat that like UTRACE_DETACH here. > */ > - if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { > - engine->ops = &utrace_detached_ops; > + if (engine->ops == &utrace_detached_ops) { > report->detaches = true; > return; > } From roland at redhat.com Fri Dec 4 18:47:26 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 4 Dec 2009 10:47:26 -0800 (PST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: Oleg Nesterov's message of Friday, 4 December 2009 18:25:35 +0100 <20091204172535.GA4101@redhat.com> References: <1968871264.1037561259907568457.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1588725216.1042441259919625479.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091204110507.GA19019@redhat.com> <20091204144710.GA28748@redhat.com> <20091204163929.72FBE39C4B@pipsqueak.sf.frob.com> <20091204172535.GA4101@redhat.com> Message-ID: <20091204184726.5CBAD39C4B@pipsqueak.sf.frob.com> > > > I forgot that there is another issue (iirc a bit discussed too). > > > finish_callback_report() sets ->ops = utrace_detached_ops lockless! > > > > You'll have to remind me why this is a problem. > > Re: [PATCH 85] ptrace_attach_task: rely on utrace_barrier(), don't check ->ops > https://www.redhat.com/archives/utrace-devel/2009-October/msg00180.html > > We already discussed this, but forgot to finish. Ah, yes. I had that message still sitting in my folder to think about again and reply. > Do you agree with the patch? I think so, yes. It could use some more comments about the importance of the lock. I added a comment and merged it in. Thanks, Roland From caiqian at redhat.com Sat Dec 5 02:28:27 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Fri, 4 Dec 2009 21:28:27 -0500 (EST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <382193103.1103961259979855047.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1606635631.1103981259980107265.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > But I failed to install the kernel on Cai's machine, perhaps he > could test the patch too ;) Yes, I'll test it there. What the problem do you have to install the kernel? I have noted the /boot is running out of the space there, I suppose you met the same problem as me before, that CONFIG_DEBUG_KERNEL needed to set to N, if "make install" was used to install the kernels. Otherwise, the image can be too large to fit in 200M /boot setup there. Thanks, CAI Qian From ICQ.Greetings at icq.com Sat Dec 5 01:10:17 2009 From: ICQ.Greetings at icq.com (ICQ Greetings) Date: Fri, 4 Dec 2009 20:10:17 -0500 (EST) Subject: Your friend has sent you an ICQ Greeting Card! Message-ID: <20091205011017.7F3C8184664B@mail.cruisesystem.com> An HTML attachment was scrubbed... URL: From mariavilan at yahoo.com.br Tue Nov 24 09:24:56 2009 From: mariavilan at yahoo.com.br (CJP - Soluções em Publicidade) Date: Tue, 24 Nov 2009 09:24:56 GMT Subject: Servidor Dedicado para Newsletter Message-ID: <200912050709.nB579iYJ031544@mx1.redhat.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Sat Dec 5 16:06:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 5 Dec 2009 17:06:18 +0100 Subject: [PATCH 141] kill suppress_sigtrap() Message-ID: <20091205160618.GA22555@redhat.com> You are right, thanks, suppress_sigtrap() is no longer needed. Surprisingly, it even has the comment which explains why it was needed before, and since the recent changes SIGTRAP from tracehook_report_syscall_exit() pathes is just not possible with utrace. This should also fix the compilation on s390. --- kernel/ptrace-utrace.c | 19 +------------------ 1 file changed, 1 insertion(+), 18 deletions(-) --- UTRACE-PTRACE/kernel/ptrace-utrace.c~141_KILL_SUPPRESS_SIGTRAP 2009-12-04 16:19:17.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace-utrace.c 2009-12-05 16:16:15.000000000 +0100 @@ -324,16 +324,6 @@ static void ptrace_clone_attach(struct t set_tsk_thread_flag(child, TIF_SIGPENDING); } -/* - * Prevents sending SIGTRAP after tracehook_report_syscall_exit(). - * Called when we are going to emulate the stop before SYSCALL_EXIT. - */ -static void suppress_sigtrap(struct task_struct *task) -{ - if (test_tsk_thread_flag(task, TIF_SINGLESTEP)) - user_disable_single_step(task); -} - static u32 ptrace_report_clone(enum utrace_resume_action action, struct utrace_engine *engine, struct task_struct *parent, @@ -369,8 +359,6 @@ static u32 ptrace_report_clone(enum utra if (!event) return UTRACE_RESUME; - suppress_sigtrap(parent); - set_stop_code(ctx, event); ctx->eventmsg = child->pid; /* @@ -411,11 +399,8 @@ static u32 ptrace_report_syscall_entry(u set_syscall_code(ctx); - if (unlikely(ctx->options & PTRACE_O_SYSEMU)) { - suppress_sigtrap(task); + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; - } - /* * Stop now to report. We will get another callback after * we resume, with the UTRACE_SYSCALL_RESUMED flag set. @@ -465,9 +450,7 @@ static u32 ptrace_report_exec(enum utrac return UTRACE_RESUME; } - suppress_sigtrap(task); set_stop_code(ctx, PTRACE_EVENT_EXEC); - return UTRACE_STOP; } From oleg at redhat.com Sat Dec 5 16:06:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 5 Dec 2009 17:06:21 +0100 Subject: [PATCH 142] fix __must_check warnings Message-ID: <20091205160621.GA22559@redhat.com> Fix __must_check warnings. The change in ptrace_wake_up() just fools the compiler, we really don't care if utrace_control() fails or returns something like -EINPROGRESS. But we could add a "clever" WARN_ON(err..) perhaps. --- kernel/ptrace-utrace.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) --- UTRACE-PTRACE/kernel/ptrace-utrace.c~142_MUST_CHECK 2009-12-05 16:16:15.000000000 +0100 +++ UTRACE-PTRACE/kernel/ptrace-utrace.c 2009-12-05 16:48:48.000000000 +0100 @@ -216,7 +216,7 @@ static int ptrace_attach_task(struct tas return 0; } -static void ptrace_wake_up(struct task_struct *tracee, +static int ptrace_wake_up(struct task_struct *tracee, struct utrace_engine *engine, enum utrace_resume_action action, bool force_wakeup) @@ -236,7 +236,8 @@ static void ptrace_wake_up(struct task_s if (action != UTRACE_REPORT) ptrace_context(engine)->stop_code = 0; - utrace_control(tracee, engine, action); + + return utrace_control(tracee, engine, action); } static void ptrace_detach_task(struct task_struct *tracee, int sig) @@ -556,7 +557,8 @@ static u32 ptrace_report_signal(u32 acti * Make sure the subsequent UTRACE_SIGNAL_REPORT clears * ->siginfo before return from get_signal_to_deliver(). */ - utrace_control(task, engine, UTRACE_INTERRUPT); + if (utrace_control(task, engine, UTRACE_INTERRUPT)) + WARN_ON(1); ctx->signr = info->si_signo; ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; From oleg at redhat.com Sat Dec 5 16:19:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 5 Dec 2009 17:19:30 +0100 Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <1606635631.1103981259980107265.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <382193103.1103961259979855047.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1606635631.1103981259980107265.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091205161930.GA22920@redhat.com> On 12/04, caiqian at redhat.com wrote: > > > But I failed to install the kernel on Cai's machine, perhaps he > > could test the patch too ;) > > Yes, I'll test it there. What the problem do you have to install the > kernel? I have noted the /boot is running out of the space there, I > suppose you met the same problem as me before, that CONFIG_DEBUG_KERNEL > needed to set to N, if "make install" was used to install the > kernels. Otherwise, the image can be too large to fit in 200M /boot > setup there. Ahhh. So that is why I failed to install the kernel! Thanks a lot. I blindly copied .config from /boot/ to ensure I use the same config options for testing. I was going to try again, but noticed you already recompiled and booted the kernel. I see ./test is running and there is nothing bad in dmesg ;) Thanks! Oleg. From caiqian at redhat.com Sat Dec 5 16:29:23 2009 From: caiqian at redhat.com (CAI Qian) Date: Sat, 5 Dec 2009 11:29:23 -0500 (EST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <20091205161930.GA22920@redhat.com> Message-ID: <831145523.1106321260030563398.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > I was going to try again, but noticed you already recompiled and > booted the kernel. I see ./test is running and there is nothing bad > in dmesg ;) Yes, it looks good so far. Ptrace tests also does not show any regression. I kicked off a few tests on other platform, so hopefully have more information shortly. From caiqian at redhat.com Sat Dec 5 16:58:54 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Sat, 5 Dec 2009 11:58:54 -0500 (EST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <123494443.1106371260032288659.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <805584630.1106391260032334529.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Yes, it looks good so far. Ptrace tests also does not show any > regression. I said this too early. Looks like step-jump-count started to fail now. step-jump-cont: step-jump-cont.c:244: main: Assertion `0' failed. /bin/sh: line 5: 28212 Aborted ${dir}$tst FAIL: step-jump-cont You can login the same machine. # cd /mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests # make check From oleg at redhat.com Sat Dec 5 17:01:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 5 Dec 2009 18:01:12 +0100 Subject: [PATCH v2] ptrace-tests: fix step-fork.c on powerpc for ptrace-utrace In-Reply-To: <20091201173827.GC31242@darkmag.usersys.redhat.com> References: <20091201163748.GA5635@darkmag.usersys.redhat.com> <20091201172457.GB31242@darkmag.usersys.redhat.com> <20091201173827.GC31242@darkmag.usersys.redhat.com> Message-ID: <20091205170112.GA24811@redhat.com> Jan, this fixes step-fork.c on powerpc. Without this patch it just hangs, see http://marc.info/?t=125924748600001 On 12/01, Veaceslav Falico wrote: > > Instead of using fork(), call syscall(__NR_fork) in step-fork.c > to avoid looping on powerpc arch in libc. > > Signed-off-by: Veaceslav Falico > --- > > --- a/ptrace-tests/tests/step-fork.c 2009-12-01 17:17:14.000000000 +0100 > +++ b/ptrace-tests/tests/step-fork.c 2009-12-01 18:35:15.000000000 +0100 > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > #include > > #ifndef PTRACE_SINGLESTEP > @@ -78,7 +79,12 @@ main (int argc, char **argv) > sigprocmask (SIG_BLOCK, &mask, NULL); > ptrace (PTRACE_TRACEME); > raise (SIGUSR1); > - if (fork () == 0) > + > + /* > + * Can't use fork() directly because on powerpc it loops inside libc under > + * PTRACE_SINGLESTEP. See http://marc.info/?l=linux-kernel&m=125927241130695 > + */ > + if (syscall(__NR_fork) == 0) > { > read (-1, NULL, 0); > _exit (22); From caiqian at redhat.com Sat Dec 5 17:16:25 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Sat, 5 Dec 2009 12:16:25 -0500 (EST) Subject: step-into-handler.c compilation failure on ppc64 In-Reply-To: <1083746827.1106431260033379517.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <612312968.1106451260033385025.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> # make check ... gcc -DPACKAGE_NAME=\"ptrace\ regression\ test\ suite\" -DPACKAGE_TARNAME=\"ptrace-tests\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"ptrace\ regression\ test\ suite\ 0.1\" -DPACKAGE_BUGREPORT=\"utrace-devel at redhat.com\" -DPACKAGE=\"ptrace-tests\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -D__EXTENSIONS__=1 -D_ALL_SOURCE=1 -D_GNU_SOURCE=1 -D_POSIX_PTHREAD_SEMANTICS=1 -D_TANDEM_SOURCE=1 -I. -std=gnu99 -Wall -Werror -g -O2 -MT step-into-handler.o -MD -MP -MF .deps/step-into-handler.Tpo -c -o step-into-handler.o step-into-handler.c cc1: warnings being treated as errors step-into-handler.c: In function ?handler_alrm_get?: step-into-handler.c:116: error: dereferencing type-punned pointer will break strict-aliasing rules make[1]: *** [step-into-handler.o] Error 1 make[1]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests' make: *** [check] Error 2 There could be a better fix. This patch only add -fno-strict-aliasing to ignore the warning. -------------- next part -------------- A non-text attachment was scrubbed... Name: ppc64.patch Type: text/x-patch Size: 415 bytes Desc: not available URL: From roland at redhat.com Sat Dec 5 17:19:20 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 5 Dec 2009 09:19:20 -0800 (PST) Subject: step-into-handler.c compilation failure on ppc64 In-Reply-To: caiqian@redhat.com's message of Saturday, 5 December 2009 12:16:25 -0500 <612312968.1106451260033385025.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <1083746827.1106431260033379517.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <612312968.1106451260033385025.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091205171920.1CD8039C4B@pipsqueak.sf.frob.com> How about this? --- step-into-handler.c 10 Dec 2008 04:42:43 -0800 1.8 +++ step-into-handler.c 05 Dec 2009 09:18:54 -0800 @@ -35,6 +35,7 @@ #include #include #include +#include #if defined __x86_64__ #define REGISTER_IP regs.rip @@ -113,11 +114,11 @@ handler_alrm_get (void) { #if defined __powerpc64__ /* ppc64 `handler_alrm' resolves to the function descriptor. */ - return *(void **) handler_alrm; + return *(void **) (uintptr_t) handler_alrm; /* __s390x__ defines both the symbols. */ #elif defined __s390__ && !defined __s390x__ /* s390 bit 31 is zero here but I am not sure if it cannot be arbitrary. */ - return (void *) (0x7fffffff & (unsigned long) handler_alrm); + return (void *) (0x7fffffff & (uintptr_t) handler_alrm); #else return handler_alrm; #endif From oleg at redhat.com Sat Dec 5 17:14:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 5 Dec 2009 18:14:12 +0100 Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <805584630.1106391260032334529.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <123494443.1106371260032288659.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <805584630.1106391260032334529.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091205171412.GB24811@redhat.com> On 12/05, caiqian at redhat.com wrote: > > > Yes, it looks good so far. Ptrace tests also does not show any > > regression. > > I said this too early. Looks like step-jump-count started to fail now. > > step-jump-cont: step-jump-cont.c:244: main: Assertion `0' failed. > /bin/sh: line 5: 28212 Aborted ${dir}$tst > FAIL: step-jump-cont Hmm. This is very, very strange. I don't know what this test-case actuallly does, but I can't see how this patch can make any difference. > You can login the same machine. Yes, will do tomorrow. Thanks. Oleg. From caiqian at redhat.com Sat Dec 5 17:39:05 2009 From: caiqian at redhat.com (CAI Qian) Date: Sat, 5 Dec 2009 12:39:05 -0500 (EST) Subject: step-into-handler.c compilation failure on ppc64 In-Reply-To: <20091205171920.1CD8039C4B@pipsqueak.sf.frob.com> Message-ID: <1942562377.1106481260034745595.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > How about this? Thanks. Fixed. From caiqian at redhat.com Sat Dec 5 17:56:58 2009 From: caiqian at redhat.com (CAI Qian) Date: Sat, 5 Dec 2009 12:56:58 -0500 (EST) Subject: ptrace tests failed to compile on i686 Message-ID: <2113558595.1106521260035818926.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> + make check make[1]: Entering directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' Making check in tests make[2]: Entering directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests' gcc -m64 -DPACKAGE_NAME=\"ptrace\ regression\ test\ suite\" -DPACKAGE_TARNAME=\"ptrace-tests\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"ptrace\ regression\ test\ suite\ 0.1\" -DPACKAGE_BUGREPORT=\"utrace-devel at redhat.com\" -DPACKAGE=\"ptrace-tests\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -D__EXTENSIONS__=1 -D_ALL_SOURCE=1 -D_GNU_SOURCE=1 -D_POSIX_PTHREAD_SEMANTICS=1 -D_TANDEM_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I. \ -std=gnu99 -Wall -Werror -g -O2 -o erestartsys-debuggee erestartsys-debuggee.c erestartsys-debuggee.c:1: sorry, unimplemented: 64-bit mode not compiled in make[2]: *** [erestartsys-debuggee] Error 1 make[2]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests' make[1]: *** [check-recursive] Error 1 make[1]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' + '[' i386 = x86_64 ']' + '[' i386 = ppc64 ']' + tee -a /tmp/tmp.yicBDv + echo '* run the crasher.' * run the crasher. + tee -a /tmp/tmp.yicBDv + make xcheck make[1]: Entering directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' make[2]: Entering directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' Making check in tests make[3]: Entering directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests' gcc -m64 -DPACKAGE_NAME=\"ptrace\ regression\ test\ suite\" -DPACKAGE_TARNAME=\"ptrace-tests\" -DPACKAGE_VERSION=\"0.1\" -DPACKAGE_STRING=\"ptrace\ regression\ test\ suite\ 0.1\" -DPACKAGE_BUGREPORT=\"utrace-devel at redhat.com\" -DPACKAGE=\"ptrace-tests\" -DVERSION=\"0.1\" -DSTDC_HEADERS=1 -DHAVE_SYS_TYPES_H=1 -DHAVE_SYS_STAT_H=1 -DHAVE_STDLIB_H=1 -DHAVE_STRING_H=1 -DHAVE_MEMORY_H=1 -DHAVE_STRINGS_H=1 -DHAVE_INTTYPES_H=1 -DHAVE_STDINT_H=1 -DHAVE_UNISTD_H=1 -D__EXTENSIONS__=1 -D_ALL_SOURCE=1 -D_GNU_SOURCE=1 -D_POSIX_PTHREAD_SEMANTICS=1 -D_TANDEM_SOURCE=1 -D_FILE_OFFSET_BITS=64 -I. \ -std=gnu99 -Wall -Werror -g -O2 -o erestartsys-debuggee erestartsys-debuggee.c erestartsys-debuggee.c:1: sorry, unimplemented: 64-bit mode not compiled in make[3]: *** [erestartsys-debuggee] Error 1 make[3]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests/tests' make[2]: *** [check-recursive] Error 1 make[1]: *** [xcheck] Error 2 make[2]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' make[1]: Leaving directory `/mnt/tests/kernel/misc/ptrace-testsuite/ptrace-tests' From roland at redhat.com Sat Dec 5 19:14:32 2009 From: roland at redhat.com (Roland McGrath) Date: Sat, 5 Dec 2009 11:14:32 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Oleg Nesterov's message of Wednesday, 2 December 2009 19:49:38 +0100 <20091202184938.GB14799@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091202184938.GB14799@redhat.com> Message-ID: <20091205191432.5FD8F39C46@pipsqueak.sf.frob.com> > > > + * Some machines get here with interrupts disabled. The same arch > > > + * code path leads to calling into get_signal_to_deliver(), which > > > + * implicitly reenables them by virtue of spin_unlock_irq. > > > + */ > > > + local_irq_enable(); > > > > Hrmm, I would much prefer to fix up the calling conventions of > > tracehook_notify_resume() than to bury something like this in the guts > > of a tracehook user. The reason I did it this way was mainly just not to make the requirement for arch maintainers' too subtle. As it is, we just say that you call tracehook_notify_resume() after clearing TIF_NOTIFY_RESUME, when it was set. That keeps the specification quite simple. Of course, that is not really much of a reason. If arch folks don't mind the requirement to replace e.g.: if (thread_info_flags & _TIF_NOTIFY_RESUME) { clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } with: if (thread_info_flags & _TIF_NOTIFY_RESUME) { local_irq_enable(); clear_thread_flag(TIF_NOTIFY_RESUME); tracehook_notify_resume(regs); } then that is certainly fine by me. But we do now have almost all the arch's calling tracehook_notify_resume() and I don't know how many of them do it in irqs-disabled context so they would need this change. > But in any case, imho it would be better to do this after we merge utrace, > otherwise we need more subtle arch-dependent changes before. I tend to agree. Thanks, Roland From caiqian at redhat.com Sun Dec 6 04:00:31 2009 From: caiqian at redhat.com (CAI Qian) Date: Sat, 5 Dec 2009 23:00:31 -0500 (EST) Subject: ptrace tests failed to compile on i686 In-Reply-To: <2113558595.1106521260035818926.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1547021300.1107791260072031447.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> OK, I think I should not use ./configure --with-biarch on i686. Sorry for the noise. From geologist at aeroflo.com Sun Dec 6 18:37:36 2009 From: geologist at aeroflo.com (Wery Randklev) Date: Sun, 06 Dec 2009 18:37:36 -0000 Subject: Cian who can not make a speech stands a poor chance of popular fa Message-ID: <4B1BF78A.2050204@aeroflo.com> Rael and Judah. Jehoram did evil in the sight of the Lord, but was not disgraced by idolatry. In his reign the Moabites, who paid a tribute of one hundred thousand sheep and one hundred thousand lambs, revolted. Jehoram, assisted by the kings of Judah, and of Edom, marched against them, and routed them, and destroyed their cities, and filled up their wells, and felled all their good trees, and covered their good land with stones. (M152) Meanwhile, it happened that there was a grievous famine in Samaria, so that an ass's head sold for eighty pieces of silver. Benhadad, in this time of national distress, came with mighty host and besieged the city; but in the night, in his camp was heard a mighty sound of chariots and horses, and a panic ensued, and the Syr -------------- next part -------------- A non-text attachment was scrubbed... Name: stabler.jpg Type: image/jpeg Size: 9086 bytes Desc: not available URL: From oleg at redhat.com Sun Dec 6 19:33:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sun, 6 Dec 2009 20:33:36 +0100 Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <805584630.1106391260032334529.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <123494443.1106371260032288659.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <805584630.1106391260032334529.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091206193336.GA15961@redhat.com> On 12/05, caiqian at redhat.com wrote: > > > Yes, it looks good so far. Ptrace tests also does not show any > > regression. > > I said this too early. Looks like step-jump-count started to fail now. > > step-jump-cont: step-jump-cont.c:244: main: Assertion `0' failed. > /bin/sh: line 5: 28212 Aborted ${dir}$tst > FAIL: step-jump-cont Could you please confirm that if you revert this [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless change the kernel passes the test? This is just impossible that this patch could make any difference for this test-case. > You can login the same machine. Yes, thanks. Unfortunately, I can't extend the reservation. # extendtesttime.sh ... Extending reservation time 48 Unable to connect to server, sleeping 5 seconds... and so on I give up for today. Yes, the test-case fails. It gets SIGSEGV right after we change the instruction pointer to raise_sigusr2. I added printf("%p\n", raise_sigusr2) to print this address, and then disassemled the code under this address: (gdb) disassemble 0x100118c0 Dump of assembler code for function raise_sigusr2: 0x00000000100118c0 : .long 0x0 <---- SIGSEGV 0x00000000100118c4 : .long 0x10000ab0 0x00000000100118c8 : .long 0x0 0x00000000100118cc : vmulosh v0,v1,v19 0x00000000100118d0 : .long 0x0 0x00000000100118d4 : vmhaddshs v0,v0,v1,v12 0x00000000100118d8 : .long 0x0 ... Hmm... this doesn't look like raise_sigusr2(), so I did (gdb) disassemble raise_sigusr2 Dump of assembler code for function raise_sigusr2: 0x0000000010000ab0 : mflr r0 0x0000000010000ab4 : li r3,12 0x0000000010000ab8 : std r0,16(r1) 0x0000000010000abc : stdu r1,-112(r1) 0x0000000010000ac0 : bl 0x10000780 0x0000000010000ac4 : ld r2,40(r1) 0x0000000010000ac8 : cmpdi cr7,r3,0 looks like ppc uses some form of "thunks" for function pointers... Another oddity, the comment says /* PTRACE_GETREGS / PTRACE_SETREGS are not available on ppc. #ifdef PTRACE_GETREGS However, PTRACE_GETREGS is defined, and the testcase does use PTRACE_GETREGS. Perhaps we have some issues with libc or compiler... Did you change anything else (except kernel) on this machine? Oleg. From caiqian at redhat.com Mon Dec 7 00:54:36 2009 From: caiqian at redhat.com (CAI Qian) Date: Sun, 6 Dec 2009 19:54:36 -0500 (EST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <20091206193336.GA15961@redhat.com> Message-ID: <2023989024.1113951260147276014.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Could you please confirm that if you revert this > > [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless > > change the kernel passes the test? This is just impossible that this > patch could make any difference for this test-case. No, it is the same. It is true also for kernels turned off CONFIG_UTRACE. > Unfortunately, I can't extend the reservation. RHTS had an outage yesterday, and now seems back to normal. > Did you change anything else (except kernel) on this machine? Not I am aware of. I will re-install this machine to have a probably clearer environment, and let you know the outcome shortly. Thanks, CAI Qian From caiqian at redhat.com Mon Dec 7 02:34:33 2009 From: caiqian at redhat.com (CAI Qian) Date: Sun, 6 Dec 2009 21:34:33 -0500 (EST) Subject: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless In-Reply-To: <2023989024.1113951260147276014.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <286699220.1115811260153273365.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Not I am aware of. I will re-install this machine to have a probably > clearer environment, and let you know the outcome shortly. It is the same there. I have extended the reservation for the next 3 days. From oleg at redhat.com Mon Dec 7 12:43:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 7 Dec 2009 13:43:27 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <286699220.1115811260153273365.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <2023989024.1113951260147276014.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <286699220.1115811260153273365.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091207124327.GA4324@redhat.com> On 12/06, CAI Qian wrote: > > > Not I am aware of. I will re-install this machine to have a probably > > clearer environment, and let you know the outcome shortly. > > It is the same there. I have extended the reservation for the next 3 days. OK, thank you. At least we know that this problem was not caused by utrace/ptrace, unpatched kernel fails too. I was greatly confused because I thought it was broken by the recent change in utrace.c I'll try to investigate, but currently I am all confused, and I suspect we have some user-space issues. If only I knew something about ppc... Ananth, could you please confirm once again that step-jump-cont (from ptrace-tests testsuite) not fail on your machine? If yes, please tell me the version of glibc/gcc. Is PTRACE_GETREGS defined on your machine? Oleg. From caiqian at redhat.com Mon Dec 7 14:06:23 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Mon, 7 Dec 2009 09:06:23 -0500 (EST) Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > I'll try to investigate, but currently I am all confused, and I > suspect we have some user-space issues. If only I knew something about ppc... Sorry for the confusing. > > Ananth, could you please confirm once again that step-jump-cont (from > ptrace-tests testsuite) not fail on your machine? If yes, please tell > me the version of glibc/gcc. Is PTRACE_GETREGS defined on your > machine? Funny enough. The above failure only seen on that particular system so far. In fact, different PPC64 systems have different results there (roland's git tree + your lockless patch). ibm-js20-02.lab.bos.redhat.com FAIL: watchpoint ppc-dabr-race: ./../tests/ppc-dabr-race.c:141: handler_fail: Assertion `0' failed. /bin/sh: line 5: 16928 Aborted ${dir}$tst FAIL: ppc-dabr-race syscall-reset: ./../tests/syscall-reset.c:95: main: Assertion `(*__errno_location ()) == 38' failed. errno 14 (Bad address) unexpected child status 67f FAIL: syscall-reset step-fork: ./../tests/step-fork.c:56: handler_fail: Assertion `0' failed. /bin/sh: line 5: 31144 Aborted ${dir}$tst FAIL: step-fork ibm-js22-02.rhts.bos.redhat.com ibm-js12-04.rhts.bos.redhat.com ibm-js12-05.rhts.bos.redhat.com Looks like failed only for syscall-reset and step-fork, as we have discussed before. I'll be reserving ibm-js20-02.lab.bos.redhat.com at the moment. Thanks, CAI Qian From oleg at redhat.com Mon Dec 7 14:24:51 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 7 Dec 2009 15:24:51 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091207142451.GA8505@redhat.com> On 12/07, caiqian at redhat.com wrote: > > > Ananth, could you please confirm once again that step-jump-cont (from > > ptrace-tests testsuite) not fail on your machine? If yes, please tell > > me the version of glibc/gcc. Is PTRACE_GETREGS defined on your > > machine? > > Funny enough. The above failure only seen on that particular system so far. > In fact, different PPC64 systems have different results there (roland's git > tree + your lockless patch). Great! thanks. OK, I seem to understand what happens, but I can not explain WHY does this happen on that machine. Once again. The tracer changes the tracee's instruction pointer to the adrress of raise_sigusr2(), and resumes the tracee. The tracee gets SIGSEGV right after that. But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), this value points to the "thunk" (I do not know the correct English term) which contains the "actual" address: (gdb) disassemble 0x100118c0 Dump of assembler code for function raise_sigusr2: 0x00000000100118c0 : .long 0x0 <---- SIGSEGV 0x00000000100118c4 : .long 0x10000ab0 <---- aof raise_sigusr2() 0x00000000100118c8 : .long 0x0 And!!! this thunk does NOT live in .text, and vma does NOT have VM_EXEC bit! # cat /proc/30494/maps 00100000-00120000 r-xp 00000000 00:00 0 [vdso] 10000000-10010000 r-xp 00000000 fd:00 59262 /root/TST/sjc 10010000-10020000 rw-p 00000000 fd:00 59262 /root/TST/sjc That is why the tracee gets SIGSEGV, and this is correct. Cai, perhaps you could give me access to another ppc machine where this test does not fail? Or, could you please run the trivial program below on that machine? Oleg. #include #include #include void my_func(void) { } int main(void) { char cmd[128]; printf("ptr: %p\n", my_func); sprintf(cmd, "cat /proc/%d/maps", getpid()); system(cmd); return 0; } From info at campaigns.canal-marketing.com Mon Dec 7 14:35:00 2009 From: info at campaigns.canal-marketing.com (=?ISO-8859-1?Q?FaxReception?=) Date: Mon, 07 Dec 2009 15:35:00 +0100 Subject: =?iso-8859-1?q?Vous_avez_re=E7u_un_Fax?= Message-ID: An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Mon Dec 7 14:47:44 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 7 Dec 2009 15:47:44 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207142451.GA8505@redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> Message-ID: <20091207144744.GA8468@host0.dyn.jankratochvil.net> On Mon, 07 Dec 2009 15:24:51 +0100, Oleg Nesterov wrote: > But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), > this value points to the "thunk" (I do not know the correct English term) ppc64 calls it "function descriptor" (GDB ppc64_linux_convert_from_func_ptr_addr): For PPC64, a function descriptor is a TOC entry, in a data section, which contains three words: the first word is the address of the function, the second word is the TOC pointer (r2), and the third word is the static chain value. (gdb) x/8gx 0x805b6f6258 0x805b6f6258 : 0x000000805b65cf68 0x000000805b702ac0 0x805b6f6268 : 0x000000805b65d010 0x000000805b702ac0 (gdb) x/20i 0x000000805b65cf68 0x805b65cf68 <.__GI___open>: lwz r10,-30432(r13) 0x805b65cf6c <.__GI___open+4>: cmpwi r10,0 0x805b65cf70 <.__GI___open+8>: bne- 0x805b65cf84 <.__GI___open+28> (gdb) info sym 0x000000805b702ac0 last_nip in section .bss I was not aware there is any "third word" before and I do not see it there. Regards, Jan From oleg at redhat.com Mon Dec 7 15:27:21 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 7 Dec 2009 16:27:21 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207144744.GA8468@host0.dyn.jankratochvil.net> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> Message-ID: <20091207152721.GA11725@redhat.com> On 12/07, Jan Kratochvil wrote: > > On Mon, 07 Dec 2009 15:24:51 +0100, Oleg Nesterov wrote: > > But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), > > this value points to the "thunk" (I do not know the correct English term) > > ppc64 calls it "function descriptor" (GDB > ppc64_linux_convert_from_func_ptr_addr): > For PPC64, a function descriptor is a TOC entry, Thanks Jan. > in a data section, Yes! Now I can't understand how this test-case could ever work on ppc. step-jump-cont does: regs->nip = raise_sigusr2; <--- points to data section ptrace(PTRACE_CONT); of course, the tracee gets SIGSEGV, this section is not executable. Oleg. From oleg at redhat.com Mon Dec 7 18:05:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 7 Dec 2009 19:05:40 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207152721.GA11725@redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> <20091207152721.GA11725@redhat.com> Message-ID: <20091207180540.GA19125@redhat.com> On 12/07, Oleg Nesterov wrote: > > On 12/07, Jan Kratochvil wrote: > > > > On Mon, 07 Dec 2009 15:24:51 +0100, Oleg Nesterov wrote: > > > But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), > > > this value points to the "thunk" (I do not know the correct English term) > > > > ppc64 calls it "function descriptor" (GDB > > ppc64_linux_convert_from_func_ptr_addr): > > For PPC64, a function descriptor is a TOC entry, > > Thanks Jan. > > > in a data section, > > Yes! > > Now I can't understand how this test-case could ever work on ppc. > step-jump-cont does: > > regs->nip = raise_sigusr2; <--- points to data section > ptrace(PTRACE_CONT); > > of course, the tracee gets SIGSEGV, this section is not executable. Hmm. Looks like, "powerpc" means a lot of different hardware, and _PAGE_EXEC may be 0. I didn't notice this when I quickly grepped arch/powerpc/ IOW, perhaps on some machines r implies x ? Is yes, this can explain why the results differ on different machines. Oleg. From peterz at infradead.org Mon Dec 7 18:34:37 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 07 Dec 2009 19:34:37 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091201220847.GA25400@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> Message-ID: <1260210877.3935.594.camel@laptop> On Tue, 2009-12-01 at 23:08 +0100, Oleg Nesterov wrote: > > > @@ -560,6 +625,20 @@ static inline void tracehook_report_deat > > > int signal, void *death_cookie, > > > int group_dead) > > > { > > > + /* > > > + * This barrier ensures that our caller's setting of > > > + * @task->exit_state precedes checking @task->utrace_flags here. > > > + * If utrace_set_events() was just called to enable > > > + * UTRACE_EVENT(DEATH), then we are obliged to call > > > + * utrace_report_death() and not miss it. utrace_set_events() > > > + * uses tasklist_lock to synchronize enabling the bit with the > > > + * actual change to @task->exit_state, but we need this barrier > > > + * to be sure we see a flags change made just before our caller > > > + * took the tasklist_lock. > > > + */ > > > + smp_mb(); > > > + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) > > > + utrace_report_death(task, death_cookie, group_dead, signal); > > > } > > > > I don't think its allowed to pair a mb with a lock-barrier, since the > > lock barriers are semi-permeable. > > Could you clarify? According to memory-barriers.txt a mb can be paired with mb,wmb,rmb depending on the situation. For LOCK it states: (1) LOCK operation implication: Memory operations issued after the LOCK will be completed after the LOCK operation has completed. Memory operations issued before the LOCK may be completed after the LOCK operation has completed. Which is not something I can see making sense to pair with an mb. So either the comment is confusing and its again referring to an UNLOCK +LOCK pair, or there's something fishy > > > @@ -589,10 +668,20 @@ static inline void set_notify_resume(str > > > * asynchronously, this will be called again before we return to > > > * user mode. > > > * > > > - * Called without locks. > > > + * Called without locks. However, on some machines this may be > > > + * called with interrupts disabled. > > > */ > > > static inline void tracehook_notify_resume(struct pt_regs *regs) > > > { > > > + struct task_struct *task = current; > > > + /* > > > + * This pairs with the barrier implicit in set_notify_resume(). > > > + * It ensures that we read the nonzero utrace_flags set before > > > + * set_notify_resume() was called by utrace setup. > > > + */ > > > + smp_rmb(); > > > + if (task_utrace_flags(task)) > > > + utrace_resume(task, regs); > > > } > > > > Sending an IPI implies the mb? > > Yes, but this has nothing to do with IPI. The caller, do_notify_resume(), > does: > clear_thread_flag(TIF_NOTIFY_RESUME); > tracehook_notify_resume: > if (task_utrace_flags(task)) > utrace_resume(); > > We should not read task_utrace_flags() before we clear TIF_NOTIFY_RESUME. Then this comment needs an update.. that wasn't at all clear to me. > > > +static inline struct utrace *task_utrace_struct(struct task_struct *task) > > > +{ > > > + struct utrace *utrace; > > > + > > > + /* > > > + * This barrier ensures that any prior load of task->utrace_flags > > > + * is ordered before this load of task->utrace. We use those > > > + * utrace_flags checks in the hot path to decide to call into > > > + * the utrace code. The first attach installs task->utrace before > > > + * setting task->utrace_flags nonzero, with a barrier between. > > > + * See utrace_task_alloc(). > > > + */ > > > + smp_rmb(); > > > + utrace = task->utrace; > > > + > > > + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ > > > + return utrace; > > > +} > > > > I spot two barriers here, but only 1 over in utrace_task_alloc(), hmm? > > smp_read_barrier_depends() pairs with utrace_task_alloc()->wmb(). > > smp_rmb() is needed for another reason. Suppose the code does: > > if (task_utrace_flags() & SOMETHING) > do_something_with(task->utrace); > > if we race with utrace_attach_task(), we can see ->utrace_flags != 0 > but task->utrace == NULL without rmb(). Still not clear what we pair with.. There is no obvious barrier in utrace_attach_task() nor a comment referring to this site. > > > +struct utrace_engine { > > > +/* private: */ > > > + struct kref kref; > > > + void (*release)(void *); > > > + struct list_head entry; > > > + > > > +/* public: */ > > > + const struct utrace_engine_ops *ops; > > > + void *data; > > > + > > > + unsigned long flags; > > > +}; > > > > Sorry, the kernel is written in C, not C++. > > Hmm. I almost never read the comments, but these 2 look very clear > to me ;) I see no point in adding comments like that at all. > > > + * Most callbacks take an @action argument, giving the resume action > > > + * chosen by other tracing engines. All callbacks take an @engine > > > + * argument, and a @task argument, which is always equal to @current. > > > > Given that some functions have a lot of arguments (depleting regparam), > > isn't it more expensive to push current on the stack than it is to > > simply read it again? > > Yes, perhaps. Only ->report_reap() really needs @task, it may be > !current. > > > > +struct utrace_engine_ops { > > > > > + u32 (*report_signal)(u32 action, > > > + struct utrace_engine *engine, > > > + struct task_struct *task, > > > + struct pt_regs *regs, > > > + siginfo_t *info, > > > + const struct k_sigaction *orig_ka, > > > + struct k_sigaction *return_ka); > > > > > + u32 (*report_clone)(enum utrace_resume_action action, > > > + struct utrace_engine *engine, > > > + struct task_struct *parent, > > > + unsigned long clone_flags, > > > + struct task_struct *child); > > > > > +}; > > > > Seems inconsistent on u32 vs enum utrace_resume_action. > > Well, this u32 can hold utrace_resume_action | utrace_signal_action, > for example. Sure, but then make all of them u32, or unsigned int, as that gets mixed in below. > > > +struct utrace_examiner { > > > +/* private: */ > > > + long state; > > > + unsigned long ncsw; > > > +}; > > > > Again, its not C++, if you want a private state like that, use an opaque > > type, like: > > > > struct utrace_examiner; > > > > and only define the thing in utrace.c or something. > > Then the caller of utrace_prepare_examine() has to alloc utrace_examiner > somehow. I disagree here. But of course we can remove this comment. Ah, right then simply drop the comment. > > > +static bool utrace_task_alloc(struct task_struct *task) > > > +{ > > > + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); > > > + if (unlikely(!utrace)) > > > + return false; > > > + spin_lock_init(&utrace->lock); > > > + INIT_LIST_HEAD(&utrace->attached); > > > + INIT_LIST_HEAD(&utrace->attaching); > > > + utrace->resume = UTRACE_RESUME; > > > + task_lock(task); > > > + if (likely(!task->utrace)) { > > > + /* > > > + * This barrier makes sure the initialization of the struct > > > + * precedes the installation of the pointer. This pairs > > > + * with smp_read_barrier_depends() in task_utrace_struct(). > > > + */ > > > + smp_wmb(); > > > + task->utrace = utrace; > > > + } > > > + task_unlock(task); > > > + /* > > > + * That unlock after storing task->utrace acts as a memory barrier > > > + * ordering any subsequent task->utrace_flags store afterwards. > > > + * This pairs with smp_rmb() in task_utrace_struct(). > > > + */ > > > + if (unlikely(task->utrace != utrace)) > > > + kmem_cache_free(utrace_cachep, utrace); > > > + return true; > > > +} > > > > Again, not sure we can pair an UNLOCK-barrier with a RMB. In fact, both > > are NOPs on x86. > > We can't. I think the comment is confusing. We need the barrier > between setting "task->utrace = utrace" and changing ->utrace_flags. > We have unlock+lock in between, this implies mb(). So this is the task_unlock() in utrace_task_alloc() and the spin_lock(&utrace->lock) in utrace_add_engine() ? Talk about non-obvious. > > > +static inline int utrace_attach_delay(struct task_struct *target) > > > +{ > > > + if ((target->flags & PF_STARTING) && > > > + task_utrace_struct(current) && > > > + task_utrace_struct(current)->cloning != target) > > > + do { > > > + schedule_timeout_interruptible(1); > > > + if (signal_pending(current)) > > > + return -ERESTARTNOINTR; > > > + } while (target->flags & PF_STARTING); > > > + > > > + return 0; > > > +} > > > > Quite gross this.. can't we key off the > > tracehoook_report_clone_complete() and use a wakeup there? > > Yes, it would be very nice to avoid this schedule_timeout_interruptible(). > But currently we don't see a simple solution, on the TODO list. But, to > clarify, this case is very unlikely. Use a global wait-queue and put a wakeup_all in tracehook_report_clone_complete() or wherever that ends up in utrace? > > Furthermore I'd add a function like: > > > > static struct utrace_engine_ops * > > get_utrace_ops(struct utrace_engine *engine, unsigned long *flags) > > { > > *flags = engine->flags; > > /* > > * This pairs with the barrier in mark_engine_detached(). > > * It makes sure that we never see the old ops vector with > > * the new flags, in case the original vector had no > > * report_quiesce. > > */ > > smp_rmb(); > > return engine->ops; > > } > > > > to take out and explicitly comment that common bit. > > > > Also, I'm not quite sure on why we play so many barrier games, looking > > at start_callback() we have 2 barriers in the callback loop, why not a > > per engine lock? > > Exactly to avoid the lock, I guess ;) I'm really thinking this code ought to get simplified a lot, there's too much non-obvious barriers. Then, and only if performance numbers show it, add back some of these optimizations, in simple small steps, that way its much easier to review as well. > > > + /* > > > + * In theory spin_lock() doesn't imply rcu_read_lock(). > > > + * Once we clear ->utrace_flags this task_struct can go away > > > + * because tracehook_prepare_release_task() path does not take > > > + * utrace->lock when ->utrace_flags == 0. > > > + */ > > > + rcu_read_lock(); > > > + task->utrace_flags = flags; > > > + spin_unlock(&utrace->lock); > > > + rcu_read_unlock(); > > > > yuck! > > > > why not simply keep a task reference over the utrace_reset call? > > Yes, we could use get_task_struct() instead. Not sure this would > be more clean, though. For one it would allow getting rid of that insane assymetric locking. > > > +static inline void finish_callback_report(struct task_struct *task, > > > + struct utrace *utrace, > > > + struct utrace_report *report, > > > + struct utrace_engine *engine, > > > + enum utrace_resume_action action) > > > +{ > > > + /* > > > + * If utrace_control() was used, treat that like UTRACE_DETACH here. > > > + */ > > > + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { > > > + engine->ops = &utrace_detached_ops; > > > + report->detaches = true; > > > + return; > > > + } > > > + > > > + if (action < report->action) > > > + report->action = action; > > > + > > > + if (action != UTRACE_STOP) { > > > + if (action < report->resume_action) > > > + report->resume_action = action; > > > + > > > + if (engine_wants_stop(engine)) { > > > + spin_lock(&utrace->lock); > > > + clear_engine_wants_stop(engine); > > > + spin_unlock(&utrace->lock); > > > + } > > > > Reads funny, but I guess it can only race the right way round? > > Not sure I understand... could you explain? It can only race with another thread also clearing the bit, not with one setting the bit? Otherwise there's no guarantee its not set after that if stmt. > > > +void utrace_report_jctl(int notify, int what) > > > +{ > > > + struct task_struct *task = current; > > > + struct utrace *utrace = task_utrace_struct(task); > > > + INIT_REPORT(report); > > > + > > > + spin_unlock_irq(&task->sighand->siglock); > > > + > > > + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), > > > + report_jctl, what, notify); > > > + > > > + spin_lock_irq(&task->sighand->siglock); > > > +} > > > > So much documentation, and non of it says that the JCTL (funny name btw) > > callback is done holding siglock... tskk. > > Not sure I understand, but we unlock ->siglock before REPORT(). If you mean > that utrace_report_jctl() is called under ->siglock, then yes. Apparently means I'm cross-eyed as I read it to lock before and unlock after :-/ From mldireto at tudoemoferta.com.br Mon Dec 7 20:07:40 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Mon, 7 Dec 2009 18:07:40 -0200 Subject: O Papai Noel e suas ofertas chegaram ao TudoemOferta.com Message-ID: <49d7b8cfee84b8c0dff4c20200186f82@tudoemoferta.com.br> An HTML attachment was scrubbed... URL: From caiqian at redhat.com Mon Dec 7 23:59:52 2009 From: caiqian at redhat.com (CAI Qian) Date: Mon, 7 Dec 2009 18:59:52 -0500 (EST) Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207142451.GA8505@redhat.com> Message-ID: <343831992.1199821260230392579.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Cai, perhaps you could give me access to another ppc machine where > this test does not fail? Sorry, I am wrong. It did not pass for 64-bit run. It looks like the "make biarch-test" can pass this test though. You can try both, ibm-js20-02.lab.bos.redhat.com ibm-js22-03.rhts.bos.redhat.com > Or, could you please run the trivial program below on that machine? # gcc read.c -o read # ./read ptr: 0x10010bf0 00100000-00120000 r-xp 00000000 00:00 0 [vdso] 10000000-10010000 r-xp 00000000 fd:00 48844 /root/read 10010000-10020000 rw-p 00000000 fd:00 48844 /root/read fffa7c70000-fffa7e30000 r-xp 00000000 fd:00 5741 /lib64/libc-2.10.90.so fffa7e30000-fffa7e40000 r--p 001b0000 fd:00 5741 /lib64/libc-2.10.90.so fffa7e40000-fffa7e60000 rw-p 001c0000 fd:00 5741 /lib64/libc-2.10.90.so fffa7e60000-fffa7e70000 rw-p 00000000 00:00 0 fffa7e70000-fffa7ea0000 r-xp 00000000 fd:00 5734 /lib64/ld-2.10.90.so fffa7ea0000-fffa7eb0000 r--p 00020000 fd:00 5734 /lib64/ld-2.10.90.so fffa7eb0000-fffa7ec0000 rw-p 00030000 fd:00 5734 /lib64/ld-2.10.90.so ffff06c0000-ffff0810000 rw-p 00000000 00:00 0 [stack] # gcc -m32 read.c -o read # ./read ptr: 0x100004fc 00100000-00120000 r-xp 00000000 00:00 0 [vdso] 0fe20000-0ffd0000 r-xp 00000000 fd:00 5827 /lib/libc-2.10.90.so 0ffd0000-0ffe0000 r--p 001a0000 fd:00 5827 /lib/libc-2.10.90.so 0ffe0000-0fff0000 rw-p 001b0000 fd:00 5827 /lib/libc-2.10.90.so 10000000-10010000 r-xp 00000000 fd:00 48844 /root/read 10010000-10020000 rw-p 00000000 fd:00 48844 /root/read f7df0000-f7e00000 rw-p 00000000 00:00 0 f7e00000-f7e30000 r-xp 00000000 fd:00 5733 /lib/ld-2.10.90.so f7e30000-f7e40000 r--p 00020000 fd:00 5733 /lib/ld-2.10.90.so f7e40000-f7e50000 rw-p 00030000 fd:00 5733 /lib/ld-2.10.90.so ff9c0000-ffb10000 rw-p 00000000 00:00 0 [stack] Thanks, CAI Qian From news at maisservicos.com Tue Dec 8 02:14:10 2009 From: news at maisservicos.com (TARA) Date: Tue, 8 Dec 2009 02:14:10 +0000 Subject: Receba a sua prenda GRATIS!!! Message-ID: <20091208021410.876DF3F275@server7.nortenet.pt> NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From ananth at in.ibm.com Tue Dec 8 09:45:05 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 8 Dec 2009 15:15:05 +0530 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207124327.GA4324@redhat.com> References: <2023989024.1113951260147276014.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <286699220.1115811260153273365.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207124327.GA4324@redhat.com> Message-ID: <20091208094504.GB4767@in.ibm.com> On Mon, Dec 07, 2009 at 01:43:27PM +0100, Oleg Nesterov wrote: > On 12/06, CAI Qian wrote: > > Ananth, could you please confirm once again that step-jump-cont (from > ptrace-tests testsuite) not fail on your machine? If yes, please tell > me the version of glibc/gcc. Is PTRACE_GETREGS defined on your machine? Hi Oleg, It works for me on a Fedora 12 machine. [ananth at mjs22lp1 ptrace-tests]$ gcc --version gcc (GCC) 4.4.2 20091027 (Red Hat 4.4.2-7) [ananth at mjs22lp1 ptrace-tests]$ rpm -qa |grep glibc glibc-common-2.11-2.ppc glibc-2.11-2.ppc64 glibc-devel-2.11-2.ppc glibc-static-2.11-2.ppc glibc-2.11-2.ppc glibc-devel-2.11-2.ppc64 glibc-headers-2.11-2.ppc And yes, PTRACE_GETREGS is defined in /usr/include/asm/ptrace.h Ananth From ananth at in.ibm.com Tue Dec 8 09:50:57 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Tue, 8 Dec 2009 15:20:57 +0530 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091207180540.GA19125@redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> <20091207152721.GA11725@redhat.com> <20091207180540.GA19125@redhat.com> Message-ID: <20091208095057.GC4767@in.ibm.com> On Mon, Dec 07, 2009 at 07:05:40PM +0100, Oleg Nesterov wrote: > On 12/07, Oleg Nesterov wrote: > > > > On 12/07, Jan Kratochvil wrote: > > > > > > On Mon, 07 Dec 2009 15:24:51 +0100, Oleg Nesterov wrote: > > > > But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), > > > > this value points to the "thunk" (I do not know the correct English term) > > > > > > ppc64 calls it "function descriptor" (GDB > > > ppc64_linux_convert_from_func_ptr_addr): > > > For PPC64, a function descriptor is a TOC entry, > > > > Thanks Jan. > > > > > in a data section, > > > > Yes! > > > > Now I can't understand how this test-case could ever work on ppc. > > step-jump-cont does: > > > > regs->nip = raise_sigusr2; <--- points to data section > > ptrace(PTRACE_CONT); > > > > of course, the tracee gets SIGSEGV, this section is not executable. > > Hmm. Looks like, "powerpc" means a lot of different hardware, and > _PAGE_EXEC may be 0. I didn't notice this when I quickly grepped > arch/powerpc/ > > IOW, perhaps on some machines r implies x ? > > Is yes, this can explain why the results differ on different > machines. Well, powerpc 32-bit adheres to the SVR4 ABI, while powerpc 64-bit uses the PPC64-ELF ABI (http://refspecs.linuxfoundation.org/ELF/ppc64/). The 64bit ABI uses function descriptors and the 'func_name' is the data address, while the '.func_name' is the text address. (See handle_rt_signal64 in arch/powerpc/kernel/signal_64.c and kprobe_lookup_name in arch/powerpc/include/asm/kprobes.h. Ananth From caiqian at redhat.com Tue Dec 8 11:03:12 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Tue, 8 Dec 2009 06:03:12 -0500 (EST) Subject: Tests Failures on PPC64 In-Reply-To: <53210486.1213181260270122979.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <394789634.1213221260270192487.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> This is seen with and without CONFIG_UTRACE. FAIL: watchpoint ppc-dabr-race: ./../tests/ppc-dabr-race.c:141: handler_fail: Assertion `0' failed. /bin/sh: line 5: 31750 Aborted ${dir}$tst FAIL: ppc-dabr-race Are those known issues? Thanks, CAI Qian From info at soft-direct.net Tue Dec 8 13:16:31 2009 From: info at soft-direct.net (Formation Management) Date: Tue, 8 Dec 2009 15:16:31 +0200 Subject: =?iso-8859-1?q?Devenez_un_leader_n=E9=2C_offre_sp=E9ciale_!?= Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Tue Dec 8 15:04:17 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Dec 2009 16:04:17 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1260210877.3935.594.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> Message-ID: <20091208150417.GA11883@redhat.com> On 12/07, Peter Zijlstra wrote: > > On Tue, 2009-12-01 at 23:08 +0100, Oleg Nesterov wrote: > > > > > @@ -560,6 +625,20 @@ static inline void tracehook_report_deat > > > > int signal, void *death_cookie, > > > > int group_dead) > > > > { > > > > + /* > > > > + * This barrier ensures that our caller's setting of > > > > + * @task->exit_state precedes checking @task->utrace_flags here. > > > > + * If utrace_set_events() was just called to enable > > > > + * UTRACE_EVENT(DEATH), then we are obliged to call > > > > + * utrace_report_death() and not miss it. utrace_set_events() > > > > + * uses tasklist_lock to synchronize enabling the bit with the > > > > + * actual change to @task->exit_state, but we need this barrier > > > > + * to be sure we see a flags change made just before our caller > > > > + * took the tasklist_lock. > > > > + */ > > > > + smp_mb(); > > > > + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) > > > > + utrace_report_death(task, death_cookie, group_dead, signal); > > > > } > > > > > > I don't think its allowed to pair a mb with a lock-barrier, since the > > > lock barriers are semi-permeable. > > > > Could you clarify? > > According to memory-barriers.txt a mb can be paired with mb,wmb,rmb > depending on the situation. > > For LOCK it states: > > (1) LOCK operation implication: > > Memory operations issued after the LOCK will be completed after the LOCK > operation has completed. > > Memory operations issued before the LOCK may be completed after the LOCK > operation has completed. > > Which is not something I can see making sense to pair with an mb. > > So either the comment is confusing and its again referring to an UNLOCK > +LOCK pair, or there's something fishy Ah. I missed your point because I didn't read the comment. Hmm. And since I didn't read the comment I misunderstood this code. Now I think the comment is wrong, and this mb() is not needed. If utrace utrace_set_events() adds _UTRACE_DEATH_EVENTS bits, it does this under read_lock(tasklist). This means tracehook_report_death() must always see the flags change, the caller took write_lock(tasklist). IOW, in _UTRACE_DEATH_EVENTS case utrace_set_events: read_lock(tasklist); if (!target->exit_state) target->utrace_flags |= UTRACE_EVENT(DEATH); read_unlock(tasklist); exit_notify: write_lock(tasklist); task->exit_state = EXIT_XXX; write_unlock(tasklist); if (target->utrace_flags & _UTRACE_DEATH_EVENTS) utrace_report_death(); It doesn't matter if the reading of ->utrace_flags can be reordered with the setting of ->exit_state, in no way this LOAD can happen _before_ we take tasklist for writing. And, if ->utrace_flags was already changed before we take tasklist, since utrace_set_events() does this under the same lock, we must see the change after write_unlock(tasklist). Roland? > > > > static inline void tracehook_notify_resume(struct pt_regs *regs) > > > > { > > > > + struct task_struct *task = current; > > > > + /* > > > > + * This pairs with the barrier implicit in set_notify_resume(). > > > > + * It ensures that we read the nonzero utrace_flags set before > > > > + * set_notify_resume() was called by utrace setup. > > > > + */ > > > > + smp_rmb(); > > > > + if (task_utrace_flags(task)) > > > > + utrace_resume(task, regs); > > > > } > > > > > > Sending an IPI implies the mb? > > > > Yes, but this has nothing to do with IPI. The caller, do_notify_resume(), > > does: > > clear_thread_flag(TIF_NOTIFY_RESUME); > > tracehook_notify_resume: > > if (task_utrace_flags(task)) > > utrace_resume(); > > > > We should not read task_utrace_flags() before we clear TIF_NOTIFY_RESUME. > > Then this comment needs an update.. that wasn't at all clear to me. OK. > > > > +static inline struct utrace *task_utrace_struct(struct task_struct *task) > > > > +{ > > > > + struct utrace *utrace; > > > > + > > > > + /* > > > > + * This barrier ensures that any prior load of task->utrace_flags > > > > + * is ordered before this load of task->utrace. We use those > > > > + * utrace_flags checks in the hot path to decide to call into > > > > + * the utrace code. The first attach installs task->utrace before > > > > + * setting task->utrace_flags nonzero, with a barrier between. > > > > + * See utrace_task_alloc(). > > > > + */ > > > > + smp_rmb(); > > > > + utrace = task->utrace; > > > > + > > > > + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ > > > > + return utrace; > > > > +} > > > > > > I spot two barriers here, but only 1 over in utrace_task_alloc(), hmm? > > > > smp_read_barrier_depends() pairs with utrace_task_alloc()->wmb(). > > > > smp_rmb() is needed for another reason. Suppose the code does: > > > > if (task_utrace_flags() & SOMETHING) > > do_something_with(task->utrace); > > > > if we race with utrace_attach_task(), we can see ->utrace_flags != 0 > > but task->utrace == NULL without rmb(). > > Still not clear what we pair with.. There is no obvious barrier in > utrace_attach_task() nor a comment referring to this site. Yes, agreed, we should move (and improve) the comment from utrace_task_alloc() to utrace_attach_task() or utrace_add_engine() which changed ->utrace_flags, see below. > > > > +static bool utrace_task_alloc(struct task_struct *task) > > > > +{ > > > > + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); > > > > + if (unlikely(!utrace)) > > > > + return false; > > > > + spin_lock_init(&utrace->lock); > > > > + INIT_LIST_HEAD(&utrace->attached); > > > > + INIT_LIST_HEAD(&utrace->attaching); > > > > + utrace->resume = UTRACE_RESUME; > > > > + task_lock(task); > > > > + if (likely(!task->utrace)) { > > > > + /* > > > > + * This barrier makes sure the initialization of the struct > > > > + * precedes the installation of the pointer. This pairs > > > > + * with smp_read_barrier_depends() in task_utrace_struct(). > > > > + */ > > > > + smp_wmb(); > > > > + task->utrace = utrace; > > > > + } > > > > + task_unlock(task); > > > > + /* > > > > + * That unlock after storing task->utrace acts as a memory barrier > > > > + * ordering any subsequent task->utrace_flags store afterwards. > > > > + * This pairs with smp_rmb() in task_utrace_struct(). > > > > + */ > > > > + if (unlikely(task->utrace != utrace)) > > > > + kmem_cache_free(utrace_cachep, utrace); > > > > + return true; > > > > +} > > > > > > Again, not sure we can pair an UNLOCK-barrier with a RMB. In fact, both > > > are NOPs on x86. > > > > We can't. I think the comment is confusing. We need the barrier > > between setting "task->utrace = utrace" and changing ->utrace_flags. > > We have unlock+lock in between, this implies mb(). > > So this is the task_unlock() in utrace_task_alloc() and the > spin_lock(&utrace->lock) in utrace_add_engine() ? Yes, and see above. This UNLOCK+LOCK provides the necessary barrier. > Talk about non-obvious. Well, agreed. We should fix the comment, or just add the explicit mb(). I personally think the "good" comment is enough. > > > > +struct utrace_engine_ops { > > > > > > > + u32 (*report_signal)(u32 action, > > > > + struct utrace_engine *engine, > > > > + struct task_struct *task, > > > > + struct pt_regs *regs, > > > > + siginfo_t *info, > > > > + const struct k_sigaction *orig_ka, > > > > + struct k_sigaction *return_ka); > > > > > > > + u32 (*report_clone)(enum utrace_resume_action action, > > > > + struct utrace_engine *engine, > > > > + struct task_struct *parent, > > > > + unsigned long clone_flags, > > > > + struct task_struct *child); > > > > > > > +}; > > > > > > Seems inconsistent on u32 vs enum utrace_resume_action. > > > > Well, this u32 can hold utrace_resume_action | utrace_signal_action, > > for example. > > Sure, but then make all of them u32, or unsigned int, as that gets mixed > in below. Not sure I understand, but if you meant all these callbacks should return int/long then I'd personally agree. > > > > +static inline int utrace_attach_delay(struct task_struct *target) > > > > +{ > > > > + if ((target->flags & PF_STARTING) && > > > > + task_utrace_struct(current) && > > > > + task_utrace_struct(current)->cloning != target) > > > > + do { > > > > + schedule_timeout_interruptible(1); > > > > + if (signal_pending(current)) > > > > + return -ERESTARTNOINTR; > > > > + } while (target->flags & PF_STARTING); > > > > + > > > > + return 0; > > > > +} > > > > > > Quite gross this.. can't we key off the > > > tracehoook_report_clone_complete() and use a wakeup there? > > > > Yes, it would be very nice to avoid this schedule_timeout_interruptible(). > > But currently we don't see a simple solution, on the TODO list. But, to > > clarify, this case is very unlikely. > > Use a global wait-queue and put a wakeup_all in > tracehook_report_clone_complete() or wherever that ends up in utrace? - First of all, can't resist, I think a global wait-queue for this is just "ugly by definition". OK, please ignore, this is non-technical and subjective. - If we change tracehook_report_clone_complete() to do the wakeup, this wakeup must be unconditional, it should be done even if the forking thread is not traced. The current code is extremly simple and works. Yes, yes, yes, any schedule_timeout(1) in a loop asks for the better solution. I don't know what Roland thinks, but as for me this problem is low priority, currently I didn't really try to think how to make this code "better". This case is very unlikely, and it is not a hot-path. This happens when the unrelated process tries to attach to the new thread in the middle of do_fork(). But there is another reason why personally I think we should improve this code later (and the similar code in utrace_barrier). A few lines below you wrote: > > > Also, I'm not quite sure on why we play so many barrier games, looking > > > at start_callback() we have 2 barriers in the callback loop, why not a > > > per engine lock? > > > > Exactly to avoid the lock, I guess ;) > > I'm really thinking this code ought to get simplified a lot, there's too > much non-obvious barriers. > > Then, and only if performance numbers show it, add back some of these > optimizations, in simple small steps, that way its much easier to review > as well. and above you suggest to complicate utrace_attach_delay() before merging. As for "in simple small steps", I agree, it would be much better. The problem is, this code was developed out-of-tree. That is why we would like to merge it asap, then do other changes which could be easily reviewed. Now, do you really mean we should throw out the working code, rewrite it avoiding these barriers, and resubmit? Sure, everything is possible. But this means another round of out-of-tree development with unclear results. Some barriers are easy, we can simply take utrace->lock. Some are not. In no way (imho) we should use spinlocks in tracehooks. OK, we can embed "struct utrace" back into task_struct, then it would be easy to eliminate more barriers, not sure this would be a good change though. > > > > + /* > > > > + * In theory spin_lock() doesn't imply rcu_read_lock(). > > > > + * Once we clear ->utrace_flags this task_struct can go away > > > > + * because tracehook_prepare_release_task() path does not take > > > > + * utrace->lock when ->utrace_flags == 0. > > > > + */ > > > > + rcu_read_lock(); > > > > + task->utrace_flags = flags; > > > > + spin_unlock(&utrace->lock); > > > > + rcu_read_unlock(); > > > > > > yuck! > > > > > > why not simply keep a task reference over the utrace_reset call? > > > > Yes, we could use get_task_struct() instead. Not sure this would > > be more clean, though. > > For one it would allow getting rid of that insane assymetric locking. Well, this is subjective, but I don't agree that get_task_struct(task); task->utrace_flags = flags; spin_unlock(&utrace->lock); put_task_struct(task); looks better. We can move get_task_struct (or rcu_read_lock) up, but then the code becomes less obvious. This get/lock is only needed for spin_unlock(&utrace->lock). I'd wish we had rcu_read_lock_in_atomic (or whatever) which could be used under spinlocks... That said, if you think get_task_struct() can help to merge utrace I personally do not care much. > > > > +static inline void finish_callback_report(struct task_struct *task, > > > > + struct utrace *utrace, > > > > + struct utrace_report *report, > > > > + struct utrace_engine *engine, > > > > + enum utrace_resume_action action) > > > > +{ > > > > + /* > > > > + * If utrace_control() was used, treat that like UTRACE_DETACH here. > > > > + */ > > > > + if (action == UTRACE_DETACH || engine->ops == &utrace_detached_ops) { > > > > + engine->ops = &utrace_detached_ops; > > > > + report->detaches = true; > > > > + return; > > > > + } > > > > + > > > > + if (action < report->action) > > > > + report->action = action; > > > > + > > > > + if (action != UTRACE_STOP) { > > > > + if (action < report->resume_action) > > > > + report->resume_action = action; > > > > + > > > > + if (engine_wants_stop(engine)) { > > > > + spin_lock(&utrace->lock); > > > > + clear_engine_wants_stop(engine); > > > > + spin_unlock(&utrace->lock); > > > > + } > > > > > > Reads funny, but I guess it can only race the right way round? > > > > Not sure I understand... could you explain? > > It can only race with another thread also clearing the bit, not with one > setting the bit? Otherwise there's no guarantee its not set after that > if stmt. We do not care if another thread (the owner of this engine) sets or clears ENGINE_STOP in engine->flags. This can happen if the tracer is "insane" and races with itself. Nothing bad can happen, the last change wins. Oleg. From peterz at infradead.org Tue Dec 8 15:29:23 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Tue, 08 Dec 2009 16:29:23 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091208150417.GA11883@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> Message-ID: <1260286163.3935.1497.camel@laptop> On Tue, 2009-12-08 at 16:04 +0100, Oleg Nesterov wrote: > > > > > + /* > > > > > + * In theory spin_lock() doesn't imply rcu_read_lock(). > > > > > + * Once we clear ->utrace_flags this task_struct can go away > > > > > + * because tracehook_prepare_release_task() path does not take > > > > > + * utrace->lock when ->utrace_flags == 0. > > > > > + */ > > > > > + rcu_read_lock(); > > > > > + task->utrace_flags = flags; > > > > > + spin_unlock(&utrace->lock); > > > > > + rcu_read_unlock(); > > > > > > > > yuck! > > > > > > > > why not simply keep a task reference over the utrace_reset call? > > > > > > Yes, we could use get_task_struct() instead. Not sure this would > > > be more clean, though. > > > > For one it would allow getting rid of that insane assymetric locking. > > Well, this is subjective, but I don't agree that > > get_task_struct(task); > task->utrace_flags = flags; > spin_unlock(&utrace->lock); > put_task_struct(task); > > looks better. No, what I mean by assymetric locking is that utrace_reset() and utrace_reap() drop the utrace->lock where their caller acquired it, resulting in non-obvious like: utrace_control() { ... spin_lock(&utrace->lock); ... if (reset) utrace_reset(utrace); else spin_unlock(&utrace->lock); } If you take a task ref you can write the much saner: utrace_control() { ... spin_lock(&utrace->lock); ... if (reset) utrace_reset(utrace); spin_unlock(&utrace->lock); } From peterz at infradead.org Tue Dec 8 15:35:34 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Tue, 08 Dec 2009 16:35:34 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091208150417.GA11883@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> Message-ID: <1260286534.3935.1511.camel@laptop> On Tue, 2009-12-08 at 16:04 +0100, Oleg Nesterov wrote: > The > problem is, this code was developed out-of-tree. That is why we would > like to merge it asap, then do other changes which could be easily > reviewed. > > Now, do you really mean we should throw out the working code, rewrite > it avoiding these barriers, and resubmit? Sure, everything is possible. > But this means another round of out-of-tree development with unclear > results. Out-of-tree development is bad, it having taken lot of effort is no excuse for merging ugly. Now, I'm not against barriers at all, but code that is as barrier heavy as this, with such bad comments and no clear indication it was actually worth using so many barriers make me wonder. Barriers aren't free either, and having multiple such things in quick succession isn't nessecarily faster than a lock, but much less obvious. From oleg at redhat.com Tue Dec 8 16:31:31 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Dec 2009 17:31:31 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1260286163.3935.1497.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> <1260286163.3935.1497.camel@laptop> Message-ID: <20091208163131.GA14815@redhat.com> On 12/08, Peter Zijlstra wrote: > > On Tue, 2009-12-08 at 16:04 +0100, Oleg Nesterov wrote: > > > > Well, this is subjective, but I don't agree that > > > > get_task_struct(task); > > task->utrace_flags = flags; > > spin_unlock(&utrace->lock); > > put_task_struct(task); > > > > looks better. > > No, what I mean by assymetric locking is that utrace_reset() and > utrace_reap() drop the utrace->lock where their caller acquired it, > resulting in non-obvious like: > > utrace_control() > { > > ... > spin_lock(&utrace->lock); > > ... > > if (reset) > utrace_reset(utrace); > else > spin_unlock(&utrace->lock); > } Agreed, the code like this never looks good. > If you take a task ref you can write the much saner: > > utrace_control() > { > ... > spin_lock(&utrace->lock); > ... > if (reset) > utrace_reset(utrace); > > spin_unlock(&utrace->lock); > } No, get_task_struct() in utrace_reset() can't help, we should move it into utrace_control() then. And in this case it becomes even more subtle: it is needed because ->utrace_flags may be cleared inside utrace_reset() and after that utrace_control()->spin_unlock() becomes unsafe. Also. utrace_reset() drops utrace->lock to call put_detached_list() lockless. If we want to avoid the assymetric locking, every caller should pass "struct list_head *detached" to utrace_reset(), drop utrace->lock, and call put_detached_list(). Oleg. From oleg at redhat.com Tue Dec 8 17:51:10 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Dec 2009 18:51:10 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1260286534.3935.1511.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> <1260286534.3935.1511.camel@laptop> Message-ID: <20091208175110.GB14815@redhat.com> On 12/08, Peter Zijlstra wrote: > > On Tue, 2009-12-08 at 16:04 +0100, Oleg Nesterov wrote: > > The > > problem is, this code was developed out-of-tree. That is why we would > > like to merge it asap, then do other changes which could be easily > > reviewed. > > > > Now, do you really mean we should throw out the working code, rewrite > > it avoiding these barriers, and resubmit? Sure, everything is possible. > > But this means another round of out-of-tree development with unclear > > results. > > Out-of-tree development is bad, it having taken lot of effort is no > excuse for merging ugly. > > Now, I'm not against barriers at all, but code that is as barrier heavy > as this, with such bad comments and no clear indication it was actually > worth using so many barriers make me wonder. Well. First of all, I agree at least partly. If you ask me, I feel that in any case utrace needs more cleanups (in fact, like almost any code in kernel) even if we forget about the barriers. In no way utrace is finished or perfect. I think that Roland won't argue ;) But. It would be much easier to do the futher development step by step, patch by patch, which the changelogs, with the possibilty to have the review. And it is much easier to change the code which is already used by people. And, cleanups/simplifications are the most hard part of the development. However, of course I can't "prove" that the current code is "good enough" for merging. > Barriers aren't free either, and having multiple such things in quick > succession isn't nessecarily faster than a lock, but much less obvious. It is hardly possible to argue. Oleg. From peterz at infradead.org Tue Dec 8 18:19:38 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Tue, 08 Dec 2009 19:19:38 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091208163131.GA14815@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> <1260286163.3935.1497.camel@laptop> <20091208163131.GA14815@redhat.com> Message-ID: <1260296378.17334.21.camel@laptop> On Tue, 2009-12-08 at 17:31 +0100, Oleg Nesterov wrote: > > If you take a task ref you can write the much saner: > > > > utrace_control() > > { > > ... > > spin_lock(&utrace->lock); > > ... > > if (reset) > > utrace_reset(utrace); > > > > spin_unlock(&utrace->lock); > > } > > No, get_task_struct() in utrace_reset() can't help, we should move > it into utrace_control() then. And in this case it becomes even more > subtle: it is needed because ->utrace_flags may be cleared inside > utrace_reset() and after that utrace_control()->spin_unlock() becomes > unsafe. The task->utrace pointer is cleaned up on free_task()->tracehook_free_task()->utrace_free_task(), so by holding a ref on the task, we ensure ->utrace stays around, and we can do spin_unlock(), right? > Also. utrace_reset() drops utrace->lock to call put_detached_list() > lockless. If we want to avoid the assymetric locking, every caller > should pass "struct list_head *detached" to utrace_reset(), drop > utrace->lock, and call put_detached_list(). All that seems to do is call ->release() and kmem_cache_free()s the utrace_engine thing, why can't that be done with utrace->lock held? But yeah, passing that list along does seem like a better solution. From oleg at redhat.com Tue Dec 8 18:37:58 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 8 Dec 2009 19:37:58 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1260296378.17334.21.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> <1260286163.3935.1497.camel@laptop> <20091208163131.GA14815@redhat.com> <1260296378.17334.21.camel@laptop> Message-ID: <20091208183758.GA20507@redhat.com> On 12/08, Peter Zijlstra wrote: > > On Tue, 2009-12-08 at 17:31 +0100, Oleg Nesterov wrote: > > > > If you take a task ref you can write the much saner: > > > > > > utrace_control() > > > { > > > ... > > > spin_lock(&utrace->lock); > > > ... > > > if (reset) > > > utrace_reset(utrace); > > > > > > spin_unlock(&utrace->lock); > > > } > > > > No, get_task_struct() in utrace_reset() can't help, we should move > > it into utrace_control() then. And in this case it becomes even more > > subtle: it is needed because ->utrace_flags may be cleared inside > > utrace_reset() and after that utrace_control()->spin_unlock() becomes > > unsafe. > > The task->utrace pointer is cleaned up on > free_task()->tracehook_free_task()->utrace_free_task(), so by holding a > ref on the task, we ensure ->utrace stays around, and we can do > spin_unlock(), right? Yes. That is why utrace_control() (which does unlock) should take the ref, not utrace_reset(). > > Also. utrace_reset() drops utrace->lock to call put_detached_list() > > lockless. If we want to avoid the assymetric locking, every caller > > should pass "struct list_head *detached" to utrace_reset(), drop > > utrace->lock, and call put_detached_list(). > > All that seems to do is call ->release() and kmem_cache_free()s the > utrace_engine thing, why can't that be done with utrace->lock held? We can, but then ->release() will be called in atomic context. Utrace tries hard to not "restrict" the module writers. > But yeah, passing that list along does seem like a better solution. Well, it has multiple callers, everyone will be complicated. Oleg. From fche at redhat.com Tue Dec 8 21:58:29 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Tue, 8 Dec 2009 16:58:29 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091201211518.GA32376@elte.hu> References: <20091130131928.GC18879@linux.vnet.ibm.com> <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> <20091201211518.GA32376@elte.hu> Message-ID: <20091208215829.GA19793@redhat.com> Hi - > > Help me out here: by "kgdb extension" do you imagine "something new > > that an unprivileged user can use to debug his own process"? Or do > > you imagine a new userspace facility that single-steps the kernel? > > Is this a trick question? Single-stepping the kernel on the same system > [especially if it's an UP system] would certainly be a challenge ;-) > > What i mean is what i said: if you provide a new framework (especially > if it's user visible - which both kgdb and the gdb stub is) you should > either fully replace existing functionality or extend it. Overlapping it > in an incomplete way is not useful to anyone. But there is no "overlap" beyond the name. The functional scope of the two interfaces is totally non-overlapping, and are consistent with the current chasms between kernel- and user-side debugging. Sure, in the future, it may make sense to teach the kernel-side (kgdb serial console) interface to manipulate userspace. But that will require a gdb extension. And it would not satisfy an unprivileged user's need to debug pure userspace (in a better way than current ptrace can). This is why I keep asking for specificity as to this "new framework" you imagine. Just sharing definitions such as kgdb_arch/kgdb_io but otherwise completely disconnected (separate channels)? > Extending kgdb to allow the use of it as if we used gdb locally would > certainly be interesting - and then you could drop into the kernel > anytime as well. (Is this a restatement of the "trick question" idea?) > > > We dont want to separate facilities for the same conceptual thing: > > > examining application state (be that in user-space and > > > kernel-space). > > This seems like a shallow sort of consistency. kgdb was added after > > ptrace existed -- why not extend ptrace instead to target the kernel? > > After all, it's "examining application state". The answer is that it > > doesn't make a heck of a lot of sense. > > kgdb simply used gdb's preferred way of remote debugging. That's > certainly the ugliest bit of it btw - but it's an externality to kgdb. > Had it extended ptrace it wouldnt have gdb compatibility. So, because of a constraint for gdb compatibility, you built a separate interface for kgdb vs. ptrace. Fine. Do you accept that, even if a hypothetical single channel existed for which kernel- and user-space debugging could occur, current gdb is not compatible with this? So by your own reasoning, such a facility should not be mandated as a "necessary first step". > [...] perf replaces oprofile functionally. (I'm told that it's not a strict superset from a functional point of view, FWIW, something about a larger selection of low level hardware counters.) > If the in-kernel gdb stub replaced kgdb functionally you'd hear no > complaints from me. Let's leave it as an idea for the future. - FChE From pubcoolgift at lifecooler.com Wed Dec 9 04:06:02 2009 From: pubcoolgift at lifecooler.com (Coolgift) Date: Wed, 9 Dec 2009 04:06:02 -0000 Subject: Saiba como a Teresa e o Jonas solucionaram este Natal Message-ID: An HTML attachment was scrubbed... URL: From lindsay at sommelleriedefrance.fr Wed Dec 9 07:47:23 2009 From: lindsay at sommelleriedefrance.fr (lindsay at sommelleriedefrance.fr) Date: Wed, 9 Dec 2009 08:47:23 +0100 Subject: Sommellerie de France Message-ID: An HTML attachment was scrubbed... URL: From info at campaigns.canal-marketing.com Wed Dec 9 15:05:53 2009 From: info at campaigns.canal-marketing.com (BestPub) Date: Wed, 09 Dec 2009 16:05:53 +0100 Subject: Demandez votre catalogue gratuit dobjets publicitaires Message-ID: An HTML attachment was scrubbed... URL: From newsletter at usbportugal.com Wed Dec 9 15:32:48 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Wed, 9 Dec 2009 16:32:48 +0100 Subject: =?iso-8859-1?q?J=E1_n=E3o_h=E1_mem=F3ria_de=2E=2E=2ESemana_50?= Message-ID: <7aa33e366ad9eb355fca83ecb0056690@newsletter2.usbportugal.com> An HTML attachment was scrubbed... URL: From oleg at redhat.com Wed Dec 9 17:37:46 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Dec 2009 18:37:46 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091208095057.GC4767@in.ibm.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> <20091207152721.GA11725@redhat.com> <20091207180540.GA19125@redhat.com> <20091208095057.GC4767@in.ibm.com> Message-ID: <20091209173746.GA17508@redhat.com> On 12/08, Ananth N Mavinakayanahalli wrote: > > On Mon, Dec 07, 2009 at 07:05:40PM +0100, Oleg Nesterov wrote: > > On 12/07, Oleg Nesterov wrote: > > > > > > On 12/07, Jan Kratochvil wrote: > > > > > > > > On Mon, 07 Dec 2009 15:24:51 +0100, Oleg Nesterov wrote: > > > > > But. &raise_sigusr2 is not equal to the "actual" address of &raise_sigusr2(), > > > > > this value points to the "thunk" (I do not know the correct English term) > > > > > > > > ppc64 calls it "function descriptor" (GDB > > > > ppc64_linux_convert_from_func_ptr_addr): > > > > For PPC64, a function descriptor is a TOC entry, > > > > > > Thanks Jan. > > > > > > > in a data section, > > > > > > Yes! > > > > > > Now I can't understand how this test-case could ever work on ppc. > > > step-jump-cont does: > > > > > > regs->nip = raise_sigusr2; <--- points to data section > > > ptrace(PTRACE_CONT); > > > > > > of course, the tracee gets SIGSEGV, this section is not executable. > > > > Hmm. Looks like, "powerpc" means a lot of different hardware, and > > _PAGE_EXEC may be 0. I didn't notice this when I quickly grepped > > arch/powerpc/ > > > > IOW, perhaps on some machines r implies x ? > > > > Is yes, this can explain why the results differ on different > > machines. > > Well, powerpc 32-bit adheres to the SVR4 ABI, while powerpc 64-bit uses > the PPC64-ELF ABI (http://refspecs.linuxfoundation.org/ELF/ppc64/). The > 64bit ABI uses function descriptors and the 'func_name' is the data > address, Cai, Ananth, thank you. So. I think we can forget about the possible kernel problems (and in any case we can rule out utrace). The test-case just wrong and should be fixed. The tracee can't execute the function descriptor in data section, that is why it gets SIGSEGV. > while the '.func_name' is the text address. tried to change the code to REGS_ACCESS (regs, nip) = (unsigned long) .raise_sigusr2 but gcc doesn't like this ;) > (See > handle_rt_signal64 in arch/powerpc/kernel/signal_64.c and > kprobe_lookup_name in arch/powerpc/include/asm/kprobes.h. Thanks... looking at handle_rt_signal64(), looks like we should also set regs->gpr[2] = funct_desc_ptr->toc if we change regs->nip I hope someone who understand powerpc could fix the test-case ;) Oleg. From oleg at redhat.com Wed Dec 9 18:12:41 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Dec 2009 19:12:41 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091209173746.GA17508@redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> <20091207152721.GA11725@redhat.com> <20091207180540.GA19125@redhat.com> <20091208095057.GC4767@in.ibm.com> <20091209173746.GA17508@redhat.com> Message-ID: <20091209181241.GA20475@redhat.com> On 12/09, Oleg Nesterov wrote: > > Cai, Ananth, thank you. > > So. I think we can forget about the possible kernel problems (and > in any case we can rule out utrace). > > The test-case just wrong and should be fixed. The tracee can't execute > the function descriptor in data section, that is why it gets SIGSEGV. > > > while the '.func_name' is the text address. > > tried to change the code to > > REGS_ACCESS (regs, nip) = (unsigned long) .raise_sigusr2 > > but gcc doesn't like this ;) > > > (See > > handle_rt_signal64 in arch/powerpc/kernel/signal_64.c and > > kprobe_lookup_name in arch/powerpc/include/asm/kprobes.h. > > Thanks... looking at handle_rt_signal64(), looks like we should > also set regs->gpr[2] = funct_desc_ptr->toc if we change regs->nip > > > I hope someone who understand powerpc could fix the test-case ;) Yes, I verified the patch below fixes step-jump-cont.c on ibm-js20-02.lab.bos.redhat.com. Oleg. --- step-jump-cont.c~ 2009-12-09 12:17:04.367733643 -0500 +++ step-jump-cont.c 2009-12-09 13:12:50.708535770 -0500 @@ -153,12 +153,19 @@ raise_sigusr2 (void) assert (0); } +typedef struct { + unsigned long entry; + unsigned long toc; + unsigned long env; +} func_descr_t; + int main (void) { long l; int status; pid_t pid; REGS_TYPE (regs); + func_descr_t *fp; setbuf (stdout, NULL); atexit (cleanup); @@ -214,7 +221,12 @@ int main (void) #elif defined __x86_64__ REGS_ACCESS (regs, rip) = (unsigned long) raise_sigusr2; #elif defined __powerpc__ - REGS_ACCESS (regs, nip) = (unsigned long) raise_sigusr2; + + fp = (void*)raise_sigusr2; + + REGS_ACCESS(regs, nip) = fp->entry; + REGS_ACCESS(regs, gpr[2]) = fp->toc; + #else # error "Check outer #ifdef" #endif From oleg at redhat.com Wed Dec 9 18:31:52 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Dec 2009 19:31:52 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <394789634.1213221260270192487.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <53210486.1213181260270122979.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <394789634.1213221260270192487.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091209183152.GA21076@redhat.com> On 12/08, caiqian at redhat.com wrote: > > This is seen with and without CONFIG_UTRACE. Good, at least we shouldn't worry about utrace. > FAIL: watchpoint > > ppc-dabr-race: ./../tests/ppc-dabr-race.c:141: handler_fail: Assertion `0' failed. > /bin/sh: line 5: 31750 Aborted ${dir}$tst > FAIL: ppc-dabr-race > > Are those known issues? No, it is not. However I do not not what this test-case does, and I know nothing about data watchpoints. Hmm. it is obvioulsy racy, "static volatile unsigned started" is not atomic and thus the main thread can hang doing while (started < THREADS); not that I think this explains the failure though. Cai, I tried to reproduce the failure on your machine but it doesn't fail? Oleg. From oleg at redhat.com Wed Dec 9 19:54:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 9 Dec 2009 20:54:28 +0100 Subject: s390: stepping && PT_PTRACED (Was: utrace failed to compile for s390x) In-Reply-To: <20091203183525.0B65C2C081@pipsqueak.sf.frob.com> References: <33810577.870481259720774110.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <2028524242.871741259724938476.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091202034229.25DF1BD8F@magilla.sf.frob.com> <20091202154129.GD4353@redhat.com> <20091202172749.GA11301@redhat.com> <20091203183525.0B65C2C081@pipsqueak.sf.frob.com> Message-ID: <20091209195428.GA24928@redhat.com> (add cc's) On 12/03, Roland McGrath wrote: > > > Not sure what should we do right now, s390 needs more attention. > > Also, it uses PT_PTRACED bit, I am afraid this is not what we wan > > with utrace. > > This looks simple. Its one use can just be > tracehook_consider_fatal_signal(SIGTRAP) instead. I expect you can just > send that change to the s390 maintainers and they will take it. Done. But... I tried to understand these check and failed. Why do we need them? They look unneeded to me, but of course I know nothing about s390. For example, do_single_step(). If notify_die(DIE_SSTEP) does not return NOTIFY_STOP, it is not kprobe. This means the caller is sysc_singlestep: in entry.S, who else except ptrace could set TIF_SINGLESTEP ? Oleg. From heiko.carstens at de.ibm.com Wed Dec 9 21:24:32 2009 From: heiko.carstens at de.ibm.com (Heiko Carstens) Date: Wed, 9 Dec 2009 22:24:32 +0100 Subject: s390: stepping && PT_PTRACED (Was: utrace failed to compile for s390x) In-Reply-To: <20091209195428.GA24928@redhat.com> References: <33810577.870481259720774110.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <2028524242.871741259724938476.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091202034229.25DF1BD8F@magilla.sf.frob.com> <20091202154129.GD4353@redhat.com> <20091202172749.GA11301@redhat.com> <20091203183525.0B65C2C081@pipsqueak.sf.frob.com> <20091209195428.GA24928@redhat.com> Message-ID: <20091209212432.GC4351@osiris.boeblingen.de.ibm.com> On Wed, Dec 09, 2009 at 08:54:28PM +0100, Oleg Nesterov wrote: > (add cc's) > > On 12/03, Roland McGrath wrote: > > > > > Not sure what should we do right now, s390 needs more attention. > > > Also, it uses PT_PTRACED bit, I am afraid this is not what we wan > > > with utrace. > > > > This looks simple. Its one use can just be > > tracehook_consider_fatal_signal(SIGTRAP) instead. I expect you can just > > send that change to the s390 maintainers and they will take it. > > Done. > > But... I tried to understand these check and failed. Why do we need them? > They look unneeded to me, but of course I know nothing about s390. Could be. I tried to figure out when and why this was added. But looks like this is >10 year old code. From roland at redhat.com Thu Dec 10 02:10:32 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 9 Dec 2009 18:10:32 -0800 (PST) Subject: s390: stepping && PT_PTRACED (Was: utrace failed to compile for s390x) In-Reply-To: Oleg Nesterov's message of Wednesday, 9 December 2009 20:54:28 +0100 <20091209195428.GA24928@redhat.com> References: <33810577.870481259720774110.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <2028524242.871741259724938476.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091202034229.25DF1BD8F@magilla.sf.frob.com> <20091202154129.GD4353@redhat.com> <20091202172749.GA11301@redhat.com> <20091203183525.0B65C2C081@pipsqueak.sf.frob.com> <20091209195428.GA24928@redhat.com> Message-ID: <20091210021033.03186595@magilla.sf.frob.com> > But... I tried to understand these check and failed. Why do we need them? > They look unneeded to me, but of course I know nothing about s390. It's not specific to s390. Other arch's have equivalent logic. As with all things ptrace, I strongly suspect that they just blindly copied the logic from some old i386 code and never contemplated the actual intent. AFAIK this is just part of some old defensive programming or partial mitigation of the general problem that we overload the user signal queue as a queue of debugger-induced hardware traps. This is some very incomplete mitigation--the general problem is a known issue we want to address in the future--but it's the status quo, so better not to tweak it now in case it might be closing an observable hole today in some usage pattern that someone might actually experience. The general problem has many corners and races and we still have those with or without this check. But consider e.g. the scenario where the debugger PTRACE_SINGLESTEP'd into a long-blocking syscall (read on a dangling pipe, etc.), then the debugger suddenly exits without doing a proper PTRACE_DETACH. That is an entirely non-racey case where TIF_SINGLE_STEP was left set but ->ptrace is clear, so without the check you could get the spurious SIGTRAP killing the tracee (the once-was-tracee-and-no-longer, that is). Perhaps nowadays exit_ptrace() leads to ptrace_disable() -> user_disable_single_step() and so the TIF_* bit is clear before resuming and getting here (or at least with utrace, it leads to UTRACE_DETACH and eventually to user_disable_single_step()). But at least before that (and it looks like with the 2.6.32 ptrace code still), it makes a difference in this scenario. So it is still an open can of worms I don't want us to dive into this week, but at least this one worm-escape hole should stay as plugged as it has been these last 10+ years. (For extra credit, write up that case in ptrace-tests and make it a KFAIL.) Thanks, Roland From mingo at elte.hu Thu Dec 10 07:41:58 2009 From: mingo at elte.hu (Ingo Molnar) Date: Thu, 10 Dec 2009 08:41:58 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091208215829.GA19793@redhat.com> References: <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> <20091201211518.GA32376@elte.hu> <20091208215829.GA19793@redhat.com> Message-ID: <20091210074158.GI16874@elte.hu> * Frank Ch. Eigler wrote: > > [...] > > > > If the in-kernel gdb stub replaced kgdb functionally you'd hear no > > complaints from me. > > Let's leave it as an idea for the future. We came a full circle - that's the argument. We say overlap, duplication and incomplete implementation in this area is a problem. Since the speed of development in this area is truly glacial at the moment and the practical advantages that i can experience personally (directly as a Linux user and indirectly as a maintainer) are miniscule so far, caution is warranted IMO. You say there is no problem. We'll have to agree to disagree i guess. Ingo From prehistorian at aaai.com.au Thu Dec 10 08:55:45 2009 From: prehistorian at aaai.com.au (Cheree) Date: Thu, 10 Dec 2009 05:55:45 -0300 Subject: (no subject) Message-ID: <4B20A8BE.9070804@aaai.com.au> -------------- next part -------------- A non-text attachment was scrubbed... Name: prerogatived.jpg Type: image/jpeg Size: 15514 bytes Desc: not available URL: From a2p at 9business.fr Thu Dec 10 14:21:46 2009 From: a2p at 9business.fr (Ets a2p) Date: Thu, 10 Dec 2009 15:21:46 +0100 Subject: Protection Incendie - Code du travail Message-ID: An HTML attachment was scrubbed... URL: From fche at redhat.com Thu Dec 10 15:08:57 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 10 Dec 2009 10:08:57 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091210074158.GI16874@elte.hu> (Ingo Molnar's message of "Thu, 10 Dec 2009 08:41:58 +0100") References: <1259588232.20516.307.camel@laptop> <20091130150314.GA10331@redhat.com> <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> <20091201211518.GA32376@elte.hu> <20091208215829.GA19793@redhat.com> <20091210074158.GI16874@elte.hu> Message-ID: Ingo Molnar writes: > [...] Since the speed of development in this area is truly glacial > at the moment and the practical advantages that i can experience > personally (directly as a Linux user and indirectly as a maintainer) > are miniscule so far, caution is warranted IMO. [...] If the "caution" you suggest is operationally equivalent to discouraging even miniscule improvements, is it any wonder that progress is glacial? The gdbstub prototype was constructed for two reasons: to demonstrate utrace usage now, and in the future to be incrementally useful (over ptrace, by moving into fast kernel-space operations like multithreading control, gdb-tracepoint support, other stuff). #1 is about done. With respect to #2, we can certainly commit to ongoing work on improvements, provided the community shows interest and goodwill. - FChE From mingo at elte.hu Thu Dec 10 18:16:38 2009 From: mingo at elte.hu (Ingo Molnar) Date: Thu, 10 Dec 2009 19:16:38 +0100 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: References: <20091130151650.GA24316@elte.hu> <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> <20091201211518.GA32376@elte.hu> <20091208215829.GA19793@redhat.com> <20091210074158.GI16874@elte.hu> Message-ID: <20091210181638.GA17986@elte.hu> * Frank Ch. Eigler wrote: > > Ingo Molnar writes: > > > [...] Since the speed of development in this area is truly glacial > > at the moment and the practical advantages that i can experience > > personally (directly as a Linux user and indirectly as a maintainer) > > are miniscule so far, caution is warranted IMO. [...] > > If the "caution" you suggest is operationally equivalent to > discouraging even miniscule improvements, is it any wonder that > progress is glacial? I think you might be mixing up cause and causation ;-) > The gdbstub prototype was constructed for two reasons: to demonstrate > utrace usage now, and in the future to be incrementally useful (over > ptrace, by moving into fast kernel-space operations like > multithreading control, gdb-tracepoint support, other stuff). #1 is > about done. With respect to #2, we can certainly commit to ongoing > work on improvements, provided the community shows interest and > goodwill. What i'd like to see is measurable benefits to users, developers and maintainers. I'd like to see the same for SystemTap too btw. Ingo From oleg at redhat.com Thu Dec 10 19:24:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 10 Dec 2009 20:24:36 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091210192436.GA21783@redhat.com> On 12/09, CAI Qian wrote: > > ----- "Oleg Nesterov" wrote: > > > Thanks, but it doesn't fail for me on this machine... > > Hmm, it failed for me. > > # cd /root/ptrace-tests > > # make check > ... > FAIL: watchpoint OMG. Yet another test-case fails on powerpc ???? I didn't see this failure in the previous reports or missed it ... I bet it fails without utrace too? (please don't tell it doesn't ;) Did you see it fails on other ppc64 machines? Oh well. I spent this day grepping arch/powerpc to understand how PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid this time I need a help from someone who understands the hardware magic on powerpc. So far: - the test-case looks correct to me - gdb uses PTRACE_SET_DEBUGREG to implement "watch var" too, and "watch" doesn't work. - the tracee notices thread.dabr correctly and calls set_dabr == pseries_set_dabr() from __switch_to - but do_dabr() or DebugException() is never called. Will continue tomorrow... > # make biarch-check > ... > FAIL: ppc-dabr-race Aaaaah. I didn't notice you did biarch-check, not check. Will take a look later... Oleg. From oleg at redhat.com Thu Dec 10 19:49:34 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Thu, 10 Dec 2009 20:49:34 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <20091210192436.GA21783@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> Message-ID: <20091210194934.GA23135@redhat.com> On 12/10, Oleg Nesterov wrote: > > On 12/09, CAI Qian wrote: > > > > ----- "Oleg Nesterov" wrote: > > > > > Thanks, but it doesn't fail for me on this machine... > > > > Hmm, it failed for me. > > > > # cd /root/ptrace-tests > > > > # make check > > ... > > FAIL: watchpoint > > OMG. Yet another test-case fails on powerpc ???? I didn't see this > failure in the previous reports or missed it ... > > I bet it fails without utrace too? (please don't tell it doesn't ;) > > Did you see it fails on other ppc64 machines? > > > Oh well. I spent this day grepping arch/powerpc to understand how > PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid > this time I need a help from someone who understands the hardware > magic on powerpc. > > So far: > > - the test-case looks correct to me OOPS. I am not sure, will re-check tomorrow. But it seems to me gcc optimizes out "check = 1", despite the fact it is declared as volatile. Oleg. From caiqian at redhat.com Thu Dec 10 23:56:25 2009 From: caiqian at redhat.com (CAI Qian) Date: Thu, 10 Dec 2009 18:56:25 -0500 (EST) Subject: Tests Failures on PPC64 In-Reply-To: <20091210192436.GA21783@redhat.com> Message-ID: <496340831.1452791260489385630.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > I bet it fails without utrace too? (please don't tell it doesn't ;) Yes. > Did you see it fails on other ppc64 machines? No. > Aaaaah. I didn't notice you did biarch-check, not check. > Will take a look later... Thanks in advance, CAI Qian From fche at redhat.com Fri Dec 11 01:27:38 2009 From: fche at redhat.com (Frank Ch. Eigler) Date: Thu, 10 Dec 2009 20:27:38 -0500 Subject: [RFC] [PATCH] In-kernel gdbstub based on utrace Infrastructure. In-Reply-To: <20091210181638.GA17986@elte.hu> References: <20091130152910.GB10331@redhat.com> <20091201161132.GA24897@elte.hu> <20091201170002.GD10331@redhat.com> <20091201170954.GA4699@elte.hu> <20091201174534.GE10331@redhat.com> <20091201211518.GA32376@elte.hu> <20091208215829.GA19793@redhat.com> <20091210074158.GI16874@elte.hu> <20091210181638.GA17986@elte.hu> Message-ID: <20091211012738.GA646@redhat.com> Hi - On Thu, Dec 10, 2009 at 07:16:38PM +0100, Ingo Molnar wrote: > [...] > > The gdbstub prototype was constructed for two reasons: to demonstrate > > utrace usage now, and in the future to be incrementally useful (over > > ptrace, by moving into fast kernel-space operations like > > multithreading control, gdb-tracepoint support, other stuff). [...] > > What i'd like to see is measurable benefits to users, developers and > maintainers. OK, it's clear that in the gdb-stub's case, some positive motivation beyond it being an api-educational example would be appropriate before merging. Note that it was only an RFC at the time. > I'd like to see the same for SystemTap too btw. systemtap's benefits are beyond question to its users. (Others are worried about systemtap problems, but that wasn't your question.) In what form do you expect to see such measurements? It would help if you could point out prior examples of such "measurable benefit" analyses that perchance accompanied other then-new kernel features, say in the tracing/debugging area. - FChE From bloomed at swedishcraft.nu Fri Dec 11 03:06:58 2009 From: bloomed at swedishcraft.nu (Bear Chesnutt) Date: Fri, 11 Dec 2009 04:06:58 +0100 Subject: (no subject) Message-ID: <4B21B432.8030701@swedishcraft.nu> -------------- next part -------------- A non-text attachment was scrubbed... Name: presuming.jpg Type: image/jpeg Size: 19164 bytes Desc: not available URL: From prasad at linux.vnet.ibm.com Fri Dec 11 05:35:49 2009 From: prasad at linux.vnet.ibm.com (K.Prasad) Date: Fri, 11 Dec 2009 11:05:49 +0530 Subject: Tests Failures on PPC64 In-Reply-To: <20091210192436.GA21783@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> Message-ID: <20091211053549.GA13245@in.ibm.com> On Thu, Dec 10, 2009 at 08:24:36PM +0100, Oleg Nesterov wrote: > On 12/09, CAI Qian wrote: > > > > ----- "Oleg Nesterov" wrote: > > > > > Thanks, but it doesn't fail for me on this machine... > > > > Hmm, it failed for me. > > > > # cd /root/ptrace-tests > > > > # make check > > ... > > FAIL: watchpoint > > OMG. Yet another test-case fails on powerpc ???? I didn't see this > failure in the previous reports or missed it ... > > I bet it fails without utrace too? (please don't tell it doesn't ;) > > Did you see it fails on other ppc64 machines? > > > Oh well. I spent this day grepping arch/powerpc to understand how > PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid > this time I need a help from someone who understands the hardware > magic on powerpc. > There's relatively less magic with PPC64 (with just one DABR) compared to x86 :-) I hope to offer a little help here (given that I work to tweak ptrace_set_debugreg() in PPC64 to use the hw-breakpoint interfaces).... Watchpoints (using DABR) through GDB can fail for many reasons....they must ideally be set after the program has started execution - to enable GDB know the size of the variable...else they would resort to single-stepping to trap access to the target variable. Cai, Where can one find the relevant piece of testcase? Thanks, K.Prasad From oleg at redhat.com Fri Dec 11 15:06:12 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 11 Dec 2009 16:06:12 +0100 Subject: powerpc: PPC970FX dabr bug? (Was: Tests Failures on PPC64) In-Reply-To: <20091210194934.GA23135@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091210194934.GA23135@redhat.com> Message-ID: <20091211150612.GA13576@redhat.com> For those who didn't read the whole thread, the test-case: http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/watchpoint.c?cvsroot=systemtap On 12/10, Oleg Nesterov wrote: > > On 12/10, Oleg Nesterov wrote: > > > > On 12/09, CAI Qian wrote: > > > > > > ----- "Oleg Nesterov" wrote: > > > > > > > Thanks, but it doesn't fail for me on this machine... > > > > > > Hmm, it failed for me. > > > > > > # cd /root/ptrace-tests > > > > > > # make check > > > ... > > > FAIL: watchpoint > > > > OMG. Yet another test-case fails on powerpc ???? I didn't see this > > failure in the previous reports or missed it ... > > > > I bet it fails without utrace too? (please don't tell it doesn't ;) > > > > Did you see it fails on other ppc64 machines? > > > > > > Oh well. I spent this day grepping arch/powerpc to understand how > > PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid > > this time I need a help from someone who understands the hardware > > magic on powerpc. > > > > So far: > > > > - the test-case looks correct to me > > OOPS. > > I am not sure, will re-check tomorrow. But it seems to me gcc > optimizes out "check = 1", despite the fact it is declared as > volatile. No, I misread the asm (which I don't understand anyway). The tracee does write to check, and this is even seen by PTRACE_PEEKDATA. Looks like a hardware problem to me. For example, this patch --- watchpoint.c~ 2009-12-11 15:32:14.000000000 +0100 +++ watchpoint.c 2009-12-11 15:36:17.000000000 +0100 @@ -144,7 +144,7 @@ handler_fail (int signo) raise (signo); } -static volatile long long check; +volatile long long check; int main (void) "fixes" the problem. This one --- watchpoint.c~ 2009-12-11 15:32:14.000000000 +0100 +++ watchpoint.c 2009-12-11 15:38:10.000000000 +0100 @@ -169,7 +169,7 @@ main (void) i = raise (SIGUSR1); assert (i == 0); - check = 1; + check = 0xfff; i = raise (SIGUSR2); assert (i == 0); helps too (any value which can't be "immediate" for powerpc works, unless I misinterpret asm again). I give up, this needs a help from powerpc experts. As a last resort I tried google, # grep cpu /proc/cpuinfo cpu : PPC970FX, altivec supported cpu : PPC970FX, altivec supported http://www.google.com/linux?q=powerpc+970FX+dabr+bug from http://lists.ozlabs.org/pipermail/linuxppc-dev/2008-March/052910.html Which is "IBM PowerPC 970FX RISC Microprocessor Errata List for DD3.X" and contains "Erratum #8: DABRX register might not always be updated correctly": Projected Impact The data address breakpoint function might not always work. Workaround None. Status A fix is not planned at this time for the PowerPC 970FX. but this machine sets set_dabr = pseries_set_dabr(), not pseries_set_xdabr(), not sure this is relevant. Gurus, please help! Oleg. From oleg at redhat.com Fri Dec 11 15:59:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 11 Dec 2009 16:59:44 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <20091211053549.GA13245@in.ibm.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091211053549.GA13245@in.ibm.com> Message-ID: <20091211155944.GB13576@redhat.com> On 12/11, K.Prasad wrote: > > On Thu, Dec 10, 2009 at 08:24:36PM +0100, Oleg Nesterov wrote: > > > > Oh well. I spent this day grepping arch/powerpc to understand how > > PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid > > this time I need a help from someone who understands the hardware > > magic on powerpc. > > > > There's relatively less magic with PPC64 (with just one DABR) compared > to x86 :-) > > I hope to offer a little help here (given that I work to tweak > ptrace_set_debugreg() in PPC64 to use the hw-breakpoint interfaces).... Thanks, please see another email, I cc'ed you. > Watchpoints (using DABR) through GDB can fail for many reasons....they > must ideally be set after the program has started execution - to enable > GDB know the size of the variable...else they would resort to > single-stepping to trap access to the target variable. Yes. I straced gdb to be sure it really does PTRACE_SET_DEBUGREF to use the hardware watchpoint. There is something strange though. gdb does PTRACE_SINGLESTEP and only then PTRACE_CONT after "watch xxx". > Where can one find the relevant piece of testcase? http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/watchpoint.c?cvsroot=systemtap Oleg. From prasad at linux.vnet.ibm.com Fri Dec 11 16:31:22 2009 From: prasad at linux.vnet.ibm.com (K.Prasad) Date: Fri, 11 Dec 2009 22:01:22 +0530 Subject: Tests Failures on PPC64 In-Reply-To: <20091211155944.GB13576@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091211053549.GA13245@in.ibm.com> <20091211155944.GB13576@redhat.com> Message-ID: <20091211163122.GC23156@in.ibm.com> On Fri, Dec 11, 2009 at 04:59:44PM +0100, Oleg Nesterov wrote: > On 12/11, K.Prasad wrote: > > Watchpoints (using DABR) through GDB can fail for many reasons....they > > must ideally be set after the program has started execution - to enable > > GDB know the size of the variable...else they would resort to > > single-stepping to trap access to the target variable. > > Yes. I straced gdb to be sure it really does PTRACE_SET_DEBUGREF to > use the hardware watchpoint. > > There is something strange though. gdb does PTRACE_SINGLESTEP and only > then PTRACE_CONT after "watch xxx". > I haven't taken a good look at the testcase...although I suspect that the use of PTRACE_SINGLESTEP vs PTRACE_SET_DEBUGREG during your trials is due to the way "watch " is being set. For instance, here are two screenlogs taken from a PPC64 (Power5 box running RHEL 5.3 2.6.18-128.el5). It can be seen that hw-breakpoints are used only during the second-run of GDB vs single-stepping done in the first...wondering if you used it in similar ways. First run ----------- [root at p510 ~]# gdb prasad GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "ppc64-redhat-linux-gnu"... (gdb) watch b Watchpoint 1: b <--------(Watchpoint vs Hardware watchpoint) (gdb) r Starting program: /root/prasad Prasad: sizeof(long): sizeof(b)=4 Watchpoint 1: b Old value = 0 New value = 200 main () at a.c:17 17 i = 300; (gdb) c Second run ----------- [root at p510 ~]# gdb prasad GNU gdb Fedora (6.8-27.el5) Copyright (C) 2008 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "ppc64-redhat-linux-gnu"... (gdb) start Breakpoint 1 at 0x100004bc: file a.c, line 14. Starting program: /root/prasad main () at a.c:14 14 printf("\nPrasad: sizeof(long): sizeof(b)=%d\n", sizeof(b)); (gdb) watch b Hardware watchpoint 2: b <----------(uses DABR unlike the firstrun) (gdb) q The program is running. Exit anyway? (y or n) y From oleg at redhat.com Fri Dec 11 16:58:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 11 Dec 2009 17:58:06 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <20091211163122.GC23156@in.ibm.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091211053549.GA13245@in.ibm.com> <20091211155944.GB13576@redhat.com> <20091211163122.GC23156@in.ibm.com> Message-ID: <20091211165806.GA18096@redhat.com> On 12/11, K.Prasad wrote: > > On Fri, Dec 11, 2009 at 04:59:44PM +0100, Oleg Nesterov wrote: > > > > Yes. I straced gdb to be sure it really does PTRACE_SET_DEBUGREF to > > use the hardware watchpoint. > > > > There is something strange though. gdb does PTRACE_SINGLESTEP and only > > then PTRACE_CONT after "watch xxx". > > > > I haven't taken a good look at the testcase...although I suspect that > the use of PTRACE_SINGLESTEP vs PTRACE_SET_DEBUGREG during your trials > is due to the way "watch " is being set. > > For instance, here are two screenlogs taken from a PPC64 (Power5 box > running RHEL 5.3 2.6.18-128.el5). It can be seen that hw-breakpoints are > used only during the second-run of GDB vs single-stepping done in the > first...wondering if you used it in similar ways. # cat T.c #include int volatile var; int main(void) { printf("without this printf dabr works\n"); var = 0xfff; return 0; } then, # cc -Wall -O2 -g -o t T.c && gdb ./t GNU gdb (GDB) Fedora (6.8.50.20090811-2.el6) Copyright (C) 2009 Free Software Foundation, Inc. License GPLv3+: GNU GPL version 3 or later This is free software: you are free to change and redistribute it. There is NO WARRANTY, to the extent permitted by law. Type "show copying" and "show warranty" for details. This GDB was configured as "ppc64-redhat-linux-gnu". For bug reporting instructions, please see: ... (gdb) b main Breakpoint 1 at 0x10000534: file T.c, line 7. (gdb) r Starting program: /root/TST/t Breakpoint 1, main () at T.c:7 7 printf("without this printf dabr works\n"); Missing separate debuginfos, use: debuginfo-install glibc-2.10.90-26.ppc64 (gdb) watch var Hardware watchpoint 2: var (gdb) c Continuing. without this printf dabr works Program exited normally. (gdb) strace shows that "c" after "watch var" does: ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_SINGLESTEP, 26680, 0x1, SIG_0) = 0 --- SIGCHLD (Child exited) @ 0 (0) --- ptrace(0x4202 /* PTRACE_??? */, 26680, 0, 0x131390d0) = 0 ptrace(PTRACE_PEEKUSER, 26680, NIP, [0x10000538]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000538, [0xf8010010f821ff91]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000538, [0xf8010010f821ff91]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_PEEKUSER, 26680, r1, [0xffffffff160]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10010b40, [0]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0x10000530, [0x7c0802a6e8628020]) = 0 ptrace(PTRACE_POKEDATA, 26680, 0x10000530, 0x7c0802a67d821008) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0xfffb7fd6300, [0x4e80002000000000]) = 0 ptrace(PTRACE_PEEKTEXT, 26680, 0xfffb7fd6300, [0x4e80002000000000]) = 0 ptrace(PTRACE_POKEDATA, 26680, 0xfffb7fd6300, 0x7d82100800000000) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(PTRACE_PEEKUSER, 26680, MSR, [0x800000005010d032]) = 0 ptrace(0x1a /* PTRACE_??? */, 26680, 0, 0x10010b46) = 0 <======= SET_DEBUGREG ptrace(PTRACE_CONT, 26680, 0x1, SIG_0) = 0 Oleg. From oleg at redhat.com Fri Dec 11 17:17:06 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 11 Dec 2009 18:17:06 +0100 Subject: powerpc: PPC970FX dabr bug? (Was: Tests Failures on PPC64) In-Reply-To: <20091211150612.GA13576@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091210194934.GA23135@redhat.com> <20091211150612.GA13576@redhat.com> Message-ID: <20091211171706.GA19482@redhat.com> On 12/11, Oleg Nesterov wrote: > > For those who didn't read the whole thread, the test-case: > http://sources.redhat.com/cgi-bin/cvsweb.cgi/~checkout~/tests/ptrace-tests/tests/watchpoint.c?cvsroot=systemtap or you can look at https://www.redhat.com/archives/utrace-devel/2009-December/msg00096.html it is very easy to reproduce the problem with gdb. > On 12/10, Oleg Nesterov wrote: > > > > On 12/10, Oleg Nesterov wrote: > > > > > > On 12/09, CAI Qian wrote: > > > > > > > > ----- "Oleg Nesterov" wrote: > > > > > > > > > Thanks, but it doesn't fail for me on this machine... > > > > > > > > Hmm, it failed for me. > > > > > > > > # cd /root/ptrace-tests > > > > > > > > # make check > > > > ... > > > > FAIL: watchpoint > > > > > > OMG. Yet another test-case fails on powerpc ???? I didn't see this > > > failure in the previous reports or missed it ... > > > > > > I bet it fails without utrace too? (please don't tell it doesn't ;) > > > > > > Did you see it fails on other ppc64 machines? > > > > > > > > > Oh well. I spent this day grepping arch/powerpc to understand how > > > PTRACE_SET_DEBUGREG works and what is the problem. But I am afraid > > > this time I need a help from someone who understands the hardware > > > magic on powerpc. > > > > > > So far: > > > > > > - the test-case looks correct to me > > > > OOPS. > > > > I am not sure, will re-check tomorrow. But it seems to me gcc > > optimizes out "check = 1", despite the fact it is declared as > > volatile. > > No, I misread the asm (which I don't understand anyway). The tracee > does write to check, and this is even seen by PTRACE_PEEKDATA. > > Looks like a hardware problem to me. For example, this patch > > --- watchpoint.c~ 2009-12-11 15:32:14.000000000 +0100 > +++ watchpoint.c 2009-12-11 15:36:17.000000000 +0100 > @@ -144,7 +144,7 @@ handler_fail (int signo) > raise (signo); > } > > -static volatile long long check; > +volatile long long check; > > int > main (void) > > "fixes" the problem. This one > > --- watchpoint.c~ 2009-12-11 15:32:14.000000000 +0100 > +++ watchpoint.c 2009-12-11 15:38:10.000000000 +0100 > @@ -169,7 +169,7 @@ main (void) > i = raise (SIGUSR1); > assert (i == 0); > > - check = 1; > + check = 0xfff; > > i = raise (SIGUSR2); > assert (i == 0); > > helps too (any value which can't be "immediate" for powerpc works, > unless I misinterpret asm again). > > > I give up, this needs a help from powerpc experts. As a last resort > I tried google, > > # grep cpu /proc/cpuinfo > cpu : PPC970FX, altivec supported > cpu : PPC970FX, altivec supported > > > http://www.google.com/linux?q=powerpc+970FX+dabr+bug > > from http://lists.ozlabs.org/pipermail/linuxppc-dev/2008-March/052910.html > > Which is "IBM PowerPC 970FX RISC Microprocessor Errata List for DD3.X" > and contains "Erratum #8: DABRX register might not always be updated correctly": > > Projected Impact > The data address breakpoint function might not always work. > Workaround > None. > Status > A fix is not planned at this time for the PowerPC 970FX. > > but this machine sets set_dabr = pseries_set_dabr(), not pseries_set_xdabr(), > not sure this is relevant. > > Gurus, please help! > > Oleg. From oleg at redhat.com Sat Dec 12 16:53:35 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Dec 2009 17:53:35 +0100 Subject: [PATCH 1/4] utrace: kill mb() in tracehook_report_death() Message-ID: <20091212165335.GA25693@redhat.com> As Peter pointed out, this barrier is not needed. utrace_set_events() and tracehook_report_death() can rely on tasklist_lock. utrace_set_events() checks ->exit_state == 0 and adds DEATH_EVENTS under tasklist_lock. After exit_notify() sets ->exit_state under write_lock(tasklist) we must see the change in flags. utrace_set_events() does not set _UTRACE_DEATH_EVENTS if ->exit_state was already set by exit_notify(), and after we set ->exit_state under write_lock(tasklist) we must see the change in ->utrace_flags. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 9 ++------- 1 file changed, 2 insertions(+), 7 deletions(-) --- UTRACE-PTRACE/include/linux/tracehook.h~1_REPORT_DEATH_KILL_MB 2009-11-18 21:16:23.000000000 +0100 +++ UTRACE-PTRACE/include/linux/tracehook.h 2009-12-12 16:32:39.000000000 +0100 @@ -626,17 +626,12 @@ static inline void tracehook_report_deat int group_dead) { /* - * This barrier ensures that our caller's setting of - * @task->exit_state precedes checking @task->utrace_flags here. * If utrace_set_events() was just called to enable * UTRACE_EVENT(DEATH), then we are obliged to call * utrace_report_death() and not miss it. utrace_set_events() - * uses tasklist_lock to synchronize enabling the bit with the - * actual change to @task->exit_state, but we need this barrier - * to be sure we see a flags change made just before our caller - * took the tasklist_lock. + * checks @task->exit_state under tasklist_lock to synchronize + * with exit_notify(), the caller. */ - smp_mb(); if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) utrace_report_death(task, death_cookie, group_dead, signal); } From oleg at redhat.com Sat Dec 12 16:53:38 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Dec 2009 17:53:38 +0100 Subject: [PATCH 2/4] utrace: fix the ->cloning check in utrace_attach_delay() Message-ID: <20091212165338.GA25697@redhat.com> Due to typo, utrace_attach_delay() always succeeds if the caller is not traced. The creator must have the valid ->utrace != NULL and utrace->cloning should be target. Signed-off-by: Oleg Nesterov --- kernel/utrace.c | 20 ++++++++++++-------- 1 file changed, 12 insertions(+), 8 deletions(-) --- UTRACE-PTRACE/kernel/utrace.c~2_ATTACH_DELAY_TYPO 2009-12-05 16:02:50.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-12-12 16:49:26.000000000 +0100 @@ -184,14 +184,18 @@ static struct utrace_engine *matching_en */ static inline int utrace_attach_delay(struct task_struct *target) { - if ((target->flags & PF_STARTING) && - task_utrace_struct(current) && - task_utrace_struct(current)->cloning != target) - do { - schedule_timeout_interruptible(1); - if (signal_pending(current)) - return -ERESTARTNOINTR; - } while (target->flags & PF_STARTING); + if (!unlikely(target->flags & PF_STARTING)) + return 0; + + if (task_utrace_struct(current) && + task_utrace_struct(current)->cloning == target) + return 0; + + do { + schedule_timeout_interruptible(1); + if (signal_pending(current)) + return -ERESTARTNOINTR; + } while (target->flags & PF_STARTING); return 0; } From oleg at redhat.com Sat Dec 12 16:53:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Dec 2009 17:53:40 +0100 Subject: [PATCH 3/4] utrace: improve the comment in tracehook_notify_resume() Message-ID: <20091212165340.GA25700@redhat.com> My attempt to make the comment more explicit. Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) --- UTRACE-PTRACE/include/linux/tracehook.h~3_NOTIFY_RESUME_MB_COMMENT 2009-12-12 16:32:39.000000000 +0100 +++ UTRACE-PTRACE/include/linux/tracehook.h 2009-12-12 17:28:03.000000000 +0100 @@ -670,9 +670,10 @@ static inline void tracehook_notify_resu { struct task_struct *task = current; /* - * This pairs with the barrier implicit in set_notify_resume(). - * It ensures that we read the nonzero utrace_flags set before - * set_notify_resume() was called by utrace setup. + * If we race with attach which sets nonzero ->utrace_flags, + * make sure we do not read ->utrace_flags before the caller + * clears TIF_NOTIFY_RESUME. This pairs with the implicit mb() + * before setting TIF_NOTIFY_RESUME in set_notify_resume(). */ smp_rmb(); if (task_utrace_flags(task)) From oleg at redhat.com Sat Dec 12 16:53:43 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Sat, 12 Dec 2009 17:53:43 +0100 Subject: [PATCH 4/4] utrace: fix the comments about rmb() in task_utrace_struct() Message-ID: <20091212165343.GA25708@redhat.com> Move the comment from utrace_task_alloc() to utrace_add_engine() and try to make it a bit more clear. Signed-off-by: Oleg Nesterov --- include/linux/utrace.h | 4 ++-- kernel/utrace.c | 11 +++++------ 2 files changed, 7 insertions(+), 8 deletions(-) --- UTRACE-PTRACE/include/linux/utrace.h~4_ADD_ENGINE_DOCUMENT_IMPLICIT_MB 2009-11-21 15:12:27.000000000 +0100 +++ UTRACE-PTRACE/include/linux/utrace.h 2009-12-12 17:42:16.000000000 +0100 @@ -164,8 +164,8 @@ static inline struct utrace *task_utrace * is ordered before this load of task->utrace. We use those * utrace_flags checks in the hot path to decide to call into * the utrace code. The first attach installs task->utrace before - * setting task->utrace_flags nonzero, with a barrier between. - * See utrace_task_alloc(). + * setting task->utrace_flags nonzero with implicit barrier in + * between, see utrace_add_engine(). */ smp_rmb(); utrace = task->utrace; --- UTRACE-PTRACE/kernel/utrace.c~4_ADD_ENGINE_DOCUMENT_IMPLICIT_MB 2009-12-12 16:49:26.000000000 +0100 +++ UTRACE-PTRACE/kernel/utrace.c 2009-12-12 17:46:55.000000000 +0100 @@ -107,11 +107,7 @@ static bool utrace_task_alloc(struct tas task->utrace = utrace; } task_unlock(task); - /* - * That unlock after storing task->utrace acts as a memory barrier - * ordering any subsequent task->utrace_flags store afterwards. - * This pairs with smp_rmb() in task_utrace_struct(). - */ + if (unlikely(task->utrace != utrace)) kmem_cache_free(utrace_cachep, utrace); return true; @@ -221,7 +217,10 @@ static int utrace_add_engine(struct task /* * In case we had no engines before, make sure that - * utrace_flags is not zero. + * utrace_flags is not zero. Since we did unlock+lock + * at least once after utrace_task_alloc() installed + * ->utrace, we have the necessary barrier which pairs + * with rmb() in task_utrace_struct(). */ ret = -ESRCH; if (!target->utrace_flags) { From sulfuryl at derniermot.net Sat Dec 12 23:14:19 2009 From: sulfuryl at derniermot.net (Didomenico) Date: Sun, 13 Dec 2009 00:14:19 +0100 Subject: (no subject) Message-ID: <4B242163.1080607@derniermot.net> -------------- next part -------------- A non-text attachment was scrubbed... Name: polygamize.jpg Type: image/jpeg Size: 19171 bytes Desc: not available URL: From roland at redhat.com Sun Dec 13 19:50:03 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 13 Dec 2009 11:50:03 -0800 (PST) Subject: Tests Failures on PPC64 In-Reply-To: Oleg Nesterov's message of Friday, 11 December 2009 16:59:44 +0100 <20091211155944.GB13576@redhat.com> References: <20091209183648.GB21076@redhat.com> <1060453513.1373101260421036327.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091210192436.GA21783@redhat.com> <20091211053549.GA13245@in.ibm.com> <20091211155944.GB13576@redhat.com> Message-ID: <20091213195003.27D7C9A@magilla.sf.frob.com> > Yes. I straced gdb to be sure it really does PTRACE_SET_DEBUGREF to > use the hardware watchpoint. > > There is something strange though. gdb does PTRACE_SINGLESTEP and only > then PTRACE_CONT after "watch xxx". powerpc's data breakpoints are before-access, whereas x86's are after-access. In x86-speak, it's a fault-type exception rather than a trap-type. The only way to actually get the caught load or store to complete is to clear the DABR, single-step, and then restore it. Thanks, Roland From roland at redhat.com Sun Dec 13 20:48:47 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 13 Dec 2009 12:48:47 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Peter Zijlstra's message of Tuesday, 8 December 2009 19:19:38 +0100 <1260296378.17334.21.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091201220847.GA25400@redhat.com> <1260210877.3935.594.camel@laptop> <20091208150417.GA11883@redhat.com> <1260286163.3935.1497.camel@laptop> <20091208163131.GA14815@redhat.com> <1260296378.17334.21.camel@laptop> Message-ID: <20091213204848.02B2B1DE@magilla.sf.frob.com> > All that seems to do is call ->release() and kmem_cache_free()s the > utrace_engine thing, why can't that be done with utrace->lock held? Calling ->release with a lock held is clearly insane, sorry. It is true that any engine-writer who does anything like utrace_* calls inside their release callback is doing things the wrong way. But guaranteeing that simple mistakes result in spin-lock deadlocks just seems clearly wrong to me. A main point of the utrace API is to make it easier to work in this space and help you avoid writing the pathological bugs. Adding picayune gotchas like this just does not help anyone. No other API callback is made holding some internal implementation lock, and making this one the sole exception seems just obviously ill-advised on its face. I can't really imagine what a justification for such an obfuscation would be. > But yeah, passing that list along does seem like a better solution. So you find it cleaner to have each caller of utrace_reset take another output parameter and be followed with the same exact source code duplicated in each call site, than to have utrace_reset() do the unlock and then the common code itself. I guess there is no accounting for taste. We try not to get excited about trivia, so on matters like this one we will do whatever the consensus of gate-keeping reviewers wants. My patch to implement your suggestion adds 13 lines of source and 134 bytes of compiled text (x86-64). Is that what you prefer? I'll note that the code as it stands uses the __releases annotation for sparse, as well as thoroughly documenting the locking details in comments. I gather that clear explanation of the code is in your eyes no excuse for ever writing code that requires one to actually read the comments. I'm not sure that attitude can ever be satisfied by any code that is nontrivial or makes any attempts at optimization. Thanks, Roland From roland at redhat.com Mon Dec 14 00:25:33 2009 From: roland at redhat.com (Roland McGrath) Date: Sun, 13 Dec 2009 16:25:33 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Peter Zijlstra's message of Tuesday, 1 December 2009 20:54:02 +0100 <1259697242.1697.1075.camel@laptop> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> Message-ID: <20091214002533.3052519@magilla.sf.frob.com> I'm sorry for the delay. I'm picking up with responding to the parts of your review that I did not include in my first reply. I appreciate very much the discussion you've had with Oleg about the issues that I did not address myself. I look forward to your replies to my comments in that first reply, which we have yet to see. > Seems inconsistent on u32 vs enum utrace_resume_action. > > Why force enum utrace_resume_action into a u32? The first argument to almost all callbacks (all the ones made when the task is alive) is called "action" and it's consistent that its low bits contain an enum utrace_resume_action. The argument is "u32 action" in the report_signal and report_syscall_entry callbacks, where it combines an enum utrace_resume_action with an enum utrace_{signal,syscall}_action (respectively). It would indeed be more consistent to use "u32 action" throughout, but it seemed nicer not to have engine writers always writing "utrace_resume_action(action)" for all the cases where there are no other bits in there. The return value is a mirror of the "u32 action" argument. In many calls, it has only an enum utrace_resume_action in it. But in some it combines that with another enum utrace_*_action. There I went for consistency (and less typing) in the return type, since it doesn't make any difference to how you have to write the code in your callback function. The main reason I used "u32" at all instead of "unsigned int" is just its shortness for less typing. I don't really mind changing these details to whatever people think is best. The other people writing code to use the utrace API may have more opinions than I do. I guess it could even be OK to make the return value and "action" argument always a plain enum utrace_resume_action, and use a second in/out "enum utrace_{signal,syscall}_action *" parameter in those particular calls. But that does put some more register pressure and loads/stores into this API. > Seems inconsistent in the bitfield type, also it feels like that 3 the 7 > and the enum should be more tightly integrated, maybe add: > > UTRACE_RESUME_MAX > > #define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX)) > #define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) Yes, that's a good cleanup. Thanks. (ilog2(7) is 2, so ilog2() + 1 is what you meant.) > > +static struct utrace_engine *matching_engine( [...] > The function does a search, suggesting the function name ought to have > something like find or search in it. Ok, I'll make it find_matching_engine. > Quite gross this.. can't we key off the > tracehoook_report_clone_complete() and use a wakeup there? Yes, we intended to clean this up at some point later. But doing that is just a distraction and complication right now so we put it off. For this case, however, I suppose we could just punt for the initial version. This code exists to support the special semantics of calling utrace_attach_task() from inside the parent's report_clone() callback. That guarantees the parent that it wins any race with any third thread calling utrace_attach_task(). This guarantees it will be first attacher in the callback order, but the general subject of callback order is already something we think we will want to revisit in the future after we have more experience with lots of different engines trying to work together. It's most meaningful when using the UTRACE_ATTACH_EXCLUSIVE flag--then you can use UTRACE_ATTACH_EXCLUSIVE|UTRACE_ATTACH_MATCH_OPS to synchronize with other threads trying to attach the same kind of engine to a task, and give special priority in that to the engine that attaches in report_clone() from tracing the parent. Really I came up with this special semantics originally just with ptrace in mind. ptrace is an engine that wants to exclude other tracer threads attaching asynchronously with the same kind of engine, and that wants to give special priority on a child to the parent's tracer (to implement PTRACE_O_TRACECLONE et al). However, Oleg's current ptrace code still relies on the old hard-coded locking kludges to exclude the separate attachers and to magically privilege the auto-attach from the parent's tracer. So we are not relying on this special semantics yet. We could just punt utrace_attach_delay() and remove the associated documentation about the special rights of report_clone() calling utrace_attach_task(). If we decide it helps clean things up later when we finish more cleanup of the ptrace world, then we can add the fancy semantics back in later. > Does this really need the inline? It has one caller and that call is unconditional. > Asymmetric locking like this is really better not done, and looking at > the callsites its really no bother to clean that up, arguably even makes > them saner. By "assymetric" you mean that utrace_reap releases a lock (as the __releases annotation indicates). As should be obvious from the code, the unlock is done before the loop that does ->report_reap callbacks and utrace_engine_put() (which can make ->release callbacks). Surely you are not suggesting that all these callbacks should be made with a spin lock held, because that would obviously be quite insane. I tried splitting utrace_reap() into two functions, so the callers make the first call, then unlock, and then make the second call. Both callers do this identically, so this just replaces utrace_reap(task, utrace); with: prepare_utrace_reap(task, utrace); spin_unlock(&utrace->lock); finish_utrace_reap(task, utrace); in two places. That change adds 13 source lines and 71 bytes of compiled text (x86-64). Is that what you had in mind? > You could codify locking assumptions like here using: > > lockdep_assert_held(&utrace->lock); > > Saves a comment and actually validates the assumption. Ok, that is fine with me. > > + /* > > + * If ptrace is among the reasons for this stop, do its > > + * notification now. This could not just be done in > > + * ptrace's own event report callbacks because it has to > > + * be done after we are in TASK_TRACED. This makes the > > + * synchronization with ptrace_do_wait() work right. > > + */ > > + ptrace_notify_stop(task); > > Well, this is a bit disappointing isn't it? So we cannot implement > ptrace on utrace without special purpose hooks? It's more of an issue that ptrace is built around special-purpose hooks in wait. We do intend to clean this up later. But it is as much about cleaning up the remaining deep insanity of the old ptrace implementation as about giving utrace better facilities for this wrinkle of synchronization. I don't doubt that the utrace API will get some changes and improvements along the way as we move incrementally to all of the ptrace internals being done in as clean and sane fashion as the legacy ptrace userland ABI makes possible. But Oleg has not yet gotten to that part of the the ptrace cleanup, and the actual problem that necessitates this kludge for ptrace is not an issue at all for many other uses of utrace that don't have to tie into a broken old model of things. So being perfectly clean here is not something we should even think we know how best to do yet, since there has been so little real call for it. It would be counterproductive to make this perfection an obstacle to incremental merging of the current utrace pieces that already enable other kinds of new functionality. > If its a programming error, WARN_ON might be appropriate, no point in > being nice about it. Sure, except that any WARN_ON shows up as "oops in utrace.c" and then people think the bug is in utrace rather than in the caller. > Seriously ugly, again. Use a wakeup where appropriate. > Its not entirely clear why we can check pending_attach outside of the > utrace->lock and not be racy. I think it can be racy sometimes but that does not matter. Maybe Oleg can verify my logic here. If it's right, he can add some comments to make it more clear. There is only a very limited sort of "timeliness" guarantee about getting your callbacks after utrace_attach_task()+utrace_set_events(). If you know somehow that the task was definitely still in TASK_STOPPED or TASK_TRACED after utrace_attach_task() returned, then your engine gets all possible callbacks starting from when it resumes. Otherwise, you can use utrace_control() with UTRACE_REPORT to ask to get some callback "pretty soon". The only callback events you are ever 100% guaranteed about (after success return from utrace_set_events()) are for DEATH and REAP, which have an unconditional lock-and-check before making engine callbacks. In the stopped cases, there are lots of locks and barriers and things after resuming. (Oleg?) In the "pretty soon" case, that means set_notify_resume: if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) kick_process(task); i.e. IPI after test_and_set. The test_and_set implies an smp_mb(). So it should be the case that the set of utrace->pending_attach was seen before the set of TIF_NOTIFY_RESUME. In a race where the tracee just saw utrace->pending_attach==0, then it has TIF_NOTIFY_RESUME set still (or again), and so will go around again before getting back to user mode. > > + if (!engine_wants_stop(engine)) { > > + spin_lock(&utrace->lock); > > + /* > > + * If utrace_control() came in and detached us > > + * before we got the lock, we must not stop now. > > + */ > > + if (unlikely(engine->ops == &utrace_detached_ops)) > > + report->detaches = true; > > + else > > + mark_engine_wants_stop(task, engine); > > + spin_unlock(&utrace->lock); > > + } > > +} > > I'm pretty sure that inline isn't really needed. You mean mark_engine_wants_stop? You prefer repeating the two lines of code to using a helper to encapsulate the magic? Really? > Simply cond_resched() is sufficient, but that comment sucks, as it > doesn't mention _why_ it is a good place. > > It seems to turn out that finish_callback() is always the last thing we > do in the engine iterations in REPORT_CALLBACKS() and > utrace_get_signal(). Oh, sorry. I didn't realize it wasn't obvious that finish_callback() is called after every engine callback, given its name. I've changed it to: /* * We've just done an engine callback. These are allowed to sleep, * though all well-behaved ones restrict that to blocking kalloc() * or quickly-acquired mutex_lock() and the like. This is a good * place to make sure tracing engines don't introduce too much * latency under voluntary preemption. */ might_sleep(); > Also the documentation needs more whitespace, its very hard to digest in > its current form. Please make specific suggestions of exactly where you want what changes. I tend to use paragraph breaks between groups of sentences that work together interdependently to communicate a single idea, like they taught me to write English in elementary school. In a few cases, I think the kernel-doc formatting might force you to avoid extra blank lines or else you wind up with the wrong kinds of grouping in HTML output or something (it's been a while since I wrote some of the longer kernel-doc comments, and at the time I looked carefully at how the make htmldocs and make mandocs results came out to make them readable that way). Of course the purpose of comments and kernel-doc is to communicate clearly. So I am happy to amend the comments in whatever fashions make them more effective. But you will have to cite exactly what you want. Thanks, Roland From jan.kratochvil at redhat.com Mon Dec 14 00:41:22 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 14 Dec 2009 01:41:22 +0100 Subject: step-into-handler.c compilation failure on ppc64 In-Reply-To: <1942562377.1106481260034745595.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091205171920.1CD8039C4B@pipsqueak.sf.frob.com> Message-ID: <20091214004122.GA31656@host0.dyn.jankratochvil.net> On Sat, 05 Dec 2009 18:19:20 +0100, Roland McGrath wrote: > How about this? > > --- step-into-handler.c 10 Dec 2008 04:42:43 -0800 1.8 > +++ step-into-handler.c 05 Dec 2009 09:18:54 -0800 [...] > @@ -113,11 +114,11 @@ handler_alrm_get (void) > { > #if defined __powerpc64__ > /* ppc64 `handler_alrm' resolves to the function descriptor. */ > - return *(void **) handler_alrm; > + return *(void **) (uintptr_t) handler_alrm; > /* __s390x__ defines both the symbols. */ > #elif defined __s390__ && !defined __s390x__ > /* s390 bit 31 is zero here but I am not sure if it cannot be arbitrary. */ [...] On Sat, 05 Dec 2009 18:39:05 +0100, CAI Qian wrote: > Thanks. Fixed. I have to say it did not help for me (gcc-4.4.2-7.el6.ppc64). error: dereferencing type-punned pointer will break strict-aliasing rules Checked-in the union-based fix below (both tests PASS on ppc64). Regards, Jan --- erestartsys.c 27 Nov 2009 22:50:31 -0000 1.13 +++ erestartsys.c 14 Dec 2009 00:38:42 -0000 1.14 @@ -38,6 +38,7 @@ #include #include #include +#include #if defined __x86_64__ # define REGISTER_IP .rip @@ -298,8 +299,23 @@ main (int argc, char **argv) user = user_orig; user REGISTER_IP = (unsigned long) func; #ifdef __powerpc64__ - user.nip = ((const unsigned long *) func)[0]; /* entry */ - user.gpr[2] = ((const unsigned long *) func)[1]; /* TOC */ + { + /* ppc64 `func' resolves to the function descriptor. */ + union + { + void (*f) (void); + struct + { + void *entry; + void *toc; + } + *p; + } + const func_u = { func }; + + user.nip = (uintptr_t) func_u.p->entry; + user.gpr[2] = (uintptr_t) func_u.p->toc; + } #endif /* GDB amd64_linux_write_pc(): */ /* We must be careful with modifying the program counter. If we --- step-into-handler.c 8 Dec 2008 18:23:41 -0000 1.8 +++ step-into-handler.c 14 Dec 2009 00:38:42 -0000 1.9 @@ -113,7 +113,19 @@ handler_alrm_get (void) { #if defined __powerpc64__ /* ppc64 `handler_alrm' resolves to the function descriptor. */ - return *(void **) handler_alrm; + union + { + void (*f) (int signo); + struct + { + void *entry; + void *toc; + } + *p; + } + const func_u = { handler_alrm }; + + return func_u.p->entry; /* __s390x__ defines both the symbols. */ #elif defined __s390__ && !defined __s390x__ /* s390 bit 31 is zero here but I am not sure if it cannot be arbitrary. */ From news at news.bloodservers.com Mon Dec 14 01:04:06 2009 From: news at news.bloodservers.com (admin) Date: Sun, 13 Dec 2009 19:04:06 -0600 Subject: Free online game for you to enjoy! Message-ID: If you like games like Civilization you'll love this. Free to play Forever! World's Best Web Game Join a global community of millions Instant access, no installation Play anywhere via your browser Build up to 10 cities and conquer the land 220+ quests, hundreds of items & techs Regular content updates Evony is a massively multiplayer online real time strategy game (MMORTS). It is highly popular because it is a persistent world. The landscape does not change each game or each time you log in, but rather you control your fledgling kingdom and direct its affairs. Your subjects will continue building, gathering, researching and laboring even while you are away. You may complete quests, attack barbarians or rival players, form alliances, achieve rank and title and expand your kingdom. Raise your Prestige and vanquish your foes. Your destiny is in your hands. Play for FREE now! -- If you do not want to receive any more newsletters, http://news.bloodservers.com/phplist/lt.php?id=YhgMBlNWBVUATwQBH1IGBAUMVg%3D%3D To update your preferences and to unsubscribe visit http://news.bloodservers.com/phplist/lt.php?id=YhgMBlNWBVUHTwQBH1IGBAUMVg%3D%3D Forward a Message to Someone http://news.bloodservers.com/phplist/lt.php?id=YhgMBlNWBVUGTwQBH1IGBAUMVg%3D%3D -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: From jan.kratochvil at redhat.com Mon Dec 14 09:53:37 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 14 Dec 2009 10:53:37 +0100 Subject: clone bug (glibc?) (Was: clone-multi-ptrace test failure) In-Reply-To: <20091201193940.154EF1DE@magilla.sf.frob.com> References: <1131500942.661141259309140094.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1792038884.661191259309349760.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091128190402.GA19374@redhat.com> <20091130044448.9D134D6D2@magilla.sf.frob.com> <20091130170726.GA4421@redhat.com> <20091201165845.GA9251@redhat.com> <20091201193940.154EF1DE@magilla.sf.frob.com> Message-ID: <20091214095337.GA14801@host0.dyn.jankratochvil.net> On Tue, 01 Dec 2009 20:39:40 +0100, Roland McGrath wrote: > I think the best bet is to link with -Wl,-z,now and then minimize the > library code you rely on. Checked-in the fix of at least Fedora 12 x86_64 below. getppid() does not look to be needed there - PTRACE_SYSCALL does stop (WIFSTOPPED) on the entry (before WIFEXITED) to __NR_exit keeping the PASS/FAIL reproducibility. Regards, Jan --- Makefile.am 29 Nov 2009 02:23:25 -0000 1.60 +++ Makefile.am 14 Dec 2009 09:47:54 -0000 1.61 @@ -111,6 +111,8 @@ stopped_attach_transparency_LDFLAGS = -l erestartsys_trap_LDFLAGS = -lutil erestartsys_trap_debugger_LDFLAGS = -lutil erestartsys_trap_32fails_debugger_LDFLAGS = -lutil +# After clone syscall it must call no glibc code (such as _dl_runtime_resolve). +clone_multi_ptrace_LDFLAGS = -Wl,-z,now check_TESTS = $(SAFE) xcheck_TESTS = $(CRASHERS) --- clone-multi-ptrace.c 5 Dec 2008 14:41:57 -0000 1.6 +++ clone-multi-ptrace.c 14 Dec 2009 09:47:54 -0000 1.7 @@ -65,10 +65,10 @@ static char grandchild_seen[THREAD_NUM]; static int grandchild_func (void *unused) { - /* Need to have at least one syscall before exit */ - getppid (); - /* _exit() would make ALL threads to exit. We need rew syscall */ + /* _exit() would make ALL threads to exit. We need rew syscall. After the + clone syscall it must call no glibc code (such as _dl_runtime_resolve). */ syscall (__NR_exit, 22); + return 0; } From jan.kratochvil at redhat.com Mon Dec 14 11:17:51 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 14 Dec 2009 12:17:51 +0100 Subject: [PATCH v2] ptrace-tests: fix step-fork.c on powerpc for ptrace-utrace In-Reply-To: <20091201173827.GC31242@darkmag.usersys.redhat.com> References: <20091201163748.GA5635@darkmag.usersys.redhat.com> <20091201172457.GB31242@darkmag.usersys.redhat.com> <20091201173827.GC31242@darkmag.usersys.redhat.com> Message-ID: <20091214111751.GA19525@host0.dyn.jankratochvil.net> On Tue, 01 Dec 2009 18:38:27 +0100, Veaceslav Falico wrote: > Instead of using fork(), call syscall(__NR_fork) in step-fork.c > to avoid looping on powerpc arch in libc. Checked-in. (Not seen any problems with syscall and using glibc afterwards as in the clone-multi-ptrace.c case so left it as is.) Regards, Jan > Signed-off-by: Veaceslav Falico > --- > > --- a/ptrace-tests/tests/step-fork.c 2009-12-01 17:17:14.000000000 +0100 > +++ b/ptrace-tests/tests/step-fork.c 2009-12-01 18:35:15.000000000 +0100 > @@ -29,6 +29,7 @@ > #include > #include > #include > +#include > #include > > #ifndef PTRACE_SINGLESTEP > @@ -78,7 +79,12 @@ main (int argc, char **argv) > sigprocmask (SIG_BLOCK, &mask, NULL); > ptrace (PTRACE_TRACEME); > raise (SIGUSR1); > - if (fork () == 0) > + > + /* > + * Can't use fork() directly because on powerpc it loops inside libc under > + * PTRACE_SINGLESTEP. See http://marc.info/?l=linux-kernel&m=125927241130695 > + */ > + if (syscall(__NR_fork) == 0) > { > read (-1, NULL, 0); > _exit (22); From jan.kratochvil at redhat.com Mon Dec 14 11:39:34 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 14 Dec 2009 12:39:34 +0100 Subject: powerpc: step-jump-cont failure (Was: [PATCH] utrace: don't set ->ops = utrace_detached_ops lockless) In-Reply-To: <20091209181241.GA20475@redhat.com> References: <620900248.1135371260194573178.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1094630574.1135601260194783524.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091207142451.GA8505@redhat.com> <20091207144744.GA8468@host0.dyn.jankratochvil.net> <20091207152721.GA11725@redhat.com> <20091207180540.GA19125@redhat.com> <20091208095057.GC4767@in.ibm.com> <20091209173746.GA17508@redhat.com> <20091209181241.GA20475@redhat.com> Message-ID: <20091214113934.GA20689@host0.dyn.jankratochvil.net> On Wed, 09 Dec 2009 19:12:41 +0100, Oleg Nesterov wrote: > > > while the '.func_name' is the text address. > > > > tried to change the code to > > > > REGS_ACCESS (regs, nip) = (unsigned long) .raise_sigusr2 > > > > but gcc doesn't like this ;) ... > Yes, I verified the patch below fixes step-jump-cont.c on > ibm-js20-02.lab.bos.redhat.com. Checked-in a similar patch but same as used now in other testcases, sorry for not using the patch of yours. Regards, Jan --- step-jump-cont.c 8 Dec 2008 18:23:41 -0000 1.12 +++ step-jump-cont.c 14 Dec 2009 11:38:37 -0000 1.13 @@ -213,6 +213,24 @@ int main (void) REGS_ACCESS (regs, eip) = (unsigned long) raise_sigusr2; #elif defined __x86_64__ REGS_ACCESS (regs, rip) = (unsigned long) raise_sigusr2; +#elif defined __powerpc64__ + { + /* ppc64 `raise_sigusr2' resolves to the function descriptor. */ + union + { + void (*f) (void); + struct + { + void *entry; + void *toc; + } + *p; + } + const func_u = { raise_sigusr2 }; + + REGS_ACCESS (regs, nip) = (unsigned long) func_u.p->entry; + REGS_ACCESS (regs, gpr[2]) = (unsigned long) func_u.p->toc; + } #elif defined __powerpc__ REGS_ACCESS (regs, nip) = (unsigned long) raise_sigusr2; #else From jan.kratochvil at redhat.com Mon Dec 14 12:04:15 2009 From: jan.kratochvil at redhat.com (Jan Kratochvil) Date: Mon, 14 Dec 2009 13:04:15 +0100 Subject: Tests Failures on PPC64 In-Reply-To: <20091209183152.GA21076@redhat.com> References: <53210486.1213181260270122979.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <394789634.1213221260270192487.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091209183152.GA21076@redhat.com> Message-ID: <20091214120415.GA21585@host0.dyn.jankratochvil.net> On Wed, 09 Dec 2009 19:31:52 +0100, Oleg Nesterov wrote: > Hmm. it is obvioulsy racy, "static volatile unsigned started" > is not atomic and thus the main thread can hang doing > > while (started < THREADS); > > not that I think this explains the failure though. Thanks, fixed (but the problem is not reproducible for me). Regards, Jan --- ppc-dabr-race.c 8 Dec 2008 18:23:41 -0000 1.8 +++ ppc-dabr-race.c 14 Dec 2009 12:03:49 -0000 1.9 @@ -141,13 +141,14 @@ handler_fail (int signo) assert (0); } +/* STARTED requires atomic access. */ static volatile unsigned started; static void *child_thread (void *data) { pid_t tid = gettid (); - started++; + __sync_add_and_fetch (&started, 1); /* We should stay in the syscall - better race probability. */ sleep (1); @@ -178,7 +179,7 @@ static void child_func (void) assert (i == 0); } - while (started < THREADS); + while (__sync_add_and_fetch (&started, 0) < THREADS); l = ptrace (PTRACE_TRACEME, 0, NULL, NULL); assert (l == 0); From peterz at infradead.org Mon Dec 14 13:51:36 2009 From: peterz at infradead.org (Peter Zijlstra) Date: Mon, 14 Dec 2009 14:51:36 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091214002533.3052519@magilla.sf.frob.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> Message-ID: <1260798696.4165.316.camel@twins> On Sun, 2009-12-13 at 16:25 -0800, Roland McGrath wrote: > I'm sorry for the delay. I'm picking up with responding to the parts of > your review that I did not include in my first reply. I appreciate very > much the discussion you've had with Oleg about the issues that I did not > address myself. I look forward to your replies to my comments in that > first reply, which we have yet to see. Yeah, no worries, I'm not too quick these days myself.. > > Seems inconsistent on u32 vs enum utrace_resume_action. > > > > Why force enum utrace_resume_action into a u32? > > The first argument to almost all callbacks (all the ones made when the > task is alive) is called "action" and it's consistent that its low bits > contain an enum utrace_resume_action. The argument is "u32 action" in > the report_signal and report_syscall_entry callbacks, where it combines > an enum utrace_resume_action with an enum utrace_{signal,syscall}_action > (respectively). It would indeed be more consistent to use "u32 action" > throughout, but it seemed nicer not to have engine writers always > writing "utrace_resume_action(action)" for all the cases where there are > no other bits in there. C does implicit casts from enum to integer types, right? So always using u32 here would not impose any extra typing on the user, or am I missing something subtle here? > The return value is a mirror of the "u32 action" argument. In many > calls, it has only an enum utrace_resume_action in it. But in some it > combines that with another enum utrace_*_action. There I went for > consistency (and less typing) in the return type, since it doesn't make > any difference to how you have to write the code in your callback > function. The main reason I used "u32" at all instead of "unsigned int" > is just its shortness for less typing. > > I don't really mind changing these details to whatever people think is > best. The other people writing code to use the utrace API may have more > opinions than I do. I guess it could even be OK to make the return > value and "action" argument always a plain enum utrace_resume_action, > and use a second in/out "enum utrace_{signal,syscall}_action *" > parameter in those particular calls. But that does put some more > register pressure and loads/stores into this API. I don't mind the sharing of the argument, it just looked odd to have the u32/unsigned int/enum thing intermixed, since you care about typing length (as good a criteria as any) I'd just be lazy and make everything u32 ;-) > > Quite gross this.. can't we key off the > > tracehoook_report_clone_complete() and use a wakeup there? > > Yes, we intended to clean this up at some point later. But doing that > is just a distraction and complication right now so we put it off. For > this case, however, I suppose we could just punt for the initial version. > > This code exists to support the special semantics of calling > utrace_attach_task() from inside the parent's report_clone() callback. > That guarantees the parent that it wins any race with any third thread > calling utrace_attach_task(). > This guarantees it will be first attacher > in the callback order, but the general subject of callback order is > already something we think we will want to revisit in the future after > we have more experience with lots of different engines trying to work > together. > It's most meaningful when using the UTRACE_ATTACH_EXCLUSIVE > flag -- then you can use UTRACE_ATTACH_EXCLUSIVE|UTRACE_ATTACH_MATCH_OPS > to synchronize with other threads trying to attach the same kind of > engine to a task, and give special priority in that to the engine that > attaches in report_clone() from tracing the parent. I broke the text so it reads easier for me, it might be me, it might not be proper English -- I'm not a native speaker -- but this is an example of what you asked for below. The thing is, your sentences are rather long, with lots of sub-parts and similar. I find I need a break after digesting a few such things. As to the content, can't you accomplish the same thing by processing such exclusive parent registration before exposing the child in the pid-hash? Right before cgroup_fork_callback() in kernel/fork.c:copy_process() seems like the ideal site. > Really I came up with this special semantics originally just with ptrace > in mind. ptrace is an engine that wants to exclude other tracer threads > attaching asynchronously with the same kind of engine, and that wants to > give special priority on a child to the parent's tracer (to implement > PTRACE_O_TRACECLONE et al). However, Oleg's current ptrace code still > relies on the old hard-coded locking kludges to exclude the separate > attachers and to magically privilege the auto-attach from the parent's > tracer. So we are not relying on this special semantics yet. > > We could just punt utrace_attach_delay() and remove the associated > documentation about the special rights of report_clone() calling > utrace_attach_task(). If we decide it helps clean things up later when > we finish more cleanup of the ptrace world, then we can add the fancy > semantics back in later. Best would be to fix up the utrace-ptrace implementation and get rid of those other kludges I think, not sure.. its all a bit involved and I'm not at all sure I'm fully aware of all the ptrace bits. > > Does this really need the inline? > > It has one caller and that call is unconditional. Won't gcc inline it anyway in that case? > > Asymmetric locking like this is really better not done, and looking at > > the callsites its really no bother to clean that up, arguably even makes > > them saner. > > By "assymetric" you mean that utrace_reap releases a lock (as the > __releases annotation indicates). As should be obvious from the code, the > unlock is done before the loop that does ->report_reap callbacks and > utrace_engine_put() (which can make ->release callbacks). Surely you are > not suggesting that all these callbacks should be made with a spin lock > held, because that would obviously be quite insane. Because there can be many engines attached? > I tried splitting utrace_reap() into two functions, so the callers make the > first call, then unlock, and then make the second call. Both callers do > this identically, so this just replaces > utrace_reap(task, utrace); > with: > prepare_utrace_reap(task, utrace); > spin_unlock(&utrace->lock); > finish_utrace_reap(task, utrace); > in two places. That change adds 13 source lines and 71 bytes of compiled > text (x86-64). Is that what you had in mind? Or in case of utrace_reap() maybe push the spin_lock() into it? > > > + /* > > > + * If ptrace is among the reasons for this stop, do its > > > + * notification now. This could not just be done in > > > + * ptrace's own event report callbacks because it has to > > > + * be done after we are in TASK_TRACED. This makes the > > > + * synchronization with ptrace_do_wait() work right. > > > + */ > > > + ptrace_notify_stop(task); > > > > Well, this is a bit disappointing isn't it? So we cannot implement > > ptrace on utrace without special purpose hooks? > > It's more of an issue that ptrace is built around special-purpose hooks > in wait. We do intend to clean this up later. But it is as much about > cleaning up the remaining deep insanity of the old ptrace implementation > as about giving utrace better facilities for this wrinkle of > synchronization. > I don't doubt that the utrace API will get some > changes and improvements along the way as we move incrementally to all > of the ptrace internals being done in as clean and sane fashion as the > legacy ptrace userland ABI makes possible. But Oleg has not yet gotten > to that part of the the ptrace cleanup, and the actual problem that > necessitates this kludge for ptrace is not an issue at all for many > other uses of utrace that don't have to tie into a broken old model of > things. > So being perfectly clean here is not something we should even > think we know how best to do yet, since there has been so little real > call for it. It would be counterproductive to make this perfection an > obstacle to incremental merging of the current utrace pieces that > already enable other kinds of new functionality. Well, yes and no. Also I'm in no way a gate-keeper for acceptance of this code, I just went through it and pointed out things I found 'odd' about it. The major improvement this utrace stuff brings over the old ptrace is that it fully multiplexes the task tracing bits, however if the new bit isn't powerful enough to express all of the old bits with that then that seems to take the shine of the new bits. I'm well aware that ptrace had some quirky bits in, and this might well be one of the crazier parts of it, but to the un-initiated reviewer (me) this could have done with a comment explaining exactly why this particular site is not worth properly abstracting etc.. That is, you're presenting a patch for merger and have the wish that people read it, yet half the comments on the rather brittle barrier logic were incomplete or even flat out wrong and things like this are not explained. That does not paint a convincing picture. > > If its a programming error, WARN_ON might be appropriate, no point in > > being nice about it. > > Sure, except that any WARN_ON shows up as "oops in utrace.c" and then > people think the bug is in utrace rather than in the caller. Not if the comment right above the WARN_ON() says that its a clueless caller.. but if you're really worried about it, use something like: WARN(cond, "Dumb-ass caller\n"); > > Its not entirely clear why we can check pending_attach outside of the > > utrace->lock and not be racy. > > I think it can be racy sometimes but that does not matter. > Maybe Oleg can verify my logic here. If it's right, he can > add some comments to make it more clear. > > There is only a very limited sort of "timeliness" guarantee about > getting your callbacks after utrace_attach_task()+utrace_set_events(). > If you know somehow that the task was definitely still in TASK_STOPPED > or TASK_TRACED after utrace_attach_task() returned, then your engine > gets all possible callbacks starting from when it resumes. > Otherwise, > you can use utrace_control() with UTRACE_REPORT to ask to get some > callback "pretty soon". The only callback events you are ever 100% > guaranteed about (after success return from utrace_set_events()) are for > DEATH and REAP, which have an unconditional lock-and-check before making > engine callbacks. OK, so in this case its a best effort thing, and any races are non-destructive. > In the stopped cases, there are lots of locks and barriers and things > after resuming. (Oleg?) > > In the "pretty soon" case, that means set_notify_resume: > if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) > kick_process(task); > i.e. IPI after test_and_set. The test_and_set implies an smp_mb(). > So it should be the case that the set of utrace->pending_attach was seen > before the set of TIF_NOTIFY_RESUME. Not exactly sure where the matching rmb() would come from in start_report() and friends -- task_utrace_struct() ? > In a race where the tracee just > saw utrace->pending_attach==0, then it has TIF_NOTIFY_RESUME set still > (or again), and so will go around again before getting back to user mode. > > > > + if (!engine_wants_stop(engine)) { > > > + spin_lock(&utrace->lock); > > > + /* > > > + * If utrace_control() came in and detached us > > > + * before we got the lock, we must not stop now. > > > + */ > > > + if (unlikely(engine->ops == &utrace_detached_ops)) > > > + report->detaches = true; > > > + else > > > + mark_engine_wants_stop(task, engine); > > > + spin_unlock(&utrace->lock); > > > + } > > > +} > > > > I'm pretty sure that inline isn't really needed. > > You mean mark_engine_wants_stop? You prefer repeating the two lines of > code to using a helper to encapsulate the magic? Really? No, +static inline void finish_callback_report(struct task_struct *task, That function looks rather large for an inline, and if its a single callsite gcc will inline it anyway due to that static thing. > > Simply cond_resched() is sufficient, but that comment sucks, as it > > doesn't mention _why_ it is a good place. > > > > It seems to turn out that finish_callback() is always the last thing we > > do in the engine iterations in REPORT_CALLBACKS() and > > utrace_get_signal(). > > Oh, sorry. I didn't realize it wasn't obvious that finish_callback() is > called after every engine callback, given its name. I've changed it to: Yeah, the name does seem to suggest some 'finish' of sorts, but it wasn't clear until I traced its callchain back a little that it was the tail of the for-each-engine loop. > /* > * We've just done an engine callback. These are allowed to sleep, > * though all well-behaved ones restrict that to blocking kalloc() > * or quickly-acquired mutex_lock() and the like. This is a good > * place to make sure tracing engines don't introduce too much > * latency under voluntary preemption. > */ > might_sleep(); Right, might_sleep() captures more cases. > > Also the documentation needs more whitespace, its very hard to digest in > > its current form. > > Please make specific suggestions of exactly where you want what changes. I > tend to use paragraph breaks between groups of sentences that work together > interdependently to communicate a single idea, like they taught me to write > English in elementary school. > In a few cases, I think the kernel-doc > formatting might force you to avoid extra blank lines or else you wind up > with the wrong kinds of grouping in HTML output or something (it's been a > while since I wrote some of the longer kernel-doc comments, and at the time > I looked carefully at how the make htmldocs and make mandocs results came > out to make them readable that way). > > Of course the purpose of comments and kernel-doc is to communicate clearly. > So I am happy to amend the comments in whatever fashions make them more > effective. But you will have to cite exactly what you want. Right, so I've broken up some of the longer paragraphs, including the penultimate quoted one, in order to illustrate what I meant. Like said before, it might just be me. From email at mercadointerativo.net Mon Dec 14 16:35:11 2009 From: email at mercadointerativo.net (www.coweb.com.br) Date: Mon, 14 Dec 2009 14:35:11 -0200 Subject: Desenvolva agora mesmo o seu site! Message-ID: <316064235056945618276@brasweb> An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Dec 14 17:03:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Dec 2009 18:03:27 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091214002533.3052519@magilla.sf.frob.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> Message-ID: <20091214170327.GA7666@redhat.com> On 12/13, Roland McGrath wrote: > > > Its not entirely clear why we can check pending_attach outside of the > > utrace->lock and not be racy. > > I think it can be racy sometimes but that does not matter. > Maybe Oleg can verify my logic here. If it's right, he can > add some comments to make it more clear. > > There is only a very limited sort of "timeliness" guarantee about > getting your callbacks after utrace_attach_task()+utrace_set_events(). > If you know somehow that the task was definitely still in TASK_STOPPED > or TASK_TRACED after utrace_attach_task() returned, then your engine > gets all possible callbacks starting from when it resumes. Otherwise, > you can use utrace_control() with UTRACE_REPORT to ask to get some > callback "pretty soon". The only callback events you are ever 100% > guaranteed about (after success return from utrace_set_events()) are for > DEATH and REAP, which have an unconditional lock-and-check before making > engine callbacks. Yes, I think this is correct. It is fine to miss ->pending_attach == T, and in any case the new attacher can come right after the check, even if it was checked under utrace->lock. It is important that the tracee can't miss, say, UTRACE_REPORT request (as you already explained), and every time the tracee clears ->resume it calls splice_attaching(). > In the stopped cases, there are lots of locks and barriers and things > after resuming. (Oleg?) Every time the tracee resumes after TASK_TRACED it uses utrace->lock to synchronize with utrace_control/etc, it must see any changes. Oleg. From pedidos at consultafacil.pt Mon Dec 14 16:51:02 2009 From: pedidos at consultafacil.pt (=?windows-1252?Q?Consulta_Facil_Pe=E7as_Auto_?=) Date: Mon, 14 Dec 2009 16:51:02 +0000 Subject: =?windows-1252?q?Com=E9rcio_e_Distribui=E7=E3o_de_Pe=E7as_Auto_U?= =?windows-1252?q?sadas?= Message-ID: <2776622701443074926653@pc2> An HTML attachment was scrubbed... URL: From arf-pecas-usadas at jpsf.pt Mon Dec 14 17:44:01 2009 From: arf-pecas-usadas at jpsf.pt (ARF Pecas Usadas) Date: Mon, 14 Dec 2009 17:44:01 +0000 Subject: Motores, Caixas de velocidades. Componentes Usados ..... Message-ID: <2776622648161094232591@pc2> An HTML attachment was scrubbed... URL: From oleg at redhat.com Mon Dec 14 17:41:27 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Dec 2009 18:41:27 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <1260798696.4165.316.camel@twins> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <1260798696.4165.316.camel@twins> Message-ID: <20091214174127.GA9315@redhat.com> On 12/14, Peter Zijlstra wrote: > > > > Quite gross this.. can't we key off the > > > tracehoook_report_clone_complete() and use a wakeup there? > > > > Yes, we intended to clean this up at some point later. But doing that > > is just a distraction and complication right now so we put it off. For > > this case, however, I suppose we could just punt for the initial version. > > > > This code exists to support the special semantics of calling > > utrace_attach_task() from inside the parent's report_clone() callback. > > That guarantees the parent that it wins any race with any third thread > > calling utrace_attach_task(). > > > This guarantees it will be first attacher > > in the callback order, but the general subject of callback order is > > already something we think we will want to revisit in the future after > > we have more experience with lots of different engines trying to work > > together. > > > It's most meaningful when using the UTRACE_ATTACH_EXCLUSIVE > > flag -- then you can use UTRACE_ATTACH_EXCLUSIVE|UTRACE_ATTACH_MATCH_OPS > > to synchronize with other threads trying to attach the same kind of > > engine to a task, and give special priority in that to the engine that > > attaches in report_clone() from tracing the parent. > > As to the content, can't you accomplish the same thing by processing > such exclusive parent registration before exposing the child in the > pid-hash? Right before cgroup_fork_callback() in > kernel/fork.c:copy_process() seems like the ideal site. I thought about this too, but there are some complications. Just for example, what if copy_process() fails after we already reported the new child was attached. And, the new child is not properly initialized yet, it doesn't even have the valid pid/real_parent/etc. Just imagine a callback wants to record task_pid_vnr(). Or it decides to send a fatal signal (even private) to the new tracee. > Best would be to fix up the utrace-ptrace implementation and get rid of > those other kludges I think, not sure.. its all a bit involved and I'm > not at all sure I'm fully aware of all the ptrace bits. It is not that utrace-ptrace is buggy. We try to preserve the current semantics. Yes, we can move this kludge to ptrace layer, but I am not sure about other UTRACE_ATTACH_EXCLUSIVE engines. If we move this to ptrace, then we can probably mark the new child as "ptrace_attach() should fail, because we are going to auto-attach". But in this case we need multiple hooks in do_fork() path again, like the old ptrace does, while utrace needs only one. > The major improvement this utrace stuff brings over the old ptrace is > that it fully multiplexes the task tracing bits, however if the new bit > isn't powerful enough to express all of the old bits with that then that > seems to take the shine of the new bits. Note that it would be easy to add another callback, and hide this special case. But we should think twice before doing this. > I'm well aware that ptrace had some quirky bits in, and this might well > be one of the crazier parts of it, but to the un-initiated reviewer (me) > this could have done with a comment explaining exactly why this > particular site is not worth properly abstracting etc.. Well, agreed. > > In the "pretty soon" case, that means set_notify_resume: > > if (!test_and_set_tsk_thread_flag(task, TIF_NOTIFY_RESUME)) > > kick_process(task); > > i.e. IPI after test_and_set. The test_and_set implies an smp_mb(). > > So it should be the case that the set of utrace->pending_attach was seen > > before the set of TIF_NOTIFY_RESUME. > > Not exactly sure where the matching rmb() would come from in > start_report() and friends -- task_utrace_struct() ? I am a bit confused... As Roland said, we don't have any "timing" guarantees, and we can't have. Whatever we do, the tracee can miss, say, ->report_syscall_entry() event even if it does a system call "after" utrace_set_events(UTRACE_EVENT_SYSCALL), this is fine. But it shouldn't miss TIF_NOTIFY_RESUME/signal_pending/etc. I mean, "sooner or later" it must hanlde the signal or TIF_NOTIFY_RESUME. And in this case we can't miss ->pending_attach. IOW, we must ensure that if ever clear TIF_NOTIFY_RESUME we must not miss ->pending_attach, correct? and for this case we have mb() after clear_thread_flag(). Perhaps instead we should add mb__after_clear_bit() into arch/ hooks, but this needs a lot of arch-dependent changes. And, btw, the usage of ->replacement_session_keyring looks racy, exactly because (without utracee) we done have the necessary barriers on both sides. Oleg. From oleg at redhat.com Mon Dec 14 19:31:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Dec 2009 20:31:32 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091214174127.GA9315@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <1260798696.4165.316.camel@twins> <20091214174127.GA9315@redhat.com> Message-ID: <20091214193132.GA14124@redhat.com> On 12/14, Oleg Nesterov wrote: > > IOW, we must ensure that if ever clear TIF_NOTIFY_RESUME we must not > miss ->pending_attach, correct? and for this case we have mb() after > clear_thread_flag(). Perhaps instead we should add mb__after_clear_bit() > into arch/ hooks, but this needs a lot of arch-dependent changes. Cough. And I always read this "rmb" as "mb". Even when I changed the comment to explain that we need a barrier between clear bit and read flags, I didn't notice it is in fact rmb... I guess we need the trivial fix, Roland? Oleg. From roland at redhat.com Mon Dec 14 19:42:49 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Dec 2009 11:42:49 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Oleg Nesterov's message of Monday, 14 December 2009 20:31:32 +0100 <20091214193132.GA14124@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <1260798696.4165.316.camel@twins> <20091214174127.GA9315@redhat.com> <20091214193132.GA14124@redhat.com> Message-ID: <20091214194250.15BE91DE@magilla.sf.frob.com> > On 12/14, Oleg Nesterov wrote: > > > > IOW, we must ensure that if ever clear TIF_NOTIFY_RESUME we must not > > miss ->pending_attach, correct? and for this case we have mb() after > > clear_thread_flag(). Perhaps instead we should add mb__after_clear_bit() > > into arch/ hooks, but this needs a lot of arch-dependent changes. Since it's utrace/tracehook code that relies on the barrier I think it makes sense to have it in tracehook_notify_resume() or utrace_resume(). The arch requirement is having done clear_thread_flag() beforehand, so the arch-independent code can reasonably assume whatever semantics that is guaranteed to have. > Cough. And I always read this "rmb" as "mb". Even when I changed > the comment to explain that we need a barrier between clear bit > and read flags, I didn't notice it is in fact rmb... > > I guess we need the trivial fix, Roland? You're the barrier man, send me what changes it should get. Thanks, Roland From roland at redhat.com Mon Dec 14 19:44:41 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Dec 2009 11:44:41 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Oleg Nesterov's message of Monday, 14 December 2009 18:03:27 +0100 <20091214170327.GA7666@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <20091214170327.GA7666@redhat.com> Message-ID: <20091214194441.4D6BFE24E@magilla.sf.frob.com> > Yes, I think this is correct. It is fine to miss ->pending_attach == T, > and in any case the new attacher can come right after the check, even > if it was checked under utrace->lock. Right. > It is important that the tracee can't miss, say, UTRACE_REPORT request > (as you already explained), and every time the tracee clears ->resume > it calls splice_attaching(). Right. > > In the stopped cases, there are lots of locks and barriers and things > > after resuming. (Oleg?) > > Every time the tracee resumes after TASK_TRACED it uses utrace->lock > to synchronize with utrace_control/etc, it must see any changes. And TASK_STOPPED? Please send me patches to add whatever comments would make all this clear enough to Peter when reading the code. Thanks, Roland From oleg at redhat.com Mon Dec 14 20:24:54 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 14 Dec 2009 21:24:54 +0100 Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: <20091214194441.4D6BFE24E@magilla.sf.frob.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <20091214170327.GA7666@redhat.com> <20091214194441.4D6BFE24E@magilla.sf.frob.com> Message-ID: <20091214202454.GA16124@redhat.com> On 12/14, Roland McGrath wrote: > > > > In the stopped cases, there are lots of locks and barriers and things > > > after resuming. (Oleg?) > > > > Every time the tracee resumes after TASK_TRACED it uses utrace->lock > > to synchronize with utrace_control/etc, it must see any changes. > > And TASK_STOPPED? SIGCONT can wake up the TASK_STOPPED tracee. I don't think the tracer should ever rely on TASK_STOPPED (utrace never does). If the tracer needs the "really stopped" tracee we have UTRACE_STOP, and this means TASK_TRACED. But I am not sure I understand this part of discussion... In any case the tracee should see any changes which were done before the wakeup. But TASK_STOPPED can't guarantee the tracee won't be resumed until the tracer wakes it up. Of course, TASK_TRACED can't prevent SIGKILL, but in this case we should only care about "the tracee can't resume until we drop utrace->lock" case. Oleg. From roland at redhat.com Tue Dec 15 02:59:17 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 14 Dec 2009 18:59:17 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Oleg Nesterov's message of Monday, 14 December 2009 21:24:54 +0100 <20091214202454.GA16124@redhat.com> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <20091214170327.GA7666@redhat.com> <20091214194441.4D6BFE24E@magilla.sf.frob.com> <20091214202454.GA16124@redhat.com> Message-ID: <20091215025917.B6882D8@magilla.sf.frob.com> > SIGCONT can wake up the TASK_STOPPED tracee. I don't think the tracer > should ever rely on TASK_STOPPED (utrace never does). If the tracer > needs the "really stopped" tracee we have UTRACE_STOP, and this means > TASK_TRACED. Ah, yes. utrace_control(task,,UTRACE_STOP) while task is in TASK_STOPPED means turning it into TASK_TRACED. Thanks, Roland From envoi at email-packs.com Tue Dec 15 09:34:22 2009 From: envoi at email-packs.com (Email Packs) Date: Tue, 15 Dec 2009 11:34:22 +0200 Subject: =?utf-8?q?Nouveau_=3A_250_000_Emails_Qualifies_pour_199_?= =?utf-8?b?4oKsIEhU?= Message-ID: An HTML attachment was scrubbed... URL: From info at campaigns.canal-marketing.com Wed Dec 16 09:40:06 2009 From: info at campaigns.canal-marketing.com (Xerox) Date: Wed, 16 Dec 2009 10:40:06 +0100 Subject: =?iso-8859-1?q?Une_nouvelle_solution_pour_r=E9duire_vos_co=FBts_?= =?iso-8859-1?q?d=27impression?= Message-ID: An HTML attachment was scrubbed... URL: From roland at redhat.com Wed Dec 16 11:18:24 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 16 Dec 2009 03:18:24 -0800 (PST) Subject: [RFC,PATCH 14/14] utrace core In-Reply-To: Peter Zijlstra's message of Monday, 14 December 2009 14:51:36 +0100 <1260798696.4165.316.camel@twins> References: <20091124200220.GA5828@redhat.com> <1259697242.1697.1075.camel@laptop> <20091214002533.3052519@magilla.sf.frob.com> <1260798696.4165.316.camel@twins> Message-ID: <20091216111824.0D6779E5@magilla.sf.frob.com> > C does implicit casts from enum to integer types, right? So always using > u32 here would not impose any extra typing on the user, or am I missing > something subtle here? No, that's right. I had just been thinking of the documentation / convenience issue. I figured with u32 people might tend to think they always had to write utrace_resume_action(action) like you do in report_signal, or would want it to get the enum so e.g. you can write a switch and have gcc give those warnings about covering all the enum cases. But you have convinced me that the consistency of using u32 everywhere is the what's really easiest to understand. > I don't mind the sharing of the argument, it just looked odd to have the > u32/unsigned int/enum thing intermixed, since you care about typing > length (as good a criteria as any) I'd just be lazy and make everything > u32 ;-) That's good enough for me. > As to the content, can't you accomplish the same thing by processing > such exclusive parent registration before exposing the child in the > pid-hash? Right before cgroup_fork_callback() in > kernel/fork.c:copy_process() seems like the ideal site. As Oleg mentioned, that would add some complications. The task is not really fully set up at that point and the clone might actually still fail. The final stages where the clone can fail are necessarily inside some important locks held while making the new task visible for lookup. One of the key features of the utrace API is that callbacks are called in uncomplicated contexts so you just don't have to worry about a lot of strangeness and arcane constraints. That means making such a callback while holding any spin lock or suchlike is really out of the question. So, either we have to make a callback where you suggest, before the task really exists, or where we do now, after the task is visible to others. An unfinished task that doesn't yet have all its pointers in place, and still might be freed before it could ever run, would add a whole lot of hair to what the utrace API semantics would be. If you get the callback that early, then you can attach to it that early, and then you expect some callbacks about it actually failing ever to exist. And meanwhile, you might have to know what you can and can't try to do with a task that is not really set up yet. It just seems like a really bad idea. Hence, we are stuck with the post-clone callback being really post-clone so that it's possible for other things in the system to see the new task and try to utrace_attach it. But, as I said, we are not actually relying on having a way to rule that out at the utrace level today. So I think we can just take out this hack and reconsider it later when we have an active need. > Best would be to fix up the utrace-ptrace implementation and get rid of > those other kludges I think, not sure.. its all a bit involved and I'm > not at all sure I'm fully aware of all the ptrace bits. We haven't figured out all the best ways to clean up ptrace the rest of the way yet. We'd like to keep improving that incrementally after the basics of utrace are in the tree. > > [...] Surely you are > > not suggesting that all these callbacks should be made with a spin lock > > held, because that would obviously be quite insane. > > Because there can be many engines attached? Because it's a callback API. A callback is allowed to use mutex_lock(), is expected to be preemptible, etc. Having an interface where you let somebody's function unwittingly run with spin locks held, preemption disabled, and so forth, is just obviously a terrible interface. > Or in case of utrace_reap() maybe push the spin_lock() into it? I did a restructuring to make that possible. IMHO it makes the control flow a bit less clear. But it came out a bit smaller in the text, so I'll go with it. > I'm well aware that ptrace had some quirky bits in, and this might well > be one of the crazier parts of it, but to the un-initiated reviewer (me) > this could have done with a comment explaining exactly why this > particular site is not worth properly abstracting etc.. We'll add more comments there. > Not if the comment right above the WARN_ON() says that its a clueless > caller.. but if you're really worried about it, use something like: > > WARN(cond, "Dumb-ass caller\n"); Oh, that's much better. I've made all the WARN_ON's give some text. Thanks, Roland From ordaining at ionizer.nl Wed Dec 16 12:28:32 2009 From: ordaining at ionizer.nl (Barrott) Date: Wed, 16 Dec 2009 13:28:32 +0100 Subject: (no subject) Message-ID: <4B28D208.5020404@ionizer.nl> -------------- next part -------------- A non-text attachment was scrubbed... Name: peepshow.jpg Type: image/jpeg Size: 17517 bytes Desc: not available URL: From roland at redhat.com Wed Dec 16 21:34:23 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 16 Dec 2009 13:34:23 -0800 (PST) Subject: post-2.6.32 utrace Message-ID: <20091216213423.6B6D8D8@magilla.sf.frob.com> Up until now, the utrace git trees were relative to 2.6.32. Now Linus has merged several of Oleg's small patches that were prerequisites for utrace, those populating my "tracehook" branch. So, I've now merged the latest tree from Linus in, and split out 2.6.32/* branches. We still have a tracehook branch. These patches (which might be in -mm?) are on the tracehook branch and still not merged (listed last to first): a8f782e export __ptrace_detach() and do_notify_parent_cldstop() c3473e1 ptrace_signal: check PT_PTRACED before reporting a signal b396f5e tracehooks: check PT_PTRACED before reporting the single-step 45667dd tracehooks: kill some PT_PTRACED checks These ones have been merged upstream now, but remain on 2.6.32/tracehook (the basis for the "backport branches" 2.6.32/utrace*): e8a2f23 ptrace: cleanup ptrace_init_task()->ptrace_link() path a88b467 ptrace: x86: change syscall_trace_leave() to rely on tracehook when stepping e01acf4 ptrace: x86: implement user_single_step_siginfo() 462a57b ptrace: change tracehook_report_syscall_exit() to handle stepping 172590d ptrace: powerpc: implement user_single_step_siginfo() d63b43d ptrace: introduce user_single_step_siginfo() helper d4ef551 (upstream) signals: check ->group_stop_count after tracehook_get_signal() There is so far no drift between the trunk utrace branch and the 2.6.32/utrace branch. If we have more tweaks to utrace as part of the next round of upstream submission, we will try to keep the 2.6.32/utrace backport branch identically updated pretty quickly. Note this is after various changes discussed in the recent LKML review thread (CC'd here) that I trust you have all been reading. This includes some callback API changes that are trivial but will break all your utrace engine code today. Thanks, Roland From roland at redhat.com Thu Dec 17 00:35:07 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 16 Dec 2009 16:35:07 -0800 (PST) Subject: new Fedora 13 utrace kernel Message-ID: <20091217003507.CCAEA968@magilla.sf.frob.com> In http://kojipkgs.fedoraproject.org/packages/kernel/2.6.32.1/10.fc13/ right now you can find a Fedora kernel with the latest utrace up to the minute. Coming soon to a rawhide near you (should be tomorrow). This is a 2.6.32.1-based kernel with exactly the 2.6.32/* utrace patches as you see them today in git and on people.redhat.com, including Oleg's utrace-based ptrace. If we have any more tweaks to the utrace code soon, we will build an updated rawhide kernel shortly thereafter. Thanks, Roland From loja_online at netcabo.pt Thu Dec 17 12:43:45 2009 From: loja_online at netcabo.pt (=?iso-8859-1?Q?Abacate=20Soap=20Store?=) Date: Thu, 17 Dec 2009 07:43:45 -0500 Subject: Franchising Message-ID: <20091217071507.BA3D9981.426B078A@192.168.0.15> MAIL ERROR -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: image/jpeg Size: 115652 bytes Desc: not available URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: not available Type: image/jpeg Size: 42760 bytes Desc: not available URL: From voidcreations at divulgacaodigital.com Thu Dec 17 15:53:48 2009 From: voidcreations at divulgacaodigital.com (VOID CREATIONS) Date: Thu, 17 Dec 2009 15:53:48 +0000 Subject: Trash Sessions - Sexta 18 Dezembro @ Bar O Seculo Message-ID: Se n?o visualizares esta p?gina correctamente, clica aqui Adiciona-nos ? tua safe-list, para garantir que recebes sempre a info dos nossos eventos. ** ** **Apresenta:** Aten??o, aten??o?aviso ? popula??o: as Trash Sessions est?o de volta!!! Depois de uma sess?o inaugural de arromba - que envolveu bombas, tsunamis, playgirls, invasores extraterrestres e muito mais - recicl?mo-nos e trazemos a Trash Sessions #2 de volta ao S?culo j? na pr?xima sexta-feira 18 de Dezembro. Nesta segunda edi??o, teremos a exibi??o do filme de culto ?The Toxic Avenger?, o extraordin?rio ?one man show? de Peltzer , que parte do ?dio da m?quina para criar o amor da m?quina e, a terminar, o dj set dos irreverentes Blare!!! , cujas sonoridades electr?nicas ir?o levar os ?nimos ao rubro na pista de dan?a e p?r toda a gente a pedir por mais. Por volta das 21h30, abrimos a tampa do contentor com a exibi??o do filme The Toxic Avenger , um dos mais conhecidos da produtora trash Troma Entertainment. A obra ficou conhecida pela ultra-explora??o da est?tica trash, repisando clichets dos mais variados tipos ? sempre com um toque de com?dia ? mas ao qual se acrescenta uma curiosa vertente s?ria, que aborda o pior da cultura norte-americana. ?Fruto da interac??o homem-m?quina?, Peltzer viaja pelo sistema bin?rio em procura do beat perfeito, fazendo incurs?es extensivas ao electro pop em can??es mel?dicas, bem estruturadas e sempre acompanhadas de uma imag?tica pr?pria. Um dos Talentos Fnac 2009 ? e j? com uns aninhos de estrada - este robot muito humano confessa que ?odeia m?quinas?, j? que o tornam ?pregui?oso, ansioso, confuso e euf?rico?. Por?m, utiliza-as, admira-as e explora perif?ricos, criando atmosferas repletas de biologia mec?nica que aquecem o cora??o ao mais frio dos robots. O dj set de Blare!!! , composto por Bernardo Drummundo e Miguel Azevedo, come?ou inicialmente pelos remixes de nomes consagrados das pistas de dan?a como Miss Kittin, Basement Jaxx, Spektrum e outras varia??es como Nine Inch Nails ou Gorilaz. Por?m, embora o seu leque de influ?ncias seja vasto (dos 70?s. 80?s, jazz, m?sica cl?ssica, etc) ? na electr?nica que se encontram e que p?em toda a gente a dan?ar. Juntos, passam som para passar vibra??es positivas, energia e levar o p?blico aos limites da euforia! Os visuais estar?o a cargo da VJ Psyberdoll, que desde 2005 encontrou nos audiovisuais a sua melhor forma de express?o. Desde ent?o, tem explorado as potencialidades de fus?o entre o org?nico e o tecnol?gico. Toda a gente est? convidada e a festa est? pront?ssima! Vamos contar com o assobiador do Chiado e muitas mais personagens obscuras. Do you think you got what it takes...? Aparece!! A entrada ? livre com flyer! Local: O S?culo ? Centro Cultural Hora: 21h30 Entrada: Livre com apresenta??o de flyer / sem flyer 3? Morada: Rua do S?culo n? 80, 1200-436, Bairro Alto, Lisboa Mapa: ** ** Contactos: Void Creations E-mail: info at voidcreations.org @ - ? favor divulgar - ** ** Para RE-ENVIAR / To FORWARD - http://www.divulgacaodigital.com/void-creations/?p=forward&uid=8796d6f78d5efbb8958965a0e70ab9c8&mid=21 Para REMOVER / To REMOVE - http://www.divulgacaodigital.com/void-creations/?p=unsubscribe&uid=8796d6f78d5efbb8958965a0e70ab9c8 Para MODIFICAR / To MODIFY - http://www.divulgacaodigital.com/void-creations/?p=preferences&uid=8796d6f78d5efbb8958965a0e70ab9c8 -- Powered by PHPlist, www.phplist.com -- -------------- next part -------------- An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: powerphplist.png Type: image/png Size: 2408 bytes Desc: not available URL: From oleg at redhat.com Thu Dec 17 23:04:11 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 00:04:11 +0100 Subject: [PATCH 1/2] utrace: s/rmb/mb/ in tracehook_notify_resume() Message-ID: <20091217230411.GA26170@redhat.com> It was always supposed to be mb(), not rmb(). Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) --- UTRACE_PTRACE/include/linux/tracehook.h~1_NOTIFY_RESUME_MB 2009-12-17 17:00:31.000000000 +0100 +++ UTRACE_PTRACE/include/linux/tracehook.h 2009-12-17 23:53:51.000000000 +0100 @@ -670,12 +670,12 @@ static inline void tracehook_notify_resu { struct task_struct *task = current; /* - * If we race with attach which sets nonzero ->utrace_flags, - * make sure we do not read ->utrace_flags before the caller - * clears TIF_NOTIFY_RESUME. This pairs with the implicit mb() - * before setting TIF_NOTIFY_RESUME in set_notify_resume(). + * Prevent the following store/load from getting ahead of the + * caller which clears TIF_NOTIFY_RESUME. This pairs with the + * implicit mb() before setting TIF_NOTIFY_RESUME in + * set_notify_resume(). */ - smp_rmb(); + smp_mb(); if (task_utrace_flags(task)) utrace_resume(task, regs); } From oleg at redhat.com Thu Dec 17 23:04:13 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 00:04:13 +0100 Subject: [PATCH 2/2] utrace: move CONFIG_UTRACE after AUDITSYSCALL in init/Kconfig Message-ID: <20091217230413.GA26178@redhat.com> Somehow I placed CONFIG_UTRACE between AUDIT and AUDITSYSCALL, move it down after AUDITSYSCALL. Signed-off-by: Oleg Nesterov --- init/Kconfig | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) --- UTRACE_PTRACE/init/Kconfig~2_CONFIG_UTRACE_AUDIT 2009-12-17 17:00:31.000000000 +0100 +++ UTRACE_PTRACE/init/Kconfig 2009-12-17 23:59:11.000000000 +0100 @@ -295,15 +295,6 @@ config AUDIT logging of avc messages output). Does not do system-call auditing without CONFIG_AUDITSYSCALL. -config UTRACE - bool "Infrastructure for tracing and debugging user processes" - depends on EXPERIMENTAL - depends on HAVE_ARCH_TRACEHOOK - help - Enable the utrace process tracing interface. This is an internal - kernel interface exported to kernel modules, to track events in - user threads, extract and change user thread state. - config AUDITSYSCALL bool "Enable system-call auditing support" depends on AUDIT && (X86 || PPC || S390 || IA64 || UML || SPARC64 || SUPERH) @@ -319,6 +310,15 @@ config AUDIT_TREE depends on AUDITSYSCALL select INOTIFY +config UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + menu "RCU Subsystem" choice From mldireto at tudoemoferta.com.br Thu Dec 17 17:35:03 2009 From: mldireto at tudoemoferta.com.br (TudoemOferta.com) Date: Thu, 17 Dec 2009 15:35:03 -0200 Subject: Desejamos a voce um Feliz Natal e Boas Festas Message-ID: An HTML attachment was scrubbed... URL: From oleg at redhat.com Fri Dec 18 00:56:50 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 01:56:50 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f Message-ID: <20091218005650.GA20667@redhat.com> Hi. do_debug() is obviously wrong wrt PTRACE_SINGLESTEP/TIF_SINGLESTEP, no? Afaics this was broken by hw-breakpoints: modifying generic debug exception to use thread-specific debug registers commit 08d68323d1f0c34452e614263b212ca556dae47f To verify, the "patch" below fixes the stepping for me, not sure what is the proper fix... Oleg. --- arch/x86/kernel/traps.c~ 2009-12-18 00:20:49.000000000 +0100 +++ arch/x86/kernel/traps.c 2009-12-18 01:44:05.000000000 +0100 @@ -575,7 +575,7 @@ dotraplinkage void __kprobes do_debug(st regs->flags &= ~X86_EFLAGS_TF; } si_code = get_si_code(tsk->thread.debugreg6); - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) +// if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) send_sigtrap(tsk, regs, error_code, si_code); preempt_conditional_cli(regs); From oleg at redhat.com Fri Dec 18 01:11:16 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:16 +0100 Subject: [PATCH 0/7] utrace/ptrace Message-ID: <20091218011116.GA29534@redhat.com> Hello. This is the new iteration of Roland's utrace patch, this time with "rewrite-ptrace-via-utrace" + cleanups in utrace core. This version tries to address some of Peter's comments. Oleg. From oleg at redhat.com Fri Dec 18 01:11:20 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:20 +0100 Subject: [PATCH 1/7] tracehooks: kill some PT_PTRACED checks Message-ID: <20091218011120.GA29538@redhat.com> No functional changes, preparation for utrace-ptrace. task_ptrace() != 0 if and only if PT_PTRACED bit is set, kill some PT_PTRACED checks in tracehook.h to ensure the result is the same with or without utrace which doesn't set PT_PTRACED. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- V1/include/linux/tracehook.h~1_TRACEHOOK_KILL_PTRACED_CHECKS 2009-12-18 00:20:50.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-12-18 00:38:09.000000000 +0100 @@ -156,7 +156,7 @@ static inline int tracehook_unsafe_exec( { int unsafe = 0; int ptrace = task_ptrace(task); - if (ptrace & PT_PTRACED) { + if (ptrace) { if (ptrace & PT_PTRACE_CAP) unsafe |= LSM_UNSAFE_PTRACE_CAP; else @@ -178,7 +178,7 @@ static inline int tracehook_unsafe_exec( */ static inline struct task_struct *tracehook_tracer_task(struct task_struct *tsk) { - if (task_ptrace(tsk) & PT_PTRACED) + if (task_ptrace(tsk)) return rcu_dereference(tsk->parent); return NULL; } @@ -492,7 +492,7 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { - return notify ?: (current->ptrace & PT_PTRACED) ? why : 0; + return notify ?: task_ptrace(current) ? why : 0; } /** From oleg at redhat.com Fri Dec 18 01:11:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:24 +0100 Subject: [PATCH 2/7] tracehooks: check PT_PTRACED before reporting the single-step Message-ID: <20091218011124.GA29545@redhat.com> No functional changes, preparation for utrace-ptrace. tracehook_report_syscall_exit() and tracehook_signal_handler() assume that only ptrace can set TIF_SINGLESTEP. Currently this is true but we are going to change this, the stepping logic will be moved into utrace layer. Change this code to check PT_PTRACED, ptrace-utrace doesn't set it. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/tracehook.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) --- V1/include/linux/tracehook.h~2_SIGNAL_HANDLER_CK_PTRACE 2009-12-18 00:38:09.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-12-18 00:45:42.000000000 +0100 @@ -134,7 +134,7 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { - if (step) { + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); force_sig_info(SIGTRAP, &info, current); @@ -386,7 +386,7 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { - if (stepping) + if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } From oleg at redhat.com Fri Dec 18 01:11:28 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:28 +0100 Subject: [PATCH 3/7] ptrace_signal: check PT_PTRACED before reporting a signal Message-ID: <20091218011128.GA29552@redhat.com> No functional changes, preparation for utrace-ptrace. Change ptrace_signal() to check PT_PTRACED instead of task_ptrace() != 0. Currently this is the same, PT_PTRACED must be always set if the task is ptraced. This change is needed to make sure ptrace_signal() does nothing if ptrace is implemented on top of utrace, eventually this code will be removed completely. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- kernel/signal.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) --- V1/kernel/signal.c~3_PTRACE_SIGNAL_CK_PTRACED 2009-12-18 00:20:50.000000000 +0100 +++ V1/kernel/signal.c 2009-12-18 00:48:35.000000000 +0100 @@ -1764,7 +1764,7 @@ static int do_signal_stop(int signr) static int ptrace_signal(int signr, siginfo_t *info, struct pt_regs *regs, void *cookie) { - if (!task_ptrace(current)) + if (!(task_ptrace(current) & PT_PTRACED)) return signr; ptrace_signal_deliver(regs, cookie); From oleg at redhat.com Fri Dec 18 01:11:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:32 +0100 Subject: [PATCH 4/7] export __ptrace_detach() and do_notify_parent_cldstop() Message-ID: <20091218011132.GA29555@redhat.com> Export __ptrace_detach() and do_notify_parent_cldstop() for ptrace-utrace. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 1 + include/linux/sched.h | 1 + kernel/ptrace.c | 2 +- kernel/signal.c | 2 +- 4 files changed, 4 insertions(+), 2 deletions(-) --- V1/include/linux/ptrace.h~4_EXPORT_2_HELPERS 2009-12-18 00:20:50.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-12-18 00:53:58.000000000 +0100 @@ -85,6 +85,7 @@ extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); extern int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len); extern int ptrace_attach(struct task_struct *tsk); +extern bool __ptrace_detach(struct task_struct *tracer, struct task_struct *tracee); extern int ptrace_detach(struct task_struct *, unsigned int); extern void ptrace_disable(struct task_struct *); extern int ptrace_check_attach(struct task_struct *task, int kill); --- V1/include/linux/sched.h~4_EXPORT_2_HELPERS 2009-12-18 00:20:50.000000000 +0100 +++ V1/include/linux/sched.h 2009-12-18 00:53:58.000000000 +0100 @@ -2081,6 +2081,7 @@ extern int kill_pgrp(struct pid *pid, in extern int kill_pid(struct pid *pid, int sig, int priv); extern int kill_proc_info(int, struct siginfo *, pid_t); extern int do_notify_parent(struct task_struct *, int); +extern void do_notify_parent_cldstop(struct task_struct *, int); extern void __wake_up_parent(struct task_struct *p, struct task_struct *parent); extern void force_sig(int, struct task_struct *); extern int send_sig(int, struct task_struct *, int); --- V1/kernel/ptrace.c~4_EXPORT_2_HELPERS 2009-09-24 21:38:54.000000000 +0200 +++ V1/kernel/ptrace.c 2009-12-18 00:53:58.000000000 +0100 @@ -271,7 +271,7 @@ static int ignoring_children(struct sigh * reap it now, in that case we must also wake up sub-threads sleeping in * do_wait(). */ -static bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) { __ptrace_unlink(p); --- V1/kernel/signal.c~4_EXPORT_2_HELPERS 2009-12-18 00:48:35.000000000 +0100 +++ V1/kernel/signal.c 2009-12-18 00:53:58.000000000 +0100 @@ -1494,7 +1494,7 @@ int do_notify_parent(struct task_struct return ret; } -static void do_notify_parent_cldstop(struct task_struct *tsk, int why) +void do_notify_parent_cldstop(struct task_struct *tsk, int why) { struct siginfo info; unsigned long flags; From oleg at redhat.com Fri Dec 18 01:11:36 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:36 +0100 Subject: [PATCH 5/7] reorder the code in kernel/ptrace.c Message-ID: <20091218011136.GA29563@redhat.com> No functional changes, preparation for the next patch. Move the code which can be shared with ptrace-utrace up, before __ptrace_link(). This way ptrace-utrace needs a single #ifdef in ptrace.c. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- kernel/ptrace.c | 556 ++++++++++++++++++++++++++++---------------------------- 1 file changed, 278 insertions(+), 278 deletions(-) --- V1/kernel/ptrace.c~5_REORDER_PTRACE_C 2009-12-18 00:53:58.000000000 +0100 +++ V1/kernel/ptrace.c 2009-12-18 01:00:26.000000000 +0100 @@ -23,6 +23,284 @@ #include #include +int __ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + const struct cred *cred = current_cred(), *tcred; + + /* May we inspect the given task? + * This check is used both for attaching with ptrace + * and for allowing access to sensitive information in /proc. + * + * ptrace_attach denies several cases that /proc allows + * because setting up the necessary parent/child relationship + * or halting the specified task is impossible. + */ + int dumpable = 0; + /* Don't let security modules deny introspection */ + if (task == current) + return 0; + rcu_read_lock(); + tcred = __task_cred(task); + if ((cred->uid != tcred->euid || + cred->uid != tcred->suid || + cred->uid != tcred->uid || + cred->gid != tcred->egid || + cred->gid != tcred->sgid || + cred->gid != tcred->gid) && + !capable(CAP_SYS_PTRACE)) { + rcu_read_unlock(); + return -EPERM; + } + rcu_read_unlock(); + smp_rmb(); + if (task->mm) + dumpable = get_dumpable(task->mm); + if (!dumpable && !capable(CAP_SYS_PTRACE)) + return -EPERM; + + return security_ptrace_access_check(task, mode); +} + +bool ptrace_may_access(struct task_struct *task, unsigned int mode) +{ + int err; + task_lock(task); + err = __ptrace_may_access(task, mode); + task_unlock(task); + return !err; +} + +/* + * Called with irqs disabled, returns true if childs should reap themselves. + */ +static int ignoring_children(struct sighand_struct *sigh) +{ + int ret; + spin_lock(&sigh->siglock); + ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || + (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); + spin_unlock(&sigh->siglock); + return ret; +} + +/* + * Called with tasklist_lock held for writing. + * Unlink a traced task, and clean it up if it was a traced zombie. + * Return true if it needs to be reaped with release_task(). + * (We can't call release_task() here because we already hold tasklist_lock.) + * + * If it's a zombie, our attachedness prevented normal parent notification + * or self-reaping. Do notification now if it would have happened earlier. + * If it should reap itself, return true. + * + * If it's our own child, there is no notification to do. But if our normal + * children self-reap, then this child was prevented by ptrace and we must + * reap it now, in that case we must also wake up sub-threads sleeping in + * do_wait(). + */ +bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) +{ + __ptrace_unlink(p); + + if (p->exit_state == EXIT_ZOMBIE) { + if (!task_detached(p) && thread_group_empty(p)) { + if (!same_thread_group(p->real_parent, tracer)) + do_notify_parent(p, p->exit_signal); + else if (ignoring_children(tracer->sighand)) { + __wake_up_parent(p, tracer); + p->exit_signal = -1; + } + } + if (task_detached(p)) { + /* Mark it as in the process of being reaped. */ + p->exit_state = EXIT_DEAD; + return true; + } + } + + return false; +} + +int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + retval = access_process_vm(tsk, src, buf, this_len, 0); + if (!retval) { + if (copied) + break; + return -EIO; + } + if (copy_to_user(dst, buf, retval)) + return -EFAULT; + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) +{ + int copied = 0; + + while (len > 0) { + char buf[128]; + int this_len, retval; + + this_len = (len > sizeof(buf)) ? sizeof(buf) : len; + if (copy_from_user(buf, src, this_len)) + return -EFAULT; + retval = access_process_vm(tsk, dst, buf, this_len, 1); + if (!retval) { + if (copied) + break; + return -EIO; + } + copied += retval; + src += retval; + dst += retval; + len -= retval; + } + return copied; +} + +static struct task_struct *ptrace_get_task_struct(pid_t pid) +{ + struct task_struct *child; + + rcu_read_lock(); + child = find_task_by_vpid(pid); + if (child) + get_task_struct(child); + rcu_read_unlock(); + + if (!child) + return ERR_PTR(-ESRCH); + return child; +} + +#ifndef arch_ptrace_attach +#define arch_ptrace_attach(child) do { } while (0) +#endif + +SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + if (!ret) + arch_ptrace_attach(current); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (ret < 0) + goto out_put_task_struct; + + ret = arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} + +int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) +{ + unsigned long tmp; + int copied; + + copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); + if (copied != sizeof(tmp)) + return -EIO; + return put_user(tmp, (unsigned long __user *)data); +} + +int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) +{ + int copied; + + copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); + return (copied == sizeof(data)) ? 0 : -EIO; +} + +#if defined CONFIG_COMPAT +#include + +asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, + compat_long_t addr, compat_long_t data) +{ + struct task_struct *child; + long ret; + + /* + * This lock_kernel fixes a subtle race with suid exec + */ + lock_kernel(); + if (request == PTRACE_TRACEME) { + ret = ptrace_traceme(); + goto out; + } + + child = ptrace_get_task_struct(pid); + if (IS_ERR(child)) { + ret = PTR_ERR(child); + goto out; + } + + if (request == PTRACE_ATTACH) { + ret = ptrace_attach(child); + /* + * Some architectures need to do book-keeping after + * a ptrace attach. + */ + if (!ret) + arch_ptrace_attach(child); + goto out_put_task_struct; + } + + ret = ptrace_check_attach(child, request == PTRACE_KILL); + if (!ret) + ret = compat_arch_ptrace(child, request, addr, data); + + out_put_task_struct: + put_task_struct(child); + out: + unlock_kernel(); + return ret; +} +#endif /* CONFIG_COMPAT */ /* * ptrace a task: make the debugger its new parent and @@ -117,53 +395,6 @@ int ptrace_check_attach(struct task_stru return ret; } -int __ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - const struct cred *cred = current_cred(), *tcred; - - /* May we inspect the given task? - * This check is used both for attaching with ptrace - * and for allowing access to sensitive information in /proc. - * - * ptrace_attach denies several cases that /proc allows - * because setting up the necessary parent/child relationship - * or halting the specified task is impossible. - */ - int dumpable = 0; - /* Don't let security modules deny introspection */ - if (task == current) - return 0; - rcu_read_lock(); - tcred = __task_cred(task); - if ((cred->uid != tcred->euid || - cred->uid != tcred->suid || - cred->uid != tcred->uid || - cred->gid != tcred->egid || - cred->gid != tcred->sgid || - cred->gid != tcred->gid) && - !capable(CAP_SYS_PTRACE)) { - rcu_read_unlock(); - return -EPERM; - } - rcu_read_unlock(); - smp_rmb(); - if (task->mm) - dumpable = get_dumpable(task->mm); - if (!dumpable && !capable(CAP_SYS_PTRACE)) - return -EPERM; - - return security_ptrace_access_check(task, mode); -} - -bool ptrace_may_access(struct task_struct *task, unsigned int mode) -{ - int err; - task_lock(task); - err = __ptrace_may_access(task, mode); - task_unlock(task); - return !err; -} - int ptrace_attach(struct task_struct *task) { int retval; @@ -243,57 +474,6 @@ int ptrace_traceme(void) return ret; } -/* - * Called with irqs disabled, returns true if childs should reap themselves. - */ -static int ignoring_children(struct sighand_struct *sigh) -{ - int ret; - spin_lock(&sigh->siglock); - ret = (sigh->action[SIGCHLD-1].sa.sa_handler == SIG_IGN) || - (sigh->action[SIGCHLD-1].sa.sa_flags & SA_NOCLDWAIT); - spin_unlock(&sigh->siglock); - return ret; -} - -/* - * Called with tasklist_lock held for writing. - * Unlink a traced task, and clean it up if it was a traced zombie. - * Return true if it needs to be reaped with release_task(). - * (We can't call release_task() here because we already hold tasklist_lock.) - * - * If it's a zombie, our attachedness prevented normal parent notification - * or self-reaping. Do notification now if it would have happened earlier. - * If it should reap itself, return true. - * - * If it's our own child, there is no notification to do. But if our normal - * children self-reap, then this child was prevented by ptrace and we must - * reap it now, in that case we must also wake up sub-threads sleeping in - * do_wait(). - */ -bool __ptrace_detach(struct task_struct *tracer, struct task_struct *p) -{ - __ptrace_unlink(p); - - if (p->exit_state == EXIT_ZOMBIE) { - if (!task_detached(p) && thread_group_empty(p)) { - if (!same_thread_group(p->real_parent, tracer)) - do_notify_parent(p, p->exit_signal); - else if (ignoring_children(tracer->sighand)) { - __wake_up_parent(p, tracer); - p->exit_signal = -1; - } - } - if (task_detached(p)) { - /* Mark it as in the process of being reaped. */ - p->exit_state = EXIT_DEAD; - return true; - } - } - - return false; -} - int ptrace_detach(struct task_struct *child, unsigned int data) { bool dead = false; @@ -347,56 +527,6 @@ void exit_ptrace(struct task_struct *tra } } -int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - retval = access_process_vm(tsk, src, buf, this_len, 0); - if (!retval) { - if (copied) - break; - return -EIO; - } - if (copy_to_user(dst, buf, retval)) - return -EFAULT; - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - -int ptrace_writedata(struct task_struct *tsk, char __user *src, unsigned long dst, int len) -{ - int copied = 0; - - while (len > 0) { - char buf[128]; - int this_len, retval; - - this_len = (len > sizeof(buf)) ? sizeof(buf) : len; - if (copy_from_user(buf, src, this_len)) - return -EFAULT; - retval = access_process_vm(tsk, dst, buf, this_len, 1); - if (!retval) { - if (copied) - break; - return -EIO; - } - copied += retval; - src += retval; - dst += retval; - len -= retval; - } - return copied; -} - static int ptrace_setoptions(struct task_struct *child, long data) { child->ptrace &= ~PT_TRACE_MASK; @@ -457,7 +587,6 @@ static int ptrace_setsiginfo(struct task return error; } - #ifdef PTRACE_SINGLESTEP #define is_singlestep(request) ((request) == PTRACE_SINGLESTEP) #else @@ -580,93 +709,7 @@ int ptrace_request(struct task_struct *c return ret; } -static struct task_struct *ptrace_get_task_struct(pid_t pid) -{ - struct task_struct *child; - - rcu_read_lock(); - child = find_task_by_vpid(pid); - if (child) - get_task_struct(child); - rcu_read_unlock(); - - if (!child) - return ERR_PTR(-ESRCH); - return child; -} - -#ifndef arch_ptrace_attach -#define arch_ptrace_attach(child) do { } while (0) -#endif - -SYSCALL_DEFINE4(ptrace, long, request, long, pid, long, addr, long, data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - if (!ret) - arch_ptrace_attach(current); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (ret < 0) - goto out_put_task_struct; - - ret = arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} - -int generic_ptrace_peekdata(struct task_struct *tsk, long addr, long data) -{ - unsigned long tmp; - int copied; - - copied = access_process_vm(tsk, addr, &tmp, sizeof(tmp), 0); - if (copied != sizeof(tmp)) - return -EIO; - return put_user(tmp, (unsigned long __user *)data); -} - -int generic_ptrace_pokedata(struct task_struct *tsk, long addr, long data) -{ - int copied; - - copied = access_process_vm(tsk, addr, &data, sizeof(data), 1); - return (copied == sizeof(data)) ? 0 : -EIO; -} - #if defined CONFIG_COMPAT -#include - int compat_ptrace_request(struct task_struct *child, compat_long_t request, compat_ulong_t addr, compat_ulong_t data) { @@ -718,47 +761,4 @@ int compat_ptrace_request(struct task_st return ret; } - -asmlinkage long compat_sys_ptrace(compat_long_t request, compat_long_t pid, - compat_long_t addr, compat_long_t data) -{ - struct task_struct *child; - long ret; - - /* - * This lock_kernel fixes a subtle race with suid exec - */ - lock_kernel(); - if (request == PTRACE_TRACEME) { - ret = ptrace_traceme(); - goto out; - } - - child = ptrace_get_task_struct(pid); - if (IS_ERR(child)) { - ret = PTR_ERR(child); - goto out; - } - - if (request == PTRACE_ATTACH) { - ret = ptrace_attach(child); - /* - * Some architectures need to do book-keeping after - * a ptrace attach. - */ - if (!ret) - arch_ptrace_attach(child); - goto out_put_task_struct; - } - - ret = ptrace_check_attach(child, request == PTRACE_KILL); - if (!ret) - ret = compat_arch_ptrace(child, request, addr, data); - - out_put_task_struct: - put_task_struct(child); - out: - unlock_kernel(); - return ret; -} #endif /* CONFIG_COMPAT */ From oleg at redhat.com Fri Dec 18 01:11:40 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:40 +0100 Subject: [PATCH 6/7] implement utrace-ptrace Message-ID: <20091218011140.GA29570@redhat.com> The patch adds the new file, kernel/ptrace-utrace.c, which contains the new implementation of ptrace over utrace. This file is not compiled until we have CONFIG_UTRACE option, will be added by the next "utrace core" patch. It's supposed to be an invisible implementation change, nothing should change to userland when CONFIG_UTRACE is enabled. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- include/linux/ptrace.h | 2 kernel/Makefile | 1 kernel/ptrace.c | 2 kernel/ptrace-utrace.c | 1080 +++++++++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 1084 insertions(+), 1 deletion(-) --- V1/include/linux/ptrace.h~6_UTRACE_PTRACE 2009-12-18 00:53:58.000000000 +0100 +++ V1/include/linux/ptrace.h 2009-12-18 01:04:56.000000000 +0100 @@ -79,7 +79,7 @@ #include /* For unlikely. */ #include /* For struct task_struct. */ - +extern void ptrace_notify_stop(struct task_struct *tracee); extern long arch_ptrace(struct task_struct *child, long request, long addr, long data); extern int ptrace_traceme(void); extern int ptrace_readdata(struct task_struct *tsk, unsigned long src, char __user *dst, int len); --- V1/kernel/Makefile~6_UTRACE_PTRACE 2009-12-18 00:20:50.000000000 +0100 +++ V1/kernel/Makefile 2009-12-18 01:57:41.000000000 +0100 @@ -69,6 +69,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o obj-$(CONFIG_GCOV_KERNEL) += gcov/ --- V1/kernel/ptrace.c~6_UTRACE_PTRACE 2009-12-18 01:00:26.000000000 +0100 +++ V1/kernel/ptrace.c 2009-12-18 01:04:56.000000000 +0100 @@ -302,6 +302,7 @@ asmlinkage long compat_sys_ptrace(compat } #endif /* CONFIG_COMPAT */ +#ifndef CONFIG_UTRACE /* * ptrace a task: make the debugger its new parent and * move it to the ptrace list. @@ -762,3 +763,4 @@ int compat_ptrace_request(struct task_st return ret; } #endif /* CONFIG_COMPAT */ +#endif /* CONFIG_UTRACE */ --- /dev/null 2009-12-15 18:13:27.615265787 +0100 +++ V1/kernel/ptrace-utrace.c 2009-12-18 01:09:36.000000000 +0100 @@ -0,0 +1,1080 @@ +/* + * linux/kernel/ptrace.c + * + * (C) Copyright 1999 Linus Torvalds + * + * Common interfaces for "ptrace()" which we do not want + * to continually duplicate across every architecture. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* + * 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; + + int signr; + siginfo_t *siginfo; + + int stop_code; + unsigned long eventmsg; + + enum utrace_resume_action resume; +}; + +#define PT_UTRACED 0x00001000 + +#define PTRACE_O_SYSEMU 0x100 + +#define PTRACE_EVENT_SYSCALL (1 << 16) +#define PTRACE_EVENT_SIGTRAP (2 << 16) +#define PTRACE_EVENT_SIGNAL (3 << 16) +/* events visible to user-space */ +#define PTRACE_EVENT_MASK 0xFFFF + +static inline bool ptrace_event_pending(struct ptrace_context *ctx) +{ + return ctx->stop_code != 0; +} + +static inline int get_stop_event(struct ptrace_context *ctx) +{ + return ctx->stop_code >> 8; +} + +static inline void set_stop_code(struct ptrace_context *ctx, int event) +{ + ctx->stop_code = (event << 8) | SIGTRAP; +} + +static inline struct ptrace_context * +ptrace_context(struct utrace_engine *engine) +{ + 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 *ctx; + int err = -EPERM; + + engine = ptrace_lookup_engine(tracee); + if (IS_ERR(engine)) + return engine; + + ctx = ptrace_context(engine); + if (unlikely(ctx->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. + */ + ctx->options = 0; + ctx->eventmsg = 0; + + /* make sure we don't get unwanted reports */ + err = utrace_set_events(tracee, engine, UTRACE_EVENT(QUIESCE)); + if (!err || err == -EINPROGRESS) { + ctx->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 *ctx; + + if (unlikely(task_utrace_flags(tracee))) { + engine = ptrace_reuse_engine(tracee); + if (!IS_ERR(engine) || IS_ERR(engine) == -EPERM) + return engine; + } + + ctx = kzalloc(sizeof(*ctx), GFP_KERNEL); + if (unlikely(!ctx)) + return ERR_PTR(-ENOMEM); + + ctx->resume = UTRACE_RESUME; + + engine = utrace_attach_task(tracee, UTRACE_ATTACH_CREATE | + UTRACE_ATTACH_EXCLUSIVE | + UTRACE_ATTACH_MATCH_OPS, + &ptrace_utrace_ops, ctx); + if (unlikely(IS_ERR(engine))) { + if (engine != ERR_PTR(-ESRCH) && + engine != ERR_PTR(-ERESTARTNOINTR)) + engine = ERR_PTR(-EPERM); + kfree(ctx); + } + + return engine; +} + +static inline int ptrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long options) +{ + struct ptrace_context *ctx = 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; + + ctx->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_events(tracee, engine, options); + WARN_ON(err && !tracee->exit_state); + utrace_engine_put(engine); + return 0; +} + +static int 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; + + return utrace_control(tracee, engine, action); +} + +static void ptrace_detach_task(struct task_struct *tracee, int sig) +{ + /* + * If true, the caller is PTRACE_DETACH, otherwise + * the tracer detaches implicitly during exit. + */ + bool voluntary = (sig >= 0); + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + enum utrace_resume_action action = UTRACE_DETACH; + + if (unlikely(IS_ERR(engine))) + return; + + if (sig) { + struct ptrace_context *ctx = ptrace_context(engine); + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_SYSCALL: + if (voluntary) + send_sig_info(sig, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + if (voluntary) + ctx->signr = sig; + ctx->resume = UTRACE_DETACH; + action = UTRACE_RESUME; + break; + } + } + + ptrace_wake_up(tracee, engine, action, voluntary); + utrace_engine_put(engine); +} + +static void ptrace_abort_attach(struct task_struct *tracee) +{ + ptrace_detach_task(tracee, 0); +} + +static u32 ptrace_report_exit(u32 action, struct utrace_engine *engine, + long orig_code, long *code) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx) && + !signal_group_exit(current->signal)); + + set_stop_code(ctx, PTRACE_EVENT_EXIT); + ctx->eventmsg = *code; + + return UTRACE_STOP; +} + +static void ptrace_clone_attach(struct task_struct *child, + int options) +{ + struct task_struct *parent = current; + struct task_struct *tracer; + bool abort = true; + + if (unlikely(ptrace_attach_task(child, options))) { + WARN_ON(1); + return; + } + + write_lock_irq(&tasklist_lock); + tracer = parent->parent; + if (!(tracer->flags & PF_EXITING) && parent->ptrace) { + child->ptrace = parent->ptrace; + __ptrace_link(child, tracer); + abort = false; + } + write_unlock_irq(&tasklist_lock); + if (unlikely(abort)) { + ptrace_abort_attach(child); + return; + } + + sigaddset(&child->pending.signal, SIGSTOP); + set_tsk_thread_flag(child, TIF_SIGPENDING); +} + +static u32 ptrace_report_clone(u32 action, struct utrace_engine *engine, + unsigned long clone_flags, + struct task_struct *child) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int event = 0; + + WARN_ON(ptrace_event_pending(ctx)); + + if (clone_flags & CLONE_UNTRACED) { + /* no events reported */ + } else if (clone_flags & CLONE_VFORK) { + if (ctx->options & PTRACE_O_TRACEVFORK) + event = PTRACE_EVENT_VFORK; + else if (ctx->options & PTRACE_O_TRACEVFORKDONE) + event = PTRACE_EVENT_VFORK_DONE; + } else if ((clone_flags & CSIGNAL) != SIGCHLD) { + if (ctx->options & PTRACE_O_TRACECLONE) + event = PTRACE_EVENT_CLONE; + } else if (ctx->options & PTRACE_O_TRACEFORK) { + event = PTRACE_EVENT_FORK; + } + /* + * Any of these reports implies auto-attaching the new child. + * So does CLONE_PTRACE, even with no event to report. + */ + if ((event && event != PTRACE_EVENT_VFORK_DONE) || + (clone_flags & CLONE_PTRACE)) + ptrace_clone_attach(child, ctx->options); + + if (!event) + return UTRACE_RESUME; + + set_stop_code(ctx, event); + ctx->eventmsg = child->pid; + /* + * We shouldn't stop now, inside the do_fork() path. + * We will stop later, before return to user-mode. + */ + if (event == PTRACE_EVENT_VFORK_DONE) + return UTRACE_REPORT; + else + return UTRACE_STOP; +} + +static inline void set_syscall_code(struct ptrace_context *ctx) +{ + set_stop_code(ctx, PTRACE_EVENT_SYSCALL); + if (ctx->options & PTRACE_O_TRACESYSGOOD) + ctx->stop_code |= 0x80; +} + +static u32 ptrace_report_syscall_entry(u32 action, struct utrace_engine *engine, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (action & UTRACE_SYSCALL_RESUMED) { + /* + * We already reported the first time. + * Nothing more to do now. + */ + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + return utrace_syscall_action(action) | UTRACE_RESUME; + } + + WARN_ON(ptrace_event_pending(ctx)); + + set_syscall_code(ctx); + + if (unlikely(ctx->options & PTRACE_O_SYSEMU)) + return UTRACE_SYSCALL_ABORT | UTRACE_REPORT; + /* + * Stop now to report. We will get another callback after + * we resume, with the UTRACE_SYSCALL_RESUMED flag set. + */ + return UTRACE_SYSCALL_RUN | UTRACE_STOP; +} + +static u32 ptrace_report_syscall_exit(u32 action, struct utrace_engine *engine, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + if (ctx->resume != UTRACE_RESUME) { + WARN_ON(ctx->resume != UTRACE_BLOCKSTEP && + ctx->resume != UTRACE_SINGLESTEP); + ctx->resume = UTRACE_RESUME; + + ctx->signr = SIGTRAP; + return UTRACE_INTERRUPT; + } + + set_syscall_code(ctx); + return UTRACE_STOP; +} + +static u32 ptrace_report_exec(u32 action, struct utrace_engine *engine, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + WARN_ON(ptrace_event_pending(ctx)); + + if (!(ctx->options & PTRACE_O_TRACEEXEC)) { + /* + * Old-fashioned ptrace'd exec just posts a plain signal. + */ + send_sig(SIGTRAP, current, 0); + return UTRACE_RESUME; + } + + set_stop_code(ctx, PTRACE_EVENT_EXEC); + return UTRACE_STOP; +} + +static enum utrace_signal_action resume_signal(struct ptrace_context *ctx, + struct k_sigaction *return_ka) +{ + siginfo_t *info = ctx->siginfo; + int signr = ctx->signr; + + ctx->siginfo = NULL; + ctx->signr = 0; + + /* Did the debugger cancel the sig? */ + if (!signr) + return UTRACE_SIGNAL_IGN; + /* + * Update the siginfo structure if the signal has changed. + * If the debugger wanted something specific in the siginfo + * then it should have updated *info via PTRACE_SETSIGINFO. + */ + if (info->si_signo != signr) { + info->si_signo = signr; + info->si_errno = 0; + info->si_code = SI_USER; + info->si_pid = task_pid_vnr(current->parent); + info->si_uid = task_uid(current->parent); + } + + /* If the (new) signal is now blocked, requeue it. */ + if (sigismember(¤t->blocked, signr)) { + send_sig_info(signr, info, current); + return UTRACE_SIGNAL_IGN; + } + + spin_lock_irq(¤t->sighand->siglock); + *return_ka = current->sighand->action[signr - 1]; + spin_unlock_irq(¤t->sighand->siglock); + + return UTRACE_SIGNAL_DELIVER; +} + +static u32 ptrace_report_signal(u32 action, struct utrace_engine *engine, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka) +{ + struct ptrace_context *ctx = ptrace_context(engine); + enum utrace_resume_action resume = ctx->resume; + + if (ptrace_event_pending(ctx)) { + action = utrace_signal_action(action); + WARN_ON(action != UTRACE_SIGNAL_REPORT); + return action | UTRACE_STOP; + } + + switch (utrace_signal_action(action)) { + case UTRACE_SIGNAL_HANDLER: + if (WARN_ON(ctx->siginfo)) + ctx->siginfo = NULL; + + if (resume != UTRACE_RESUME) { + WARN_ON(resume != UTRACE_BLOCKSTEP && + resume != UTRACE_SINGLESTEP); + + set_stop_code(ctx, PTRACE_EVENT_SIGTRAP); + return UTRACE_STOP | UTRACE_SIGNAL_IGN; + } + + case UTRACE_SIGNAL_REPORT: + if (!ctx->siginfo) { + if (ctx->signr) { + /* set by ptrace_resume(SYSCALL_EXIT) */ + WARN_ON(ctx->signr != SIGTRAP); + user_single_step_siginfo(current, regs, info); + force_sig_info(SIGTRAP, info, current); + } + + return resume | UTRACE_SIGNAL_IGN; + } + + if (WARN_ON(ctx->siginfo != info)) + return resume | UTRACE_SIGNAL_IGN; + + return resume | resume_signal(ctx, return_ka); + + default: + break; + } + + WARN_ON(ctx->siginfo); + ctx->siginfo = info; + /* + * ctx->siginfo points to the caller's stack. + * Make sure the subsequent UTRACE_SIGNAL_REPORT clears + * ->siginfo before return from get_signal_to_deliver(). + */ + if (utrace_control(current, engine, UTRACE_INTERRUPT)) + WARN_ON(1); + + ctx->signr = info->si_signo; + ctx->stop_code = (PTRACE_EVENT_SIGNAL << 8) | ctx->signr; + + return UTRACE_STOP | UTRACE_SIGNAL_IGN; +} + +static u32 ptrace_report_quiesce(u32 action, struct utrace_engine *engine, + unsigned long event) +{ + struct ptrace_context *ctx = ptrace_context(engine); + + if (ptrace_event_pending(ctx)) + return UTRACE_STOP; + + return event ? UTRACE_RESUME : ctx->resume; +} + +static void ptrace_release(void *data) +{ + kfree(data); +} + +static const struct utrace_engine_ops ptrace_utrace_ops = { + .report_signal = ptrace_report_signal, + .report_quiesce = ptrace_report_quiesce, + .report_exec = ptrace_report_exec, + .report_exit = ptrace_report_exit, + .report_clone = ptrace_report_clone, + .report_syscall_entry = ptrace_report_syscall_entry, + .report_syscall_exit = ptrace_report_syscall_exit, + .release = ptrace_release, +}; + +int ptrace_check_attach(struct task_struct *child, int kill) +{ + struct utrace_engine *engine; + struct utrace_examiner exam; + int ret = -ESRCH; + + engine = ptrace_lookup_engine(child); + if (IS_ERR(engine)) + return ret; + + if (child->parent != current) + goto out; + + if (unlikely(kill)) + ret = 0; + + if (!task_is_stopped_or_traced(child)) + goto out; + /* + * Make sure our engine has already stopped the child. + * Then wait for it to be off the CPU. + */ + if (!utrace_control(child, engine, UTRACE_STOP) && + !utrace_prepare_examine(child, engine, &exam)) + ret = 0; +out: + utrace_engine_put(engine); + return ret; +} + +int ptrace_attach(struct task_struct *task) +{ + int retval; + + audit_ptrace(task); + + retval = -EPERM; + if (unlikely(task->flags & PF_KTHREAD)) + goto out; + if (same_thread_group(task, current)) + goto out; + + /* + * Protect exec's credential calculations against our interference; + * interference; SUID, SGID and LSM creds get determined differently + * under ptrace. + */ + retval = -ERESTARTNOINTR; + if (mutex_lock_interruptible(&task->cred_guard_mutex)) + goto out; + + task_lock(task); + retval = __ptrace_may_access(task, PTRACE_MODE_ATTACH); + task_unlock(task); + if (retval) + goto unlock_creds; + + retval = ptrace_attach_task(task, 0); + if (unlikely(retval)) + goto unlock_creds; + + write_lock_irq(&tasklist_lock); + retval = -EPERM; + if (unlikely(task->exit_state)) + goto unlock_tasklist; + + BUG_ON(task->ptrace); + task->ptrace = PT_UTRACED; + if (capable(CAP_SYS_PTRACE)) + task->ptrace |= PT_PTRACE_CAP; + + __ptrace_link(task, current); + send_sig_info(SIGSTOP, SEND_SIG_FORCED, task); + + retval = 0; +unlock_tasklist: + write_unlock_irq(&tasklist_lock); +unlock_creds: + mutex_unlock(&task->cred_guard_mutex); +out: + return retval; +} + +/* + * Performs checks and sets PT_UTRACED. + * Should be used by all ptrace implementations for PTRACE_TRACEME. + */ +int ptrace_traceme(void) +{ + bool detach = true; + int ret = ptrace_attach_task(current, 0); + + if (unlikely(ret)) + return ret; + + ret = -EPERM; + write_lock_irq(&tasklist_lock); + BUG_ON(current->ptrace); + ret = security_ptrace_traceme(current->parent); + /* + * Check PF_EXITING to ensure ->real_parent has not passed + * exit_ptrace(). Otherwise we don't report the error but + * pretend ->real_parent untraces us right after return. + */ + if (!ret && !(current->real_parent->flags & PF_EXITING)) { + current->ptrace = PT_UTRACED; + __ptrace_link(current, current->real_parent); + detach = false; + } + write_unlock_irq(&tasklist_lock); + + if (detach) + ptrace_abort_attach(current); + return ret; +} + +static void ptrace_do_detach(struct task_struct *tracee, unsigned int data) +{ + bool detach, release; + + write_lock_irq(&tasklist_lock); + /* + * This tracee can be already killed. Make sure de_thread() or + * our sub-thread doing do_wait() didn't do release_task() yet. + */ + detach = tracee->ptrace != 0; + release = false; + if (likely(detach)) + release = __ptrace_detach(current, tracee); + write_unlock_irq(&tasklist_lock); + + if (unlikely(release)) + release_task(tracee); + else if (likely(detach)) + ptrace_detach_task(tracee, data); +} + +int ptrace_detach(struct task_struct *child, unsigned int data) +{ + if (!valid_signal(data)) + return -EIO; + + ptrace_do_detach(child, data); + + return 0; +} + +/* + * Detach all tasks we were using ptrace on. + */ +void exit_ptrace(struct task_struct *tracer) +{ + for (;;) { + struct task_struct *tracee = NULL; + + read_lock(&tasklist_lock); + if (!list_empty(&tracer->ptraced)) { + tracee = list_first_entry(&tracer->ptraced, + struct task_struct, ptrace_entry); + get_task_struct(tracee); + } + read_unlock(&tasklist_lock); + if (!tracee) + break; + + ptrace_do_detach(tracee, -1); + put_task_struct(tracee); + } +} + +static int ptrace_set_options(struct task_struct *tracee, + struct utrace_engine *engine, long data) +{ + BUILD_BUG_ON(PTRACE_O_MASK & PTRACE_O_SYSEMU); + + ptrace_set_events(tracee, engine, data & PTRACE_O_MASK); + return (data & ~PTRACE_O_MASK) ? -EINVAL : 0; +} + +static int ptrace_rw_siginfo(struct task_struct *tracee, + struct ptrace_context *ctx, + siginfo_t *info, bool write) +{ + unsigned long flags; + int err; + + switch (get_stop_event(ctx)) { + case 0: /* jctl stop */ + return -EINVAL; + + case PTRACE_EVENT_SIGNAL: + err = -ESRCH; + if (lock_task_sighand(tracee, &flags)) { + if (likely(task_is_traced(tracee))) { + if (write) + *ctx->siginfo = *info; + else + *info = *ctx->siginfo; + err = 0; + } + unlock_task_sighand(tracee, &flags); + } + + return err; + + default: + if (!write) { + memset(info, 0, sizeof(*info)); + info->si_signo = SIGTRAP; + info->si_code = ctx->stop_code & PTRACE_EVENT_MASK; + info->si_pid = task_pid_vnr(tracee); + info->si_uid = task_uid(tracee); + } + + return 0; + } +} + +static void do_ptrace_notify_stop(struct ptrace_context *ctx, + struct task_struct *tracee) +{ + /* + * This can race with SIGKILL, but we borrow this race from + * the old ptrace implementation. ->exit_code is only needed + * for wait_task_stopped()->task_stopped_code(), we should + * change it to use ptrace_context. + */ + tracee->exit_code = ctx->stop_code & PTRACE_EVENT_MASK; + WARN_ON(!tracee->exit_code); + + read_lock(&tasklist_lock); + /* + * Don't want to allow preemption here, because + * sys_ptrace() needs this task to be inactive. + */ + preempt_disable(); + /* + * It can be killed and then released by our subthread, + * or ptrace_attach() has not completed yet. + */ + if (task_ptrace(tracee)) + do_notify_parent_cldstop(tracee, CLD_TRAPPED); + read_unlock(&tasklist_lock); + preempt_enable_no_resched(); +} + +void ptrace_notify_stop(struct task_struct *tracee) +{ + struct utrace_engine *engine = ptrace_lookup_engine(tracee); + + if (IS_ERR(engine)) + return; + + do_ptrace_notify_stop(ptrace_context(engine), tracee); + utrace_engine_put(engine); +} + +static int ptrace_resume_action(struct task_struct *tracee, + struct utrace_engine *engine, long request) +{ + struct ptrace_context *ctx = ptrace_context(engine); + unsigned long events; + int action; + + ctx->options &= ~PTRACE_O_SYSEMU; + events = engine->flags & ~UTRACE_EVENT_SYSCALL; + action = UTRACE_RESUME; + + switch (request) { +#ifdef PTRACE_SINGLEBLOCK + case PTRACE_SINGLEBLOCK: + if (unlikely(!arch_has_block_step())) + return -EIO; + action = UTRACE_BLOCKSTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SINGLESTEP + case PTRACE_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + events |= UTRACE_EVENT(SYSCALL_EXIT); + break; +#endif + +#ifdef PTRACE_SYSEMU + case PTRACE_SYSEMU_SINGLESTEP: + if (unlikely(!arch_has_single_step())) + return -EIO; + action = UTRACE_SINGLESTEP; + case PTRACE_SYSEMU: + ctx->options |= PTRACE_O_SYSEMU; + events |= UTRACE_EVENT(SYSCALL_ENTRY); + break; +#endif + + case PTRACE_SYSCALL: + events |= UTRACE_EVENT_SYSCALL; + break; + + case PTRACE_CONT: + break; + default: + return -EIO; + } + + if (events != engine->flags && + utrace_set_events(tracee, engine, events)) + return -ESRCH; + + return action; +} + +static int ptrace_resume(struct task_struct *tracee, + struct utrace_engine *engine, + long request, long data) +{ + struct ptrace_context *ctx = ptrace_context(engine); + int action; + + if (!valid_signal(data)) + return -EIO; + + action = ptrace_resume_action(tracee, engine, request); + if (action < 0) + return action; + + switch (get_stop_event(ctx)) { + case PTRACE_EVENT_VFORK: + if (ctx->options & PTRACE_O_TRACEVFORKDONE) { + set_stop_code(ctx, PTRACE_EVENT_VFORK_DONE); + action = UTRACE_REPORT; + } + break; + + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_CLONE: + case PTRACE_EVENT_VFORK_DONE: + if (request == PTRACE_SYSCALL) { + set_syscall_code(ctx); + do_ptrace_notify_stop(ctx, tracee); + return 0; + } + + if (action != UTRACE_RESUME) { + /* + * single-stepping. UTRACE_SIGNAL_REPORT will + * synthesize a trap to follow the syscall insn. + */ + ctx->signr = SIGTRAP; + action = UTRACE_INTERRUPT; + } + break; + + case PTRACE_EVENT_SYSCALL: + if (data) + send_sig_info(data, SEND_SIG_PRIV, tracee); + break; + + case PTRACE_EVENT_SIGNAL: + ctx->signr = data; + break; + } + + ctx->resume = action; + ptrace_wake_up(tracee, engine, action, true); + return 0; +} + +int ptrace_request(struct task_struct *child, long request, + long addr, long data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = generic_ptrace_peekdata(child, addr, data); + break; + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = generic_ptrace_pokedata(child, addr, data); + break; + +#ifdef PTRACE_OLDSETOPTIONS + case PTRACE_OLDSETOPTIONS: +#endif + case PTRACE_SETOPTIONS: + ret = ptrace_set_options(child, engine, data); + break; + case PTRACE_GETEVENTMSG: + ret = put_user(ptrace_context(engine)->eventmsg, + (unsigned long __user *) data); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user((siginfo_t __user *) data, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + if (copy_from_user(&siginfo, (siginfo_t __user *) data, + sizeof siginfo)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + case PTRACE_DETACH: /* detach a process that was attached. */ + ret = ptrace_detach(child, data); + break; + + case PTRACE_KILL: + /* Ugly historical behaviour. */ + if (task_is_traced(child)) + ptrace_resume(child, engine, PTRACE_CONT, SIGKILL); + ret = 0; + break; + + default: + ret = ptrace_resume(child, engine, request, data); + break; + } + + utrace_engine_put(engine); + return ret; +} + +#if defined CONFIG_COMPAT +#include + +int compat_ptrace_request(struct task_struct *child, compat_long_t request, + compat_ulong_t addr, compat_ulong_t data) +{ + struct utrace_engine *engine = ptrace_lookup_engine(child); + compat_ulong_t __user *datap = compat_ptr(data); + compat_ulong_t word; + siginfo_t siginfo; + int ret; + + if (unlikely(IS_ERR(engine))) + return -ESRCH; + + switch (request) { + case PTRACE_PEEKTEXT: + case PTRACE_PEEKDATA: + ret = access_process_vm(child, addr, &word, sizeof(word), 0); + if (ret != sizeof(word)) + ret = -EIO; + else + ret = put_user(word, datap); + break; + + case PTRACE_POKETEXT: + case PTRACE_POKEDATA: + ret = access_process_vm(child, addr, &data, sizeof(data), 1); + ret = (ret != sizeof(data) ? -EIO : 0); + break; + + case PTRACE_GETEVENTMSG: + ret = put_user((compat_ulong_t)ptrace_context(engine)->eventmsg, + datap); + break; + + case PTRACE_GETSIGINFO: + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, false); + if (!ret) + ret = copy_siginfo_to_user32( + (struct compat_siginfo __user *) datap, + &siginfo); + break; + + case PTRACE_SETSIGINFO: + memset(&siginfo, 0, sizeof siginfo); + if (copy_siginfo_from_user32( + &siginfo, (struct compat_siginfo __user *) datap)) + ret = -EFAULT; + else + ret = ptrace_rw_siginfo(child, ptrace_context(engine), + &siginfo, true); + break; + + default: + ret = ptrace_request(child, request, addr, data); + } + + utrace_engine_put(engine); + return ret; +} +#endif /* CONFIG_COMPAT */ From oleg at redhat.com Fri Dec 18 01:11:44 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 02:11:44 +0100 Subject: [PATCH 7/7] utrace core Message-ID: <20091218011144.GA29573@redhat.com> From: Roland McGrath This adds the utrace facility, a new modular interface in the kernel for implementing user thread tracing and debugging. This fits on top of the tracehook_* layer, so the new code is well-isolated. The new interface is in and the DocBook utrace book describes it. It allows for multiple separate tracing engines to work in parallel without interfering with each other. Higher-level tracing facilities can be implemented as loadable kernel modules using this layer. The new facility is made optional under CONFIG_UTRACE. It can only be enabled on machines that have all the prerequisites and select CONFIG_HAVE_ARCH_TRACEHOOK. If CONFIG_UTRACE is set ptrace uses the utrace facilities, it can play nicely with other utrace-based things tracing the same threads. Signed-off-by: Roland McGrath Signed-off-by: Oleg Nesterov --- Documentation/DocBook/Makefile | 2 Documentation/DocBook/utrace.tmpl | 590 +++++++++ fs/proc/array.c | 3 include/linux/sched.h | 5 include/linux/tracehook.h | 87 + include/linux/utrace.h | 692 ++++++++++ init/Kconfig | 9 kernel/Makefile | 1 kernel/fork.c | 3 kernel/utrace.c | 2443 ++++++++++++++++++++++++++++++++++++++ 10 files changed, 3833 insertions(+), 2 deletions(-) --- V1/Documentation/DocBook/Makefile~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/Documentation/DocBook/Makefile 2009-12-18 01:58:37.000000000 +0100 @@ -14,7 +14,7 @@ DOCBOOKS := z8530book.xml mcabook.xml de genericirq.xml s390-drivers.xml uio-howto.xml scsi.xml \ mac80211.xml debugobjects.xml sh.xml regulator.xml \ alsa-driver-api.xml writing-an-alsa-driver.xml \ - tracepoint.xml media.xml + tracepoint.xml utrace.xml media.xml ### # The build process is as follows (targets): --- /dev/null 2009-12-15 18:13:27.615265787 +0100 +++ V1/Documentation/DocBook/utrace.tmpl 2009-12-18 01:58:37.000000000 +0100 @@ -0,0 +1,590 @@ + + + + + + The utrace User Debugging Infrastructure + + + + + utrace concepts + + Introduction + + + utrace is infrastructure code for tracing + and controlling user threads. This is the foundation for writing + tracing engines, which can be loadable kernel modules. + + + + The basic actors in utrace are the thread + and the tracing engine. A tracing engine is some body of code that + calls into the <linux/utrace.h> + interfaces, represented by a struct + utrace_engine_ops. (Usually it's a kernel module, + though the legacy ptrace support is a tracing + engine that is not in a kernel module.) The interface operates on + individual threads (struct task_struct). + If an engine wants to treat several threads as a group, that is up + to its higher-level code. + + + + Tracing begins by attaching an engine to a thread, using + utrace_attach_task or + utrace_attach_pid. If successful, it returns a + pointer that is the handle used in all other calls. + + + + + Events and Callbacks + + + An attached engine does nothing by default. An engine makes something + happen by requesting callbacks via utrace_set_events + and poking the thread with utrace_control. + The synchronization issues related to these two calls + are discussed further below in . + + + + Events are specified using the macro + UTRACE_EVENT(type). + Each event type is associated with a callback in struct + utrace_engine_ops. A tracing engine can leave unused + callbacks NULL. The only callbacks required + are those used by the event flags it sets. + + + + Many engines can be attached to each thread. When a thread has an + event, each engine gets a callback if it has set the event flag for + that event type. For most events, engines are called in the order they + attached. Engines that attach after the event has occurred do not get + callbacks for that event. This includes any new engines just attached + by an existing engine's callback function. Once the sequence of + callbacks for that one event has completed, such new engines are then + eligible in the next sequence that starts when there is another event. + + + + Event reporting callbacks have details particular to the event type, + but are all called in similar environments and have the same + constraints. Callbacks are made from safe points, where no locks + are held, no special resources are pinned (usually), and the + user-mode state of the thread is accessible. So, callback code has + a pretty free hand. But to be a good citizen, callback code should + never block for long periods. It is fine to block in + kmalloc and the like, but never wait for i/o or + for user mode to do something. If you need the thread to wait, use + UTRACE_STOP and return from the callback + quickly. When your i/o finishes or whatever, you can use + utrace_control to resume the thread. + + + + The UTRACE_EVENT(SYSCALL_ENTRY) event is a special + case. While other events happen in the kernel when it will return to + user mode soon, this event happens when entering the kernel before it + will proceed with the work requested from user mode. Because of this + difference, the report_syscall_entry callback is + special in two ways. For this event, engines are called in reverse of + the normal order (this includes the report_quiesce + call that precedes a report_syscall_entry call). + This preserves the semantics that the last engine to attach is called + "closest to user mode"--the engine that is first to see a thread's user + state when it enters the kernel is also the last to see that state when + the thread returns to user mode. For the same reason, if these + callbacks use UTRACE_STOP (see the next section), + the thread stops immediately after callbacks rather than only when it's + ready to return to user mode; when allowed to resume, it will actually + attempt the system call indicated by the register values at that time. + + + + + Stopping Safely + + Writing well-behaved callbacks + + + Well-behaved callbacks are important to maintain two essential + properties of the interface. The first of these is that unrelated + tracing engines should not interfere with each other. If your engine's + event callback does not return quickly, then another engine won't get + the event notification in a timely manner. The second important + property is that tracing should be as noninvasive as possible to the + normal operation of the system overall and of the traced thread in + particular. That is, attached tracing engines should not perturb a + thread's behavior, except to the extent that changing its user-visible + state is explicitly what you want to do. (Obviously some perturbation + is unavoidable, primarily timing changes, ranging from small delays due + to the overhead of tracing, to arbitrary pauses in user code execution + when a user stops a thread with a debugger for examination.) Even when + you explicitly want the perturbation of making the traced thread block, + just blocking directly in your callback has more unwanted effects. For + example, the CLONE event callbacks are called when + the new child thread has been created but not yet started running; the + child can never be scheduled until the CLONE + tracing callbacks return. (This allows engines tracing the parent to + attach to the child.) If a CLONE event callback + blocks the parent thread, it also prevents the child thread from + running (even to process a SIGKILL). If what you + want is to make both the parent and child block, then use + utrace_attach_task on the child and then use + UTRACE_STOP on both threads. A more crucial + problem with blocking in callbacks is that it can prevent + SIGKILL from working. A thread that is blocking + due to UTRACE_STOP will still wake up and die + immediately when sent a SIGKILL, as all threads + should. Relying on the utrace + infrastructure rather than on private synchronization calls in event + callbacks is an important way to help keep tracing robustly + noninvasive. + + + + + Using <constant>UTRACE_STOP</constant> + + + To control another thread and access its state, it must be stopped + with UTRACE_STOP. This means that it is + stopped and won't start running again while we access it. When a + thread is not already stopped, utrace_control + returns -EINPROGRESS and an engine must wait + for an event callback when the thread is ready to stop. The thread + may be running on another CPU or may be blocked. When it is ready + to be examined, it will make callbacks to engines that set the + UTRACE_EVENT(QUIESCE) event bit. To wake up an + interruptible wait, use UTRACE_INTERRUPT. + + + + As long as some engine has used UTRACE_STOP and + not called utrace_control to resume the thread, + then the thread will remain stopped. SIGKILL + will wake it up, but it will not run user code. When the stop is + cleared with utrace_control or a callback + return value, the thread starts running again. + (See also .) + + + + + + + Tear-down Races + + Primacy of <constant>SIGKILL</constant> + + Ordinarily synchronization issues for tracing engines are kept fairly + straightforward by using UTRACE_STOP. You ask a + thread to stop, and then once it makes the + report_quiesce callback it cannot do anything else + that would result in another callback, until you let it with a + utrace_control call. This simple arrangement + avoids complex and error-prone code in each one of a tracing engine's + event callbacks to keep them serialized with the engine's other + operations done on that thread from another thread of control. + However, giving tracing engines complete power to keep a traced thread + stuck in place runs afoul of a more important kind of simplicity that + the kernel overall guarantees: nothing can prevent or delay + SIGKILL from making a thread die and release its + resources. To preserve this important property of + SIGKILL, it as a special case can break + UTRACE_STOP like nothing else normally can. This + includes both explicit SIGKILL signals and the + implicit SIGKILL sent to each other thread in the + same thread group by a thread doing an exec, or processing a fatal + signal, or making an exit_group system call. A + tracing engine can prevent a thread from beginning the exit or exec or + dying by signal (other than SIGKILL) if it is + attached to that thread, but once the operation begins, no tracing + engine can prevent or delay all other threads in the same thread group + dying. + + + + Final callbacks + + The report_reap callback is always the final event + in the life cycle of a traced thread. Tracing engines can use this as + the trigger to clean up their own data structures. The + report_death callback is always the penultimate + event a tracing engine might see; it's seen unless the thread was + already in the midst of dying when the engine attached. Many tracing + engines will have no interest in when a parent reaps a dead process, + and nothing they want to do with a zombie thread once it dies; for + them, the report_death callback is the natural + place to clean up data structures and detach. To facilitate writing + such engines robustly, given the asynchrony of + SIGKILL, and without error-prone manual + implementation of synchronization schemes, the + utrace infrastructure provides some special + guarantees about the report_death and + report_reap callbacks. It still takes some care + to be sure your tracing engine is robust to tear-down races, but these + rules make it reasonably straightforward and concise to handle a lot of + corner cases correctly. + + + + Engine and task pointers + + The first sort of guarantee concerns the core data structures + themselves. struct utrace_engine is + a reference-counted data structure. While you hold a reference, an + engine pointer will always stay valid so that you can safely pass it to + any utrace call. Each call to + utrace_attach_task or + utrace_attach_pid returns an engine pointer with a + reference belonging to the caller. You own that reference until you + drop it using utrace_engine_put. There is an + implicit reference on the engine while it is attached. So if you drop + your only reference, and then use + utrace_attach_task without + UTRACE_ATTACH_CREATE to look up that same engine, + you will get the same pointer with a new reference to replace the one + you dropped, just like calling utrace_engine_get. + When an engine has been detached, either explicitly with + UTRACE_DETACH or implicitly after + report_reap, then any references you hold are all + that keep the old engine pointer alive. + + + + There is nothing a kernel module can do to keep a struct + task_struct alive outside of + rcu_read_lock. When the task dies and is reaped + by its parent (or itself), that structure can be freed so that any + dangling pointers you have stored become invalid. + utrace will not prevent this, but it can + help you detect it safely. By definition, a task that has been reaped + has had all its engines detached. All + utrace calls can be safely called on a + detached engine if the caller holds a reference on that engine pointer, + even if the task pointer passed in the call is invalid. All calls + return -ESRCH for a detached engine, which tells + you that the task pointer you passed could be invalid now. Since + utrace_control and + utrace_set_events do not block, you can call those + inside a rcu_read_lock section and be sure after + they don't return -ESRCH that the task pointer is + still valid until rcu_read_unlock. The + infrastructure never holds task references of its own. Though neither + rcu_read_lock nor any other lock is held while + making a callback, it's always guaranteed that the struct + task_struct and the struct + utrace_engine passed as arguments remain valid + until the callback function returns. + + + + The common means for safely holding task pointers that is available to + kernel modules is to use struct pid, which + permits put_pid from kernel modules. When using + that, the calls utrace_attach_pid, + utrace_control_pid, + utrace_set_events_pid, and + utrace_barrier_pid are available. + + + + + + Serialization of <constant>DEATH</constant> and <constant>REAP</constant> + + + The second guarantee is the serialization of + DEATH and REAP event + callbacks for a given thread. The actual reaping by the parent + (release_task call) can occur simultaneously + while the thread is still doing the final steps of dying, including + the report_death callback. If a tracing engine + has requested both DEATH and + REAP event reports, it's guaranteed that the + report_reap callback will not be made until + after the report_death callback has returned. + If the report_death callback itself detaches + from the thread, then the report_reap callback + will never be made. Thus it is safe for a + report_death callback to clean up data + structures and detach. + + + + Interlock with final callbacks + + The final sort of guarantee is that a tracing engine will know for sure + whether or not the report_death and/or + report_reap callbacks will be made for a certain + thread. These tear-down races are disambiguated by the error return + values of utrace_set_events and + utrace_control. Normally + utrace_control called with + UTRACE_DETACH returns zero, and this means that no + more callbacks will be made. If the thread is in the midst of dying, + it returns -EALREADY to indicate that the + report_death callback may already be in progress; + when you get this error, you know that any cleanup your + report_death callback does is about to happen or + has just happened--note that if the report_death + callback does not detach, the engine remains attached until the thread + gets reaped. If the thread is in the midst of being reaped, + utrace_control returns -ESRCH + to indicate that the report_reap callback may + already be in progress; this means the engine is implicitly detached + when the callback completes. This makes it possible for a tracing + engine that has decided asynchronously to detach from a thread to + safely clean up its data structures, knowing that no + report_death or report_reap + callback will try to do the same. utrace_detach + returns -ESRCH when the struct + utrace_engine has already been detached, but is + still a valid pointer because of its reference count. A tracing engine + can use this to safely synchronize its own independent multiple threads + of control with each other and with its event callbacks that detach. + + + + In the same vein, utrace_set_events normally + returns zero; if the target thread was stopped before the call, then + after a successful call, no event callbacks not requested in the new + flags will be made. It fails with -EALREADY if + you try to clear UTRACE_EVENT(DEATH) when the + report_death callback may already have begun, if + you try to clear UTRACE_EVENT(REAP) when the + report_reap callback may already have begun, or if + you try to newly set UTRACE_EVENT(DEATH) or + UTRACE_EVENT(QUIESCE) when the target is already + dead or dying. Like utrace_control, it returns + -ESRCH when the thread has already been detached + (including forcible detach on reaping). This lets the tracing engine + know for sure which event callbacks it will or won't see after + utrace_set_events has returned. By checking for + errors, it can know whether to clean up its data structures immediately + or to let its callbacks do the work. + + + + Using <function>utrace_barrier</function> + + When a thread is safely stopped, calling + utrace_control with UTRACE_DETACH + or calling utrace_set_events to disable some events + ensures synchronously that your engine won't get any more of the callbacks + that have been disabled (none at all when detaching). But these can also + be used while the thread is not stopped, when it might be simultaneously + making a callback to your engine. For this situation, these calls return + -EINPROGRESS when it's possible a callback is in + progress. If you are not prepared to have your old callbacks still run, + then you can synchronize to be sure all the old callbacks are finished, + using utrace_barrier. This is necessary if the + kernel module containing your callback code is going to be unloaded. + + + After using UTRACE_DETACH once, further calls to + utrace_control with the same engine pointer will + return -ESRCH. In contrast, after getting + -EINPROGRESS from + utrace_set_events, you can call + utrace_set_events again later and if it returns zero + then know the old callbacks have finished. + + + Unlike all other calls, utrace_barrier (and + utrace_barrier_pid) will accept any engine pointer you + hold a reference on, even if UTRACE_DETACH has already + been used. After any utrace_control or + utrace_set_events call (these do not block), you can + call utrace_barrier to block until callbacks have + finished. This returns -ESRCH only if the engine is + completely detached (finished all callbacks). Otherwise it waits + until the thread is definitely not in the midst of a callback to this + engine and then returns zero, but can return + -ERESTARTSYS if its wait is interrupted. + + + + + + + +utrace core API + + + The utrace API is declared in <linux/utrace.h>. + + +!Iinclude/linux/utrace.h +!Ekernel/utrace.c + + + +Machine State + + + The task_current_syscall function can be used on any + valid struct task_struct at any time, and does + not even require that utrace_attach_task was used at all. + + + + The other ways to access the registers and other machine-dependent state of + a task can only be used on a task that is at a known safe point. The safe + points are all the places where utrace_set_events can + request callbacks (except for the DEATH and + REAP events). So at any event callback, it is safe to + examine current. + + + + One task can examine another only after a callback in the target task that + returns UTRACE_STOP so that task will not return to user + mode after the safe point. This guarantees that the task will not resume + until the same engine uses utrace_control, unless the + task dies suddenly. To examine safely, one must use a pair of calls to + utrace_prepare_examine and + utrace_finish_examine surrounding the calls to + struct user_regset functions or direct examination + of task data structures. utrace_prepare_examine returns + an error if the task is not properly stopped, or is dead. After a + successful examination, the paired utrace_finish_examine + call returns an error if the task ever woke up during the examination. If + so, any data gathered may be scrambled and should be discarded. This means + there was a spurious wake-up (which should not happen), or a sudden death. + + +<structname>struct user_regset</structname> + + + The struct user_regset API + is declared in <linux/regset.h>. + + +!Finclude/linux/regset.h + + + + + <filename>System Call Information</filename> + + + This function is declared in <linux/ptrace.h>. + + +!Elib/syscall.c + + + +<filename>System Call Tracing</filename> + + + The arch API for system call information is declared in + <asm/syscall.h>. + Each of these calls can be used only at system call entry tracing, + or can be used only at system call exit and the subsequent safe points + before returning to user mode. + At system call entry tracing means either during a + report_syscall_entry callback, + or any time after that callback has returned UTRACE_STOP. + + +!Finclude/asm-generic/syscall.h + + + + + +Kernel Internals + + + This chapter covers the interface to the tracing infrastructure + from the core of the kernel and the architecture-specific code. + This is for maintainers of the kernel and arch code, and not relevant + to using the tracing facilities described in preceding chapters. + + +Core Calls In + + + These calls are declared in <linux/tracehook.h>. + The core kernel calls these functions at various important places. + + +!Finclude/linux/tracehook.h + + + +Architecture Calls Out + + + An arch that has done all these things sets + CONFIG_HAVE_ARCH_TRACEHOOK. + This is required to enable the utrace code. + + +<filename><asm/ptrace.h></filename> + + + An arch defines these in <asm/ptrace.h> + if it supports hardware single-step or block-step features. + + +!Finclude/linux/ptrace.h arch_has_single_step arch_has_block_step +!Finclude/linux/ptrace.h user_enable_single_step user_enable_block_step +!Finclude/linux/ptrace.h user_disable_single_step + + + + + <filename><asm/syscall.h></filename> + + + An arch provides <asm/syscall.h> that + defines these as inlines, or declares them as exported functions. + These interfaces are described in . + + + + + + <filename><linux/tracehook.h></filename> + + + An arch must define TIF_NOTIFY_RESUME + and TIF_SYSCALL_TRACE + in its <asm/thread_info.h>. + The arch code must call the following functions, all declared + in <linux/tracehook.h> and + described in : + + + + tracehook_notify_resume + + + tracehook_report_syscall_entry + + + tracehook_report_syscall_exit + + + tracehook_signal_handler + + + + + + + + + + + + --- V1/fs/proc/array.c~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/fs/proc/array.c 2009-12-18 01:58:37.000000000 +0100 @@ -82,6 +82,7 @@ #include #include #include +#include #include #include @@ -189,6 +190,8 @@ static inline void task_state(struct seq cred->uid, cred->euid, cred->suid, cred->fsuid, cred->gid, cred->egid, cred->sgid, cred->fsgid); + task_utrace_proc_status(m, p); + task_lock(p); if (p->files) fdt = files_fdtable(p->files); --- V1/include/linux/sched.h~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/include/linux/sched.h 2009-12-18 01:58:37.000000000 +0100 @@ -1396,6 +1396,11 @@ struct task_struct { #endif seccomp_t seccomp; +#ifdef CONFIG_UTRACE + struct utrace *utrace; + unsigned long utrace_flags; +#endif + /* Thread group tracking */ u32 parent_exec_id; u32 self_exec_id; --- V1/include/linux/tracehook.h~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/include/linux/tracehook.h 2009-12-18 01:58:37.000000000 +0100 @@ -49,6 +49,7 @@ #include #include #include +#include struct linux_binprm; /** @@ -63,6 +64,8 @@ struct linux_binprm; */ static inline int tracehook_expect_breakpoints(struct task_struct *task) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_CORE))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -111,6 +114,9 @@ static inline void ptrace_report_syscall static inline __must_check int tracehook_report_syscall_entry( struct pt_regs *regs) { + if ((task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_ENTRY)) && + utrace_report_syscall_entry(regs)) + return 1; ptrace_report_syscall(regs); return 0; } @@ -134,6 +140,9 @@ static inline __must_check int tracehook */ static inline void tracehook_report_syscall_exit(struct pt_regs *regs, int step) { + if (task_utrace_flags(current) & UTRACE_EVENT(SYSCALL_EXIT)) + utrace_report_syscall_exit(regs); + if (step && (task_ptrace(current) & PT_PTRACED)) { siginfo_t info; user_single_step_siginfo(current, regs, &info); @@ -201,6 +210,8 @@ static inline void tracehook_report_exec struct linux_binprm *bprm, struct pt_regs *regs) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXEC))) + utrace_report_exec(fmt, bprm, regs); if (!ptrace_event(PT_TRACE_EXEC, PTRACE_EVENT_EXEC, 0) && unlikely(task_ptrace(current) & PT_PTRACED)) send_sig(SIGTRAP, current, 0); @@ -218,10 +229,37 @@ static inline void tracehook_report_exec */ static inline void tracehook_report_exit(long *exit_code) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(EXIT))) + utrace_report_exit(exit_code); ptrace_event(PT_TRACE_EXIT, PTRACE_EVENT_EXIT, *exit_code); } /** + * tracehook_init_task - task_struct has just been copied + * @task: new &struct task_struct just copied from parent + * + * Called from do_fork() when @task has just been duplicated. + * After this, @task will be passed to tracehook_free_task() + * even if the rest of its setup fails before it is fully created. + */ +static inline void tracehook_init_task(struct task_struct *task) +{ + utrace_init_task(task); +} + +/** + * tracehook_free_task - task_struct is being freed + * @task: dead &struct task_struct being freed + * + * Called from free_task() when @task is no longer in use. + */ +static inline void tracehook_free_task(struct task_struct *task) +{ + if (task_utrace_struct(task)) + utrace_free_task(task); +} + +/** * tracehook_prepare_clone - prepare for new child to be cloned * @clone_flags: %CLONE_* flags from clone/fork/vfork system call * @@ -285,6 +323,8 @@ static inline void tracehook_report_clon unsigned long clone_flags, pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE))) + utrace_report_clone(clone_flags, child); if (unlikely(task_ptrace(child))) { /* * It doesn't matter who attached/attaching to this @@ -317,6 +357,9 @@ static inline void tracehook_report_clon pid_t pid, struct task_struct *child) { + if (unlikely(task_utrace_flags(current) & UTRACE_EVENT(CLONE)) && + (clone_flags & CLONE_VFORK)) + utrace_finish_vfork(current); if (unlikely(trace)) ptrace_event(0, trace, pid); } @@ -351,6 +394,10 @@ static inline void tracehook_report_vfor */ static inline void tracehook_prepare_release_task(struct task_struct *task) { + /* see utrace_add_engine() about this barrier */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_maybe_reap(task, task_utrace_struct(task), true); } /** @@ -365,6 +412,7 @@ static inline void tracehook_prepare_rel static inline void tracehook_finish_release_task(struct task_struct *task) { ptrace_release_task(task); + BUG_ON(task->exit_state != EXIT_DEAD); } /** @@ -386,6 +434,8 @@ static inline void tracehook_signal_hand const struct k_sigaction *ka, struct pt_regs *regs, int stepping) { + if (task_utrace_flags(current)) + utrace_signal_handler(current, stepping); if (stepping && (task_ptrace(current) & PT_PTRACED)) ptrace_notify(SIGTRAP); } @@ -403,6 +453,8 @@ static inline void tracehook_signal_hand static inline int tracehook_consider_ignored_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & UTRACE_EVENT(SIGNAL_IGN))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -422,6 +474,9 @@ static inline int tracehook_consider_ign static inline int tracehook_consider_fatal_signal(struct task_struct *task, int sig) { + if (unlikely(task_utrace_flags(task) & (UTRACE_EVENT(SIGNAL_TERM) | + UTRACE_EVENT(SIGNAL_CORE)))) + return 1; return (task_ptrace(task) & PT_PTRACED) != 0; } @@ -436,6 +491,8 @@ static inline int tracehook_consider_fat */ static inline int tracehook_force_sigpending(void) { + if (unlikely(task_utrace_flags(current))) + return utrace_interrupt_pending(); return 0; } @@ -465,6 +522,8 @@ static inline int tracehook_get_signal(s siginfo_t *info, struct k_sigaction *return_ka) { + if (unlikely(task_utrace_flags(task))) + return utrace_get_signal(task, regs, info, return_ka); return 0; } @@ -492,6 +551,8 @@ static inline int tracehook_get_signal(s */ static inline int tracehook_notify_jctl(int notify, int why) { + if (task_utrace_flags(current) & UTRACE_EVENT(JCTL)) + utrace_report_jctl(notify, why); return notify ?: task_ptrace(current) ? why : 0; } @@ -502,6 +563,8 @@ static inline int tracehook_notify_jctl( */ static inline void tracehook_finish_jctl(void) { + if (task_utrace_flags(current)) + utrace_finish_stop(); } #define DEATH_REAP -1 @@ -524,6 +587,8 @@ static inline void tracehook_finish_jctl static inline int tracehook_notify_death(struct task_struct *task, void **death_cookie, int group_dead) { + *death_cookie = task_utrace_struct(task); + if (task_detached(task)) return task->ptrace ? SIGCHLD : DEATH_REAP; @@ -560,6 +625,15 @@ static inline void tracehook_report_deat int signal, void *death_cookie, int group_dead) { + /* + * If utrace_set_events() was just called to enable + * UTRACE_EVENT(DEATH), then we are obliged to call + * utrace_report_death() and not miss it. utrace_set_events() + * checks @task->exit_state under tasklist_lock to synchronize + * with exit_notify(), the caller. + */ + if (task_utrace_flags(task) & _UTRACE_DEATH_EVENTS) + utrace_report_death(task, death_cookie, group_dead, signal); } #ifdef TIF_NOTIFY_RESUME @@ -589,10 +663,21 @@ static inline void set_notify_resume(str * asynchronously, this will be called again before we return to * user mode. * - * Called without locks. + * Called without locks. However, on some machines this may be + * called with interrupts disabled. */ static inline void tracehook_notify_resume(struct pt_regs *regs) { + struct task_struct *task = current; + /* + * Prevent the following store/load from getting ahead of the + * caller which clears TIF_NOTIFY_RESUME. This pairs with the + * implicit mb() before setting TIF_NOTIFY_RESUME in + * set_notify_resume(). + */ + smp_mb(); + if (task_utrace_flags(task)) + utrace_resume(task, regs); } #endif /* TIF_NOTIFY_RESUME */ --- /dev/null 2009-12-15 18:13:27.615265787 +0100 +++ V1/include/linux/utrace.h 2009-12-18 01:58:37.000000000 +0100 @@ -0,0 +1,692 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + * + * This interface allows for notification of interesting events in a + * thread. It also mediates access to thread state such as registers. + * Multiple unrelated users can be associated with a single thread. + * We call each of these a tracing engine. + * + * A tracing engine starts by calling utrace_attach_task() or + * utrace_attach_pid() on the chosen thread, passing in a set of hooks + * (&struct utrace_engine_ops), and some associated data. This produces a + * &struct utrace_engine, which is the handle used for all other + * operations. An attached engine has its ops vector, its data, and an + * event mask controlled by utrace_set_events(). + * + * For each event bit that is set, that engine will get the + * appropriate ops->report_*() callback when the event occurs. The + * &struct utrace_engine_ops need not provide callbacks for an event + * unless the engine sets one of the associated event bits. + */ + +#ifndef _LINUX_UTRACE_H +#define _LINUX_UTRACE_H 1 + +#include +#include +#include +#include + +struct linux_binprm; +struct pt_regs; +struct utrace; +struct user_regset; +struct user_regset_view; + +/* + * Event bits passed to utrace_set_events(). + * These appear in &struct task_struct. at utrace_flags + * and &struct utrace_engine. at flags. + */ +enum utrace_events { + _UTRACE_EVENT_QUIESCE, /* Thread is available for examination. */ + _UTRACE_EVENT_REAP, /* Zombie reaped, no more tracing possible. */ + _UTRACE_EVENT_CLONE, /* Successful clone/fork/vfork just done. */ + _UTRACE_EVENT_EXEC, /* Successful execve just completed. */ + _UTRACE_EVENT_EXIT, /* Thread exit in progress. */ + _UTRACE_EVENT_DEATH, /* Thread has died. */ + _UTRACE_EVENT_SYSCALL_ENTRY, /* User entered kernel for system call. */ + _UTRACE_EVENT_SYSCALL_EXIT, /* Returning to user after system call. */ + _UTRACE_EVENT_SIGNAL, /* Signal delivery will run a user handler. */ + _UTRACE_EVENT_SIGNAL_IGN, /* No-op signal to be delivered. */ + _UTRACE_EVENT_SIGNAL_STOP, /* Signal delivery will suspend. */ + _UTRACE_EVENT_SIGNAL_TERM, /* Signal delivery will terminate. */ + _UTRACE_EVENT_SIGNAL_CORE, /* Signal delivery will dump core. */ + _UTRACE_EVENT_JCTL, /* Job control stop or continue completed. */ + _UTRACE_NEVENTS +}; +#define UTRACE_EVENT(type) (1UL << _UTRACE_EVENT_##type) + +/* + * All the kinds of signal events. + * These all use the @report_signal() callback. + */ +#define UTRACE_EVENT_SIGNAL_ALL (UTRACE_EVENT(SIGNAL) \ + | UTRACE_EVENT(SIGNAL_IGN) \ + | UTRACE_EVENT(SIGNAL_STOP) \ + | UTRACE_EVENT(SIGNAL_TERM) \ + | UTRACE_EVENT(SIGNAL_CORE)) +/* + * Both kinds of syscall events; these call the @report_syscall_entry() + * and @report_syscall_exit() callbacks, respectively. + */ +#define UTRACE_EVENT_SYSCALL \ + (UTRACE_EVENT(SYSCALL_ENTRY) | UTRACE_EVENT(SYSCALL_EXIT)) + +/* + * The event reports triggered synchronously by task death. + */ +#define _UTRACE_DEATH_EVENTS (UTRACE_EVENT(DEATH) | UTRACE_EVENT(QUIESCE)) + +/* + * Hooks in call these entry points to the utrace dispatch. + */ +void utrace_free_task(struct task_struct *); +bool utrace_interrupt_pending(void); +void utrace_resume(struct task_struct *, struct pt_regs *); +void utrace_finish_stop(void); +void utrace_maybe_reap(struct task_struct *, struct utrace *, bool); +int utrace_get_signal(struct task_struct *, struct pt_regs *, + siginfo_t *, struct k_sigaction *); +void utrace_report_clone(unsigned long, struct task_struct *); +void utrace_finish_vfork(struct task_struct *); +void utrace_report_exit(long *exit_code); +void utrace_report_death(struct task_struct *, struct utrace *, bool, int); +void utrace_report_jctl(int notify, int type); +void utrace_report_exec(struct linux_binfmt *, struct linux_binprm *, + struct pt_regs *regs); +bool utrace_report_syscall_entry(struct pt_regs *); +void utrace_report_syscall_exit(struct pt_regs *); +void utrace_signal_handler(struct task_struct *, int); + +#ifndef CONFIG_UTRACE + +/* + * uses these accessors to avoid #ifdef CONFIG_UTRACE. + */ +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return 0; +} +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + return NULL; +} +static inline void utrace_init_task(struct task_struct *child) +{ +} + +static inline void task_utrace_proc_status(struct seq_file *m, + struct task_struct *p) +{ +} + +#else /* CONFIG_UTRACE */ + +static inline unsigned long task_utrace_flags(struct task_struct *task) +{ + return task->utrace_flags; +} + +static inline struct utrace *task_utrace_struct(struct task_struct *task) +{ + struct utrace *utrace; + + /* + * This barrier ensures that any prior load of task->utrace_flags + * is ordered before this load of task->utrace. We use those + * utrace_flags checks in the hot path to decide to call into + * the utrace code. The first attach installs task->utrace before + * setting task->utrace_flags nonzero with implicit barrier in + * between, see utrace_add_engine(). + */ + smp_rmb(); + utrace = task->utrace; + + smp_read_barrier_depends(); /* See utrace_task_alloc(). */ + return utrace; +} + +static inline void utrace_init_task(struct task_struct *task) +{ + task->utrace_flags = 0; + task->utrace = NULL; +} + +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p); + + +/* + * Version number of the API defined in this file. This will change + * whenever a tracing engine's code would need some updates to keep + * working. We maintain this here for the benefit of tracing engine code + * that is developed concurrently with utrace API improvements before they + * are merged into the kernel, making LINUX_VERSION_CODE checks unwieldy. + */ +#define UTRACE_API_VERSION 20091216 + +/** + * enum utrace_resume_action - engine's choice of action for a traced task + * @UTRACE_STOP: Stay quiescent after callbacks. + * @UTRACE_INTERRUPT: Make @report_signal() callback soon. + * @UTRACE_REPORT: Make some callback soon. + * @UTRACE_SINGLESTEP: Resume in user mode for one instruction. + * @UTRACE_BLOCKSTEP: Resume in user mode until next branch. + * @UTRACE_RESUME: Resume normally in user mode. + * @UTRACE_DETACH: Detach my engine (implies %UTRACE_RESUME). + * + * See utrace_control() for detailed descriptions of each action. This is + * encoded in the @action argument and the return value for every callback + * with a &u32 return value. + * + * The order of these is important. When there is more than one engine, + * each supplies its choice and the smallest value prevails. + */ +enum utrace_resume_action { + UTRACE_STOP, + UTRACE_INTERRUPT, + UTRACE_REPORT, + UTRACE_SINGLESTEP, + UTRACE_BLOCKSTEP, + UTRACE_RESUME, + UTRACE_DETACH, + UTRACE_RESUME_MAX +}; +#define UTRACE_RESUME_BITS (ilog2(UTRACE_RESUME_MAX) + 1) +#define UTRACE_RESUME_MASK ((1 << UTRACE_RESUME_BITS) - 1) + +/** + * utrace_resume_action - &enum utrace_resume_action from callback action + * @action: &u32 callback @action argument or return value + * + * This extracts the &enum utrace_resume_action from @action, + * which is the @action argument to a &struct utrace_engine_ops + * callback or the return value from one. + */ +static inline enum utrace_resume_action utrace_resume_action(u32 action) +{ + return action & UTRACE_RESUME_MASK; +} + +/** + * enum utrace_signal_action - disposition of signal + * @UTRACE_SIGNAL_DELIVER: Deliver according to sigaction. + * @UTRACE_SIGNAL_IGN: Ignore the signal. + * @UTRACE_SIGNAL_TERM: Terminate the process. + * @UTRACE_SIGNAL_CORE: Terminate with core dump. + * @UTRACE_SIGNAL_STOP: Deliver as absolute stop. + * @UTRACE_SIGNAL_TSTP: Deliver as job control stop. + * @UTRACE_SIGNAL_REPORT: Reporting before pending signals. + * @UTRACE_SIGNAL_HANDLER: Reporting after signal handler setup. + * + * This is encoded in the @action argument and the return value for + * a @report_signal() callback. It says what will happen to the + * signal described by the &siginfo_t parameter to the callback. + * + * The %UTRACE_SIGNAL_REPORT value is used in an @action argument when + * a tracing report is being made before dequeuing any pending signal. + * If this is immediately after a signal handler has been set up, then + * %UTRACE_SIGNAL_HANDLER is used instead. A @report_signal callback + * that uses %UTRACE_SIGNAL_DELIVER|%UTRACE_SINGLESTEP will ensure + * it sees a %UTRACE_SIGNAL_HANDLER report. + */ +enum utrace_signal_action { + UTRACE_SIGNAL_DELIVER = 0x00, + UTRACE_SIGNAL_IGN = 0x10, + UTRACE_SIGNAL_TERM = 0x20, + UTRACE_SIGNAL_CORE = 0x30, + UTRACE_SIGNAL_STOP = 0x40, + UTRACE_SIGNAL_TSTP = 0x50, + UTRACE_SIGNAL_REPORT = 0x60, + UTRACE_SIGNAL_HANDLER = 0x70 +}; +#define UTRACE_SIGNAL_MASK 0xf0 +#define UTRACE_SIGNAL_HOLD 0x100 /* Flag, push signal back on queue. */ + +/** + * utrace_signal_action - &enum utrace_signal_action from callback action + * @action: @report_signal callback @action argument or return value + * + * This extracts the &enum utrace_signal_action from @action, which + * is the @action argument to a @report_signal callback or the + * return value from one. + */ +static inline enum utrace_signal_action utrace_signal_action(u32 action) +{ + return action & UTRACE_SIGNAL_MASK; +} + +/** + * enum utrace_syscall_action - disposition of system call attempt + * @UTRACE_SYSCALL_RUN: Run the system call. + * @UTRACE_SYSCALL_ABORT: Don't run the system call. + * + * This is encoded in the @action argument and the return value for + * a @report_syscall_entry callback. + */ +enum utrace_syscall_action { + UTRACE_SYSCALL_RUN = 0x00, + UTRACE_SYSCALL_ABORT = 0x10 +}; +#define UTRACE_SYSCALL_MASK 0xf0 +#define UTRACE_SYSCALL_RESUMED 0x100 /* Flag, report_syscall_entry() repeats */ + +/** + * utrace_syscall_action - &enum utrace_syscall_action from callback action + * @action: @report_syscall_entry callback @action or return value + * + * This extracts the &enum utrace_syscall_action from @action, which + * is the @action argument to a @report_syscall_entry callback or the + * return value from one. + */ +static inline enum utrace_syscall_action utrace_syscall_action(u32 action) +{ + return action & UTRACE_SYSCALL_MASK; +} + +/* + * Flags for utrace_attach_task() and utrace_attach_pid(). + */ +#define UTRACE_ATTACH_MATCH_OPS 0x0001 /* Match engines on ops. */ +#define UTRACE_ATTACH_MATCH_DATA 0x0002 /* Match engines on data. */ +#define UTRACE_ATTACH_MATCH_MASK 0x000f +#define UTRACE_ATTACH_CREATE 0x0010 /* Attach a new engine. */ +#define UTRACE_ATTACH_EXCLUSIVE 0x0020 /* Refuse if existing match. */ + +/** + * struct utrace_engine - per-engine structure + * @ops: &struct utrace_engine_ops pointer passed to utrace_attach_task() + * @data: engine-private &void * passed to utrace_attach_task() + * @flags: event mask set by utrace_set_events() plus internal flag bits + * + * The task itself never has to worry about engines detaching while + * it's doing event callbacks. These structures are removed from the + * task's active list only when it's stopped, or by the task itself. + * + * utrace_engine_get() and utrace_engine_put() maintain a reference count. + * When it drops to zero, the structure is freed. One reference is held + * implicitly while the engine is attached to its task. + */ +struct utrace_engine { +/* private: */ + struct kref kref; + void (*release)(void *); + struct list_head entry; + +/* public: */ + const struct utrace_engine_ops *ops; + void *data; + + unsigned long flags; +}; + +/** + * utrace_engine_get - acquire a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you get another. + */ +static inline void utrace_engine_get(struct utrace_engine *engine) +{ + kref_get(&engine->kref); +} + +void __utrace_engine_release(struct kref *); + +/** + * utrace_engine_put - release a reference on a &struct utrace_engine + * @engine: &struct utrace_engine pointer + * + * You must hold a reference on @engine, and you lose that reference. + * If it was the last one, @engine becomes an invalid pointer. + */ +static inline void utrace_engine_put(struct utrace_engine *engine) +{ + kref_put(&engine->kref, __utrace_engine_release); +} + +/** + * struct utrace_engine_ops - tracing engine callbacks + * + * Each @report_*() callback corresponds to an %UTRACE_EVENT(*) bit. + * utrace_set_events() calls on @engine choose which callbacks will + * be made to @engine from @task. + * + * Most callbacks take an @action argument, giving the resume action + * chosen by other tracing engines. All callbacks take an @engine + * argument. The @report_reap callback takes a @task argument that + * might or might not be @current. All other @report_* callbacks + * report an event in the @current task. + * + * For some calls, @action also includes bits specific to that event + * and utrace_resume_action() is used to extract the resume action. + * This shows what would happen if @engine wasn't there, or will if + * the callback's return value uses %UTRACE_RESUME. This always + * starts as %UTRACE_RESUME when no other tracing is being done on + * this task. + * + * All return values contain &enum utrace_resume_action bits. For + * some calls, other bits specific to that kind of event are added to + * the resume action bits with OR. These are the same bits used in + * the @action argument. The resume action returned by a callback + * does not override previous engines' choices, it only says what + * @engine wants done. What @current actually does is the action that's + * most constrained among the choices made by all attached engines. + * See utrace_control() for more information on the actions. + * + * When %UTRACE_STOP is used in @report_syscall_entry, then @current + * stops before attempting the system call. In this case, another + * @report_syscall_entry callback will follow after @current resumes if + * %UTRACE_REPORT or %UTRACE_INTERRUPT was returned by some callback + * or passed to utrace_control(). In a second or later callback, + * %UTRACE_SYSCALL_RESUMED is set in the @action argument to indicate + * a repeat callback still waiting to attempt the same system call + * invocation. This repeat callback gives each engine an opportunity + * to reexamine registers another engine might have changed while + * @current was held in %UTRACE_STOP. + * + * In other cases, the resume action does not take effect until @current + * is ready to check for signals and return to user mode. If there + * are more callbacks to be made, the last round of calls determines + * the final action. A @report_quiesce callback with @event zero, or + * a @report_signal callback, will always be the last one made before + * @current resumes. Only %UTRACE_STOP is "sticky"--if @engine returned + * %UTRACE_STOP then @current stays stopped unless @engine returns + * different from a following callback. + * + * The report_death() and report_reap() callbacks do not take @action + * arguments, and only %UTRACE_DETACH is meaningful in the return value + * from a report_death() callback. None of the resume actions applies + * to a dead thread. + * + * All @report_*() hooks are called with no locks held, in a generally + * safe environment when we will be returning to user mode soon (or just + * entered the kernel). It is fine to block for memory allocation and + * the like, but all hooks are asynchronous and must not block on + * external events! If you want the thread to block, use %UTRACE_STOP + * in your hook's return value; then later wake it up with utrace_control(). + * + * @report_quiesce: + * Requested by %UTRACE_EVENT(%QUIESCE). + * This does not indicate any event, but just that @current is in a + * safe place for examination. This call is made before each specific + * event callback, except for @report_reap. The @event argument gives + * the %UTRACE_EVENT(@which) value for the event occurring. This + * callback might be made for events @engine has not requested, if + * some other engine is tracing the event; calling utrace_set_events() + * call here can request the immediate callback for this occurrence of + * @event. @event is zero when there is no other event, @current is + * now ready to check for signals and return to user mode, and some + * engine has used %UTRACE_REPORT or %UTRACE_INTERRUPT to request this + * callback. For this case, if @report_signal is not %NULL, the + * @report_quiesce callback may be replaced with a @report_signal + * callback passing %UTRACE_SIGNAL_REPORT in its @action argument, + * whenever @current is entering the signal-check path anyway. + * + * @report_signal: + * Requested by %UTRACE_EVENT(%SIGNAL_*) or %UTRACE_EVENT(%QUIESCE). + * Use utrace_signal_action() and utrace_resume_action() on @action. + * The signal action is %UTRACE_SIGNAL_REPORT when some engine has + * used %UTRACE_REPORT or %UTRACE_INTERRUPT; the callback can choose + * to stop or to deliver an artificial signal, before pending signals. + * It's %UTRACE_SIGNAL_HANDLER instead when signal handler setup just + * finished (after a previous %UTRACE_SIGNAL_DELIVER return); this + * serves in lieu of any %UTRACE_SIGNAL_REPORT callback requested by + * %UTRACE_REPORT or %UTRACE_INTERRUPT, and is also implicitly + * requested by %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP into the + * signal delivery. The other signal actions indicate a signal about + * to be delivered; the previous engine's return value sets the signal + * action seen by the the following engine's callback. The @info data + * can be changed at will, including @info->si_signo. The settings in + * @return_ka determines what %UTRACE_SIGNAL_DELIVER does. @orig_ka + * is what was in force before other tracing engines intervened, and + * it's %NULL when this report began as %UTRACE_SIGNAL_REPORT or + * %UTRACE_SIGNAL_HANDLER. For a report without a new signal, @info + * is left uninitialized and must be set completely by an engine that + * chooses to deliver a signal; if there was a previous @report_signal + * callback ending in %UTRACE_STOP and it was just resumed using + * %UTRACE_REPORT or %UTRACE_INTERRUPT, then @info is left unchanged + * from the previous callback. In this way, the original signal can + * be left in @info while returning %UTRACE_STOP|%UTRACE_SIGNAL_IGN + * and then found again when resuming with %UTRACE_INTERRUPT. + * The %UTRACE_SIGNAL_HOLD flag bit can be OR'd into the return value, + * and might be in @action if the previous engine returned it. This + * flag asks that the signal in @info be pushed back on @current's queue + * so that it will be seen again after whatever action is taken now. + * + * @report_clone: + * Requested by %UTRACE_EVENT(%CLONE). + * Event reported for parent, before the new task @child might run. + * @clone_flags gives the flags used in the clone system call, or + * equivalent flags for a fork() or vfork() system call. This + * function can use utrace_attach_task() on @child. Then passing + * %UTRACE_STOP to utrace_control() on @child here keeps the child + * stopped before it ever runs in user mode, %UTRACE_REPORT or + * %UTRACE_INTERRUPT ensures a callback from @child before it + * starts in user mode. + * + * @report_jctl: + * Requested by %UTRACE_EVENT(%JCTL). + * Job control event; @type is %CLD_STOPPED or %CLD_CONTINUED, + * indicating whether we are stopping or resuming now. If @notify + * is nonzero, @current is the last thread to stop and so will send + * %SIGCHLD to its parent after this callback; @notify reflects + * what the parent's %SIGCHLD has in @si_code, which can sometimes + * be %CLD_STOPPED even when @type is %CLD_CONTINUED. + * + * @report_exec: + * Requested by %UTRACE_EVENT(%EXEC). + * An execve system call has succeeded and the new program is about to + * start running. The initial user register state is handy to be tweaked + * directly in @regs. @fmt and @bprm gives the details of this exec. + * + * @report_syscall_entry: + * Requested by %UTRACE_EVENT(%SYSCALL_ENTRY). + * Thread has entered the kernel to request a system call. + * The user register state is handy to be tweaked directly in @regs. + * The @action argument contains an &enum utrace_syscall_action, + * use utrace_syscall_action() to extract it. The return value + * overrides the last engine's action for the system call. + * If the final action is %UTRACE_SYSCALL_ABORT, no system call + * is made. The details of the system call being attempted can + * be fetched here with syscall_get_nr() and syscall_get_arguments(). + * The parameter registers can be changed with syscall_set_arguments(). + * See above about the %UTRACE_SYSCALL_RESUMED flag in @action. + * Use %UTRACE_REPORT in the return value to guarantee you get + * another callback (with %UTRACE_SYSCALL_RESUMED flag) in case + * @current stops with %UTRACE_STOP before attempting the system call. + * + * @report_syscall_exit: + * Requested by %UTRACE_EVENT(%SYSCALL_EXIT). + * Thread is about to leave the kernel after a system call request. + * The user register state is handy to be tweaked directly in @regs. + * The results of the system call attempt can be examined here using + * syscall_get_error() and syscall_get_return_value(). It is safe + * here to call syscall_set_return_value() or syscall_rollback(). + * + * @report_exit: + * Requested by %UTRACE_EVENT(%EXIT). + * Thread is exiting and cannot be prevented from doing so, + * but all its state is still live. The @code value will be + * the wait result seen by the parent, and can be changed by + * this engine or others. The @orig_code value is the real + * status, not changed by any tracing engine. Returning %UTRACE_STOP + * here keeps @current stopped before it cleans up its state and dies, + * so it can be examined by other processes. When @current is allowed + * to run, it will die and get to the @report_death callback. + * + * @report_death: + * Requested by %UTRACE_EVENT(%DEATH). + * Thread is really dead now. It might be reaped by its parent at + * any time, or self-reap immediately. Though the actual reaping + * may happen in parallel, a report_reap() callback will always be + * ordered after a report_death() callback. + * + * @report_reap: + * Requested by %UTRACE_EVENT(%REAP). + * Called when someone reaps the dead task (parent, init, or self). + * This means the parent called wait, or else this was a detached + * thread or a process whose parent ignores SIGCHLD. + * No more callbacks are made after this one. + * The engine is always detached. + * There is nothing more a tracing engine can do about this thread. + * After this callback, the @engine pointer will become invalid. + * The @task pointer may become invalid if get_task_struct() hasn't + * been used to keep it alive. + * An engine should always request this callback if it stores the + * @engine pointer or stores any pointer in @engine->data, so it + * can clean up its data structures. + * Unlike other callbacks, this can be called from the parent's context + * rather than from the traced thread itself--it must not delay the + * parent by blocking. + * + * @release: + * If not %NULL, this is called after the last utrace_engine_put() + * call for a &struct utrace_engine, which could be implicit after + * a %UTRACE_DETACH return from another callback. Its argument is + * the engine's @data member. + */ +struct utrace_engine_ops { + u32 (*report_quiesce)(u32 action, struct utrace_engine *engine, + unsigned long event); + u32 (*report_signal)(u32 action, struct utrace_engine *engine, + struct pt_regs *regs, + siginfo_t *info, + const struct k_sigaction *orig_ka, + struct k_sigaction *return_ka); + u32 (*report_clone)(u32 action, struct utrace_engine *engine, + unsigned long clone_flags, + struct task_struct *child); + u32 (*report_jctl)(u32 action, struct utrace_engine *engine, + int type, int notify); + u32 (*report_exec)(u32 action, struct utrace_engine *engine, + const struct linux_binfmt *fmt, + const struct linux_binprm *bprm, + struct pt_regs *regs); + u32 (*report_syscall_entry)(u32 action, struct utrace_engine *engine, + struct pt_regs *regs); + u32 (*report_syscall_exit)(u32 action, struct utrace_engine *engine, + struct pt_regs *regs); + u32 (*report_exit)(u32 action, struct utrace_engine *engine, + long orig_code, long *code); + u32 (*report_death)(struct utrace_engine *engine, + bool group_dead, int signal); + void (*report_reap)(struct utrace_engine *engine, + struct task_struct *task); + void (*release)(void *data); +}; + +/** + * struct utrace_examiner - private state for using utrace_prepare_examine() + * + * The members of &struct utrace_examiner are private to the implementation. + * This data type holds the state from a call to utrace_prepare_examine() + * to be used by a call to utrace_finish_examine(). + */ +struct utrace_examiner { +/* private: */ + long state; + unsigned long ncsw; +}; + +/* + * These are the exported entry points for tracing engines to use. + * See kernel/utrace.c for their kerneldoc comments with interface details. + */ +struct utrace_engine *utrace_attach_task(struct task_struct *, int, + const struct utrace_engine_ops *, + void *); +struct utrace_engine *utrace_attach_pid(struct pid *, int, + const struct utrace_engine_ops *, + void *); +int __must_check utrace_control(struct task_struct *, + struct utrace_engine *, + enum utrace_resume_action); +int __must_check utrace_set_events(struct task_struct *, + struct utrace_engine *, + unsigned long eventmask); +int __must_check utrace_barrier(struct task_struct *, + struct utrace_engine *); +int __must_check utrace_prepare_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); +int __must_check utrace_finish_examine(struct task_struct *, + struct utrace_engine *, + struct utrace_examiner *); + +/** + * utrace_control_pid - control a thread being traced by a tracing engine + * @pid: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is the same as utrace_control(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_control_pid( + struct pid *pid, struct utrace_engine *engine, + enum utrace_resume_action action) +{ + /* + * We don't bother with rcu_read_lock() here to protect the + * task_struct pointer, because utrace_control will return + * -ESRCH without looking at that pointer if the engine is + * already detached. A task_struct pointer can't die before + * all the engines are detached in release_task() first. + */ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_control(task, engine, action); +} + +/** + * utrace_set_events_pid - choose which event reports a tracing engine gets + * @pid: thread to affect + * @engine: attached engine to affect + * @eventmask: new event mask + * + * This is the same as utrace_set_events(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_set_events_pid( + struct pid *pid, struct utrace_engine *engine, unsigned long eventmask) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : + utrace_set_events(task, engine, eventmask); +} + +/** + * utrace_barrier_pid - synchronize with simultaneous tracing callbacks + * @pid: thread to affect + * @engine: engine to affect (can be detached) + * + * This is the same as utrace_barrier(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +static inline __must_check int utrace_barrier_pid(struct pid *pid, + struct utrace_engine *engine) +{ + struct task_struct *task = pid_task(pid, PIDTYPE_PID); + return unlikely(!task) ? -ESRCH : utrace_barrier(task, engine); +} + +#endif /* CONFIG_UTRACE */ + +#endif /* linux/utrace.h */ --- V1/init/Kconfig~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/init/Kconfig 2009-12-18 01:58:37.000000000 +0100 @@ -310,6 +310,15 @@ config AUDIT_TREE depends on AUDITSYSCALL select INOTIFY +config UTRACE + bool "Infrastructure for tracing and debugging user processes" + depends on EXPERIMENTAL + depends on HAVE_ARCH_TRACEHOOK + help + Enable the utrace process tracing interface. This is an internal + kernel interface exported to kernel modules, to track events in + user threads, extract and change user thread state. + menu "RCU Subsystem" choice --- V1/kernel/Makefile~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/kernel/Makefile 2009-12-18 01:58:37.000000000 +0100 @@ -69,6 +69,7 @@ obj-$(CONFIG_IKCONFIG) += configs.o obj-$(CONFIG_RESOURCE_COUNTERS) += res_counter.o obj-$(CONFIG_STOP_MACHINE) += stop_machine.o obj-$(CONFIG_KPROBES_SANITY_TEST) += test_kprobes.o +obj-$(CONFIG_UTRACE) += utrace.o obj-$(CONFIG_UTRACE) += ptrace-utrace.o obj-$(CONFIG_AUDIT) += audit.o auditfilter.o audit_watch.o obj-$(CONFIG_AUDITSYSCALL) += auditsc.o --- V1/kernel/fork.c~7_UTRACE 2009-12-18 01:57:41.000000000 +0100 +++ V1/kernel/fork.c 2009-12-18 01:58:37.000000000 +0100 @@ -153,6 +153,7 @@ void free_task(struct task_struct *tsk) free_thread_info(tsk->stack); rt_mutex_debug_task_free(tsk); ftrace_graph_exit_task(tsk); + tracehook_free_task(tsk); free_task_struct(tsk); } EXPORT_SYMBOL(free_task); @@ -1023,6 +1024,8 @@ static struct task_struct *copy_process( if (!p) goto fork_out; + tracehook_init_task(p); + ftrace_graph_init_task(p); rt_mutex_init_task(p); --- /dev/null 2009-12-15 18:13:27.615265787 +0100 +++ V1/kernel/utrace.c 2009-12-18 01:58:37.000000000 +0100 @@ -0,0 +1,2443 @@ +/* + * utrace infrastructure interface for debugging user processes + * + * Copyright (C) 2006-2009 Red Hat, Inc. All rights reserved. + * + * This copyrighted material is made available to anyone wishing to use, + * modify, copy, or redistribute it subject to the terms and conditions + * of the GNU General Public License v.2. + * + * Red Hat Author: Roland McGrath. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +/* + * Per-thread structure private to utrace implementation. + * If task_struct.utrace_flags is nonzero, task_struct.utrace + * has always been allocated first. Once allocated, it is + * never freed until free_task(). + * + * The common event reporting loops are done by the task making the + * report without ever taking any locks. To facilitate this, the two + * lists @attached and @attaching work together for smooth asynchronous + * attaching with low overhead. Modifying either list requires @lock. + * The @attaching list can be modified any time while holding @lock. + * New engines being attached always go on this list. + * + * The @attached list is what the task itself uses for its reporting + * loops. When the task itself is not quiescent, it can use the + * @attached list without taking any lock. Nobody may modify the list + * when the task is not quiescent. When it is quiescent, that means + * that it won't run again without taking @lock itself before using + * the list. + * + * At each place where we know the task is quiescent (or it's current), + * while holding @lock, we call splice_attaching(), below. This moves + * the @attaching list members on to the end of the @attached list. + * Since this happens at the start of any reporting pass, any new + * engines attached asynchronously go on the stable @attached list + * in time to have their callbacks seen. + */ +struct utrace { + spinlock_t lock; + struct list_head attached, attaching; + + struct task_struct *cloning; + + struct utrace_engine *reporting; + + enum utrace_resume_action resume:UTRACE_RESUME_BITS; + unsigned int signal_handler:1; + unsigned int vfork_stop:1; /* need utrace_stop() before vfork wait */ + unsigned int death:1; /* in utrace_report_death() now */ + unsigned int reap:1; /* release_task() has run */ + unsigned int pending_attach:1; /* need splice_attaching() */ +}; + +static struct kmem_cache *utrace_cachep; +static struct kmem_cache *utrace_engine_cachep; +static const struct utrace_engine_ops utrace_detached_ops; /* forward decl */ + +static int __init utrace_init(void) +{ + utrace_cachep = KMEM_CACHE(utrace, SLAB_PANIC); + utrace_engine_cachep = KMEM_CACHE(utrace_engine, SLAB_PANIC); + return 0; +} +module_init(utrace_init); + +/* + * Set up @task.utrace for the first time. We can have races + * between two utrace_attach_task() calls here. The task_lock() + * governs installing the new pointer. If another one got in first, + * we just punt the new one we allocated. + * + * This returns false only in case of a memory allocation failure. + */ +static bool utrace_task_alloc(struct task_struct *task) +{ + struct utrace *utrace = kmem_cache_zalloc(utrace_cachep, GFP_KERNEL); + if (unlikely(!utrace)) + return false; + spin_lock_init(&utrace->lock); + INIT_LIST_HEAD(&utrace->attached); + INIT_LIST_HEAD(&utrace->attaching); + utrace->resume = UTRACE_RESUME; + task_lock(task); + if (likely(!task->utrace)) { + /* + * This barrier makes sure the initialization of the struct + * precedes the installation of the pointer. This pairs + * with smp_read_barrier_depends() in task_utrace_struct(). + */ + smp_wmb(); + task->utrace = utrace; + } + task_unlock(task); + + if (unlikely(task->utrace != utrace)) + kmem_cache_free(utrace_cachep, utrace); + return true; +} + +/* + * This is called via tracehook_free_task() from free_task() + * when @task is being deallocated. + */ +void utrace_free_task(struct task_struct *task) +{ + kmem_cache_free(utrace_cachep, task->utrace); +} + +/* + * This is calledwhen the task is safely quiescent, i.e. it won't consult + * utrace->attached without the lock. Move any engines attached + * asynchronously from @utrace->attaching onto the @utrace->attached list. + */ +static void splice_attaching(struct utrace *utrace) +{ + lockdep_assert_held(&utrace->lock); + list_splice_tail_init(&utrace->attaching, &utrace->attached); + utrace->pending_attach = 0; +} + +/* + * This is the exported function used by the utrace_engine_put() inline. + */ +void __utrace_engine_release(struct kref *kref) +{ + struct utrace_engine *engine = container_of(kref, struct utrace_engine, + kref); + BUG_ON(!list_empty(&engine->entry)); + if (engine->release) + (*engine->release)(engine->data); + kmem_cache_free(utrace_engine_cachep, engine); +} +EXPORT_SYMBOL_GPL(__utrace_engine_release); + +static bool engine_matches(struct utrace_engine *engine, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + if ((flags & UTRACE_ATTACH_MATCH_OPS) && engine->ops != ops) + return false; + if ((flags & UTRACE_ATTACH_MATCH_DATA) && engine->data != data) + return false; + return engine->ops && engine->ops != &utrace_detached_ops; +} + +static struct utrace_engine *find_matching_engine( + struct utrace *utrace, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine; + list_for_each_entry(engine, &utrace->attached, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + list_for_each_entry(engine, &utrace->attaching, entry) + if (engine_matches(engine, flags, ops, data)) + return engine; + return NULL; +} + +/* + * Enqueue @engine, or maybe don't if UTRACE_ATTACH_EXCLUSIVE. + */ +static int utrace_add_engine(struct task_struct *target, + struct utrace *utrace, + struct utrace_engine *engine, + int flags, + const struct utrace_engine_ops *ops, + void *data) +{ + int ret; + + spin_lock(&utrace->lock); + + ret = -EEXIST; + if ((flags & UTRACE_ATTACH_EXCLUSIVE) && + unlikely(find_matching_engine(utrace, flags, ops, data))) + goto unlock; + + /* + * In case we had no engines before, make sure that + * utrace_flags is not zero. Since we did unlock+lock + * at least once after utrace_task_alloc() installed + * ->utrace, we have the necessary barrier which pairs + * with rmb() in task_utrace_struct(). + */ + ret = -ESRCH; + if (!target->utrace_flags) { + target->utrace_flags = UTRACE_EVENT(REAP); + /* + * If we race with tracehook_prepare_release_task() + * make sure that either it sees utrace_flags != 0 + * or we see exit_state == EXIT_DEAD. + */ + smp_mb(); + if (unlikely(target->exit_state == EXIT_DEAD)) { + target->utrace_flags = 0; + goto unlock; + } + } + + /* + * Put the new engine on the pending ->attaching list. + * Make sure it gets onto the ->attached list by the next + * time it's examined. Setting ->pending_attach ensures + * that start_report() takes the lock and splices the lists + * before the next new reporting pass. + * + * When target == current, it would be safe just to call + * splice_attaching() right here. But if we're inside a + * callback, that would mean the new engine also gets + * notified about the event that precipitated its own + * creation. This is not what the user wants. + */ + list_add_tail(&engine->entry, &utrace->attaching); + utrace->pending_attach = 1; + ret = 0; +unlock: + spin_unlock(&utrace->lock); + + return ret; +} + +/** + * utrace_attach_task - attach new engine, or look up an attached engine + * @target: thread to attach to + * @flags: flag bits combined with OR, see below + * @ops: callback table for new engine + * @data: engine private data pointer + * + * The caller must ensure that the @target thread does not get freed, + * i.e. hold a ref or be its parent. It is always safe to call this + * on @current, or on the @child pointer in a @report_clone callback. + * For most other cases, it's easier to use utrace_attach_pid() instead. + * + * UTRACE_ATTACH_CREATE: + * Create a new engine. If %UTRACE_ATTACH_CREATE is not specified, you + * only look up an existing engine already attached to the thread. + * + * UTRACE_ATTACH_EXCLUSIVE: + * Attempting to attach a second (matching) engine fails with -%EEXIST. + * + * UTRACE_ATTACH_MATCH_OPS: Only consider engines matching @ops. + * UTRACE_ATTACH_MATCH_DATA: Only consider engines matching @data. + * + * Calls with neither %UTRACE_ATTACH_MATCH_OPS nor %UTRACE_ATTACH_MATCH_DATA + * match the first among any engines attached to @target. That means that + * %UTRACE_ATTACH_EXCLUSIVE in such a call fails with -%EEXIST if there + * are any engines on @target at all. + */ +struct utrace_engine *utrace_attach_task( + struct task_struct *target, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace *utrace = task_utrace_struct(target); + struct utrace_engine *engine; + int ret; + + if (!(flags & UTRACE_ATTACH_CREATE)) { + if (unlikely(!utrace)) + return ERR_PTR(-ENOENT); + spin_lock(&utrace->lock); + engine = find_matching_engine(utrace, flags, ops, data); + if (engine) + utrace_engine_get(engine); + spin_unlock(&utrace->lock); + return engine ?: ERR_PTR(-ENOENT); + } + + if (unlikely(!ops) || unlikely(ops == &utrace_detached_ops)) + return ERR_PTR(-EINVAL); + + if (unlikely(target->flags & PF_KTHREAD)) + /* + * Silly kernel, utrace is for users! + */ + return ERR_PTR(-EPERM); + + if (!utrace) { + if (unlikely(!utrace_task_alloc(target))) + return ERR_PTR(-ENOMEM); + utrace = task_utrace_struct(target); + } + + engine = kmem_cache_alloc(utrace_engine_cachep, GFP_KERNEL); + if (unlikely(!engine)) + return ERR_PTR(-ENOMEM); + + /* + * Initialize the new engine structure. It starts out with two + * refs: one ref to return, and one ref for being attached. + */ + kref_set(&engine->kref, 2); + engine->flags = 0; + engine->ops = ops; + engine->data = data; + engine->release = ops->release; + + ret = utrace_add_engine(target, utrace, engine, flags, ops, data); + + if (unlikely(ret)) { + kmem_cache_free(utrace_engine_cachep, engine); + engine = ERR_PTR(ret); + } + + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_task); + +/** + * utrace_attach_pid - attach new engine, or look up an attached engine + * @pid: &struct pid pointer representing thread to attach to + * @flags: flag bits combined with OR, see utrace_attach_task() + * @ops: callback table for new engine + * @data: engine private data pointer + * + * This is the same as utrace_attach_task(), but takes a &struct pid + * pointer rather than a &struct task_struct pointer. The caller must + * hold a ref on @pid, but does not need to worry about the task + * staying valid. If it's been reaped so that @pid points nowhere, + * then this call returns -%ESRCH. + */ +struct utrace_engine *utrace_attach_pid( + struct pid *pid, int flags, + const struct utrace_engine_ops *ops, void *data) +{ + struct utrace_engine *engine = ERR_PTR(-ESRCH); + struct task_struct *task = get_pid_task(pid, PIDTYPE_PID); + if (task) { + engine = utrace_attach_task(task, flags, ops, data); + put_task_struct(task); + } + return engine; +} +EXPORT_SYMBOL_GPL(utrace_attach_pid); + +/* + * When an engine is detached, the target thread may still see it and + * make callbacks until it quiesces. We install a special ops vector + * with these two callbacks. When the target thread quiesces, it can + * safely free the engine itself. For any event we will always get + * the report_quiesce() callback first, so we only need this one + * pointer to be set. The only exception is report_reap(), so we + * supply that callback too. + */ +static u32 utrace_detached_quiesce(u32 action, struct utrace_engine *engine, + unsigned long event) +{ + return UTRACE_DETACH; +} + +static void utrace_detached_reap(struct utrace_engine *engine, + struct task_struct *task) +{ +} + +static const struct utrace_engine_ops utrace_detached_ops = { + .report_quiesce = &utrace_detached_quiesce, + .report_reap = &utrace_detached_reap +}; + +/* + * The caller has to hold a ref on the engine. If the attached flag is + * true (all but utrace_barrier() calls), the engine is supposed to be + * attached. If the attached flag is false (utrace_barrier() only), + * then return -ERESTARTSYS for an engine marked for detach but not yet + * fully detached. The task pointer can be invalid if the engine is + * detached. + * + * Get the utrace lock for the target task. + * Returns the struct if locked, or ERR_PTR(-errno). + * + * This has to be robust against races with: + * utrace_control(target, UTRACE_DETACH) calls + * UTRACE_DETACH after reports + * utrace_report_death + * utrace_release_task + */ +static struct utrace *get_utrace_lock(struct task_struct *target, + struct utrace_engine *engine, + bool attached) + __acquires(utrace->lock) +{ + struct utrace *utrace; + + rcu_read_lock(); + + /* + * If this engine was already detached, bail out before we look at + * the task_struct pointer at all. If it's detached after this + * check, then RCU is still keeping this task_struct pointer valid. + * + * The ops pointer is NULL when the engine is fully detached. + * It's &utrace_detached_ops when it's marked detached but still + * on the list. In the latter case, utrace_barrier() still works, + * since the target might be in the middle of an old callback. + */ + if (unlikely(!engine->ops)) { + rcu_read_unlock(); + return ERR_PTR(-ESRCH); + } + + if (unlikely(engine->ops == &utrace_detached_ops)) { + rcu_read_unlock(); + return attached ? ERR_PTR(-ESRCH) : ERR_PTR(-ERESTARTSYS); + } + + utrace = task_utrace_struct(target); + spin_lock(&utrace->lock); + if (unlikely(!engine->ops) || + unlikely(engine->ops == &utrace_detached_ops)) { + /* + * By the time we got the utrace lock, + * it had been reaped or detached already. + */ + spin_unlock(&utrace->lock); + utrace = ERR_PTR(-ESRCH); + if (!attached && engine->ops == &utrace_detached_ops) + utrace = ERR_PTR(-ERESTARTSYS); + } + rcu_read_unlock(); + + return utrace; +} + +/* + * Now that we don't hold any locks, run through any + * detached engines and free their references. Each + * engine had one implicit ref while it was attached. + */ +static void put_detached_list(struct list_head *list) +{ + struct utrace_engine *engine, *next; + list_for_each_entry_safe(engine, next, list, entry) { + list_del_init(&engine->entry); + utrace_engine_put(engine); + } +} + +/* + * We use an extra bit in utrace_engine.flags past the event bits, + * to record whether the engine is keeping the target thread stopped. + * + * This bit is set in task_struct.utrace_flags whenever it is set in any + * engine's flags. Only utrace_reset() resets it in utrace_flags. + */ +#define ENGINE_STOP (1UL << _UTRACE_NEVENTS) + +static void mark_engine_wants_stop(struct task_struct *task, + struct utrace_engine *engine) +{ + engine->flags |= ENGINE_STOP; + task->utrace_flags |= ENGINE_STOP; +} + +static void clear_engine_wants_stop(struct utrace_engine *engine) +{ + engine->flags &= ~ENGINE_STOP; +} + +static bool engine_wants_stop(struct utrace_engine *engine) +{ + return (engine->flags & ENGINE_STOP) != 0; +} + +/** + * utrace_set_events - choose which event reports a tracing engine gets + * @target: thread to affect + * @engine: attached engine to affect + * @events: new event mask + * + * This changes the set of events for which @engine wants callbacks made. + * + * This fails with -%EALREADY and does nothing if you try to clear + * %UTRACE_EVENT(%DEATH) when the @report_death callback may already have + * begun, if you try to clear %UTRACE_EVENT(%REAP) when the @report_reap + * callback may already have begun, or if you try to newly set + * %UTRACE_EVENT(%DEATH) or %UTRACE_EVENT(%QUIESCE) when @target is + * already dead or dying. + * + * This can fail with -%ESRCH when @target has already been detached, + * including forcible detach on reaping. + * + * If @target was stopped before the call, then after a successful call, + * no event callbacks not requested in @events will be made; if + * %UTRACE_EVENT(%QUIESCE) is included in @events, then a + * @report_quiesce callback will be made when @target resumes. + * + * If @target was not stopped and @events excludes some bits that were + * set before, this can return -%EINPROGRESS to indicate that @target + * may have been making some callback to @engine. When this returns + * zero, you can be sure that no event callbacks you've disabled in + * @events can be made. If @events only sets new bits that were not set + * before on @engine, then -%EINPROGRESS will never be returned. + * + * To synchronize after an -%EINPROGRESS return, see utrace_barrier(). + * + * When @target is @current, -%EINPROGRESS is not returned. But note + * that a newly-created engine will not receive any callbacks related to + * an event notification already in progress. This call enables @events + * callbacks to be made as soon as @engine becomes eligible for any + * callbacks, see utrace_attach_task(). + * + * These rules provide for coherent synchronization based on %UTRACE_STOP, + * even when %SIGKILL is breaking its normal simple rules. + */ +int utrace_set_events(struct task_struct *target, + struct utrace_engine *engine, + unsigned long events) +{ + struct utrace *utrace; + unsigned long old_flags, old_utrace_flags; + int ret; + + /* + * We just ignore the internal bit, so callers can use + * engine->flags to seed bitwise ops for our argument. + */ + events &= ~ENGINE_STOP; + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + old_utrace_flags = target->utrace_flags; + old_flags = engine->flags & ~ENGINE_STOP; + + if (target->exit_state && + (((events & ~old_flags) & _UTRACE_DEATH_EVENTS) || + (utrace->death && + ((old_flags & ~events) & _UTRACE_DEATH_EVENTS)) || + (utrace->reap && ((old_flags & ~events) & UTRACE_EVENT(REAP))))) { + spin_unlock(&utrace->lock); + return -EALREADY; + } + + /* + * When setting these flags, it's essential that we really + * synchronize with exit_notify(). They cannot be set after + * exit_notify() takes the tasklist_lock. By holding the read + * lock here while setting the flags, we ensure that the calls + * to tracehook_notify_death() and tracehook_report_death() will + * see the new flags. This ensures that utrace_release_task() + * knows positively that utrace_report_death() will be called or + * that it won't. + */ + if ((events & ~old_utrace_flags) & _UTRACE_DEATH_EVENTS) { + read_lock(&tasklist_lock); + if (unlikely(target->exit_state)) { + read_unlock(&tasklist_lock); + spin_unlock(&utrace->lock); + return -EALREADY; + } + target->utrace_flags |= events; + read_unlock(&tasklist_lock); + } + + engine->flags = events | (engine->flags & ENGINE_STOP); + target->utrace_flags |= events; + + if ((events & UTRACE_EVENT_SYSCALL) && + !(old_utrace_flags & UTRACE_EVENT_SYSCALL)) + set_tsk_thread_flag(target, TIF_SYSCALL_TRACE); + + ret = 0; + if ((old_flags & ~events) && target != current && + !task_is_stopped_or_traced(target) && !target->exit_state) { + /* + * This barrier ensures that our engine->flags changes + * have hit before we examine utrace->reporting, + * pairing with the barrier in start_callback(). If + * @target has not yet hit finish_callback() to clear + * utrace->reporting, we might be in the middle of a + * callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_set_events); + +/* + * Asynchronously mark an engine as being detached. + * + * This must work while the target thread races with us doing + * start_callback(), defined below. It uses smp_rmb() between checking + * @engine->flags and using @engine->ops. Here we change @engine->ops + * first, then use smp_wmb() before changing @engine->flags. This ensures + * it can check the old flags before using the old ops, or check the old + * flags before using the new ops, or check the new flags before using the + * new ops, but can never check the new flags before using the old ops. + * Hence, utrace_detached_ops might be used with any old flags in place. + * It has report_quiesce() and report_reap() callbacks to handle all cases. + */ +static void mark_engine_detached(struct utrace_engine *engine) +{ + engine->ops = &utrace_detached_ops; + smp_wmb(); + engine->flags = UTRACE_EVENT(QUIESCE); +} + +/* + * Get @target to stop and return true if it is already stopped now. + * If we return false, it will make some event callback soonish. + * Called with @utrace locked. + */ +static bool utrace_do_stop(struct task_struct *target, struct utrace *utrace) +{ + if (task_is_stopped(target)) { + /* + * Stopped is considered quiescent; when it wakes up, it will + * go through utrace_finish_stop() before doing anything else. + */ + spin_lock_irq(&target->sighand->siglock); + if (likely(task_is_stopped(target))) + __set_task_state(target, TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); + } else if (utrace->resume > UTRACE_REPORT) { + utrace->resume = UTRACE_REPORT; + set_notify_resume(target); + } + + return task_is_traced(target); +} + +/* + * If the target is not dead it should not be in tracing + * stop any more. Wake it unless it's in job control stop. + */ +static void utrace_wakeup(struct task_struct *target, struct utrace *utrace) +{ + lockdep_assert_held(&utrace->lock); + spin_lock_irq(&target->sighand->siglock); + if (target->signal->flags & SIGNAL_STOP_STOPPED || + target->signal->group_stop_count) + target->state = TASK_STOPPED; + else + wake_up_state(target, __TASK_TRACED); + spin_unlock_irq(&target->sighand->siglock); +} + +/* + * This is called when there might be some detached engines on the list or + * some stale bits in @task->utrace_flags. Clean them up and recompute the + * flags. Returns true if we're now fully detached. + * + * Called with @utrace->lock held, returns with it released. + * After this returns, @utrace might be freed if everything detached. + */ +static bool utrace_reset(struct task_struct *task, struct utrace *utrace) + __releases(utrace->lock) +{ + struct utrace_engine *engine, *next; + unsigned long flags = 0; + LIST_HEAD(detached); + + splice_attaching(utrace); + + /* + * Update the set of events of interest from the union + * of the interests of the remaining tracing engines. + * For any engine marked detached, remove it from the list. + * We'll collect them on the detached list. + */ + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->ops == &utrace_detached_ops) { + engine->ops = NULL; + list_move(&engine->entry, &detached); + } else { + flags |= engine->flags | UTRACE_EVENT(REAP); + } + } + + if (task->exit_state) { + /* + * Once it's already dead, we never install any flags + * except REAP. When ->exit_state is set and events + * like DEATH are not set, then they never can be set. + * This ensures that utrace_release_task() knows + * positively that utrace_report_death() can never run. + */ + BUG_ON(utrace->death); + flags &= UTRACE_EVENT(REAP); + } else if (!(flags & UTRACE_EVENT_SYSCALL) && + test_tsk_thread_flag(task, TIF_SYSCALL_TRACE)) { + clear_tsk_thread_flag(task, TIF_SYSCALL_TRACE); + } + + if (!flags) { + /* + * No more engines, cleared out the utrace. + */ + utrace->resume = UTRACE_RESUME; + utrace->signal_handler = 0; + } + + /* + * If no more engines want it stopped, wake it up. + */ + if (task_is_traced(task) && !(flags & ENGINE_STOP)) + utrace_wakeup(task, utrace); + + /* + * In theory spin_lock() doesn't imply rcu_read_lock(). + * Once we clear ->utrace_flags this task_struct can go away + * because tracehook_prepare_release_task() path does not take + * utrace->lock when ->utrace_flags == 0. + */ + rcu_read_lock(); + task->utrace_flags = flags; + spin_unlock(&utrace->lock); + rcu_read_unlock(); + + put_detached_list(&detached); + + return !flags; +} + +void utrace_finish_stop(void) +{ + /* + * If we were task_is_traced() and then SIGKILL'ed, make + * sure we do nothing until the tracer drops utrace->lock. + */ + if (unlikely(__fatal_signal_pending(current))) { + struct utrace *utrace = task_utrace_struct(current); + spin_unlock_wait(&utrace->lock); + } +} + +/* + * Perform %UTRACE_STOP, i.e. block in TASK_TRACED until woken up. + * @task == current, @utrace == current->utrace, which is not locked. + * Return true if we were woken up by SIGKILL even though some utrace + * engine may still want us to stay stopped. + */ +static void utrace_stop(struct task_struct *task, struct utrace *utrace, + enum utrace_resume_action action) +{ +relock: + spin_lock(&utrace->lock); + + if (action < utrace->resume) { + /* + * Ensure a reporting pass when we're resumed. + */ + utrace->resume = action; + if (action == UTRACE_INTERRUPT) + set_thread_flag(TIF_SIGPENDING); + else + set_thread_flag(TIF_NOTIFY_RESUME); + } + + /* + * If the ENGINE_STOP bit is clear in utrace_flags, that means + * utrace_reset() ran after we processed some UTRACE_STOP return + * values from callbacks to get here. If all engines have detached + * or resumed us, we don't stop. This check doesn't require + * siglock, but it should follow the interrupt/report bookkeeping + * steps (this can matter for UTRACE_RESUME but not UTRACE_DETACH). + */ + if (unlikely(!(task->utrace_flags & ENGINE_STOP))) { + utrace_reset(task, utrace); + if (task->utrace_flags & ENGINE_STOP) + goto relock; + return; + } + + /* + * The siglock protects us against signals. As well as SIGKILL + * waking us up, we must synchronize with the signal bookkeeping + * for stop signals and SIGCONT. + */ + spin_lock_irq(&task->sighand->siglock); + + if (unlikely(__fatal_signal_pending(task))) { + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + return; + } + + __set_current_state(TASK_TRACED); + + /* + * If there is a group stop in progress, + * we must participate in the bookkeeping. + */ + if (unlikely(task->signal->group_stop_count) && + !--task->signal->group_stop_count) + task->signal->flags = SIGNAL_STOP_STOPPED; + + spin_unlock_irq(&task->sighand->siglock); + spin_unlock(&utrace->lock); + + /* + * If ptrace is among the reasons for this stop, do its + * notification now. This could not just be done in + * ptrace's own event report callbacks because it has to + * be done after we are in TASK_TRACED. This makes the + * synchronization with ptrace_do_wait() work right. + * + * It's only because of the bad old overloading of the do_wait() + * logic for handling ptrace stops that we need this special case + * here. One day we will clean up ptrace so it does not need to + * work this way. New things that are designed sensibly don't need + * a wakeup that synchronizes with tasklist_lock and ->state, so + * the proper utrace API does not try to support this weirdness. + */ + ptrace_notify_stop(task); + + schedule(); + + utrace_finish_stop(); + + /* + * While in TASK_TRACED, we were considered "frozen enough". + * Now that we woke up, it's crucial if we're supposed to be + * frozen that we freeze now before running anything substantial. + */ + try_to_freeze(); + + /* + * While we were in TASK_TRACED, complete_signal() considered + * us "uninterested" in signal wakeups. Now make sure our + * TIF_SIGPENDING state is correct for normal running. + */ + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); +} + +/* + * Called by release_task() with @reap set to true. + * Called by utrace_report_death() with @reap set to false. + * On reap, make report_reap callbacks and clean out @utrace + * unless still making callbacks. On death, update bookkeeping + * and handle the reap work if release_task() came in first. + */ +void utrace_maybe_reap(struct task_struct *target, struct utrace *utrace, + bool reap) +{ + struct utrace_engine *engine, *next; + + spin_lock(&utrace->lock); + + if (reap) { + /* + * If the target will do some final callbacks but hasn't + * finished them yet, we know because it clears these event + * bits after it's done. Instead of cleaning up here and + * requiring utrace_report_death() to cope with it, we + * delay the REAP report and the teardown until after the + * target finishes its death reports. + */ + utrace->reap = 1; + + if (target->utrace_flags & _UTRACE_DEATH_EVENTS) { + spin_unlock(&utrace->lock); + return; + } + } else { + /* + * After we unlock with this flag clear, any competing + * utrace_control/utrace_set_events calls know that we've + * finished our callbacks and any detach bookkeeping. + */ + utrace->death = 0; + + if (!utrace->reap) { + /* + * We're just dead, not reaped yet. This will + * reset @target->utrace_flags so the later call + * with @reap set won't hit the check above. + */ + utrace_reset(target, utrace); + return; + } + } + + /* + * utrace_add_engine() checks ->utrace_flags != 0. + * Since @utrace->reap is set, nobody can set or clear + * UTRACE_EVENT(REAP) in @engine->flags or change + * @engine->ops, and nobody can change @utrace->attached. + */ + target->utrace_flags = 0; + splice_attaching(utrace); + spin_unlock(&utrace->lock); + + list_for_each_entry_safe(engine, next, &utrace->attached, entry) { + if (engine->flags & UTRACE_EVENT(REAP)) + engine->ops->report_reap(engine, target); + + engine->ops = NULL; + engine->flags = 0; + list_del_init(&engine->entry); + + utrace_engine_put(engine); + } +} + +/* + * You can't do anything to a dead task but detach it. + * If release_task() has been called, you can't do that. + * + * On the exit path, DEATH and QUIESCE event bits are set only + * before utrace_report_death() has taken the lock. At that point, + * the death report will come soon, so disallow detach until it's + * done. This prevents us from racing with it detaching itself. + * + * Called only when @target->exit_state is nonzero. + */ +static inline int utrace_control_dead(struct task_struct *target, + struct utrace *utrace, + enum utrace_resume_action action) +{ + lockdep_assert_held(&utrace->lock); + + if (action != UTRACE_DETACH || unlikely(utrace->reap)) + return -ESRCH; + + if (unlikely(utrace->death)) + /* + * We have already started the death report. We can't + * prevent the report_death and report_reap callbacks, + * so tell the caller they will happen. + */ + return -EALREADY; + + return 0; +} + +/** + * utrace_control - control a thread being traced by a tracing engine + * @target: thread to affect + * @engine: attached engine to affect + * @action: &enum utrace_resume_action for thread to do + * + * This is how a tracing engine asks a traced thread to do something. + * This call is controlled by the @action argument, which has the + * same meaning as the &enum utrace_resume_action value returned by + * event reporting callbacks. + * + * If @target is already dead (@target->exit_state nonzero), + * all actions except %UTRACE_DETACH fail with -%ESRCH. + * + * The following sections describe each option for the @action argument. + * + * UTRACE_DETACH: + * + * After this, the @engine data structure is no longer accessible, + * and the thread might be reaped. The thread will start running + * again if it was stopped and no longer has any attached engines + * that want it stopped. + * + * If the @report_reap callback may already have begun, this fails + * with -%ESRCH. If the @report_death callback may already have + * begun, this fails with -%EALREADY. + * + * If @target is not already stopped, then a callback to this engine + * might be in progress or about to start on another CPU. If so, + * then this returns -%EINPROGRESS; the detach happens as soon as + * the pending callback is finished. To synchronize after an + * -%EINPROGRESS return, see utrace_barrier(). + * + * If @target is properly stopped before utrace_control() is called, + * then after successful return it's guaranteed that no more callbacks + * to the @engine->ops vector will be made. + * + * The only exception is %SIGKILL (and exec or group-exit by another + * thread in the group), which can cause asynchronous @report_death + * and/or @report_reap callbacks even when %UTRACE_STOP was used. + * (In that event, this fails with -%ESRCH or -%EALREADY, see above.) + * + * UTRACE_STOP: + * + * This asks that @target stop running. This returns 0 only if + * @target is already stopped, either for tracing or for job + * control. Then @target will remain stopped until another + * utrace_control() call is made on @engine; @target can be woken + * only by %SIGKILL (or equivalent, such as exec or termination by + * another thread in the same thread group). + * + * This returns -%EINPROGRESS if @target is not already stopped. + * Then the effect is like %UTRACE_REPORT. A @report_quiesce or + * @report_signal callback will be made soon. Your callback can + * then return %UTRACE_STOP to keep @target stopped. + * + * This does not interrupt system calls in progress, including ones + * that sleep for a long time. For that, use %UTRACE_INTERRUPT. + * To interrupt system calls and then keep @target stopped, your + * @report_signal callback can return %UTRACE_STOP. + * + * UTRACE_RESUME: + * + * Just let @target continue running normally, reversing the effect + * of a previous %UTRACE_STOP. If another engine is keeping @target + * stopped, then it remains stopped until all engines let it resume. + * If @target was not stopped, this has no effect. + * + * UTRACE_REPORT: + * + * This is like %UTRACE_RESUME, but also ensures that there will be + * a @report_quiesce or @report_signal callback made soon. If + * @target had been stopped, then there will be a callback before it + * resumes running normally. If another engine is keeping @target + * stopped, then there might be no callbacks until all engines let + * it resume. + * + * Since this is meaningless unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_INTERRUPT: + * + * This is like %UTRACE_REPORT, but ensures that @target will make a + * @report_signal callback before it resumes or delivers signals. + * If @target was in a system call or about to enter one, work in + * progress will be interrupted as if by %SIGSTOP. If another + * engine is keeping @target stopped, then there might be no + * callbacks until all engines let it resume. + * + * This gives @engine an opportunity to introduce a forced signal + * disposition via its @report_signal callback. + * + * UTRACE_SINGLESTEP: + * + * It's invalid to use this unless arch_has_single_step() returned true. + * This is like %UTRACE_RESUME, but resumes for one user instruction only. + * + * Note that passing %UTRACE_SINGLESTEP or %UTRACE_BLOCKSTEP to + * utrace_control() or returning it from an event callback alone does + * not necessarily ensure that stepping will be enabled. If there are + * more callbacks made to any engine before returning to user mode, + * then the resume action is chosen only by the last set of callbacks. + * To be sure, enable %UTRACE_EVENT(%QUIESCE) and look for the + * @report_quiesce callback with a zero event mask, or the + * @report_signal callback with %UTRACE_SIGNAL_REPORT. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * UTRACE_BLOCKSTEP: + * + * It's invalid to use this unless arch_has_block_step() returned true. + * This is like %UTRACE_SINGLESTEP, but resumes for one whole basic + * block of user instructions. + * + * Since this is not robust unless @report_quiesce callbacks will + * be made, it returns -%EINVAL if @engine lacks %UTRACE_EVENT(%QUIESCE). + * + * %UTRACE_BLOCKSTEP devolves to %UTRACE_SINGLESTEP when another + * tracing engine is using %UTRACE_SINGLESTEP at the same time. + */ +int utrace_control(struct task_struct *target, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + struct utrace *utrace; + bool reset; + int ret; + + if (unlikely(action >= UTRACE_RESUME_MAX)) { + WARN(1, "invalid action argument to utrace_control()!"); + return -EINVAL; + } + + /* + * This is a sanity check for a programming error in the caller. + * Their request can only work properly in all cases by relying on + * a follow-up callback, but they didn't set one up! This check + * doesn't do locking, but it shouldn't matter. The caller has to + * be synchronously sure the callback is set up to be operating the + * interface properly. + */ + if (action >= UTRACE_REPORT && action < UTRACE_RESUME && + unlikely(!(engine->flags & UTRACE_EVENT(QUIESCE)))) { + WARN(1, "utrace_control() with no QUIESCE callback in place!"); + return -EINVAL; + } + + utrace = get_utrace_lock(target, engine, true); + if (unlikely(IS_ERR(utrace))) + return PTR_ERR(utrace); + + reset = task_is_traced(target); + ret = 0; + + /* + * ->exit_state can change under us, this doesn't matter. + * We do not care about ->exit_state in fact, but we do + * care about ->reap and ->death. If either flag is set, + * we must also see ->exit_state != 0. + */ + if (unlikely(target->exit_state)) { + ret = utrace_control_dead(target, utrace, action); + if (ret) { + spin_unlock(&utrace->lock); + return ret; + } + reset = true; + } + + switch (action) { + case UTRACE_STOP: + mark_engine_wants_stop(target, engine); + if (!reset && !utrace_do_stop(target, utrace)) + ret = -EINPROGRESS; + reset = false; + break; + + case UTRACE_DETACH: + if (engine_wants_stop(engine)) + target->utrace_flags &= ~ENGINE_STOP; + mark_engine_detached(engine); + reset = reset || utrace_do_stop(target, utrace); + if (!reset) { + /* + * As in utrace_set_events(), this barrier ensures + * that our engine->flags changes have hit before we + * examine utrace->reporting, pairing with the barrier + * in start_callback(). If @target has not yet hit + * finish_callback() to clear utrace->reporting, we + * might be in the middle of a callback to @engine. + */ + smp_mb(); + if (utrace->reporting == engine) + ret = -EINPROGRESS; + } + break; + + case UTRACE_RESUME: + /* + * This and all other cases imply resuming if stopped. + * There might not be another report before it just + * resumes, so make sure single-step is not left set. + */ + clear_engine_wants_stop(engine); + if (likely(reset)) + user_disable_single_step(target); + break; + + case UTRACE_BLOCKSTEP: + /* + * Resume from stopped, step one block. + * We fall through to treat it like UTRACE_SINGLESTEP. + */ + if (unlikely(!arch_has_block_step())) { + WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); + action = UTRACE_SINGLESTEP; + } + + case UTRACE_SINGLESTEP: + /* + * Resume from stopped, step one instruction. + * We fall through to the UTRACE_REPORT case. + */ + if (unlikely(!arch_has_single_step())) { + WARN(1, + "UTRACE_SINGLESTEP when !arch_has_single_step()"); + reset = false; + ret = -EOPNOTSUPP; + break; + } + + case UTRACE_REPORT: + /* + * Make the thread call tracehook_notify_resume() soon. + * But don't bother if it's already been interrupted. + * In that case, utrace_get_signal() will be reporting soon. + */ + clear_engine_wants_stop(engine); + if (action < utrace->resume) { + utrace->resume = action; + set_notify_resume(target); + } + break; + + case UTRACE_INTERRUPT: + /* + * Make the thread call tracehook_get_signal() soon. + */ + clear_engine_wants_stop(engine); + if (utrace->resume == UTRACE_INTERRUPT) + break; + utrace->resume = UTRACE_INTERRUPT; + + /* + * If it's not already stopped, interrupt it now. We need + * the siglock here in case it calls recalc_sigpending() + * and clears its own TIF_SIGPENDING. By taking the lock, + * we've serialized any later recalc_sigpending() after our + * setting of utrace->resume to force it on. + */ + if (reset) { + /* + * This is really just to keep the invariant that + * TIF_SIGPENDING is set with UTRACE_INTERRUPT. + * When it's stopped, we know it's always going + * through utrace_get_signal() and will recalculate. + */ + set_tsk_thread_flag(target, TIF_SIGPENDING); + } else { + struct sighand_struct *sighand; + unsigned long irqflags; + sighand = lock_task_sighand(target, &irqflags); + if (likely(sighand)) { + signal_wake_up(target, 0); + unlock_task_sighand(target, &irqflags); + } + } + break; + + default: + BUG(); /* We checked it on entry. */ + } + + /* + * Let the thread resume running. If it's not stopped now, + * there is nothing more we need to do. + */ + if (reset) + utrace_reset(target, utrace); + else + spin_unlock(&utrace->lock); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_control); + +/** + * utrace_barrier - synchronize with simultaneous tracing callbacks + * @target: thread to affect + * @engine: engine to affect (can be detached) + * + * This blocks while @target might be in the midst of making a callback to + * @engine. It can be interrupted by signals and will return -%ERESTARTSYS. + * A return value of zero means no callback from @target to @engine was + * in progress. Any effect of its return value (such as %UTRACE_STOP) has + * already been applied to @engine. + * + * It's not necessary to keep the @target pointer alive for this call. + * It's only necessary to hold a ref on @engine. This will return + * safely even if @target has been reaped and has no task refs. + * + * A successful return from utrace_barrier() guarantees its ordering + * with respect to utrace_set_events() and utrace_control() calls. If + * @target was not properly stopped, event callbacks just disabled might + * still be in progress; utrace_barrier() waits until there is no chance + * an unwanted callback can be in progress. + */ +int utrace_barrier(struct task_struct *target, struct utrace_engine *engine) +{ + struct utrace *utrace; + int ret = -ERESTARTSYS; + + if (unlikely(target == current)) + return 0; + + do { + utrace = get_utrace_lock(target, engine, false); + if (unlikely(IS_ERR(utrace))) { + ret = PTR_ERR(utrace); + if (ret != -ERESTARTSYS) + break; + } else { + /* + * All engine state changes are done while + * holding the lock, i.e. before we get here. + * Since we have the lock, we only need to + * worry about @target making a callback. + * When it has entered start_callback() but + * not yet gotten to finish_callback(), we + * will see utrace->reporting == @engine. + * When @target doesn't take the lock, it uses + * barriers to order setting utrace->reporting + * before it examines the engine state. + */ + if (utrace->reporting != engine) + ret = 0; + spin_unlock(&utrace->lock); + if (!ret) + break; + } + schedule_timeout_interruptible(1); + } while (!signal_pending(current)); + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_barrier); + +/* + * This is local state used for reporting loops, perhaps optimized away. + */ +struct utrace_report { + u32 result; + enum utrace_resume_action action; + enum utrace_resume_action resume_action; + bool detaches; + bool spurious; +}; + +#define INIT_REPORT(var) \ + struct utrace_report var = { \ + .action = UTRACE_RESUME, \ + .resume_action = UTRACE_RESUME, \ + .spurious = true \ + } + +/* + * We are now making the report, so clear the flag saying we need one. + * When there is a new attach, ->pending_attach is set just so we will + * know to do splice_attaching() here before the callback loop. + */ +static enum utrace_resume_action start_report(struct utrace *utrace) +{ + enum utrace_resume_action resume = utrace->resume; + if (utrace->pending_attach || + (resume > UTRACE_INTERRUPT && resume < UTRACE_RESUME)) { + spin_lock(&utrace->lock); + splice_attaching(utrace); + resume = utrace->resume; + if (resume > UTRACE_INTERRUPT) + utrace->resume = UTRACE_RESUME; + spin_unlock(&utrace->lock); + } + return resume; +} + +static inline void finish_report_reset(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + if (unlikely(report->spurious || report->detaches)) { + spin_lock(&utrace->lock); + if (utrace_reset(task, utrace)) + report->action = UTRACE_RESUME; + } +} + +/* + * Complete a normal reporting pass, pairing with a start_report() call. + * This handles any UTRACE_DETACH or UTRACE_REPORT or UTRACE_INTERRUPT + * returns from engine callbacks. If @will_not_stop is true and any + * engine's last callback used UTRACE_STOP, we do UTRACE_REPORT here to + * ensure we stop before user mode. If there were no callbacks made, it + * will recompute @task->utrace_flags to avoid another false-positive. + */ +static void finish_report(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, bool will_not_stop) +{ + enum utrace_resume_action resume = report->action; + + if (resume == UTRACE_STOP) + resume = will_not_stop ? UTRACE_REPORT : UTRACE_RESUME; + + if (resume < utrace->resume) { + spin_lock(&utrace->lock); + utrace->resume = resume; + if (resume == UTRACE_INTERRUPT) + set_tsk_thread_flag(task, TIF_SIGPENDING); + else + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + spin_unlock(&utrace->lock); + } + + finish_report_reset(task, utrace, report); +} + +static void finish_callback_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + enum utrace_resume_action action) +{ + if (action == UTRACE_DETACH) { + /* + * By holding the lock here, we make sure that + * utrace_barrier() (really get_utrace_lock()) sees the + * effect of this detach. Otherwise utrace_barrier() could + * return 0 after this callback had returned UTRACE_DETACH. + * This way, a 0 return is an unambiguous indicator that any + * callback returning UTRACE_DETACH has indeed caused detach. + */ + spin_lock(&utrace->lock); + engine->ops = &utrace_detached_ops; + spin_unlock(&utrace->lock); + } + + /* + * If utrace_control() was used, treat that like UTRACE_DETACH here. + */ + if (engine->ops == &utrace_detached_ops) { + report->detaches = true; + return; + } + + if (action < report->action) + report->action = action; + + if (action != UTRACE_STOP) { + if (action < report->resume_action) + report->resume_action = action; + + if (engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + clear_engine_wants_stop(engine); + spin_unlock(&utrace->lock); + } + + return; + } + + if (!engine_wants_stop(engine)) { + spin_lock(&utrace->lock); + /* + * If utrace_control() came in and detached us + * before we got the lock, we must not stop now. + */ + if (unlikely(engine->ops == &utrace_detached_ops)) + report->detaches = true; + else + mark_engine_wants_stop(task, engine); + spin_unlock(&utrace->lock); + } +} + +/* + * Apply the return value of one engine callback to @report. + * Returns true if @engine detached and should not get any more callbacks. + */ +static bool finish_callback(struct task_struct *task, struct utrace *utrace, + struct utrace_report *report, + struct utrace_engine *engine, + u32 ret) +{ + report->result = ret & ~UTRACE_RESUME_MASK; + finish_callback_report(task, utrace, report, engine, + utrace_resume_action(ret)); + + /* + * Now that we have applied the effect of the return value, + * clear this so that utrace_barrier() can stop waiting. + * A subsequent utrace_control() can stop or resume @engine + * and know this was ordered after its callback's action. + * + * We don't need any barriers here because utrace_barrier() + * takes utrace->lock. If we touched engine->flags above, + * the lock guaranteed this change was before utrace_barrier() + * examined utrace->reporting. + */ + utrace->reporting = NULL; + + /* + * We've just done an engine callback. These are allowed to sleep, + * though all well-behaved ones restrict that to blocking kalloc() + * or quickly-acquired mutex_lock() and the like. This is a good + * place to make sure tracing engines don't introduce too much + * latency under voluntary preemption. + */ + might_sleep(); + + return engine->ops == &utrace_detached_ops; +} + +/* + * Start the callbacks for @engine to consider @event (a bit mask). + * This makes the report_quiesce() callback first. If @engine wants + * a specific callback for @event, we return the ops vector to use. + * If not, we return NULL. The return value from the ops->callback + * function called should be passed to finish_callback(). + */ +static const struct utrace_engine_ops *start_callback( + struct utrace *utrace, struct utrace_report *report, + struct utrace_engine *engine, struct task_struct *task, + unsigned long event) +{ + const struct utrace_engine_ops *ops; + unsigned long want; + + /* + * This barrier ensures that we've set utrace->reporting before + * we examine engine->flags or engine->ops. utrace_barrier() + * relies on this ordering to indicate that the effect of any + * utrace_control() and utrace_set_events() calls is in place + * by the time utrace->reporting can be seen to be NULL. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(). + * It makes sure that we never see the old ops vector with + * the new flags, in case the original vector had no report_quiesce. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if (want & UTRACE_EVENT(QUIESCE)) { + if (finish_callback(task, utrace, report, engine, + (*ops->report_quiesce)(report->action, + engine, event))) + return NULL; + + /* + * finish_callback() reset utrace->reporting after the + * quiesce callback. Now we set it again (as above) + * before re-examining engine->flags, which could have + * been changed synchronously by ->report_quiesce or + * asynchronously by utrace_control() or utrace_set_events(). + */ + utrace->reporting = engine; + smp_mb(); + want = engine->flags; + } + + if (want & ENGINE_STOP) + report->action = UTRACE_STOP; + + if (want & event) { + report->spurious = false; + return ops; + } + + utrace->reporting = NULL; + return NULL; +} + +/* + * Do a normal reporting pass for engines interested in @event. + * @callback is the name of the member in the ops vector, and remaining + * args are the extras it takes after the standard three args. + */ +#define REPORT_CALLBACKS(rev, task, utrace, report, event, callback, ...) \ + do { \ + struct utrace_engine *engine; \ + const struct utrace_engine_ops *ops; \ + list_for_each_entry##rev(engine, &utrace->attached, entry) { \ + ops = start_callback(utrace, report, engine, task, \ + event); \ + if (!ops) \ + continue; \ + finish_callback(task, utrace, report, engine, \ + (*ops->callback)(__VA_ARGS__)); \ + } \ + } while (0) +#define REPORT(task, utrace, report, event, callback, ...) \ + do { \ + start_report(utrace); \ + REPORT_CALLBACKS(, task, utrace, report, event, callback, \ + (report)->action, engine, ## __VA_ARGS__); \ + finish_report(task, utrace, report, true); \ + } while (0) + +/* + * Called iff UTRACE_EVENT(EXEC) flag is set. + */ +void utrace_report_exec(struct linux_binfmt *fmt, struct linux_binprm *bprm, + struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(EXEC), + report_exec, fmt, bprm, regs); +} + +static u32 do_report_syscall_entry(struct pt_regs *regs, + struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report, + u32 resume_report) +{ + start_report(utrace); + REPORT_CALLBACKS(_reverse, task, utrace, report, + UTRACE_EVENT(SYSCALL_ENTRY), report_syscall_entry, + resume_report | report->result | report->action, + engine, regs); + finish_report(task, utrace, report, false); + + if (report->action != UTRACE_STOP) + return 0; + + utrace_stop(task, utrace, report->resume_action); + + if (fatal_signal_pending(task)) { + /* + * We are continuing despite UTRACE_STOP because of a + * SIGKILL. Don't let the system call actually proceed. + */ + report->result = UTRACE_SYSCALL_ABORT; + } else if (utrace->resume <= UTRACE_REPORT) { + /* + * If we've been asked for another report after our stop, + * go back to report (and maybe stop) again before we run + * the system call. The second (and later) reports are + * marked with the UTRACE_SYSCALL_RESUMED flag so that + * engines know this is a second report at the same + * entry. This gives them the chance to examine the + * registers anew after they might have been changed + * while we were stopped. + */ + report->detaches = false; + report->spurious = true; + report->action = report->resume_action = UTRACE_RESUME; + return UTRACE_SYSCALL_RESUMED; + } + + return 0; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_ENTRY) flag is set. + * Return true to prevent the system call. + */ +bool utrace_report_syscall_entry(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + u32 resume_report = 0; + + do { + resume_report = do_report_syscall_entry(regs, task, utrace, + &report, resume_report); + } while (resume_report); + + return utrace_syscall_action(report.result) == UTRACE_SYSCALL_ABORT; +} + +/* + * Called iff UTRACE_EVENT(SYSCALL_EXIT) flag is set. + */ +void utrace_report_syscall_exit(struct pt_regs *regs) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + REPORT(task, utrace, &report, UTRACE_EVENT(SYSCALL_EXIT), + report_syscall_exit, regs); +} + +/* + * Called iff UTRACE_EVENT(CLONE) flag is set. + * This notification call blocks the wake_up_new_task call on the child. + * So we must not quiesce here. tracehook_report_clone_complete will do + * a quiescence check momentarily. + */ +void utrace_report_clone(unsigned long clone_flags, struct task_struct *child) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + /* + * We don't use the REPORT() macro here, because we need + * to clear utrace->cloning before finish_report(). + * After finish_report(), utrace can be a stale pointer + * in cases when report.action is still UTRACE_RESUME. + */ + start_report(utrace); + utrace->cloning = child; + + REPORT_CALLBACKS(, task, utrace, &report, + UTRACE_EVENT(CLONE), report_clone, + report.action, engine, clone_flags, child); + + utrace->cloning = NULL; + finish_report(task, utrace, &report, !(clone_flags & CLONE_VFORK)); + + /* + * For a vfork, we will go into an uninterruptible block waiting + * for the child. We need UTRACE_STOP to happen before this, not + * after. For CLONE_VFORK, utrace_finish_vfork() will be called. + */ + if (report.action == UTRACE_STOP && (clone_flags & CLONE_VFORK)) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 1; + spin_unlock(&utrace->lock); + } +} + +/* + * We're called after utrace_report_clone() for a CLONE_VFORK. + * If UTRACE_STOP was left from the clone report, we stop here. + * After this, we'll enter the uninterruptible wait_for_completion() + * waiting for the child. + */ +void utrace_finish_vfork(struct task_struct *task) +{ + struct utrace *utrace = task_utrace_struct(task); + + if (utrace->vfork_stop) { + spin_lock(&utrace->lock); + utrace->vfork_stop = 0; + spin_unlock(&utrace->lock); + utrace_stop(task, utrace, UTRACE_RESUME); /* XXX */ + } +} + +/* + * Called iff UTRACE_EVENT(JCTL) flag is set. + * + * Called with siglock held. + */ +void utrace_report_jctl(int notify, int what) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + + spin_unlock_irq(&task->sighand->siglock); + + REPORT(task, utrace, &report, UTRACE_EVENT(JCTL), + report_jctl, what, notify); + + spin_lock_irq(&task->sighand->siglock); +} + +/* + * Called iff UTRACE_EVENT(EXIT) flag is set. + */ +void utrace_report_exit(long *exit_code) +{ + struct task_struct *task = current; + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + long orig_code = *exit_code; + + REPORT(task, utrace, &report, UTRACE_EVENT(EXIT), + report_exit, orig_code, exit_code); + + if (report.action == UTRACE_STOP) + utrace_stop(task, utrace, report.resume_action); +} + +/* + * Called iff UTRACE_EVENT(DEATH) or UTRACE_EVENT(QUIESCE) flag is set. + * + * It is always possible that we are racing with utrace_release_task here. + * For this reason, utrace_release_task checks for the event bits that get + * us here, and delays its cleanup for us to do. + */ +void utrace_report_death(struct task_struct *task, struct utrace *utrace, + bool group_dead, int signal) +{ + INIT_REPORT(report); + + BUG_ON(!task->exit_state); + + /* + * We are presently considered "quiescent"--which is accurate + * inasmuch as we won't run any more user instructions ever again. + * But for utrace_control and utrace_set_events to be robust, they + * must be sure whether or not we will run any more callbacks. If + * a call comes in before we do, taking the lock here synchronizes + * us so we don't run any callbacks just disabled. Calls that come + * in while we're running the callbacks will see the exit.death + * flag and know that we are not yet fully quiescent for purposes + * of detach bookkeeping. + */ + spin_lock(&utrace->lock); + BUG_ON(utrace->death); + utrace->death = 1; + utrace->resume = UTRACE_RESUME; + splice_attaching(utrace); + spin_unlock(&utrace->lock); + + REPORT_CALLBACKS(, task, utrace, &report, UTRACE_EVENT(DEATH), + report_death, engine, group_dead, signal); + + utrace_maybe_reap(task, utrace, false); +} + +/* + * Finish the last reporting pass before returning to user mode. + */ +static void finish_resume_report(struct task_struct *task, + struct utrace *utrace, + struct utrace_report *report) +{ + finish_report_reset(task, utrace, report); + + switch (report->action) { + case UTRACE_STOP: + utrace_stop(task, utrace, report->resume_action); + break; + + case UTRACE_INTERRUPT: + if (!signal_pending(task)) + set_tsk_thread_flag(task, TIF_SIGPENDING); + break; + + case UTRACE_BLOCKSTEP: + if (likely(arch_has_block_step())) { + user_enable_block_step(task); + break; + } + + /* + * This means some callback is to blame for failing + * to check arch_has_block_step() itself. Warn and + * then fall through to treat it as SINGLESTEP. + */ + WARN(1, "UTRACE_BLOCKSTEP when !arch_has_block_step()"); + + case UTRACE_SINGLESTEP: + if (likely(arch_has_single_step())) { + user_enable_single_step(task); + } else { + /* + * This means some callback is to blame for failing + * to check arch_has_single_step() itself. Spew + * about it so the loser will fix his module. + */ + WARN(1, + "UTRACE_SINGLESTEP when !arch_has_single_step()"); + } + break; + + case UTRACE_REPORT: + case UTRACE_RESUME: + default: + user_disable_single_step(task); + break; + } +} + +/* + * This is called when TIF_NOTIFY_RESUME had been set (and is now clear). + * We are close to user mode, and this is the place to report or stop. + * When we return, we're going to user mode or into the signals code. + */ +void utrace_resume(struct task_struct *task, struct pt_regs *regs) +{ + struct utrace *utrace = task_utrace_struct(task); + INIT_REPORT(report); + struct utrace_engine *engine; + + /* + * Some machines get here with interrupts disabled. The same arch + * code path leads to calling into get_signal_to_deliver(), which + * implicitly reenables them by virtue of spin_unlock_irq. + */ + local_irq_enable(); + + /* + * If this flag is still set it's because there was a signal + * handler setup done but no report_signal following it. Clear + * the flag before we get to user so it doesn't confuse us later. + */ + if (unlikely(utrace->signal_handler)) { + spin_lock(&utrace->lock); + utrace->signal_handler = 0; + spin_unlock(&utrace->lock); + } + + /* + * Update our bookkeeping even if there are no callbacks made here. + */ + report.action = start_report(utrace); + + switch (report.action) { + case UTRACE_RESUME: + /* + * Anything we might have done was already handled by + * utrace_get_signal(), or this is an entirely spurious + * call. (The arch might use TIF_NOTIFY_RESUME for other + * purposes as well as calling us.) + */ + return; + case UTRACE_REPORT: + if (unlikely(!(task->utrace_flags & UTRACE_EVENT(QUIESCE)))) + break; + /* + * Do a simple reporting pass, with no specific + * callback after report_quiesce. + */ + report.action = UTRACE_RESUME; + list_for_each_entry(engine, &utrace->attached, entry) + start_callback(utrace, &report, engine, task, 0); + break; + default: + /* + * Even if this report was truly spurious, there is no need + * for utrace_reset() now. TIF_NOTIFY_RESUME was already + * cleared--it doesn't stay spuriously set. + */ + report.spurious = false; + break; + } + + /* + * Finish the report and either stop or get ready to resume. + * If utrace->resume was not UTRACE_REPORT, this applies its + * effect now (i.e. step or interrupt). + */ + finish_resume_report(task, utrace, &report); +} + +/* + * Return true if current has forced signal_pending(). + * + * This is called only when current->utrace_flags is nonzero, so we know + * that current->utrace must be set. It's not inlined in tracehook.h + * just so that struct utrace can stay opaque outside this file. + */ +bool utrace_interrupt_pending(void) +{ + return task_utrace_struct(current)->resume == UTRACE_INTERRUPT; +} + +/* + * Take the siglock and push @info back on our queue. + * Returns with @task->sighand->siglock held. + */ +static void push_back_signal(struct task_struct *task, siginfo_t *info) + __acquires(task->sighand->siglock) +{ + struct sigqueue *q; + + if (unlikely(!info->si_signo)) { /* Oh, a wise guy! */ + spin_lock_irq(&task->sighand->siglock); + return; + } + + q = sigqueue_alloc(); + if (likely(q)) { + q->flags = 0; + copy_siginfo(&q->info, info); + } + + spin_lock_irq(&task->sighand->siglock); + + sigaddset(&task->pending.signal, info->si_signo); + if (likely(q)) + list_add(&q->list, &task->pending.list); + + set_tsk_thread_flag(task, TIF_SIGPENDING); +} + +/* + * This is the hook from the signals code, called with the siglock held. + * Here is the ideal place to stop. We also dequeue and intercept signals. + */ +int utrace_get_signal(struct task_struct *task, struct pt_regs *regs, + siginfo_t *info, struct k_sigaction *return_ka) + __releases(task->sighand->siglock) + __acquires(task->sighand->siglock) +{ + struct utrace *utrace; + struct k_sigaction *ka; + INIT_REPORT(report); + struct utrace_engine *engine; + const struct utrace_engine_ops *ops; + unsigned long event, want; + u32 ret; + int signr; + + utrace = task_utrace_struct(task); + if (utrace->resume < UTRACE_RESUME || + utrace->pending_attach || utrace->signal_handler) { + enum utrace_resume_action resume; + + /* + * We've been asked for an explicit report before we + * even check for pending signals. + */ + + spin_unlock_irq(&task->sighand->siglock); + + spin_lock(&utrace->lock); + + splice_attaching(utrace); + + report.result = utrace->signal_handler ? + UTRACE_SIGNAL_HANDLER : UTRACE_SIGNAL_REPORT; + utrace->signal_handler = 0; + + resume = utrace->resume; + utrace->resume = UTRACE_RESUME; + + spin_unlock(&utrace->lock); + + /* + * Make sure signal_pending() only returns true + * if there are real signals pending. + */ + if (signal_pending(task)) { + spin_lock_irq(&task->sighand->siglock); + recalc_sigpending(); + spin_unlock_irq(&task->sighand->siglock); + } + + if (resume > UTRACE_REPORT) { + /* + * We only got here to process utrace->resume. + * Despite no callbacks, this report is not spurious. + */ + report.action = resume; + report.spurious = false; + finish_resume_report(task, utrace, &report); + return -1; + } else if (!(task->utrace_flags & UTRACE_EVENT(QUIESCE))) { + /* + * We only got here to clear utrace->signal_handler. + */ + return -1; + } + + /* + * Do a reporting pass for no signal, just for EVENT(QUIESCE). + * The engine callbacks can fill in *info and *return_ka. + * We'll pass NULL for the @orig_ka argument to indicate + * that there was no original signal. + */ + event = 0; + ka = NULL; + memset(return_ka, 0, sizeof *return_ka); + } else if (!(task->utrace_flags & UTRACE_EVENT_SIGNAL_ALL) || + unlikely(task->signal->group_stop_count)) { + /* + * If no engine is interested in intercepting signals or + * we must stop, let the caller just dequeue them normally + * or participate in group-stop. + */ + return 0; + } else { + /* + * Steal the next signal so we can let tracing engines + * examine it. From the signal number and sigaction, + * determine what normal delivery would do. If no + * engine perturbs it, we'll do that by returning the + * signal number after setting *return_ka. + */ + signr = dequeue_signal(task, &task->blocked, info); + if (signr == 0) + return signr; + BUG_ON(signr != info->si_signo); + + ka = &task->sighand->action[signr - 1]; + *return_ka = *ka; + + /* + * We are never allowed to interfere with SIGKILL. + * Just punt after filling in *return_ka for our caller. + */ + if (signr == SIGKILL) + return signr; + + if (ka->sa.sa_handler == SIG_IGN) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (ka->sa.sa_handler != SIG_DFL) { + event = UTRACE_EVENT(SIGNAL); + report.result = UTRACE_SIGNAL_DELIVER; + } else if (sig_kernel_coredump(signr)) { + event = UTRACE_EVENT(SIGNAL_CORE); + report.result = UTRACE_SIGNAL_CORE; + } else if (sig_kernel_ignore(signr)) { + event = UTRACE_EVENT(SIGNAL_IGN); + report.result = UTRACE_SIGNAL_IGN; + } else if (signr == SIGSTOP) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_STOP; + } else if (sig_kernel_stop(signr)) { + event = UTRACE_EVENT(SIGNAL_STOP); + report.result = UTRACE_SIGNAL_TSTP; + } else { + event = UTRACE_EVENT(SIGNAL_TERM); + report.result = UTRACE_SIGNAL_TERM; + } + + /* + * Now that we know what event type this signal is, we + * can short-circuit if no engines care about those. + */ + if ((task->utrace_flags & (event | UTRACE_EVENT(QUIESCE))) == 0) + return signr; + + /* + * We have some interested engines, so tell them about + * the signal and let them change its disposition. + */ + spin_unlock_irq(&task->sighand->siglock); + } + + /* + * This reporting pass chooses what signal disposition we'll act on. + */ + list_for_each_entry(engine, &utrace->attached, entry) { + /* + * See start_callback() comment about this barrier. + */ + utrace->reporting = engine; + smp_mb(); + + /* + * This pairs with the barrier in mark_engine_detached(), + * see start_callback() comments. + */ + want = engine->flags; + smp_rmb(); + ops = engine->ops; + + if ((want & (event | UTRACE_EVENT(QUIESCE))) == 0) { + utrace->reporting = NULL; + continue; + } + + if (ops->report_signal) + ret = (*ops->report_signal)( + report.result | report.action, engine, + regs, info, ka, return_ka); + else + ret = (report.result | (*ops->report_quiesce)( + report.action, engine, event)); + + /* + * Avoid a tight loop reporting again and again if some + * engine is too stupid. + */ + switch (utrace_resume_action(ret)) { + default: + break; + case UTRACE_INTERRUPT: + case UTRACE_REPORT: + ret = (ret & ~UTRACE_RESUME_MASK) | UTRACE_RESUME; + break; + } + + finish_callback(task, utrace, &report, engine, ret); + } + + /* + * We express the chosen action to the signals code in terms + * of a representative signal whose default action does it. + * Our caller uses our return value (signr) to decide what to + * do, but uses info->si_signo as the signal number to report. + */ + switch (utrace_signal_action(report.result)) { + case UTRACE_SIGNAL_TERM: + signr = SIGTERM; + break; + + case UTRACE_SIGNAL_CORE: + signr = SIGQUIT; + break; + + case UTRACE_SIGNAL_STOP: + signr = SIGSTOP; + break; + + case UTRACE_SIGNAL_TSTP: + signr = SIGTSTP; + break; + + case UTRACE_SIGNAL_DELIVER: + signr = info->si_signo; + + if (return_ka->sa.sa_handler == SIG_DFL) { + /* + * We'll do signr's normal default action. + * For ignore, we'll fall through below. + * For stop/death, break locks and returns it. + */ + if (likely(signr) && !sig_kernel_ignore(signr)) + break; + } else if (return_ka->sa.sa_handler != SIG_IGN && + likely(signr)) { + /* + * Complete the bookkeeping after the report. + * The handler will run. If an engine wanted to + * stop or step, then make sure we do another + * report after signal handler setup. + */ + if (report.action != UTRACE_RESUME) + report.action = UTRACE_INTERRUPT; + finish_report(task, utrace, &report, true); + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + /* + * We do the SA_ONESHOT work here since the + * normal path will only touch *return_ka now. + */ + if (unlikely(return_ka->sa.sa_flags & SA_ONESHOT)) { + return_ka->sa.sa_flags &= ~SA_ONESHOT; + if (likely(valid_signal(signr))) { + ka = &task->sighand->action[signr - 1]; + ka->sa.sa_handler = SIG_DFL; + } + } + + return signr; + } + + /* Fall through for an ignored signal. */ + + case UTRACE_SIGNAL_IGN: + case UTRACE_SIGNAL_REPORT: + default: + /* + * If the signal is being ignored, then we are on the way + * directly back to user mode. We can stop here, or step, + * as in utrace_resume(), above. After we've dealt with that, + * our caller will relock and come back through here. + */ + finish_resume_report(task, utrace, &report); + + if (unlikely(fatal_signal_pending(task))) { + /* + * The only reason we woke up now was because of a + * SIGKILL. Don't do normal dequeuing in case it + * might get a signal other than SIGKILL. That would + * perturb the death state so it might differ from + * what the debugger would have allowed to happen. + * Instead, pluck out just the SIGKILL to be sure + * we'll die immediately with nothing else different + * from the quiescent state the debugger wanted us in. + */ + sigset_t sigkill_only; + siginitsetinv(&sigkill_only, sigmask(SIGKILL)); + spin_lock_irq(&task->sighand->siglock); + signr = dequeue_signal(task, &sigkill_only, info); + BUG_ON(signr != SIGKILL); + *return_ka = task->sighand->action[SIGKILL - 1]; + return signr; + } + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) { + push_back_signal(task, info); + spin_unlock_irq(&task->sighand->siglock); + } + + return -1; + } + + /* + * Complete the bookkeeping after the report. + * This sets utrace->resume if UTRACE_STOP was used. + */ + finish_report(task, utrace, &report, true); + + return_ka->sa.sa_handler = SIG_DFL; + + /* + * If this signal is fatal, si_signo gets through as exit_code. + * We can't allow a completely bogus value there or else core + * kernel code can freak out. (If an engine wants to control + * the exit_code value exactly, it can do so in report_exit.) + * We'll produce a big complaint in dmesg, but won't crash. + * That's nicer for debugging your utrace engine. + */ + if (unlikely(info->si_signo & 0x80)) { + WARN(1, "utrace engine left bogus si_signo value!"); + info->si_signo = SIGTRAP; + } + + if (unlikely(report.result & UTRACE_SIGNAL_HOLD)) + push_back_signal(task, info); + else + spin_lock_irq(&task->sighand->siglock); + + if (sig_kernel_stop(signr)) + task->signal->flags |= SIGNAL_STOP_DEQUEUED; + + return signr; +} + +/* + * This gets called after a signal handler has been set up. + * We set a flag so the next report knows it happened. + * If we're already stepping, make sure we do a report_signal. + * If not, make sure we get into utrace_resume() where we can + * clear the signal_handler flag before resuming. + */ +void utrace_signal_handler(struct task_struct *task, int stepping) +{ + struct utrace *utrace = task_utrace_struct(task); + + spin_lock(&utrace->lock); + + utrace->signal_handler = 1; + if (utrace->resume > UTRACE_INTERRUPT) { + if (stepping) { + utrace->resume = UTRACE_INTERRUPT; + set_tsk_thread_flag(task, TIF_SIGPENDING); + } else if (utrace->resume == UTRACE_RESUME) { + set_tsk_thread_flag(task, TIF_NOTIFY_RESUME); + } + } + + spin_unlock(&utrace->lock); +} + +/** + * utrace_prepare_examine - prepare to examine thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: temporary state, a &struct utrace_examiner pointer + * + * This call prepares to safely examine the thread @target using + * &struct user_regset calls, or direct access to thread-synchronous fields. + * + * When @target is current, this call is superfluous. When @target is + * another thread, it must be held stopped via %UTRACE_STOP by @engine. + * + * This call may block the caller until @target stays stopped, so it must + * be called only after the caller is sure @target is about to unschedule. + * This means a zero return from a utrace_control() call on @engine giving + * %UTRACE_STOP, or a report_quiesce() or report_signal() callback to + * @engine that used %UTRACE_STOP in its return value. + * + * Returns -%ESRCH if @target is dead or -%EINVAL if %UTRACE_STOP was + * not used. If @target has started running again despite %UTRACE_STOP + * (for %SIGKILL or a spurious wakeup), this call returns -%EAGAIN. + * + * When this call returns zero, it's safe to use &struct user_regset + * calls and task_user_regset_view() on @target and to examine some of + * its fields directly. When the examination is complete, a + * utrace_finish_examine() call must follow to check whether it was + * completed safely. + */ +int utrace_prepare_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->exit_state)) + ret = -ESRCH; + else { + exam->state = target->state; + if (unlikely(exam->state == TASK_RUNNING)) + ret = -EAGAIN; + else + get_task_struct(target); + } + rcu_read_unlock(); + + if (likely(!ret)) { + exam->ncsw = wait_task_inactive(target, exam->state); + put_task_struct(target); + if (unlikely(!exam->ncsw)) + ret = -EAGAIN; + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_prepare_examine); + +/** + * utrace_finish_examine - complete an examination of thread state + * @target: thread of interest, a &struct task_struct pointer + * @engine: engine pointer returned by utrace_attach_task() + * @exam: pointer passed to utrace_prepare_examine() call + * + * This call completes an examination on the thread @target begun by a + * paired utrace_prepare_examine() call with the same arguments that + * returned success (zero). + * + * When @target is current, this call is superfluous. When @target is + * another thread, this returns zero if @target has remained unscheduled + * since the paired utrace_prepare_examine() call returned zero. + * + * When this returns an error, any examination done since the paired + * utrace_prepare_examine() call is unreliable and the data extracted + * should be discarded. The error is -%EINVAL if @engine is not + * keeping @target stopped, or -%EAGAIN if @target woke up unexpectedly. + */ +int utrace_finish_examine(struct task_struct *target, + struct utrace_engine *engine, + struct utrace_examiner *exam) +{ + int ret = 0; + + if (unlikely(target == current)) + return 0; + + rcu_read_lock(); + if (unlikely(!engine_wants_stop(engine))) + ret = -EINVAL; + else if (unlikely(target->state != exam->state)) + ret = -EAGAIN; + else + get_task_struct(target); + rcu_read_unlock(); + + if (likely(!ret)) { + unsigned long ncsw = wait_task_inactive(target, exam->state); + if (unlikely(ncsw != exam->ncsw)) + ret = -EAGAIN; + put_task_struct(target); + } + + return ret; +} +EXPORT_SYMBOL_GPL(utrace_finish_examine); + +/* + * This is declared in linux/regset.h and defined in machine-dependent + * code. We put the export here to ensure no machine forgets it. + */ +EXPORT_SYMBOL_GPL(task_user_regset_view); + +/* + * Called with rcu_read_lock() held. + */ +void task_utrace_proc_status(struct seq_file *m, struct task_struct *p) +{ + seq_printf(m, "Utrace:\t%lx\n", p->utrace_flags); +} From roland at redhat.com Fri Dec 18 01:40:21 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Dec 2009 17:40:21 -0800 (PST) Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: Oleg Nesterov's message of Friday, 18 December 2009 01:56:50 +0100 <20091218005650.GA20667@redhat.com> References: <20091218005650.GA20667@redhat.com> Message-ID: <20091218014021.CB474135F@magilla.sf.frob.com> Comparing to the old (2.6.32) logic, I think it might be this (untested). I also note this is the sole use of get_si_code, seems like it should just be rolled in here. Thanks, Roland diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index 3339917..16a88f5 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -530,7 +530,6 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) { struct task_struct *tsk = current; unsigned long dr6; - int si_code; get_debugreg(dr6, 6); @@ -569,14 +568,15 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) * We already checked v86 mode above, so we can check for kernel mode * by just checking the CPL of CS. */ + dr6 = tsk->thread.debugreg6; if ((dr6 & DR_STEP) && !user_mode(regs)) { tsk->thread.debugreg6 &= ~DR_STEP; set_tsk_thread_flag(tsk, TIF_SINGLESTEP); regs->flags &= ~X86_EFLAGS_TF; + } else if (dr6 & (DR_STEP | DR_TRAP_BITS)) { + send_sigtrap(tsk, regs, error_code, get_si_code(dr6)); } - si_code = get_si_code(tsk->thread.debugreg6); - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) - send_sigtrap(tsk, regs, error_code, si_code); + preempt_conditional_cli(regs); return; From oleg at redhat.com Fri Dec 18 02:10:42 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 03:10:42 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218014021.CB474135F@magilla.sf.frob.com> References: <20091218005650.GA20667@redhat.com> <20091218014021.CB474135F@magilla.sf.frob.com> Message-ID: <20091218021042.GA508@redhat.com> On 12/17, Roland McGrath wrote: > > Comparing to the old (2.6.32) logic, I think it might be this (untested). > I also note this is the sole use of get_si_code, seems like it should > just be rolled in here. Well, it is too late for me to even try to read this patch ;) but... > @@ -569,14 +568,15 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) > * We already checked v86 mode above, so we can check for kernel mode > * by just checking the CPL of CS. > */ > + dr6 = tsk->thread.debugreg6; why? we have "tsk->thread.debugreg6 = dr6" above > if ((dr6 & DR_STEP) && !user_mode(regs)) { > tsk->thread.debugreg6 &= ~DR_STEP; > set_tsk_thread_flag(tsk, TIF_SINGLESTEP); > regs->flags &= ~X86_EFLAGS_TF; this looks strange... we set TIF_SINGLESTEP but clear X86_EFLAGS_TF > + } else if (dr6 & (DR_STEP | DR_TRAP_BITS)) { > + send_sigtrap(tsk, regs, error_code, get_si_code(dr6)); > } > - si_code = get_si_code(tsk->thread.debugreg6); > - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > - send_sigtrap(tsk, regs, error_code, si_code); > + can't understand how this change can fix the problem. We should always send SIGTRAP if the task returns to user-mode with X86_EFLAGS_TF? OK. I blindly applied this patch, step-simple still fails. Oleg. From fweisbec at gmail.com Fri Dec 18 02:58:09 2009 From: fweisbec at gmail.com (Frederic Weisbecker) Date: Fri, 18 Dec 2009 03:58:09 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218021042.GA508@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218014021.CB474135F@magilla.sf.frob.com> <20091218021042.GA508@redhat.com> Message-ID: <20091218025806.GA16470@nowhere> On Fri, Dec 18, 2009 at 03:10:42AM +0100, Oleg Nesterov wrote: > On 12/17, Roland McGrath wrote: > > > > Comparing to the old (2.6.32) logic, I think it might be this (untested). > > I also note this is the sole use of get_si_code, seems like it should > > just be rolled in here. > > Well, it is too late for me to even try to read this patch ;) > > but... > > > @@ -569,14 +568,15 @@ dotraplinkage void __kprobes do_debug(struct pt_regs *regs, long error_code) > > * We already checked v86 mode above, so we can check for kernel mode > > * by just checking the CPL of CS. > > */ > > + dr6 = tsk->thread.debugreg6; > > why? we have "tsk->thread.debugreg6 = dr6" above Yeah. > > if ((dr6 & DR_STEP) && !user_mode(regs)) { > > tsk->thread.debugreg6 &= ~DR_STEP; > > set_tsk_thread_flag(tsk, TIF_SINGLESTEP); > > regs->flags &= ~X86_EFLAGS_TF; > > this looks strange... we set TIF_SINGLESTEP but clear X86_EFLAGS_TF Yep, I don't understand what happens here either. This logic was there before the refactoring and the comment indicates we want to ignore traps from kernel. Why do we set this flag in a random thread? > > + } else if (dr6 & (DR_STEP | DR_TRAP_BITS)) { > > + send_sigtrap(tsk, regs, error_code, get_si_code(dr6)); > > } > > - si_code = get_si_code(tsk->thread.debugreg6); > > - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > > - send_sigtrap(tsk, regs, error_code, si_code); > > + > > can't understand how this change can fix the problem. We should always > send SIGTRAP if the task returns to user-mode with X86_EFLAGS_TF? > > OK. I blindly applied this patch, step-simple still fails. Yep, that doesn't fix your problem but this patch makes sense in that if we were not in user mode while the step occured, we shouldn't send the signal. From fweisbec at gmail.com Fri Dec 18 03:06:03 2009 From: fweisbec at gmail.com (Frederic Weisbecker) Date: Fri, 18 Dec 2009 04:06:03 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218005650.GA20667@redhat.com> References: <20091218005650.GA20667@redhat.com> Message-ID: <20091218030601.GB16470@nowhere> On Fri, Dec 18, 2009 at 01:56:50AM +0100, Oleg Nesterov wrote: > Hi. > > do_debug() is obviously wrong wrt PTRACE_SINGLESTEP/TIF_SINGLESTEP, no? > > Afaics this was broken by > > hw-breakpoints: modifying generic debug exception to use thread-specific debug registers > commit 08d68323d1f0c34452e614263b212ca556dae47f > > To verify, the "patch" below fixes the stepping for me, not sure what > is the proper fix... > > Oleg. > > --- arch/x86/kernel/traps.c~ 2009-12-18 00:20:49.000000000 +0100 > +++ arch/x86/kernel/traps.c 2009-12-18 01:44:05.000000000 +0100 > @@ -575,7 +575,7 @@ dotraplinkage void __kprobes do_debug(st > regs->flags &= ~X86_EFLAGS_TF; > } > si_code = get_si_code(tsk->thread.debugreg6); > - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > +// if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > send_sigtrap(tsk, regs, error_code, si_code); But I don't understand why it is broken with the check. If we are in a singlestep exception, dr6 should have its DR_STEP bit set... Single stepping works well for me, after a quick check on gdb. How did you trigger the bug? Thanks. From fweisbec at gmail.com Fri Dec 18 03:09:17 2009 From: fweisbec at gmail.com (Frederic Weisbecker) Date: Fri, 18 Dec 2009 04:09:17 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218025806.GA16470@nowhere> References: <20091218005650.GA20667@redhat.com> <20091218014021.CB474135F@magilla.sf.frob.com> <20091218021042.GA508@redhat.com> <20091218025806.GA16470@nowhere> Message-ID: <20091218030915.GC16470@nowhere> On Fri, Dec 18, 2009 at 03:58:09AM +0100, Frederic Weisbecker wrote: > Yep, that doesn't fix your problem but this patch makes sense > in that if we were not in user mode while the step occured, > we shouldn't send the signal. That wouldn't happen actually, as we clear the STEP flag before. From roland at redhat.com Fri Dec 18 03:53:45 2009 From: roland at redhat.com (Roland McGrath) Date: Thu, 17 Dec 2009 19:53:45 -0800 (PST) Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: Oleg Nesterov's message of Friday, 18 December 2009 03:10:42 +0100 <20091218021042.GA508@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218014021.CB474135F@magilla.sf.frob.com> <20091218021042.GA508@redhat.com> Message-ID: <20091218035345.A002F135F@magilla.sf.frob.com> > > + dr6 = tsk->thread.debugreg6; > > why? we have "tsk->thread.debugreg6 = dr6" above Yeah, it's a little superfluous. Except that the existing code uses tsk->thread.debugreg6 and dr6 inconsistently. It only matters either way if some notifier function might change thread.debugreg6, which I wasn't sure that none might. i.e., does/should hw_breakpoint hide/remap the watchpoint-fired bits when they are not for the same-numbered, ptrace-installed virtual debugreg? And does/should kprobes, kgdb, and whatnot, hide DR_STEP from thread.debugreg6 for a step that's not from user_enable_single_step? > > if ((dr6 & DR_STEP) && !user_mode(regs)) { > > tsk->thread.debugreg6 &= ~DR_STEP; > > set_tsk_thread_flag(tsk, TIF_SINGLESTEP); > > regs->flags &= ~X86_EFLAGS_TF; > > this looks strange... we set TIF_SINGLESTEP but clear X86_EFLAGS_TF This was the original purpose of TIF_SINGLESTEP from long, long ago. This happens when TF was set in user mode and then it did syscall/sysenter so TF is still set at the first instruction in kernel mode. TF is cleared from the interrupted kernel registers so the kernel can resume normally. In the original logic, TIF_SINGLESTEP served just to make it turn TF back on when going to user mode. Since then we grew the complicated step.c stuff and it all fits together slightly differently than it did when the original traps.c path was written. > can't understand how this change can fix the problem. We should always > send SIGTRAP if the task returns to user-mode with X86_EFLAGS_TF? If the debug exception happened in user mode, then we should send SIGTRAP. In the old (2.6.32) code with its goto-heavy logic the !user_mode(regs) was goto clear_TF_reenable; and that is: clear_TF_reenable: set_tsk_thread_flag(tsk, TIF_SINGLESTEP); regs->flags &= ~X86_EFLAGS_TF; preempt_conditional_cli(regs); return; I thought the new logic was falling through to the send_sigtrap case after "if ((dr6 & DR_STEP) && !user_mode(regs))". But now I see that the subtle use of dr6 vs tsk->thread.debugreg6 (without comments about it!) meant that DR_STEP is cleared from tsk->thread.debugreg6 before we test it. So I guess the idea there is that the !user_mode case would swallow the step indication but still leave some DR_TRAP_BITS set and so you'd generate a user SIGTRAP in honor of those (i.e. watchpoint hits). But I thought the hardware behavior was that a step will set DR_STEP in DR6 but not clear any DR_TRAP_BITS set from before, so I'm not sure this can't sometimes send a SIGTRAP twice for a combination of a watchpoint hit and a delayed step. > OK. I blindly applied this patch, step-simple still fails. Yeah, it was a quick reaction to the funny-looking control flow. But I didn't really investigate what is actually happening. Thanks, Roland From cornel at upload-ro.ro Fri Dec 18 04:17:12 2009 From: cornel at upload-ro.ro (EVRIKA GROUP) Date: Fri, 18 Dec 2009 06:17:12 +0200 Subject: LA MULTI ANI ! Message-ID: <20091217.XGOXASLNAQYZWEOQ@upload-ro.ro> An HTML attachment was scrubbed... URL: -------------- next part -------------- A non-text attachment was scrubbed... Name: 21_la_multi_ani4.jpg Type: image/jpeg Size: 86551 bytes Desc: not available URL: From undefenses at acanac.net Fri Dec 18 10:42:40 2009 From: undefenses at acanac.net (Gsell) Date: Fri, 18 Dec 2009 11:42:40 +0100 Subject: (no subject) Message-ID: <4B2B5B0F.6040502@acanac.net> -------------- next part -------------- A non-text attachment was scrubbed... Name: fractals.jpg Type: image/jpeg Size: 15215 bytes Desc: not available URL: From erz at tycz.com Fri Oct 16 19:54:22 2009 From: erz at tycz.com (=?GB2312?B?xeDRtQ==?=) Date: Fri, 16 Oct 2009 19:54:22 -0000 Subject: (no subject) Message-ID: <200910161954.n9GJs5N0030220@mx1.redhat.com> ????????????? ?????2009?11?7-8? ?? ?????2009?11?14-15? ?? ? ??2200?/?????????????????? ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ----------------------------------------------------------------------------------------------- ??????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????. ??????????????????????????????????????????????? ??????????????????????????????????????????????! ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? -------------------------------------------------------------------------------------------- ???????????? l?????????????????????????????????????????? 2??????????????????????????????? 3?????????????????????????????????????????? 4????????????????????????????????????????????? 5???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? -------------------------------------------------------------------------------------------- ????? l??????????????????????????????? 2??????????????????? 3????????????????????? 4???????????????????????????? 5??????????????TPM???????? ????? l????????????????????????? 2???????????????????????????????????? 3???????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????? ??????????????? ??????????? ????????????????? ????????????? ?????/?????/????? ?????????????? ??????????? ????????????? ????????????? ???????????????? ????????????????? ???????????????? ???????????????? ???????????? ???????????? ??????????????? ???????????? ??????????? ?????????????? ???????????????? ??????????????? ???????(?????) ?????????????? ????????? ??????????? ????????? ??????????? ????????????? ??:??????????? ???? ??N?????/??????? ???ISO9000??????????? ??????????????? ????????????????TPS? ???????????TOYOTA??? ????????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ????TQM?6?????????? ????????????????????????? ??????????????????? ??????????????? ???TPM??????????????????? ???TPM????????? ???: ???? ???? ??????????? ??????????? ?????????? ????????? ????????? ??: ??????????? ?????????????? ??????? ?????????????????? ??????????? ??????????????? ---???????????,??????????????) ---????????? ---????????? ---???????????? ??????/????????????; ???? 1.??????????????? 2.?????????? ?????????????????; ---???????????? ------------------------------------------------------------------------------------------------------------- ?????????? ?????? ???????? ???????????????(SUMIDA)????????(CASIO) ???13??????????????????????????????????????????????? ??WF&IE ???????????????????????????????????????????????????????JIT ??????NPS????????????? ??????????????(??,??,??,??,?????)????? ?:??????????ST?????????????????????????????????????????????? ???????????????????????????????80?????? ?????????????????????????????????????????????ABB?????????? ?????-??????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ?????????????????????????????? ??????????????????,?????????????????????????????????????? ?????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From vbeo at rehv.com Sat Oct 17 18:46:38 2009 From: vbeo at rehv.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Sat, 17 Oct 2009 18:46:38 -0000 Subject: (no subject) Message-ID: <200910171846.n9HIkMD6023545@mx1.redhat.com> ??????????????????????PPT+Excel+?????????????????? ?????????????????????? ??????????????????????????????office2003??Office2007?? ??????????2009??10??30????11??1?????? ??????????2009??11??6-8?????? ??????????2009??11??20-22?????? ??????????3600/???????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? ====================================================================================== ??????????????20???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????3?????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? ????????????????????????????Powerpoint??Excel???????????????????????????????????????????????????????? ???????????????????????????????????????????? Powerpoint??????????????????????????????????????????Powerpoint????????????????Office???????????????? ????????Powerpoint????????????????PPT?????????????????????????????????????????? ??????????Powerpoint???????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????Photoshp???????????? ?????????????????????????????????????????????????? Excel??????????????????????????????????????????????????????????????Excel??80%???????????????????????? ??????????????????????????????????????????5?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ============================================================================================== ????????????????????????????????????????????????????????????office2003??Office2007 ????PPT??????????????????????????????Powerpoint???????????????????????? 1.???????????????????????????????????????????????????????????? 2.?????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????????????????????????????????? 4.Flash??????????????????????Flash??????????PPT??????????????????????Flash?? ?????????????????????????????????????????? ????Excel??????????????????????????????BladeOfficeExcel???????????????????????? 1.????????????????????????????????????????????????????????????????????Excel???????????????????????????? ???????????????????????????????????????????????????????? 2.Excel??????????????Excel2003???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ======================================================================================================== ???????? ???????????????????????? ?????????????????????????? 1.?????????????????????????????????????????????????????????? 2.????????????????????????500???????????????????????????????? 3.???????????????????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ?????????????????????????? 1.????Office???????????????? 2.???????????????????? 3.?????????????????? 4.???????????????? 5.???????????????????????????????? 6.?????????????????? 7.????3D?????????????? 8.???????????????????????? 9.?????????????????? 10.??????????????* 11.??????????????????????????????????3-D????* ???????????????????????? 1.???????????? 2.???????????????????????? ???????????????????????? 3.???????????? ???????????????????????????????????? 4.????????????????40M??????????6M 5.???????????????? ????SmartArt???????? 1.?????????????????????????????? 2.???????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????????????? 6.??????????????SmartArt ???????????????????? 1.?????????????????????????????? 2.?????????????????????????? 3.?????????????????????????? 4.?????????????? 5.?????????????????????? 6.?????????????????? ????Excel???????? 1.?????????????????????????????????????????????? 2.??????????????????????????????10??????????5???????? 3.?????????????????????? 4.?????????????????? 5.???????????????????????????????????????????????? 6.??????Powerpoint???????????????????? 7.?????????????????????? 8.???????????????????????????????? 9.???????????????????????????????????? ?????????????????? 1.????????????Powerpoint?????????? 2.???????????????????????????? 3.?????????????????? 4.?????????????????????? 5.?????????????????????????????????? ???????????????????? 1.Powerpoint?????????????????? 2.?????????????????????????????????? 3.???????????????? 4.???????????????????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.?????????????????????? 8.?????????????????????????????????????? ????????Excel?????????????? ???????????? 1.?????????????????? 2.?????????????????? 3.??????????2?????? 4.??????????????????Excel?????????????????????????????? 5.?????????????????????????????????? ???????????????? 1.????IF???????????????? 2.AND??OR??NOT???? 3.?????????????????????? ?????????????? 1.?????????????????? 2.???????????????????????????? 3.???????? a)???????????????????????????????? b)?????????? c)???????????????????? ???????????? 1.???????????? 2.???????????????????????? ???????????? 1.???????????????? 2.????VLOOKUP??HLOOKUP???????????? 3.?????????????????????? a)???????????????????????????????????? b)???????????????????????????????????????????????????????????????? 4.?????????????????????????? 5.???????????????????????????? ???????????? 1.???????????????? 2.?????????????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????? 6.?????????????????? ???????????? 1.?????????? 2.?????????? 3.???????????????? ???????????????? 1.???????????????? 2.???????????????? 3.?????????????????? 4.???????????????? 5.?????????????????????????? ?????????????????????? 1.?????????????? 2.?????????????? 3.???????????? 4.???????????? 5.???????????? 6.?????????????????????????????? 7.???????????????????? a)?????????? b)?????????? c)?????? d)?????????? 8.???????????????????????? 9.?????????????????????????????? ?????????????????? 1.?????????????????????? 2.???????????????????????????????? 3.?????????????????? ???????????????????? ?????????????????? 1.?????????????????? 2.????Powerpoint?????????????????? 3.????Word?????????????????? 4.????Excel?????????????????? ???????????? 1.?????????????????????????????????????????????? 2.???????????????? 3.??????????????SmartArt???????????? 4.???????????????????? ???????????????? 1.?????????????????? 2.???????????????????????????????? 3.Outlook?????????????????? ================================================================================================== ??????????????????????????????????????????????IPMP???????????????????????????????????????????????? ????????????????????????????????????????????????????????????????ERP???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????DELL????????????????????????????????????????????????????????????????????TCL???????? ============================================================================================== ????????????????????????PPT+Excel+??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From rtg at wyu.com Sat Oct 17 19:16:59 2009 From: rtg at wyu.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 17 Oct 2009 19:16:59 -0000 Subject: (no subject) Message-ID: <200910171916.n9HJGaTS012809@mx1.redhat.com> ???????????????? ??????????2009??10??23-24?? ???? ??????????2009??10??29-30?? ???? ??????????2009??10??31-11??1?? ???? ??????????2009??11??20-21?? ???? ??????????2009??11??27-28?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From io at bios.com Sat Oct 17 23:05:33 2009 From: io at bios.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Sat, 17 Oct 2009 23:05:33 -0000 Subject: (no subject) Message-ID: <200910172305.n9HN5KP3024149@mx1.redhat.com> ???????????????????????????????? ??????????2009??10??23-24??---?? ?? ??????????????????????CEO/??????????????????????????????????????????/?????? ??????/??????????????????/HR????????HR????????/???????????????????????????? ?????????????????????????????????????????????????????????? ??====????2500??/2??/??(??????????????????????????????????????????????) ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????500?????????????????????????????????????????????? ============================================================================ ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????KPI???????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????? ??????????????????????????????????????????30%??????????????70%???????????????? ?????????????????????????????????????????????????????????????????????????????????? ====================================================================================== ?????????????????????????? 1. ???????????????????????????????????????????????????????????????????????????????????? 2. ?????????????????????????????????????????????????????????????????? 3. ???????????????????????????????????????????????????????????????? 4. ?????????????????????????????????????????????????? 5. ??????????????????????????????????????KPI ???????????????????????????? 6. ????????????????????????????????????????PBC?? 7. ?????????????????????????????????????????????????????? 8. ??????????????PDCA ???????????????????????????? 9. ?????????????????????????????????????????????????????????????????????????????????? 10.????????20 ???????????????????????????????????????????????????????????????????? ??Action Plan??????????????????????????????????????????. ====================================================================================== ???????? ???????????????????????? 1???????????????????????? 1???????????????? 2???????????????? 3???????????????? 4?????????????? 5?????? 2???????????????????????????????? 3?????????????????????????????????????????????????? 4????????????A?????????? ???????????????????????????????????? 1?????????????????????????????? 1???????????????????????? 2??18???????????? 3?????????????????????????????? ???????????? ??B??E??I?????? 4?????????????????????????????????????????????????? 5???????????????????????????????? ?????????? ?????????? ???????????? ?????????????? ???????????????? ?????? 2?????????????????????????????????? 1???????????????????? ?????????? ?????????? ?????????????? 2?????????????????????????? 3???????????????????????????????????????? 4???????????????????????????????????????????????? ???????????????????????????? 1?????????????????????????????????? 2?????????????????????????????????????????? 3?????????????????????????????? 1?????????????????? 2???????????????????????????????????????????? 3???????????????????? 4???????????????????????????? 5???????????????????????? 6???????????????????????? 1?????????????????????????? 2??????????????????????????????????????????KPI?? 7???????????????????????? 1???????????? 2???????????????? 8?????????????????????????????? 1?????????????? 2???????????????????????????? 3?????????????????????? 9???????????? 1?????????????????????????????????????????????? ????????????????????KPI ???????? 1??????????KPI ???????????????????? 2??????????????????????????????????????KPI ???? 3??????????KPI ?????????????? 4??????????KPI ?????????? 1?????????????????? 2?????????????? 5??????????KPI ??????????????????I??T??Q??C??S?? 6????????????KPI ?????? 1??????????KPI ???? ???????????????????????????????????????????? 2??????????KPI ????????????????????????????????????QA?????? 3????????????????KPI ????????????HR?????????????????????????? 7??????????KPI ?????? 8???????????????????? 1?????????????????????????????? 2???????????????????????? 3????????????????KPI ???????????? 4???????????????????????????????????????????????? 9???????????? 1??????????????????????KPI ?????????????????????????????????????????????? 2????????????KPI ???????????????????????D?D??????????????PCB ?????????????????????? 1???????????????????????????? 2???????????????????????? 1???????????????????? 2???????????????????????????????????????????????????????? 3???????????????????? 1???????????????????? 2?????????? 3???????????????? 4?????????????????????????D?D????????????PBC 1????????????WINNING?? 2????????????EXECUTION?? 3????????????TEAMWORK?? 5??????????????????PBC ?????????????? 6??????????????????????????????????PBC 7???????????????????????????????? 8????????????????????????????PIP?? 9???????????? 1??????????????????????????PBC???????? 2??????????????????????????PIP???????? ????????????/?????????????? 1?????????????????????????? 1??????????????PAC 2??????????????PDT 3??????????FT 2?????????????????????????? 3???????????????????????? 1?????????????????????????? 2?????????????? 3?????????????????? 4???????????????????????? 5???????????????????????????? 6???????????????????????????? 7?????????????????????????????????????????????? 1???????????? 2???????????? 3???????????? 4???????????? 8???????????? 1?????????????????????????????????????????????? ???????????????????????????? 1????????????????????A??????????????B?????????????????????????????????????????????? 1???????????????????????????????????????????? 2?????????????????????????????????????????? 2????????????????????????????????????????????HR???????? 3???????????????????????????????????????????? 4?????????????????????????????????????????????????????? 5?????????????? 1???????????????????????? 2?????????????????????????????????????????????????????????????? 3?????????????????????????????? 4???????????????????????????????????? 6?????????????????????????? 1???????????????? 2?????????????????????????????????????????????????????????????????????? 7???????????????????????? 1???????????????? 2???????????????????????????? 8?????????????????????????????????????????????????? 9?????????????????????????????????????????????? 1?????????? 2?????????? 3?????????????????? 10?????????????????????????????????????????? 11???????????? 1?????????????????????????????????????????? ???????????????????????????? 1?????????????????????????? 2???????????????????? 1???????? 2??5??/10???????? 3???????? 4???????? 5?????? 6?????? 2?????????????????????????????????????????????? 3???????????????? 1????????/?????? 2???????? 3???????? 4???????? 5???????? 4???????????????????????????????????????? 5?????????????????????????????????????????????????????? ====================================================================================== ???????????????????? ???????????????????????????????????????????????? ?????????????????????? ==>?????????????????????? ???????? & ?????????? ==>???????????????????????????????????????????????? ???????????? ???????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????? ==>???????????????????? ==>?????????????????????????? ==>?????????????????????????? ==>???????????????????????????????????????? ???????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????? ??????????????????????????????????????????????????????(????)?????? ??????????????????????????????????????????????????????????????????????????????????(????)???????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From rtf at utym.com Sun Oct 18 20:04:27 2009 From: rtf at utym.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sun, 18 Oct 2009 20:04:27 -0000 Subject: (no subject) Message-ID: <200910182004.n9IK4FnU017976@mx1.redhat.com> ???????????????? ?????2009?10?24-25? ?? ?????2009?10?31?-11?1? ?? ?????2600/?????????????????? ????????????????????????????????????????????????? ??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ------------------------------------------------------------------------------------------------- ????????????????????????????????????????????????? ????????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????????,??????????? ????????????????????????????????????????????????? ???????????????????????????,??????????????? ?????????????????????????????????????????????????-- ?????????????????? ?????????????,??????,??????,??????,??????????,?????? ????????????,????????????????????. ------------------------------------------------------------------------------------------------- ????: ????????????????? ??????? ??????????? ????????????? ??????????????? ?????????????????? ??????????????????????? ???????????????? ??????????????? ??????????? ?????????????? ??????????? ?????????????? ???????????? ?????????????? ???????????????? ????????????? ????????????? ??????????????? ???????????? ??????????? ??????????????(????) ??????????? ????????????????????? ????????????????? ??????????????????? ????????? ???????????? ???????????? ????????? ?????????? ??????????? ???????????? ?????????????? ??????????????? ????????????????? ?????????????? ---------------------------------------------------------------------------------------------- ?????????????????????????? ????????????????????????????????????????????COB&SMT&AI? ???????????????????????????????WF&IE???????????????? ???????????????????????????????????????JIT??????NPS?? ?????????????????????????(??,??,??,??,??,??)?????????? ???????ST?????????????????????????????????????????? ???????????????????????????????????80?????? ?????????????????????????????????????????????ABB???? ???????????-??????????????????????????????????????? ?????????????????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????,???????????????????????????????? ???????????????????????????????? -------------------------------------------------------------------------------------------------- ???????????????????????????020-62351156? ? ? ? ????? ??? ? ? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638??? From wei at srtr.com Mon Oct 19 02:48:57 2009 From: wei at srtr.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Mon, 19 Oct 2009 02:48:57 -0000 Subject: (no subject) Message-ID: <200910190248.n9J2miaj014068@mx1.redhat.com> ?????????????????????? ??????????2009??10??26-27?????? ??????????2009??10??29-30?????? ??????????2009??11??02-03?????? ??????????2009??11??11-12?????? ??????????2009??11??14-15?????? ??????????2009??11??17-18?????? ??????????3200??/???????????????????????????????????????????????? ?????????????????????????????????????????????????????????? ????????????????????/??????????????????/??????????PMO????????????????????????????????????????QA???? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? 1.???????????????????????????????????????????????????????????????? 2.???????????????????????????????????????????????????????????????????? 3.???????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????? 5.?????????????????????????????????????????????????????????????????????? 6.???????????????????????????????????????????????? 7.???????????????????????????????????????????????????? 8.???????????????????????????????????????????????????? 9.???????????????????????????????????????????????????????????? 10.???????????????????????????????????????????????????????????? ??????????????????????6????????????700???????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????2008???????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? --------------------------------------------------------------------------------------------- ???????? 1.???????????????????????????????????????????????????????????? 2.???????????????????????????????????? 3.?????????????????????????????????? 4.?????????????????????????????????????????????????????????? 5.?????????????????????????? 6.?????????????????????????????? 7.?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? 8.???????????????????????????????????????????????????????????? ------------------------------------------------------------------------------ ???????? ???????????? 1???????????????????????? 2???????????????????????????????????????????????????????????????? 3???????????????????????????????????? 4???????????????????????????????????????? ???????????????????? 1.?????????????? i.?????????????????????? ii.?????????????????????? iii.?????????????? iv.??????????????????????????????????(PMI) 2.???????????? 1)?????????????????? 2)?????????????????????????? 3)???????????????????????????? 4)???????????????????????????????? 3.??????????????VRM?? 1)?????????????? 2)?????????????? 3)?????????????? 4.???????????????? 1)?????????????????????D?D???????????????????????????????? 2)???????????????????? ???????????????? 1???????????????????? 1)?????????????? 2)?????????????????? 3)?????????????????????????? 4)?????????????? 2?????????????????? 1)?????????????????????????? 2)?????????????????????????? ?????????????????????? 1???????????????????????? 1)?????????? 2)?????????? 3)?????????? 2?????????????????????????????? 1)???????????????????????? 2)?????????????????????????????? 3)?????????????????????????????? 4)?????????????????????????????????????? 3?????????????????????????? 1)???????????????????????????????? 2)?????????????????????????? 4?????????????????? 1)???????????????????????????????????????????????????? 2)???????????????????????????????????? 3)?????????????????????? 4)?????????????????????????????????????????????????? 5)???????????????????????????? 5???????????????? 1)?????????????????????????????????????????????????? ???????????????????? 1??????????????IT?????? 1)?????????????????????? 2)????????3?????????? n?????????? n?????????? n?????????????????? 3)???????????????????????????????? 2???????????????? 1)?????????????????????????????????????????? 2)?????????????????? 3)?????????????????????? 4)?????????????????? 5)?????????????????? 6)?????????????????????????????? 3?????????????????????????????? 1)WBS?????????????????? 2)WBS?????????????? 3)PBS??WBS??OBS??RBS?????????????? 4)?????????????????? 5)?????????????????????? 6)PERT???????? 7)???????????????????? n?????????? n?????????? 4?????????????????????????????????????? 5????????????????????????????14?????? 1)?????????????? 2)???????????????????? 3)???? 6?????????????????? 1)?????????????????????????????? 2)???????????????? 3)???????????????????????? 4)??????????????????????PCB?????????????????????????? 5)???????????????????????????? 7???????????????? ???????????????????? 1?????????????????? 1)???????????????????????????? 2)?????????????????? 3)???????????????? 4)???????????????????????? 5)?????????????????????????????????????????????? 2???????????????????????????? 1)???????????????? 2)???????????????? 3)?????????????? 4)???????????????? 5)?????????????????? 3???????????????????????????? 1)???????????????????????????????????????????? 2)?????????????????????????????????????? 3)?????????????????????????? 4)???????????????????????? 5)?????????????? 4?????????????? 1)QA?????????? 2)QA???????? 3)QA?????????? 4)????????????????QA?? 5?????????????????? 1)???????????????????????? 2)?????????????????????? 3)???????????????????? 4)???????????????? 5)?????????????????????? 6)?????????????????????? 7)???????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? 8)???????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? l???????????????????????????????? ???????????????????? 1???????????????????????????? 2?????????????????? 3???????????????????????????? 4???????????????????????????? 5?????????????????????????????????????????? 6???????????????????????????????????????????? 7?????????? 8???????????????????????????? 9???????????????? 10???????????????? 11?????????????????? 1)??SEI?????????????? 2)???????????????????? 3)?????????????????????? 4)???????????????????????????? ???????????????????? 1???????????????????????????????????????? 2?????????????????????????? 3???????????????????????????? 1)???????????? 2)???????????? 4???????????????????????????? 1)???????????? 2)?????????????? 5???????????????????????????????? 1)???????????? 2)???????????? 6?????????????????? 1)???????? 2)???????????? 3)?????????????? 4)???????? 5)???????? 6)QA???????? 7???????????????? 8?????????????????? 1)???????????????? 2)????????/???????????? 3)???????????????? 4)???????????????? 5)???????????????????????? ???????????????????? 1????????????????????????BSC 2?????????????????????? 1)???????????????????????????? 2)?????????????????????? 3)???????????????? 3?????????????????? 1)??????????KPI???????? 4??????1?????????????????????????? 5??????2???????????????? ?????????????????????? 1?????????????????????????????????? 2?????????????????????????????? 3?????????????????????? 4?????????????????????????????? 5???????????????????????????????????????? ------------------------------------------------------------------------------- ????????????????????????????????????CMM/CMMI???????? ?????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????NGN?????????? ?????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????CMM???? ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????(????????)???? ??????????????????????????????????????????????????????????????????????????????????CMMIL4 ????????CMMIL2???????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????? -------------------------------------------------------------------------- ????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From wed at rytf.com Sat Oct 24 10:16:13 2009 From: wed at rytf.com (=?GB2312?B?xeDRtQ==?=) Date: Sat, 24 Oct 2009 10:16:13 -0000 Subject: (no subject) Message-ID: <200910241015.n9OAFu0u031940@mx1.redhat.com> ???????????? ?????2009?10?30-11?1? ?? ?????2009?11?13-15? ?? ?????2009?11?27-29? ?? ?????????????????????????????????????? ?????3600?/??????????????????? ?????020-80560638?020-85917945??????????????chinammc21 at 126.com??? ======================================================================================== ????????????????????????????????????? ???????????????????????????????????????????? ????????????? ??????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ?????????? ???????????????????????????????????????????? ????????????????????????????????????????? ???????????????????????????????????????????? ?????????????????? --------------------------------------------------------------------------------------- ???? ????????? ????????? ?????????? ????????????????? ??????????? ???????????? ??????????????????? ????????????????????????????? ????????????????????????????? ?????????????????????? ???????????????? ?????????????????? ??????????? ??????????? ??????????? ????????????? ???????????? ????????? ??????????? ???????????????????? ?????? ????????????? ???????????????????? ???????????? ????????????????????????????? ??????????? ???????? 1?????????? 2???????? 3???????? 4???????? ??????????????????? ?????? (?) ?????? (?) ?????????? (?) ??????? (?) ??????? ????????????? ???????? ??????? ?????????? ?????????????? ???????????? ??????????? ??????? ????????????????? ???????????? ???????????? ???????????? ???????????? ??????????????????????? ??????? ??????????????????? 1?????? 2?????? 3?????? ???????????????????????? ????????????????? ??????????????? ?????????????? ???????????????????? ????????????????? ???????????? ??????? 1??????1+1=?? 2????????? 3??????? ?????????????????????? ?????????? 1????????????????????????????? 2????????????????????? 3????????????????????????? 4????????????????? 5??????????????????? 6??????????????????? 7?????????????????????? 8????????(???????????????) ????????????????????? ?????????? 1?????????? 2???????????? 3?????????? ??????????????????????? ??????????????? 1???????? 2???????? ????????????????????? ??????? ???????? ??????????????????? ??????? 1??? ??-??-???????????????? 2?????(???????????) 3?????????????????????? 4??????????????? 5?????????????????????? 6???????????????? 7????????????? 8????????????????? ??????????? ??????????????? ----------------------------------------------------------------------------------------- ????---???????????????????????????????????????? ?????????????????????????????AITA????????????SKP? ?????????????????????????????????????????????? ?????MOTHERS?????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????? ????????????????????????????????????????????? ???????????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????????? ???????????????????????????????????????????????? ????????????TCL????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????????? ???? 1.????,???????????. -???????????????? 2.??????????,??????????. -??????? 3.???????,????????????,????. -??????? 4.?????????????. -????????????????? 5.??????????????????????. -???????????????? 6.???????????,??????????????????.-TCL????(??)?????? 7.??????,???????.????????. -??????? =========================================================================================== ???????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From bvgi at ertgr.com Sat Oct 24 14:38:00 2009 From: bvgi at ertgr.com (=?GB2312?B?xeDRtQ==?=) Date: Sat, 24 Oct 2009 14:38:00 -0000 Subject: (no subject) Message-ID: <200910241437.n9OEbnj9001242@mx1.redhat.com> ??????????????? ?????2009?10?30-31?--- ?? ?????2009?11?6--7? ----?? ????: ?????????????????????????????????????? ????: 2800?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ====================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????? ================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????? ??????????????????? ??????????????????????? ?????????????????? ?????????????????????????? ????????????????????????????????????? ??????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA??????? ??CPA????????CPT???????????????????????????????????? ????????????????????????????????????????????????? ?????????CFO?????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????????????????????????????,?????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????(??)?? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? ???????? ??????????? 1????? 2??????? 3???????? ??????? 1??? 2??? 3?????? 4??? 5??? 6??? ???????? 1???????? 2?????? ????????????? ????????????????????? 1??????????? 2??????????? ?????????????????? 1????? 2????? 3????? 4?????? 5????? 6??? 7)???? 8????? 9????? 10????? 11????? 12?????? 13????? 14?????? 15????? 16????? 17????? 18?????? ?????????? 1??????????????? 2???????????? 3?????????? 4????????????? ??????????? ?????????? 1?????? 2?????? ???????????? 1????? 2????? 3???????? 4????? 5????? 6????? 7?????? 8?????? 9????? 10???? ?????????????? 1????????????? 2????????????? 3????????????? 4????????????? 5???????????? ???????? 1?????????? 2?????????? 3?????????????????? 4????????? ?????????? ???????????? 1?????????????? 2?????????????? 3?????????????? 4?????????????? ???????????? 1???????????????????? 2??????????????? 3????????????? ?????????? 1????????? 2??????? 3????????? ????????????? ????????????? 1?????????? 2?????????? 3????????? 4?????????? 5????????????? ????????? 1??????????? 2???????????? ????? ???????????? 1???????? 2???????? 3???????? ???????? 1??????? 2??????? 3???????? 4?????????? 5????????? 6?????? 7????? 8??????? 9??????? 10?????? 11?????????? 12?????? 13??????? 14???????? 15???????? 16????? ?????????????????? ????????????? ?????????????????? 1????????? 2????????? 3???????????? 4????????? 5????????? ?????? 1???????? 2??????? 3????????? 4??????ABC??? ???????? 1?????????? 2????? 3????? 4?????????? ???????? 1???????? 2??????? 3???????? 4?????????? 5????????????Z-SCORE??? ???????????????????? 1??????? 2?????????????????? ???????????? ???????? ????????????????????? 1??????? 2??????? 3?????????? 4???????? ???????????? 1????? 2????? 3????? 4????? 5????? ???????????? 1????? 2????? 3????? 4????? ?????????? 1?????????? 2?????????? 3?????????? 4?????????? ?????????? 1?????? 2?????? 3?????? ???????????? 1????? 2????? 3????? 4????? 5????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? 6??????? 7??????? 8??????? 9??????? ???????? 1???????? 2???????? ?????????? 1????????????? 2????? 3????? ???????? ??????? 1????????? 2?????????? 3????? 4???????????????? ??????????????? 1?????? 2????? 3????? 4??????? -------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From wew at qyub.com Sun Oct 25 07:27:29 2009 From: wew at qyub.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Sun, 25 Oct 2009 07:27:29 -0000 Subject: (no subject) Message-ID: <200910250727.n9P7RETY019930@mx1.redhat.com> ???????????????? ??????????2009??10??31-11??1?? ???? ??????????2009??11??20-21?? ???? ??????????2009??11??27-28?? ???? ??????????2009??12??25-26?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From opg at erhe.com Mon Oct 26 06:38:52 2009 From: opg at erhe.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Mon, 26 Oct 2009 06:38:52 -0000 Subject: (no subject) Message-ID: <200910260638.n9Q6cab7028279@mx1.redhat.com> ?????????????????? ?????2009?11?13-14?--- ? ? ?????2009?12?4-5? ----? ? ????: ?????????;???????????????????;???????? ??????????????;??????????????????????????? ??????????????? ????: 2500?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ??????????????chinammc21 at 126.com??? ====================================================================================== ???? ??????????????? ??????????????? ??????????????? ???????????? ????????????????????? ?????????????????????????? ?? ????????????????????????????????????????????? ????????????????????????????????????????????? ??????????????????????????????? ???? ????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????????? ??????????????????????? ??????????????????????????? ????????????????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA????? ????CPA????????CPT???????????????????????????????? ??????????????????????????????????????????????? ???????????????CFO??????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????,??????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????(??)??????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????????????????????? ????????????????? ???????????????????? ====================================================================================== ???? ??????? ??????????? ?????????? 1????2????3????????????? ???????????? 1????2??????3??????4????????? ?????????? 1?????2?????3?????4???? ????????? 1??????2????????3?????????4?????????5?????? ????????? 1????????2??????3????????4????? ?????????????????????? 1?????????????? ?2??????3??????????4?????????????????? 5??????6??????7????????8??????9??????? ???????????? 1????????2????????????3??????4????????5????? 6???????7???????8????????10??????11????????????? 12?????????????????????13???????????14???????15???????16?????? ?????????????????? 1?????????????2???????????????3???????????? ??????? ???????? ?????????? 1???????????2?COSO??????3???????? ?????????? 1??????2????????3??????4?????????5?????? ?????????? 1????????2????????3????????4????????5??????? ???????????? 1??????2??????3??????4??????5????? ??????????? 1??????????????????????2??????? ?????????? ???????????? ??????????????? 1??????2??????3???????4???????5??????6????7????? ?????????????????? 1??????2????3????4??????5??? ???????? ?????????? 1????????2???????3??????? 4???????5?????????6????? ??????????????????? 1????????2??????3????4????? ?????????????????????? 1?????????2?????????3?????????4????? 5??????????????6??????????????7????????8????? ???????? 1???????????2?????????3????????? 4??????5???????????? ???????? ?????????? 1??????2??????3??????4??????5??????6??????7????? 8??????9??????10??????11??????12??????13????? ???????????? 1????????2????????3????????4??????? ??????????? 1??????????2???????????? ?3??????????4???????????? 5???????????6????????7??????? ???????????????????? 1??????2??????3??????4????? ?????????? ??????????????????????? ???????????? 1?????????2????????????? ?????????? 1??????2??????3????????4???????? ?????????? 1?????2?????3??????4???? ????????????? 1??????2??????????????3????????4????????? ???????????? ???????????Z-SCORE??? ??????????????? 1?????2???? ?3?????4???? ---------------------------------------------------------------- ?????????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From eag at ryta.com Mon Oct 26 13:22:56 2009 From: eag at ryta.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Mon, 26 Oct 2009 13:22:56 -0000 Subject: (no subject) Message-ID: <200910261322.n9QDMgLT021007@mx1.redhat.com> ????????/???????????????????????????????? ??????????2009??11??14-15?? ???? ??????????2009??11??21-22?? ???? ??????????2009??11??28-29?? ???? ??????????2000/???????????????????????????????????? ??????????????????????????????????????????????????????HR???????? ??????????020-80560638??020-85917945 ????????????????????????????chinammc21 at 126.com?????? ======================================================================================== ???????????????????? 1.?????????????????????????????????????????????????????????????????????? 2.???????????????????????????????????????? 3.???????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? 5.?????????????????????????????????????????????? 6.?????????????????????????? 7.?????????????????????????????????????????? 8.???????????????????????????????????????????????????????? 9.???????????????????????????????????????????? 10.???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? =========================================================================================== ????????: 1??????/?????????????? ????/???????? ????????/???????????????? ????????/?????????????????????????? ????????/???????????????????????? ???????????????????????D?D?????????????????? ???????????????????????????? 2??????????????/????/???????? ????/?????????????????D?D????????????????/????/???????? ???????????? ?????????????? ???????????????????????? ???????????????? ?????????????????????????? 3??????????5S???? 5S?????? ???????????????????????? ???????????????????????? ???????????????????????? ???????????????????????? 4?? ??????????????/?????????????????? 1)????/????/?????????????????????? PDCA?????????????????????????? ??????????/????/?????????????????????? ???????????????????????????????? ?????????????? 2)???????????????????????? ?????????????? ?????????????? ???????????????? ?????????????????? ???????????????????????????????? 3)???????????????????? ?????????????????????????????????? ?????????????????? ?????????????????? ???????? 4)???????? ???????????????? ?????????????????? ?????????????????? ?????????????????? ?????????????????? ?????????????????? ?????????????????? 5?? ?????????????? ?????????? ?????????????????????? ?????????????????????????????????? ?????????????????????? A/???????????????? B/???????????????????????? ?????????????? 5?????????????? 1)?????????????????????????????? 2)?????????????? ???????? ?????????????????? ???????????????????????? ?????????????????? ?????????? ?????????? ?????????? ?????????????? 3)?????????????????????????? ???????????????????? ?????????????? ???????????????? ???????????????? ???????????????????? 4)?????????????????????????????? ???????????????????????????????????????? ???? ========================================================================================== ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????5????????????500?????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????TTT???????????????? ??????????????????????????/???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????????TCL?? ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????? =========================================================================================== ??????????/????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From Edisy.srth at aol.com Tue Oct 27 08:25:43 2009 From: Edisy.srth at aol.com (Edisy.srth at aol.com) Date: Tue, 27 Oct 2009 08:25:43 -0000 Subject: (no subject) Message-ID: <200910270825.n9R8PUbV015638@mx1.redhat.com> =================================================================================== ????????????????????(PPT+Excel+????????)???????? ---???????????????????? =================================================================================== ???????????? 2009??10??30??-11??1?? ???? 2009??11??06-08?? ???? 2009??11??20-22?? ???? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 =================================================================================== ???????????? ??20?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? ??????????????????????????3?????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????? ??-??-??-??: ??????????????????Powerpoint??Excel???????????????????????????????????????????? ???????????????????????????????????????????????????????? Powerpoint??????????????????????????????????????????Powerpoint???????????????? Office????????????????????????Powerpoint????????????????PPT?????????????????????? ???????????????????? ??????????Powerpoint?????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ????????????????????Photoshp?????????????????????????????????????????????????????? ???????? Excel??????????????????????????????????????????????????????????????Excel??80% ??????????????????????????????????????????????????????????????????5?????????????? ?????????????????????????????????????????????????????????????????????? ?????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???? ?????????? ??????????????????????????????????????????????????office2003??Office2007 ????PPT??????????????????????????????Powerpoint???????????????????????? 1.???????????????????????????????????????????????????????????? 2.?????????????????????????????????????????????????????????? 3.?? ?? ?? ?? ?????????????????????????????????????????????????????????????????? ???????????????????????????????? 4.Flash??????????????????????Flash??????????PPT??????????????????????Flash?? ?????????????????????????????????????????? ????Excel??????????????????????????????BladeOffice Excel???????????????????????? 1.????????????????????????????????????????????????????????????????????Excel???? ???????????????????????????????????????????????????????????????????????????????? 2.Excel??????????????Excel2003?????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ?????????? ??????????????????????????Powerpoint??????????????????????PPT?????????????????? ??????????????????????????????????????????Excel???????????????????????????????? ?????????? ??-??-??-???? ?????????????????????????????????????????????????????????????????????????????????? ?????????? ??-??-??-???? ????????-????????-????????-?????????? =================================================================================== ???????????????????????? ?????????????????????????? 1.?????????????????????????????????????????????????????????? 2.????????????????????????500???????????????????????????????? 3.???????????????????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ?????????????????????????? 1.????Office???????????????? 2.???????????????????? 3.?????????????????? 4.???????????????? 5.???????????????????????????????? 6.?????????????????? 7.????3D?????????????? 8.???????????????????????? 9.?????????????????? 10.??????????????* 11.?????????????????????????????????? 3-D ????* ???????????????????????? 1.???????????? 2.???????????????????????? ???????????????????????? 3.???????????? ???????????????????????????????????? 4.????????????????40M??????????6M 5.???????????????? ????SmartArt???????? 1.?????????????????????????????? 2.???????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????????????? 6.??????????????SmartArt ???????????????????? 1.?????????????????????????????? 2.?????????????????????????? 3.?????????????????????????? 4.?????????????? 5.?????????????????????? 6.?????????????????? ????Excel???????? 1.?????????????????????????????????????????????? 2.??????????????????????????????10??????????5???????? 3.?????????????????????? 4.?????????????????? 5.???????????????????????????????????????????????? 6.??????Powerpoint???????????????????? 7.?????????????????????? 8.???????????????????????????????? 9.???????????????????????????????????? ???? ?????????????? 1.????????????Powerpoint?????????? 2.???????????????????????????? 3.?????????????????? 4.?????????????????????? 5.?????????????????????????????????? ???????????????????? 1.Powerpoint?????????????????? 2.?????????????????????????????????? 3.???????????????? 4.???????????????????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.?????????????????????? 8.?????????????????????????????????????? ????????Excel?????????????? ???????????? 1.?????????????????? 2.?????????????????? 3.??????????2?????? 4.??????????????????Excel?????????????????????????????? 5.?????????????????????????????????? ???????????????? 1.????IF???????????????? 2.AND??OR??NOT???? 3.?????????????????????? ?????????????? 1.?????????????????? 2.???????????????????????????? 3.???????? a)???????????????????????????????? b)?????????? c)???????????????????? ???????????? 1.???????????? 2.???????????????????????? ???????????? 1.???????????????? 2.????VLOOKUP??HLOOKUP???????????? 3.?????????????????????? a)???????????????????????????????????? b)???????????????????????????????????????????????????????????????? 4.?????????????????????????? 5.???????????????????????????? ???????????? 1.???????????????? 2.?????????????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????? 6.?????????????????? ???????????? 1.?????????? 2.?????????? 3.???????????????? ???????????????? 1.???????????????? 2.???????????????? 3.?????????????????? 4.???????????????? 5.?????????????????????????? ?????????????????????? 1.?????????????? 2.?????????????? 3.???????????? 4.???????????? 5.???????????? 6.?????????????????????????????? 7.???????????????????? a)?????????? b)?????????? c)?????? d)?????????? 8.???????????????????????? 9.?????????????????????????????? ?????????????????? 1.?????????????????????? 2.???????????????????????????????? 3.?????????????????? ???????????????????? ?????????????????? 1.?????????????????? 2.????Powerpoint?????????????????? 3.????Word?????????????????? 4.????Excel?????????????????? ???????????? 1.?????????????????????????????????????????????? 2.???????????????? 3.??????????????SmartArt???????????? 4.???????????????????? ???????????????? 1.?????????????????? 2.???????????????????????????????? 3.Outlook?????????????????? =================================================================================== ??-??-??-??: ???? ????????????????MBA ??IPMP??????????????????????MCP???????????????????????????? ?????????????????????????????????????????? ???????????????????????????????????????? ????????????????????????????????????10???????????????????????????????????????????? ???????????????????? ???????????????????????????????????? ???????????????????????????? ?????????????????????????????? ??Excle??POWERPOINT???????????????????? ????????????powerpoint???????????????? ?????????? ??????????????????????????????.???????????????????????????????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????? ???????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????? ???????????????????????????????? ??????????????????????????????????????DELL???????????? ???????????????????????????? ??????????????????TCL?????????????????????????????????????????????? =================================================================================== ?????????????????????????????????? ????????:2,200/???????????????????????????????????? ???????????????????? ------------------------------------------ M M C ?? ?? ?? ?? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????hrlawclub @126.com =================================================================================== From ewdar.0013k at hotmail.com Tue Oct 27 21:15:52 2009 From: ewdar.0013k at hotmail.com (ewdar.0013k at hotmail.com) Date: Tue, 27 Oct 2009 21:15:52 -0000 Subject: (no subject) Message-ID: <200910272115.n9RLFc0e020320@mx1.redhat.com> PMC-???????????????????????????? ????????????????PMC???? ---------------------------------------------------------------------------------------- ?????????? 2009??11??05-06?? [????] 2009??11??07-08?? [????] 2010??01??14-15?? [????] 2010??01??16-17?? [????] ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ---------------------------------------------------------------------------------------- ?? ??-??-??-???? ????????????????????????????????????????,??????????????????????????????,???????????? ????????????????.),????????(PMC)????????????????????????????????????.???????????????????? ?????????????????????????????????????????????? ??????????????????????????????????????.?? ????????????????????????????????????????:????????????????????????????????????(?????????? ????????????)????????????????????????,?????????????????????????????????? ?? ??-??-??-??: -???????????????????????????????? -?????????????????????????? -???????????????????????????????????? -???????????????????? -?????????????????????????????????????????????????????????? -???????????????????????? -?????????????????????????????????????? -??????????????,???????????? -?????????????????????????????????????? -?????????????????????????????????? -?????????????????????????????????????? -????????????,?????????????? ?? ??-??-??-??: ????????????????????????????/??????PMC(????????/????????)????/????/????????????????????/ ??????????????????/????????????????????????????????????????????/ERP??????????/?????????? ???????????? ?? ??-??-??-??: ????????/??????????????????/???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????,??????????????????.???????? ??????????????,????????????. ??????????????????????????????????????????????????/???????? ?????????????????????????????????????????????? ---------------------------------------------------------------------------------------- ?? ??-??-??-???? ??????:????????/????????/???????????????????? 1??????????/??????????????????--?????????????????? 2??????????/????????/???????????????????? --??????????????????????/????????/???????????????? 3??????????/????????????????--??????????????????????/????????--???? 4????????????????????????????- ????????????VS??????????VS???????????????? --????????????????/????????/??????????????????/?????????????? --???????????????????????????????????????????????????????? --?????????????????????????????????????????????? ????????????????????????/????????????(????)--?????????????? ????????????/?????????????????????????????????? 5???????????????????????????????????????????? ????????????/?????????????????????????????????????? ?????????????????????????????????????????????????? ?????????????D?D?????????????????????????????????????????????????????? --?????????????????????????????????????????????????????????????????????? 6????????????????????????????--????????????????????????(push)????????????????????(pull) ???????????? --??????????????.??????????Schneider???????????????????????????????????????????????? ?? --????????????/????/?????????????????????????????????????????????????? ? --????????????????????????????????--????????/????????/????????/????????/???????? ? --??????????????????????????????????????????????????/????????/????????/????????/???? ?????? ? --???????????????????????????????????? ??????????????/????????????--??????/???????????????????? 1??????????/??????????????????????--????/?????????????????????? ?????????????????????????????????????? --???????????????????????????????????????????? --????????????????/???????????????????????????????? --????????????/??/?????????????????? --??????????????????????????????????????- --??????????????????????????????????????????/???????????????????????????????????????? ???? --???????????????????????????????????????????????? ?????????????????????? --????????????????????????????????????/??????????????/???????????????????????????? --????????????????????????/???????????????????????????? --?????????????????????????????????????????????????????????????????????????????????? --?????????????????????????????????????????????????????? --??????(????????)ERP??SAP/R3?????????????????????????????? --?????????????????????????????????????????????????? --????????????????????????????(push)???????????????? --??????????????????????????(pull)????????????????????????????????- ????????????????????????--?????????????????????? --????????????????????????????/???????????????????????? --??????????????????????????/????????????????????/????????????????????/?????????????? ?????????????? --????????????????????????????????????/????????/?? ????????????????/?????????????? ???????????????? 2??????????????????(????)????--??????/?????????????????????? ??????/??????????????(JIT)???????????????????? ??????????????(JIT)???????????????????? --??????????BOSCH?????????????????????????????????????????? --??????????BOSCH???????????????????????????????????????????? --???????????????????????????????????????????????????????????????????????? --???????????????????????????????????????????????????????????????? --??????????????????????????(JIT)?????????? ???????????????????????? ??????????(IPK)KANBAN???? ?????????????????????? --????????????????????????????????????????????????--?????????????? --????????IE???????????????????????????? ?????????????????????????????????????????? --?????????????????????????????????????????????????? ??????????????--?????????????????????? ???????????????????????????????? ????PE/IE?????????????? ??????????/????????????????--?????? --?????????????????????????? ?????? ???????????????? 1?????????????????? --?????????????????????????????????????????????????? --???????????????????????????????????????????????????? 2????/???????????????????????????????????? --???????????????????????????????????????? --???????????????????????????????????????? 3???????????????????????? 4????????????????????????--????????/???????????? --??????????????2007/04???????????????????????? ??????????????????--?????????????????? ??????????????????--?????????? 5????????????????????????????????---- 1?? ??/??????????????????????????????????--?????? ??????????????/?????????????????? ?????????? 2???????????????????? 6?????????????????? 7??????????????????????--????/????/???? 1?????????????????????? 2????????????????????????????????????????????--?????????????? 3??????????LED????????????????????????????--???????? 8??????????????????????????--???????????????????????? 9????????????????????--???????????????????????? 10??????????????????????????????/????????????????????????--???????? 11??????????????????????????????????/????????????????--???????? ?????? ??????????????????????????--??????(OEM)/??????(ODM) 1????????????????????????--??????????????????(??????????????????) --??????????????????MRP??????????(????)???????? --??????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????????? --????????????????????????(????????)ERP--SAP/R3?????????????????????????????????? --??????????????????ERP-???????????????????????????????????? ?????????????????????? --????????Flextronics?????????????????????????? --??????????????????????????????????????????????--???????? --??????????????????????ERP-ORACLE????????????/?????????????????? 2?????????????????????????? 1????????????????????????????????--????????Flextronics???????????????????????????????? 2????????????????????????????/?????????????????????????????? 3????????????????????????/????????????????--??????????????????/TTi/??????????????/???? ????????????????/???????????????? 3??????????????????(????)???????????????? ????????--???????????????????? --?????????????????????????????????????????????????????????????????????? --??????????????????????????????/?????????????? --?????????????????????????????????????????????????????? --??????????????????????????????????????SQE?? --?????????????????????????????????????????????? ????????????(RIP)KANBAN???? ???????????????????? ??????????????KANBAN?????? ??????????????/???????????????? ???????????????????????? --???????????????????????????????????? --??????????BOSCH????????????????????????/???????????? --ABB/AREVA?????????????????????????????????? --???????????????????????????????????????????????????????????????? --?????????????????????????????????????????????????????????? --??????????????????????????/????/?????????????????????????? ??????JIT???????????????? --????????JIT?????????????????? --?????????????????????????????????????? --??????????????????????????????????????????Milk-Run?????????? --???????????????????????????????????? ??????????JIT??????--????????????????????/????/????/???? --???????????????????????????????????????????? --????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????? --????????????????VMI??--???????????????????????? --??????????VMI???????????? --??????????VMI?????????? --??????????????(????)??????????VMI?????????????????? --????????????????????????VMI ???????????????????? ??????????????????????--????????????????/???????????? --?????????????????? --???????????????????????????????????????????????????? --??????????ERP-ORACLE????SCP?????????????????????? ????????????????????????????????????(EDI)???????? 4?????????????? 1???????????????????????????? 2?????????? (BOM) 3??????????/????--?????????????????? --?????????????????????????????????? 4??????ABC???????????? 5??????ABC?????????? 6??????ABC????????.??ERP???????????????? 5?????????? ???????????????????????????????????? --???????????????????????????????????????????? --?????????????????????????????????????????????????????? ???????????????????????????????????? --????????????????????????--????????/???????????? --TCL????????????????????????--????lean time??????????????????VS????????VS.???????? ???????????????????? ????????????LOT-FOR -LOT?? ABC?????? ???????????????????????????? ???????????????????????????????????????????? ?????????????????????? ?????????????????? ???????????????????????????????????????? ???????????????????? ?????????????????????????? ????????????????????????????????????????????????????????????????????--?????????????? ????????????????????MTO /ROP ????????/??????????MOQ???????????????? --???????????????????????????????????????????????????????? --???????????????????????????????????????????? --??????????????????????????????/??????/?????????? ????/?????????????????????????????? --?????????????????????????????? 6???????????????????????????????? ????:?????????????????? 1??????/????????,??????????????????????????????- 2??????????????????--????????/????????/???????? 3??????/?????????????? ---------------------------------------------------------------------------------------- ?? ???????????????? --????????????MBA --???????????????????????? --????????????(AMA)?????????????? --????????/????????/????????/????????EMBA???????????????? --?????????????????@?? ?????????? 2004/2005/2006/2007???????????????????????????????????????????????????????????????????? ??????????????????????????????,????????????????????/?????????????????????????????????????? ??????????????/??????4920??????????(??2007??)????????????????????????????????????????.???? ??????????????????????????/????????????????????????????????????????????????????????????200 4/2005/2006????????????????????????????/????????????????????????(????/JIT-????/????????/?? ?????? ?????????? ????????????????,????????????????,??????????????,??????????????????????,????????????,?? ??????????????????????????????????.???????????????????????????????????????????????????????? ?????????????? ???????????????????????????????? ??????????????????????????/???????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????/?????????????????????? ????????????????????????????????????????????????????????/??????????????????Flextronics??/ ??????????Jabil??????????????????????????????????????????????????????????/?????????????????? ??????????????????????????????????????????/??????????????????????/?????????????????????????? ??(MeadJohnson)????????????????????????????????????????????????????????/???????????????????? ????????/???????????????????????????????????????????????????????????????????????????????????? ??ABB???????????????? ???????????? ????????????????????????????????????TCL??????/?????????????????????????????????????????????? ????????????????????????/????/????/?????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????????????(????)?? ??????????(????)?? ??????????????????????????????????????????????TOTO????????????(arrow)?? ?? ????????????Delta?????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????? ????????: ??????????????????????????????????????,??????????????????????????????????????,???????????????? ????????,????????. --??????????????????????????????????????????????/?????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? --????????(????????)/???? ????????????????????????????????????????????????????????????????????,?????????????????????????? ??,????????????????????????????. --??????????????????????????????????/?????? ---------------------------------------------------------------------------------------- ???????????????????? ------------------------------------------ M M C ?? ?? ?? ?? / M M C ?? ?? ?? ?? ?? ?? ??????????2??600?? /2 ??/ ??(??????????????????????????????????????????????) ---------------------------------------------------------------------------------------- ?? ?? ????FAX??0 2 0-345,068,95 ) ---------------------------------------------------------------------------------------- ???????? ??-??-??-????: ????????: ???? : ????????: ????????: ---------------------------------------------------------------------------------------- ??-??-??-??-??-???? ???????????????????????????? ????????: ????????: ?? ????????------------------------ ------------------------ -------------------- ????????------------------------ ------------------------ -------------------- ?????????? ?????????????????? ??1?????? ??2?????? ??3?????? ??4?????? From weh at yujx.com Wed Oct 28 20:08:03 2009 From: weh at yujx.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Wed, 28 Oct 2009 20:08:03 -0000 Subject: (no subject) Message-ID: <200910282007.n9SK7mUB026948@mx1.redhat.com> ???????????? ????? ?????2009?11?13--14? ?? ?????2009?12?4-5? ?? ????: ????????????????????????????????????? ????: 2800?/????????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------------- ?????500??????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ???????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????????????? ------------------------------------------------------------------------------------------ ???? ????????????? ?????GE?????? ?????????????????? ???????????? (1)?????? (2)??????? (3)??????? (4)???? (5)???? (6)?????? ???????????????????????? ????????????? ??????????? ???????????????????? ????????????????????????? ????????? ??????? ??????????? ?????????????????? ?????????????????????????? ??????????????????????????? ??????????????????????????? ??????????????? ???????????????? ????????????????????????????? ???????????????????????????? ????? ???????????????????????????????????????? ?????????????????? 360???????? KPI ??????? MBO ?????? BSC ?????? ?????????????????? ??????????? ??????????? ??????????? ??????????? ??????????? ??????????? ??????????? ???????????????????? ??????????? ???????????????????? ??????????? ????????? ??????? ????????? ???????????? ?????? ????? ??????????????? ??????????????????? ???????????????????? ??????????????????????? ??????????? ??????????????? ???????????--???????? ??????????????????? 1.???????? 2.????????? (1)?????????????? (2)?????????????? (3)???????????????? (4)??????????? (5)????????????????? 3.?????? (1)?????????? (2)????????? (3)??????????????????? (4)?????????? (5)?????????????7????13??????? (6)?????????????????????? 4.???????? (1)????? (2)?????????? 5.?????? (1)???????? (2)??????? (3)???????? (4)????????? 6.??????????? (1)?????????????? (2)?????????????? (3)??????????????? 1)?????????? 2)??????????? 3)????????? 4)????????? 5)?????????? ????????????????? ???????????????????? ?????????????? ???????????????????? ?????????? ?1?????----??????? ???????????????????? ????????????????????? ?2?????----???????????? ?????--?????????????? ?????--??????? ?????--???????? ?????---????????????????????????????? ?3?????---????????? ?????--????????????????? ?????--??????????????????????????? ?????--????????????? ?4????????????????????? ?????????????? ??????????????? -------------------------------------------------------------------------------------- ????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ?????3C???????????DELL(??)?????(??)?VAG???????????? ??????????????????????????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????? ????????????????????????????????? ????? ? ???????????????????????? ????? ? ???????????????????????? ????? ? ??????????????????????? ????? ? ????????????????????????? ????? ? ?????????????????????????????????????? ????????????????? ???????????????VIP????????????????????????????? ??????????? ----------------------------------------------------------------------------------- ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From pfu at ewgr.com Fri Oct 30 07:55:48 2009 From: pfu at ewgr.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Fri, 30 Oct 2009 07:55:48 -0000 Subject: (no subject) Message-ID: <200910300755.n9U7tZ9M028917@mx1.redhat.com> ???????????????? ?????2009?11?13-14? ?? ? ?????2009?11?20-21? ?? ?????????????????????????????????????????????? ??????????????????????????????? ?????2800?(???????????????????????) ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------- ??????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????? ????? ?????????????????????? ????????????????????? ?????????????????????? ????????????????? ??????????????????? ??????????????? ??????????????????? ?????????????????? ????????????????????? ?????????????????????? ???????????????????? ??????????????????? ??????????????????? ????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????? -------------------------------------------------------------------------------- ????? ??????????????? 1???????????? ??1?????????????????????????? ??2?09?????????? ??3?????????????? 2??????????? ----????????????? ?A?????????????? ?B???????????? ?C???????????? ?D?????????????? ???????????????????? ??????????? ???????????? ?1???100%?????? ?2???100%?????? ?????????? ?1???????? ?2??????????????????????? ???????????? ?1???????? ?2???????? ????????????????? ?????????? ?1???? ?2???? ?3???? ?4???? ?5???? ???????????????????? ?????????? ?1??????? ?2???????? ?3???????? ?4????? ?5?????? ???????????????? ????????????? ???????????????? 1???????? ?1????? ?2????? ?3????? 2?????????? ?1??????? ?2??????? ?3????????? ?4??????? ?5??????? ?6??????? ?7????????? ???????????? ???????????????????????????? ?1????????? ?2?????????? ?3?????????????? ?4??????????"?"????????????????????? ?5?????????????????????????? ?6????????? ?7????????? ??????????????????????????????????? ?1????????????????????? ?2???????????????????? ?3???????????????????????? ????????????? ?1???????????? ?????? ???? ?? ???? ????? ????? ?2???????????? ????????????? ????????????? ????????????? ?????? ?3???"??"??"??"??? ????????????? ?1???????????????????????? ?2?????????? ???1??????? ???2????????? ????????????? 1?????????? ?1???????????? ?A??????????????????? ?B?????????????????????????? ?2?????????????????? ?3????????????????????? ?4???????????????????????? 2???????????????? ?1??????????????????????????????? ?2???????????????????????????????? ?3????????????????????????????????? ????????????????? ????????????? ??????????????????????????? ??????????????? ?1????????? ?2????????? ?3????????? ?4????????? ?5???????? ?6???????? ?7?????????? ?8???????????? ?9??????????? ?10????????? ????????????? ?1???????? ?2???????? ?3???????? ?4?????????? ?5???????? ?6?????????? ?????????? 1???????????? ??1????????????????????????? ??2???????????????? 2????????????????? ??1?????????? ??2???????????????????? ??3??????????????????? ------------------------------------------------------------------------------------------------- ?????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????????????? ? ---------------------------------------------------------------------------------------------- ???????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! ? From ghjkt.cfdv at aol.com Sat Oct 31 16:45:16 2009 From: ghjkt.cfdv at aol.com (ghjkt.cfdv at aol.com) Date: Sat, 31 Oct 2009 16:45:16 -0000 Subject: (no subject) Message-ID: <200910311645.n9VGj3eP019126@mx1.redhat.com> ============================================================================================== ???????? ============================================================================================== ?????? 2009?11?20-21? ?? 2009?11?27-28? ?? 2009?12?17-18? ?? 2009?12?19-20? ?? 2009?12?25-26? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ? ??hrlawclub @126.com ============================================================================================== ?-?-?-?: --??????????????????????????? --??????????????????????????? --??????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ???????? ?-?-?-?? ???????????????????? ?-?-?-?? ????-????-????-????-????? ============================================================================================== ?????????????? 1????????? 2???????????? 3???????????? 4???????????? ?????????????? ??????????? 1???????????? 2??????????????????? 3?????????? ??????????? ??????????? 1??????? 2??????????? 3????????? 4???????????? 5????????????? 6??????????? 7??????????? ???????-????-???? ????????????? 1???????? 2??????????? 3?????????? ?????????????? 1. ?????? 2. ???????? 3. ??????????? 4. ????????? 5. ????????? 6. ??????? 7. ??????? 8. ???????? 9. ????????? 10. ?????????? 11. ?????? 12. ???? ??????????? 1??????????????? 2????????? 3???????????? 4???????????? 5????????????????? ????????????? 1????????????? 2??????4??? 3??????5?? 4?????????? ???????????? ??????????? 1??????????????????? 2???????????? 3??????????? ??????????? 1???????????? 2?????????????? 3?????????E-mail????? 4?????????????? ????????????? 1???????????? 2?????????????? 3?????????????? ??????????????? ============================================================================================== ?-?-?-?: ???: -?????????? -?????????? -???????????? -?????????????? -????????????(CAML)?? -????????????(IHRL)?? -???????????????? -?????????ICMCI -???????????? ????? ??????????????????????????????????????????????? ?????????????????????????????????????? ????? ??????2001??????????????????????????????????????? ??????????????????????????2008?????????????300???? ????8000????????????50000?????????????????????????? ???????????????????????? ????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ICMCI????????? ???????????????? ??.???????????????????????????? ??????????????????? ????? ????????????TTT?????????????LTT????????360????????? ?????????????????????????? ????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????? ============================================================================================== ? ??2,500 /?(??????????????) ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ? ??hrlawclub @126.com ============================================================================================== From grtu.dwvx at msn.com Sat Oct 31 20:56:52 2009 From: grtu.dwvx at msn.com (grtu.dwvx at msn.com) Date: Sat, 31 Oct 2009 20:56:52 -0000 Subject: (no subject) Message-ID: <200910312056.n9VKudGD010911@mx1.redhat.com> ============================================================================= ????????????? ============================================================================= ?????? 2009?11?27-28? ?? 2009?12?18-19? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ? ??hrlawclub @126.com ============================================================================= ????? ????????????????????????????,???????? ???????????????????????????????????,??? ???????????????????07?????????????,????? ????? --?????????????????? --?????????????????????????????????? --????ISO-9000?TS16949????????????????????????? ??? --???????????????ERP?????????????? --????????????????????????????????????? --??????????????????????????? --??????????????????????????? --????????????????????????????????????? --??????????????????????????????? ?????? ?????????????????????????????????????? ???? ????: ?????????????? ????? 2?/13??? ============================================================================= ???? ???????? ????????????????????????? ?? ?????????? 1? ??????? 2? ?????????????????????? 3? ???????????????????? ??????????????????????????? ???????????????????????????????????? ?????????? 1? ?????????????????????????????? 2? ???????????? 3? ??????PMC??????????? 4? ?????????? 5? MRP?ERP?????????? ???? ????????? ?? ???? 1? ????????? 2? ?????? ?? ?????? 1? ?????????/????????? 2? MRP??????????????? 3? ??????MRPII?ERP????????????? ?? ???????? 1? ?????????????????? 2? ???????ABC??/????/????/??????/??????????? ?????? 3? ?????????????????????? ??????VMI???? 1?VMI???????????? 2?VMI????????????????? ??????????? 1? ??????? 2? ?????????????????????????????? ?????????? 3? ??????????? ???????? 1? ????????????????? 2? ????????????????? 3? ???????????????????????????? 4? ????????????????????????????????????? ??? 5? ???????????????????????????? 6? ?????????????????????? ??????????????????? ???? ?????? ?? ????????????????? 1? ??????????????????? 2? ????????????????????????????????????? ???? 3? ???????????????? 4? ????MRP???????????????MRP?????????? 5? ????????????????????????????????????? ?????????????? ????????? 1? ??????????? 2? ?????????????????? 3? ?????????????? ?????????? 1? ????????????????????????????????????? ??? 2? ?????????????? 3? ?????????????? ??ERP?MRP????????????????????????????????? ????????? ???????????????? ????????????? 1? ?????ISO-9000?16949????????????????? ????????????????? 1? ???????????????????????? 2? ????????????????????????????????????? ???? ????????? ???????? 1? ??????????????????????????? 2? ??????????????????????????????? 3? ?MRP??ERP????????????????????? ???????? 1? ?????????????????????????? 2? ??????????????????????? 3? ???????????????????????????????????? ???????????????????? 4? ?????????????? ??????????????? 4? ?????????? 2?????????????? 3???????????? 4?????????? ???????? 1? ??????????? 2? ???????? 3? ????????????????????????????????? ???? ?????? ?? ????????? ??????????????? ???????????? 1? ???????????? 2????? ?????????? 1? ?????????????? 2? ???????????????????? ???? ?????? ??????????????????? ???????????????? ??????????? 1? ?????? 2? ??????????????????? 3? ???????????????????????????? ??????????? 1?????????? 2???????? ????????????? l ????????????????? l ????????????????? ??????????JIT?VMI 1????JIT????? 2?????????VMI????? ?????????????VMI?????? 3????JIT???????? ????????????????????????? 4? ?????Milk-Run????? ???????SGM???TNT?????????? ?????????????? ???? ?????? ?? ??????????????105???? ???????????????????????105????? 1. ????????????? 2. ?????????? 3. ????????? ????????????? ????????????????????????? ???? ?????? ?? ?????? ???????????? ?????????????????? ??????????????????? ???? ???????? ?? ?????????? ?? ???????????? ??????ERP??????????? 1? ??????????? 2? ?????????????? ============================================================================= ? ????:??? ???????M M C ???????????? ?????????? ??? ?????????????????????????????????????? ??????????????ISO-9000?TS16949?GMP????????????? ????????500?????????? ?????????????????? ???????????????????????PMC?? ??????????? ?????????????????????????????????????? ?????????????????????????????????????? ????????????????????????????????? ????????????? ????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????? ??/??/??? ?????????????????????????????????????? ?????????????????????????????????????? ??????? ????? ?????????????????????????????????????? ?????????????????????????????????????? ???????? ???IT/??? ?????????????????????????????????????? ?????????????????????????????????????? ?-????????????????????????????NEC??????? ?????????????????????????????????????? ???? ????? ???????????????????EMERSON????????????? ?? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????? ???? ?????????????????????????????????????? ?????????????????????????????????????? ???????????????? ??/??? ???(??)???????????????????????????????? ???????????????????? ============================================================================= ?????2800?/???????????????????? ?????????? ------------------------------------------ M M C ? ? ? ? / M M C ? ? ? ? ? ? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ? ??hrlawclub @126.com ============================================================================= From iuf at wegz.com Tue Nov 3 07:06:51 2009 From: iuf at wegz.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Tue, 03 Nov 2009 07:06:51 -0000 Subject: (no subject) Message-ID: <200911030706.nA376dbK002858@mx1.redhat.com> ???????????????????? ?????2009?11?21-22?? ? ? ?????2009?11?28-29?? ? ? ? ??2500?/????????????????? ???????????????????????????????????????????????????SOHO?? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------------- ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????????????????????? 1??????????????????????????? 2???????????????????????????????? 3?????????????????? 4???????????????? 5??????????????????????? 6????????????????????? 7??????????????????????????????????????????????? 8????????????????????? 9??????????????????????????????? 10???????????????????????????? 11???????????????????????????? 12?????????????????? 13?????????????????????????????????? 14???????????????????????????????????? 15?????????????????????? 16??????????????????? 17?????????????????????????????????????????? 18???????????? 19???????????????????????? 20????????????? ------------------------------------------------------------------------ ????: ??? ???????????????? ???????????????? ???????????????? ???????????? ????????????????????????? ??????????????? ??????????????? ????????????????? ??? ?????????????? ??????????? ??????????? ?????????????????? ?????????????????? ??????????? ???????????????????? ?????????????????? ??????????? ??? ??????????? ?????? ?????? ?????? ?????? ?????? ??????????? ??????????? ??????????? ???????????? ??????????? ?????????? ??? ?????????????????? ???????????????? ???????????? ???????????????? ??????????????? ??????????? ?????????????? ???????????? ?????????? ??? ??????????? ???????????? ???????????? ??????????????? ?????????????????? ?????????????? ???????????? ????????????? ??? ?????????????? ???????? 1??? 2??? 3??? 4?????? 5??????? 6??????????????? ?????????????? 1???? 2???????????? 3???????????? 4?????? 5?????????? 6???????? 7???????? ????????? ?????????????? ????????? 1????? 2?????? 3?????? 4??????? 5????????????????? 6????????????????? 7?????????? 8?????????? 9?????????? 10?????????????????? 11????????????? ?????????????? ??? ?????????? ?????? ?????????????? ???????? ???????????????? ???????? ?????????????? ???????????????? ??? ????????? ????????? ?????????????????? ?????????? ????????????????????????????? ?????????????? ??????????? ??????????????????????????? ??? ???????????? ????????? ?????????????????? ????????? ?????????????????? ?????????????????? ?????????????????? ??????????????????????? ------------------------------------------------------------------------------ ?????????????(???????MBA??????????)??????????????? ???????????????????????????????????????????????? ????????????????????????????????????????(?)?????? ?????????????????????????????IBT??????????? ?????? ???????????????????????????????????????????????? ????????????????????????????????????????? ??? ???? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????? --------------------------------------------------------------------------------------------- ???????????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From wegho at bnid.com Tue Nov 3 22:47:53 2009 From: wegho at bnid.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Tue, 03 Nov 2009 22:47:53 -0000 Subject: (no subject) Message-ID: <200911032247.nA3MkO3Y018863@mx1.redhat.com> ???????????? ?????2009?11?20?21? ?? ?????2009?12?11?12? ?? ???????????????????????????????????? ?????2500?/??????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? ---------------------------------------------------------------------------------------- ?????500?/????????????????????????????????????? ?????????????????????????????????????????????? ???????????????60%?80%??????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????? ---------------------------------------------------------------------------------------- ???? ?1???????????? 1.?????????????? 2.????????? ????????????? 3.????????????? ????????Sourcing?????Buyer/Purchasing ??????Receiving/QC??????SupplierManagement 4.???????SRM ??????Intel?AMD??? 5.???????????? ????????????????????? ???????????????LT? ??????????????????????????? ?2???????? 1.?????ABC?? 2.???????? ?????????????????????? 3.??ABC?????????????? ????????? 1)??????????????????? 2)?????????? 3)???????????????????? 4)???????? a)??????????????????????? b)???????????? ????????? 1)????????????? 2)???????????????????? 3)???????????????????????? 4)??????????????? 5)???????????JIT???VMI? 6)???????????? ????????? 1)??????????????? 2)???????????????????????????????????????????? 3)???????????????? 4)???????? 5)????????? 6)?????????????? ????????? 1)??????????? 2)?????????????????? 3)?????JIT??????? 4)??????????????????????????? ????????????????? ???????????????????? 4.?????? ????????????????????OEM?ODM?CM???? ?3????????? 1.??????????? ???????????????????????? ??????????????????????????? ???????????????????AVL ????????????????? 2.???????????? i.?????????? ??????? ii.?????????????????????????????? iii.????????? iv.??????????? 3.?????????? 4.?????????? ??????????????????? ?4???????????? 1.?????????? 2.????????????????? 3.????????? 4.????????????? 5.????PDCA?6-Sigma 6.?????????? ?5??????????? 1.???????????????? ???????????????BNSF?????????? 2.????????? ??????????PI???????????SPI 3.????????? ?6??????? 1.???????2.????????????????? 3.?????????4.???????Break-EvenPoint 5.???????6.?????????VA/VE ?7??????? 1.???????? 2.??????????? 3.??????????????????? 4.???????????? a)????????????b)???????????? c)?????????????? 5.??????????? 6.????????????? ?8??????? 1.???????????2.??????? 3.????????????4.?????????????????? 5.????????? 6.??????? a)????b)????c)???? 7.???????POCKET?? 8.?????POCKET9.???????????? ---------------------------------------------------------------------------------- ???????????1984??????????????1986??????????MS?? 1992??????????????863/CIMS????????????????????? ???????1992-1996??????LeedandNorthrup???????????????? ????????????????????????????? 1996??2000??IBM????ERP/SCM???????????????????(ERP)??? ???(SCM)???????????????????????????????????? ?????????????????????????2000??????????????? ??ManufacturingandDistribution?????????????????????????? ?????????????????????????????????????????? ??????????CPC??????????????????????????????? ????????????? ???????????????????????EMBA????????????????? ?????????????????????????????????????????? ??????????????????????????????????????? ?????????????????????TCL???TCLAV?????????????? ???3M?????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ???????????????? =============================================================================== ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From ytu at hgjy.com Wed Nov 4 02:43:23 2009 From: ytu at hgjy.com (=?GB2312?B?16rQ6MfzyMvUsQ==?=) Date: Wed, 04 Nov 2009 02:43:23 -0000 Subject: (no subject) Message-ID: <200911040243.nA42h89M003284@mx1.redhat.com> ?????KPI+BSC????? ?????2009?11?13-14? ?? ?????2009?11?19-20? ?? ?????2009?11?21-22? ?? ?????2009?12?18-19? ?? ??????????????????????????????????????? ?????2600?/?(?????????????????) ???????600?/?;??800?/?(??????????????????????????????) ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------------- ????? ??????????????????????????????????????????????????????? ?????????????? ??????????????????????????????????????????????????????? ?????????????????? ???????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????? ????????????????????? ????????KPI?????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ?????????????? ????????????????????? ?????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ?????????? ??????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????? ??????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????????????????????????????????????????? ??????????? ???????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????????????????????????????????????????????? ??????????????? ?????????????????? ?????:???????????? ?????????? ??????????????????????????????????????????????????????? ???????????????????????????????????KPI????????????????? ---------------------------------------------------------------------------------------------- ????? ????KPI???????????????? 1?????????????????? ????????????????????? ????????????? ????????????? ?????????????? ?????????????? ??KPI??????????? 2????????????????????? ?????????????? ????????????? ???????????????? 3????????KPI??? ??KPI?????????? 1????????? 2?KPI?????????????? ?????????????????????? ??????????????????????? ?????????????????????? 3?KPI??????????KPI????????????????????????????????????? ????KPI???????? ?????????KPI???????????????????????????????????????????KPI??????? 1???????????????????????KPI????????????????? 2?????????????? 3?????????????? 4?????????? ??????? 1????????????????????????????? 2????????????????????????? 3?????????????????????????????????????????????? 4??????????????? 5???????????????????????????????? ?????????????????? 1????????????? 2??????????? 3????????????????????KPI????????? ??????KPI ??KPI??????????????????????KPI?????????????????kpi???????????????????? ???????????????KPI???????? 1?????KpI??????????????? 2??????2????? 3?????????KPI???3?????? 4???KPI?????????????????????????????????? ????????? ??????????????????????????????KPI?????KPI? 1????????KPI 2?KPI????????????? 3?KPI???????????? 4???????KPI??????? ????????KPI????? ???????????????????????????????????????????????? 1????????? 2????????????? 3?????????????????????? 4?????????????????????KPI?????? ????????? ??????????????????????????????????????????????????????? 1????????????? 2????????? 3?????????????? 4?????KPI????????????? ????????? ???????????????????????????????????????? ???????????????????????????????????????? 1?KPI????????? 2?????????????? 3????????????????? ???KPI????? ??????????????????????????????KPI??????????? 1???????????????????????????? 2???????????????? 3??????????????????????? 4?????????????? ??????????????????? ????KPI???????????????????KPI???????????????? 1????????????????????? 2??????? 3????????????? 4??????????? ------------------------------------------------------------------------------------------ ??????? ????---?????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???? ???????????????????????????????????????????????????KPI ??????????????BSC???????????????????????????????? ?????????????????????????????????????????????TCL?????? ????????????????????????????????????????????????????? ????????????????????????????????????????????????????? ???????????????????????????????????????? ----------------------------------------------------------------------------------- ??????KPI+BSC???????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From Henry.4587 at hotmail.com Sat Nov 7 19:35:21 2009 From: Henry.4587 at hotmail.com (Ji.Henry) Date: Sat, 07 Nov 2009 19:35:21 -0000 Subject: (no subject) Message-ID: <200911071935.nA7JYvJJ004737@mx2.redhat.com> ============================================================================= ??????????????? ============================================================================= ?????? 2009?12?19-20? (??) 2009?12?26-27????? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ? ??hrlawclub @126.com ?.?.?.?:????????????????????????????? ============================================================================= ?.?.?.? ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????? ????????????????????? ???????????????? ?????????? ????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ? ????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??? 1???????????????????? 2?????????????????????? 3??????????????????????? 4?????????????????????????????????????? ??? ?.?.?.? 1???????????????? 2????????????????? ?.?.?.? ??????????????????????IE??????????????? ???? ????-????-???? ???? 2??13???? ============================================================================= ???????????? ????????????????? ??????????????? ?????????? ?????????????? (?????????????JIT?) ????????????????? ????????????????? ???????????????????? ????????????????? ????????????????? 1??????????? 2???????????? 3????????JIT??? 4???????????????????? 5?????????????????????? 6???????????? 7???????????? ??????????? ????????? ???????????? ????????????? ??????? ??????? ????????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ????????????? ??????????? ?????????? ?????????? ?????????? ?????????? ?????????? ???????????? ???????????????? 1?????????????? ?????? ?????? ????? 2??????? ????????? ????????? 3???????????? 3.1??????? ????? ???? ?????? ?????? ?????? ?????? ?????? 3.2??????? ?????? ????????? ???? 3.3??????? ?????? ??????? ?????? ?????? ???? ???????? ============================================================================= ???????? ??????? ????????? ?MMC?????????? ?????????????????????IE???????? ??????? ???????????????????????????????? ??WF&IE?? ??????????????????????????????????????? ???????????????JIT??????NPS??????????????? ????????????(??,??,??,??,??,??)??????:????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????????????????????? ????????????????????????????????????? ????????ABB???????????????-?????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????? ??????????????????,?????????????????? ??????????????????????????????????????? ??????? ============================================================================= ????????M M C ? ? ? ? ? ? ?====??2,600?/? ???????????????????????? ?.?.?.?:????????????????????????????? ============================================================================= From muf at tbwe.com Wed Nov 11 05:15:20 2009 From: muf at tbwe.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Wed, 11 Nov 2009 05:15:20 -0000 Subject: (no subject) Message-ID: <200911110515.nAB5EgBr002107@mx1.redhat.com> ?????? ?????2009?11?23-24??? ?????2009?11?26-27??? ?????2009?11?30-12?1??? ?????3200?/????????????????????*?????????* ????????????????????????????? ???????CEO/?????????/?????????????/?????PMO??????? ??????????QA??? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------------------- ???? ????????????????54????????????????????????????? ????????????????????? 1.?????????????? 2.????????????????????? 3.????????????????????? 4.?????????????????????????????? 5.??????????????????????????????? 6.??????????????????????????? 7.???????????????????????????????? 8.??????????????????????????????? ??. ??????????????????????????????????????????????? ???????????????????????????????? -------------------------------------------------------------------------------------------- ???? 1)???????????????????? 2)???????????????????????? 3)?????????????????? 4)??????????????????????? 5)?????????????????? 6)??????????????????????? 7)????????????? 8)????????????????????? 9)???????????????????????????? 10???????????????????????? ---------------------------------------------------------------------------------------------- ???? ??????????????????????????????? ?????????? 1.??????????? 1)??????????????? 2)?????????????????? 3)???????????????????????IT???????? 2.?????????????????? 1)?????????????????? 2)????????????????????????? 3)????????????????????????? 4)???????????????? 3.????????????? 1)???????????NPD??? 2)NPD?CMM/CMMI??? 3)ISO9000?TL9000?QS9000?16949?GJB?????????? 4)????????????????????????????? 5)??????????? ?????????? 1.??????????? 1)???????????????? 2)?????????????????????? 3)?????????????????????????????????? 4)?????????????? 5)?????????????? 6)?????????????? 7)??????????????????????????????? 8)??????????????????????? 2.??????????? 1)QA?QC?????????? 2)?????????QA?QC??? 3)PQA?SQA?HQA?TQA?MQA?? 4)???????????????????????? 5)???????QA?????? 6)??QA???QA?????? 7)????QA??? 8)????????????????????????? ??????????????? 1.?????? 1)?????????????????? 2)??????? ?????????????????????????? ????????????????????????????? ???????????????????????????????????? ??????????????WBS? ????????????????????????????? 2.????????? 1)?????????????????????????????? 2)???????????????????? 3)??????????????? 4)???????????????????????????? ???????????????????? 1.????????????? 1)???????????????????????????????? 2.????????????????? 1)?????????????????????? 2)???????????????????????????? 3)???????????????? 4)???????????????? 3.?????TR? 1)TR?????? 2)TR??????????????????????????? 3)???????????????SE?PM?QA???????? 4)????????????????????? 5)?TR?????????????????????????????? 6)TR??????????? 7)???TR???????????????QA???????? 8)??????????????????????????????? 9)?????????????/????????? 10)????????????????????????? ???????????????????? 1.????????????? 1)???????????????????????? 2.????????????? 1)???????????? 2)ALPHA???BETA????? 3)??????????????IBT??BUILD???????? 4)????????????? 3.???????DFT? 1)??????? 2)???????? 3)???????????????DFT?? 4.??????????????????????? ??????????????? 1.???????QA???? 1)QA???? 2)QA?QC??? 2.QA??????????PQA?SQA?HQA?TQA??? 3.QA???? 1)????????????? 2)??????????? 3)????????????? 4)????????????TR? 5)????????? 6)????????????? 7)????????????? 8)??????????? 9)?????????PHB 10)??????????????? 4.?????????????????? ??????????????? 1.????????????? 1)?????????????????????????? 2.????????????????????????????? 3.?????????????????????????????????? 1)?????????? 2)????????? 3)???????????????????????PCB? 4.??????? 1)?????????????????? 2)????????????????? 3)??????????????????? 4)??????????????????? 5.??????? 1)??????????? 2)????????????????????????? 3)????????????? 4)????????????? 6.???????????? 7.??????????????????????? ??????????????? 1.??????? 2.????????? 3.???????????DFX?FMEA? 4.?????????? 5.??????????????? ???????????????????????????????IT? -------------------------------------------------------------------------------------- ??????????????????CMM/CMMI???? ?????????????????????????????????????????????? ??????????????????????? ????????????????????????????????????????????? ?????????NGN???????? ????????????????????????????????????????????? ???????????????????????????????????CMM????????? ????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????(????)???? ???????????????????????????????????????CMMIL4??? ?CMMIL2????????????????????????????????????????? ?????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ??????????????????????????????????????????? ????????????????????????????????????????????? ????????????????????????????????????????????? ????????????? -------------------------------------------------------------------------- ??????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From nkakm at ybzhan.com Wed Nov 11 07:44:40 2009 From: nkakm at ybzhan.com (=?gb2312?B?zOzIu82tzPW3or6nI8rWwbQ=?=) Date: Wed, 11 Nov 2009 07:44:40 -0000 Subject: (no subject) Message-ID: ????#?? ?????? ??? ???? WwW.KakM.cN utrace-devel 3lklm-2009-11-11=15:34:28 -------------- next part -------------- An HTML attachment was scrubbed... URL: From sfrd.kpli at yahoo.com.hk Wed Nov 11 16:33:36 2009 From: sfrd.kpli at yahoo.com.hk (sfrd.kpli at yahoo.com.hk) Date: Wed, 11 Nov 2009 16:33:36 -0000 Subject: (no subject) Message-ID: <200911111633.nABGXYWp016799@mx1.redhat.com> ============================================================================================== TPM-????????????? ============================================================================================== ?????? 2009?11?26-27? ?? 2009?12?04-05? ?? 2009?12?11-12? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ?????2600?/???????????????????? ??????????????????/??/???/???????????? ???????????TPM?????????? ============================================================================================== ?-?-?-?: ??????????????????????????????????TPM????????? ??????????????????????????????????????????????? ??????????????????????? ?-?-?-?? --?????????????????????????????? --??TPM???????OEE????????OEE???5S?TPM???????????--?????? ???????TPM???????TPM???? ????????????????????????????????????? ?-?-?-?? ?????????????/??/???/??????????????????TPM???????? ? ?-?-?-?? ?????????????????? ============================================================================================== ?-?-?-?? 1?TPM?? TPM????????? TPM????? ???????? TPM?????? TPM?????????????????? ???????? ???????? ????????? ???????? ?????????????? 2??????? ????????????? ????????? ??????????? ?????????????????? ??????? TPM??????? ???? ???????OEE? ???OEE ??OEE?????????????????????? OEE???????????????????????????OEEOEE ????OEE??????? ????OEE??????OEE????????? ??????OEE??????? ????TPM???MTBF?MTTR???????? 3? TPM??????? TPM?????????????????????????? ???????????????? ?????????????PM??????????????????,?????????????? ????5S????????????????????TPM 4?TPM??????5S????? 5S?TPM??? ???????5S?? 5S?????????????????? ?????? ?????????????? ?????????????? ??????????? 5S?TPM?????? 5?TPM????????? ?????????????????????? ?????????????????? ??????????TPM?????????????PM ?? ???????PM?????????? ???????PM?????????????? ??5S?????????????? ??OEE???TPM???TPM???? ???? 6?TPM????? SMED????????????? ?????????????? ??????????? ????????, ??????? ?????TPM??,??????? 7???????????TPM?KAIZAN?? ???KAIZAN ???????????CIP(??????) TPM?KAIZAN???? ============================================================================================== ?-?-?-?:??? -MBA -?? Lean Master ?IE ?? -????????? ? ?93?????????????1??TPS??????????????????IE??????? ?????????????????????????? ??Delphi?????????????????????????????TPM?????????? ??????????????????Kaizen??????????????????????? ??? ??????????????????????????????????? ???????????????????????????????????????? ?????????????????????????????????????????????? 5S ? KANBAN ? Kaizen ???????VSM??????????????????????????JIT ??????TPM?????????????????????????????IE?????????6- sigma ???????????? ?????????: --??????????TPM????; --????????IE???????????MOD????????????????20%? --?????????????TPM?????????????? --???????????????TPM???????????30%? --????????????????LP?????????????????????????????? ?????? --???IT?????????????????? ?????????????????????????????????????????????? ??????????????TCL?????????? ?????????????????????? ????????????????????????????????????? ============================================================================================== ?-?-?-??M M C ? ? ? ? ? ? ???????0 2 1 - 5109?9475 ???????0 2 0 - 3397?2216 / 3366,5697 ?-?-?-?: ?????-?-? ? ???-?? ? ????? ? ?????? ?====??2,600?/? ????,???????????????????? ============================================================================================== From uyji.3681b at yahoo.com Thu Nov 12 14:24:44 2009 From: uyji.3681b at yahoo.com (uyji.3681b at yahoo.com) Date: Thu, 12 Nov 2009 14:24:44 -0000 Subject: (no subject) Message-ID: <200911121424.nACEOe78016631@mx1.redhat.com> ?????????????????????????????????????????? --------------------------------------------------------------------- ???????????? 2009??11??23-24?? ???? 2009??11??25-26?? ???? 2009??11??30-12??1?? ???? ?????????????????????????????????????????????????????????? ??????????????CEO/??????????????????/??????????????/???????????????? ????????????????/??????????????????????????????????????PMO?????????? ???????????????????????????????????????????????? ??????????3200 ??/2???????????????????????????????????????? ??????????????????400-8899,628 ??????????????021-5109,9475 ??????????????020-3366,5697 / 3452,0981 ?? ????rdwork at 126.com --------------------------------------------------------------------- ?????????? ??????????????????????????????????????????????????95%?????????????? ??????????????????????????????????????????????,???????????????????? ??????????????????????,???????????????????????????????????????????? ????????????????,?????????????????????????????????????????????????? ????????????????????????????????????????????????????????????,?????? ????????????????????????????????????????,?????????????????????????? ??????????????????????????????????????????????.???????????????????? ???????????????????????????????????????????????????????????????????? ??????????????????,???????????????????????????????????????????????? ?????????????????????????????????????????? --------------------------------------------------------------------- ?????????? 1.?????????????????????????????????????????????????????????????????? ?????????????? 2.???????????????????????????????????????????????? 3.?????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????????? ?????????????????? 5.???????????????????????? 6.?????????????????????????????????????????????????????????????????? ?????????????????????????????????????? 7.???????????????????????????????????????????? 8.???????????????????????????????????????????????????????????????????? ?????????????? Action Plan?????????????????????????????????????????? -------------------------------------------------------------------- ?????????? ??????????????0.5?? 1)???????????????????????? ????????????????????????????????????????1.5?? 1)???????????????????????????????????? 2)???????????????????????????? 3)???????????????????????????? *???????????????????????????????????????? *??????????????10?????????? *???????????????????????????????????????????????? *?????????????????? 4)?????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????????????????? 5)???????????????????????? 6)?????????????? 7)???????????????????????????? *?????????????????????????????? *???????????????? *???????????????????????? *???????????????????????????????? *???????????????????? *???????????????????????? *???????????????????????????? *???????????????????????????? *?????????????????????????????????????? *?????????????????????????? 8?????????????????????????????????????????????? 9???????????????? ????????????????????????????????3.5?? 1)???????????????? 2)?????????? 3)?????????????????? *???????????????? *???????????????????????? *???????????????????????????? *?????????????????????????? *?????????????????????????????????????????????????? *?????????????????????????????????????????????????????????? 4)?????????????????? *???????????????????????????????? *???????????????????????????????????????????????????? *???????????????????????????????????????????? *?????????????????????????????????????????? *?????????????????? *?????????????????? *?????????????????????????????????????? *?????????????????????????????????????? *?????????????????????????????????????????????? *?????????????????????????????????????????????????????????????? *?????????????????????????????????????????????????????????????????? ???????????????????? *???????????????????????????????????????? 5)?????????????????? *?????????????????????????????????? *???????????????????????????????????????????? *???????????????????????????????????????????????????????????????????? *?????????????????????????????????????????????????????????????????? ?????????? *?????????????????????????????? 6)?????????????????? *???????????????????????? *?????????????????????? *???????????????????????? *?????????????????????????????????????? 7)?????????????????? *?????? *???????????????????????????? *??????????????5?????? *?????????????????????????????????? *?????????????????????????????????? *?????????????? *??????????????????????????QA???????? *???????????????????? *???????????????????? *??????????????????????????????????QA?????????????? *?????????????????????????????????????????????? ??????????????????????????????1.5?? 1)?????????????????????????????????????????????????? 2)?????????????????????????????????????????????????????????? 3)?????????????????? 4)?????????????????????????? 5)?????????????? 6)?????????????????????????? 7)???????????????????????????????????????????? 8)???????????????? 9)?????????????????????? 10)???????????????????????????? 11)?????????????????????? 12)???????????????????? 13)?????????????????????????? 14)???????????????????????????????? 15)?????????????????????????????????????????????????????????????????? ?????????????????? 16)?????????????????? 17)???????????????????????????????????????? 18)?????????????????? 19)???????????????????????????????????????????? ??????????????????????????????????????????????????????1.0?? 1)???????????????? 2)???????????????????????? 3)?????????????????????????????????????????????????? 4)?????????????????????????????????? 5)???????????????????????? 6)??????????????????SMART????????????????????????????PBC???? 7)??????????????????????????SMART 8)??????????????????SMART??????????????????????SMART 9)??????????????PDCA???? 10)?????????????????????????????????????????????????????????????????? 11)???????????????????? 12)?????????????????????? 13)PERT????????????GANNT 14)??????????????????????PERT?? 15)???????????????????????????????????????????????????????????? 16)???????????????????????? 17)?????????????????? 18)???????????????????????? 19)?????????????????????????????????????? ??????????????????????????????????????????????????????????2.0?? 1)???????????????????????? 2)?????????????????????? 3)???????????????????????? 4)???????????????????????? 5)?????????????????????????????????? 6)?????????????????? 7)???????????????? 8)???????????????? 9)??????????????/???????? 10)?????????????????????? 11)?????????????????????????? 12)???????????????????????? 13)?????????????????????????????????????????????????? 14)?????????????????????????????????????????????????????????? 15)???????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????? ?????????????? 16)?????????????????????????????????????????????????????????????? 17)???????? 30 ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? 18)???????????????????????????????????????????????????????????????????? 19)?????????????????????????????????????????????????????????????????? 20)?????????????????????????????????????????????????????????? 21)?????????????????????????????????????????????? 22)?????????????????????????????????????? ??????????????????????????????????????????????????????1.5?? 1)?????????????????????? 2)???????????????????????????? 3)?????????????????? 4)???????????????????????????????????????????? 5)???????????????????????????????????????????????? 6)???????????????????????????????????????????? 7)?????????????????????????????????????????????????????? 8)???????????????????????????????????????????????? 9)???????????????????????????????????????????????????? 10)???????????????????????????????????????????? 11)?????????????????????????????????????????????????? 12)????????????????????????????????????????????PCB?? 13)?????????????????????????????????? *???????? *???????????????????????????????? *???????????????????????????????????????????????? *???????????????????????????????????? *???????????????????? *?????????????????????????????????????????????????????????????? 14)???????????????????????????? 15)???????????????????????? 16)?????????????????????????????????????? 17)???????????????????? 18)?????????????????????????????????????? 19)???????????????????????????????? 20)???????????????????????? 21)?????????????????????????????????????? 22)?????????????????????????????????????????????????? 23)?????????????? ??????????????????????????????????????????????????????2.0?? 1)???????????????????? 2)???????????????????????? 3)???????????????????????????????????????????? 4)???????????????????????????????????? 5)???????????????? 6)???????????????????????????????? 7)???????????????????????????????? 8)???????????????????????????????????????????????? *?????????????????? *?????????????????????????????????????????? *????????????????????KPI?????????????????????????? *??????????????????BSC???????????????????? *????????????????PBC?????????????????????????? *??????????360?????????????????????????? *?????????? *???????????????????????????????? *?????????????????????????????????????? *???????????????????????????????? 9)?????????????????????????????????? *?????????????????????????????? *????????????????7???????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? *?????????????????????????????????????????????????????????????????? ???????????????????????????????? *?????????????????????????????????????????? *????????????????????????????????????????????QA???????????????????? ?????????????????? 10)???????????????????????????????????????? *???????????????????? *???????????????????????????????????????? *?????????????????????????????????????????? *???????????????????????????????????????????? *?????????????????????????????????????????????????????????????????? ?????????????????????????? *???????????????????????????????????? *???????????????????????????????????? *???????????????????????????????????????????? *?????????????????????????????????????????????????????? *?????????????????????????????????????????????????????????????????? ???????????????????????? *?????????????????????????????? *???????????????????????????????????????????????????? 11)?????????? ??????????????????????????????????????0.5?? 1)?????????????????? 2)?????????????? 3)?????????????????????????????????? 4)?????????????????????? 5)?????????????????????????????????????????? --------------------------------------------------------------------- ?????????? ??????(Giles) -???????? ???????? 10?????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ????????????IPD????????????ITS&P????,????IPD???????????????????????? ????????????????????????????????IPD??????????????,?????????????????? ???????????????? ???????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ??????????????,?????????????????????????????????????????????????????? ???????????????????? ???????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ??????????????????????10???????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? --------------------????????????????????????----------------------------- ??????????(FAX:020-34506895) ??????????????????????????????????????5???????????????????????? ?????????????????????????????????????????????? ??????????____________________________________ ????????????____________ ??????????______________ ??????????_____________ ??????????____________ ??????????___________ ?? ??????????_____________ ?? ?? ?? ????______________ ??????????_____________ ??????????____________ ?? ?? ????______________ ??????????_____________ ??????????____________ ?? ?? ????______________ ??????????_____________ ??????????____________ ??????????????????????????????????????????????????????????,???????????? ?????????????????????????? ????????????????/???? ????????????????????????????????????????______?? ??????????????????????????????????????????2009??___??___???????? ____?? ????????????????____ ??????????????____ ?????????????? ????????????????????????????__________________________________________ ______________________________________________________________________ ______________________________________________________________________ From bare at erbz.com Fri Nov 13 19:52:45 2009 From: bare at erbz.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Fri, 13 Nov 2009 19:52:45 -0000 Subject: (no subject) Message-ID: <200911131952.nADJqfr5017499@mx1.redhat.com> ???????????? ?????2009?11?20?21? ?? ?????2009?12?11?12? ?? ???????????????????????????????????? ?????2500?/??????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? ---------------------------------------------------------------------------------------- ?????500?/????????????????????????????????????? ?????????????????????????????????????????????? ???????????????60%?80%??????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????? ---------------------------------------------------------------------------------------- ???? ?1???????????? 1.?????????????? 2.????????? ????????????? 3.????????????? ????????Sourcing?????Buyer/Purchasing ??????Receiving/QC??????SupplierManagement 4.???????SRM ??????Intel?AMD??? 5.???????????? ????????????????????? ???????????????LT? ??????????????????????????? ?2???????? 1.?????ABC?? 2.???????? ?????????????????????? 3.??ABC?????????????? ????????? 1)??????????????????? 2)?????????? 3)???????????????????? 4)???????? a)??????????????????????? b)???????????? ????????? 1)????????????? 2)???????????????????? 3)???????????????????????? 4)??????????????? 5)???????????JIT???VMI? 6)???????????? ????????? 1)??????????????? 2)???????????????????????????????????????????? 3)???????????????? 4)???????? 5)????????? 6)?????????????? ????????? 1)??????????? 2)?????????????????? 3)?????JIT??????? 4)??????????????????????????? ????????????????? ???????????????????? 4.?????? ????????????????????OEM?ODM?CM???? ?3????????? 1.??????????? ???????????????????????? ??????????????????????????? ???????????????????AVL ????????????????? 2.???????????? i.?????????? ??????? ii.?????????????????????????????? iii.????????? iv.??????????? 3.?????????? 4.?????????? ??????????????????? ?4???????????? 1.?????????? 2.????????????????? 3.????????? 4.????????????? 5.????PDCA?6-Sigma 6.?????????? ?5??????????? 1.???????????????? ???????????????BNSF?????????? 2.????????? ??????????PI???????????SPI 3.????????? ?6??????? 1.???????2.????????????????? 3.?????????4.???????Break-EvenPoint 5.???????6.?????????VA/VE ?7??????? 1.???????? 2.??????????? 3.??????????????????? 4.???????????? a)????????????b)???????????? c)?????????????? 5.??????????? 6.????????????? ?8??????? 1.???????????2.??????? 3.????????????4.?????????????????? 5.????????? 6.??????? a)????b)????c)???? 7.???????POCKET?? 8.?????POCKET9.???????????? ---------------------------------------------------------------------------------- ???????????1984??????????????1986??????????MS?? 1992??????????????863/CIMS????????????????????? ???????1992-1996??????LeedandNorthrup???????????????? ????????????????????????????? 1996??2000??IBM????ERP/SCM???????????????????(ERP)??? ???(SCM)???????????????????????????????????? ?????????????????????????2000??????????????? ??ManufacturingandDistribution?????????????????????????? ?????????????????????????????????????????? ??????????CPC??????????????????????????????? ????????????? ???????????????????????EMBA????????????????? ?????????????????????????????????????????? ??????????????????????????????????????? ?????????????????????TCL???TCLAV?????????????? ???3M?????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ?????????????????????????????????????????? ???????????????? =============================================================================== ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From ghn at bwja.com Sat Nov 14 21:57:05 2009 From: ghn at bwja.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Sat, 14 Nov 2009 21:57:05 -0000 Subject: (no subject) Message-ID: <200911142156.nAELuk5F006789@mx1.redhat.com> ??????????????????????PPT+Excel+?????????????????? ?????????????????????? ??????????????????????????????office2003??Office2007 ??????????2009??11??20-22?????? ??????????3600/???????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945??????????????????????????????????chinammc21 at 126.com?????? ====================================================================================== ??????????????20???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????3?????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????? ????????????????????????????Powerpoint??Excel???????????????????????????????????????????????????????? ???????????????????????????????????????????? Powerpoint??????????????????????????????????????????Powerpoint????????????????Office???????????????? ????????Powerpoint????????????????PPT?????????????????????????????????????????? ??????????Powerpoint???????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????????????????Photoshp???????????? ?????????????????????????????????????????????????? Excel??????????????????????????????????????????????????????????????Excel??80%???????????????????????? ??????????????????????????????????????????5?????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ============================================================================================== ????????????????????????????????????????????????????????????office2003??Office2007 ????PPT??????????????????????????????Powerpoint???????????????????????? 1.???????????????????????????????????????????????????????????? 2.?????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????????????????????????????????? 4.Flash??????????????????????Flash??????????PPT??????????????????????Flash?? ?????????????????????????????????????????? ????Excel??????????????????????????????BladeOfficeExcel???????????????????????? 1.????????????????????????????????????????????????????????????????????Excel???????????????????????????? ???????????????????????????????????????????????????????? 2.Excel??????????????Excel2003???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ======================================================================================================== ???????? ???????????????????????? ?????????????????????????? 1.?????????????????????????????????????????????????????????? 2.????????????????????????500???????????????????????????????? 3.???????????????????????????????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????? ?????????????????????????? 1.????Office???????????????? 2.???????????????????? 3.?????????????????? 4.???????????????? 5.???????????????????????????????? 6.?????????????????? 7.????3D?????????????? 8.???????????????????????? 9.?????????????????? 10.??????????????* 11.??????????????????????????????????3-D????* ???????????????????????? 1.???????????? 2.???????????????????????? ???????????????????????? 3.???????????? ???????????????????????????????????? 4.????????????????40M??????????6M 5.???????????????? ????SmartArt???????? 1.?????????????????????????????? 2.???????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????????????? 6.??????????????SmartArt ???????????????????? 1.?????????????????????????????? 2.?????????????????????????? 3.?????????????????????????? 4.?????????????? 5.?????????????????????? 6.?????????????????? ????Excel???????? 1.?????????????????????????????????????????????? 2.??????????????????????????????10??????????5???????? 3.?????????????????????? 4.?????????????????? 5.???????????????????????????????????????????????? 6.??????Powerpoint???????????????????? 7.?????????????????????? 8.???????????????????????????????? 9.???????????????????????????????????? ?????????????????? 1.????????????Powerpoint?????????? 2.???????????????????????????? 3.?????????????????? 4.?????????????????????? 5.?????????????????????????????????? ???????????????????? 1.Powerpoint?????????????????? 2.?????????????????????????????????? 3.???????????????? 4.???????????????????????????????? 5.?????????????????????? 6.???????????????????????????????? 7.?????????????????????? 8.?????????????????????????????????????? ????????Excel?????????????? ???????????? 1.?????????????????? 2.?????????????????? 3.??????????2?????? 4.??????????????????Excel?????????????????????????????? 5.?????????????????????????????????? ???????????????? 1.????IF???????????????? 2.AND??OR??NOT???? 3.?????????????????????? ?????????????? 1.?????????????????? 2.???????????????????????????? 3.???????? a)???????????????????????????????? b)?????????? c)???????????????????? ???????????? 1.???????????? 2.???????????????????????? ???????????? 1.???????????????? 2.????VLOOKUP??HLOOKUP???????????? 3.?????????????????????? a)???????????????????????????????????? b)???????????????????????????????????????????????????????????????? 4.?????????????????????????? 5.???????????????????????????? ???????????? 1.???????????????? 2.?????????????????????? 3.?????????????????????????? 4.???????????????????????? 5.?????????????????????? 6.?????????????????? ???????????? 1.?????????? 2.?????????? 3.???????????????? ???????????????? 1.???????????????? 2.???????????????? 3.?????????????????? 4.???????????????? 5.?????????????????????????? ?????????????????????? 1.?????????????? 2.?????????????? 3.???????????? 4.???????????? 5.???????????? 6.?????????????????????????????? 7.???????????????????? a)?????????? b)?????????? c)?????? d)?????????? 8.???????????????????????? 9.?????????????????????????????? ?????????????????? 1.?????????????????????? 2.???????????????????????????????? 3.?????????????????? ???????????????????? ?????????????????? 1.?????????????????? 2.????Powerpoint?????????????????? 3.????Word?????????????????? 4.????Excel?????????????????? ???????????? 1.?????????????????????????????????????????????? 2.???????????????? 3.??????????????SmartArt???????????? 4.???????????????????? ???????????????? 1.?????????????????? 2.???????????????????????????????? 3.Outlook?????????????????? ================================================================================================== ??????????????????????????????????????????????IPMP???????????????????????????????????????????????? ????????????????????????????????????????????????????????????????ERP???????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????? ??????????DELL????????????????????????????????????????????????????????????????????TCL???????? ============================================================================================== ????????????????????????PPT+Excel+??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From rto at zyux.com Wed Nov 18 05:56:04 2009 From: rto at zyux.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Wed, 18 Nov 2009 05:56:04 -0000 Subject: (no subject) Message-ID: <200911180555.nAI5ti4F001938@mx1.redhat.com> ??????? ?????2009?11?23-24? ?? ?????2009?11?26-27? ?? ?????2009?11?30-12?1? ?? ?????3200????????1600?????????/???????????????????? ???????CEO/?????????/???????/???????????/??????????? ????????PMO???????????????????????? ????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? --------------------------------------------------------------------------------- ????????????????????????????95%?????????????????? ????????????: ??????????????????????????????? ??????????????? ????????????????????????? ???????????????????????????? ????????????????? ????????????????????????????????? ????????????????????? ????????????????????????????????????????????????? ?????????????????????????????????????????????????? ------------------------------------------------------------------------------------------------- ???? 1.??????????????????????????????????????? 2.???????????????????????? 3.??????????????????????? 4.????????????????????????????????????????? 5.???????????? 6.??????????????????????????????????????????????????? 7.?????????????????????? 8.???????????????????????????????????????? Action Plan???? ????????????????? --------------------------------------------------------------------------------------------------- ???? ???????0.5? 1)???????????? ????????????????????1.5? 1)?????????????????? 2)?????????????? 3)?????????????? 4)?????????????????????????????????????????????????????????????????????????????? 5)???????????? 6)??????? 7)?????????????? 8??????????????????????? 9???????? ????????????????3.5? 1)???????? 2)????? 3)????????? 4)????????? 5)????????? 6)????????? 7)????????? ???????????????1.5? 1)????????????????????????? 2)????????????????????????????? 3)????????? 4)????????????? 5)??????? 6)????????????? 7)?????????????????????? 8)???????? 9)??????????? 10)?????????????? 11)??????????? 12)?????????? 13)????????????? 14)???????????????? 15)?????????????????????????????????????????? 16)????????? 17)???????????????????? 18)????????? 19)?????????????????????? ???????????????????????????1.0? 1)???????? 2)???????????? 3)????????????????????????? 4)????????????????? 5)???????????? 6)?????????SMART??????????????PBC?? 7)?????????????SMART 8)?????????SMART???????????SMART 9)???????PDCA?? 10)????????????????????????????????? 11)?????????? 12)??????????? 13)PERT??????GANNT 14)???????????PERT? 15)?????????????????????????????? 16)???????????? 17)????????? 18)???????????? 19)??????????????????? ?????????????????????????????2.0? 1)???????????? 2)??????????? 3)???????????? 4)???????????? 5)????????????????? 6)????????? 7)???????? 8)???????? 9)???????/???? 10)??????????? 11)????????????? 12)???????????? 13)????????????????????????? 14)????????????????????????????? 15)???????????????????????????????????????????????????????????????????????? 16)??????????????????????????????? 17)???? 30 ???????????????????????????????????????????????????????????? 18)?????????????????????????????????? 19)????????????????????????????????? 20)????????????????????????????? 21)??????????????????????? 22)??????????????????? ???????????????????????????1.5? 1)??????????? 2)?????????????? 3)????????? 4)?????????????????????? 5)???????????????????????? 6)?????????????????????? 7)??????????????????????????? 8)???????????????????????? 9)?????????????????????????? 10)?????????????????????? 11)????????????????????????? 12)??????????????????????PCB? 13)????????????????? 14)?????????????? 15)???????????? 16)??????????????????? 17)?????????? 18)??????????????????? 19)???????????????? 20)???????????? 21)??????????????????? 22)????????????????????????? 23)??????? ???????????????????????????2.0? 1)?????????? 2)???????????? 3)?????????????????????? 4)?????????????????? 5)???????? 6)???????????????? 7)???????????????? 8)???????????????????????? 9)????????????????? 10)???????????????????? 11)????? ???????????????????0.5? 1)????????? 2)??????? 3)????????????????? 4)??????????? 5)????????????????????? -------------------------------------------------------------------------------------------------------- ???? Giles ???? ?????10??????????????????????????????????????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????????IPD??????ITS&P ?????IPD????????????????????????????IPD???????????????? ????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? ????????????????????????????????10??????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????? ??????????????????????????????????????? -------------------------------------------------------------------- ??????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From fon.dyu at hotmail.com Fri Nov 20 09:21:07 2009 From: fon.dyu at hotmail.com (fon.dyu at hotmail.com) Date: Fri, 20 Nov 2009 09:21:07 -0000 Subject: (no subject) Message-ID: <200911200920.nAK9Knwt000605@mx1.redhat.com> ============================================================================= ???????????? ============================================================================= ?????? 2009?11?20-21? ?? 2009?12?11-12? ?? ?????????400-889,9628 ???????021-510,994,75 ???????020-336,656,97 / 345,209,81 ============================================================================= ????? ???????????????????????????????????? ????????????????????60%?80%?????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ????????? ?????? ??????????????????????????????? ????: ?????????????? ????? 2?/13??? ============================================================================= ?1? ??????????? 1.?????????????? 2.????????? ? ???????????? 3.????????????? ? ??????? Sourcing ? ???? Buyer/Purchasing ? ????? Receiving/QC ? ????? Supplier Management 4.??????? SRM ? ?????Intel?AMD??? 5.???????????? ? ??????????? ? ???????? ? ????? ? ????????LT? ? ?????????? ? ??????????????? ?2? ??????? 1.?????ABC?? 2.???????? ? ?????????? ? ?????????? 3.??ABC?????????????? ? ???????? 1)??????????????????? 2)?????????? 3)???????????????????? 4)???????? a)??????????????????????? b)???????????? ? ???????? 1)????????????? 2)???????????????????? 3)???????????????????????? 4)??????????????? 5)???????????JIT???VMI? 6)???????????? ? ???????? 1)??????????????? 2)???????????????????????????????????? ???????? 3)???????????????? 4)???????? 5)????????? 6)?????????????? ? ???????? 1)??????????? 2)?????????????????? 3)?????JIT??????? 4)??????????????????????????? ? ???????????????? ? ??????????????????? 4.?????? ? ??????? ? ?????????? ? OEM?ODM?CM???? ?3? ???????? 1.??????????? ? ???????????? ? ?????????? ? ????????????? ? ???????????? ? ??????????????????AVL ? ???????????????? 2.???????????? i.?????????? ? ?????? ii.?????????????????????????????? iii.????????? iv.??????????? 3.?????????? 4.?????????? ? ???????? ? ????????? ?4? ??????????? 1.?????????? 2.????????????????? 3.????????? 4.????????????? 5.????PDCA?6-Sigma 6.?????????? ?5? ?????????? 1.???????????????? ? ?????????? ? ???BNSF?????????? 2.????????? ? ?????????PI ? ??????????SPI 3.????????? ?6? ?????? 1.??????? 2.????????????????? 3.????????? 4.??????? Break-Even Point 5.??????? 6.?????????VA/VE ?7? ?????? 1.???????? 2.??????????? 3.??????????????????? 4.???????????? a)???????????? b)???????????? c)?????????????? 5.??????????? 6.????????????? ?8? ?????? 1.??????????? 2.??????? 3.???????????? 4.?????????????????? 5.????????? 6.??????? a)???? b)???? c)???? 7.???????POCKET?? 8.?????POCKET 9.???????????? ============================================================================= ? ????:????? ???1984??????????????1986??????????MS??1992 ??????????????863/CIMS???????????????????? ????????1992-1996??????Leed and Northrup??????????? ?????????????????????????????????? 1996??2000??IBM????ERP/SCM??????????????????? (ERP)??????(SCM)??????????????????????????? ??????????????????????????????????2000?? ???????????????Manufacturing and Distribution???????? ?????????????????????????????????????? ???????????????????????????? ????CPC???? ?????????????????????????????????????? ???????????????????????EMBA??????????? ?????????????????????????????????????? ?????????????????????????????????????? ??????????? ??????? ??????????????TCL???TCL AV?????????????? ???3M?????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ??????????????????????????? ============================================================================= ?????2?500?/???????????????????? ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-889,9628 ???????021-510,994,75 ???????020-336,656,97 / 345,209,81 ============================================================================= From spjovukrfxv at gmail.com Sun Nov 22 04:03:41 2009 From: spjovukrfxv at gmail.com (Anastasia.Ben) Date: Sun, 22 Nov 2009 04:03:41 -0000 Subject: (no subject) Message-ID: <200911220403.nAM43OGd000611@mx1.redhat.com> ============================================================================== ???:2010????????? ============================================================================== ????? 2009?12?17-19? ?? 2010?01?08-10? ?? 2010?01?23-25? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ???hrlawclub at 126. com ============================================================================== ?????? ???: -????????????????????? -????????????????????? ????????????????????????????????? ???????????????????????????????? ????????????????????????????????? ???????????????????????????????? ???????????????????????????????? ???????????????/????????????????? ------------------------------------------------------------------------------ ????????????????????????? ????????????????????????? ????????????????????????? ------------------------------------------------------------------------------ ?????????????????? ?????????????????? ????? ?????4,800 ?/?(????????, ???????????20??) ?????5,800 ?/?(???+??1??, ????????????????) ?????? ????CEO???????????????????? ============================================================================== ?????? ????????2010?????????????????????? ????????????????????????????????? ????????????????????????????????? ????????????????????????????????? ????????????????????????????????? ============================================================================== ?????? ????????????????? ?????????? ??????????????????????????????????????? ?????????????????????????? ????????????????????????2010????????????? ????????????????????????? ????????????????? ?????????? ??????????????????????????????????????? ?????????????????????? ??????????????????????????????????????? ?????????????????????????? ????????????????? ?????? ??????????????????????????????????????? ??????????????????????????? ??????????????????????????????????????? ?????????????????????? ????????????????? ?????? ??????????????????????????????????????? ??????????????????????? ??????????????????????????????????????? ???????????????? ????????????????? ?????? ??????????????????????????????????????? ?????????????????????? ??????????????????????????????????????? ???????????????????? ? ??????(??????,??????): ???????????? ???TOC?????????????????????????????????? ??????????? ??????????????????????????????????????? ????????????? ????????????? ??????????????????????????????????????? ?? ??????????????????????????????????????? ?????????????? ????????????? ??????????????????????????????????????? ??? ??????????????????????????????????????? ??????????? ============================================================================== ??????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????1990????????????????????????????? ????? ????????2001?-2003????????2003????????????? ?? ???????????????2005?????????????????????? ??????????????????????? ------------------------------------------------------------------------------ ??????? ??????????????????????????????????????? ??????15???????????????????????????????? ??????????????????????????????????????? ??????????????????????????????????????? ????????????? ??HPO?????????????????????? ???????? ??????????????????????????????????????? ??????????????????????????????????????? ?????????????? ------------------------------------------------------------------------------ ???????? ??????????????????????????????????????? ???????????? ------------------------------------------------------------------------------ ??????????? ???????????????????????????????????????, ?????????????????? ??????????????????????????????????????? ????? ============================================================================== ??????????????????????????????????????? ?????????????????? ------------------------------------------------------------------------------ ????? M-M-C???? ???????????? ============================================================================== From har.rie at hotmail.com Sun Nov 22 21:06:29 2009 From: har.rie at hotmail.com (har.rie at hotmail.com) Date: Sun, 22 Nov 2009 21:06:29 -0000 Subject: (no subject) Message-ID: <200911222106.nAML5xOC011555@mx1.redhat.com> ============================================================================= ???????????? ============================================================================= ?????? 2009?12?11-12? ?? ?????????400-889,9628 ???????021-510,994,75 ???????020-336,656,97 / 345,209,81 ============================================================================= ????? ???????????????????????????????????? ????????????????????60%?80%?????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ????????? ?????? ??????????????????????????????? ????: ?????????????? ????? 2?/13??? ============================================================================= ?1? ??????????? 1.?????????????? 2.????????? ? ???????????? 3.????????????? ? ??????? Sourcing ? ???? Buyer/Purchasing ? ????? Receiving/QC ? ????? Supplier Management 4.??????? SRM ? ?????Intel?AMD??? 5.???????????? ? ??????????? ? ???????? ? ????? ? ????????LT? ? ?????????? ? ??????????????? ?2? ??????? 1.?????ABC?? 2.???????? ? ?????????? ? ?????????? 3.??ABC?????????????? ? ???????? 1)??????????????????? 2)?????????? 3)???????????????????? 4)???????? a)??????????????????????? b)???????????? ? ???????? 1)????????????? 2)???????????????????? 3)???????????????????????? 4)??????????????? 5)???????????JIT???VMI? 6)???????????? ? ???????? 1)??????????????? 2)???????????????????????????????????? ???????? 3)???????????????? 4)???????? 5)????????? 6)?????????????? ? ???????? 1)??????????? 2)?????????????????? 3)?????JIT??????? 4)??????????????????????????? ? ???????????????? ? ??????????????????? 4.?????? ? ??????? ? ?????????? ? OEM?ODM?CM???? ?3? ???????? 1.??????????? ? ???????????? ? ?????????? ? ????????????? ? ???????????? ? ??????????????????AVL ? ???????????????? 2.???????????? i.?????????? ? ?????? ii.?????????????????????????????? iii.????????? iv.??????????? 3.?????????? 4.?????????? ? ???????? ? ????????? ?4? ??????????? 1.?????????? 2.????????????????? 3.????????? 4.????????????? 5.????PDCA?6-Sigma 6.?????????? ?5? ?????????? 1.???????????????? ? ?????????? ? ???BNSF?????????? 2.????????? ? ?????????PI ? ??????????SPI 3.????????? ?6? ?????? 1.??????? 2.????????????????? 3.????????? 4.??????? Break-Even Point 5.??????? 6.?????????VA/VE ?7? ?????? 1.???????? 2.??????????? 3.??????????????????? 4.???????????? a)???????????? b)???????????? c)?????????????? 5.??????????? 6.????????????? ?8? ?????? 1.??????????? 2.??????? 3.???????????? 4.?????????????????? 5.????????? 6.??????? a)???? b)???? c)???? 7.???????POCKET?? 8.?????POCKET 9.???????????? ============================================================================= ? ????:????? ???1984??????????????1986??????????MS??1992 ??????????????863/CIMS???????????????????? ????????1992-1996??????Leed and Northrup??????????? ?????????????????????????????????? 1996??2000??IBM????ERP/SCM??????????????????? (ERP)??????(SCM)??????????????????????????? ??????????????????????????????????2000?? ???????????????Manufacturing and Distribution???????? ?????????????????????????????????????? ???????????????????????????? ????CPC???? ?????????????????????????????????????? ???????????????????????EMBA??????????? ?????????????????????????????????????? ?????????????????????????????????????? ??????????? ??????? ??????????????TCL???TCL AV?????????????? ???3M?????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ??????????????????????????? ============================================================================= ?????2?500?/???????????????????? ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-889,9628 ???????021-510,994,75 ???????020-336,656,97 / 345,209,81 ============================================================================= From wer at puic.com Thu Nov 26 22:12:57 2009 From: wer at puic.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Thu, 26 Nov 2009 22:12:57 -0000 Subject: (no subject) Message-ID: <200911262212.nAQMCbBG016865@mx1.redhat.com> 2009??????????????????????????????????? ?????2009?12?15-16??? ?14?????? ?????2010?01?16-17??? ?15?????? ?????????????????????????????(???)?????????????? ???A?:???2200?/?(?????????????????????)? B?:???4600?/?(?????????????????????????????)? ????:????????????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------- ????:2009???????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ??????????????????? 2009???????????????????????????????????????????? ????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ?????????????????????????????????????????????? ????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????????????? ?????????????????????????????????????,????????? ??????? ????????09?11??12????????????????????????????????? ????????????????2009????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????? -------------------------------------------------------------------------------------------- ???? ????2009??????????????????????????? ?????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? ???????????????????????????????????? ???????????1?????????????????????2??????????????? ???3??????4?????????????5?????????????? ????????1?????????????????2???????????????3?????? ?????4???????5???????????6??????????????7???????? 8?????????????? ??????????1?????????2????????? 3????????????????? 4????????????? ??????????????????????????????????????????????? ???????????????????????????? ??????????1??????????????????????????????2?????? ??????????????????????3????????????????????????? ???????????????4???????????????????????????5???? ????????????????????????? ??????????????1??????????????????????????2????? ???????????3????????????????????4?????????????? ???????5????????????????????????6?????????????? ?????????????? ???????????????????? ?????????????????????? ???????????? ????2009???????????????????????????????? ???????????????????? ???????????????1??????????????????????????????? 2?????????????????????????? ??????????????1??????????????????????????????????? ???????????????????????????????????????????????? ?????????????2???????????????? ?????????????????? ???????????????????????????????????????????????? ????? 3?????????????? ?????????????????????????? ??????????????????????????????4??????????????????? 5?????????????????? ????????????? 1?????????????? 2??????????????????? ???????????????? 3??????????4?????? ???????????? ============================================================================================= ??????????????????500?????????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????????? ????????????????????????? ================================================================================================== From poe.dec at hotmail.com Fri Nov 27 21:08:45 2009 From: poe.dec at hotmail.com (poe.dec at hotmail.com) Date: Fri, 27 Nov 2009 21:08:45 -0000 Subject: (no subject) Message-ID: <200911272108.nARL8Lx2024709@mx1.redhat.com> ================================================================================ ?????????????????? ================================================================================ ?.?.?.?.?? 2009?12?15-16? ???14?????? 2010?01?16-17? ???15?????? ================================================================================ ?-?-?-?: 2009???????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????? 2009???????????????????????????????????? ??????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ????????????????????????? ????????????????????? ???????????? ???? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????2009??????????????????????? ???????????????????????????????????????? ?????????2009-2010???????????????,??????????? ???????????????????????????????????????? ???????????????????????? ?-?-?-?? ????????????????????????????(???)???????? ?????? ?????????????????????? ================================================================================= ?.?.?.?: ????2009??????????????????????????? ?????????????? ?????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ?????????? ???????????????????????????????????? ??????????? 1????????????????????? 2?????????????????? 3?????? 4????????????? 5??????????? ???????? 1????????????????? 2??????????????? 3??????????? 4??????? 5??????????? 6?????????????? 7???????? 8?????????????? ?????????? 1????????? 2????????? 3????????????????? 4????????????? ????????????????????????????????????????? ?????????????????????????????????? ?????????? 1?????????????????????????????? 2???????????????????????????? 3???????????????????????????????????????? 4??????????????????????????? 5????????????????????????????? ?????????????? 1?????????????????????????? 2???????????????? 3???????????????????? 4????????????????????? 5???????????????????????? 6???????????????????????????? ???????????????????? ???????????????? ???????????????? ???????????????????? ??????????????? 1??????????????????????????????? 2?????????????????????????? ?????????????? 1???????????????? ???????????????????????????????????????? ???????????????????????????????????????? 2???????????????? ?????????????????????? ???????????????????????????????????????? ????????? 3??????????????????????????????????????? ??????????????????????????????? 4??????????????????? 5?????????????????? ????????????? 1?????????????? 2??????????????????????????????????? 3?????????? 4?????? ================================================================================ ???????? ??????????????500?????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ????????????????????????????????? ================================================================================ ????? A??2?200 ?/?????.??????????????? B??4600?/?(??.???????????????????????????)? ? ? ? ? ? ? ? ?? ------------------------------------------ M-M-C ?.?.?.? ????????????????????? ???????????????????? ???????????????????? ? ??chinaipo@???.com ================================================================================ From eregt at uyce.com Thu Dec 3 07:42:01 2009 From: eregt at uyce.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Thu, 03 Dec 2009 07:42:01 -0000 Subject: (no subject) Message-ID: <200912030741.nB37fgUv000526@mx1.redhat.com> (TPM)???????? ?????2009?12?4-5? ?? ?????2009?12?11-12 ?? ??????????????????/??/???/??????????????????TPM????????? ?????2600?/?????????????????? ?????020-80560638?020-85917945?????????????????chinammc21 at 126.com??? ====================================================================================== ??????????????????????????????????TPM??????????? ?????????????????????????????????????????????? ????????????????????????????????? ?????????????????????????????? ??TPM???????OEE????????OEE???5S?TPM??????????????????? ?????TPM???????TPM???? ????????????????????????????????????? ------------------------------------------------------------------------------------------ ?????????MBA???LeanMaster?IE????????????? ?93?????????????1??TPS??????????????????IE????????? ???????????????????????? ??Delphi?????????????????????????????TPM????????????? ???????????????Kaizen?????????????????????????????? ??????????????????????????????? ???????????????????????????????????? ??????????????????????????????????????????????5S? KANBAN?Kaizen???????VSM??????????????????????????JIT?????? TPM?????????????????????????????IE?????????6sigma????? ??????? ?????????:??????????TPM????;????????IE???????????MOD?? ??????????????20%??????????????TPM?????????????????? ???????????TPM???????????30%?????????????????LP?????? ?????????????????????????????????IT????????????????? ????????????????????????????????????????????????? ???????????TCL????????????????????????????????????? ???????????????????????????????? ----------------------------------------------------------------------------------------------- 1?TPM?? TPM????????? TPM????? ???????? TPM?????? TPM?????????????????? ???????? ???????? ????????? ???????? ?????????????? 2??????? ????????????? ????????? ??????????? ?????????????????? ??????? TPM??????? ???? ???????OEE? ???OEE ??OEE?????????????????????? OEE???????????????????????????OEE OEE????OEE??????? ????OEE??????OEE????????? ??????OEE??????? ????TPM???MTBF?MTTR???????? 3?TPM??????? TPM?????????????????????????????????????????? ?????????????PM??????????????????,??????????? ???????5S????????????????????TPM 4?TPM??????5S????? 5S?TPM??? ???????5S?? 5S?????????????????? ?????? ?????????????? ?????????????? ??????????? 5S?TPM?????? 5?TPM????????? ?????????????????????? ?????????????????? ??????????TPM?????????????PM?? ???????PM?????????? ???????PM?????????????? ??5S?????????????? ??OEE???TPM???TPM???? ???? 6?TPM????? SMED????????????? ?????????????? ??????????? ????????,??????? ?????TPM??,??????? 7???????????TPM?KAIZAN?? ???KAIZAN ???????????CIP(??????) TPM?KAIZAN???? ============================================================================================== ?(TPM)??????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! 8?TPM?????? From bny.toun at hotmail.com Mon Dec 7 17:43:28 2009 From: bny.toun at hotmail.com (bny.toun at hotmail.com) Date: Tue, 8 Dec 2009 01:43:28 +0800 Subject: (no subject) Message-ID: <200912061750.nB6HovvT008343@mx1.redhat.com> ================================================================================ ?????????????????? ================================================================================ ?.?.?.?.?? 2009?12?15-16? ???14?????? 2010?01?16-17? ???15?????? ================================================================================ ?-?-?-?: 2009???????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????? 2009???????????????????????????????????? ??????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ????????????????????????? ????????????????????? ???????????? ???? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ????????????????????? ?????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????2009??????????????????????? ???????????????????????????????????????? ?????????2009-2010???????????????,??????????? ???????????????????????????????????????? ???????????????????????? ?-?-?-?? ????????????????????????????(???)???????? ?????? ?????????????????????? ================================================================================= ?.?.?.?: ????2009??????????????????????????? ?????????????? ?????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ????????????????????????????????????????? ?????????? ???????????????????????????????????? ??????????? 1????????????????????? 2?????????????????? 3?????? 4????????????? 5??????????? ???????? 1????????????????? 2??????????????? 3??????????? 4??????? 5??????????? 6?????????????? 7???????? 8?????????????? ?????????? 1????????? 2????????? 3????????????????? 4????????????? ????????????????????????????????????????? ?????????????????????????????????? ?????????? 1?????????????????????????????? 2???????????????????????????? 3???????????????????????????????????????? 4??????????????????????????? 5????????????????????????????? ?????????????? 1?????????????????????????? 2???????????????? 3???????????????????? 4????????????????????? 5???????????????????????? 6???????????????????????????? ???????????????????? ???????????????? ???????????????? ???????????????????? ??????????????? 1??????????????????????????????? 2?????????????????????????? ?????????????? 1???????????????? ???????????????????????????????????????? ???????????????????????????????????????? 2???????????????? ?????????????????????? ???????????????????????????????????????? ????????? 3??????????????????????????????????????? ??????????????????????????????? 4??????????????????? 5?????????????????? ????????????? 1?????????????? 2??????????????????????????????????? 3?????????? 4?????? ================================================================================ ???????? ??????????????500?????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ????????????????????????????????? ================================================================================ ????? A??2?200 ?/?????.??????????????? B??4600?/?(??.???????????????????????????)? ? ? ? ? ? ? ? ?? ------------------------------------------ M-M-C ?.?.?.? ????????????????????? ???????????????????? ???????????????????? ? ??chinaipo@???.com ================================================================================ From bno at rejx.com Wed Dec 9 02:48:07 2009 From: bno at rejx.com (=?GB2312?B?xeDRtQ==?=) Date: Wed, 9 Dec 2009 10:48:07 +0800 Subject: (no subject) Message-ID: <200912090248.nB92m0uA011430@mx1.redhat.com> utrace-devel???????????????? ??????????2009??12??17-18?? ???? ??????????2009??12??19-20?? ???? ??????????2009??12??25-26?? ???? ??????????2010??1??15-16?? ???? ??????????2009??1??22-23?? ???? ?????????????????????????????????????????????????? ??????????????????-????????-????????-????????-?????????? ?? ????2500??/?? ?????????????????????????????????????????? ???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ??????????500??/?????????????????????????????? -------------------------------------------------------------------------------------- ?????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????? -------------------------------------------------------------------------------------- ?????????? ???????????????????????????? 1?????????????????? 2???????????????????????? 3???????????????????????? 4???????????????????????? ???????????????????????????? ?????????????????????? 1???????????????????????? 2?????????????????????????????????????? 3???????????????????? ?????????????????????? ?????????????????????? 1?????????????? 2?????????????????????? 3?????????????????? 4???????????????????????? 5?????????????????????????? 6?????????????????????? 7?????????????????????? ??????????????-????????-???????? ?????????????????????????? 1???????????????? 2?????????????????????? 3???????????????????? ???????????????????????????? 1. ???????????? 2. ???????????????? 3. ?????????????????????? 4. ?????????????????? 5. ?????????????????? 6. ?????????????? 7. ?????????????? 8. ???????????????? 9. ?????????????????? 10. ???????????????????? 11. ???????????? 12. ???????? ?????????????????????? 1?????????????????????????????? 2?????????????????? 3???????????????????????? 4???????????????????????? 5?????????????????????????????????? ?????????????????????????? 1?????????????????????????? 2????????????4?????? 3????????????5???? 4???????????????????? ???????????????????????? ?????????????????????? 1?????????????????????????????????????? 2???????????????????????? 3?????????????????????? ?????????????????????? 1???????????????????????? 2???????????????????????????? 3??????????????????E-mail?????????? 4???????????????????????????? ?????????????????????????? 1???????????????????????? 2???????????????????????????? 3???????????????????????????? ?????????????????????????????? ???????????????????????????????????????????????????? --------------------------------------------------------------------------------- ?????????? ?????????? ????????????????????????????????????,?????????????????????????????????????????????????? 2001???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????? ?????????????? ?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ------------------------------------------------------------------------------- ??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From gong.chui at gmail.com Thu Dec 10 08:19:04 2009 From: gong.chui at gmail.com (gong.chui at gmail.com) Date: Thu, 10 Dec 2009 16:19:04 +0800 Subject: (no subject) Message-ID: <200912090826.nB98QYe8024923@mx1.redhat.com> -------------------------------------------------------------------- ??????????????--?????????????? ????????????2009??12??21-22?? ???? 2009??12??24-25?? ???? 2009??12??28-29?? ???? ????????????3200??/???????????????????????????????????????????????? ?????? ???????????????????????????????????????????????????????????? -------------------------------------------------------------------- ?? ???????? ????CEO/??????????????????/??????????????????????/?????????????????? ??????????/????????????????????????????????/???????????????????????? ?? ?? ???????? ???????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????? 1. ?????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????? 2. ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????? 3. ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????????????? 4. ???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ???????? 5. ?????????????????????????????????????????????????????????? 6. ???????????????????????????????????? 7. ???????????????????????????????????????????????????????????????? ???? ???????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????/????/???????????????? ?????????????????????????????? ?? ???????? 1???????????????????????????????????????????????? 2??????????????????????????DFM?????????????????? 3??????????????????????????DFT?????????????????? 4?????????????????????????????????????? 5???????????????????????????????????????????????????? 6???????????????????????????????? -------------------------------------------------------------------- ?????????? ???? ???????? ???? ???????????????? 1. ???????????????????????????????????????? 2. ?????????????????? 1?????????????????????????????????? 2?????????????????????????????????????? 3. ???????????????????????????????????????? 4. ?????????????????? 1????????RD??????????D&P??????????P???????? 2???????????????????? 3???????????????? 4?????????????????? * ???????? * ???????????? * ???????????????????? * ?????????????????????????????????? 5. ?????????????? 1????????????????????????NPI?? 2???????????????????????????? 3???????????????????????????? 4???????????????????????????????????????????????????????? 6. ???????????????????????????????????????????????????????????????? ???? ?????????????? 1. ???????????????????? 1?????????? 2?????????? 3?????????? 4?????????? 5?????????? 6???????????????????????????? 2. ???????????????????? 3. ?????????????????????????????????? 1???????????????????????????? 2???????????????????????????????? 3?????????????????????????????????? * ?????????????????? * ???????????????????? * ???????????????? 4?????????????????????? * ???????????????????????????????????????????? * ???????????????????????????????????????? 4. ?????????????????????????????????????????????????????????????? ???? ????????????????????????DFM?? 1. ?????????????????????????????????????????? 1?????????????????????????? 2???????????????????????????????????????????????? 3???????????????????????????????????????????????????????? 4???????????? * ?????????????????????? * ???????????????????????? * ?????????????????????????????????????? * ???????????????????????????? * ???????????????? * ???????????????????????????????????????? * ?????????????????????????????????????????? * ?????????????????? * ?????????????????? * ?????????????????????????????????????????????????? 5???????????????? * ?????????????? * ?????????????????????????? * ?????????????????? * ?????????????????? * ???????????????????????????? * ?????????????????????????????????? * ?????????????????????????????? 6?????????? * ???????????????????????????????? * ???????????????????????????????? * ?????????????????????????????? 2. ???????????????????????????????????????????????????????????????????? 3. ???????????????? 1???????????????????????? 2?????????????????????????????????? 3???????????????????? 4???????????????????? 5?????????????????????????????? * ???????? * ???????? * ???????? * ???????? 6??????????????????????DFM???????????? 7???????????????????????????????? 8?????????????????????????? 4. ?????????????????????????????????????????????????????????????????????????? ???????? ???? ????????????????????????DFT?? 1. ???????????????????????????????? 1????????????Alpha????????????????Beta???????????? 2. ??????????Alpha????BETA???? 1???????????????????????????????????????????????????????? 2???????????????????????????????????? 3????????????????????????????????????????????????BETA?????????????? 4???????????????????????????????? 5???????????????????????????????????????????????????????????????????????????? 3. ???????????????????????????????? 1?????????????????????? 2?????????????????????????????????? 3?????????????????????????????????? 4???????????????????????? 5?????????????????????????????????????????????????? * ?????????????????????? * ?????????????????????????????????????? * ???????????????????????????????????????????????????? * ?????????????????????????????????????????? * ???????????????????????????????????????????????????????? * ???????????????????????? * ???????????????????????????? 6????????????????????????DFT???????????? 7?????????????????????????? 4. ????????????????????????????DFT?????????????????????????????????????????? ???? ???????????????? 1. ?????????????????????????? 2. ???????????????????????????? 3. ???????????????????????????????????????????????????????????? 4. ?????????????????????????????? 1?????????????????????????????????? 5. ?????????????????? 1???????????????????????????????????????????? 2?????????????????????????? 3???????????????????? 4?????????????????????????? * ?????????????????????????????????????????????????????????????????????? * ???????????????????????????????????????? * ???????? * ??????????????BOM???????????????????? * ???????????????????????????????? 5?????????????????????????????????? 6?????????????????????????? 6. ???????? 1?????????????????????????????????? 2?????????????????????????????? * ???????????????? * ?????????????????? * ?????????????????? 7. ???????????????? 1?????????????????????? 2?????????????????????????? 3?????????????? 4???????????????? 5?????????? 8. ?????????????????????????????????????????????????????????????????? ???? -------------------------------------------------------------------- ??????(Charles)?? -???????????????? -???????????????????????? -???????????????? ?????????????????????????????????????????????????????????????????? ??????????10?????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? IBM???????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ???????? ??????IBM?????????????????????????????????????????D?D???????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ????IT??????MARKETING?? ?????????????????????? ???????????????? ?????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????IT???? ????????????????????????????????????????????????????????????????????KP I?????????????????????????????? ?????????????????? ?????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????IT?????? ?????????????????????????????????????????????????????????????? ????KP I?????????????????????????????????????????????? ?????????????????????? ?????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????,?????????????????????????????? -------------------------------------------------------------------- From erp6108sapiis at ce.cn Wed Dec 9 18:36:20 2009 From: erp6108sapiis at ce.cn (erp6108sapiis) Date: Thu, 10 Dec 2009 02:36:20 +0800 (CST) Subject: (no subject) Message-ID: <20091209183620.6C02329EBBB@mail.ce.cn> SAP??????????????110G????160G??????????900??????????????????????600??????????????,????????????: 1??FI???????STEVEN????????PA???? 23.8G 2??CO????????WangHai????????PA???? 9G 3??BW????????GuoYu????BW????PA???? 4.09G 4??MM????????KANT WANG 08??????????PA???? 24.1G 5??PP????????KANT WANG 08??????????PA???? 21G 6??PS????????????????????PA???? 3.08G 7??SD????????????????ZHU YONG QING????????PA???? 12.6G 8??BASIS????????????????PA???? 2.03 ?????????????????????????????????????????????? 9??CRM????????????????PA???? 4.92G 10??WM????????????????PA???? 1.84G 11??PM PA???? 1G ?????????????????????????????????????????????? 12??PLM(140) 1G PA???? ?????????????????????????????????????????????? 13??ABAP: ????????????2G ????AC 1G ???????? 6G 14??HR PA???? 2.53G 15??QM ????PA???? 3.04G ??????????????????????????????1203545169 at qq.com???????????????????????????????????????????????????????? wdtwou4046394???????????? From vkg at erhc.com Thu Dec 10 16:30:57 2009 From: vkg at erhc.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Fri, 11 Dec 2009 00:30:57 +0800 Subject: (no subject) Message-ID: <200912101631.nBAGV4Kl005970@mx1.redhat.com> utrace-devel???????????????????????????????? ??????????2009??12??19-20?? ???? ??????????2009??12??26-27?? ???? ?? ????2500??/???????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? =============================================================================================== ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????,???????????????????????????????? =========================================================================== ?????????? ???????? ???????????????????????????? ?????????????????????????????????????????? 1?????????????????????????????????????????????????????????? 2???????????????????????????????????????????? 3???????????????????????????????????????????????????? 4???????????????????????????????????????????????????????????? 5???????????????????????????????????????????????????????????????????????? 6???????????????????????????????????????????????????????????????????? 7???????????????????????????????????????????????????????????? 8???????????????????????????? ?????????????????????????????????????????????????????? 1?????????????????????????????????????? 2?????????????????????????????????????????????????????????????????????? 3?????????????????????????????????????????????????????? 4???????????????????????????????? 5?????????????????????????????????????????????????? 6?????????????????????????????????????????????????????? 7???????????????????????????????????????? 8???????????????????????????????????????? 9???????????????????????????????? ?????????????????????????????????????????????? 1?????????????????????????? 2???????????????????????????????????????? 3???????????????????????????? 4???????????????????????? 5???????????????????????????????????????????? 6???????????????????????????????????????????????????????????? ???????????????????????????????????????? 1???????????????????? 2???????????????????????? 3???????????????????????????????????? 4?????????????????????????????????????????? 5???????????????????????????????? 6?????????????????????????????????????? ???????????????????????????????????????? 1???????????????????????????????????????????????????????????????????????????????????????????????????? 2???????????????????????????? 3???????????????????????????? 4???????????????????????????????? 5?????????????????????? 6?????????????????????????????????????????????????? 7?????????????????????????????????? ???????????????????????????????????????????????? 1???????????????????????????? 2?????????????????????????????????????? 3???????????????????????????? 4???????????????????? 5???????????????????????????????????? 6???????????????????????????? 7?????????????????????????????????? 8???????????????????????????? 9?????????????????? 10???????????????????????? 11???????????????????????????? 12?????????????? 13???????????????????????????????????????????????? 14???????????????????????????? ???????? ???????????????????? ?? ?????????????????????????????? 1???????????????????????????????????????????? 2?????????????????????????? 3?????????????????????????????????????????? 4?????????????????????????????????????????? 5???????????????????????????????? 6????????DM???????????? ?? ?????????????????????????????? 1???????????????????????????????????????????????? 2???????????????????????????? 3?????????????????????????????????????? 4?????????????????????????? 5?????????????? 6???????????????????????????????? 7?????????????????????? 8?????????????????????? 9?????????????????????????????????????? 10???????????????????????? 11?????????????????????????????? ?? ?????????????????????????????? 1?????????????????????? 2?????????????????????????????? 3???????????????????????????????????? 4?????????????????????????????????????????????? 5???????????????????? 6???????????????????????????????????????????????????? ?????? ?????????????????????????????????? 1?????????????????? 2????????????????????ABC???? 3?????????????????????????????????? 4?????????????????????????????? 5???????????????????????????????????? ???????? ?????????????????????????? ?? ?????????????????????????????????????? 1.?????????????? 2.?????????????? 3.?????????????? 4.???????????????? 5.?????????????? 6.?????????????? 7.?????????????? 8.?????????????? 9.?????????? 10.?????????? 11.???????????????????? 12.?????????????????????????? 13.????????+???????? ?? ?????????????????????????? 1.???????????????????????? 2.???????????????????? 3.???????????????????????? 4.???????????????????????????? 5.?????????????????????????????????? 6.?????????????????? 7.???????????? ?? ????????????????+???????? 1.?????????????????????? 2.?????????????????????? 3.?????????????????????? 4.??????????+???????? 5.??????????+???????? 6.??????????+???????? 7.??????????+???????? 8.????????????????????B2C+???????? 9.????????????????????B2B+???????? 10.????????????????????B2A+???????? 11.????????????????B2B+???????? 12.????????????????B2B+???????? 13.????????????????????????B2B+???????? ?? ?????????????????????????????????????????? 1?????????????????????????????????????? 2???????????????????????????????????????????????????? 3?????????????????????????????????????????????????? 4???????????????????????????????????????????????? 5???????????????????????????? 6?????????????????????????????????????????????????????? 7???????????????????????????????????????????????????????? 8???????????????????????????????????????????? 9?????????????????????????????????????????????????????????? 10?????????????????????????????????? 11?????????????????????????????????? 12?????????????????????????????????? 13???????????????????????? 14???????????????????????? 15?????????? 16???????????????????????????? 17???????????????????????????????????? 18?????????????????????????????????? 19?????????????????????????????????????????????? 20?????????????????????? 21?????????????????????????????????? ======================================================================= ??????????????????????????(??????????????MBA????????????????????)?????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????(??)???????????? ??????????????????????????????????????????????????????????IBT?????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????? ?????? ???????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????? ====================================================================================== ??????????????????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From mong.shiao at live.cn Sun Dec 13 06:09:58 2009 From: mong.shiao at live.cn (mong.shiao at live.cn) Date: Sun, 13 Dec 2009 14:09:58 +0800 Subject: (no subject) Message-ID: <200912120614.nBC6ErjV016158@mx1.redhat.com> ================================================================================ ?????????????????D?D???????????????? ================================================================================ ??.??.??.??.???? 2009??12??21-22?? ???? 2009??12??24-25?? ???? 2009??12??28-29?? ???? ??.??.??.??.??.??.??.?????????????????????????? ??.??.??.??.??.???????????????????????????? ??.??.??.??.??.???????????????????????????? ??.????rdwork@ 126.com ??????????????????????/???????????????????????????????????????? ================================================================================ ???????????????? ???????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????? ?????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????? ?????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????? ?????????????????????????????????????????????????????? 1.???????????????????????????????????????????????????????? 2.??????????????????????????????????????????????????????????????+?????? 3.?????????????????????????????????????????????????????????????????????????????? ?? 4.?????????????????????????????????????????????????????????????????? 5.?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ?????????? ???????????????????????????? ?????????????????????????????????????????????????? ??????????????????KJ??AHP??$APPEALS??BSA??HOQ??FFBD??RAS?????? ???????????????? ???????????????????????????? ?????????????????????????????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????? ?????????????????????????????? ???????????????? 1.???????????????????????????????????????????????? 2.???????????????????????????????????????????????????????????????????????? 3.?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????? 4.?????????????????????????????????????????????????????????????????????????? 5.?????????????????????????????????????????????????????????????????????????????? 6.???????????????????????????????????????????????????????????????????? 7.???????????????????????????????????????????????????????????????? 8.???????????????????????????????????????????????????? ?????????????????? ????CEO/??????????????????????????/????????/????????/?????????????????????????? ?????????? ??.??.??.???????????????????????????????????????????????????? ================================================================================ ???????????????? : ???????????? ?????????????????????????????? 1.???????????????????????????????????????????? 1)?????????????????????????????????????????? 2)???????????????????????????????????????? 2.?????????????????? 1)WANTS/NEEDS/DEMANDS?????????????????????????????????????????????????????????????? ???????????????????? 3.???????????????????????????????????????????????????????????????????????????????? ?????????????????????????? 4.CMMI???????????????? 1)RM???????????????????????????? 2)RD???????????????????????????? 5.?????????????? ???????????????????????????????????????????????? 1.?????????????????????????? 2.?????????????????????????????????????????????????? 3.?????????? 1)???????????????????????????????? 2)?????????????? --?????????????????? --?????????????????? 3)?????????????????????????????? --???????????????????????? --?????????????? --???????????? --?????????????????????????????????? 4.???????? 1)???????????????? 2)?????????????? 3)?????????????????? 5.?????????????????????? 1)???????????????? 2)???????????????????? 3)???????? 4)???????????? 5)?????????????????????????????????????????????????????????? 6.???????????????? 1)???????????????????? 2)???????????????? 3)????????????7???? 4)?????????????????????? 5)?????????????????? 7.???????????????????????????????????????????????????? 1)?????????????????? --???????????????????????????????????????????? --??????????????10???????????? 2)?????????????????? 3)?????????? ?????????????? --???????????????????????????????????????????? --???????????????????????????????????????????????????? 4)???????????????????????????????????????????????? 5)?????????????????????? 6)???????????????????????????????????????????????????? 7)?????????????????? 8.?????????????????????????????? 1)??????????IT???? 2)?????????????????????????? 3)???????????????? 4)???????????????????? 5)???????????????????????????????????? ?????????????????????? ?? ?????????????????????????????????????? 1.?????????????????????????? 2.???????????? 1)???????????????????? 2)???????????????????????????? --?????????????????????????????????? --???????????????????????? --???????????????????????????? --???????????????????????????????????????????????????????? 3)???????????????????? --?????????????????? --?????????????????????????????????????????? --?????????????????? 3.???????????????????????????????? 1)???????????????? --???????????????????????????????????? --???????????????????????????????????????????????????? 2)????????????????????????????BSA???? 3)????????????????????????AHP?? --????????4???? --???????????????????????????? --FBS???????????????????????? 4.?????????????????? 1)???????????????????????????? --?????????????????????? --???????????????????????????????????????????? --?????????????????????????????????? 5.?????????????????????????????????????? 1)????????????????????????????????$APPEALS?? --???????????????? --???????????????????? --????????????????????????????????8?????????????????? 6.???????????? 1)?????????????????????????????????? 2)?????????????????????????????????? 7.???????????????????????????????????????????????????? 8.???????????????????????????????????????????????????? 1)???????????????????? 2)?????????????? 3)???????????????????????????? 4)???????????????????????????????????????????? 5)?????????????????? ???????????????????????? ?? ???????????????????????????????????????????? 1.?????????????????????????? 2.???????????????????????? 1)?????????????????? 2)???????????????????????????????????????????? 3.??????????????????????????????FBS 1)???????????? 2)????????????????????????????????????FBS???? 3)??????????FBS???????? --?????????????? --???????????????????????????? --???????????????????????????????????????????????????? --???????????????????????????????????????? --?????????????????? 4)???????????? --?????????????????????????????? --??????????????????????????CDS???? --????????????????????????????????CDS???????? --??????????????????????????????SBD???? --????????????????????????????????SBD???????? --?????????????????????????? 5)???????? --????????????RAS?????? --?????????????????????????? --?????????????????? --??????????????????????????????->??????????->????????->?????????????????????? ???? ================================================================================ ????????:??????(DON) ??????????????????CMM/CMMI???????? ????????: ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? NGN???????????????? ???????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ????????????????????CMM?????????????? ?????????????????????????????????????????? ???????????? ????????????????: ???????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????????????????????????????(????????)?? ???????????????????????????????????????????????????????????????????????????????? ????CMMIL4????????CMMI L2???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????? ????????????????: ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ================================================================================ ??.??.??.??.??.??.??.??.???? ------------------------------------------ M.M.C.?? ?? ?? ?? ??.??.??.??.??.??.??.?????????????????????????? ??.??.??.??.??.???????????????????????????? ??.??.??.??.??.???????????????????????????? ??.????rdwork@ 126.com ================================================================================ From zt at iee.com Mon Dec 14 03:06:31 2009 From: zt at iee.com (=?GB2312?B?x+vXqs/gudiyv8PF?=) Date: Mon, 14 Dec 2009 11:06:31 +0800 Subject: (no subject) Message-ID: <200912140306.nBE36MTm013440@mx1.redhat.com> ??????????????--?????????????? ??????????2009??12??21-22?? ???? ??????????2009??12??24-25?? ???? ??????????2009??12??28-29?? ???? ??????????3200??/???? *????????????????* ???????????????????????????????? ?????????????????????????????????????????????????????????? ????????????????????/??????????????????/????????????????????/???????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------- ???????? ?????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????? 1. ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????? 2. ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????? 3. ???????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????? ?????????????????????? 4. ???????????????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????? 5. ?????????????????????????????????????????????????????????? 6. ???????????????????????????????????? 7. ???????????????????????????????????????????????????????????????? ???? ???????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????/????/?????????????????????????????????????????????? ------------------------------------------------------------------------------------------ ???????? 1???????????????????????????????????????????????? 2??????????????????????????DFM?????????????????? 3??????????????????????????DFT?????????????????? 4?????????????????????????????????????? 5???????????????????????????????????????????????????? 6???????????????????????????????? ------------------------------------------------------------------------------------------- ???????? ???? ???????? ???? ???????????????? 1. ???????????????????????????????????????? 2. ?????????????????? 1?????????????????????????????????? 2?????????????????????????????????????? 3. ???????????????????????????????????????? 4. ?????????????????? 1????????RD??????????D&P??????????P???????? 2???????????????????? 3???????????????? 4?????????????????? * ???????? * ???????????? * ???????????????????? * ?????????????????????????????????? 5. ?????????????? 1????????????????????????NPI?? 2???????????????????????????? 3???????????????????????????? 4???????????????????????????????????????????????????????? 6. ???????????????????????????????????????????????????????????????? ???? ?????????????? 1. ???????????????????? 1?????????? 2?????????? 3?????????? 4?????????? 5?????????? 6???????????????????????????? 2. ???????????????????? 3. ?????????????????????????????????? 1???????????????????????????? 2???????????????????????????????? 3?????????????????????????????????? * ?????????????????? * ???????????????????? * ???????????????? 4?????????????????????? * ???????????????????????????????????????????? * ???????????????????????????????????????? 4. ?????????????????????????????????????????????????????????????? ???? ????????????????????????DFM?? 1. ?????????????????????????????????????????? 1?????????????????????????? 2???????????????????????????????????????????????? 3???????????????????????????????????????????????????????? 4???????????? * ?????????????????????? * ???????????????????????? * ?????????????????????????????????????? * ???????????????????????????? * ???????????????? * ???????????????????????????????????????? * ?????????????????????????????????????????? * ?????????????????? * ?????????????????? * ?????????????????????????????????????????????????? 5???????????????? * ?????????????? * ?????????????????????????? * ?????????????????? * ?????????????????? * ???????????????????????????? * ?????????????????????????????????? * ?????????????????????????????? 6?????????? * ???????????????????????????????? * ???????????????????????????????? * ?????????????????????????????? 2. ???????????????????????????????????????????????????????????????????? 3. ???????????????? 1???????????????????????? 2?????????????????????????????????? 3???????????????????? 4???????????????????? 5?????????????????????????????? * ???????? * ???????? * ???????? * ???????? 6??????????????????????DFM???????????? 7???????????????????????????????? 8?????????????????????????? 4. ?????????????????????????????????????????????????????????????????????????????????? ???? ????????????????????????DFT?? 1. ???????????????????????????????? 1????????????Alpha????????????????Beta???????????? 2. ??????????Alpha????BETA???? 1???????????????????????????????????????????????????????? 2???????????????????????????????????? 3????????????????????????????????????????????????BETA?????????????? 4???????????????????????????????? 5???????????????????????????????????????????????????????????????????????????? 3. ???????????????????????????????? 1?????????????????????? 2?????????????????????????????????? 3?????????????????????????????????? 4???????????????????????? 5?????????????????????????????????????????????????? * ?????????????????????? * ?????????????????????????????????????? * ???????????????????????????????????????????????????? * ?????????????????????????????????????????? * ???????????????????????????????????????????????????????? * ???????????????????????? * ???????????????????????????? 6????????????????????????DFT???????????? 7?????????????????????????? 4. ????????????????????????????DFT?????????????????????????????????????????? ???? ???????????????? 1. ?????????????????????????? 2. ???????????????????????????? 3. ???????????????????????????????????????????????????????????? 4. ?????????????????????????????? 1?????????????????????????????????? 5. ?????????????????? 1???????????????????????????????????????????? 2?????????????????????????? 3???????????????????? 4?????????????????????????? * ?????????????????????????????????????????????????????????????????????? * ???????????????????????????????????????? * ???????? * ??????????????BOM???????????????????? * ???????????????????????????????? 5?????????????????????????????????? 6?????????????????????????? 6. ???????? 1?????????????????????????????????? 2?????????????????????????????? * ???????????????? * ?????????????????? * ?????????????????? 7. ???????????????? 1?????????????????????? 2?????????????????????????? 3?????????????? 4???????????????? 5?????????? 8. ?????????????????????????????????????????????????????????????????????? -------------------------------------------------------------------------------- ?????????? Charles ???????? ???????????????????????????????????????????????????????????????????????????????????? ??10?????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??????????????????IBM???????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??IBM?????????????????????????????????????????D?D?????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????IT??????MARKETING ???????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????????? ????????????????????????????????????????????IT???????????????????????????????????? ????????????????????????????????????KPI?????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????? ====================================================================================== ????????????????--??????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From ang.nang at yahoo.com.hk Fri Dec 18 11:00:31 2009 From: ang.nang at yahoo.com.hk (ang.nang at yahoo.com.hk) Date: Fri, 18 Dec 2009 19:00:31 +0800 Subject: (no subject) Message-ID: <200912171108.nBHB8BGK003079@mx1.redhat.com> ============================================================================= ?????????????????????? ============================================================================= ???????????? 2010??01??21-22 ???? 2010??01??23-24 ???? 2010??01??30-31 ???? ??????????????????400-889,9628 ??????????????021-510,994,75 ??????????????020-336,656,97 / 345,209,81 ============================================================================= ?????????? -?????????????????????? -???????????????????? -?????????????????????? -?????????????????????????? -???????????????????????? -?????????????????????????????????? -?????????????????????????????????????? -?????????????????? ???????????? ?????????????????????????????????????????????????????????????? ????????: ???????????????????????????? ?????????? 2??/13?????? ============================================================================= ???????????????????????????????????? ???????????????????????????????? ?????????????????? ?????????????????????????????? ???????????????????????????? ?????????????????????? ?????????????????????????? ???????????? ???????????????????????? ?????????????????? ?????????????????????????? ???????????????????? ?????????????? ???????????????? ?????????????? ???????????????? ?????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????? ???????????? ?????????????????? ???????????????????????????????????????????? ?????????????? ???????????????? ???????????????? ?????????????????????? ???????????????????? ?????????????? ?????????????? ?????????????? ???????????????????????? ?????????????????? ???????????? ?????????????????????????????????????? ???????????????????????????????? ???????????????????????????? ???????????????? ?????????????? ???????????????????????????????? ?????????????????????? ?????????????????????????? ?????????? ???????????????????????????????????? ?????????????????????????????????? ?????????????????????? ?????????????? ?????????? ???????? ?????????????????????????? ?????????? ???????????????? ???????????????????????? ?????????????????????? ???????????????? ?????????????????? ???????????????????????????????? ????????/?????????????????????? ????????/?????????????????????? ???????????????????? MRO???????????????? ???????????????????? ???????????????????????????????????????????? ???????????????????????????? ???????????????? ???????????????????? ???????? ?C ???????????????? --??????????????????????????, --?????????????????????????? ???????? ????????????????????,????????, ?????????????????????????? ???????????????????????? ??????????????/?????????????? ????????/?????????????????? ?????????????? ?????????????????????????? ============================================================================= ?? ????????:?????? -???????????? -???????????????????? -?????????????????????? ??????????????????????????????????????????????????????????????500???????? ??????????????????????????????????????????????????????????????????????????500 ?????????????????????????????????????????????????????????????????? ??CIPS???? ?????????????? ????????????????????????ISM????????????????CPM???????????????? ????????/ITC ???????????????????????????????????????????????????????????????? ????????????????????,???????????????????????????????????????????????????????? ????????????????????????????????????,???????????????????????????????????????? ????????????????????????????????????????????????????????,???????????????????? ??????????????????????????????????????????????????????????????,?????????????? ???????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????? ============================================================================= ??????????2800??/???????????????????????????????????????? ???????????????????? ------------------------------------------ M M C ?? ?? ?? ?? ??????????????????400-889,9628 ??????????????021-510,994,75 ??????????????020-336,656,97 / 345,209,81 ============================================================================= From sqy at yrft.com Thu Dec 17 17:55:51 2009 From: sqy at yrft.com (=?GB2312?B?16rQ6MfzyMvUsQ==?=) Date: Fri, 18 Dec 2009 01:55:51 +0800 Subject: (no subject) Message-ID: <200912171755.nBHHtmcr001692@mx1.redhat.com> ============================================================= utrace-devel??????????????? ?????2010?1?9?-10? ?? ?????2010?1?20-21??? ? ??2500?/ ?????????????????? ????? ????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ========================================================================================== ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ==================================================================================== ????? ?????????????? ??????????? ????????????? ???????????? ???????????? ????????? ?????????? ????????????? ?????????? =================================================================================== ???? ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? ==================================================================================== ??????????:???????????????1986????Gerber???????? ?Michigan State University (???????) ????????????,?????Heinz (??)???????????????????????????????????????? ????????????????2000???,?????????????????????? ??,???????500?????????????,?????????????????? ??????????????????????????????????????????? ?????????????????? ???????????????????????? ??????????????????????????????????????????? ??????????????????????????? ?????????????,?? ???????,??,???????????,?????,???????????????? ?????????????????,??????????????,???????????? ???????? ------------------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From usnklu at yahoo.com Fri Dec 18 04:09:47 2009 From: usnklu at yahoo.com (Allen.Chang) Date: Fri, 18 Dec 2009 12:09:47 +0800 Subject: (no subject) Message-ID: <200912180409.nBI49fOc018162@mx1.redhat.com> ============================================================================================== ???????? ============================================================================================== ?????? 2009?12?17-18? ?? 2009?12?19-20? ?? 2009?12?25-26? ?? 2010?01?15-16? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ============================================================================================== ?-?-?-?: --??????????????????????????? --??????????????????????????? --??????????????????????????? ?????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ???????? ?-?-?-?? ???????????????????? ?-?-?-?? ????-????-????-????-????? ============================================================================================== ?????????????? 1????????? 2???????????? 3???????????? 4???????????? ?????????????? ??????????? 1???????????? 2??????????????????? 3?????????? ??????????? ??????????? 1??????? 2??????????? 3????????? 4???????????? 5????????????? 6??????????? 7??????????? ???????-????-???? ????????????? 1???????? 2??????????? 3?????????? ?????????????? 1. ?????? 2. ???????? 3. ??????????? 4. ????????? 5. ????????? 6. ??????? 7. ??????? 8. ???????? 9. ????????? 10. ?????????? 11. ?????? 12. ???? ??????????? 1??????????????? 2????????? 3???????????? 4???????????? 5????????????????? ????????????? 1????????????? 2??????4??? 3??????5?? 4?????????? ???????????? ??????????? 1??????????????????? 2???????????? 3??????????? ??????????? 1???????????? 2?????????????? 3?????????E-mail????? 4?????????????? ????????????? 1???????????? 2?????????????? 3?????????????? ??????????????? ============================================================================================== ?-?-?-?: ???: -?????????? -?????????? -???????????? -?????????????? -????????????(CAML)?? -????????????(IHRL)?? -???????????????? -?????????ICMCI -???????????? ????? ??????????????????????????????????????????????? ?????????????????????????????????????? ????? ??????2001??????????????????????????????????????? ??????????????????????????2008?????????????300???? ????8000????????????50000?????????????????????????? ???????????????????????? ????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ICMCI????????? ???????????????? ??.???????????????????????????? ??????????????????? ????? ????????????TTT?????????????LTT????????360????????? ?????????????????????????? ????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????? ============================================================================================== ? ??2,500 /?(??????????????) ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-8899,628 ???????021-5109,9475 ???????020-3397,2216 / 3452,0981 ? ??hrlawclub @126.com ============================================================================================== From oleg at redhat.com Fri Dec 18 17:27:47 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 18:27:47 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218030601.GB16470@nowhere> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> Message-ID: <20091218172747.GA10924@redhat.com> On 12/18, Frederic Weisbecker wrote: > > On Fri, Dec 18, 2009 at 01:56:50AM +0100, Oleg Nesterov wrote: > > Hi. > > > > do_debug() is obviously wrong wrt PTRACE_SINGLESTEP/TIF_SINGLESTEP, no? > > > > Afaics this was broken by > > > > hw-breakpoints: modifying generic debug exception to use thread-specific debug registers > > commit 08d68323d1f0c34452e614263b212ca556dae47f > > > > To verify, the "patch" below fixes the stepping for me, not sure what > > is the proper fix... > > > > Oleg. > > > > --- arch/x86/kernel/traps.c~ 2009-12-18 00:20:49.000000000 +0100 > > +++ arch/x86/kernel/traps.c 2009-12-18 01:44:05.000000000 +0100 > > @@ -575,7 +575,7 @@ dotraplinkage void __kprobes do_debug(st > > regs->flags &= ~X86_EFLAGS_TF; > > } > > si_code = get_si_code(tsk->thread.debugreg6); > > - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > > +// if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > > send_sigtrap(tsk, regs, error_code, si_code); > > > > But I don't understand why it is broken with the check. > If we are in a singlestep exception, dr6 should have its > DR_STEP bit set... > > Single stepping works well for me, after a quick check on > gdb. How did you trigger the bug? Please find the trivial test-case below. It hangs, because PTRACE_SINGLESTEP doesn't trigger the trap. (not sure this matters, but I did the testing under kvm) Oleg. #include #include #include #include #include #include int main(void) { int pid, status, i; pid = fork(); if (!pid) for (;;); sleep(1); assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0); assert(pid == wait(&status)); assert(WIFSTOPPED(status)); for (i = 0; i < 10; ++i) { assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); printf("wait %d ...\n", i); assert(pid == wait(&status)); assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP); } kill(pid, SIGKILL); return 0; } From prasad at linux.vnet.ibm.com Fri Dec 18 17:37:03 2009 From: prasad at linux.vnet.ibm.com (K.Prasad) Date: Fri, 18 Dec 2009 23:07:03 +0530 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218005650.GA20667@redhat.com> References: <20091218005650.GA20667@redhat.com> Message-ID: <20091218173703.GA3726@in.ibm.com> On Fri, Dec 18, 2009 at 01:56:50AM +0100, Oleg Nesterov wrote: > Hi. > > do_debug() is obviously wrong wrt PTRACE_SINGLESTEP/TIF_SINGLESTEP, no? > > Afaics this was broken by > > hw-breakpoints: modifying generic debug exception to use thread-specific debug registers > commit 08d68323d1f0c34452e614263b212ca556dae47f > > To verify, the "patch" below fixes the stepping for me, not sure what > is the proper fix... > > Oleg. > > --- arch/x86/kernel/traps.c~ 2009-12-18 00:20:49.000000000 +0100 > +++ arch/x86/kernel/traps.c 2009-12-18 01:44:05.000000000 +0100 > @@ -575,7 +575,7 @@ dotraplinkage void __kprobes do_debug(st > regs->flags &= ~X86_EFLAGS_TF; > } > si_code = get_si_code(tsk->thread.debugreg6); > - if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > +// if (tsk->thread.debugreg6 & (DR_STEP | DR_TRAP_BITS)) > send_sigtrap(tsk, regs, error_code, si_code); > preempt_conditional_cli(regs); > The cause for such a behaviour isn't apparent to me and like others, I'm unable to recreate it (Single-stepping using gdb over a tiny program running on x86, latest -tip works fine). Did you try to narrow down the causative piece of code, among the several hooks in do_debug()? A separate 'dr6' and 'thread.debugreg6' was desired by the community (refer: Pine.LNX.4.44L0.0904011216460.3736-100000 at iolanthe.rowland.org and Pine.LNX.4.44L0.0904091634150.4094-100000 at iolanthe.rowland.org) then. 'dr6' and 'thread.deebugreg6' would contain the value of the DR6 status register and every exception handler would reset the bits in them corresponding to which action has been taken. The difference in them being that 'thread.debugreg6' would be eventually processed by code interested in user-space while 'dr6' was restricted to those hooks in do_debug(). Thanks, K.Prasad From prasad at linux.vnet.ibm.com Fri Dec 18 17:58:42 2009 From: prasad at linux.vnet.ibm.com (K.Prasad) Date: Fri, 18 Dec 2009 23:28:42 +0530 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218172747.GA10924@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> Message-ID: <20091218175842.GA10666@in.ibm.com> On Fri, Dec 18, 2009 at 06:27:47PM +0100, Oleg Nesterov wrote: > On 12/18, Frederic Weisbecker wrote: > > > > On Fri, Dec 18, 2009 at 01:56:50AM +0100, Oleg Nesterov wrote: > > > Hi. > > Single stepping works well for me, after a quick check on > > gdb. How did you trigger the bug? > > Please find the trivial test-case below. It hangs, because > PTRACE_SINGLESTEP doesn't trigger the trap. > aah...my other mail just criss-crossed yours. I quickly ran on the said x86 box, loaded with -tip (commit 7818b3d0fc68f5c2a85fed86d9fa37131c5a3068) and it runs fine. [root at llm05 prasadkr]# cat oleg.c #include #include #include #include #include #include int main(void) { int pid, status, i; pid = fork(); if (!pid) for (;;); sleep(1); assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0); assert(pid == wait(&status)); assert(WIFSTOPPED(status)); for (i = 0; i < 10; ++i) { assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); printf("wait %d ...\n", i); assert(pid == wait(&status)); assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP); } kill(pid, SIGKILL); return 0; } [root at llm05 prasadkr]# gcc -o oleg oleg.c -g -Wall [root at llm05 prasadkr]# ./oleg wait 0 ... wait 1 ... wait 2 ... wait 3 ... wait 4 ... wait 5 ... wait 6 ... wait 7 ... wait 8 ... wait 9 ... [root at llm05 prasadkr]# Am I missing something here? Thanks, K.Prasad From oleg at redhat.com Fri Dec 18 18:24:24 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 19:24:24 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218175842.GA10666@in.ibm.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218175842.GA10666@in.ibm.com> Message-ID: <20091218182424.GA24180@redhat.com> On 12/18, K.Prasad wrote: > > On Fri, Dec 18, 2009 at 06:27:47PM +0100, Oleg Nesterov wrote: > > On 12/18, Frederic Weisbecker wrote: > > > > > > On Fri, Dec 18, 2009 at 01:56:50AM +0100, Oleg Nesterov wrote: > > > > Hi. > > > > > > Single stepping works well for me, after a quick check on > > > gdb. How did you trigger the bug? > > > > Please find the trivial test-case below. It hangs, because > > PTRACE_SINGLESTEP doesn't trigger the trap. > > > > aah...my other mail just criss-crossed yours. > > I quickly ran on the said x86 box, loaded with -tip (commit > 7818b3d0fc68f5c2a85fed86d9fa37131c5a3068) and it runs fine. Hmm. Just re-tested 2.6.33-rc1 under kvm, it hangs... Oleg. > [root at llm05 prasadkr]# cat oleg.c > #include > #include > #include > #include > #include > #include > > int main(void) > { > int pid, status, i; > > pid = fork(); > if (!pid) > for (;;); > > sleep(1); > assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0); > > assert(pid == wait(&status)); > assert(WIFSTOPPED(status)); > > for (i = 0; i < 10; ++i) { > assert(ptrace(PTRACE_SINGLESTEP, pid, 0,0) == 0); > > printf("wait %d ...\n", i); > assert(pid == wait(&status)); > > assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP); > } > > kill(pid, SIGKILL); > return 0; > } > > [root at llm05 prasadkr]# gcc -o oleg oleg.c -g -Wall > [root at llm05 prasadkr]# ./oleg > wait 0 ... > wait 1 ... > wait 2 ... > wait 3 ... > wait 4 ... > wait 5 ... > wait 6 ... > wait 7 ... > wait 8 ... > wait 9 ... > [root at llm05 prasadkr]# > > Am I missing something here? > > Thanks, > K.Prasad > From roland at redhat.com Fri Dec 18 20:05:03 2009 From: roland at redhat.com (Roland McGrath) Date: Fri, 18 Dec 2009 12:05:03 -0800 (PST) Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: Oleg Nesterov's message of Friday, 18 December 2009 18:27:47 +0100 <20091218172747.GA10924@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> Message-ID: <20091218200503.2CA0DF9A4@magilla.sf.frob.com> > Please find the trivial test-case below. It hangs, because > PTRACE_SINGLESTEP doesn't trigger the trap. 2.6.33-rc1 x86-64 works for me with either -m64 or -m32 version of that test. > (not sure this matters, but I did the testing under kvm) Apparently it does. You should hack some printks into do_debug() and see how kvm is differing from real hardware. (Actually you can probably do this with a notifier added by a module, not that you are shy about recompiling!) Probably kvm's emulation of the hardware behavior wrt the DR6 bits is not sufficiently faithful. Conceivably, kvm is being consistent with some older hardware and we have encoded assumptions that only newer hardware meets. But I'd guess it's just a plain kvm bug. Thanks, Roland From oleg at redhat.com Fri Dec 18 22:32:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Fri, 18 Dec 2009 23:32:30 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218200503.2CA0DF9A4@magilla.sf.frob.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> Message-ID: <20091218223230.GA1853@redhat.com> On 12/18, Roland McGrath wrote: > > > Please find the trivial test-case below. It hangs, because > > PTRACE_SINGLESTEP doesn't trigger the trap. > > 2.6.33-rc1 x86-64 works for me with either -m64 or -m32 version of that test. > > > (not sure this matters, but I did the testing under kvm) > > Apparently it does. You should hack some printks into do_debug() and see > how kvm is differing from real hardware. (Actually you can probably do > this with a notifier added by a module, not that you are shy about > recompiling!) > > Probably kvm's emulation of the hardware behavior wrt the DR6 bits is not > sufficiently faithful. Conceivably, kvm is being consistent with some > older hardware and we have encoded assumptions that only newer hardware > meets. But I'd guess it's just a plain kvm bug. OK, thanks. Hmm. Now I see how wrong I was when I said this code is "obviously wrong" ;) I'll add the debugging printk's and report the output. Sorry for delay, can't do this today. Oleg. From fweisbec at gmail.com Fri Dec 18 23:15:47 2009 From: fweisbec at gmail.com (Frederic Weisbecker) Date: Sat, 19 Dec 2009 00:15:47 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218200503.2CA0DF9A4@magilla.sf.frob.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> Message-ID: <20091218231545.GA8803@nowhere> On Fri, Dec 18, 2009 at 12:05:03PM -0800, Roland McGrath wrote: > > Please find the trivial test-case below. It hangs, because > > PTRACE_SINGLESTEP doesn't trigger the trap. > > 2.6.33-rc1 x86-64 works for me with either -m64 or -m32 version of that test. > > > (not sure this matters, but I did the testing under kvm) > > Apparently it does. You should hack some printks into do_debug() and see > how kvm is differing from real hardware. (Actually you can probably do > this with a notifier added by a module, not that you are shy about > recompiling!) > > Probably kvm's emulation of the hardware behavior wrt the DR6 bits is not > sufficiently faithful. Conceivably, kvm is being consistent with some > older hardware and we have encoded assumptions that only newer hardware > meets. But I'd guess it's just a plain kvm bug. It looks like in kvm, before entering the guest, we restore its debug registers: vcpu_enter_guest(): if (unlikely(vcpu->arch.switch_db_regs)) { set_debugreg(0, 7); set_debugreg(vcpu->arch.eff_db[0], 0); set_debugreg(vcpu->arch.eff_db[1], 1); set_debugreg(vcpu->arch.eff_db[2], 2); set_debugreg(vcpu->arch.eff_db[3], 3); } But what happens to dr6, I don't know. Adding Avi and Jan in Cc. From caiqian at redhat.com Sat Dec 19 15:32:32 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Sat, 19 Dec 2009 10:32:32 -0500 (EST) Subject: new Fedora 13 utrace kernel In-Reply-To: <651708828.1959921261236317846.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1104922288.1959941261236752306.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Hi Roland, The utrace patch looks suspicious in utrace.h, which cause the compilation failure without CONFIG_UTRACE. I have confirmed that the git tree looks sane. +static inline void utrace_init_task(struct task_struct *child) +{ +} +{ +} + Thanks, CAI Qian From greatness at awexp.com.au Sun Dec 20 04:21:51 2009 From: greatness at awexp.com.au (Bennefield) Date: Sun, 20 Dec 2009 13:21:51 +0900 Subject: No subject Message-ID: <4B2DA44D.2070607@awexp.com.au> -------------- next part -------------- A non-text attachment was scrubbed... Name: velutinous.jpg Type: image/jpeg Size: 14513 bytes Desc: not available URL: From e4a at oyeu.com Sun Dec 20 04:51:51 2009 From: e4a at oyeu.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Sun, 20 Dec 2009 12:51:51 +0800 Subject: =?GB2312?B?s7W85Nb3udy53MDtxNzBpszhyf11dHJhY2UtZGV2ZWw=?= Message-ID: <200912200451.nBK4pgZ9019223@mx1.redhat.com> utrace-devel????????????? ?????2010?1?16-17? ?? ?????2010?1?23-24? ?? ? ??2600?/? ???? ????????????????????? ??????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ----------------------------------------------------------------------------------------------- ??????? ???????????????????????????????????????????????? ??????????????????????????????????????????????? ?????????. ??????????????????????????????????????????????? ??????????????????????????????????????????????! ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????? ??????????????????????????????????? -------------------------------------------------------------------------------------------- ???????????? l?????????????????????????????????????????? 2??????????????????????????????? 3?????????????????????????????????????????? 4????????????????????????????????????????????? 5???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? -------------------------------------------------------------------------------------------- ????? l??????????????????????????????? 2??????????????????? 3????????????????????? 4???????????????????????????? 5??????????????TPM???????? ????? l????????????????????????? 2???????????????????????????????????? 3???????????????????????????????????????????? -------------------------------------------------------------------------------------------- ????? ??????????????? ??????????? ????????????????? ????????????? ?????/?????/????? ?????????????? ??????????? ????????????? ????????????? ???????????????? ????????????????? ???????????????? ???????????????? ???????????? ???????????? ??????????????? ???????????? ??????????? ?????????????? ???????????????? ??????????????? ???????(?????) ?????????????? ????????? ??????????? ????????? ??????????? ????????????? ??:??????????? ???? ??N?????/??????? ???ISO9000??????????? ??????????????? ????????????????TPS? ???????????TOYOTA??? ????????????? ????5S??????????? ????5S????????????? ?5S????????????5??S? ???????5S?????6S?7S? ???????????? ???????????????? ????????????????? ???????????????????? ?????????????????? ????TQM?6?????????? ????????????????????????? ??????????????????? ??????????????? ???TPM??????????????????? ???TPM????????? ???: ???? ???? ??????????? ??????????? ?????????? ????????? ????????? ??: ??????????? ?????????????? ??????? ?????????????????? ??????????? ??????????????? ---???????????,??????????????) ---????????? ---????????? ---???????????? ??????/????????????; ???? 1.??????????????? 2.?????????? ?????????????????; ---???????????? ------------------------------------------------------------------------------------------------------------- ?????????? ?????? ???????? ???????????????(SUMIDA)????????(CASIO) ???13??????????????????????????????????????????????? ??WF&IE ???????????????????????????????????????????????????????JIT ??????NPS????????????? ??????????????(??,??,??,??,?????)????? ?:??????????ST?????????????????????????????????????????????? ???????????????????????????????80?????? ?????????????????????????????????????????????ABB?????????? ?????-??????????????????????????????????????????????????? ????????????????????????????????????????????????????????? ?????????????????????????????? ??????????????????,?????????????????????????????????????? ?????????????????????????? ------------------------------------------------------------------------------------------------------------- ????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From avi at redhat.com Sun Dec 20 08:30:33 2009 From: avi at redhat.com (Avi Kivity) Date: Sun, 20 Dec 2009 10:30:33 +0200 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218231545.GA8803@nowhere> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> <20091218231545.GA8803@nowhere> Message-ID: <4B2DE0A9.4090400@redhat.com> On 12/19/2009 01:15 AM, Frederic Weisbecker wrote: > >> Apparently it does. You should hack some printks into do_debug() and see >> how kvm is differing from real hardware. (Actually you can probably do >> this with a notifier added by a module, not that you are shy about >> recompiling!) >> >> Probably kvm's emulation of the hardware behavior wrt the DR6 bits is not >> sufficiently faithful. Conceivably, kvm is being consistent with some >> older hardware and we have encoded assumptions that only newer hardware >> meets. But I'd guess it's just a plain kvm bug. >> > A kvm bug is most likely. > It looks like in kvm, before entering the guest, we restore its > debug registers: > > vcpu_enter_guest(): > if (unlikely(vcpu->arch.switch_db_regs)) { > set_debugreg(0, 7); > set_debugreg(vcpu->arch.eff_db[0], 0); > set_debugreg(vcpu->arch.eff_db[1], 1); > set_debugreg(vcpu->arch.eff_db[2], 2); > set_debugreg(vcpu->arch.eff_db[3], 3); > } > > > But what happens to dr6, I don't know. > That's done later, in vmx.c:vmx_vcpu_run(): if (vcpu->arch.switch_db_regs) set_debugreg(vcpu->arch.dr6, 6); Can you describe the failure? I'll try to construct a test case reproducer and work with Jan to fix it. -- error compiling committee.c: too many arguments to function From marketing at prehospitalar.com.br Sun Dec 20 17:45:46 2009 From: marketing at prehospitalar.com.br (Grupo Anjos APH) Date: Sun, 20 Dec 2009 17:45:46 GMT Subject: Serviço Aeromédico de Emergência em São Paulo **Grátis Uniforme** Message-ID: An HTML attachment was scrubbed... URL: From jan.kiszka at web.de Mon Dec 21 10:22:16 2009 From: jan.kiszka at web.de (Jan Kiszka) Date: Mon, 21 Dec 2009 11:22:16 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091218223230.GA1853@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> <20091218223230.GA1853@redhat.com> Message-ID: <4B2F4C58.8010303@web.de> Oleg Nesterov wrote: > On 12/18, Roland McGrath wrote: >>> Please find the trivial test-case below. It hangs, because >>> PTRACE_SINGLESTEP doesn't trigger the trap. >> 2.6.33-rc1 x86-64 works for me with either -m64 or -m32 version of that test. >> >>> (not sure this matters, but I did the testing under kvm) >> Apparently it does. You should hack some printks into do_debug() and see >> how kvm is differing from real hardware. (Actually you can probably do >> this with a notifier added by a module, not that you are shy about >> recompiling!) >> >> Probably kvm's emulation of the hardware behavior wrt the DR6 bits is not >> sufficiently faithful. Conceivably, kvm is being consistent with some >> older hardware and we have encoded assumptions that only newer hardware >> meets. But I'd guess it's just a plain kvm bug. > > OK, thanks. > > Hmm. Now I see how wrong I was when I said this code is "obviously wrong" ;) > > I'll add the debugging printk's and report the output. Sorry for delay, > can't do this today. Can't reproduce, runs fine here with with 2.6.33-rc1 as both host&guest and qemu-kvm latest git. Host uses kvm-intel. Can you specify your setup in more details? Which host kernel did you use, which qemu-kvm version? Are you on AMD or Intel? Any specific guest kernel config switch that may influence this? Jan -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 257 bytes Desc: OpenPGP digital signature URL: From ananth at in.ibm.com Mon Dec 21 13:48:37 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Mon, 21 Dec 2009 19:18:37 +0530 Subject: [PATCH 6/7] implement utrace-ptrace In-Reply-To: <20091218011140.GA29570@redhat.com> References: <20091218011140.GA29570@redhat.com> Message-ID: <20091221134837.GB12670@in.ibm.com> On Fri, Dec 18, 2009 at 02:11:40AM +0100, Oleg Nesterov wrote: > The patch adds the new file, kernel/ptrace-utrace.c, which contains > the new implementation of ptrace over utrace. > > This file is not compiled until we have CONFIG_UTRACE option, will be > added by the next "utrace core" patch. > > It's supposed to be an invisible implementation change, nothing should > change to userland when CONFIG_UTRACE is enabled. > > Signed-off-by: Roland McGrath > Signed-off-by: Oleg Nesterov > --- Oleg, ptrace/utrace performs better with the ptrace-tests [1] testsuite (1 failure vs. 3 with vanilla ptrace [1]). The gdb testsuite also has no regressions. In fact, the results on the gdb testsuite are identical. Ananth [1] http://sourceware.org/systemtap/wiki/utrace/tests [2] detach-stopped and stopped-attach-transparency are the additional failures. syscall-reset fails in both cases. From ananth at in.ibm.com Mon Dec 21 13:50:43 2009 From: ananth at in.ibm.com (Ananth N Mavinakayanahalli) Date: Mon, 21 Dec 2009 19:20:43 +0530 Subject: [PATCH 6/7] implement utrace-ptrace In-Reply-To: <20091221134837.GB12670@in.ibm.com> References: <20091218011140.GA29570@redhat.com> <20091221134837.GB12670@in.ibm.com> Message-ID: <20091221135043.GC12670@in.ibm.com> On Mon, Dec 21, 2009 at 07:18:37PM +0530, Ananth N Mavinakayanahalli wrote: > On Fri, Dec 18, 2009 at 02:11:40AM +0100, Oleg Nesterov wrote: > > The patch adds the new file, kernel/ptrace-utrace.c, which contains > > the new implementation of ptrace over utrace. > > > > This file is not compiled until we have CONFIG_UTRACE option, will be > > added by the next "utrace core" patch. > > > > It's supposed to be an invisible implementation change, nothing should > > change to userland when CONFIG_UTRACE is enabled. > > > > Signed-off-by: Roland McGrath > > Signed-off-by: Oleg Nesterov > > --- > > Oleg, > > ptrace/utrace performs better with the ptrace-tests [1] testsuite (1 failure > vs. 3 with vanilla ptrace [1]). The gdb testsuite also has no > regressions. In fact, the results on the gdb testsuite are identical. Forgot to mention the tests were on powerpc. From oleg at redhat.com Mon Dec 21 16:53:04 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Mon, 21 Dec 2009 17:53:04 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <4B2F4C58.8010303@web.de> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> <20091218223230.GA1853@redhat.com> <4B2F4C58.8010303@web.de> Message-ID: <20091221165304.GA5061@redhat.com> On 12/21, Jan Kiszka wrote: > > Oleg Nesterov wrote: > > > > Hmm. Now I see how wrong I was when I said this code is "obviously wrong" ;) Yes, it is easy to blame the code you don't understand. My apologies to all. > > I'll add the debugging printk's and report the output. Sorry for delay, > > can't do this today. > > Can't reproduce, runs fine here with with 2.6.33-rc1 as both host&guest > and qemu-kvm latest git. Host uses kvm-intel. Everything runs fine under 2.6.32 as a _host_ kernel. Previously I did the testing under 2.6.26.5-45.fc9. Sorry for noise, thanks all for your help. Oleg. From jan.kiszka at web.de Mon Dec 21 16:48:17 2009 From: jan.kiszka at web.de (Jan Kiszka) Date: Mon, 21 Dec 2009 17:48:17 +0100 Subject: x86: do_debug && PTRACE_SINGLESTEP broken by 08d68323d1f0c34452e614263b212ca556dae47f In-Reply-To: <20091221165304.GA5061@redhat.com> References: <20091218005650.GA20667@redhat.com> <20091218030601.GB16470@nowhere> <20091218172747.GA10924@redhat.com> <20091218200503.2CA0DF9A4@magilla.sf.frob.com> <20091218223230.GA1853@redhat.com> <4B2F4C58.8010303@web.de> <20091221165304.GA5061@redhat.com> Message-ID: <4B2FA6D1.20408@web.de> Oleg Nesterov wrote: > On 12/21, Jan Kiszka wrote: >> Oleg Nesterov wrote: >>> Hmm. Now I see how wrong I was when I said this code is "obviously wrong" ;) > > Yes, it is easy to blame the code you don't understand. > > My apologies to all. > >>> I'll add the debugging printk's and report the output. Sorry for delay, >>> can't do this today. >> Can't reproduce, runs fine here with with 2.6.33-rc1 as both host&guest >> and qemu-kvm latest git. Host uses kvm-intel. > > Everything runs fine under 2.6.32 as a _host_ kernel. Previously I did > the testing under 2.6.26.5-45.fc9. Makes sense: that kernel (most probably) predates any debug register virtualization in kvm. > > Sorry for noise, thanks all for your help. Never mind. Jan -------------- next part -------------- A non-text attachment was scrubbed... Name: signature.asc Type: application/pgp-signature Size: 257 bytes Desc: OpenPGP digital signature URL: From envoi at bdop89.info Mon Dec 21 16:59:02 2009 From: envoi at bdop89.info (Celine de Fizeo) Date: Mon, 21 Dec 2009 18:59:02 +0200 Subject: =?UTF-8?Q?Comparez_les_diff=C3=A9rents_prestataires.?= Message-ID: An HTML attachment was scrubbed... URL: From admin at ebuppies.com Mon Dec 21 22:43:23 2009 From: admin at ebuppies.com (ebuppies admin) Date: Mon, 21 Dec 2009 17:43:23 -0500 Subject: eBuppies.com - Offers New Online Dating Site for Black Urban Professionals Message-ID: December 18, 2009 Dear Friend, eBuppies.com (www.ebuppies.com ) is a new online dating site that is dedicated to providing singles from all over with the opportunity to connect with other buppy singles in their local area or anywhere of their choice. More and more buppy singles are going online to connect with others because going out week after week to nightclubs and bars can be tiresome, as well as expensive. eBuppies.com makes dating easy by hosting hundreds of profiles of different singles looking for love. Buppies can join on a monthly basis for less than they would probably pay for one night at a nightclub or bar. Buppies who are looking for love, romance or just friendship now have a unique resource that can help them discover their future soul mate: eBuppies.com. Although high technology drives eBuppies.com, the online dating site is simple and easy for buppies to navigate. Buppies can register, browse, search and contact other singles at no charge. There is also no charge for buppies to upload a photo with their profile. A control panel enables buppies to customize preferences based on their individual requirements. The control panel also blocks undesired contacts for buppies' convenience. The pricing for membership is quite cost effective especially for the average buppy. By January 31 2010 visitors can sign up for 1 Month and get 30 Days extra membership exclusively through our THIRTYPLUS promo code. For more information, visit www.ebuppies.com. About eBuppies.com: eBuppies.com is a new online dating service based in San Francisco. Its goal is to provide easy and affordable online dating to Black Urban Professionals by using state of the art chat systems, instant messaging, and forum technology to satisfy today's evolving online community demands. Terms of use Contact Info: Name: Mr. F. Jackson Address: 1230 Market Street, #252 City: San Francisco State: California Country: United States Zip: 94102 Web Address: www.ebuppies.com Phone: 510-575-4124 / / / / Site Statistics Special Offer! Members in Last Week: 1 Total Male eBuppies: 10 Total Female eBuppies: 15 Pictures in Last Week: 0 Members online: 0 News Women More Likely to Snoop Than Men Nov 24, 2009 In the new film, Little Black Book, Brittany Murphy's character engages in some high-tech snooping on her new boyfriend. Based... more Internet Dating More Successful than Thought Nov 24, 2009 Internet dating is proving a much more successful way to find long-term romance and friendship for thousands of people than... more All News Poll Success Stories A Sister's Story Sep 11, 2009 by Monique What initially started out as something to relieve a little boredom and to have some fun turned into one of... more All Stories Welcome to eBuppies.com See why eBuppies.com is the fastest growing Black Urban Professional relationship site on the web. Create your eBuppies.com profile to begin the exciting journey towards finding your match. Members online: 0 Don't stay alone, Join Now for Free Newest eBuppies kldixson systemsthinking Show full list Newest Profiles brotherX *Age:* 40 *Gender:* Man *Looking for:* Woman *Location:* Albany, California, United States No Pictures *Active wihin 1 week* View Profile kldixon *Age:* 40 *Gender:* Man *Looking for:* Woman *Location:* Oakland, California, United States No Pictures *Active wihin 1 week* View Profile Login | Privacy | Terms of Use | Services | FAQ's | Articles | Affiliate | Invite a Friend | Feedback

If you do not want to receive any more newsletters, http://ebuppies.com/emailserv/?p=unsubscribe&uid=3e306b7e73479a3071899d3733829ce7 To update your preferences and to unsubscribe visit http://ebuppies.com/emailserv/?p=preferences&uid=3e306b7e73479a3071899d3733829ce7 Forward a Message to Someone http://ebuppies.com/emailserv/?p=forward&uid=3e306b7e73479a3071899d3733829ce7&mid=20
CUBEMEDIALAB

1230 Market Street
Suite 252
San Francisco, California 94102
USA
Try digital design
with cubemedialab.com!
-- Powered by PHPlist, www.phplist.com -- From news at standalgarve.com Mon Dec 21 23:51:05 2009 From: news at standalgarve.com (Bidoloo.pt) Date: Mon, 21 Dec 2009 23:51:05 +0000 Subject: Leiloes completamente incriveis - IPHONE por =?iso-8859-1?b?gA==?=30, 97!!! Message-ID: <20091221235100.2E3264028A@server7.nortenet.pt> Caso n?o visualize correctamente este e-mail, por favor clique AQUI. NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Se pretender n?o receber mais estes emails clique AQUI. -------------- next part -------------- An HTML attachment was scrubbed... URL: From roland at redhat.com Tue Dec 22 01:11:30 2009 From: roland at redhat.com (Roland McGrath) Date: Mon, 21 Dec 2009 17:11:30 -0800 (PST) Subject: new Fedora 13 utrace kernel In-Reply-To: caiqian@redhat.com's message of Saturday, 19 December 2009 10:32:32 -0500 <1104922288.1959941261236752306.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <651708828.1959921261236317846.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1104922288.1959941261236752306.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091222011130.702C910274@magilla.sf.frob.com> > The utrace patch looks suspicious in utrace.h, which cause the compilation failure without CONFIG_UTRACE. I have confirmed that the git tree looks sane. > > +static inline void utrace_init_task(struct task_struct *child) > +{ > +} > +{ > +} Oops! That snafu got fixed on the main branch but I forgot to put the fix on the 2.6.32/utrace branch too. Fixed now. Thanks, Roland From newsletter at brinde-companhia.com Tue Dec 22 07:46:55 2009 From: newsletter at brinde-companhia.com (Brinde & Companhia) Date: Tue, 22 Dec 2009 08:46:55 +0100 Subject: Feliz Natal Message-ID: <6f2716db3fbc788bc400a9e6963c98a5@newsletter1.brinde-companhia.com> An HTML attachment was scrubbed... URL: From caiqian at redhat.com Tue Dec 22 10:37:32 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Tue, 22 Dec 2009 05:37:32 -0500 (EST) Subject: odd utrace testing results on s390x In-Reply-To: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> The following are testing results on s390x kernels build from the source, http://kojipkgs.fedoraproject.org/packages/kernel/2.6.32.2/14.fc13/src/kernel-2.6.32.2-14.fc13.src.rpm without and with CONFIG_UTRACE using the latest ptrace-utrace git tree. ptrace testsuite: looks like step-simple is starting to fail, and a different syscall number when syscall-from-clone failed. -- noutrace/n.log 2009-12-22 05:21:12.070623429 -0500 +++ utrace/utrace.log 2009-12-22 04:48:47.880634495 -0500 @@ -29,10 +29,10 @@ ./syscall-reset: Port this test to this machine! SKIP: syscall-reset PASS: reparent-zombie -PASS: step-simple +FAIL: step-simple SKIP: step-through-sigret PASS: stop-attach-then-wait -FAIL: detach-stopped +PASS: detach-stopped PASS: detach-stopped-rhel5 PASS: clone-multi-ptrace PASS: clone-ptrace @@ -43,27 +43,27 @@ PASS: waitpid-double-report PASS: o_tracevfork-parent PASS: stopped-detach-sleeping -FAIL: stopped-attach-transparency +PASS: stopped-attach-transparency SKIP: erestartsys-trap highmem-debugger: highmem-debugger.c:161: main: Assertion `got != 0' failed. -/bin/sh: line 5: 24278 Aborted ${dir}$tst +/bin/sh: line 5: 18363 Aborted ${dir}$tst FAIL: highmem-debugger PASS: sigint-before-syscall-exit unexpected syscall 0 syscall-from-clone: syscall-from-clone.c:246: main: Assertion `!"unexpected syscall"' failed. syscall-from-clone: syscall-from-clone.c:131: handler_fail: Assertion `0' failed. -/bin/sh: line 5: 24288 Aborted ${dir}$tst +/bin/sh: line 5: 18373 Aborted ${dir}$tst FAIL: syscall-from-clone -unexpected syscall 0x5ee9 +unexpected syscall 0 step-from-clone: step-from-clone.c:245: main: Assertion `!"unexpected syscall"' failed. step-from-clone: step-from-clone.c:130: handler_fail: Assertion `0' failed. -/bin/sh: line 5: 24295 Aborted ${dir}$tst +/bin/sh: line 5: 18380 Aborted ${dir}$tst FAIL: step-from-clone PASS: step-fork SKIP: erestartsys-trap-debugger SKIP: erestartsys-trap-32fails-debugger ======================================== -5 of 36 tests failed +4 of 36 tests failed GDB testsuite: it is failing much more with CONFIG_UTRACE. --- noutrace/gdb.sum 2009-12-22 04:40:30.900613255 -0500 +++ utrace/gdb.sum 2009-12-22 03:21:34.109226329 -0500 ... === gdb Summary === -# of expected passes 13657 -# of unexpected failures 367 -# of unexpected successes 2 -# of expected failures 40 -# of untested testcases 21 -# of unresolved testcases 7 -# of unsupported tests 55 +# of expected passes 5540 +# of unexpected failures 3735 +# of expected failures 38 +# of untested testcases 38 +# of unresolved testcases 113 +# of unsupported tests 66 Full logs can be found here. http://people.redhat.com/qcai/log/ Thanks, CAI Qian From oleg at redhat.com Tue Dec 22 12:59:30 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 22 Dec 2009 13:59:30 +0100 Subject: odd utrace testing results on s390x In-Reply-To: <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <20091222125930.GA7699@redhat.com> On 12/22, caiqian at redhat.com wrote: > > The following are testing results on s390x kernels build from the source, > > http://kojipkgs.fedoraproject.org/packages/kernel/2.6.32.2/14.fc13/src/kernel-2.6.32.2-14.fc13.src.rpm > > without and with CONFIG_UTRACE using the latest ptrace-utrace git tree. > > ptrace testsuite: looks like step-simple is starting to fail, Damn, my fault. I forgot to cc you when I sent the fix for s390 (attached below), and I forgot to remind you about this fix when we discussed the testing on s390. Could you please re-test with this patch applied? > and a different syscall number when syscall-from-clone failed. This is not clear to me, will take a look. Thanks! Oleg. ----------------------------------------------------------------------------- Untested, but hopefully trivial enough and should't change the compiled code. Nobody except ptrace itself should use task->ptrace or PT_PTRACED directly, change arch/s390/kernel/traps.c to use the helper. Signed-off-by: Oleg Nesterov Acked-by: Roland McGrath --- arch/s390/kernel/traps.c | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) --- V1/arch/s390/kernel/traps.c~S390_DONT_ABUSE_PT_PTRACED 2009-04-06 00:03:36.000000000 +0200 +++ V1/arch/s390/kernel/traps.c 2009-12-09 20:31:49.000000000 +0100 @@ -18,7 +18,7 @@ #include #include #include -#include +#include #include #include #include @@ -382,7 +382,7 @@ void __kprobes do_single_step(struct pt_ SIGTRAP) == NOTIFY_STOP){ return; } - if ((current->ptrace & PT_PTRACED) != 0) + if (tracehook_consider_fatal_signal(current, SIGTRAP)) force_sig(SIGTRAP, current); } @@ -483,7 +483,7 @@ static void illegal_op(struct pt_regs * if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) return; if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { - if (current->ptrace & PT_PTRACED) + if (tracehook_consider_fatal_signal(current, SIGTRAP)) force_sig(SIGTRAP, current); else signal = SIGILL; From oleg at redhat.com Tue Dec 22 13:06:07 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 22 Dec 2009 14:06:07 +0100 Subject: odd utrace testing results on s390x In-Reply-To: <20091222125930.GA7699@redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091222125930.GA7699@redhat.com> Message-ID: <20091222130607.GB7699@redhat.com> And of course, I forgot that rhel6 need this patch too. Roland, should I open bz and send this patch right now, or it is better to wait until I see the patches you sent in rhel6 tree? This patch is already in Linus's tree btw. On 12/22, Oleg Nesterov wrote: > > On 12/22, caiqian at redhat.com wrote: > > > > The following are testing results on s390x kernels build from the source, > > > > http://kojipkgs.fedoraproject.org/packages/kernel/2.6.32.2/14.fc13/src/kernel-2.6.32.2-14.fc13.src.rpm > > > > without and with CONFIG_UTRACE using the latest ptrace-utrace git tree. > > > > ptrace testsuite: looks like step-simple is starting to fail, > > Damn, my fault. I forgot to cc you when I sent the fix for s390 (attached > below), and I forgot to remind you about this fix when we discussed the > testing on s390. > > Could you please re-test with this patch applied? > > > and a different syscall number when syscall-from-clone failed. > > This is not clear to me, will take a look. > > Thanks! > > Oleg. > > ----------------------------------------------------------------------------- > Untested, but hopefully trivial enough and should't change the > compiled code. > > Nobody except ptrace itself should use task->ptrace or PT_PTRACED > directly, change arch/s390/kernel/traps.c to use the helper. > > Signed-off-by: Oleg Nesterov > Acked-by: Roland McGrath > --- > > arch/s390/kernel/traps.c | 6 +++--- > 1 file changed, 3 insertions(+), 3 deletions(-) > > --- V1/arch/s390/kernel/traps.c~S390_DONT_ABUSE_PT_PTRACED 2009-04-06 00:03:36.000000000 +0200 > +++ V1/arch/s390/kernel/traps.c 2009-12-09 20:31:49.000000000 +0100 > @@ -18,7 +18,7 @@ > #include > #include > #include > -#include > +#include > #include > #include > #include > @@ -382,7 +382,7 @@ void __kprobes do_single_step(struct pt_ > SIGTRAP) == NOTIFY_STOP){ > return; > } > - if ((current->ptrace & PT_PTRACED) != 0) > + if (tracehook_consider_fatal_signal(current, SIGTRAP)) > force_sig(SIGTRAP, current); > } > > @@ -483,7 +483,7 @@ static void illegal_op(struct pt_regs * > if (get_user(*((__u16 *) opcode), (__u16 __user *) location)) > return; > if (*((__u16 *) opcode) == S390_BREAKPOINT_U16) { > - if (current->ptrace & PT_PTRACED) > + if (tracehook_consider_fatal_signal(current, SIGTRAP)) > force_sig(SIGTRAP, current); > else > signal = SIGILL; From seats at hotspring.nl Tue Dec 22 14:51:29 2009 From: seats at hotspring.nl (Feltner Grudzinski) Date: Tue, 22 Dec 2009 15:51:29 +0100 Subject: No subject Message-ID: <4B30DC72.8050201@hotspring.nl> -------------- next part -------------- A non-text attachment was scrubbed... Name: sparkling.jpg Type: image/jpeg Size: 18008 bytes Desc: not available URL: From oleg at redhat.com Tue Dec 22 16:22:22 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 22 Dec 2009 17:22:22 +0100 Subject: odd utrace testing results on s390x In-Reply-To: <20091222125930.GA7699@redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091222125930.GA7699@redhat.com> Message-ID: <20091222162222.GA16761@redhat.com> On 12/22, Oleg Nesterov wrote: > > On 12/22, caiqian at redhat.com wrote: > > > > and a different syscall number when syscall-from-clone failed. > > This is not clear to me, will take a look. Should I say I know nothing about s390 and can't read its asm? First of all, I think syscall-from-clone is wrong on s390 and needs a fix, #elif defined __s390__ # define REGISTER_CALLNO offsetof (struct user_regs_struct, orig_gpr2) # define REGISTER_RETVAL offsetof (struct user_regs_struct, gprs[2]) This doesn't look right. I did a simple test-case (below), and with or without utrace it prints syscall=1234 ret=6 <----- __NR_close syscall=1234 ret=-9 <----- -EBADF, this is correct Apparently, 1234 is the argument for close(1234). So: it is not clear to me how to get "callno" on SYSCALL_EXIT, and I don't know whether it is OK or not that syscall-from-clone sees different ->orig_gpr2 after return from fork() on s390 -unexpected syscall 0x5ee9 <---- without utrace +unexpected syscall 0 <---- with utrace syscall_get_nr() returns regs->svcnr, but there is no "svcnr" in user_regs_struct on s390. Still investigating... Oleg. #include #include #include #include #include #include #include #include #include #include #ifdef __s390__ #define REGISTER_CALLNO offsetof(struct user_regs_struct, orig_gpr2) #define REGISTER_RETVAL offsetof(struct user_regs_struct, gprs[2]) #else #define REGISTER_CALLNO offsetof(struct user_regs_struct, orig_rax) #define REGISTER_RETVAL offsetof(struct user_regs_struct, rax) #endif int main(void) { int pid, status, i; long scn, ret; pid = fork(); if (!pid) { assert(ptrace(PTRACE_TRACEME, 0, 0, 0) == 0); kill(getpid(), SIGUSR1); close(1234); return 0x66; } assert(pid == wait(&status)); assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGUSR1); assert(ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_TRACESYSGOOD) == 0); for (i = 0; i < 2; ++i) { ptrace(PTRACE_SYSCALL, pid, 0,0); assert(pid == wait(&status)); assert(status == 0x857f); scn = ptrace(PTRACE_PEEKUSER, pid, REGISTER_CALLNO, NULL); ret = ptrace(PTRACE_PEEKUSER, pid, REGISTER_RETVAL, NULL); printf("syscall=%ld ret=%ld\n", scn, ret); } kill(pid, SIGKILL); return 0; } From oleg at redhat.com Tue Dec 22 18:46:18 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Tue, 22 Dec 2009 19:46:18 +0100 Subject: odd utrace testing results on s390x In-Reply-To: <20091222162222.GA16761@redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091222125930.GA7699@redhat.com> <20091222162222.GA16761@redhat.com> Message-ID: <20091222184618.GA20594@redhat.com> On 12/22, Oleg Nesterov wrote: > > On 12/22, Oleg Nesterov wrote: > > > and I don't know whether it is OK or not that syscall-from-clone > sees different ->orig_gpr2 after return from fork() on s390 > > -unexpected syscall 0x5ee9 <---- without utrace > +unexpected syscall 0 <---- with utrace AAAAAARGH. I misread the diff you reported, the difference above has nothing to do with syscall-from-clone! This is the output form the next test-case, step-from-clone. I think, everything is (almost) clear now, I'll try to summarize. Both syscall-from-clone and step-from-clone fail, with or without utrace. I think they both need the fix, REGISTER_CALLNO and REGISTER_RETVAL are wrong on s390. (I also tested my trivial test-case on rhel5 and it prints the same). Now, the difference above _can_ be explained because utrace kernel lacks ca633fd006486ed2c2d3b542283067aab61e6dc8 (Cai, I attached this patch in the first reply), or we have issues with utrace on s390. without utrace: -unexpected syscall 0x5ee9 this is in fact grandchild's pid == fork's retval because REGISTER_CALLNO is wrong with utrace: +unexpected syscall 0 well, we are reading orig_gpr2 which is wrong anyway, but I am worried because cat /proc/child/syscall reports -1 0x3ffffff21d8 0x200000f1e52 _Perhaps_ this all will be fixed by ca633fd006486ed2c2d3b542283067aab61e6dc8, but I am not sure. This trap was (I think) generated by ptrace_report_signal(), it may happen that so s390 doesn't preserve some registers when we dequeue SIGTRAP after do_notify_resume()->utrace_stop() and call utrace_stop() again. Oh. I am still trying to parse arch/s390/kernel/entry.S to understand how can we fix these test-cases. I think I need the help, will continue tomorrow. Oleg. From roland at redhat.com Tue Dec 22 19:03:50 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 22 Dec 2009 11:03:50 -0800 (PST) Subject: odd utrace testing results on s390x In-Reply-To: Oleg Nesterov's message of Tuesday, 22 December 2009 13:59:30 +0100 <20091222125930.GA7699@redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091222125930.GA7699@redhat.com> Message-ID: <20091222190350.9B569105F7@magilla.sf.frob.com> > Damn, my fault. I forgot to cc you when I sent the fix for s390 (attached > below), and I forgot to remind you about this fix when we discussed the > testing on s390. That change is upstream for 2.6.33 now. I'll cherry-picked it into the 2.6.32/tracehook branch so it will be in the backport patchset too. Thanks, Roland From roland at redhat.com Tue Dec 22 19:10:26 2009 From: roland at redhat.com (Roland McGrath) Date: Tue, 22 Dec 2009 11:10:26 -0800 (PST) Subject: odd utrace testing results on s390x In-Reply-To: Oleg Nesterov's message of Tuesday, 22 December 2009 19:46:18 +0100 <20091222184618.GA20594@redhat.com> References: <1503844142.2061111261478093776.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <1257887498.2061171261478252049.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> <20091222125930.GA7699@redhat.com> <20091222162222.GA16761@redhat.com> <20091222184618.GA20594@redhat.com> Message-ID: <20091222191026.C48FD105F7@magilla.sf.frob.com> > Oh. I am still trying to parse arch/s390/kernel/entry.S to understand > how can we fix these test-cases. I think I need the help, will continue > tomorrow. Martin Schwidefsky is the s390 arch maintainer. He is friendly and helpful. You can ask him for help both with understanding the intended s390 behavior before, and with understanding the code paths. He won't expect any of us to grok s390 assembly. :-) Thanks, Roland From erg at pnyu.com Tue Dec 22 20:40:25 2009 From: erg at pnyu.com (=?GB2312?B?16rQ6MfzyMvUsQ==?=) Date: Wed, 23 Dec 2009 04:40:25 +0800 Subject: =?GB2312?B?YzY6dXRyYWNlLWRldmVsu6rOqs/uxL+53MDtuaS+39PrxKOw5dTL08M=?= Message-ID: <200912222040.nBMKeKlO012813@mx1.redhat.com> utrace-devel????????????? ?????2009?12?25-26? ?? ?????2009?12?30-31? ?? ? ??2800?/?????????????????? ????????????????????????????????????????? ????????????+????+????+???? ?????020-80560638?020-85917945 ???????????????chinammc21 at 126.com??? ---------------------------------------------------------------------------------- ????????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ??????????????????????????? ????????????????????????????????????????? ???????????????????????????????????????? ?????????????????????????????? ???????????????????????????????????????? ???????????????????????????????? -------------------------------------------------------------------------------- ????? 1?????????????????? 2???????????? 3????????? 4????????? 5?????????????? 6??????? -------------------------------------------------------------------------------- ????: ???????????????????????EDP?????????????????? ??????????????????????????????????????????? ????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????IBM???????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ??????????????????????????????????????????? ?????? ????????? ??????????? ?????????? ??????????? ??????????? ???????????????????? ????????????? ?Project2007????? ??????? ??????????LG????????????????????????????????? ???????????????????????????????????????????? ???????????????????NISSAN?????????????????????? ???????????????????????????????????????????? ??????????SMC????????????????????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ???????????????????????????????????????????? ????????????????????????????????????????????? ?????????? ????? ?????????????????????????????????????? ????????????????????? ????????????????????????? ????4:3:2:1????? 4?40%??????????? 3?30%??????????? 2?20%?????? 1?10%?????? ====================================================================================== ???? ?????????? 1??????? ???? ?????? ??????? ?????????? 2????????? ?????9??? ?????5??? ????????????? ?????????????? 1????? ?????? ??????????? ??????????????? ?????? 2??????? ?????? ??????? ??????? ??????? ??????? ??????? ???????? ??????? ????????? ??????????? ???????? 3????????? ???? ????? ?????? ????? 4?????? ???? ?????? ?????? ?????????????? ????????? ????????? ??????????? ???????? ?????????????? 1????????WBS? ?????? WBS????? WBS????????? 2??????? 3????? 4????????????? 5??????? ??? ????? 6????????? ???????? ?????? ????? ???? ????? SWOT??? ?????? ?????? ???????? ?????? ????????????? 7????????? ???????? ??????? ??????? ????????? ??????? ????????? ????????? ?????? ?????? ??????? ??????????? ??????????? ????????????? ?????????? WBS???? ????????? ????????? ????????? PERT???????? ???? ????????????????? 1??????? 2?????????? ??????? ???? ????? ?????? ??????? 3??????? ????????????? ??????????? ?????????? ?????????? ??????????? ?????? ??? ??? PDCA?? ?????????????? 1?????? 2????? ?????? ????????? 3????? ??????????? ????????? ????????????? 1?????????? 2?????????PBC 3???????? 4???????? ???????????????? ?????? ????PKI???? ????PBC???? ???????????? 1???????????? 2???????????? 3??????????????? ????????????????? ?????????Project2007???? ????????????????Project2007??? ???????? ============================================================================= ????????????????????????020-62351156? ???????? ??? ? ? ? ??_______________________________________________________ ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638??? From envoi at bdop89.info Tue Dec 22 18:55:31 2009 From: envoi at bdop89.info (DHL Epost) Date: Tue, 22 Dec 2009 20:55:31 +0200 Subject: DHL Epost - envoyer votre courrier depuis votre ordinateur Message-ID: An HTML attachment was scrubbed... URL: From akpm at linux-foundation.org Tue Dec 22 21:58:09 2009 From: akpm at linux-foundation.org (Andrew Morton) Date: Tue, 22 Dec 2009 13:58:09 -0800 Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: <20091218011116.GA29534@redhat.com> References: <20091218011116.GA29534@redhat.com> Message-ID: <20091222135809.1ab10869.akpm@linux-foundation.org> On Fri, 18 Dec 2009 02:11:16 +0100 Oleg Nesterov wrote: > Hello. > > This is the new iteration of Roland's utrace patch, this time > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. > So... should we merge this? I'll confess that I've rather forgotten why we might want this. > It allows for multiple separate tracing engines to work > in parallel without interfering with each other. Higher-level tracing > facilities can be implemented as loadable kernel modules using this layer. That's a bit brief. Do you have a nicer sales brochure? What are these "separate tracing engines" and what is their merge status and why would we want any of them, for what purpose? etc. IOW: give us a reason! From newsletter at usbportugal.com Tue Dec 22 23:56:10 2009 From: newsletter at usbportugal.com (USBPortugal.com) Date: Wed, 23 Dec 2009 00:56:10 +0100 Subject: Feliz Natal Message-ID: An HTML attachment was scrubbed... URL: From iaf.xui at gmail.com Tue Dec 22 14:07:47 2009 From: iaf.xui at gmail.com (iaf.xui at gmail.com) Date: Tue, 22 Dec 2009 22:07:47 +0800 Subject: =?GB2312?B?vKjQp7+8usujrL6/vrm/vLW5wcvLraO/?= Message-ID: <200912230526.nBN5Q4lE032516@mx1.redhat.com> ================================================================================ ??????????????? ================================================================================ ?.?.?.?.?? 2009?12?17-19? ?? 2009?12?25-27? ?? ================================================================================ ?*?*?*?: ?????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????? ????????????????? ?*?*?*?? -???????????????????????????? -???????????????????? -????????????????????? -??????????????????????????? -????KPI?????????? -??????????????????????? ?*?*?*?? ????????????????????????????? ?*?*?*???????????????????????? ================================================================================= ?*?*?*?: ?????????12?17? ?? / 12?25? ??? ???????????? 1???????????? 2????????????????????? 3?????????????????? 4??????????? ???????????????? 1???????????? 2???????? 3???????? 4???????????? 5?????????????????????????? 6?????????? ??????????? ???? 1???????????? 2????????? 3???????????? 4????????? 5??????????????????? ????? 1????????????? 2?????????? 3??????????????????? ???????? 1?????????? 2???????? 3???????? ???????? ??????? 1?????? 2?????? 3?????? ???????? 1???????????? 2???????? 3??????????? ???????????????? 1?????????????????? 2????????????????? 3??????????????? 4????????????????????????? ???????????? 1?????????????? 2?????????????????? ???????12?18-19? ?? / 12?26-27? ??? ????KPI???????????????? 1?????????????????? ?? ??????????????????? ?? ??????????? ?? ??????????? ?? ???????????? ?? ???????????? ?? KPI??????????? 2????????????????????? ?? ???????????? ?? ??????????? ?? ?????????????? 3????????KPI??? ??KPI?????????? 1????????? 2?KPI?????????????? ?? ???????????????????? ?? ????????????????????? ?? ???????????????????? 3?KPI??????????KPI????????????????????????? ???????????? ????KPI???????? ?? ???????KPI????????????????????????????? ??????????????KPI??????? 1???????????????????????KPI??????????????? ?? 2?????????????? 3?????????????? 4?????????? ??????? 1????????????????????????????? 2????????????????????????? 3???????????????????????????????????????? ?????? 4??????????????? 5???????????????????????????????? ?????????????????? 1????????????? 2??????????? 3????????????????????KPI????????? ??????KPI ?? KPI??????????????????????KPI????????????? ????kpi???????????????????? ?? ?????????????KPI???????? 1?????KpI??????????????? 2??????2????? 3?????????KPI???3?????? 4???KPI?????????????????????????????????? ????????? ?? ????????????????????????????KPI?????KPI? 1????????KPI 2?KPI????????????? 3?KPI???????????? 4???????KPI??????? ????????KPI????? ???????????????????????????????????????? ???????? 1????????? 2????????????? 3?????????????????????? 4?????????????????????KPI?????? ????????? ??????????????????????????????????????? ?????????????????? 1????????????? 2????????? 3?????????????? 4?????KPI????????????? ????????? ?? ?????????????????????????????????????? ?? ?????????????????????????????????????? 1?KPI????????? 2?????????????? 3????????????????? ???KPI????? ?? ????????????????????????????KPI???????? ??? 1???????????????????????????? 2???????????????? 3??????????????????????? 4?????????????? ??????????????????? ?? ??KPI???????????????????KPI?????????????? ?? 1????????????????????? 2??????? 3????????????? 4??????????? ================================================================================ ????? ???: -?????? -???????????????? -?????? -MBA??????? ???????-??????????????????????????????? ????????????????91???????????????? ??????? ???????????????????????100?????????93?????? ???????????????PTT?? ?????????????????????? ???????????2005?2006?2007?????????????????????? ????????????????????????????? ??????????? ????????/????? ??????????????????????????????????????? ????????????????????????????????????????? ????? ????????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????? ??: -??????????????? -?????? -???????????? ??????????????????????????????????????? ????????????????????????????????????????? ??????????????????????????????????????. ????????????????????????????????????????? ?????????KPI??????????????BSC??????????????? ????????????????? ?? ?????????????????????????????????????TCL ????????????????????????????????????????? ???????????????? ??????????????? ????????? ???????????????????????? ????????????????? ????????????????????? ????????? ================================================================================ ????? 3?800 ?/?????.??????????????? ------------------------------------------ M-M-C ?.?.?.? ????????????????????? ???????????????????? ???????????????????? ? ??chinaipo@???.com ================================================================================ From uygi at cvoq.com Wed Dec 23 16:08:02 2009 From: uygi at cvoq.com (=?GB2312?B?xeDRtQ==?=) Date: Thu, 24 Dec 2009 00:08:02 +0800 Subject: =?GB2312?B?YTY6dXRyYWNlLWRldmVsyfqy+rzGu67T687vwc+/2NbG?= Message-ID: <200912231608.nBNG7xr3031134@mx2.redhat.com> utrace-devel?????????????????? 2010??1??14-15?? [????] 2010??1??16-17?? [????] ?????????????????????????????????????????????????????????????????????????????????????????????? ??????2600??/???????????????????????????????????????? ???????????????????????????????????????????????? ============================================================================== ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? ???????????????????????????????????????????? =============================================================================== ??????????????????????????????????????????????????,??????????????????????????????,???????????????????? ????????.),????????(PMC)????????????????????????????????????.???????????????????????????????????????? ????????????????????????????????????????????????????????????????.???????????????????????????????????? ??????:????????????????????????????????????(??????????????????????)????????????????????????,?????????? ???????????X???????????? ================================================================================ ????????????60/40??????????(????60%,????40%)??????????/??????????????????/???????????????????????????? ?????????????????????????????????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????????????????????,??????????????????.???? ??????????????????,????????????. ??????????????????????????????????????????????????/?????????????????? ?????????????????????????????????? ================================================================================= ????????????????????????,??????????????????+??????????????????+?????????? ?????????? ????????????MBA,??????????????????????????????????????(AMA)????????????????????????/???????? /????????/????????EMBA????????????????..?????r?????A???s?@????2004/2005/2006?????????????????????????? ????????????????????????????????????????.??????????????????????????????,????????????????????/?????????? ??. ????????????????????????????????????????/??????4524??????????(??2006??)???????????????????????????? ????????????.??????????????????????????????/?????????????????????????????????r?????A?????????????????? ??2004/2005/2006????????????????????????????/?????????F??????????????(????/JIT-????/????????/??????. ????????????????,????????????????,??????????????,??????????????????????,????????????,?????????????????? ??????????????????.????????????????????????????????????????????????????????????????????. ??????????????????????????????????????,????????????????????????????????????????????????/????????????.?? ????????????????????????????????????????????????????????????????????????????.????????.??????????.?????? ????????.??????????????????/??????????.??????(MULTEK)/ ??????????Jabil??.?????????????????????????????? ???????????????? ?????????F.?????????? ============================================================================== ???????? ?????? ?N??????/???b????/???????????????????? ??.???b????/??????????????????---?????????????????? ??.???b????/???????????????????? ?? ?????????????????b/???????????????? ??.???b????/????????????????----??????????????????????/????????--???? 4 .??????????????????????????- ?? ????????????VS??????????VS???????????????? ?? ????????????????/????????/??????????????????/?????????????? ?? ????????????????????????????????(????)-----?????????????? ?? ????????????/?????????????????????????????????? 5.?????????????????????????????????????????? ?? ?N???????????D?D?????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? 6.???????????????????????????D?D????????????????????????(push)????????????????????(pull)???????????? ?? ?????????????I?????Y??.??????????Schneider?????????????????? ?? ????????????????????????????????-----????????????/????/???????? ?? ?????????????????????????????????????????? ?? ???????????????????????????????????? ?????? ????????????----??????/???????????????????? 1.??????????????????????---????/?????????????????????? ?? ??????????????????????????????????????- ?? ???????????????????????????????????????? ?? ??????????????????????????????????????????/???????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ?????????????I?????????????????????????????????????????????????????????????????? ?? ???????????????I?????Y??????????ultek???b???????????????????? ?? ??????(????????)ERP??SAP/R3?????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ?????????????I???????I??????(push)???????????????? ?? ??????????????????????????(pull)????????????????????????????????- ?? ????????????????????????------?????????????????????? ?? ????????????????????????????/???????????????????????? ?? ??????????????????????????/????????????????????/????????????????????/???????????????????????????? ?? ????????????????????????????????????/????????/??????????????????/?????????????????????????????? 2.???b????????????(????)????---?????????????? ?? ??????/??????????????(JIT)???????????????????? ?? ??????????????(JIT)???????????????????? ?? ??????????BOSCH?????????????????????????????????????????? ?? ??????????BOSCH???????????????????????????????????????????? ?? ?????????????I???????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ??????????????????????????(JIT)?????????? ?? ???????????????????????? ?? ????????IE???????????????????????????? ?? ?????????????????????????????????????????? ?? ?????????????????????????????????????????????????? ?? ??????????????---?????????????????????? ?? ???????????????????????????????? ?? ????PE/IE?????????????? ?? ??????????/????????????????---?????? ------?????????????????????????? ?????? ???????????????? 1.???????????????? ?? ?????????????????????????????????????????????? ?? ???????????????????????????????????????????????????? 2.??/???????????????????????????????????? ?? ???????????????????????????????????????? ?? ???????????????????????????????????????? 3.?????????????????????? 4.??????????????????????---????????/???????????? ?? ??????????????2007/04???????????????????????? ?? ??????????????????-----?????????????????? ?? ??????????????????------?????????? 5.??????????????????????????????---- ?? ??/??????????????????????????????????--????????????????????/???????????????????????????? ?? ?????????????????? 6.???????????????? 7. ????????????????????------????/????/???? ?? ???????????????????? ?? ??????????????????????????????????????????---?????????????? ?? ????????LED????????????????????????????---???????? 8. ????????????????????????--???????????????????????? 9. ??????????????????--???????????????????????? 10.????????????????????????????/????????????????????????--------???????? 11.????????????????????????????????/???C????????????--------???????? ????????????????????????????????-----??????(OEM)/??????(ODM) 1.??????????????????????----??????????????????(??????????????????) ?? ??????????????????MRP??????????(????)???????? ?? ??????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????????? ?? ????????????????????????(????????)ERP??SAP/R3???????????????????????????????????? ?? ??????????????????ERP-???????????????????????????????????? ?? ???????????Y?????????????????????????? ?? ???????????????I?????Y?????????????????????????D?D???????? ?? ?????????????????I???IERP-ORACLE????????????/?????????????????? ??.???????????????????????? ?? ?????????????? ????????????????--?D?D?????????Y?????????????????????????? ?? ??????????????????????????/?????????Y???????????????????? ?? ??????????????????????/????????????????--?????????????? ?? ????/TTi/??????????????/????????????????????/???????????????? 3.????????????????(????)???????? ?? ????????---???????????????????? ?? ?????????????????????????????????????????????????????????????????????? ?? ??????????????????????????????/?????????????? ?? ??????????????????????????????????????????????????????-- ?? ??????????????/?????? ?? ?????????????????????? ?? ???????????????????????????????????? ?? ??????????BOSCH????????????????????????/???????????? ?? ABB/AREVA???????????????????????????????? ?? ?????????????????????????????????????????????????????????????? ?? ?????????????????????????????????????????????????????????? ?? ??????????????????????????/????/?????????????????????????? ?? ??????JIT???????????????? ?? ????????????????????????????????????Milk-Run?????????? ?? ??????????JIT??????---????????????????????/????/????/???? ?? ???????????????????????????????????????????? ?? ????????Normal Order/ CONSIGNMENT/VMI/JIT/Buffer Control???????????? ?? ????????????????VMI??----???????????????????????? ?? ??????????VMI?????????? ?? ??????????????(????)??????????VMI?????????????????? ?? ????????????????????????VMI ???????????????????? ?? ??????????????????????--????????????????/???????????? ?? ?????????????????? ?? ???????????????????????????????????????????????????? ?? ??????????ERP-ORACLE????SCP?????????????????????? ?? ????????????????????????????????????(EDI)???????? 4.???????? ?? ???????????????????? ?? ?????????????????? ?? ????????????????????????????????????????????????????????????????????----?????????????? ?? -????????????????????MTO /ROP ????????/??????????MOQ???????????????? ?? ???????????????????????????????????????????????????????? ?? ???????????????????????????????????????????? ?? ??????????????????????????????/??????/?????????? ?? ????/?????????????????????????????? ?? ?????????????????????????????? 5.?????????????????????????????? ?? ????:?????????????????? ?? ????/????????,??????????????????????????????- ?? ????????????????--????????/????????/???????? ?? ????/?????????????? ------------------------------------------------------------------------------- ??PMC??????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ???? ?????? ?????? ?????? ???? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From oleg at redhat.com Wed Dec 23 17:42:32 2009 From: oleg at redhat.com (Oleg Nesterov) Date: Wed, 23 Dec 2009 18:42:32 +0100 Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: <20091222135809.1ab10869.akpm@linux-foundation.org> References: <20091218011116.GA29534@redhat.com> <20091222135809.1ab10869.akpm@linux-foundation.org> Message-ID: <20091223174232.GA14993@redhat.com> On 12/22, Andrew Morton wrote: > > On Fri, 18 Dec 2009 02:11:16 +0100 > Oleg Nesterov wrote: > > > It allows for multiple separate tracing engines to work > > in parallel without interfering with each other. Higher-level tracing > > facilities can be implemented as loadable kernel modules using this layer. > > That's a bit brief. Do you have a nicer sales brochure? What are > these "separate tracing engines" and what is their merge status and why > would we want any of them, for what purpose? etc. > > IOW: give us a reason! First of all, utrace makes other things possible. gdbstub, nondestructive core dump, uprobes, kmview, hopefully more. I didn't look at these projects closely, perhaps other people can tell more. As for their merge status, until utrace itself is merged it is very hard to develop them out of tree. To me, even seccomp is the good example why utrace is useful. seccomp is simple, but it needs hooks in arch/ hot pathes. Contrary, utrace-based implementation is more flexible, simple, and it is completely "hidden" behind utrace. In my opinion, ptrace-utrace is another example. Once CONFIG_UTRACE goes away, we can remove almost all ptrace-related code from core kernel (and kill task_struct->ptrace/etc members). ftrace/etc is excellent in many ways, but even if we need the simple "passive" tracing it is not enough sometimes. And we have nothing else except ptrace currently. But ptrace is so horrible and unfixeable, and it has so many limitations. In fact, even the simple things like stop/ continue this thread/process are not trivial using ptrace, gdb/strace have to do a lot of hacks to overcome ptrace's limitations, and some of these hacks falls into "mostly works, but that is all" category. Of course, I can't promise we will have the new gdb which explores utrace facilities soon, but I think at leat utrace gives a chance. Well. I had a lot of technical discussions with Roland about utrace, but I never asked him why he created this thing ;) To me, utrace looks like vfs. Currently we have the single and very poor "filesystem", ptrace. Until we add the appropriate layer, we can't expect the further improvements is this area. Oleg. From roland at redhat.com Wed Dec 23 19:33:13 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Dec 2009 11:33:13 -0800 (PST) Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: Oleg Nesterov's message of Wednesday, 23 December 2009 18:42:32 +0100 <20091223174232.GA14993@redhat.com> References: <20091218011116.GA29534@redhat.com> <20091222135809.1ab10869.akpm@linux-foundation.org> <20091223174232.GA14993@redhat.com> Message-ID: <20091223193313.1B89E16DB@magilla.sf.frob.com> > Well. I had a lot of technical discussions with Roland about utrace, > but I never asked him why he created this thing ;) To me, utrace > looks like vfs. Currently we have the single and very poor "filesystem", > ptrace. Until we add the appropriate layer, we can't expect the > further improvements is this area. I think that is an excellent analogy, and it's one I've used before. Oleg and I have had our hands pretty full just with the infrastructure layer and with ptrace. Having this layer in the kernel is what makes it tractable for a lot of other people to collaborate on new features in this space, and that's what we want to enable and accelerate. Some of those on the CC list have worked and are working on such things, and I hope they will pipe up about those. Given the date, I suspect we might not see much from anybody on this (or anything) until January. Myself, I expect to be largely offline for the rest of the year. As Oleg mentioned, I have a cleanup/reimplementation of seccomp using utrace. That is quite a trivial use--it demonstrates how easy the utrace API makes it to do things like that, in contrast to previous solutions with arch-specific assembly hacking and so forth. I can dust that patch off and post it if anybody cares. Some other features based on utrace have been floating around for some time, posted here before. Those include uprobes, kmview, and the gdb stub. I don't which of those are quite ready for merging, but honing and polishing them gets quite a lot more doable with utrace in the tree instead of out. Thanks, Roland From andi at firstfloor.org Wed Dec 23 19:47:12 2009 From: andi at firstfloor.org (Andi Kleen) Date: Wed, 23 Dec 2009 20:47:12 +0100 Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: <20091223193313.1B89E16DB@magilla.sf.frob.com> References: <20091218011116.GA29534@redhat.com> <20091222135809.1ab10869.akpm@linux-foundation.org> <20091223174232.GA14993@redhat.com> <20091223193313.1B89E16DB@magilla.sf.frob.com> Message-ID: <20091223194712.GO20539@basil.fritz.box> > As Oleg mentioned, I have a cleanup/reimplementation of seccomp using > utrace. That is quite a trivial use--it demonstrates how easy the > utrace API makes it to do things like that, in contrast to previous > solutions with arch-specific assembly hacking and so forth. I can > dust that patch off and post it if anybody cares. Do you have an estimate or better numbers how the overhead of seccomp-over-utrace compares to the current in-tree seccomp? -Andi -- ak at linux.intel.com -- Speaking for myself only. From roland at redhat.com Wed Dec 23 19:55:32 2009 From: roland at redhat.com (Roland McGrath) Date: Wed, 23 Dec 2009 11:55:32 -0800 (PST) Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: Andi Kleen's message of Wednesday, 23 December 2009 20:47:12 +0100 <20091223194712.GO20539@basil.fritz.box> References: <20091218011116.GA29534@redhat.com> <20091222135809.1ab10869.akpm@linux-foundation.org> <20091223174232.GA14993@redhat.com> <20091223193313.1B89E16DB@magilla.sf.frob.com> <20091223194712.GO20539@basil.fritz.box> Message-ID: <20091223195532.8E65316DB@magilla.sf.frob.com> > Do you have an estimate or better numbers how the overhead of > seccomp-over-utrace compares to the current in-tree seccomp? I never measured it. I would estimate that any difference one way or another is in the noise. The point of seccomp is to run a process that almost never makes any system calls. The only effects of utrace for that use are on the system call path itself, and the essential effects there (i.e. taking the tracing path vs the hot path) are the same as what the old seccomp implementation does. If you have some example uses of seccomp or something that can serve as a benchmark for it, I would be glad to measure the difference. Thanks, Roland From amleto.ricardo at gmail.com Wed Dec 23 22:07:11 2009 From: amleto.ricardo at gmail.com (Amleto) Date: Wed, 23 Dec 2009 20:07:11 -0200 Subject: C a s a p r =?ISO-8859-1?Q?=F3?= p r i a sem entrada s/juros =?ISO-8859-1?Q?N=E3o?= e consorcio , conheca a AFTB Message-ID: <20091223220619.B30CEED3F5@mail> An HTML attachment was scrubbed... URL: From caiqian at redhat.com Thu Dec 24 08:03:49 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Thu, 24 Dec 2009 03:03:49 -0500 (EST) Subject: odd utrace testing results on s390x In-Reply-To: <1251463927.2160561261641707404.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <427623802.2160621261641829472.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > Could you please re-test with this patch applied? It turned out that this patch did not make much difference. the step-simple is still failing with the patch applied. It could be reproduced a few times after a fresh reboot. The test exited with 1 here, /* Known bug in 2.6.28-rc7 + utrace patch: * child was left to run freely, and exited * Deterministic (happens even with NUM_SINGLESTEPS = 1) */ if (WIFEXITED (status)) { VERBOSE("PTRACE_SINGLESTEP did not stop (step #%d)\n", i+1); assert (WEXITSTATUS (status) == 42); exit (1); } Here was the strace output when failure. # strace ./step-simple execve("./step-simple", ["./step-simple"], [/* 28 vars */]) = 0 brk(0) = 0x80003000 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x20000027000 access("/etc/ld.so.preload", R_OK) = -1 ENOENT (No such file or directory) open("/etc/ld.so.cache", O_RDONLY) = 3 fstat(3, {st_mode=S_IFREG|0644, st_size=44711, ...}) = 0 mmap(NULL, 44711, PROT_READ, MAP_PRIVATE, 3, 0) = 0x20000028000 close(3) = 0 open("/lib64/libc.so.6", O_RDONLY) = 3 read(3, "\177ELF\2\2\1\0\0\0\0\0\0\0\0\0\0\3\0\26\0\0\0\1\0\0\0\0\0\2\10\364\0"..., 832) = 832 fstat(3, {st_mode=S_IFREG|0755, st_size=2703224, ...}) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x20000033000 mmap(NULL, 1729920, PROT_READ|PROT_EXEC, MAP_PRIVATE|MAP_DENYWRITE, 3, 0) = 0x20000034000 mmap(0x200001d1000, 20480, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_DENYWRITE, 3, 0x19c000) = 0x200001d1000 mmap(0x200001d6000, 17792, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_FIXED|MAP_ANONYMOUS, -1, 0) = 0x200001d6000 close(3) = 0 mmap(NULL, 4096, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0) = 0x200001db000 mprotect(0x200001d1000, 16384, PROT_READ) = 0 mprotect(0x20000022000, 4096, PROT_READ) = 0 munmap(0x20000028000, 44711) = 0 rt_sigaction(SIGABRT, {0x80000e7c, [ABRT], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGINT, {0x80000e7c, [INT], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 rt_sigaction(SIGALRM, {0x80000e7c, [ALRM], SA_RESTART}, {SIG_DFL, [], 0}, 8) = 0 alarm(5) = 0 clone(child_stack=0, flags=CLONE_CHILD_CLEARTID|CLONE_CHILD_SETTID|SIGCHLD, child_tidptr=0x200001db7c0) = 2026 wait4(2026, [{WIFSTOPPED(s) && WSTOPSIG(s) == SIGSTOP}], 0, NULL) = 2026 --- SIGCHLD (Child exited) @ 0 (0) --- ptrace(PTRACE_SINGLESTEP, 2026, 0, SIG_0) = 0 wait4(2026, [{WIFEXITED(s) && WEXITSTATUS(s) == 42}], 0, NULL) = 2026 --- SIGCHLD (Child exited) @ 0 (0) --- kill(2026, SIGKILL) = -1 ESRCH (No such process) wait4(-1, NULL, __WALL, NULL) = -1 ECHILD (No child processes) exit_group(1) Also, I could not reproduce the problem in kernels without utrace. Thanks, CAI Qian From swb at wsut.com Thu Dec 24 12:23:41 2009 From: swb at wsut.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Thu, 24 Dec 2009 20:23:41 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVsssm5usH3s8zTxbuvvLC5qdOmyczGwLnA?= Message-ID: <200912241223.nBOCNZoC016440@mx1.redhat.com> ============================================================= ??????????????? ?????2010?1?9?-10? ?? ?????2010?1?20-21??? ? ??2500?/ ?????????????????? ????? ????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ========================================================================================== ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ??????????????????????????????????????????????? ????????????????????????????????????????? ==================================================================================== ????? ?????????????? ??????????? ????????????? ???????????? ???????????? ????????? ?????????? ????????????? ?????????? =================================================================================== ???? ?????????????????? ?????KPI?????? ???????????? ?????????????? ??????????????? ??????????? ????????????? ????????????? ?????????????? ????????????? ??????????????? ????????????? ????????????? ??????????? ?????????? ????????? ?????????? ?????? ???????????? ?????????? ??????? ?????????? ????KPI??????? ????????????????? ??????????? ??????????? ??????????????? ???????????? ??????????? ????????????? ?????????????? ???????????? ?????????? ?????????? ??????? ??????????????? ??????????? ?????????????? ????????????? ????????? ??????? Pareto ???????? ABC??? ???????????????? 1????? 2?????????? 3??????????? 4??????????? 5???????? 6??????????? 7????????? 8??????????????? 9????? 10?????? 11????????? 12?????????? 13??????? ?????????????? XX?????????? ???????????????? ???????????????? ????????????? ???????????? ????????????????? ???????????? ????????? ????????????? ??????????? ????????????? ?????????????? ??????????????????? ????????? ?????????????????? ?????????????? ??????????? ????????? ???????? ?????????? ???????? ?????????? ??????????? ?????????? ???????????? ???????????? INCOTERMS ????????????????? QA?QC??????? ???????????? ??????????? ?????????? ???????????? ???????????? ???????? ??????????? ????????????? ??????????????? ????????????? ????????????????? ?????????? ???????????? ?????????????????????? ?????????????????? ????????????? ??????????? ??????????? ?????????????? ????????????????????? ??????? ????????? ?????????? ????????????? ???????????? ???????????? ??????????????? ????????????? ???????? ????????? ????????? ==================================================================================== ??????????:???????????????1986????Gerber???????? ?Michigan State University (???????) ????????????,?????Heinz (??)???????????????????????????????????????? ????????????????2000???,?????????????????????? ??,???????500?????????????,?????????????????? ??????????????????????????????????????????? ?????????????????? ???????????????????????? ??????????????????????????????????????????? ??????????????????????????? ?????????????,?? ???????,??,???????????,?????,???????????????? ?????????????????,??????????????,???????????? ???????? ------------------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ?? ??? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From erpo.tuj88 at yahoo.com Fri Dec 25 06:26:19 2009 From: erpo.tuj88 at yahoo.com (Carey.Cang) Date: Fri, 25 Dec 2009 14:26:19 +0800 Subject: No subject Message-ID: <200912250626.nBP6Q2LG031122@mx1.redhat.com> From duti.mjhy at hotmail.com Sat Dec 26 20:44:46 2009 From: duti.mjhy at hotmail.com (duti.mjhy at hotmail.com) Date: Sun, 27 Dec 2009 04:44:46 +0800 Subject: =?GB2312?B?MjAxMMTquqO52NX+st/HsNWw0+u9+LP2v9q52M7xstnX9w==?= Message-ID: <200912252052.nBPKqaaC016230@mx1.redhat.com> ============================================================================= 2010??????????????? ============================================================================= ?=?=?=?: 2009?01?23-24? ?? 2009?01?30-31? ?? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ? ??salesclub @126.com ============================================================================= ?=?=?=?? ?????????????????????????? ============================================================================= ? ?? 2010???????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????? HS????????????????????????????????????? ????????????????????????????????????? ???????????????????????????????????? ?????????????????????????????????????? ?? ============================================================================= ? ???? ?????????????????? ?????????????????? 1??????????? 2? ????????E??? 3??????????????????? 4????????????????????? 5??????????????????? 6???????????????? ??2010??????????????????? 1??????????? 2????????????????? 3???????????????? 4?????????????? 5???????????????????? 6??????????????? ????????????????????? 1??????????????? 2?????????????????? 3?????????????????????? 4????????????????? 5?????????????????? 6???????????????????? 7????????????????????? 8??????????????????? 10?????????????????????? 11????????????????? 12?????????????????????? 13???????????????????? 14??????????????????? ????????????????????? 1??????????????? 2??????????????????? 3????????????????? 4????????????????? 5???????????????????? 6???????????????????? 7??????????????????????? 8??????????????????????????? 9?????????????????????? ??????????????????????? 1????????????????????????? 2????????????????? 3???????????????????????? 4??????????????????? 5????????????????? 6??????????????? 7? ????????????????????? 8?????????????? 9?????????????????????? 10???????????????????????? 11?????????????????? 12????????????????? 13??8??????????????? ??2010??????????????? ============================================================================= ? ????:??? ???????MBA???????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????? ?????????? ????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? 10?????????????????????????????????20??? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ?????????????????????????????????????? ??????????????? ???????????????????ABB?TCL????????????? ???????BP?????????????????????????????? ????????????????????3000????????? ============================================================================= ????????/?????????????????? ?????????? ------------------------------------------ M M C ? ? ? ? ?????????400-8899,628 ???????021-5109,9475 ???????020-3366,5697 / 3452,0981 ? ??salesclub @126.com ============================================================================= From news at maisservicos.com Sun Dec 27 12:19:34 2009 From: news at maisservicos.com (DIESEL) Date: Sun, 27 Dec 2009 12:19:34 +0000 Subject: Ganha 450 EUROS em produtos DIESEL! Message-ID: <20091227121929.D11DA3EA8C@server7.nortenet.pt> Caso n?o visualize correctamente este e-mail, por favor clique AQUI. Gostas da marca Diesel? Habilita-te a receber um vale de compras de 450 euros NOTA INFORMATIVA: O presente email destina-se ?nica e exclusivamente a informar potenciais utilizadores e n?o pode ser considerado SPAM. De acordo com a legisla??o internacional que regulamenta o correio electr?nico, "o email n?o pode ser? ser considerado SPAM quando incluir uma forma do receptor ser removido da lista do emissor". Para deixar de receber estas ofertas no seu e-mail clicar aqui -------------- next part -------------- An HTML attachment was scrubbed... URL: From gev at eygtx.com Mon Dec 28 12:13:44 2009 From: gev at eygtx.com (=?GB2312?B?x+vXqsjLysI=?=) Date: Mon, 28 Dec 2009 20:13:44 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVstPO/zbun06rP+rLfwtQ=?= Message-ID: <200912281213.nBSCD33V030167@mx1.redhat.com> utrace-devel????????????????????????? ?????2010?1?15?16?17? ? ? ?????2010?1?22?23?24? ? ? ????????????????????????????! ????????????????????????/????????????????????????? ?----??3900?/?(?????????????????) ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------- ?????21???????????????????????????????????80%????? 20%?????????????????????????????????????????????? ???????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????? ???????????????????????????????????????????????? ???? ????????????????????????? ????????????????????????????? ?????????????????????????? ????????????????,??????????? ?????????????????????? ???????????????????????????????????????????????? ???? ???????????? ??? ??????? ?. ????????? 1. ???????????? 2. ????????????? 3. ??????? ?. ????????????? 1. ?????????? 2. ???????????? 3. ??????????? ??? ?????????????? ?. ?????????? 1. ????????? 2. ??????????????????? 3. ????????? ?. ???????? 1. ??????????????????????????? 2. ???????????????????? 3. ???????????????????? ?. ???????? 1. ???????????? 2. ???????? ?. ?????????? 1. ?????????? 2. ?????????? 3. ??????? ?. ????????????? 1. ????? ??????? 2.???????? 3.???????N?? ?. ??????????????? 1. ?????????? 2. ?????????????????????? 3. ?????????? ??? ???????????????? ?.????????????????? 1. ????????? 2. ????????????? ?.????????????????? 1. ?????????? 2. ???????????? 3. ????????????? 4. ?????????????? ??? ?????????????? ?. ?????????? 1. ???????????? 2. ???????????? ?. ????????? 1. ?????????????? 2. ??????? 3. ????????? 4. ??????? ??? ?????????? ?. ??????????????? 1. ??????????????? 2. ?????????? 3. ????????? ?. ?????????????? 1. ?????????????????? 2. ?????? ??? ????????? ?. ???????????? 1. ????????????? 2. ?????????????? 3. ???????????????? 4. ?????????????? 5. ???????????? ?. ????? 1. ??????? 2. ????? ???????????????? ????????????? ??? ???????????? ?. ??????????????? ?. ?????????????? ?. ??????????????? ?. ??????????? ?. ???????? ?. ???????? ??? ??????????? ?. ??????????? ?. ?????? ?. ??????? ?. ??????? ?. ????????????? ?. ??????????? ??? ??????? ?. ???????? ?. ??????????? ?. ?????? ?. ?????????? ?. ??????????? ?. ????????????? ?. ??????????? ??? ????????????????? ?. ?????? ?. ??????? ?. ??????? ?. ??????? ?. ??????? ?. ??????? ??? ???????????????? ?. ???????? ?. ??????????????? ?. ???????????????? ?. ?????????????????????? ?. ????. ???????? ?. ?????????? ?. ?????????? ??? ????????????? ?. ???????????? 1. ????????????? 2. ????????????? 3. ????????????? 4. ????????????? 5. ????????????? 6. ????????????? 7. ????????????? 8. ????????????? 9. ????????????? ?. ??????????? ????????? ???? ???????? ?. ????????? ?. ????????? ?. ??????? ?. ??????? ?. ???????? ???? ?????????? ?. ???????? ?. ??????? ?. ???????? ?. ?????? ?. ?????? ???? ???????? ?. ?????? ?. ?????????? ?. ???????? ?. ???????? ???????????????? ?. ????????? ?. ????????? ?. ???????? ?. ????????? ?. ??????? ?. ??????? ???????????????? ?. ???? ?. ???? ?. ????? ?. ??????? ?. ??????? ?. ????? ?. ???? ?. ???? ???????????????????????????????????????????????? ???????????????????? 2006??2007????????? ??????????? ?????????????????????? ????MBA ????? ?? ?????????CEO? ?? ????IT???????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ?????????????????????????????? ?????????IBM??????????????????????????????????????? ??????????????MBA????????CEO??????EMBA?....... =============================================================================== ????????????????????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From rseu at wsy.com Mon Dec 28 15:39:47 2009 From: rseu at wsy.com (=?GB2312?B?x+vXqtPQudjIy8rC?=) Date: Mon, 28 Dec 2009 15:39:47 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsus/NrLncwO3T67fnz9W55rHc?= Message-ID: <200912281539.nBSFdOs7020459@mx1.redhat.com> utrace-devel?????????????????????? ??????????2010??1??21-22?? ???? ??????????2010??1??23-24?? ???? ??????????2010??1??30-31?? ???? ???????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????????????????? ????????????????2800??/?????????????????????????????????????????????? ??????????020-80560638??020-85917945 ??????????????????????????????????chinammc21 at 126.com?????? --------------------------------------------------------------- ?????????????????????????????????????????????????? ?????????????????????? ???????????????????? ?????????????????????? ?????????????????????????? ???????????????????????? ?????????????????????????????????? ?????????????????????????????????????? ?????????????????? ----------------------------------------------------------------------- ???????? ???????????????????????????????????? ???????????????????????????????? ?????????????????? ?????????????????????????????? ???????????????????????????? ?????????????????????? ?????????????????????????? ???????????? ???????????????????????? ?????????????????? ?????????????????????????? ???????????????????? ?????????????? ???????????????? ?????????????? ???????????????? ?????????????????????????????????????? ???????????????????????????????????????????? ?????????????????????????? ???????????? ?????????????????? ???????????????????????????????????????????? ???????????? ???????????????? ???????????????? ?????????????????????? ???????????????????? ?????????????? ?????????????? ?????????????? ???????????????????????? ?????????????????? ???????????? ?????????????????????????????????????? ???????????????????????????????? ???????????????????????????? ???????????????? ?????????????? ???????????????????????????????? ?????????????????????? ?????????????????????????? ?????????? ???????????????????????????????????? ?????????????????????????????????? ?????????????????????? ?????????????? ?????????? ???????? ?????????????????????????? ?????????? ???????????????? ???????????????????????? ?????????????????????? ???????????????? ?????????????????? ???????????????????????????????? ????????/?????????????????????? ????????/?????????????????????? ???????????????????? MRO???????????????? ???????????????????? ???????????????????????????????????????????? ???????????????????????????? ???????????????? ???????????????????? ?????????C???????????????? --??????????????????????????, --?????????????????????????? ???????? ????????????????????,????????,,?????????????????????????? ???????????????????????? ??????????????/?????????????? ????????/?????????????????? ?????????????? ?????????????????????????? --------------------------------------------------------------------------- ???????????????????????????????????????????????????????????????????????????? ??????????????????????????????????????????????????????????????500???????????? ??????????????????????????????????????????????????????????????????????500?? ??????????????????????????????????Thomas??????????????????????????CIPS?????? ????????????????????????????????????ISM????????????????CPM?????????????????? ??????/ITC?????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ?????????????????????????????????????????????????????????????????????????????? ???????????????????????????????????????????????????? ====================================================================================== ????????????????????????????????????????????020-62351156?? ?? ?? ?? ?? ?? ????_______________________________________________________ ?? ?? ?? ?????????? ?????? ?????? ????????______________????:________________????:________________ ??????______________ ?? ?? ?? ??:_________?? ?? ?? ????_________?? ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ?? ?? ????___________?? ?? ?? ????____________?? ?? ?? ????_____________ ???????????????????????????? ??1?????? ??2?????? ??3?????? ==================================================================================== ????:????????????????????????????????????????,??????????????020-80560638??????! From kasssku at gmail.com Mon Dec 28 17:08:06 2009 From: kasssku at gmail.com (kasssku) Date: Tue, 29 Dec 2009 01:08:06 +0800 Subject: [135 7041 =?GB2312?B?ODc3Ml3Kx9PQob5mYaGkoaShpMauob+/qrP2o7tRUTs=?= 8753 64642 Message-ID: <4b38e5df.9613f30a.75a7.ffff8141@mx.google.com> ?????????????????????????? ????????---??????! `?????????????????????????????????????????? ??????????????????????... ???????????? ?????? From stipulating at raretrend.com Mon Dec 28 18:22:36 2009 From: stipulating at raretrend.com (Alcosiba Mallak) Date: Mon, 28 Dec 2009 16:22:36 -0200 Subject: Were preparing for their fre Message-ID: <4B38F483.5010204@raretrend.com> the ice-bound Arctic to where the gray and sullen waters of Bering Sea break on a bleak and wind-swept shore. They figure but little in the forest-crowned Alaska of the South, with its enchanted isles, emerald green, in the sunlit, silver waves; but they are an indispensable factor in the very struggle for mere existence up beyond the chain of rugged Aleutians whose towering volcanoes are ever enveloped in a sinister shroud of smoke. Up in the eternal snows of the Alaska of the North, the unknown Alaska--the Alaska of Men and Dogs. [Illustration: THE ALASKA OF MEN AND DOGS June 1--The steamer Corwin at the edge of the ice, five miles from shore] And so it is not strange that in such a land where the dog has ever played well his role of support to those who have faced its dangers and conquered its terrors, that his importance should be at last freely acknowledged, and the fact admitted that only the best possible dogs should be used for all arduous tasks. Toward this end the Nome Kennel Cl -------------- next part -------------- A non-text attachment was scrubbed... Name: springboks.jpg Type: image/jpeg Size: 11984 bytes Desc: not available URL: From dt at edgg.com Wed Dec 30 02:24:35 2009 From: dt at edgg.com (=?GB2312?B?x+vXqtDox/PIy9Sx?=) Date: Wed, 30 Dec 2009 02:24:35 -0000 Subject: =?GB2312?B?dXRyYWNlLWRldmVsz/rK28r9vt231s72yczStdSksuI=?= Message-ID: <200912300224.nBU2OD2X017831@mx1.redhat.com> utrace-devel???????????? ?????2010?01?8-9? ?? ?????2010?01?15-16? ?? ? ??2600?/???????????????????????????? ?????????????????????????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? -------------------------------------------------------------------------------- ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ???????????????????????????????????? ?????????????? ------------------------------------------------------------------------- ???? ????????????????????Office???Excel???????? ?????????BladeOffice??????????????????????????? ---------------------------------------------------------------------------------- ????: ???? ????????????????????????????????????????????????????... 1.????? 2.???????? 3.?????? 4.???????????????? 5.??????????? ?????? ?????????????????????????????????? ?????????????? ??????????????? 1.?????????? 2.?????? 3.???????? 4.?????? 5.?????? 6.??????????????????????? 7.?????????????? 8.???? ????????????? ????????????????????????????????????????????? 1.??????????? 2.????????? 3.????????? 4.????????? 5.????????? 6.????KPI?? ?????? ????????????????????????????????????? 1.????????? 2.???????? 3.???????? 4.??????? 5.?????? 6.??????? 7.?????? ???????? ????????????????????????????????????? 1.???? 2.??????????? 3.???? 4.??????????? 5.?????????? ???????????? ???????????????????????????????????????????????? 1.?????????? 2.????????????? 3.????????????????? 4.????????? 5.?????????? 6.??????????? 7.????????????? ??????????? ???????????????????????????????????????????????????????????? 1.??????? 2.??????? 3.??????1?1?????? 4.??????????? 5.?????????????? 6.????????RFM?? 7.?????(VOC)?? 8.??????????? 9.??????? ???????? ????????????????????????????????????????????????? 1.????????? 2.??????????? 3.???????????????? i. ???????????????? ii. ??????????? 4.??????????????????????????? i.????????????? ii.???????????? iii.?????????????????????? iv.????????????? 5.???????????????????????? -------------------------------------------------------------------------------------------- ?????????: ??????IPMA???????MCSE?MCDBA?????????????? ??????????????????????????????????????????OA? ERP?BI???????????????????????????????????????? ??????????????????? ????????????????????????????????????????????? ???????????????????????????????????????????????? =============================================================================== ???????????????????????020-62351156? ???????_______________________________________________________ ???????? ??? ??? ????______________??:________________??:________________ ???______________????:_________?????_________? ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ????___________?????____________?????_____________ ???????????????1????2????3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From caiqian at redhat.com Wed Dec 30 03:09:04 2009 From: caiqian at redhat.com (caiqian at redhat.com) Date: Tue, 29 Dec 2009 22:09:04 -0500 (EST) Subject: [PATCH 0/7] utrace/ptrace In-Reply-To: <1319782550.2227981262142487066.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> Message-ID: <1358829885.2228001262142544881.JavaMail.root@zmail06.collab.prod.int.phx2.redhat.com> > This is the new iteration of Roland's utrace patch, this time > with "rewrite-ptrace-via-utrace" + cleanups in utrace core. Tested-by: CAI Qian From emailmarketing at omail1.armmarketing.com.br Thu Dec 31 06:52:36 2009 From: emailmarketing at omail1.armmarketing.com.br (AR Marketing) Date: 31 Dec 2009 04:52:36 -0200 Subject: Email Marketing e Newsletter Message-ID: <200912310707.nBV77i5E008075@mx1.redhat.com> An HTML attachment was scrubbed... URL: From vbiu at werg.com Thu Dec 31 21:15:25 2009 From: vbiu at werg.com (=?GB2312?B?x+vXqs/gudjIy9Sx?=) Date: Fri, 1 Jan 2010 05:15:25 +0800 Subject: =?GB2312?B?dXRyYWNlLWRldmVs19y+rcDttcSyxs7xudzA7cq11b0=?= Message-ID: <200912312115.nBVLFM5x008167@mx1.redhat.com> utrace-devel?????????? ?????2010?1?21-22?--- ?? ?????2010?1?23-24? ----?? ????: ?????????????????????????????????????? ????: 2800?/????????????????????? ?????500??????????????????????? ?????020-80560638?020-85917945 ?????????????????chinammc21 at 126.com??? ====================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ????? ================================================================================== ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ???????????????????????????????????????????????? ??????????????????????????????????????? ??????????????????? ??????????????????????? ?????????????????? ?????????????????????????? ????????????????????????????????????? ??????????????????????????? ====================================================================================== ?????????? (?????????????????????????????????)??????MBA??????? ??CPA????????CPT???????????????????????????????????? ????????????????????????????????????????????????? ?????????CFO?????????????????????????????????????? ????????????????????????????????????????????????? ??????????????????????????????????????????,?????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????(??)?? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ????????????????????????????????????????????????? ???????????????????????????????????? ???????????????????? ====================================================================================== ???? ???????????? ???????? ??????????? 1????? 2??????? 3???????? ??????? 1??? 2??? 3?????? 4??? 5??? 6??? ???????? 1???????? 2?????? ????????????? ????????????????????? 1??????????? 2??????????? ?????????????????? 1????? 2????? 3????? 4?????? 5????? 6??? 7)???? 8????? 9????? 10????? 11????? 12?????? 13????? 14?????? 15????? 16????? 17????? 18?????? ?????????? 1??????????????? 2???????????? 3?????????? 4????????????? ??????????? ?????????? 1?????? 2?????? ???????????? 1????? 2????? 3???????? 4????? 5????? 6????? 7?????? 8?????? 9????? 10???? ?????????????? 1????????????? 2????????????? 3????????????? 4????????????? 5???????????? ???????? 1?????????? 2?????????? 3?????????????????? 4????????? ?????????? ???????????? 1?????????????? 2?????????????? 3?????????????? 4?????????????? ???????????? 1???????????????????? 2??????????????? 3????????????? ?????????? 1????????? 2??????? 3????????? ????????????? ????????????? 1?????????? 2?????????? 3????????? 4?????????? 5????????????? ????????? 1??????????? 2???????????? ????? ???????????? 1???????? 2???????? 3???????? ???????? 1??????? 2??????? 3???????? 4?????????? 5????????? 6?????? 7????? 8??????? 9??????? 10?????? 11?????????? 12?????? 13??????? 14???????? 15???????? 16????? ?????????????????? ????????????? ?????????????????? 1????????? 2????????? 3???????????? 4????????? 5????????? ?????? 1???????? 2??????? 3????????? 4??????ABC??? ???????? 1?????????? 2????? 3????? 4?????????? ???????? 1???????? 2??????? 3???????? 4?????????? 5????????????Z-SCORE??? ???????????????????? 1??????? 2?????????????????? ???????????? ???????? ????????????????????? 1??????? 2??????? 3?????????? 4???????? ???????????? 1????? 2????? 3????? 4????? 5????? ???????????? 1????? 2????? 3????? 4????? ?????????? 1?????????? 2?????????? 3?????????? 4?????????? ?????????? 1?????? 2?????? 3?????? ???????????? 1????? 2????? 3????? 4????? 5????? ?????????? 1??????? 2??????? 3??????? 4??????? 5??????? 6??????? 7??????? 8??????? 9??????? ???????? 1???????? 2???????? ?????????? 1????????????? 2????? 3????? ???????? ??????? 1????????? 2?????????? 3????? 4???????????????? ??????????????? 1?????? 2????? 3????? 4??????? -------------------------------------------------------------------- ??????????????????????????020-62351156? ? ? ? ? ? ??_______________________________________________________ ? ? ? ????? ??? ????______________??:________________??:________________ ???______________ ? ? ? ?:_________? ? ? ??_________? ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ? ? ??___________? ? ? ??____________? ? ? ??_____________ ?????????????? ?1??? ?2??? ?3??? ==================================================================================== ??:????????????????????,???????020-80560638???! From repay at divaika.ch Thu Dec 31 22:56:19 2009 From: repay at divaika.ch (Drum) Date: Fri, 01 Jan 2010 00:56:19 +0200 Subject: Fter their flight to the mountains of Kwangsi. Message-ID: <4B3D3912.4040707@divaika.ch> Allowed entrance into the States, but they only ask that the Americans cease treating the Chinese with contempt and allow their merchants and students the same privileges that other foreigners receive." "'Peale graduated from the Princeton Theological Seminary last May. "Is it not evident that whatever spark caused the explosion, the nitro-glycerin that made it possible came from the boycott? "Not only do they boycott ponderables such as figure at the custom-house, but they extend the taboo to things of the head and heart. The leader of the whole movement was formerly an active supporter of the International Institute, an institution which proposes to open gratuitous courses of lectures and to place Chinese men of intelligence on common ground with scholars of the West, He now opposes the International Institute -------------- next part -------------- A non-text attachment was scrubbed... Name: vanguardism.jpg Type: image/jpeg Size: 15160 bytes Desc: not available URL: