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 <o...@redhat.com>
---

 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);

Reply via email to