• Oleg Nesterov's avatar
    ptrace_detach: the wrong wakeup breaks the ERESTARTxxx logic · 95a3540d
    Oleg Nesterov authored
    Another ancient bug. Consider this trivial test-case,
    
    	int main(void)
    	{
    		int pid = fork();
    
    		if (pid) {
    			ptrace(PTRACE_ATTACH, pid, NULL, NULL);
    			wait(NULL);
    			ptrace(PTRACE_DETACH, pid, NULL, NULL);
    		} else {
    			pause();
    			printf("WE HAVE A KERNEL BUG!!!\n");
    		}
    
    		return 0;
    	}
    
    the child must not "escape" for sys_pause(), but it can and this was seen
    in practice.
    
    This is because ptrace_detach does:
    
    	if (!child->exit_state)
    		wake_up_process(child);
    
    this wakeup can happen after this child has already restarted sys_pause(),
    because it gets another wakeup from ptrace_untrace().
    
    With or without this patch, perhaps sys_pause() needs a fix.  But this
    wakeup also breaks the SIGNAL_STOP_STOPPED logic in ptrace_untrace().
    
    Remove this wakeup.  The caller saw this task in TASK_TRACED state, and
    unless it was SIGKILL'ed in between __ptrace_unlink()->ptrace_untrace()
    should handle this case correctly.  If it was SIGKILL'ed, we don't need to
    wakup the dying tracee too.
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Cc: Jerome Marchand <jmarchan@redhat.com>
    Acked-by: default avatarRoland McGrath <roland@redhat.com>
    Cc: Denys Vlasenko <dvlasenk@redhat.com>
    Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    95a3540d
ptrace.c 18.6 KB