Skip to content

Commit

Permalink
Don't close file descriptor 0
Browse files Browse the repository at this point in the history
Also save some FD manipulation during process_io().
  • Loading branch information
DemiMarie committed Apr 11, 2024
1 parent f1370c5 commit b4a2de9
Show file tree
Hide file tree
Showing 2 changed files with 52 additions and 40 deletions.
38 changes: 25 additions & 13 deletions daemon/qrexec-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -327,7 +327,6 @@ static void init(int xid)
}
}

close(0);

if (!opt_direct) {
snprintf(qrexec_error_log_name, sizeof(qrexec_error_log_name),
Expand Down Expand Up @@ -625,25 +624,26 @@ static void handle_cmdline_message_from_client(int fd)

static void handle_client_hello(int fd)
{
struct msg_header hdr;
struct peer_info info;

if (!read_all(fd, &hdr, sizeof hdr)) {
struct {
struct msg_header hdr;
struct peer_info info;
} data;
_Static_assert(sizeof data == sizeof(data.hdr) + sizeof(data.info),
"unexpected padding");

if (!read_all(fd, &data, sizeof data)) {
terminate_client(fd);
return;
}
if (hdr.type != MSG_HELLO || hdr.len != sizeof(info)) {
if (data.hdr.type != MSG_HELLO || data.hdr.len != sizeof(data.info)) {
LOG(ERROR, "Invalid HELLO packet received from client %d: "
"type %d, len %d", fd, hdr.type, hdr.len);
"type %d, len %d", fd, data.hdr.type, data.hdr.len);
terminate_client(fd);
return;
}
if (!read_all(fd, &info, sizeof info)) {
terminate_client(fd);
return;
}
if (info.version != QREXEC_PROTOCOL_VERSION) {
LOG(ERROR, "Incompatible client protocol version (remote %d, local %d)", info.version, QREXEC_PROTOCOL_VERSION);
if (data.info.version != QREXEC_PROTOCOL_VERSION) {
LOG(ERROR, "Incompatible client protocol version (remote %d, local %d)",
data.info.version, QREXEC_PROTOCOL_VERSION);
terminate_client(fd);
return;
}
Expand Down Expand Up @@ -1484,6 +1484,18 @@ int main(int argc, char **argv)
int i, opt;
sigset_t selectmask;

{
int null_fd = open("/dev/null", O_RDONLY|O_NOCTTY);
if (null_fd < 0)
err(1, "open(%s)", "/dev/null");
if (null_fd > 0) {
if (dup2(null_fd, 0) != 0)
err(1, "dup2(%d, 0)", null_fd);
if (null_fd > 2 && close(null_fd) != 0)
err(1, "close(%d)", null_fd);
}
}

setup_logging("qrexec-daemon");

while ((opt=getopt_long(argc, argv, "hqp:D", longopts, NULL)) != -1) {
Expand Down
54 changes: 27 additions & 27 deletions libqrexec/process_io.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,36 +47,40 @@ static _Noreturn void handle_vchan_error(const char *op)
* don't care, because we created it)
*/

static void close_stdin(int fd, bool restore_block) {
static void close_stdin(int fd, bool restore_block, bool close_fd) {
if (fd == -1)
return;

if (restore_block)
set_block(fd);

if (fd == 1) {
close(fd);
} else if (shutdown(fd, SHUT_WR) == -1) {
if (errno == ENOTSOCK)
if (close_fd)
close(fd);
else
} else if (shutdown(fd, SHUT_WR) == -1) {
if (errno == ENOTSOCK) {
if (close_fd)
close(fd);
} else
PERROR("shutdown close_stdin");
}
}

static void close_stdout(int fd, bool restore_block) {
static void close_stdout(int fd, bool restore_block, bool close_fd) {
if (fd == -1)
return;

if (restore_block)
set_block(fd);

if (fd == 0) {
close(fd);
} else if (shutdown(fd, SHUT_RD) == -1) {
if (errno == ENOTSOCK)
if (close_fd)
close(fd);
else
} else if (shutdown(fd, SHUT_RD) == -1) {
if (errno == ENOTSOCK) {
if (close_fd)
close(fd);
} else
PERROR("shutdown close_stdout");
}
}
Expand Down Expand Up @@ -117,7 +121,7 @@ int process_io(const struct process_io_request *req) {
pid_t local_status = -1;
pid_t remote_status = -1;
int stdout_msg_type = is_service ? MSG_DATA_STDOUT : MSG_DATA_STDIN;
bool use_stdio_socket = false;
bool use_stdio_socket = stdin_fd == stdout_fd;

int ret;
struct pollfd fds[FD_NUM];
Expand All @@ -134,8 +138,6 @@ int process_io(const struct process_io_request *req) {
set_nonblock(stdin_fd);
if (stdout_fd != stdin_fd)
set_nonblock(stdout_fd);
else if ((stdout_fd = fcntl(stdin_fd, F_DUPFD_CLOEXEC, 3)) < 0)
abort(); // not worth handling running out of file descriptors
if (stderr_fd >= 0)
set_nonblock(stderr_fd);

Expand All @@ -149,7 +151,7 @@ int process_io(const struct process_io_request *req) {
else
local_status = WEXITSTATUS(status);
if (stdin_fd >= 0) {
close_stdin(stdin_fd, !use_stdio_socket);
close_stdin(stdin_fd, !use_stdio_socket, stdin_fd != stdout_fd);
stdin_fd = -1;
}
}
Expand Down Expand Up @@ -194,14 +196,12 @@ int process_io(const struct process_io_request *req) {
}

/* child signaled desire to use single socket for both stdin and stdout */
if (sigusr1 && *sigusr1) {
if (sigusr1 && *sigusr1 && stdin_fd != stdout_fd) {
if (stdout_fd != -1) {
do
errno = 0;
while (dup3(stdin_fd, stdout_fd, O_CLOEXEC) &&
(errno == EINTR || errno == EBUSY));
// other errors are fatal
if (errno) {
while (dup3(stdin_fd, stdout_fd, O_CLOEXEC) == -1) {
if (errno == EINTR || errno == EBUSY)
continue;
// other errors are fatal
PERROR("dup3");
abort();
}
Expand Down Expand Up @@ -265,7 +265,7 @@ int process_io(const struct process_io_request *req) {
handle_vchan_error("wait");

if (stdin_fd >= 0 && fds[FD_STDIN].revents & (POLLHUP | POLLERR)) {
close_stdin(stdin_fd, !use_stdio_socket);
close_stdin(stdin_fd, !use_stdio_socket, stdin_fd != stdout_fd);
stdin_fd = -1;
}

Expand All @@ -282,15 +282,15 @@ int process_io(const struct process_io_request *req) {
handle_vchan_error("read");
break;
case REMOTE_EOF:
close_stdin(stdin_fd, !use_stdio_socket);
close_stdin(stdin_fd, !use_stdio_socket, stdin_fd != stdout_fd);
stdin_fd = -1;
break;
case REMOTE_EXITED:
/* Remote process exited, we don't need any more data from
* local FDs. However, don't exit yet, because there might
* still be some data in stdin_buf waiting to be flushed.
*/
close_stdout(stdout_fd, !use_stdio_socket);
close_stdout(stdout_fd, !use_stdio_socket, stdin_fd != stdout_fd);
stdout_fd = -1;
close_stderr(stderr_fd);
stderr_fd = -1;
Expand All @@ -304,7 +304,7 @@ int process_io(const struct process_io_request *req) {
handle_vchan_error("send(handle_input stdout)");
break;
case REMOTE_EOF:
close_stdout(stdout_fd, !use_stdio_socket);
close_stdout(stdout_fd, !use_stdio_socket, stdin_fd != stdout_fd);
stdout_fd = -1;
break;
}
Expand All @@ -325,8 +325,8 @@ int process_io(const struct process_io_request *req) {
}
/* make sure that all the pipes/sockets are closed, so the child process
* (if any) will know that the connection is terminated */
close_stdin(stdin_fd, true);
close_stdout(stdout_fd, true);
close_stdin(stdin_fd, true, stdin_fd != stdout_fd);
close_stdout(stdout_fd, true, true);
close_stderr(stderr_fd);

/* wait for local process, in case we exited early */
Expand Down

0 comments on commit b4a2de9

Please sign in to comment.