Make qrexec_client wait for its local child before exiting
If we do not wait and exit imemdiately, qrexec_daemon will decrease the children count and continue spawning processes, while e.g. qfile-daemon still waits for kdialog - so dom0 will be DoSed by multiple processes.
This commit is contained in:
parent
27cfd6111a
commit
769eedd33a
@ -26,6 +26,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
#include <ioall.h>
|
#include <ioall.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
#include "qrexec.h"
|
#include "qrexec.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "glue.h"
|
#include "glue.h"
|
||||||
@ -58,6 +59,18 @@ void do_exec(char *prog)
|
|||||||
|
|
||||||
int local_stdin_fd, local_stdout_fd;
|
int local_stdin_fd, local_stdout_fd;
|
||||||
|
|
||||||
|
void do_exit(int code)
|
||||||
|
{
|
||||||
|
int status;
|
||||||
|
// sever communication lines; wait for child, if any
|
||||||
|
// so that qrexec-daemon can count (recursively) spawned processes correctly
|
||||||
|
close(local_stdin_fd);
|
||||||
|
close(local_stdout_fd);
|
||||||
|
waitpid(-1, &status, 0);
|
||||||
|
exit(code);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void prepare_local_fds(char *cmdline)
|
void prepare_local_fds(char *cmdline)
|
||||||
{
|
{
|
||||||
int pid;
|
int pid;
|
||||||
@ -79,7 +92,7 @@ void send_cmdline(int s, int type, char *cmdline)
|
|||||||
if (!write_all(s, &hdr, sizeof(hdr))
|
if (!write_all(s, &hdr, sizeof(hdr))
|
||||||
|| !write_all(s, cmdline, hdr.len)) {
|
|| !write_all(s, cmdline, hdr.len)) {
|
||||||
perror("write daemon");
|
perror("write daemon");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -90,7 +103,7 @@ void handle_input(int s)
|
|||||||
ret = read(local_stdout_fd, buf, sizeof(buf));
|
ret = read(local_stdout_fd, buf, sizeof(buf));
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
perror("read");
|
perror("read");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
if (ret == 0) {
|
if (ret == 0) {
|
||||||
local_stdout_fd = -1;
|
local_stdout_fd = -1;
|
||||||
@ -98,7 +111,7 @@ void handle_input(int s)
|
|||||||
}
|
}
|
||||||
if (!write_all(s, buf, ret)) {
|
if (!write_all(s, buf, ret)) {
|
||||||
perror("write daemon");
|
perror("write daemon");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -110,15 +123,15 @@ void handle_daemon_data(int s)
|
|||||||
|
|
||||||
if (!read_all(s, &hdr, sizeof hdr)) {
|
if (!read_all(s, &hdr, sizeof hdr)) {
|
||||||
perror("read daemon");
|
perror("read daemon");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
if (hdr.len > MAX_DATA_CHUNK) {
|
if (hdr.len > MAX_DATA_CHUNK) {
|
||||||
fprintf(stderr, "client_header.len=%d\n", hdr.len);
|
fprintf(stderr, "client_header.len=%d\n", hdr.len);
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
if (!read_all(s, buf, hdr.len)) {
|
if (!read_all(s, buf, hdr.len)) {
|
||||||
perror("read daemon");
|
perror("read daemon");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
switch (hdr.type) {
|
switch (hdr.type) {
|
||||||
@ -127,7 +140,7 @@ void handle_daemon_data(int s)
|
|||||||
close(local_stdin_fd);
|
close(local_stdin_fd);
|
||||||
else if (!write_all(local_stdin_fd, buf, hdr.len)) {
|
else if (!write_all(local_stdin_fd, buf, hdr.len)) {
|
||||||
perror("write local stdout");
|
perror("write local stdout");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case MSG_SERVER_TO_CLIENT_STDERR:
|
case MSG_SERVER_TO_CLIENT_STDERR:
|
||||||
@ -136,13 +149,13 @@ void handle_daemon_data(int s)
|
|||||||
case MSG_SERVER_TO_CLIENT_EXIT_CODE:
|
case MSG_SERVER_TO_CLIENT_EXIT_CODE:
|
||||||
status = *(unsigned int *) buf;
|
status = *(unsigned int *) buf;
|
||||||
if (WIFEXITED(status))
|
if (WIFEXITED(status))
|
||||||
exit(WEXITSTATUS(status));
|
do_exit(WEXITSTATUS(status));
|
||||||
else
|
else
|
||||||
exit(255);
|
do_exit(255);
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
fprintf(stderr, "unknown msg %d\n", hdr.type);
|
fprintf(stderr, "unknown msg %d\n", hdr.type);
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -160,7 +173,7 @@ void handle_daemon_only_until_writable(s)
|
|||||||
|
|
||||||
if (select(s + 1, &rdset, &wrset, NULL, NULL) < 0) {
|
if (select(s + 1, &rdset, &wrset, NULL, NULL) < 0) {
|
||||||
perror("select");
|
perror("select");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
if (FD_ISSET(s, &rdset))
|
if (FD_ISSET(s, &rdset))
|
||||||
handle_daemon_data(s);
|
handle_daemon_data(s);
|
||||||
@ -183,7 +196,7 @@ void select_loop(int s)
|
|||||||
}
|
}
|
||||||
if (select(max + 1, &select_set, NULL, NULL, NULL) < 0) {
|
if (select(max + 1, &select_set, NULL, NULL, NULL) < 0) {
|
||||||
perror("select");
|
perror("select");
|
||||||
exit(1);
|
do_exit(1);
|
||||||
}
|
}
|
||||||
if (FD_ISSET(s, &select_set))
|
if (FD_ISSET(s, &select_set))
|
||||||
handle_daemon_data(s);
|
handle_daemon_data(s);
|
||||||
|
Loading…
Reference in New Issue
Block a user