13
0

close all open fd's on fork

This commit is contained in:
Robin Gareus 2013-06-07 20:50:59 +02:00
parent fd5f1ef5f5
commit b26cc12513

View File

@ -1,5 +1,6 @@
/*
Copyright (C) 2010 Paul Davis
Copyright 2005-2008 Lennart Poettering
Author: Robin Gareus <robin@gareus.org>
This program is free software; you can redistribute it and/or modify
@ -23,6 +24,9 @@
#include <errno.h>
#include <unistd.h>
#include <assert.h>
#include <dirent.h>
#ifdef __WIN32__
#include <windows.h>
#else
@ -31,8 +35,11 @@
#include <sys/wait.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <sys/time.h>
#include <sys/resource.h>
#endif
#include "system_exec.h"
using namespace std;
@ -40,6 +47,104 @@ void * interposer_thread (void *arg);
static void close_fd (int& fd) { if (fd >= 0) ::close (fd); fd = -1; }
#ifndef __WIN32__
/*
* This function was part of libasyncns.
* LGPL v2.1
* Copyright 2005-2008 Lennart Poettering
*/
static int close_allv(const int except_fds[]) {
struct rlimit rl;
int fd;
#ifdef __linux__
DIR *d;
assert(except_fds);
if ((d = opendir("/proc/self/fd"))) {
struct dirent *de;
while ((de = readdir(d))) {
int found;
long l;
char *e = NULL;
int i;
if (de->d_name[0] == '.')
continue;
errno = 0;
l = strtol(de->d_name, &e, 10);
if (errno != 0 || !e || *e) {
closedir(d);
errno = EINVAL;
return -1;
}
fd = (int) l;
if ((long) fd != l) {
closedir(d);
errno = EINVAL;
return -1;
}
if (fd < 3)
continue;
if (fd == dirfd(d))
continue;
found = 0;
for (i = 0; except_fds[i] >= 0; i++)
if (except_fds[i] == fd) {
found = 1;
break;
}
if (found) continue;
if (close(fd) < 0) {
int saved_errno;
saved_errno = errno;
closedir(d);
errno = saved_errno;
return -1;
}
}
closedir(d);
return 0;
}
#endif
if (getrlimit(RLIMIT_NOFILE, &rl) < 0)
return -1;
for (fd = 0; fd < (int) rl.rlim_max; fd++) {
int i;
if (fd <= 3)
continue;
for (i = 0; except_fds[i] >= 0; i++)
if (except_fds[i] == fd)
continue;
if (close(fd) < 0 && errno != EBADF)
return -1;
}
return 0;
}
#endif /* not on windows */
SystemExec::SystemExec (std::string c, std::string a)
: cmd(c)
{
@ -619,6 +724,11 @@ SystemExec::start (int stderr_mode)
signal(SIGPIPE, SIG_DFL);
#endif
#ifndef __WIN32__
int good_fds[1] = { 0 };
close_allv(good_fds);
#endif
::execve(argp[0], argp, envp);
/* if we reach here something went wrong.. */
char buf = 0;