Based on your comments to the bug I filed against gdm, here's a patch
that disables the SIGCHLD handler while waiting for the helper process
to exit. This seems to be the approach favoured by upstream; the same
modifications were made to pam_unix and pam_pwdb:
<https://www.redhat.com/archives/pam-list/2002-September/msg00040.html>.
I also changed from wait(2) to waitpid(2) in case the authenticating
process has other children that happen to change state while pam_tmpdir
is waiting on the helper process.
--
Sam Morris
http://robots.org.uk/
PGP key id 5EA01078
3412 EA18 1277 354B 991B C869 B219 7FDB 5EA0 1078
--- pam-tmpdir-0.05/pam_tmpdir.c 2006-03-07 17:52:16.000000000 +0000
+++ pam-tmpdir-0.05+sam/pam_tmpdir.c 2006-03-07 19:41:07.000000000 +0000
@@ -15,6 +15,7 @@
#include <ctype.h>
#include <errno.h>
#include <pwd.h>
+#include <signal.h>
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
@@ -94,6 +95,19 @@
int ret = 0;
int status;
pid_t pid;
+ struct sigaction old, new;
+
+ new.sa_handler = SIG_DFL;
+ sigemptyset(&new.sa_mask);
+ new.sa_flags = 0;
+
+ /* save old signal handler */
+ ret = sigaction(SIGCHLD, &new, &old);
+ if (ret == -1) {
+ _log_err(LOG_WARNING, "could not save SIGCHLD handler");
+ return 1;
+ }
+
/* Do fork and exec by hand.. */
pid = fork();
if (!pid) {
@@ -101,8 +115,21 @@
if (geteuid() == 0)
setuid(get_user_id(pamh));
execl(PAM_TMPDIR_HELPER,PAM_TMPDIR_HELPER,NULL);
- }
- wait(&status);
+ }
+
+ ret = waitpid(pid, &status, 0);
+ if (ret == -1) {
+ _log_err(LOG_ERR, "error waiting for helper binary (%d)\n", errno);
+ return 1;
+ }
+
+ /* restore old signal handler */
+ ret = sigaction(SIGCHLD, &old, NULL);
+ if (ret == -1) {
+ _log_err(LOG_WARNING, "could not restore SIGCHLD handler");
+ return 1;
+ }
+
return WEXITSTATUS(status);
}