Skip to content

Commit 2be9adc

Browse files
committed
qrexec-client: fail if service configuration loading fails
Previously all such errors were ignored. Fixes: QubesOS/qubes-issues#9101
1 parent 0d85560 commit 2be9adc

File tree

2 files changed

+72
-14
lines changed

2 files changed

+72
-14
lines changed

daemon/qrexec-client.c

+23-8
Original file line numberDiff line numberDiff line change
@@ -211,36 +211,46 @@ static _Noreturn void do_exec(const char *prog, const char *username __attribute
211211

212212

213213
/* See also qrexec-agent.c:wait_for_session_maybe() */
214-
static void wait_for_session_maybe(char *cmdline)
214+
static bool wait_for_session_maybe(char *cmdline)
215215
{
216216
struct qrexec_parsed_command *cmd;
217217
pid_t pid;
218218
int status;
219+
bool rc = false;
219220

220221
cmd = parse_qubes_rpc_command(cmdline, false);
221222
if (!cmd)
222223
goto out;
223224

224-
if (cmd->nogui)
225+
if (cmd->nogui) {
226+
rc = true;
225227
goto out;
228+
}
226229

227-
if (!cmd->service_descriptor)
230+
if (!cmd->service_descriptor) {
231+
rc = true;
228232
goto out;
233+
}
229234

230-
load_service_config_v2(cmd);
231-
if (!cmd->wait_for_session)
235+
if (load_service_config_v2(cmd) < 0)
232236
goto out;
237+
if (!cmd->wait_for_session) {
238+
rc = true;
239+
goto out;
240+
}
233241

234242
pid = fork();
235243
switch (pid) {
236244
case 0:
237245
close(0);
238246
exec_wait_for_session(cmd->source_domain);
239247
PERROR("exec");
240-
exit(1);
248+
_exit(1);
241249
case -1:
242250
PERROR("fork");
243251
goto out;
252+
default:
253+
rc = true;
244254
}
245255

246256
if (waitpid(local_pid, &status, 0) > 0) {
@@ -251,6 +261,7 @@ static void wait_for_session_maybe(char *cmdline)
251261

252262
out:
253263
destroy_qrexec_parsed_command(cmd);
264+
return rc;
254265
}
255266

256267
static int prepare_local_fds(char *cmdline, struct buffer *stdin_buffer)
@@ -617,8 +628,12 @@ int main(int argc, char **argv)
617628

618629
struct buffer stdin_buffer;
619630
buffer_init(&stdin_buffer);
620-
wait_for_session_maybe(remote_cmdline);
621-
prepare_ret = prepare_local_fds(remote_cmdline, &stdin_buffer);
631+
if (!wait_for_session_maybe(remote_cmdline)) {
632+
LOG(ERROR, "Cannot load service configuration, or forking process failed");
633+
prepare_ret = -1;
634+
} else {
635+
prepare_ret = prepare_local_fds(remote_cmdline, &stdin_buffer);
636+
}
622637
if (request_id) {
623638
void (*old_handler)(int);
624639

qrexec/tests/socket/daemon.py

+49-6
Original file line numberDiff line numberDiff line change
@@ -782,19 +782,56 @@ def test_run_dom0_command_and_connect_vm(self):
782782
self.client.wait()
783783
self.assertEqual(self.client.returncode, 0)
784784

785-
def test_run_dom0_service_exec(self):
785+
def exec_service_with_invalid_config(self, invalid_config):
786+
config_path = os.path.join(self.tempdir, "rpc-config", "qubes.Service+arg")
787+
if invalid_config is not None:
788+
with open(config_path, "w") as f:
789+
f.write(invalid_config)
790+
else:
791+
os.symlink("/dev/null/doesnotexist", config_path)
786792
util.make_executable_service(
787793
self.tempdir,
788794
"rpc",
789795
"qubes.Service",
790796
"""\
791-
#!/bin/sh
792-
read input
793-
echo "arg: $1, remote domain: $QREXEC_REMOTE_DOMAIN, input: $input"
794-
""",
797+
#!/bin/sh
798+
read input
799+
echo "arg: $1, remote domain: $QREXEC_REMOTE_DOMAIN, input: $input"
800+
""",
795801
)
802+
self.test_run_dom0_service_failed()
796803

797-
cmd = "QUBESRPC qubes.Service+arg src_domain name src_domain"
804+
def test_exec_service_with_invalid_config_1(self):
805+
self.exec_service_with_invalid_config("wait-for-session = 00\n")
806+
807+
def test_exec_service_with_invalid_config_2(self):
808+
self.exec_service_with_invalid_config("wait-for-session = 01\n")
809+
810+
def test_exec_service_with_invalid_config_3(self):
811+
self.exec_service_with_invalid_config("wait-for-session = \n")
812+
813+
def test_exec_service_with_invalid_config_4(self):
814+
self.exec_service_with_invalid_config("wait-for-session = \"a\"\n")
815+
816+
def test_exec_service_with_invalid_config_5(self):
817+
self.exec_service_with_invalid_config("wait-for-session\n")
818+
819+
def test_exec_service_with_invalid_config_6(self):
820+
self.exec_service_with_invalid_config(None)
821+
822+
def _test_run_dom0_service_exec(self, nogui):
823+
util.make_executable_service(
824+
self.tempdir,
825+
"rpc",
826+
"qubes.Service",
827+
"""\
828+
#!/bin/sh
829+
read input
830+
echo "arg: $1, remote domain: $QREXEC_REMOTE_DOMAIN, input: $input"
831+
""",
832+
)
833+
834+
cmd = ("nogui:" if nogui else "") + "QUBESRPC qubes.Service+arg src_domain name src_domain"
798835
source = self.connect_service_request(cmd)
799836

800837
source.send_message(qrexec.MSG_DATA_STDIN, b"stdin data\n")
@@ -814,6 +851,12 @@ def test_run_dom0_service_exec(self):
814851
self.client.wait()
815852
self.assertEqual(self.client.returncode, 0)
816853

854+
def test_run_dom0_service_exec(self):
855+
self._test_run_dom0_service_exec(False)
856+
857+
def test_run_dom0_service_exec_nogui(self):
858+
self._test_run_dom0_service_exec(True)
859+
817860
def test_run_dom0_service_failed(self):
818861
# qubes.Service does not exist
819862
cmd = "QUBESRPC qubes.Service+arg src_domain name src_domain"

0 commit comments

Comments
 (0)