dom0/qrexec: do not exit client before all data in both direction transfered

When qrexec_client cannot write to its stdout, this doesn't necessary mean that
there is no data in opposite direction.
Simple example is RPC service: when process in destination VM closes its stdin,
it can still send some data to triggering VM.
This commit is contained in:
Marek Marczykowski 2012-08-25 01:14:16 +02:00
parent 77b2758c93
commit c9a43f66ed

View File

@ -27,6 +27,7 @@
#include <unistd.h> #include <unistd.h>
#include <ioall.h> #include <ioall.h>
#include <sys/wait.h> #include <sys/wait.h>
#include <errno.h>
#include "qrexec.h" #include "qrexec.h"
#include "buffer.h" #include "buffer.h"
#include "glue.h" #include "glue.h"
@ -108,6 +109,10 @@ void handle_input(int s)
if (ret == 0) { if (ret == 0) {
local_stdout_fd = -1; local_stdout_fd = -1;
shutdown(s, SHUT_WR); shutdown(s, SHUT_WR);
if (local_stdin_fd == -1) {
// if pipe in opposite direction already closed, no need to stay alive
do_exit(0);
}
} }
if (!write_all(s, buf, ret)) { if (!write_all(s, buf, ret)) {
perror("write daemon"); perror("write daemon");
@ -136,11 +141,20 @@ void handle_daemon_data(int s)
switch (hdr.type) { switch (hdr.type) {
case MSG_SERVER_TO_CLIENT_STDOUT: case MSG_SERVER_TO_CLIENT_STDOUT:
if (hdr.len == 0) if (local_stdin_fd == -1)
break;
if (hdr.len == 0) {
close(local_stdin_fd); close(local_stdin_fd);
else if (!write_all(local_stdin_fd, buf, hdr.len)) { local_stdin_fd = -1;
perror("write local stdout"); } else if (!write_all(local_stdin_fd, buf, hdr.len)) {
do_exit(1); if (errno == EPIPE) {
// remote side have closed its stdin, handle data in oposite
// direction (if any) before exit
local_stdin_fd = -1;
} else {
perror("write local stdout");
do_exit(1);
}
} }
break; break;
case MSG_SERVER_TO_CLIENT_STDERR: case MSG_SERVER_TO_CLIENT_STDERR: