Skip to content

Commit 76790cb

Browse files
committed
Avoid leaking vchans
Leaking vchans will cause Xenstore entries to also leak, which is bad. If it happens in a VM it will cause quota problems, while if it happens in dom0 it will just slow down Xenstore.
1 parent e06514b commit 76790cb

File tree

4 files changed

+20
-14
lines changed

4 files changed

+20
-14
lines changed

daemon/qrexec-client.c

+1
Original file line numberDiff line numberDiff line change
@@ -292,6 +292,7 @@ int main(int argc, char **argv)
292292
if (qubes_wait_for_vchan_connection_with_timeout(
293293
data_vchan, fd, true, connection_timeout) < 0) {
294294
LOG(ERROR, "qrexec connection timeout");
295+
libvchan_close(data_vchan);
295296
rc = QREXEC_EXIT_PROBLEM;
296297
goto cleanup;
297298
}

daemon/qrexec-daemon-common.c

+14-11
Original file line numberDiff line numberDiff line change
@@ -479,6 +479,7 @@ int run_qrexec_to_dom0(const struct service_params *svc_params,
479479
if (qubes_wait_for_vchan_connection_with_timeout(
480480
data_vchan, wait_fd, false, connection_timeout) < 0) {
481481
LOG(ERROR, "qrexec connection timeout");
482+
libvchan_close(data_vchan);
482483
return QREXEC_EXIT_PROBLEM;
483484
}
484485

@@ -496,23 +497,25 @@ int run_qrexec_to_dom0(const struct service_params *svc_params,
496497

497498
int handshake_and_go(struct handshake_params *params)
498499
{
500+
int rc = QREXEC_EXIT_PROBLEM;
499501
if (params->data_vchan == NULL || !libvchan_is_open(params->data_vchan)) {
500502
LOG(ERROR, "Failed to open data vchan connection");
501-
return QREXEC_EXIT_PROBLEM;
503+
goto cleanup;
502504
}
503-
int rc;
504505
int data_protocol_version = handle_agent_handshake(params->data_vchan,
505506
params->remote_send_first);
506-
if (data_protocol_version < 0) {
507-
rc = QREXEC_EXIT_PROBLEM;
508-
} else if (params->prepare_ret != 0) {
509-
rc = params->prepare_ret == -1 ? QREXEC_EXIT_SERVICE_NOT_FOUND : QREXEC_EXIT_PROBLEM;
510-
handle_failed_exec(params->data_vchan, params->remote_send_first, rc);
511-
} else {
512-
params->data_protocol_version = data_protocol_version;
513-
rc = select_loop(params);
507+
if (data_protocol_version >= 0) {
508+
if (params->prepare_ret != 0) {
509+
rc = params->prepare_ret == -1 ? QREXEC_EXIT_SERVICE_NOT_FOUND : QREXEC_EXIT_PROBLEM;
510+
handle_failed_exec(params->data_vchan, params->remote_send_first, rc);
511+
} else {
512+
params->data_protocol_version = data_protocol_version;
513+
rc = select_loop(params);
514+
}
514515
}
515-
libvchan_close(params->data_vchan);
516+
cleanup:
517+
if (params->data_vchan != NULL)
518+
libvchan_close(params->data_vchan);
516519
params->data_vchan = NULL;
517520
return rc;
518521
}

libqrexec/exec.c

+4-2
Original file line numberDiff line numberDiff line change
@@ -120,12 +120,14 @@ static int do_fork_exec(const char *user,
120120
(stderr_fd && socketpair(AF_UNIX, SOCK_STREAM, 0, errpipe)) ||
121121
socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, statuspipe)) {
122122
PERROR("socketpair");
123-
exit(1);
123+
/* FD leaks do not matter, we exit soon anyway */
124+
return -2;
124125
}
125126
switch (*pid = fork()) {
126127
case -1:
127128
PERROR("fork");
128-
exit(-1);
129+
/* ditto */
130+
return -2;
129131
case 0: {
130132
int status;
131133
if (signal(SIGPIPE, SIG_DFL) == SIG_ERR)

libqrexec/libqrexec-utils.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -182,7 +182,7 @@ int execute_parsed_qubes_rpc_command(
182182
*/
183183
__attribute__((visibility("default")))
184184
int find_qrexec_service(
185-
const struct qrexec_parsed_command *cmd,
185+
struct qrexec_parsed_command *cmd,
186186
int *socket_fd, struct buffer *stdin_buffer);
187187

188188
/** Suggested buffer size for the path buffer of find_qrexec_service. */

0 commit comments

Comments
 (0)