summaryrefslogtreecommitdiff
path: root/src/shared/varlink.c
diff options
context:
space:
mode:
authorZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-08-28 19:22:20 +0200
committerZbigniew Jędrzejewski-Szmek <zbyszek@in.waw.pl>2020-09-01 10:48:10 +0200
commit77472d06a4740d820ebccdb04e217d6b7d66dd50 (patch)
treea4d27564cdf37ae2d13ceee0f5e69dd6a392ff76 /src/shared/varlink.c
parentf7dc8248d3402a6c7a4c1ccabf58ae83df713417 (diff)
downloadsystemd-77472d06a4740d820ebccdb04e217d6b7d66dd50.tar.gz
varlink: do not parse invalid messages twice
Upon reception of a message which fails in json_parse(), we would proceed to parse it again from a deferred callback and hang. Once we have realized that the message is invalid, let's move the pointer in the buffer even if the message is invalid. We don't want to look at this data again. (before) $ build-rawhide/userdbctl --output=json user test.user n/a: varlink: setting state idle-client /run/systemd/userdb/io.systemd.Multiplexer: Sending message: {"method":"io.systemd.UserDatabase.GetUserRecord","parameters":{"userName":"test.user","service":"io.systemd.Multiplexer"}} /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state idle-client → awaiting-reply /run/systemd/userdb/io.systemd.Multiplexer: New incoming message: {...} /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state awaiting-reply → pending-disconnect /run/systemd/userdb/io.systemd.Multiplexer: New incoming message: {...} /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state pending-disconnect → disconnected ^C (after) $ n/a: varlink: setting state idle-client /run/systemd/userdb/io.systemd.Multiplexer: Sending message: {"method":"io.systemd.UserDatabase.GetUserRecord","parameters":{"userName":"test.user","service":"io.systemd.Multiplexer"}} /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state idle-client → awaiting-reply /run/systemd/userdb/io.systemd.Multiplexer: New incoming message: {...} /run/systemd/userdb/io.systemd.Multiplexer: Failed to parse JSON: Invalid argument /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state awaiting-reply → pending-disconnect /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state pending-disconnect → processing-disconnect Got lookup error: io.systemd.Disconnected /run/systemd/userdb/io.systemd.Multiplexer: varlink: changing state processing-disconnect → disconnected Failed to find user test.user: Input/output error This should fix #16683 and https://bugs.gentoo.org/735072.
Diffstat (limited to 'src/shared/varlink.c')
-rw-r--r--src/shared/varlink.c12
1 files changed, 9 insertions, 3 deletions
diff --git a/src/shared/varlink.c b/src/shared/varlink.c
index e2b4bb623d..99ae9265f9 100644
--- a/src/shared/varlink.c
+++ b/src/shared/varlink.c
@@ -579,11 +579,17 @@ static int varlink_parse_message(Varlink *v) {
sz = e - begin + 1;
- varlink_log(v, "New incoming message: %s", begin);
+ varlink_log(v, "New incoming message: %s", begin); /* FIXME: should we output the whole message here before validation?
+ * This may produce a non-printable journal entry if the message
+ * is invalid. We may also expose privileged information. */
r = json_parse(begin, 0, &v->current, NULL, NULL);
- if (r < 0)
- return r;
+ if (r < 0) {
+ /* If we encounter a parse failure flush all data. We cannot possibly recover from this,
+ * hence drop all buffered data now. */
+ v->input_buffer_index = v->input_buffer_size = v->input_buffer_unscanned = 0;
+ return varlink_log_errno(v, r, "Failed to parse JSON: %m");
+ }
v->input_buffer_size -= sz;