Skip to content
  • Oleg Nesterov's avatar
    ptrace: dont send SIGSTOP on auto-attach if PT_SEIZED · d184d6eb
    Oleg Nesterov authored
    
    
    The fake SIGSTOP during attach has numerous problems. PTRACE_SEIZE
    is already fine, but we have basically the same problems is SIGSTOP
    is sent on auto-attach, the tracer can't know if this signal signal
    should be cancelled or not.
    
    Change ptrace_event() to set JOBCTL_TRAP_STOP if the new child is
    PT_SEIZED, this triggers the PTRACE_EVENT_STOP report.
    
    Thereafter a PT_SEIZED task can never report the bogus SIGSTOP.
    
    Test-case:
    
    	#define PTRACE_SEIZE		0x4206
    	#define PTRACE_SEIZE_DEVEL	0x80000000
    	#define PTRACE_EVENT_STOP	7
    	#define WEVENT(s)		((s & 0xFF0000) >> 16)
    
    	int main(void)
    	{
    		int child, grand_child, status;
    		long message;
    
    		child = fork();
    		if (!child) {
    			kill(getpid(), SIGSTOP);
    			fork();
    			assert(0);
    			return 0x23;
    		}
    
    		assert(ptrace(PTRACE_SEIZE, child, 0,PTRACE_SEIZE_DEVEL) == 0);
    		assert(wait(&status) == child);
    		assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGSTOP);
    
    		assert(ptrace(PTRACE_SETOPTIONS, child, 0, PTRACE_O_TRACEFORK) == 0);
    
    		assert(ptrace(PTRACE_CONT, child, 0,0) == 0);
    		assert(waitpid(child, &status, 0) == child);
    		assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);
    		assert(WEVENT(status) == PTRACE_EVENT_FORK);
    
    		assert(ptrace(PTRACE_GETEVENTMSG, child, 0, &message) == 0);
    		grand_child = message;
    
    		assert(waitpid(grand_child, &status, 0) == grand_child);
    		assert(WIFSTOPPED(status) && WSTOPSIG(status) == SIGTRAP);
    		assert(WEVENT(status) == PTRACE_EVENT_STOP);
    
    		kill(child, SIGKILL);
    		kill(grand_child, SIGKILL);
    		return 0;
    	}
    
    Signed-off-by: default avatarOleg Nesterov <oleg@redhat.com>
    Acked-by: default avatarTejun Heo <tj@kernel.org>
    d184d6eb