Skip to content

Commit 611dda4

Browse files
committed
Use bsd_closefrom.c from openssh-portable to fix haskell#189
1 parent 484286a commit 611dda4

File tree

6 files changed

+180
-24
lines changed

6 files changed

+180
-24
lines changed

cbits/posix/bsd_closefrom.c

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

cbits/posix/close_fds.c

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,22 @@
1+
2+
#include "common.h"
3+
4+
#include <unistd.h>
5+
6+
#if defined(HAVE_CLOSERANGE)
7+
#include <linux/close_range.h>
8+
#endif
9+
10+
11+
void closefrom_excluding(int lowfd, int excludingFd) {
12+
#if defined(HAVE_CLOSERANGE)
13+
close_range(lowfd, excludingFd - 1);
14+
closefrom(excludingFd + 1);
15+
#else
16+
for (int i = lowfd; i < excludingFd; i++) {
17+
close(i);
18+
}
19+
20+
closefrom(excludingFd + 1);
21+
#endif
22+
}

cbits/posix/common.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,8 @@ struct std_handle {
2222
};
2323
};
2424

25-
int get_max_fd(void);
25+
void closefrom_excluding(int from, int excluding);
26+
void closefrom(int lowfd);
2627

2728
// defined in find_executable.c
2829
#if !defined(HAVE_EXECVPE)

cbits/posix/fork_exec.c

Lines changed: 1 addition & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -222,13 +222,7 @@ do_spawn_fork (char *const args[],
222222
setup_std_handle_fork(STDERR_FILENO, stdErrHdl, forkCommunicationFds[1]);
223223

224224
if ((flags & RUN_PROCESS_IN_CLOSE_FDS) != 0) {
225-
int max_fd = get_max_fd();
226-
// XXX Not the pipe
227-
for (int i = 3; i < max_fd; i++) {
228-
if (i != forkCommunicationFds[1]) {
229-
close(i);
230-
}
231-
}
225+
closefrom_excluding(3, forkCommunicationFds[1]);
232226
}
233227

234228
/* Reset the SIGINT/SIGQUIT signal handlers in the child, if requested

cbits/posix/runProcess.c

Lines changed: 0 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -21,22 +21,6 @@
2121
#include <signal.h>
2222
#endif
2323

24-
int
25-
get_max_fd()
26-
{
27-
static int cache = 0;
28-
if (cache == 0) {
29-
#if HAVE_SYSCONF
30-
cache = sysconf(_SC_OPEN_MAX);
31-
if (cache == -1) {
32-
cache = 256;
33-
}
34-
#else
35-
cache = 256;
36-
#endif
37-
}
38-
return cache;
39-
}
4024

4125
// If a process was terminated by a signal, the exit status we return
4226
// via the System.Process API is (-signum). This encoding avoids collision with

process.cabal

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -66,6 +66,8 @@ library
6666
else
6767
c-sources:
6868
cbits/posix/runProcess.c
69+
cbits/posix/bsd_closefrom.c
70+
cbits/posix/close_fds.c
6971
cbits/posix/fork_exec.c
7072
cbits/posix/posix_spawn.c
7173
cbits/posix/find_executable.c

0 commit comments

Comments
 (0)