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 #include #include +#include /* * 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