X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fbus-proxyd%2Fbus-proxyd.c;h=4d0a265c6676bd3ea7bf477fa01b4dcd42ce283a;hb=d714387ed7003ce011a3ed0f1a604a7984a8a68d;hp=a7818f546226d3f1359e9360142dd4efa4b4a1fe;hpb=146d47736780e06f618379a6c9f46edcf46803a7;p=elogind.git diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index a7818f546..4d0a265c6 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -189,7 +189,7 @@ static int rename_service(sd_bus *a, sd_bus *b) { assert(a); assert(b); - r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM, &creds); + r = sd_bus_get_owner_creds(b, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_CMDLINE|SD_BUS_CREDS_COMM|SD_BUS_CREDS_AUGMENT, &creds); if (r < 0) return r; @@ -405,6 +405,9 @@ static int synthetic_reply_return_strv(sd_bus_message *call, char **l) { assert(call); + if (call->header->flags & BUS_MESSAGE_NO_REPLY_EXPECTED) + return 0; + r = sd_bus_message_new_method_return(call, &m); if (r < 0) return synthetic_reply_method_errno(call, r, NULL); @@ -1005,6 +1008,24 @@ static int process_policy(sd_bus *from, sd_bus *to, sd_bus_message *m, Policy *p (void) sd_bus_creds_get_uid(&m->creds, &sender_uid); (void) sd_bus_creds_get_gid(&m->creds, &sender_gid); + if (sender_uid == UID_INVALID || sender_gid == GID_INVALID) { + _cleanup_bus_creds_unref_ sd_bus_creds *sender_creds = NULL; + + /* If the message came from another legacy + * client, then the message creds will be + * missing, simply because on legacy clients + * per-message creds were unknown. In this + * case, query the creds of the peer + * instead. */ + + r = bus_get_name_creds_kdbus(from, m->sender, SD_BUS_CREDS_UID|SD_BUS_CREDS_GID, true, &sender_creds); + if (r < 0) + return handle_policy_error(m, r); + + (void) sd_bus_creds_get_uid(sender_creds, &sender_uid); + (void) sd_bus_creds_get_gid(sender_creds, &sender_gid); + } + /* First check whether the sender can send the message to our name */ if (set_isempty(owned_names)) { if (policy_check_send(policy, sender_uid, sender_gid, m->header->type, NULL, m->path, m->interface, m->member)) @@ -1279,6 +1300,7 @@ int main(int argc, char *argv[]) { _cleanup_free_ char *peersec = NULL; Policy policy_buffer = {}, *policy = NULL; _cleanup_set_free_free_ Set *owned_names = NULL; + uid_t original_uid; log_set_target(LOG_TARGET_JOURNAL_OR_KMSG); log_parse_environment(); @@ -1300,6 +1322,8 @@ int main(int argc, char *argv[]) { goto finish; } + original_uid = getuid(); + is_unix = sd_is_socket(in_fd, AF_UNIX, 0, 0) > 0 && sd_is_socket(out_fd, AF_UNIX, 0, 0) > 0; @@ -1441,7 +1465,11 @@ int main(int argc, char *argv[]) { policy = &policy_buffer; /* policy_dump(policy); */ - if (!policy_check_hello(policy, ucred.uid, ucred.gid)) { + if (ucred.uid == original_uid) + log_debug("Permitting access, since bus owner matches bus client."); + else if (policy_check_hello(policy, ucred.uid, ucred.gid)) + log_debug("Permitting access due to XML policy."); + else { r = log_error_errno(EPERM, "Policy denied connection."); goto finish; } @@ -1602,14 +1630,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; } @@ -1679,17 +1719,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;