From 28744182cf90e0073b76a9e98de58a47e688b2c4 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Fri, 30 Aug 2019 13:21:38 +1000 Subject: 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@ --- openbsd-compat/bsd-closefrom.c | 88 ++++++++++++++++++++++++++++++++---------- 1 file changed, 67 insertions(+), 21 deletions(-) (limited to 'openbsd-compat/bsd-closefrom.c') diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c index b56476a2d..8b9a56278 100644 --- a/openbsd-compat/bsd-closefrom.c +++ b/openbsd-compat/bsd-closefrom.c @@ -46,6 +46,9 @@ # include # endif #endif +#if defined(HAVE_LIBPROC_H) +# include +#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 */ -- cgit v1.2.3 From 368f1cc2fbd6ad10c66bc1b67c2c04aebf8a04a8 Mon Sep 17 00:00:00 2001 From: Damien Miller Date: Mon, 2 Sep 2019 10:28:42 +1000 Subject: fixed test in OSX closefrom() replacement from likan_999.student AT sina.com --- openbsd-compat/bsd-closefrom.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'openbsd-compat/bsd-closefrom.c') diff --git a/openbsd-compat/bsd-closefrom.c b/openbsd-compat/bsd-closefrom.c index 8b9a56278..8fadca2da 100644 --- a/openbsd-compat/bsd-closefrom.c +++ b/openbsd-compat/bsd-closefrom.c @@ -107,9 +107,9 @@ closefrom(int lowfd) if ((fdinfo_buf = malloc(sz)) == NULL) goto fallback; r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz); - if (r < 0 || r >= sz) + if (r < 0 || r > sz) goto fallback; - for (i = 0; i < sz / (int)PROC_PIDLISTFD_SIZE; i++) { + for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) { if (fdinfo_buf[i].proc_fd >= lowfd) close(fdinfo_buf[i].proc_fd); } -- cgit v1.2.3