From: Duncan Overbruck Date: Fri, 26 Jul 2019 15:01:54 +0000 (+0200) Subject: libopenbsd/closefrom.c: sync with sudo X-Git-Tag: v6.6~24 X-Git-Url: https://git.armaanb.net/?p=opendoas.git;a=commitdiff_plain;h=8cba47c99d1efa726801fac41c478f1712ab481a libopenbsd/closefrom.c: sync with sudo --- diff --git a/libopenbsd/closefrom.c b/libopenbsd/closefrom.c index ef7d611..8f66084 100644 --- a/libopenbsd/closefrom.c +++ b/libopenbsd/closefrom.c @@ -1,5 +1,8 @@ /* - * Copyright (c) 2004-2005 Todd C. Miller + * SPDX-License-Identifier: ISC + * + * Copyright (c) 2004-2005, 2007, 2010, 2012-2015, 2017-2018 + * Todd C. Miller * * Permission to use, copy, modify, and distribute this software for any * purpose with or without fee is hereby granted, provided that the above @@ -14,96 +17,121 @@ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. */ -#include "includes.h" +/* + * This is an open source non-commercial project. Dear PVS-Studio, please check it. + * PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com + */ + +#include #ifndef HAVE_CLOSEFROM #include -#include #include #include -#ifdef HAVE_FCNTL_H -# include -#endif -#include #include -#include -#include -#include -#ifdef HAVE_DIRENT_H -# include -# define NAMLEN(dirent) strlen((dirent)->d_name) +#include +#include +#ifdef HAVE_PSTAT_GETPROC +# include #else -# define dirent direct -# define NAMLEN(dirent) (dirent)->d_namlen -# ifdef HAVE_SYS_NDIR_H -# include -# endif -# ifdef HAVE_SYS_DIR_H -# include -# endif -# ifdef HAVE_NDIR_H -# include -# endif +# include #endif -#ifndef OPEN_MAX -# define OPEN_MAX 256 -#endif +#include "openbsd.h" -#if 0 -__unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $"; -#endif /* lint */ +#ifndef _POSIX_OPEN_MAX +# define _POSIX_OPEN_MAX 20 +#endif /* * Close all file descriptors greater than or equal to lowfd. + * This is the expensive (fallback) method. */ -#ifdef HAVE_FCNTL_CLOSEM -void -closefrom(int lowfd) +static void +closefrom_fallback(int lowfd) { - (void) fcntl(lowfd, F_CLOSEM, 0); -} + long fd, maxfd; + + /* + * Fall back on sysconf(_SC_OPEN_MAX). 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. + */ + maxfd = sysconf(_SC_OPEN_MAX); + if (maxfd < 0) + maxfd = _POSIX_OPEN_MAX; + + for (fd = lowfd; fd < maxfd; fd++) { +#ifdef __APPLE__ + /* Avoid potential libdispatch crash when we close its fds. */ + (void) fcntl((int) fd, F_SETFD, FD_CLOEXEC); #else + (void) close((int) fd); +#endif + } +} + +/* + * Close all file descriptors greater than or equal to lowfd. + * We try the fast way first, falling back on the slow method. + */ void closefrom(int lowfd) { - long fd, maxfd; -#if defined(HAVE_PROC_PID) - char fdpath[PATH_MAX], *endp; - struct dirent *dent; +#if defined(HAVE_PSTAT_GETPROC) + struct pst_status pstat; +#elif defined(HAVE_DIRFD) + const char *path; DIR *dirp; - int len; +#endif - /* 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))) { + /* Try the fast method first, if possible. */ +#if defined(HAVE_FCNTL_CLOSEM) + if (fcntl(lowfd, F_CLOSEM, 0) != -1) + return; +#endif +#if defined(HAVE_PSTAT_GETPROC) + /* + * EOVERFLOW is not a fatal error for the fields we use. + * See the "EOVERFLOW Error" section of pstat_getvminfo(3). + */ + if (pstat_getproc(&pstat, sizeof(pstat), 0, getpid()) != -1 || + errno == EOVERFLOW) { + int fd; + + for (fd = lowfd; fd <= pstat.pst_highestfd; fd++) + (void) close(fd); + return; + } +#elif defined(HAVE_DIRFD) + /* Use /proc/self/fd (or /dev/fd on macOS) if it exists. */ +# ifdef __APPLE__ + path = _PATH_DEV "fd"; +# else + path = "/proc/self/fd"; +# endif + if ((dirp = opendir(path)) != NULL) { + struct dirent *dent; while ((dent = readdir(dirp)) != NULL) { - fd = strtol(dent->d_name, &endp, 10); - if (dent->d_name != endp && *endp == '\0' && - fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) - (void) close((int) fd); + const char *errstr; + int fd = strtonum(dent->d_name, lowfd, INT_MAX, &errstr); + if (errstr == NULL && fd != dirfd(dirp)) { +# ifdef __APPLE__ + /* Avoid potential libdispatch crash when we close its fds. */ + (void) fcntl(fd, F_SETFD, FD_CLOEXEC); +# else + (void) close(fd); +# endif + } } (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; } +#endif /* HAVE_DIRFD */ + + /* Do things the slow way. */ + closefrom_fallback(lowfd); } -#endif /* !HAVE_FCNTL_CLOSEM */ + #endif /* HAVE_CLOSEFROM */