X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbus-proxyd%2Fproxy.c;h=0c851f93c14fb4cf4bb4b8bd334a9d7d38ff6531;hb=0289f2fb2a64df53b589b771f69c43126b029590;hp=e3042d827d747f1ad1ebb66c07e08da3319f17a4;hpb=418e4cb07d56e365b9b77b24d3c851e85940d68b;p=elogind.git diff --git a/src/bus-proxyd/proxy.c b/src/bus-proxyd/proxy.c index e3042d827..0c851f93c 100644 --- a/src/bus-proxyd/proxy.c +++ b/src/bus-proxyd/proxy.c @@ -23,30 +23,20 @@ ***/ #include -#include #include -#include -#include #include #include #include -#include -#include #include "log.h" #include "util.h" -#include "socket-util.h" #include "sd-daemon.h" #include "sd-bus.h" #include "bus-internal.h" #include "bus-message.h" #include "bus-util.h" -#include "build.h" #include "strv.h" -#include "def.h" -#include "capability.h" #include "bus-control.h" -#include "smack-util.h" #include "set.h" #include "bus-xml-policy.h" #include "driver.h" @@ -81,14 +71,14 @@ static int proxy_create_destination(Proxy *p, const char *destination, const cha b->fake_pids.pid = p->local_creds.pid; b->fake_pids_valid = true; - b->fake_creds.uid = p->local_creds.uid; + b->fake_creds.uid = UID_INVALID; b->fake_creds.euid = p->local_creds.uid; - b->fake_creds.suid = p->local_creds.uid; - b->fake_creds.fsuid = p->local_creds.uid; - b->fake_creds.gid = p->local_creds.gid; + b->fake_creds.suid = UID_INVALID; + b->fake_creds.fsuid = UID_INVALID; + b->fake_creds.gid = GID_INVALID; b->fake_creds.egid = p->local_creds.gid; - b->fake_creds.sgid = p->local_creds.gid; - b->fake_creds.fsgid = p->local_creds.gid; + b->fake_creds.sgid = GID_INVALID; + b->fake_creds.fsgid = GID_INVALID; b->fake_creds_valid = true; } @@ -376,7 +366,7 @@ static int proxy_wait(Proxy *p) { } pollfd = (struct pollfd[3]) { - { .fd = fd, .events = events_destination, }, + { .fd = fd, .events = events_destination, }, { .fd = p->local_in, .events = events_local & POLLIN, }, { .fd = p->local_out, .events = events_local & POLLOUT, }, }; @@ -673,7 +663,7 @@ static int proxy_process_destination_to_local(Proxy *p) { assert(p); r = sd_bus_process(p->destination_bus, &m); - if (r == -ECONNRESET) /* Treat 'connection reset by peer' as clean exit condition */ + if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ return r; if (r < 0) { log_error_errno(r, "Failed to process destination bus: %m"); @@ -689,6 +679,8 @@ static int proxy_process_destination_to_local(Proxy *p) { return -ECONNRESET; r = synthesize_name_acquired(p->destination_bus, p->local_bus, m); + if (r == -ECONNRESET || r == -ENOTCONN) + return r; if (r < 0) return log_error_errno(r, "Failed to synthesize message: %m"); @@ -696,6 +688,8 @@ static int proxy_process_destination_to_local(Proxy *p) { if (p->policy) { r = process_policy(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); + if (r == -ECONNRESET || r == -ENOTCONN) + return r; if (r < 0) return log_error_errno(r, "Failed to process policy: %m"); if (r > 0) @@ -704,23 +698,32 @@ static int proxy_process_destination_to_local(Proxy *p) { r = sd_bus_send(p->local_bus, m, NULL); if (r < 0) { - if (r == -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. */ - return 1; - } else { - if (r != -ECONNRESET) - log_error_errno(r, "Failed to send message to client: %m"); + if (r == -ECONNRESET || r == -ENOTCONN) return r; - } + + /* 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. */ + if (r == -EPERM && m->reply_cookie > 0) + return 1; + + /* Return the error to the client, if we can */ + synthetic_reply_method_errnof(m, r, "Failed to forward message we got from destination: %m"); + log_error_errno(r, + "Failed to forward message we got from destination: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", + p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), + strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); + return 1; } return 1; @@ -733,7 +736,7 @@ static int proxy_process_local_to_destination(Proxy *p) { assert(p); r = sd_bus_process(p->local_bus, &m); - if (r == -ECONNRESET) /* Treat 'connection reset by peer' as clean exit condition */ + if (r == -ECONNRESET || r == -ENOTCONN) /* Treat 'connection reset by peer' as clean exit condition */ return r; if (r < 0) { log_error_errno(r, "Failed to process local bus: %m"); @@ -749,12 +752,16 @@ static int proxy_process_local_to_destination(Proxy *p) { return -ECONNRESET; r = process_hello(p, m); + if (r == -ECONNRESET || r == -ENOTCONN) + return r; if (r < 0) return log_error_errno(r, "Failed to process HELLO: %m"); if (r > 0) return 1; r = bus_proxy_process_driver(p->destination_bus, p->local_bus, m, p->policy, &p->local_creds, p->owned_names); + if (r == -ECONNRESET || r == -ENOTCONN) + return r; if (r < 0) return log_error_errno(r, "Failed to process driver calls: %m"); if (r > 0) @@ -763,25 +770,33 @@ static int proxy_process_local_to_destination(Proxy *p) { for (;;) { if (p->policy) { r = process_policy(p->local_bus, p->destination_bus, m, p->policy, &p->local_creds, p->owned_names); + if (r == -ECONNRESET || r == -ENOTCONN) + return r; if (r < 0) return log_error_errno(r, "Failed to process policy: %m"); - else if (r > 0) + if (r > 0) return 1; } r = sd_bus_send(p->destination_bus, m, NULL); if (r < 0) { - if (r == -EREMCHG) { - /* The name database changed since the policy check, hence let's check again */ + if (r == -ECONNRESET || r == -ENOTCONN) + return r; + + /* The name database changed since the policy check, hence let's check again */ + if (r == -EREMCHG) continue; - } else if (r == -EPERM && m->reply_cookie > 0) { - /* see above why EPERM is ignored for replies */ + + /* see above why EPERM is ignored for replies */ + if (r == -EPERM && m->reply_cookie > 0) return 1; - } else { - if (r != -ECONNRESET) - log_error_errno(r, "Failed to send message to bus: %m"); - return r; - } + + synthetic_reply_method_errnof(m, r, "Failed to forward message we got from local: %m"); + log_error_errno(r, + "Failed to forward message we got from local: uid=" UID_FMT " gid=" GID_FMT" message=%s destination=%s path=%s interface=%s member=%s: %m", + p->local_creds.uid, p->local_creds.gid, bus_message_type_to_string(m->header->type), + strna(m->destination), strna(m->path), strna(m->interface), strna(m->member)); + return 1; } break; @@ -801,7 +816,7 @@ int proxy_run(Proxy *p) { if (p->got_hello) { /* Read messages from bus, to pass them on to our client */ r = proxy_process_destination_to_local(p); - if (r == -ECONNRESET) + if (r == -ECONNRESET || r == -ENOTCONN) return 0; if (r < 0) return r; @@ -811,7 +826,7 @@ int proxy_run(Proxy *p) { /* Read messages from our client, to pass them on to the bus */ r = proxy_process_local_to_destination(p); - if (r == -ECONNRESET) + if (r == -ECONNRESET || r == -ENOTCONN) return 0; if (r < 0) return r; @@ -820,6 +835,8 @@ int proxy_run(Proxy *p) { if (!busy) { r = proxy_wait(p); + if (r == -ECONNRESET || r == -ENOTCONN) + return 0; if (r < 0) return r; }