X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fpasswd-pam.c;h=43f2cbc2cddbaa0ae0d9d6e3815f5ab99a91dc92;hb=3c58fb6311db49c46f1670922933b27c6ea0c065;hp=aedd47e294c4e64917b2554a7d32555b3105a3b8;hpb=0316d74da7982288abddd34e7a62698eb7f79965;p=xscreensaver diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c index aedd47e2..43f2cbc2 100644 --- a/driver/passwd-pam.c +++ b/driver/passwd-pam.c @@ -1,7 +1,7 @@ /* passwd-pam.c --- verifying typed passwords with PAM * (Pluggable Authentication Modules.) * written by Bill Nottingham (and jwz) for - * xscreensaver, Copyright (c) 1993-1998, 2000 Jamie Zawinski + * xscreensaver, Copyright (c) 1993-2001 Jamie Zawinski * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that @@ -55,6 +55,8 @@ extern char *blurb(void); #include +extern void block_sigchld (void); +extern void unblock_sigchld (void); /* blargh */ #undef Bool @@ -152,6 +154,7 @@ struct pam_closure { So we get around this by using a global variable instead. Shoot me! (I've been told this is bug 4092227, and is fixed in Solaris 7.) + (I've also been told that it's fixed in Solaris 2.6 by patch 106257-05.) */ static void *suns_pam_implementation_blows = 0; @@ -210,9 +213,31 @@ pam_passwd_valid_p (const char *typed_passwd, Bool verbose_p) } /* Try to authenticate as the current user. + We must turn off our SIGCHLD handler for the duration of the call to + pam_authenticate(), because in some cases, the underlying PAM code + will do this: + + 1: fork a setuid subprocess to do some dirty work; + 2: read a response from that subprocess; + 3: waitpid(pid, ...) on that subprocess. + + If we (the ignorant parent process) have a SIGCHLD handler, then there's + a race condition between steps 2 and 3: if the subprocess exits before + waitpid() was called, then our SIGCHLD handler fires, and gets notified + of the subprocess death; then PAM's call to waitpid() fails, because the + process has already been reaped. + + I consider this a bug in PAM, since the caller should be able to have + whatever signal handlers it wants -- the PAM documentation doesn't say + "oh by the way, if you use PAM, you can't use SIGCHLD." */ + PAM_NO_DELAY(pamh); + + block_sigchld(); status = pam_authenticate (pamh, 0); + unblock_sigchld(); + if (verbose_p) fprintf (stderr, "%s: pam_authenticate (...) ==> %d (%s)\n", blurb(), status, PAM_STRERROR(pamh, status));