Skip to content
  • Oleg Nesterov's avatar
    ptrace: partially fix the do_wait(WEXITED) vs EXIT_DEAD->EXIT_ZOMBIE race · ef50d8d9
    Oleg Nesterov authored
    commit 50b8d257 upstream.
    
    Test-case:
    
    	int main(void)
    	{
    		int pid, status;
    
    		pid = fork();
    		if (!pid) {
    			for (;;) {
    				if (!fork())
    					return 0;
    				if (waitpid(-1, &status, 0) < 0) {
    					printf("ERR!! wait: %m\n");
    					return 0;
    				}
    			}
    		}
    
    		assert(ptrace(PTRACE_ATTACH, pid, 0,0) == 0);
    		assert(waitpid(-1, NULL, 0) == pid);
    
    		assert(ptrace(PTRACE_SETOPTIONS, pid, 0,
    					PTRACE_O_TRACEFORK) == 0);
    
    		do {
    			ptrace(PTRACE_CONT, pid, 0, 0);
    			pid = waitpid(-1, NULL, 0);
    		} while (pid > 0);
    
    		return 1;
    	}
    
    It fails because ->real_parent sees its child in EXIT_DEAD state
    while the tracer is going to change the state back to EXIT_ZOMBIE
    in wait_task_zombie().
    
    The offending commit is 823b018e
    
     which moved the EXIT_DEAD check,
    but in fact we should not blame it. The original code was not
    correct as well because it didn't take ptrace_reparented() into
    account and because we can't really trust ->ptrace.
    
    This patch adds the additional check to close this particular
    race but it doesn't solve the whole problem. We simply can't
    rely on ->ptrace in this case, it can be cleared if the tracer
    is multithreaded by the exiting ->parent.
    
    I think we should kill EXIT_DEAD altogether, we should always
    remove the soon-to-be-reaped child from ->children or at least
    we should never do the DEAD->ZOMBIE transition. But this is too
    complex for 3.2.
    
    Reported-and-tested-by: default avatarDenys Vlasenko <vda.linux@googlemail.com>
    Tested-by: default avatarLukasz Michalik <lmi@ift.uni.wroc.pl>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
    Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@suse.de>
    ef50d8d9