Skip to content

Commit acda549

Browse files
committed
Use close_range() instead of close loop
This is both more correct (it avoids assuming an arbitrary maximum file descriptor value) and faster. If close_range() is not supported by the kernel or libc, fall back to the old code.
1 parent d9e3a76 commit acda549

File tree

1 file changed

+11
-8
lines changed

1 file changed

+11
-8
lines changed

libqrexec/exec.c

+11-8
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@
3030
#include <sys/types.h>
3131
#include <sys/socket.h>
3232
#include <sys/stat.h>
33+
#include <sys/syscall.h>
3334
#include <sys/un.h>
3435
#include <sys/wait.h>
3536
#include <netdb.h>
@@ -86,20 +87,22 @@ void fix_fds(int fdin, int fdout, int fderr)
8687
fdin, fdout, fderr);
8788
_exit(125);
8889
}
89-
int i;
90-
for (i = 3; i < 256; i++)
91-
if (i != fdin && i != fdout && i != fderr)
92-
close(i);
9390
if (dup2(fdin, 0) < 0 || dup2(fdout, 1) < 0 || dup2(fderr, 2) < 0) {
9491
PERROR("dup2");
9592
abort();
9693
}
97-
98-
if (close(fdin) || (fdin != fdout && close(fdout)) ||
99-
(fdin != fderr && fdout != fderr && fderr != 2 && close(fderr))) {
100-
PERROR("close");
94+
#ifdef SYS_close_range
95+
int close_range_res = syscall(SYS_close_range, 3, ~0U, 0);
96+
if (close_range_res == 0)
97+
return;
98+
assert(close_range_res == -1);
99+
if (errno != ENOSYS) {
100+
PERROR("close_range");
101101
abort();
102102
}
103+
#endif
104+
for (int i = 3; i < 256; ++i)
105+
close(i);
103106
}
104107

105108
static int do_fork_exec(const char *user,

0 commit comments

Comments
 (0)