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