noux: close files marked with the 'close_on_execve' flag on 'execve()'

Fixes #2660
This commit is contained in:
Christian Prochaska 2018-01-30 16:39:41 +01:00 committed by Norman Feske
parent c7d1a9e270
commit 584aaec2a5
6 changed files with 46 additions and 23 deletions

View File

@ -155,7 +155,8 @@ struct Noux::Sysio
enum Fcntl_cmd {
FCNTL_CMD_GET_FILE_STATUS_FLAGS,
FCNTL_CMD_SET_FILE_STATUS_FLAGS,
FCNTL_CMD_SET_FD_FLAGS
FCNTL_CMD_SET_FD_FLAGS,
FCNTL_CMD_GET_FD_FLAGS
};
/**

View File

@ -1595,14 +1595,8 @@ namespace {
}
case F_GETFD:
/*
* Normally, we would return the file-descriptor flags.
*
* XXX: FD_CLOEXEC not yet supported
*/
if (verbose)
warning("fcntl(F_GETFD) not implemented, returning 0");
return 0;
sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_GET_FD_FLAGS;
break;
case F_SETFD:
sysio()->fcntl_in.cmd = Noux::Sysio::FCNTL_CMD_SET_FD_FLAGS;

View File

@ -243,11 +243,15 @@ class Noux::Child : public Rpc_object<Session>,
/**
* Let specified child inherit our file descriptors
*/
void _assign_io_channels_to(Child *child)
void _assign_io_channels_to(Child *child, bool skip_when_close_on_execve_set)
{
for (int fd = 0; fd < MAX_FILE_DESCRIPTORS; fd++)
if (fd_in_use(fd))
if (fd_in_use(fd)) {
if (skip_when_close_on_execve_set && close_fd_on_execve(fd))
continue;
child->add_io_channel(io_channel_by_fd(fd), fd);
child->close_fd_on_execve(fd, close_fd_on_execve(fd));
}
}
/**
@ -536,7 +540,7 @@ class Noux::Child : public Rpc_object<Session>,
false,
_destruct_queue);
_assign_io_channels_to(child);
_assign_io_channels_to(child, true);
/* move the signal queue */
while (!_pending_signals.empty())

View File

@ -30,6 +30,7 @@ class Noux::File_descriptor_registry
struct {
bool allocated;
bool close_on_execve;
Shared_pointer<Io_channel> io_channel;
} _fds[MAX_FILE_DESCRIPTORS];
@ -51,14 +52,16 @@ class Noux::File_descriptor_registry
void _assign_fd(int fd, Shared_pointer<Io_channel> &io_channel)
{
_fds[fd].io_channel = io_channel;
_fds[fd].allocated = true;
_fds[fd].io_channel = io_channel;
_fds[fd].allocated = true;
_fds[fd].close_on_execve = false;
}
void _reset_fd(int fd)
{
_fds[fd].io_channel = Shared_pointer<Io_channel>();
_fds[fd].allocated = false;
_fds[fd].io_channel = Shared_pointer<Io_channel>();
_fds[fd].allocated = false;
_fds[fd].close_on_execve = false;
}
public:
@ -110,6 +113,24 @@ class Noux::File_descriptor_registry
return _fds[fd].io_channel;
}
void close_fd_on_execve(int fd, bool close_on_execve)
{
if (!_valid_fd(fd))
error("file descriptor ", fd, " is out of range");
else
_fds[fd].close_on_execve = close_on_execve;
}
bool close_fd_on_execve(int fd)
{
if (!_valid_fd(fd)) {
error("file descriptor ", fd, " is out of range");
return false;
}
return _fds[fd].close_on_execve;
}
virtual void flush()
{
/* close all file descriptors */

View File

@ -68,10 +68,6 @@ class Noux::Io_channel : public Reference_counter
public:
bool close_on_execve;
Io_channel() : close_on_execve(false) { }
virtual ~Io_channel() { }
virtual Io_channel_backend *backend() { return nullptr; }

View File

@ -171,8 +171,15 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_SET_FD_FLAGS) {
/* we assume that there is only the close-on-execve flag */
_lookup_channel(_sysio.fcntl_in.fd)->close_on_execve =
!!_sysio.fcntl_in.long_arg;
close_fd_on_execve(_sysio.fcntl_in.fd, !!_sysio.fcntl_in.long_arg);
result = true;
break;
}
if (_sysio.fcntl_in.cmd == Sysio::FCNTL_CMD_GET_FD_FLAGS) {
/* we assume that there is only the close-on-execve flag */
_sysio.fcntl_out.result = close_fd_on_execve(_sysio.fcntl_in.fd);
result = true;
break;
}
@ -556,7 +563,7 @@ bool Noux::Child::syscall(Noux::Session::Syscall sc)
Family_member::insert(child);
_assign_io_channels_to(child);
_assign_io_channels_to(child, false);
/* copy our address space into the new child */
try {