Skip to content

Commit 48944be

Browse files
committed
Forbid empty service names in legacy MSG_TRIGGER_SERVICE
There is no point in allowing calls with an empty service name: if the argument was empty, the call would be unconditionally rejected by the policy daemon, and even if it was _not_ empty, libqrexec would refuse to execute the call. Furthermore, MSG_TRIGGER_SERVICE3 already checks for empty service names and sends MSG_SERVICE_REFUSED without even querying the policy daemon, so querying the policy daemon for MSG_TRIGGER_SERVICE is inconsistent. Fixes: QubesOS/qubes-issues#9098
1 parent a8052a3 commit 48944be

File tree

2 files changed

+34
-24
lines changed

2 files changed

+34
-24
lines changed

daemon/qrexec-daemon.c

+34-23
Original file line numberDiff line numberDiff line change
@@ -1262,6 +1262,21 @@ static bool validate_request_id(struct service_params *untrusted_params, const c
12621262

12631263
#define ENSURE_NULL_TERMINATED(x) x[sizeof(x)-1] = 0
12641264

1265+
static bool validate_service_name(char *untrusted_service_name)
1266+
{
1267+
switch (untrusted_service_name[0]) {
1268+
case '\0':
1269+
LOG(ERROR, "Empty service name not allowed");
1270+
return false;
1271+
case '+':
1272+
LOG(ERROR, "Service name must not start with '+'");
1273+
return false;
1274+
default:
1275+
sanitize_name(untrusted_service_name, "+");
1276+
return true;
1277+
}
1278+
}
1279+
12651280
#ifndef FUZZING_BUILD_MODE_UNSAFE_FOR_PRODUCTION
12661281
static
12671282
#endif
@@ -1296,6 +1311,10 @@ void handle_message_from_agent(void)
12961311
send_service_refused(vchan, &untrusted_params.request_id);
12971312
return;
12981313
}
1314+
if (!validate_service_name(untrusted_params.service_name)) {
1315+
send_service_refused(vchan, &untrusted_params.request_id);
1316+
return;
1317+
}
12991318
params = untrusted_params;
13001319
/* sanitize end */
13011320

@@ -1329,38 +1348,30 @@ void handle_message_from_agent(void)
13291348
ENSURE_NULL_TERMINATED(untrusted_params3.target_domain);
13301349
sanitize_name(untrusted_params3.target_domain, "@:");
13311350
if (!validate_request_id(&untrusted_params3.request_id, "MSG_TRIGGER_SERVICE3"))
1332-
goto fail;
1351+
goto fail3;
13331352
params3 = untrusted_params3;
13341353
if (untrusted_service_name[service_name_len] != 0) {
13351354
LOG(ERROR, "Service name not NUL-terminated");
1336-
goto fail;
1355+
goto fail3;
13371356
}
13381357
nul_offset = strlen(untrusted_service_name);
13391358
if (nul_offset != service_name_len) {
13401359
LOG(ERROR, "Service name contains NUL byte at offset %zu", nul_offset);
1341-
goto fail;
1360+
goto fail3;
13421361
}
1343-
switch (untrusted_service_name[0]) {
1344-
case '\0':
1345-
LOG(ERROR, "Empty service name not allowed");
1346-
goto fail;
1347-
case '+':
1348-
LOG(ERROR, "Service name must not start with '+'");
1349-
goto fail;
1350-
default:
1351-
sanitize_name(untrusted_service_name, "+");
1352-
service_name = untrusted_service_name;
1353-
untrusted_service_name = NULL;
1354-
/* sanitize end */
1362+
if (!validate_service_name(untrusted_service_name))
1363+
goto fail3;
1364+
service_name = untrusted_service_name;
1365+
untrusted_service_name = NULL;
1366+
/* sanitize end */
13551367

1356-
handle_execute_service(remote_domain_id, remote_domain_name,
1357-
params3.target_domain,
1358-
service_name,
1359-
&params3.request_id);
1360-
free(service_name);
1361-
return;
1362-
}
1363-
fail:
1368+
handle_execute_service(remote_domain_id, remote_domain_name,
1369+
params3.target_domain,
1370+
service_name,
1371+
&params3.request_id);
1372+
free(service_name);
1373+
return;
1374+
fail3:
13641375
send_service_refused(vchan, &untrusted_params3.request_id);
13651376
free(untrusted_service_name);
13661377
return;

qrexec/tests/socket/daemon.py

-1
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,6 @@ def test_bad_request_id_bad_byte_after_nul_terminator(self):
203203
self.assertEqual(data[:4], b"a\0b\0")
204204
self.assertEqual(data[4:], b"\0" * 28)
205205

206-
@unittest.expectedFailure
207206
def test_bad_old_style_request(self):
208207
agent = self.start_daemon_with_agent()
209208
agent.send_message(qrexec.MSG_HELLO, struct.pack("<L", 2))

0 commit comments

Comments
 (0)