Implemented mechanism to trigger predefined execution in dom0.

Processes in AppVM can ask qrexec-agent to send a
MSG_AGENT_TO_SERVER_TRIGGER_EXEC message to qrexec-daemon.
The latter will execute predefined program. It is useful for
the purpose of file copy; the predefined program will create
a connected qfile-daemon<->qfile-agent pair.
This commit is contained in:
Rafal Wojtczuk 2011-03-10 15:41:31 +01:00
parent 8f90623661
commit f1a7df6e95
5 changed files with 96 additions and 2 deletions

View File

@ -25,6 +25,8 @@
#define REXEC_PORT 512
#define QREXEC_AGENT_TRIGGER_PATH "/var/run/qubes/qrexec_agent"
enum {
MSG_CLIENT_TO_SERVER_EXEC_CMDLINE = 0x100,
MSG_CLIENT_TO_SERVER_JUST_EXEC,
@ -40,12 +42,18 @@ enum {
MSG_AGENT_TO_SERVER_STDOUT,
MSG_AGENT_TO_SERVER_STDERR,
MSG_AGENT_TO_SERVER_EXIT_CODE,
MSG_AGENT_TO_SERVER_TRIGGER_EXEC,
MSG_SERVER_TO_CLIENT_STDOUT,
MSG_SERVER_TO_CLIENT_STDERR,
MSG_SERVER_TO_CLIENT_EXIT_CODE
};
enum {
QREXEC_EXECUTE_FILE_COPY=0x700,
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM
};
struct server_header {
unsigned int type;
unsigned int clid;

View File

@ -30,6 +30,7 @@
#include <string.h>
#include <pwd.h>
#include <grp.h>
#include <sys/stat.h>
#include "qrexec.h"
#include "buffer.h"
#include "glue.h"
@ -63,9 +64,16 @@ struct _process_fd process_fd[MAX_FDS];
/* indexed by client id, which is descriptor number of a client in daemon */
struct _client_info client_info[MAX_FDS];
int trigger_fd;
void init()
{
peer_server_init(REXEC_PORT);
umask(0);
mkfifo(QREXEC_AGENT_TRIGGER_PATH, 0666);
umask(077);
trigger_fd =
open(QREXEC_AGENT_TRIGGER_PATH, O_RDONLY | O_NONBLOCK);
}
void no_colon_in_cmd()
@ -418,6 +426,11 @@ int fill_fds_for_select(fd_set * rdset, fd_set * wrset)
FD_SET(i, rdset);
max = i;
}
FD_SET(trigger_fd, rdset);
if (trigger_fd > max)
max = trigger_fd;
for (i = 0; i < MAX_FDS; i++)
if (client_info[i].pid > 0 && client_info[i].is_blocked) {
fd = client_info[i].stdin_fd;
@ -446,6 +459,28 @@ void flush_client_data_agent(int clid)
}
}
void handle_trigger_io()
{
struct server_header s_hdr;
char buf[5];
s_hdr.clid = 0;
s_hdr.len = 0;
if (read(trigger_fd, buf, 4) == 4) {
buf[4] = 0;
if (!strcmp(buf, "FCPR"))
s_hdr.clid = QREXEC_EXECUTE_FILE_COPY;
else if (!strcmp(buf, "DVMR"))
s_hdr.clid = QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM;
if (s_hdr.clid) {
s_hdr.type = MSG_AGENT_TO_SERVER_TRIGGER_EXEC;
write_all_vchan_ext(&s_hdr, sizeof s_hdr);
}
}
close(trigger_fd);
trigger_fd =
open(QREXEC_AGENT_TRIGGER_PATH, O_RDONLY | O_NONBLOCK);
}
int main()
{
@ -469,6 +504,9 @@ int main()
while (read_ready_vchan_ext())
handle_server_data();
if (FD_ISSET(trigger_fd, &rdset))
handle_trigger_io();
handle_process_data_all(&rdset);
for (i = 0; i <= MAX_FDS; i++)
if (client_info[i].pid > 0

View File

@ -51,9 +51,11 @@ int server_fd;
void handle_usr1(int x)
{
exit(0);
exit(0);
}
char domain_id[64];
void init(int xid)
{
char dbg_log[256];
@ -63,6 +65,7 @@ void init(int xid)
fprintf(stderr, "domain id=0?\n");
exit(1);
}
snprintf(domain_id, sizeof(domain_id), "%d", xid);
signal(SIGUSR1, handle_usr1);
switch (fork()) {
case -1:
@ -71,7 +74,7 @@ void init(int xid)
case 0:
break;
default:
pause();
pause();
exit(0);
}
close(0);
@ -94,6 +97,7 @@ void init(int xid)
peer_client_init(xid, REXEC_PORT);
setuid(getuid());
signal(SIGPIPE, SIG_IGN);
signal(SIGCHLD, SIG_IGN);
signal(SIGUSR1, SIG_DFL);
kill(getppid(), SIGUSR1);
}
@ -242,6 +246,41 @@ void pass_to_client(int clid, struct client_header *hdr)
}
}
void handle_trigger_exec(int req)
{
char *rcmd = NULL, *lcmd = NULL;
int i;
switch (req) {
case QREXEC_EXECUTE_FILE_COPY:
rcmd = "directly:user:/usr/lib/qubes/qfile-agent";
lcmd = "/usr/lib/qubes/qfile-daemon";
break;
case QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM:
rcmd = "directly:user:/usr/lib/qubes/qfile-agent-dvm";
lcmd = "/usr/lib/qubes/qfile-daemon-dvm";
break;
default:
fprintf(stderr, "got trigger exec no %d\n", req);
exit(1);
}
switch (fork()) {
case -1:
perror("fork");
exit(1);
case 0:
break;
default:
return;
}
for (i = 3; i < 256; i++)
close(i);
signal(SIGCHLD, SIG_DFL);
execl("/usr/lib/qubes/qrexec_client", "qrexec_client", "-d",
domain_id, "-l", lcmd, rcmd, NULL);
perror("execl");
exit(1);
}
void handle_agent_data()
{
struct client_header hdr;
@ -251,6 +290,11 @@ void handle_agent_data()
// fprintf(stderr, "got %x %x %x\n", s_hdr.type, s_hdr.clid,
// s_hdr.len);
if (s_hdr.type == MSG_AGENT_TO_SERVER_TRIGGER_EXEC) {
handle_trigger_exec(s_hdr.clid);
return;
}
if (s_hdr.clid >= MAX_FDS || s_hdr.clid < 0) {
fprintf(stderr, "from agent: clid=%d\n", s_hdr.clid);
exit(1);

View File

@ -107,6 +107,7 @@ install -D ../u2mfn/u2mfn-kernel.h $RPM_BUILD_ROOT/usr/include/u2mfn-kernel.h
install -D ../vchan/libvchan.so $RPM_BUILD_ROOT/%{_libdir}/libvchan.so
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
mkdir -p $RPM_BUILD_ROOT/var/run/qubes
%triggerin -- initscripts
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
@ -227,6 +228,7 @@ rm -rf $RPM_BUILD_ROOT
/usr/include/libvchan.h
%{_libdir}/libvchan.so
%{_libdir}/libu2mfn.so
%dir /var/run/qubes
%package devel

View File

@ -83,6 +83,7 @@ cp ../common/vif-route-qubes $RPM_BUILD_ROOT/etc/xen/scripts
install -D ../vchan/libvchan.so $RPM_BUILD_ROOT/%{_libdir}/libvchan.so
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
mkdir -p $RPM_BUILD_ROOT/var/run/qubes
%triggerin -- initscripts
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
@ -193,3 +194,4 @@ rm -rf $RPM_BUILD_ROOT
%dir /var/run/qubes
%{_libdir}/libvchan.so
%{_libdir}/libu2mfn.so
%dir /var/run/qubes