diff -up Linux-PAM-1.0.4/modules/pam_unix/pam_unix_passwd.c.safeguards Linux-PAM-1.0.4/modules/pam_unix/pam_unix_passwd.c --- Linux-PAM-1.0.4/modules/pam_unix/pam_unix_passwd.c.safeguards 2009-03-17 11:25:11.000000000 +0100 +++ Linux-PAM-1.0.4/modules/pam_unix/pam_unix_passwd.c 2009-03-26 10:29:32.000000000 +0100 @@ -139,7 +139,7 @@ static int _unix_run_update_binary(pam_h const char *fromwhat, const char *towhat, int remember) { int retval, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("called.")); /* create a pipe for the password */ @@ -157,13 +157,15 @@ static int _unix_run_update_binary(pam_h * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ child = fork(); if (child == 0) { - size_t i=0; + int i=0; struct rlimit rlim; static char *envp[] = { NULL }; char *args[] = { NULL, NULL, NULL, NULL, NULL, NULL }; @@ -171,15 +173,18 @@ static int _unix_run_update_binary(pam_h /* XXX - should really tidy up PAM here too */ - close(0); close(1); /* reopen stdin as pipe */ - close(fds[1]); dup2(fds[0], STDIN_FILENO); + /* and replace also the stdout/err as the helper will + not write anything there */ + dup2(fds[1], STDOUT_FILENO); + dup2(fds[1], STDERR_FILENO); if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[0] != i) - close(i); + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++) { + close(i); } } @@ -239,8 +244,8 @@ static int _unix_run_update_binary(pam_h retval = PAM_AUTH_ERR; } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } return retval; diff -up Linux-PAM-1.0.4/modules/pam_unix/support.c.safeguards Linux-PAM-1.0.4/modules/pam_unix/support.c --- Linux-PAM-1.0.4/modules/pam_unix/support.c.safeguards 2009-03-17 11:25:11.000000000 +0100 +++ Linux-PAM-1.0.4/modules/pam_unix/support.c 2009-03-26 10:29:54.000000000 +0100 @@ -396,7 +396,7 @@ static int _unix_run_helper_binary(pam_h unsigned int ctrl, const char *user) { int retval, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("called.")); /* create a pipe for the password */ @@ -414,7 +414,9 @@ static int _unix_run_helper_binary(pam_h * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ @@ -427,15 +429,18 @@ static int _unix_run_helper_binary(pam_h /* XXX - should really tidy up PAM here too */ - close(0); close(1); /* reopen stdin as pipe */ - close(fds[1]); dup2(fds[0], STDIN_FILENO); + /* and replace also the stdout/err as the helper will + not write anything there */ + dup2(fds[1], STDOUT_FILENO); + dup2(fds[1], STDERR_FILENO); if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < (int)rlim.rlim_max; i++) { - if (fds[0] != i) - close(i); + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++) { + close(i); } } @@ -488,8 +493,8 @@ static int _unix_run_helper_binary(pam_h retval = PAM_AUTH_ERR; } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } D(("returning %d", retval)); diff -up Linux-PAM-1.0.4/modules/pam_unix/pam_unix_acct.c.safeguards Linux-PAM-1.0.4/modules/pam_unix/pam_unix_acct.c --- Linux-PAM-1.0.4/modules/pam_unix/pam_unix_acct.c.safeguards 2009-03-03 10:00:31.000000000 +0100 +++ Linux-PAM-1.0.4/modules/pam_unix/pam_unix_acct.c 2009-03-26 10:29:17.000000000 +0100 @@ -65,7 +65,7 @@ int _unix_run_verify_binary(pam_handle_t const char *user, int *daysleft) { int retval=0, child, fds[2]; - void (*sighandler)(int) = NULL; + struct sigaction newsa, oldsa; D(("running verify_binary")); /* create a pipe for the messages */ @@ -85,29 +85,33 @@ int _unix_run_verify_binary(pam_handle_t * The "noreap" module argument is provided so that the admin can * override this behavior. */ - sighandler = signal(SIGCHLD, SIG_DFL); + memset(&newsa, '\0', sizeof(newsa)); + newsa.sa_handler = SIG_DFL; + sigaction(SIGCHLD, &newsa, &oldsa); } /* fork */ child = fork(); if (child == 0) { - size_t i=0; + int i=0; struct rlimit rlim; static char *envp[] = { NULL }; char *args[] = { NULL, NULL, NULL, NULL }; - close(0); close(1); - /* reopen stdin as pipe */ - close(fds[0]); + /* reopen stdout as pipe */ dup2(fds[1], STDOUT_FILENO); + /* and replace also the stdin, stderr so we do not exec the helper with + tty as stdin, it will not read anything from there anyway */ + dup2(fds[0], STDIN_FILENO); + dup2(fds[1], STDERR_FILENO); /* XXX - should really tidy up PAM here too */ if (getrlimit(RLIMIT_NOFILE,&rlim)==0) { - for (i=2; i < rlim.rlim_max; i++) { - if ((unsigned int)fds[1] != i) { - close(i); - } + if (rlim.rlim_max >= MAX_FD_NO) + rlim.rlim_max = MAX_FD_NO; + for (i = STDERR_FILENO + 1; i < (int)rlim.rlim_max; i++) { + close(i); } } @@ -126,7 +130,6 @@ int _unix_run_verify_binary(pam_handle_t pam_syslog(pamh, LOG_ERR, "helper binary execve failed: %m"); /* should not get here: exit with error */ - close (fds[1]); D(("helper binary is not available")); printf("-1\n"); exit(PAM_AUTHINFO_UNAVAIL); @@ -162,9 +165,11 @@ int _unix_run_verify_binary(pam_handle_t } close(fds[0]); } - if (sighandler != SIG_ERR) { - (void) signal(SIGCHLD, sighandler); /* restore old signal handler */ + + if (off(UNIX_NOREAP, ctrl)) { + sigaction(SIGCHLD, &oldsa, NULL); /* restore old signal handler */ } + D(("Returning %d",retval)); return retval; } diff -up Linux-PAM-1.0.4/modules/pam_unix/passverify.c.safeguards Linux-PAM-1.0.4/modules/pam_unix/passverify.c --- Linux-PAM-1.0.4/modules/pam_unix/passverify.c.safeguards 2009-03-02 16:02:22.000000000 +0100 +++ Linux-PAM-1.0.4/modules/pam_unix/passverify.c 2009-03-17 11:25:11.000000000 +0100 @@ -117,7 +117,7 @@ verify_pwd_hash(const char *p, char *has p = NULL; /* no longer needed here */ /* the moment of truth -- do we agree with the password? */ - D(("comparing state of pp[%s] and salt[%s]", pp, salt)); + D(("comparing state of pp[%s] and hash[%s]", pp, hash)); if (pp && strcmp(pp, hash) == 0) { retval = PAM_SUCCESS; @@ -675,8 +675,13 @@ save_old_password(const char *forwho, co } } + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to old passwords file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to old passwords file: %m")); + D(("fclose error writing entries to old passwords file: %m")); err = 1; } @@ -795,8 +800,13 @@ unix_update_passwd(pam_handle_t *pamh, c } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to password file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to password file: %m")); + D(("fclose error writing entries to password file: %m")); err = 1; } @@ -925,8 +935,13 @@ unix_update_shadow(pam_handle_t *pamh, c } fclose(opwfile); + if (fflush(pwfile) || fsync(fileno(pwfile))) { + D(("fflush or fsync error writing entries to shadow file: %m")); + err = 1; + } + if (fclose(pwfile)) { - D(("error writing entries to shadow file: %m")); + D(("fclose error writing entries to shadow file: %m")); err = 1; } @@ -1007,8 +1022,12 @@ su_sighandler(int sig) { #ifndef SA_RESETHAND /* emulate the behaviour of the SA_RESETHAND flag */ - if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) - signal(sig, SIG_DFL); + if ( sig == SIGILL || sig == SIGTRAP || sig == SIGBUS || sig = SIGSERV ) { + struct sigaction sa; + memset(&sa, '\0, sizeof(sa)); + sa.sa_handler = SIG_DFL; + sigaction(sig, &sa, NULL); + } #endif if (sig > 0) { _exit(sig); diff -up Linux-PAM-1.0.4/modules/pam_unix/support.h.safeguards Linux-PAM-1.0.4/modules/pam_unix/support.h --- Linux-PAM-1.0.4/modules/pam_unix/support.h.safeguards 2008-01-23 16:35:13.000000000 +0100 +++ Linux-PAM-1.0.4/modules/pam_unix/support.h 2009-03-17 11:25:11.000000000 +0100 @@ -127,6 +127,7 @@ static const UNIX_Ctrls unix_args[UNIX_C #define UNIX_DEFAULTS (unix_args[UNIX__NONULL].flag) +#define MAX_FD_NO 2000000 /* use this to free strings. ESPECIALLY password strings */