summaryrefslogtreecommitdiffstats
path: root/compat
diff options
context:
space:
mode:
authorNicholas Marriott <nicholas.marriott@gmail.com>2020-11-17 17:56:55 +0000
committerNicholas Marriott <nicholas.marriott@gmail.com>2020-11-17 17:57:21 +0000
commitbfdc4373d71895a5f454834da4b0bd92ab964dd4 (patch)
treee9c2968287d3766459d193d2fb612ebcfa295e82 /compat
parent3ee1addbb97fdbe3b7dc9f3c5a79c65c9595d449 (diff)
Update closefrom from OpenSSH for macOS code which is now needed.
Diffstat (limited to 'compat')
-rw-r--r--compat/closefrom.c94
1 files changed, 70 insertions, 24 deletions
diff --git a/compat/closefrom.c b/compat/closefrom.c
index 7915cde4..28be3680 100644
--- a/compat/closefrom.c
+++ b/compat/closefrom.c
@@ -14,6 +14,8 @@
* OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
*/
+#include "compat.h"
+
#ifndef HAVE_CLOSEFROM
#include <sys/types.h>
@@ -44,8 +46,9 @@
# include <ndir.h>
# endif
#endif
-
-#include "compat.h"
+#if defined(HAVE_LIBPROC_H)
+# include <libproc.h>
+#endif
#ifndef OPEN_MAX
# define OPEN_MAX 256
@@ -55,21 +58,73 @@
__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $";
#endif /* lint */
+#ifndef HAVE_FCNTL_CLOSEM
/*
* Close all file descriptors greater than or equal to lowfd.
*/
+static void
+closefrom_fallback(int lowfd)
+{
+ long fd, maxfd;
+
+ /*
+ * Fall back on sysconf() or getdtablesize(). We avoid checking
+ * resource limits since it is possible to open a file descriptor
+ * and then drop the rlimit such that it is below the open fd.
+ */
+#ifdef HAVE_SYSCONF
+ maxfd = sysconf(_SC_OPEN_MAX);
+#else
+ maxfd = getdtablesize();
+#endif /* HAVE_SYSCONF */
+ if (maxfd < 0)
+ maxfd = OPEN_MAX;
+
+ for (fd = lowfd; fd < maxfd; fd++)
+ (void) close((int) fd);
+}
+#endif /* HAVE_FCNTL_CLOSEM */
+
#ifdef HAVE_FCNTL_CLOSEM
void
closefrom(int lowfd)
{
(void) fcntl(lowfd, F_CLOSEM, 0);
}
-#else
+#elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO)
void
closefrom(int lowfd)
{
- long fd, maxfd;
-#if defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+ int i, r, sz;
+ pid_t pid = getpid();
+ struct proc_fdinfo *fdinfo_buf = NULL;
+
+ sz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0);
+ if (sz == 0)
+ return; /* no fds, really? */
+ else if (sz == -1)
+ goto fallback;
+ if ((fdinfo_buf = malloc(sz)) == NULL)
+ goto fallback;
+ r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz);
+ if (r < 0 || r > sz)
+ goto fallback;
+ for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) {
+ if (fdinfo_buf[i].proc_fd >= lowfd)
+ close(fdinfo_buf[i].proc_fd);
+ }
+ free(fdinfo_buf);
+ return;
+ fallback:
+ free(fdinfo_buf);
+ closefrom_fallback(lowfd);
+ return;
+}
+#elif defined(HAVE_DIRFD) && defined(HAVE_PROC_PID)
+void
+closefrom(int lowfd)
+{
+ long fd;
char fdpath[PATH_MAX], *endp;
struct dirent *dent;
DIR *dirp;
@@ -77,7 +132,7 @@ closefrom(int lowfd)
/* Check for a /proc/$$/fd directory. */
len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid());
- if (len > 0 && (size_t)len <= sizeof(fdpath) && (dirp = opendir(fdpath))) {
+ if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) {
while ((dent = readdir(dirp)) != NULL) {
fd = strtol(dent->d_name, &endp, 10);
if (dent->d_name != endp && *endp == '\0' &&
@@ -85,25 +140,16 @@ closefrom(int lowfd)
(void) close((int) fd);
}
(void) closedir(dirp);
- } else
-#endif
- {
- /*
- * Fall back on sysconf() or getdtablesize(). We avoid checking
- * resource limits since it is possible to open a file descriptor
- * and then drop the rlimit such that it is below the open fd.
- */
-#ifdef HAVE_SYSCONF
- maxfd = sysconf(_SC_OPEN_MAX);
-#else
- maxfd = getdtablesize();
-#endif /* HAVE_SYSCONF */
- if (maxfd < 0)
- maxfd = OPEN_MAX;
-
- for (fd = lowfd; fd < maxfd; fd++)
- (void) close((int) fd);
+ return;
}
+ /* /proc/$$/fd strategy failed, fall back to brute force closure */
+ closefrom_fallback(lowfd);
+}
+#else
+void
+closefrom(int lowfd)
+{
+ closefrom_fallback(lowfd);
}
#endif /* !HAVE_FCNTL_CLOSEM */
#endif /* HAVE_CLOSEFROM */