File pam-restrict-number-fds-to-close.patch of Package pam.8944
Index: Linux-PAM-1.1.8/modules/pam_exec/pam_exec.c
===================================================================
--- Linux-PAM-1.1.8.orig/modules/pam_exec/pam_exec.c
+++ Linux-PAM-1.1.8/modules/pam_exec/pam_exec.c
@@ -48,7 +48,7 @@
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
-
+#include <dirent.h>
#define PAM_SM_AUTH
#define PAM_SM_ACCOUNT
@@ -107,6 +107,7 @@ call_exec (const char *pam_type, pam_han
int fds[2];
int stdout_fds[2];
FILE *stdout_file = NULL;
+ DIR *d;
if (argc < 1) {
pam_syslog (pamh, LOG_ERR,
@@ -392,8 +393,46 @@ call_exec (const char *pam_type, pam_han
_exit (err);
}
- for (i = 3; i < sysconf (_SC_OPEN_MAX); i++)
- close (i);
+ if ((d = opendir("/proc/self/fd")) != NULL)
+ {
+ struct dirent *de;
+
+ /*
+ * Traverse /proc/self/fd and close every fd found except
+ * - stdin/stdout/stderr
+ * - the fd of "d" (obviously)
+ */
+ while ((de = readdir(d)) != NULL)
+ {
+ char *next;
+
+ if (de->d_name[0] == '.')
+ continue;
+ i = strtol(de->d_name, &next, 10);
+ if ((next != de->d_name) && (*next == '\0') && (i > STDERR_FILENO) && (i != dirfd(d)))
+ {
+ if (debug)
+ {
+ char pn[32], ln[128];
+ ssize_t len;
+
+ snprintf(pn, sizeof(pn), "/proc/self/fd/%d", i);
+ if ((len = readlink(pn, ln, sizeof(ln))) != -1)
+ ln[len] = '\0';
+ else
+ strcpy(ln, "??");
+ pam_syslog (pamh, LOG_DEBUG, "Closing %d -> \"%s\"", i, ln);
+ }
+ close(i);
+ }
+ }
+ closedir(d);
+ }
+ else
+ {
+ for (i = STDERR_FILENO + 1; i < sysconf (_SC_OPEN_MAX); i++)
+ close (i);
+ }
if (call_setuid)
if (setuid (geteuid ()) == -1)