File pam-restrict-number-fds-to-close.patch of Package pam.14449

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)
openSUSE Build Service is sponsored by