1 /* 2 * Copyright (c) 2004-2005 Todd C. Miller <Todd.Miller@courtesan.com> 3 * 4 * Permission to use, copy, modify, and distribute this software for any 5 * purpose with or without fee is hereby granted, provided that the above 6 * copyright notice and this permission notice appear in all copies. 7 * 8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES 9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF 10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR 11 * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES 12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN 13 * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF 14 * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. 15 */ 16 17 #include "includes.h" 18 19 #if !defined(HAVE_CLOSEFROM) || defined(BROKEN_CLOSEFROM) 20 21 #include <sys/types.h> 22 #include <unistd.h> 23 #include <stdio.h> 24 #ifdef HAVE_FCNTL_H 25 # include <fcntl.h> 26 #endif 27 #include <limits.h> 28 #include <stdlib.h> 29 #include <stddef.h> 30 #include <string.h> 31 #include <unistd.h> 32 #ifdef HAVE_DIRENT_H 33 # include <dirent.h> 34 # define NAMLEN(dirent) strlen((dirent)->d_name) 35 #else 36 # define dirent direct 37 # define NAMLEN(dirent) (dirent)->d_namlen 38 # ifdef HAVE_SYS_NDIR_H 39 # include <sys/ndir.h> 40 # endif 41 # ifdef HAVE_SYS_DIR_H 42 # include <sys/dir.h> 43 # endif 44 # ifdef HAVE_NDIR_H 45 # include <ndir.h> 46 # endif 47 #endif 48 #if defined(HAVE_LIBPROC_H) 49 # include <libproc.h> 50 #endif 51 52 #ifndef OPEN_MAX 53 # define OPEN_MAX 256 54 #endif 55 56 #if 0 57 __unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $"; 58 #endif /* lint */ 59 60 #ifndef HAVE_FCNTL_CLOSEM 61 /* 62 * Close all file descriptors greater than or equal to lowfd. 63 */ 64 static void 65 closefrom_fallback(int lowfd) 66 { 67 long fd, maxfd; 68 69 /* 70 * Fall back on sysconf() or getdtablesize(). We avoid checking 71 * resource limits since it is possible to open a file descriptor 72 * and then drop the rlimit such that it is below the open fd. 73 */ 74 #ifdef HAVE_SYSCONF 75 maxfd = sysconf(_SC_OPEN_MAX); 76 #else 77 maxfd = getdtablesize(); 78 #endif /* HAVE_SYSCONF */ 79 if (maxfd < 0) 80 maxfd = OPEN_MAX; 81 82 for (fd = lowfd; fd < maxfd; fd++) 83 (void) close((int) fd); 84 } 85 #endif /* HAVE_FCNTL_CLOSEM */ 86 87 #ifdef HAVE_FCNTL_CLOSEM 88 void 89 closefrom(int lowfd) 90 { 91 (void) fcntl(lowfd, F_CLOSEM, 0); 92 } 93 #elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO) 94 void 95 closefrom(int lowfd) 96 { 97 int i, r, sz; 98 pid_t pid = getpid(); 99 struct proc_fdinfo *fdinfo_buf = NULL; 100 101 sz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); 102 if (sz == 0) 103 return; /* no fds, really? */ 104 else if (sz == -1) 105 goto fallback; 106 if ((fdinfo_buf = malloc(sz)) == NULL) 107 goto fallback; 108 r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz); 109 if (r < 0 || r > sz) 110 goto fallback; 111 for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) { 112 if (fdinfo_buf[i].proc_fd >= lowfd) 113 close(fdinfo_buf[i].proc_fd); 114 } 115 free(fdinfo_buf); 116 return; 117 fallback: 118 free(fdinfo_buf); 119 closefrom_fallback(lowfd); 120 return; 121 } 122 #elif defined(HAVE_DIRFD) && defined(HAVE_PROC_PID) 123 void 124 closefrom(int lowfd) 125 { 126 long fd; 127 char fdpath[PATH_MAX], *endp; 128 struct dirent *dent; 129 DIR *dirp; 130 int len; 131 132 #ifdef HAVE_CLOSE_RANGE 133 if (close_range(lowfd, INT_MAX, 0) == 0) 134 return; 135 #endif 136 137 /* Check for a /proc/$$/fd directory. */ 138 len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid()); 139 if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) { 140 while ((dent = readdir(dirp)) != NULL) { 141 fd = strtol(dent->d_name, &endp, 10); 142 if (dent->d_name != endp && *endp == '\0' && 143 fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) 144 (void) close((int) fd); 145 } 146 (void) closedir(dirp); 147 return; 148 } 149 /* /proc/$$/fd strategy failed, fall back to brute force closure */ 150 closefrom_fallback(lowfd); 151 } 152 #else 153 void 154 closefrom(int lowfd) 155 { 156 closefrom_fallback(lowfd); 157 } 158 #endif /* !HAVE_FCNTL_CLOSEM */ 159 #endif /* HAVE_CLOSEFROM */ 160