Linux-PAM and saslauthd process reaping conflict

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

 



Hello,

my apologies for crossposting. I am unsure which project this should be
fixed in, if not both.

When you use saslauthd with pam_exec.so, a process reaping race is
created. pam_exec.c uses a fork/waitpid combination to run it's child
process and saslauthd has a signal handler for SIGCHLD. If the process
terminates before the waitpid is entered, the SIGCHLD is handled by
saslauthd and pam_exec returns with an error to the pam stack.

I tried fixing it in PAM by restoring the default sighandler but this
did not seem to work (see patch). Perhaps I made a silly mistake or it
has something to do with MT signal handling, I do not know. In any case,
it seems a bad idea for PAM to assume there is no SIGCHLD handler
installed in the parent process.

Eventually, I fixed it by disabling automatic process reaping in
saslautd with the pam authentication mechanism. Afaict, this handler is
not used anyway.

Regards,

Johan Verrept


--
NEW on aXs GUARD: SSL VPN !! (contact your reseller for more info)

---------------------------------------------------
aXs GUARD has completed security and anti-virus checks on this e-mail (http://www.axsguard.com)
---------------------------------------------------
Able NV: ond.nr 0457.938.087
RPR Mechelen

--- pam_exec.c	2008-12-19 15:07:04.000000000 +0100
+++ pam_exec.c.new	2008-12-19 15:07:51.000000000 +0100
@@ -80,6 +80,7 @@
   int optargc;
   const char *logfile = NULL;
   pid_t pid;
+  struct sigaction newact, oldact;
 
   if (argc < 1) {
     pam_syslog (pamh, LOG_ERR,
@@ -110,15 +111,27 @@
     return PAM_SERVICE_ERR;
   }
 
+  /* Setup signals so that SIGCHLD is ignored as we want to do waitpid */
+  newact.sa_handler = SIG_DFL;
+  newact.sa_flags = 0;
+  sigfillset(&newact.sa_mask);
+  sigaction (SIGCHLD, &newact, &oldact);
+                      
   pid = fork();
-  if (pid == -1)
+  if (pid == -1) {
+    /* restore sigaction */
+    sigaction (SIGCHLD, &oldact, NULL);
     return PAM_SYSTEM_ERR;
+  }
   if (pid > 0) /* parent */
     {
       int status = 0;
       pid_t retval;
       while ((retval = waitpid (pid, &status, 0)) == -1 &&
 	     errno == EINTR);
+
+      /* restore sigaction before we start returning */
+      sigaction (SIGCHLD, &oldact, NULL);
       if (retval == (pid_t)-1)
 	{
 	  pam_syslog (pamh, LOG_ERR, "waitpid returns with -1: %m");
diff -ur cyrus-sasl-2.1.21/saslauthd/saslauthd-main.c cyrus-sasl-2.1.21-jov2/saslauthd/saslauthd-main.c
--- cyrus-sasl-2.1.21/saslauthd/saslauthd-main.c	2008-12-18 11:11:15.000000000 +0100
+++ cyrus-sasl-2.1.21-jov2/saslauthd/saslauthd-main.c	2008-12-18 11:10:38.000000000 +0100
@@ -528,15 +528,18 @@
 
 	/**************************************************************
 	 * Handler for SIGCHLD
+	 * not installed for pam to avoid reaping problems.
 	 **************************************************************/
-	act_sigchld.sa_handler = handle_sigchld;
-	sigemptyset(&act_sigchld.sa_mask);
-
-	if (sigaction(SIGCHLD, &act_sigchld, NULL) != 0) {
-		rc = errno;
-		logger(L_ERR, L_FUNC, "failed to set sigaction for SIGCHLD");
-		logger(L_ERR, L_FUNC, "sigaction: %s", strerror(rc));
-		exit(1);
+	if (strcmp (auth_mech->name, "pam")) {
+		act_sigchld.sa_handler = handle_sigchld;
+		sigemptyset(&act_sigchld.sa_mask);
+
+		if (sigaction(SIGCHLD, &act_sigchld, NULL) != 0) {
+			rc = errno;
+			logger(L_ERR, L_FUNC, "failed to set sigaction for SIGCHLD");
+			logger(L_ERR, L_FUNC, "sigaction: %s", strerror(rc));
+			exit(1);
+		}
 	}
 
 	/**************************************************************

[Index of Archives]     [Info Cyrus]     [Squirrel Mail]     [Linux Media]     [Yosemite News]     [gtk]     [KDE]     [Gimp on Windows]     [Steve's Art]

  Powered by Linux