Skip to content

Commit

Permalink
Allow specifying a username in service config
Browse files Browse the repository at this point in the history
This also dramatically improves the configuration parser.  Configuration
files now use a strict subset of TOML rather than an ad-hoc format with
no validation.

Fixes: QubesOS/qubes-issues#6354
Fixes: QubesOS/qubes-issues#8153
  • Loading branch information
DemiMarie committed Aug 3, 2023
1 parent 403eaa2 commit 71e08f1
Show file tree
Hide file tree
Showing 12 changed files with 457 additions and 176 deletions.
42 changes: 9 additions & 33 deletions agent/qrexec-agent-data.c
Original file line number Diff line number Diff line change
Expand Up @@ -129,33 +129,21 @@ int handle_handshake(libvchan_t *ctrl)
}


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

char *username = NULL;
char *realcmd = cmdline;

if (!qrexec_is_fork_server) {
username = cmdline;
realcmd = strchr(cmdline, ':');
if (!realcmd) {
LOG(ERROR, "No colon in command from dom0");
return -1;
}
*realcmd++ = '\0';
}
switch (pid = fork()) {
case -1:
PERROR("fork");
return -1;
case 0:
fdn = open("/dev/null", O_RDWR);
fix_fds(fdn, fdn, fdn);
do_exec(realcmd, username);
do_exec(cmd->command, cmd->username);
default:;
}
LOG(INFO, "executed (nowait): %s (pid %d)", cmdline, pid);
LOG(INFO, "executed (nowait): %s (pid %d)", cmd->command, pid);
return 0;
}

Expand All @@ -172,7 +160,7 @@ static int handle_just_exec(char *cmdline)
*/
static int handle_new_process_common(
int type, int connect_domain, int connect_port,
char *cmdline, size_t cmdline_len,
struct qrexec_parsed_command *cmd,
int buffer_size)
{
libvchan_t *data_vchan;
Expand All @@ -188,18 +176,6 @@ static int handle_new_process_common(
if (buffer_size == 0)
buffer_size = VCHAN_BUFFER_SIZE;

if (cmdline == NULL) {
LOG(ERROR, "internal qrexec error: NULL cmdline passed to a non-MSG_SERVICE_CONNECT call");
abort();
} else if (cmdline_len == 0) {
LOG(ERROR, "internal qrexec error: zero-length command line passed to a non-MSG_SERVICE_CONNECT call");
abort();
} else if (cmdline_len > MAX_QREXEC_CMD_LEN) {
/* This is arbitrary, but it helps reduce the risk of overflows in other code */
LOG(ERROR, "Bad command from dom0: command line too long: length %zu", cmdline_len);
abort();
}
cmdline[cmdline_len-1] = 0;
data_vchan = libvchan_client_init(connect_domain, connect_port);
if (!data_vchan) {
LOG(ERROR, "Data vchan connection failed");
Expand All @@ -215,13 +191,13 @@ static int handle_new_process_common(

switch (type) {
case MSG_JUST_EXEC:
if (send_exit_code(data_vchan, handle_just_exec(cmdline)) < 0)
if (send_exit_code(data_vchan, handle_just_exec(cmd)) < 0)
handle_vchan_error("just_exec");
libvchan_close(data_vchan);
return 0;
case MSG_EXEC_CMDLINE:
buffer_init(&stdin_buf);
if (execute_qubes_rpc_command(cmdline, &pid, &stdin_fd, &stdout_fd, &stderr_fd, !qrexec_is_fork_server, &stdin_buf) < 0) {
if (execute_parsed_qubes_rpc_command(cmd, &pid, &stdin_fd, &stdout_fd, &stderr_fd, &stdin_buf) < 0) {
struct msg_header hdr = {
.type = MSG_DATA_STDOUT,
.len = 0,
Expand All @@ -240,7 +216,7 @@ static int handle_new_process_common(
libvchan_close(data_vchan);
return exit_code;
}
LOG(INFO, "executed: %s (pid %d)", cmdline, pid);
LOG(INFO, "executed: %s (pid %d)", cmd->cmdline, pid);
break;
default:
LOG(ERROR, "unknown request type: %d", type);
Expand Down Expand Up @@ -279,7 +255,7 @@ static int handle_new_process_common(

/* Returns PID of data processing process */
pid_t handle_new_process(int type, int connect_domain, int connect_port,
char *cmdline, size_t cmdline_len)
struct qrexec_parsed_command *cmd)
{
int exit_code;
pid_t pid;
Expand All @@ -297,7 +273,7 @@ pid_t handle_new_process(int type, int connect_domain, int connect_port,

/* child process */
exit_code = handle_new_process_common(type, connect_domain, connect_port,
cmdline, cmdline_len, 0);
cmd, 0);

exit(exit_code);
}
Expand Down
Loading

0 comments on commit 71e08f1

Please sign in to comment.