Skip to content

Commit c6ec6ef

Browse files
committed
Support not passing metadata to socket-based services
This makes it easier to implement socket-based services that do not require the metadata. This avoids having to use a slow executable-based service or write a custom wrapper. Fixes: QubesOS/qubes-issues#9036
1 parent 07ec597 commit c6ec6ef

File tree

5 files changed

+55
-6
lines changed

5 files changed

+55
-6
lines changed

libqrexec/exec.c

+8-4
Original file line numberDiff line numberDiff line change
@@ -269,7 +269,8 @@ static int load_service_config_raw(struct qrexec_parsed_command *cmd,
269269
config_full_path, sizeof(config_full_path), NULL);
270270
if (ret < 0)
271271
return 0;
272-
return qubes_toml_config_parse(config_full_path, &cmd->wait_for_session, user);
272+
return qubes_toml_config_parse(config_full_path, &cmd->wait_for_session, user,
273+
&cmd->send_service_descriptor);
273274
}
274275

275276
int load_service_config_v2(struct qrexec_parsed_command *cmd) {
@@ -304,6 +305,7 @@ struct qrexec_parsed_command *parse_qubes_rpc_command(
304305
}
305306

306307
memset(cmd, 0, sizeof(*cmd));
308+
cmd->send_service_descriptor = true;
307309
cmd->cmdline = cmdline;
308310

309311
if (strip_username) {
@@ -489,9 +491,11 @@ static int execute_qrexec_service(
489491
*pid = 0;
490492
set_nonblock(s);
491493

492-
/* send part after "QUBESRPC ", including trailing NUL */
493-
const char *desc = cmd->command + RPC_REQUEST_COMMAND_LEN + 1;
494-
buffer_append(stdin_buffer, desc, strlen(desc) + 1);
494+
if (cmd->send_service_descriptor) {
495+
/* send part after "QUBESRPC ", including trailing NUL */
496+
const char *desc = cmd->command + RPC_REQUEST_COMMAND_LEN + 1;
497+
buffer_append(stdin_buffer, desc, strlen(desc) + 1);
498+
}
495499
return 0;
496500
}
497501

libqrexec/libqrexec-utils.h

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,9 @@ struct qrexec_parsed_command {
7979

8080
/* Should a session be waited for? */
8181
bool wait_for_session;
82+
83+
/* For socket-based services: Should the service descriptor be sent? */
84+
bool send_service_descriptor;
8285
};
8386

8487
/* Parse a command, return NULL on failure. Uses cmd->cmdline

libqrexec/private.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,2 @@
11
#include <stdbool.h>
2-
int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session, char **user);
2+
int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session, char **user, bool *skip_service_descriptor);

libqrexec/toml.c

+7-1
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ static void toml_value_free(union toml_data *value, enum toml_type ty) {
171171
}
172172
}
173173

174-
int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session, char **user)
174+
int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session, char **user, bool *send_service_descriptor)
175175
{
176176
int result = -1; /* assume problem */
177177
FILE *config_file = fopen(config_full_path, "re");
@@ -186,7 +186,9 @@ int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session
186186
ssize_t signed_linelen;
187187
bool seen_wait_for_session = false;
188188
bool seen_user = false;
189+
bool seen_skip_service_descriptor = false;
189190
*wait_for_session = 0;
191+
*send_service_descriptor = true;
190192
#define CHECK_DUP_KEY(v) do { \
191193
if (toml_check_dup_key(&(v), config_full_path, lineno, current_line)) { \
192194
toml_value_free(&value, ty); \
@@ -288,6 +290,10 @@ int qubes_toml_config_parse(const char *config_full_path, bool *wait_for_session
288290
CHECK_TYPE(TOML_TYPE_BOOL, "wait-for-session");
289291
*wait_for_session = value.boolean;
290292
}
293+
} else if (strcmp(current_line, "skip-service-descriptor") == 0) {
294+
CHECK_DUP_KEY(seen_skip_service_descriptor);
295+
CHECK_TYPE(TOML_TYPE_BOOL, "skip-service-descriptor");
296+
*send_service_descriptor = !value.boolean;
291297
} else if (strcmp(current_line, "force-user") == 0) {
292298
CHECK_DUP_KEY(seen_user);
293299
CHECK_TYPE(TOML_TYPE_STRING, "user name or user ID");

qrexec/tests/socket/agent.py

+36
Original file line numberDiff line numberDiff line change
@@ -525,6 +525,42 @@ def test_exec_service_with_arg(self):
525525
)
526526
self.check_dom0(dom0)
527527

528+
def test_connect_socket_no_metadata(self):
529+
socket_path = os.path.join(
530+
self.tempdir, "rpc", "qubes.SocketService+arg2"
531+
)
532+
with open(
533+
os.path.join(self.tempdir, "rpc-config", "qubes.SocketService+arg2"), "w"
534+
) as f:
535+
f.write("""\
536+
skip-service-descriptor = true
537+
""")
538+
server = qrexec.socket_server(socket_path)
539+
self.addCleanup(server.close)
540+
541+
target, dom0 = self.execute_qubesrpc("qubes.SocketService+arg2", "domX")
542+
543+
server.accept()
544+
545+
message = b"stdin data"
546+
target.send_message(qrexec.MSG_DATA_STDIN, message)
547+
target.send_message(qrexec.MSG_DATA_STDIN, b"")
548+
self.assertEqual(server.recvall(len(message)), message)
549+
550+
server.sendall(b"stdout data")
551+
server.close()
552+
messages = target.recv_all_messages()
553+
# No stderr
554+
self.assertListEqual(
555+
util.sort_messages(messages),
556+
[
557+
(qrexec.MSG_DATA_STDOUT, b"stdout data"),
558+
(qrexec.MSG_DATA_STDOUT, b""),
559+
(qrexec.MSG_DATA_EXIT_CODE, b"\0\0\0\0"),
560+
],
561+
)
562+
self.check_dom0(dom0)
563+
528564
def test_connect_socket(self):
529565
socket_path = os.path.join(
530566
self.tempdir, "rpc", "qubes.SocketService+arg"

0 commit comments

Comments
 (0)