[Date Prev][Date Next] [Thread Prev][Thread Next] [Date Index] [Thread Index]

Bug#248125: sshd processes hanging around after Ctrl-C-ed authentication



Colin Watson wrote:
I'm afraid I'm currently on 3.8.1p1 and can still reproduce it.

Damn, you're right.

It appears that what is happening is that the client exits, breaking the TCP connection. When that happens, the privsep slave exits too, which causes a SIGCHLD to be delivered to the monitor. The monitor then attempts to waitpid() on the PAM "thread" which is still alive and blissfully unaware of a problem (because nobody told it to die). That waitpid hangs the monitor's cleanup.

The attached patch tests adds a test for this case to the signal handler to shoot the PAM thread itself if it has to. It needs a bit more thought, but works for me in limited testing.

--
Darren Tucker (dtucker at zip.com.au)
GPG key 8FF4FA69 / D9A3 86E9 7EEE AF4B B2D4  37C9 C982 80C7 8FF4 FA69
    Good judgement comes with experience. Unfortunately, the experience
usually comes from bad judgement.
Index: auth-pam.c
===================================================================
RCS file: /usr/local/src/security/openssh/cvs/openssh_cvs/auth-pam.c,v
retrieving revision 1.101
diff -u -p -r1.101 auth-pam.c
--- auth-pam.c	13 May 2004 07:29:35 -0000	1.101
+++ auth-pam.c	20 May 2004 16:34:11 -0000
@@ -95,8 +95,14 @@ sshpam_sigchld_handler(int sig)
 {
 	if (cleanup_ctxt == NULL)
 		return;	/* handler called after PAM cleanup, shouldn't happen */
-	if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0) == -1)
-		return;	/* couldn't wait for process */
+	if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, WNOHANG)
+	     == -1) {
+		/* PAM thread has not exitted, privsep slave must have */
+		kill(cleanup_ctxt->pam_thread, SIGTERM);
+		if (waitpid(cleanup_ctxt->pam_thread, &sshpam_thread_status, 0)
+		    == -1)
+			return; /* could not wait */
+	}
 	if (WIFSIGNALED(sshpam_thread_status) &&
 	    WTERMSIG(sshpam_thread_status) == SIGTERM)
 		return;	/* terminated by pthread_cancel */

Reply to: