summaryrefslogtreecommitdiff
path: root/openbsd-compat
diff options
context:
space:
mode:
authorDamien Miller <djm@mindrot.org>2019-08-30 13:21:38 +1000
committerDamien Miller <djm@mindrot.org>2019-08-30 13:23:04 +1000
commit28744182cf90e0073b76a9e98de58a47e688b2c4 (patch)
treeba8d283a447136b3b8cf9d8abdfcb1c4de3092cd /openbsd-compat
parentdc2ca588144f088a54febebfde3414568dc73d5f (diff)
proc_pidinfo()-based closefrom() for OS X
Refactor closefrom() to use a single brute-force close() loop fallback. Based on patch from likan_999.student@sina.com in bz#3049. ok dtucker@
Diffstat (limited to 'openbsd-compat')
-rw-r--r--openbsd-compat/bsd-closefrom.c88
1 files changed, 67 insertions, 21 deletions
diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c
index b56476a2..8b9a5627 100644
--- a/openbsd-compat/bsd-closefrom.c
+++ b/openbsd-compat/bsd-closefrom.c
@@ -46,6 +46,9 @@
# include <ndir.h>
# endif
#endif
+#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 < sz / (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;
@@ -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 */