X-Git-Url: http://git.hungrycats.org/cgi-bin/gitweb.cgi?a=blobdiff_plain;f=driver%2Fpasswd-pam.c;h=324e31fd197188e3e87b5c9192893744f7951124;hb=a1d41b2aa6e18bf9a49b914a99dda8232c5d7762;hp=9e6a7194f3150424abfa87cd61dd87f04ee83d91;hpb=14627f4038ada5d11456f3770090f3c39740d70f;p=xscreensaver diff --git a/driver/passwd-pam.c b/driver/passwd-pam.c index 9e6a7194..324e31fd 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 @@ -67,6 +69,13 @@ extern char *blurb(void); #undef countof #define countof(x) (sizeof((x))/sizeof(*(x))) +/* Some time between Red Hat 4.2 and 7.0, the words were transposed + in the various PAM_x_CRED macro names. Yay! + */ +#ifndef PAM_REFRESH_CRED +# define PAM_REFRESH_CRED PAM_CRED_REFRESH +#endif + static int pam_conversation (int nmsgs, const struct pam_message **msg, struct pam_response **resp, @@ -211,9 +220,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));