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); + } } /**************************************************************