diff options
author | David Herrmann <dh.herrmann@gmail.com> | 2015-01-08 21:06:14 +0100 |
---|---|---|
committer | David Herrmann <dh.herrmann@gmail.com> | 2015-01-08 21:06:14 +0100 |
commit | b864535791844ce4f9437cebefaf3c37b3741b4a (patch) | |
tree | e427be9f2ee61762fc7bebe9bf3f655691c1cea0 /src | |
parent | 426bb5ddb8ff122d3e08b0480466718b68485e70 (diff) |
bus-proxyd: fix EPERM on replies
Imagine a kdbus peer sending a method-call without EXPECT_REPLY set
through the proxy to a dbus1 peer. The proxy turns the missing
EXPECT_REPLY flag into a dbus1 NO_REPLY_EXPECTED flag. However, if the
receipient ignores that flag (valid dbus1 behavior) and sends a reply, the
proxy will try to forward it to the original peer. This will fail with
EPERM as the kernel didn't track the reply.
We have two options now: Either we ignore EPERM for reply messages, or we
track reply-windows in the proxy so we can properly ignore replies if
EXPECT_REPLY wasn't set.
This commit chose the first option: ignore EPERM for replies. The only
down-side is that replies without matching method call will no longer be
forwarded by the proxy. This works on dbus1, though.
Nobody sane does this, so lets ignore it.
Diffstat (limited to 'src')
-rw-r--r-- | src/bus-proxyd/bus-proxyd.c | 33 |
1 files changed, 24 insertions, 9 deletions
diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 44e16fcd15..21cd4e29d2 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -1605,14 +1605,26 @@ int main(int argc, char *argv[]) { if (!processed) { k = sd_bus_send(b, m, NULL); if (k < 0) { - if (k == -ECONNRESET) + if (k == -ECONNRESET) { r = 0; - else { + goto finish; + } else if (k == -EPERM && m->reply_cookie > 0) { + /* If the peer tries to send a reply and it is rejected with EPERM + * by the kernel, we ignore the error. This catches cases where the + * original method-call didn't had EXPECT_REPLY set, but the proxy-peer + * still sends a reply. This is allowed in dbus1, but not in kdbus. We + * don't want to track reply-windows in the proxy, so we simply ignore + * EPERM for all replies. The only downside is, that callers are no + * longer notified if their replies are dropped. However, this is + * equivalent to the caller's timeout to expire, so this should be + * acceptable. Nobody sane sends replies without a matching method-call, + * so nobody should care. */ + r = 1; + } else { r = k; log_error_errno(r, "Failed to send message to client: %m"); + goto finish; } - - goto finish; } else r = 1; } @@ -1682,17 +1694,20 @@ int main(int argc, char *argv[]) { k = sd_bus_send(a, m, NULL); if (k < 0) { - if (k == -EREMCHG) + if (k == -EREMCHG) { /* The name database changed since the policy check, hence let's check again */ continue; - else if (k == -ECONNRESET) + } else if (k == -ECONNRESET) { r = 0; - else { + goto finish; + } else if (k == -EPERM && m->reply_cookie > 0) { + /* see above why EPERM is ignored for replies */ + r = 1; + } else { r = k; log_error_errno(r, "Failed to send message to bus: %m"); + goto finish; } - - goto finish; } else r = 1; |