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-17 11:25:11.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,14 @@ 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);
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 +240,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-17 11:25:11.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,14 @@ 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);
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 +489,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-17 15:14:09.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,32 @@ 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 so we do not exec the helper with
+ tty as stdin, it will not read anything from there anyway */
+ dup2(fds[0], STDIN_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 +129,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 +164,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 */