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:
parent
8f90623661
commit
f1a7df6e95
@ -25,6 +25,8 @@
|
|||||||
|
|
||||||
#define REXEC_PORT 512
|
#define REXEC_PORT 512
|
||||||
|
|
||||||
|
#define QREXEC_AGENT_TRIGGER_PATH "/var/run/qubes/qrexec_agent"
|
||||||
|
|
||||||
enum {
|
enum {
|
||||||
MSG_CLIENT_TO_SERVER_EXEC_CMDLINE = 0x100,
|
MSG_CLIENT_TO_SERVER_EXEC_CMDLINE = 0x100,
|
||||||
MSG_CLIENT_TO_SERVER_JUST_EXEC,
|
MSG_CLIENT_TO_SERVER_JUST_EXEC,
|
||||||
@ -40,12 +42,18 @@ enum {
|
|||||||
MSG_AGENT_TO_SERVER_STDOUT,
|
MSG_AGENT_TO_SERVER_STDOUT,
|
||||||
MSG_AGENT_TO_SERVER_STDERR,
|
MSG_AGENT_TO_SERVER_STDERR,
|
||||||
MSG_AGENT_TO_SERVER_EXIT_CODE,
|
MSG_AGENT_TO_SERVER_EXIT_CODE,
|
||||||
|
MSG_AGENT_TO_SERVER_TRIGGER_EXEC,
|
||||||
|
|
||||||
MSG_SERVER_TO_CLIENT_STDOUT,
|
MSG_SERVER_TO_CLIENT_STDOUT,
|
||||||
MSG_SERVER_TO_CLIENT_STDERR,
|
MSG_SERVER_TO_CLIENT_STDERR,
|
||||||
MSG_SERVER_TO_CLIENT_EXIT_CODE
|
MSG_SERVER_TO_CLIENT_EXIT_CODE
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum {
|
||||||
|
QREXEC_EXECUTE_FILE_COPY=0x700,
|
||||||
|
QREXEC_EXECUTE_FILE_COPY_FOR_DISPVM
|
||||||
|
};
|
||||||
|
|
||||||
struct server_header {
|
struct server_header {
|
||||||
unsigned int type;
|
unsigned int type;
|
||||||
unsigned int clid;
|
unsigned int clid;
|
||||||
|
@ -30,6 +30,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pwd.h>
|
#include <pwd.h>
|
||||||
#include <grp.h>
|
#include <grp.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
#include "qrexec.h"
|
#include "qrexec.h"
|
||||||
#include "buffer.h"
|
#include "buffer.h"
|
||||||
#include "glue.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 */
|
/* indexed by client id, which is descriptor number of a client in daemon */
|
||||||
struct _client_info client_info[MAX_FDS];
|
struct _client_info client_info[MAX_FDS];
|
||||||
|
|
||||||
|
int trigger_fd;
|
||||||
|
|
||||||
void init()
|
void init()
|
||||||
{
|
{
|
||||||
peer_server_init(REXEC_PORT);
|
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()
|
void no_colon_in_cmd()
|
||||||
@ -418,6 +426,11 @@ int fill_fds_for_select(fd_set * rdset, fd_set * wrset)
|
|||||||
FD_SET(i, rdset);
|
FD_SET(i, rdset);
|
||||||
max = i;
|
max = i;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
FD_SET(trigger_fd, rdset);
|
||||||
|
if (trigger_fd > max)
|
||||||
|
max = trigger_fd;
|
||||||
|
|
||||||
for (i = 0; i < MAX_FDS; i++)
|
for (i = 0; i < MAX_FDS; i++)
|
||||||
if (client_info[i].pid > 0 && client_info[i].is_blocked) {
|
if (client_info[i].pid > 0 && client_info[i].is_blocked) {
|
||||||
fd = client_info[i].stdin_fd;
|
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()
|
int main()
|
||||||
{
|
{
|
||||||
@ -469,6 +504,9 @@ int main()
|
|||||||
while (read_ready_vchan_ext())
|
while (read_ready_vchan_ext())
|
||||||
handle_server_data();
|
handle_server_data();
|
||||||
|
|
||||||
|
if (FD_ISSET(trigger_fd, &rdset))
|
||||||
|
handle_trigger_io();
|
||||||
|
|
||||||
handle_process_data_all(&rdset);
|
handle_process_data_all(&rdset);
|
||||||
for (i = 0; i <= MAX_FDS; i++)
|
for (i = 0; i <= MAX_FDS; i++)
|
||||||
if (client_info[i].pid > 0
|
if (client_info[i].pid > 0
|
||||||
|
@ -51,9 +51,11 @@ int server_fd;
|
|||||||
|
|
||||||
void handle_usr1(int x)
|
void handle_usr1(int x)
|
||||||
{
|
{
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
char domain_id[64];
|
||||||
|
|
||||||
void init(int xid)
|
void init(int xid)
|
||||||
{
|
{
|
||||||
char dbg_log[256];
|
char dbg_log[256];
|
||||||
@ -63,6 +65,7 @@ void init(int xid)
|
|||||||
fprintf(stderr, "domain id=0?\n");
|
fprintf(stderr, "domain id=0?\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
snprintf(domain_id, sizeof(domain_id), "%d", xid);
|
||||||
signal(SIGUSR1, handle_usr1);
|
signal(SIGUSR1, handle_usr1);
|
||||||
switch (fork()) {
|
switch (fork()) {
|
||||||
case -1:
|
case -1:
|
||||||
@ -71,7 +74,7 @@ void init(int xid)
|
|||||||
case 0:
|
case 0:
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
pause();
|
pause();
|
||||||
exit(0);
|
exit(0);
|
||||||
}
|
}
|
||||||
close(0);
|
close(0);
|
||||||
@ -94,6 +97,7 @@ void init(int xid)
|
|||||||
peer_client_init(xid, REXEC_PORT);
|
peer_client_init(xid, REXEC_PORT);
|
||||||
setuid(getuid());
|
setuid(getuid());
|
||||||
signal(SIGPIPE, SIG_IGN);
|
signal(SIGPIPE, SIG_IGN);
|
||||||
|
signal(SIGCHLD, SIG_IGN);
|
||||||
signal(SIGUSR1, SIG_DFL);
|
signal(SIGUSR1, SIG_DFL);
|
||||||
kill(getppid(), SIGUSR1);
|
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()
|
void handle_agent_data()
|
||||||
{
|
{
|
||||||
struct client_header hdr;
|
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,
|
// fprintf(stderr, "got %x %x %x\n", s_hdr.type, s_hdr.clid,
|
||||||
// s_hdr.len);
|
// 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) {
|
if (s_hdr.clid >= MAX_FDS || s_hdr.clid < 0) {
|
||||||
fprintf(stderr, "from agent: clid=%d\n", s_hdr.clid);
|
fprintf(stderr, "from agent: clid=%d\n", s_hdr.clid);
|
||||||
exit(1);
|
exit(1);
|
||||||
|
@ -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 ../vchan/libvchan.so $RPM_BUILD_ROOT/%{_libdir}/libvchan.so
|
||||||
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
|
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
|
||||||
|
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/var/run/qubes
|
||||||
|
|
||||||
%triggerin -- initscripts
|
%triggerin -- initscripts
|
||||||
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
||||||
@ -227,6 +228,7 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
/usr/include/libvchan.h
|
/usr/include/libvchan.h
|
||||||
%{_libdir}/libvchan.so
|
%{_libdir}/libvchan.so
|
||||||
%{_libdir}/libu2mfn.so
|
%{_libdir}/libu2mfn.so
|
||||||
|
%dir /var/run/qubes
|
||||||
|
|
||||||
|
|
||||||
%package devel
|
%package devel
|
||||||
|
@ -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 ../vchan/libvchan.so $RPM_BUILD_ROOT/%{_libdir}/libvchan.so
|
||||||
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
|
install -D ../u2mfn/libu2mfn.so $RPM_BUILD_ROOT/%{_libdir}/libu2mfn.so
|
||||||
|
|
||||||
|
mkdir -p $RPM_BUILD_ROOT/var/run/qubes
|
||||||
|
|
||||||
%triggerin -- initscripts
|
%triggerin -- initscripts
|
||||||
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
cp /var/lib/qubes/serial.conf /etc/init/serial.conf
|
||||||
@ -193,3 +194,4 @@ rm -rf $RPM_BUILD_ROOT
|
|||||||
%dir /var/run/qubes
|
%dir /var/run/qubes
|
||||||
%{_libdir}/libvchan.so
|
%{_libdir}/libvchan.so
|
||||||
%{_libdir}/libu2mfn.so
|
%{_libdir}/libu2mfn.so
|
||||||
|
%dir /var/run/qubes
|
||||||
|
Loading…
Reference in New Issue
Block a user