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 #ifndef HAVE_CLOSEFROM 20 21 #include <sys/types.h> 22 #include <sys/param.h> 23 #include <unistd.h> 24 #include <stdio.h> 25 #ifdef HAVE_FCNTL_H 26 # include <fcntl.h> 27 #endif 28 #include <limits.h> 29 #include <stdlib.h> 30 #include <stddef.h> 31 #include <string.h> 32 #include <unistd.h> 33 #ifdef HAVE_DIRENT_H 34 # include <dirent.h> 35 # define NAMLEN(dirent) strlen((dirent)->d_name) 36 #else 37 # define dirent direct 38 # define NAMLEN(dirent) (dirent)->d_namlen 39 # ifdef HAVE_SYS_NDIR_H 40 # include <sys/ndir.h> 41 # endif 42 # ifdef HAVE_SYS_DIR_H 43 # include <sys/dir.h> 44 # endif 45 # ifdef HAVE_NDIR_H 46 # include <ndir.h> 47 # endif 48 #endif 49 #if defined(HAVE_LIBPROC_H) 50 # include <libproc.h> 51 #endif 52 53 #ifndef OPEN_MAX 54 # define OPEN_MAX 256 55 #endif 56 57 #if 0 58 __unused static const char rcsid[] = "$Sudo: closefrom.c,v 1.11 2006/08/17 15:26:54 millert Exp $"; 59 #endif /* lint */ 60 61 #ifndef HAVE_FCNTL_CLOSEM 62 /* 63 * Close all file descriptors greater than or equal to lowfd. 64 */ 65 static void 66 closefrom_fallback(int lowfd) 67 { 68 long fd, maxfd; 69 70 /* 71 * Fall back on sysconf() or getdtablesize(). We avoid checking 72 * resource limits since it is possible to open a file descriptor 73 * and then drop the rlimit such that it is below the open fd. 74 */ 75 #ifdef HAVE_SYSCONF 76 maxfd = sysconf(_SC_OPEN_MAX); 77 #else 78 maxfd = getdtablesize(); 79 #endif /* HAVE_SYSCONF */ 80 if (maxfd < 0) 81 maxfd = OPEN_MAX; 82 83 for (fd = lowfd; fd < maxfd; fd++) 84 (void) close((int) fd); 85 } 86 #endif /* HAVE_FCNTL_CLOSEM */ 87 88 #ifdef HAVE_FCNTL_CLOSEM 89 void 90 closefrom(int lowfd) 91 { 92 (void) fcntl(lowfd, F_CLOSEM, 0); 93 } 94 #elif defined(HAVE_LIBPROC_H) && defined(HAVE_PROC_PIDINFO) 95 void 96 closefrom(int lowfd) 97 { 98 int i, r, sz; 99 pid_t pid = getpid(); 100 struct proc_fdinfo *fdinfo_buf = NULL; 101 102 sz = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, NULL, 0); 103 if (sz == 0) 104 return; /* no fds, really? */ 105 else if (sz == -1) 106 goto fallback; 107 if ((fdinfo_buf = malloc(sz)) == NULL) 108 goto fallback; 109 r = proc_pidinfo(pid, PROC_PIDLISTFDS, 0, fdinfo_buf, sz); 110 if (r < 0 || r > sz) 111 goto fallback; 112 for (i = 0; i < r / (int)PROC_PIDLISTFD_SIZE; i++) { 113 if (fdinfo_buf[i].proc_fd >= lowfd) 114 close(fdinfo_buf[i].proc_fd); 115 } 116 free(fdinfo_buf); 117 return; 118 fallback: 119 free(fdinfo_buf); 120 closefrom_fallback(lowfd); 121 return; 122 } 123 #elif defined(HAVE_DIRFD) && defined(HAVE_PROC_PID) 124 void 125 closefrom(int lowfd) 126 { 127 long fd; 128 char fdpath[PATH_MAX], *endp; 129 struct dirent *dent; 130 DIR *dirp; 131 int len; 132 133 /* Check for a /proc/$$/fd directory. */ 134 len = snprintf(fdpath, sizeof(fdpath), "/proc/%ld/fd", (long)getpid()); 135 if (len > 0 && (size_t)len < sizeof(fdpath) && (dirp = opendir(fdpath))) { 136 while ((dent = readdir(dirp)) != NULL) { 137 fd = strtol(dent->d_name, &endp, 10); 138 if (dent->d_name != endp && *endp == '\0' && 139 fd >= 0 && fd < INT_MAX && fd >= lowfd && fd != dirfd(dirp)) 140 (void) close((int) fd); 141 } 142 (void) closedir(dirp); 143 return; 144 } 145 /* /proc/$$/fd strategy failed, fall back to brute force closure */ 146 closefrom_fallback(lowfd); 147 } 148 #else 149 void 150 closefrom(int lowfd) 151 { 152 closefrom_fallback(lowfd); 153 } 154 #endif /* !HAVE_FCNTL_CLOSEM */ 155 #endif /* HAVE_CLOSEFROM */ 156