a46dbe
diff -up Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c
a46dbe
--- Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c.fds-closing	2017-02-10 11:10:15.000000000 +0100
a46dbe
+++ Linux-PAM-1.3.1/libpam/pam_modutil_sanitize.c	2019-10-16 16:07:31.259021159 +0200
a46dbe
@@ -10,6 +10,7 @@
a46dbe
 #include <fcntl.h>
a46dbe
 #include <syslog.h>
a46dbe
 #include <sys/resource.h>
a46dbe
+#include <dirent.h>
a46dbe
 
a46dbe
 /*
a46dbe
  * Creates a pipe, closes its write end, redirects fd to its read end.
a46dbe
@@ -116,27 +117,45 @@ redirect_out(pam_handle_t *pamh, enum pa
a46dbe
 static void
a46dbe
 close_fds(void)
a46dbe
 {
a46dbe
+	DIR *dir = NULL;
a46dbe
+	struct dirent *dent;
a46dbe
+	int dfd = -1;
a46dbe
+	int fd;
a46dbe
+	struct rlimit rlim;
a46dbe
+
a46dbe
 	/*
a46dbe
 	 * An arbitrary upper limit for the maximum file descriptor number
a46dbe
 	 * returned by RLIMIT_NOFILE.
a46dbe
 	 */
a46dbe
-	const int MAX_FD_NO = 65535;
a46dbe
+	const unsigned int MAX_FD_NO = 65535;
a46dbe
 
a46dbe
 	/* The lower limit is the same as for _POSIX_OPEN_MAX. */
a46dbe
-	const int MIN_FD_NO = 20;
a46dbe
+	const unsigned int MIN_FD_NO = 20;
a46dbe
 
a46dbe
-	int fd;
a46dbe
-	struct rlimit rlim;
a46dbe
-
a46dbe
-	if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
a46dbe
-		fd = MAX_FD_NO;
a46dbe
-	else if (rlim.rlim_max < MIN_FD_NO)
a46dbe
-		fd = MIN_FD_NO;
a46dbe
-	else
a46dbe
-		fd = rlim.rlim_max - 1;
a46dbe
+	/* If /proc is mounted, we can optimize which fd can be closed. */
a46dbe
+	if ((dir = opendir("/proc/self/fd")) != NULL) {
a46dbe
+		if ((dfd = dirfd(dir)) >= 0) {
a46dbe
+			while ((dent = readdir(dir)) != NULL) {
a46dbe
+				fd = atoi(dent->d_name);
a46dbe
+				if (fd > STDERR_FILENO && fd != dfd)
a46dbe
+					close(fd);
a46dbe
+			}
a46dbe
+		}
a46dbe
+		closedir(dir);
a46dbe
+	}
a46dbe
+
a46dbe
+	/* If /proc isn't available, fallback to the previous behavior. */
a46dbe
+	if (dfd < 0) {
a46dbe
+		if (getrlimit(RLIMIT_NOFILE, &rlim) || rlim.rlim_max > MAX_FD_NO)
a46dbe
+			fd = MAX_FD_NO;
a46dbe
+		else if (rlim.rlim_max < MIN_FD_NO)
a46dbe
+			fd = MIN_FD_NO;
a46dbe
+		else
a46dbe
+			fd = rlim.rlim_max - 1;
a46dbe
 
a46dbe
-	for (; fd > STDERR_FILENO; --fd)
a46dbe
-		close(fd);
a46dbe
+		for (; fd > STDERR_FILENO; --fd)
a46dbe
+			close(fd);
a46dbe
+	}
a46dbe
 }
a46dbe
 
a46dbe
 int