Skip to content

Commit

Permalink
Rip out qubes-rpc-multiplexer
Browse files Browse the repository at this point in the history
Instead, directly execute the command from C.

Marked as draft for two reasons:

1. This PR is based on another PR (QubesOS#139), not main.

2. All variables with names beginning with QREXEC_ are stripped from the
   environment, except for QREXEC_SERVICE_PATH.  This is a change in
   behavior compared to the current code.

1 must be fixed before this can be merged.  2 is a design decision that
could go either way.

Fixes: QubesOS/qubes-issues#9062
  • Loading branch information
DemiMarie committed Apr 16, 2024
1 parent 2aef335 commit 0b32ed3
Show file tree
Hide file tree
Showing 20 changed files with 250 additions and 156 deletions.
25 changes: 19 additions & 6 deletions agent/qrexec-agent-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -132,28 +132,38 @@ int handle_handshake(libvchan_t *ctrl)

static int handle_just_exec(struct qrexec_parsed_command *cmd)
{
int fdn, pid;
int fdn, pid, log_fd;

if (cmd == NULL)
return 127;

char file_path[QUBES_SOCKADDR_UN_MAX_PATH_LEN];
struct buffer buf = { .data = file_path, .buflen = (int)sizeof(file_path) };
struct buffer stdin_buffer;
buffer_init(&stdin_buffer);
if (cmd->service_descriptor) {
int socket_fd;
struct buffer stdin_buffer;
buffer_init(&stdin_buffer);
if (!find_qrexec_service(cmd, &socket_fd, &stdin_buffer))
if (!find_qrexec_service(cmd, &socket_fd, &stdin_buffer, &buf))
return 127;
if (socket_fd != -1)
return write_all(socket_fd, stdin_buffer.data, stdin_buffer.buflen) ? 0 : 127;
} else {
buf.data = NULL;
}
switch (pid = fork()) {
case -1:
PERROR("fork");
return 127;
case 0:
fdn = open("/dev/null", O_RDWR);
fix_fds(fdn, fdn, fdn);
do_exec(cmd->command, cmd->username);
if (fdn < 0)
_exit(127);
int other_pid;
log_fd = cmd->service_descriptor ? open_logger(cmd, &other_pid) : fdn;
if (log_fd < 0)
_exit(127);
fix_fds(fdn, fdn, log_fd);
do_exec(buf.data, cmd->command, cmd->username);
default:;
}
LOG(INFO, "executed (nowait): %s (pid %d)", cmd->command, pid);
Expand Down Expand Up @@ -311,6 +321,7 @@ static int handle_new_process_common(
return 0;
}

int logger_pid = 0;
req.vchan = data_vchan;
req.stdin_buf = &stdin_buf;

Expand All @@ -330,6 +341,8 @@ static int handle_new_process_common(

req.prefix_data.data = NULL;
req.prefix_data.len = 0;
if (cmd->service_descriptor != NULL)
req.logger_fd = open_logger(cmd, &logger_pid);

exit_code = process_io(&req);

Expand Down
8 changes: 4 additions & 4 deletions agent/qrexec-agent.c
Original file line number Diff line number Diff line change
Expand Up @@ -139,7 +139,7 @@ static struct pam_conv conv = {
* If dom0 sends overly long cmd, it will probably crash qrexec-agent (unless
* process can allocate up to 4GB on both stack and heap), sorry.
*/
_Noreturn void do_exec(const char *cmd, const char *user)
_Noreturn void do_exec(const char *prog, const char *cmd, const char *user)
{
#ifdef HAVE_PAM
int retval, status;
Expand Down Expand Up @@ -178,7 +178,7 @@ _Noreturn void do_exec(const char *cmd, const char *user)
exit(1);
}
/* call QUBESRPC if requested */
exec_qubes_rpc_if_requested(cmd, environ);
exec_qubes_rpc_if_requested(prog, cmd, environ);

/* otherwise exec shell */
execl("/bin/sh", "sh", "-c", cmd, NULL);
Expand Down Expand Up @@ -285,7 +285,7 @@ _Noreturn void do_exec(const char *cmd, const char *user)
warn("chdir(%s)", pw->pw_dir);

/* call QUBESRPC if requested */
exec_qubes_rpc_if_requested(cmd, env);
exec_qubes_rpc_if_requested(prog, cmd, env);

/* otherwise exec shell */
execle(pw->pw_shell, arg0, "-c", cmd, (char*)NULL, env);
Expand Down Expand Up @@ -323,7 +323,7 @@ _Noreturn void do_exec(const char *cmd, const char *user)
exit(1);
#else
/* call QUBESRPC if requested */
exec_qubes_rpc_if_requested(cmd, environ);
exec_qubes_rpc_if_requested(prog, cmd, environ);

/* otherwise exec shell */
execl("/bin/su", "su", "-", user, "-c", cmd, NULL);
Expand Down
2 changes: 1 addition & 1 deletion agent/qrexec-agent.h
Original file line number Diff line number Diff line change
Expand Up @@ -29,7 +29,7 @@

int handle_handshake(libvchan_t *ctrl);
void handle_vchan_error(const char *op);
_Noreturn void do_exec(const char *cmd, const char *user);
_Noreturn void do_exec(const char *prog, const char *cmd, const char *user);
/* call before fork() for service handling process (either end) */
void prepare_child_env(void);

Expand Down
2 changes: 1 addition & 1 deletion agent/qrexec-client-vm.c
Original file line number Diff line number Diff line change
Expand Up @@ -42,7 +42,7 @@ _Noreturn void handle_vchan_error(const char *op)
exit(1);
}

_Noreturn void do_exec(const char *cmd __attribute__((unused)), char const* user __attribute__((__unused__))) {
_Noreturn void do_exec(const char *prog __attribute__((unused)), const char *cmd __attribute__((unused)), char const* user __attribute__((__unused__))) {
LOG(ERROR, "BUG: do_exec function shouldn't be called!");
abort();
}
Expand Down
4 changes: 2 additions & 2 deletions agent/qrexec-fork-server.c
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,15 @@
extern char **environ;
const bool qrexec_is_fork_server = true;

void do_exec(const char *cmd, const char *user __attribute__((unused)))
void do_exec(const char *prog, const char *cmd, const char *user __attribute__((unused)))
{
char *shell;

signal(SIGCHLD, SIG_DFL);
signal(SIGPIPE, SIG_DFL);

/* call QUBESRPC if requested */
exec_qubes_rpc_if_requested(cmd, environ);
exec_qubes_rpc_if_requested(prog, cmd, environ);

/* otherwise, pass it to shell */
shell = getenv("SHELL");
Expand Down
8 changes: 5 additions & 3 deletions daemon/qrexec-client.c
Original file line number Diff line number Diff line change
Expand Up @@ -62,13 +62,15 @@ static void set_remote_domain(const char *src_domain_name) {
}

/* called from do_fork_exec */
static _Noreturn void do_exec(const char *prog, const char *username __attribute__((unused)))
static _Noreturn void do_exec(const char *prog,
const char *cmdline,
const char *username __attribute__((unused)))
{
/* avoid calling qubes-rpc-multiplexer through shell */
exec_qubes_rpc_if_requested(prog, environ);
exec_qubes_rpc_if_requested(prog, cmdline, environ);

/* if above haven't executed qubes-rpc-multiplexer, pass it to shell */
execl("/bin/bash", "bash", "-c", prog, NULL);
execl("/bin/bash", "bash", "-c", cmdline, NULL);
PERROR("exec bash");
exit(1);
}
Expand Down
6 changes: 3 additions & 3 deletions daemon/qrexec-daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -1064,13 +1064,13 @@ static size_t compute_service_length(const char *const remote_cmdline) {
}

/* called from do_fork_exec */
static _Noreturn void do_exec(const char *prog, const char *username __attribute__((unused)))
static _Noreturn void do_exec(const char *prog, const char *cmd, const char *username __attribute__((unused)))
{
/* avoid calling qubes-rpc-multiplexer through shell */
exec_qubes_rpc_if_requested(prog, environ);
exec_qubes_rpc_if_requested(prog, cmd, environ);

/* if above haven't executed qubes-rpc-multiplexer, pass it to shell */
execl("/bin/bash", "bash", "-c", prog, NULL);
execl("/bin/bash", "bash", "-c", cmd, NULL);
PERROR("exec bash");
_exit(126);
}
Expand Down
1 change: 0 additions & 1 deletion debian/qubes-core-qrexec.install
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,5 @@ usr/bin/qubes-policy-lint
usr/lib/qubes/qrexec-agent
usr/lib/qubes/qrexec-client-vm
usr/lib/qubes/qrexec_client_vm
usr/lib/qubes/qubes-rpc-multiplexer
usr/lib/qubes/qrexec-policy-agent-autostart
usr/share/man/man1/qrexec-client-vm.1.gz
64 changes: 0 additions & 64 deletions lib/qubes-rpc-multiplexer

This file was deleted.

2 changes: 1 addition & 1 deletion libqrexec/Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -21,7 +21,7 @@ endif


all: libqrexec-utils.so
libqrexec-utils.so.$(SO_VER): unix-server.o ioall.o buffer.o exec.o txrx-vchan.o write-stdin.o replace.o remote.o process_io.o log.o toml.o
libqrexec-utils.so.$(SO_VER): unix-server.o ioall.o buffer.o exec.o txrx-vchan.o write-stdin.o replace.o remote.o process_io.o log.o toml.o open_logger.o
$(CC) $(LDFLAGS) -Wl,-soname,$@ -o $@ $^ $(VCHANLIBS)

libqrexec-utils.so: libqrexec-utils.so.$(SO_VER)
Expand Down
10 changes: 5 additions & 5 deletions libqrexec/buffer.c
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ static char *limited_malloc(int len)
(total_mem > BUFFER_LIMIT) || (len <= 0))
{
LOG(ERROR, "attempt to allocate >BUFFER_LIMIT");
exit(1);
abort();
}
ret = malloc((size_t)len);
if (!ret) {
PERROR("malloc");
exit(1);
abort();
}
return ret;
}
Expand Down Expand Up @@ -83,11 +83,11 @@ void buffer_append(struct buffer *b, const char *data, int len)
assert(data != NULL && "NULL data");
if (b->buflen < 0 || b->buflen > BUFFER_LIMIT) {
LOG(ERROR, "buffer_append buflen %d", len);
exit(1);
abort();
}
if (len < 0 || len > BUFFER_LIMIT) {
LOG(ERROR, "buffer_append %d", len);
exit(1);
abort();
}
if (len == 0)
return;
Expand All @@ -108,7 +108,7 @@ void buffer_remove(struct buffer *b, int len)
char *qdata = NULL;
if (len < 0 || len > b->buflen) {
LOG(ERROR, "buffer_remove %d/%d", len, b->buflen);
exit(1);
abort();
}
newsize = b->buflen - len;
if (newsize > 0) {
Expand Down
Loading

0 comments on commit 0b32ed3

Please sign in to comment.