X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbus-proxyd%2Fbus-proxyd.c;h=b6933417a1519dda59c422cde602410021f6343f;hp=0574eb056730a6e606f1496a321a5ecdb1f71b65;hb=91fd0103cc1525c66e3efb03ef781e9553437724;hpb=f3c4724635951c5b8a2b3f3c3f25798ce4d290cd diff --git a/src/bus-proxyd/bus-proxyd.c b/src/bus-proxyd/bus-proxyd.c index 0574eb056..b6933417a 100644 --- a/src/bus-proxyd/bus-proxyd.c +++ b/src/bus-proxyd/bus-proxyd.c @@ -570,94 +570,127 @@ static int patch_sender(sd_bus *a, sd_bus_message *m) { return 0; } -static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) { -#ifdef HAVE_SMACK - int r = 0, k; +static int bus_new_destination(sd_bus **out, struct ucred *ucred, const char *peersec, bool negotiate_fds) { + _cleanup_bus_close_unref_ sd_bus *a = NULL; + int r; - if (!mac_smack_use()) - return 0; + r = sd_bus_new(&a); + if (r < 0) + return log_error_errno(r, "Failed to allocate bus: %m"); - if (new_label && its_pid > 0) - r = mac_smack_apply_pid(its_pid, new_label); + r = sd_bus_set_description(a, "sd-proxy"); + if (r < 0) + return log_error_errno(r, "Failed to set bus name: %m"); - k = drop_capability(CAP_MAC_ADMIN); - return r < 0 ? r : k; -#else - return 0; -#endif -} + r = sd_bus_set_address(a, arg_address); + if (r < 0) + return log_error_errno(r, "Failed to set address to connect to: %m"); -static int synthesize_name_acquired(sd_bus *a, sd_bus *b, sd_bus_message *m) { - _cleanup_bus_message_unref_ sd_bus_message *n = NULL; - const char *name, *old_owner, *new_owner; - int r; + r = sd_bus_negotiate_fds(a, negotiate_fds); + if (r < 0) + return log_error_errno(r, "Failed to set FD negotiation: %m"); - assert(a); - assert(b); - assert(m); + r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT); + if (r < 0) + return log_error_errno(r, "Failed to set credential negotiation: %m"); - /* If we get NameOwnerChanged for our own name, we need to - * synthesize NameLost/NameAcquired, since socket clients need - * that, even though it is obsoleted on kdbus */ + if (ucred->pid > 0) { + a->fake_pids.pid = ucred->pid; + a->fake_pids_valid = true; - if (!a->is_kernel) - return 0; + a->fake_creds.uid = ucred->uid; + a->fake_creds.euid = UID_INVALID; + a->fake_creds.suid = UID_INVALID; + a->fake_creds.fsuid = UID_INVALID; + a->fake_creds.gid = ucred->gid; + a->fake_creds.egid = GID_INVALID; + a->fake_creds.sgid = GID_INVALID; + a->fake_creds.fsgid = GID_INVALID; + a->fake_creds_valid = true; + } - if (!sd_bus_message_is_signal(m, "org.freedesktop.DBus", "NameOwnerChanged") || - !streq_ptr(m->path, "/org/freedesktop/DBus") || - !streq_ptr(m->sender, "org.freedesktop.DBus")) - return 0; + if (peersec) { + a->fake_label = strdup(peersec); + if (!a->fake_label) + return log_oom(); + } - r = sd_bus_message_read(m, "sss", &name, &old_owner, &new_owner); - if (r < 0) - return r; + a->manual_peer_interface = true; - r = sd_bus_message_rewind(m, true); + r = sd_bus_start(a); if (r < 0) - return r; + return log_error_errno(r, "Failed to start bus client: %m"); - if (streq(old_owner, a->unique_name)) { + *out = a; + a = NULL; + return 0; +} - r = sd_bus_message_new_signal( - b, - &n, - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "NameLost"); +static int bus_new_local(sd_bus **out, sd_bus *dest, int in_fd, int out_fd, bool negotiate_fds) { + _cleanup_bus_close_unref_ sd_bus *b = NULL; + sd_id128_t server_id; + int r; - } else if (streq(new_owner, a->unique_name)) { + r = sd_bus_new(&b); + if (r < 0) + return log_error_errno(r, "Failed to allocate bus: %m"); - r = sd_bus_message_new_signal( - b, - &n, - "/org/freedesktop/DBus", - "org.freedesktop.DBus", - "NameAcquired"); - } else - return 0; + r = sd_bus_set_fd(b, in_fd, out_fd); + if (r < 0) + return log_error_errno(r, "Failed to set fds: %m"); + r = sd_bus_get_bus_id(dest, &server_id); if (r < 0) - return r; + return log_error_errno(r, "Failed to get server ID: %m"); - r = sd_bus_message_append(n, "s", name); + r = sd_bus_set_server(b, 1, server_id); if (r < 0) - return r; + return log_error_errno(r, "Failed to set server mode: %m"); - r = bus_message_append_sender(n, "org.freedesktop.DBus"); + r = sd_bus_negotiate_fds(b, negotiate_fds); if (r < 0) - return r; + return log_error_errno(r, "Failed to set FD negotiation: %m"); - r = bus_seal_synthetic_message(b, n); + r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT); if (r < 0) - return r; + return log_error_errno(r, "Failed to set credential negotiation: %m"); + + r = sd_bus_set_anonymous(b, true); + if (r < 0) + return log_error_errno(r, "Failed to set anonymous authentication: %m"); + + b->manual_peer_interface = true; + + r = sd_bus_start(b); + if (r < 0) + return log_error_errno(r, "Failed to start bus client: %m"); + + *out = b; + b = NULL; + return 0; +} + +static int mac_smack_apply_label_and_drop_cap_mac_admin(pid_t its_pid, const char *new_label) { +#ifdef HAVE_SMACK + int r = 0, k; + + if (!mac_smack_use()) + return 0; + + if (new_label && its_pid > 0) + r = mac_smack_apply_pid(its_pid, new_label); - return sd_bus_send(b, n, NULL); + k = drop_capability(CAP_MAC_ADMIN); + return r < 0 ? r : k; +#else + return 0; +#endif } + int main(int argc, char *argv[]) { _cleanup_bus_close_unref_ sd_bus *a = NULL, *b = NULL; - sd_id128_t server_id; int r, in_fd, out_fd; bool got_hello = false; bool is_unix; @@ -724,69 +757,9 @@ int main(int argc, char *argv[]) { goto finish; } - r = sd_bus_new(&a); - if (r < 0) { - log_error_errno(r, "Failed to allocate bus: %m"); - goto finish; - } - - r = sd_bus_set_description(a, "sd-proxy"); - if (r < 0) { - log_error_errno(r, "Failed to set bus name: %m"); - goto finish; - } - - r = sd_bus_set_address(a, arg_address); - if (r < 0) { - log_error_errno(r, "Failed to set address to connect to: %m"); - goto finish; - } - - r = sd_bus_negotiate_fds(a, is_unix); - if (r < 0) { - log_error_errno(r, "Failed to set FD negotiation: %m"); - goto finish; - } - - r = sd_bus_negotiate_creds(a, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT); - if (r < 0) { - log_error_errno(r, "Failed to set credential negotiation: %m"); - goto finish; - } - - if (ucred.pid > 0) { - a->fake_pids.pid = ucred.pid; - a->fake_pids_valid = true; - - a->fake_creds.uid = ucred.uid; - a->fake_creds.euid = UID_INVALID; - a->fake_creds.suid = UID_INVALID; - a->fake_creds.fsuid = UID_INVALID; - a->fake_creds.gid = ucred.gid; - a->fake_creds.egid = GID_INVALID; - a->fake_creds.sgid = GID_INVALID; - a->fake_creds.fsgid = GID_INVALID; - a->fake_creds_valid = true; - } - - if (peersec) { - a->fake_label = peersec; - peersec = NULL; - } - - a->manual_peer_interface = true; - - r = sd_bus_start(a); - if (r < 0) { - log_error_errno(r, "Failed to start bus client: %m"); - goto finish; - } - - r = sd_bus_get_bus_id(a, &server_id); - if (r < 0) { - log_error_errno(r, "Failed to get server ID: %m"); + r = bus_new_destination(&a, &ucred, peersec, is_unix); + if (r < 0) goto finish; - } if (a->is_kernel) { if (!arg_configuration) { @@ -840,49 +813,9 @@ int main(int argc, char *argv[]) { } } - r = sd_bus_new(&b); - if (r < 0) { - log_error_errno(r, "Failed to allocate bus: %m"); - goto finish; - } - - r = sd_bus_set_fd(b, in_fd, out_fd); - if (r < 0) { - log_error_errno(r, "Failed to set fds: %m"); - goto finish; - } - - r = sd_bus_set_server(b, 1, server_id); - if (r < 0) { - log_error_errno(r, "Failed to set server mode: %m"); - goto finish; - } - - r = sd_bus_negotiate_fds(b, is_unix); - if (r < 0) { - log_error_errno(r, "Failed to set FD negotiation: %m"); - goto finish; - } - - r = sd_bus_negotiate_creds(b, true, SD_BUS_CREDS_UID|SD_BUS_CREDS_PID|SD_BUS_CREDS_GID|SD_BUS_CREDS_SELINUX_CONTEXT); - if (r < 0) { - log_error_errno(r, "Failed to set credential negotiation: %m"); - goto finish; - } - - r = sd_bus_set_anonymous(b, true); - if (r < 0) { - log_error_errno(r, "Failed to set anonymous authentication: %m"); - goto finish; - } - - b->manual_peer_interface = true; - - r = sd_bus_start(b); - if (r < 0) { - log_error_errno(r, "Failed to start bus client: %m"); + r = bus_new_local(&b, a, in_fd, out_fd, is_unix); + if (r < 0) goto finish; - } r = rename_service(a, b); if (r < 0)