X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Flibsystemd-bus%2Fbus-util.c;h=0a3f6b85f5422796ba4a5f7747feefb742f6c8d3;hp=2140dbc676888c29f25a88832033bfedcae9d318;hb=6e8df5f00a3874decf1e5542da3d65b25f6da1dc;hpb=21586b77de9bad401f245dd55b75cedb0c2e9b7c diff --git a/src/libsystemd-bus/bus-util.c b/src/libsystemd-bus/bus-util.c index 2140dbc67..0a3f6b85f 100644 --- a/src/libsystemd-bus/bus-util.c +++ b/src/libsystemd-bus/bus-util.c @@ -20,6 +20,7 @@ ***/ #include +#include #include "util.h" #include "strv.h" @@ -65,7 +66,7 @@ int bus_async_unregister_and_quit(sd_event *e, sd_bus *bus, const char *name) { if (r < 0) return r; - if (r != SD_BUS_NAME_RELEASED) + if (r != BUS_NAME_RELEASED) return -EIO; return 0; @@ -103,6 +104,32 @@ int bus_event_loop_with_idle(sd_event *e, sd_bus *bus, const char *name, usec_t return 0; } +int bus_name_has_owner(sd_bus *c, const char *name, sd_bus_error *error) { + _cleanup_bus_message_unref_ sd_bus_message *rep = NULL; + int r, has_owner = 0; + + assert(c); + assert(name); + + r = sd_bus_call_method(c, + "org.freedesktop.DBus", + "/org/freedesktop/dbus", + "org.freedesktop.DBus", + "NameHasOwner", + error, + &rep, + "s", + name); + if (r < 0) + return r; + + r = sd_bus_message_read_basic(rep, 'b', &has_owner); + if (r < 0) + return sd_bus_error_set_errno(error, r); + + return has_owner; +} + int bus_verify_polkit( sd_bus *bus, sd_bus_message *m, @@ -111,7 +138,7 @@ int bus_verify_polkit( bool *_challenge, sd_bus_error *e) { - const char *sender; + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uid_t uid; int r; @@ -119,11 +146,11 @@ int bus_verify_polkit( assert(m); assert(action); - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EBADMSG; + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; - r = sd_bus_get_owner_uid(bus, sender, &uid); + r = sd_bus_creds_get_uid(creds, &uid); if (r < 0) return r; @@ -134,6 +161,11 @@ int bus_verify_polkit( else { _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; int authorized = false, challenge = false; + const char *sender; + + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EBADMSG; r = sd_bus_call_method( bus, @@ -206,7 +238,6 @@ static void async_polkit_query_free(sd_bus *b, AsyncPolkitQuery *q) { static int async_polkit_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) { _cleanup_bus_error_free_ sd_bus_error error_buffer = SD_BUS_ERROR_NULL; - _cleanup_bus_message_unref_ sd_bus_message *m = NULL; AsyncPolkitQuery *q = userdata; int r; @@ -246,8 +277,9 @@ int bus_verify_polkit_async( #ifdef ENABLE_POLKIT _cleanup_bus_message_unref_ sd_bus_message *pk = NULL; AsyncPolkitQuery *q; -#endif const char *sender; +#endif + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; uid_t uid; int r; @@ -294,17 +326,21 @@ int bus_verify_polkit_async( } #endif - sender = sd_bus_message_get_sender(m); - if (!sender) - return -EBADMSG; + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; - r = sd_bus_get_owner_uid(bus, sender, &uid); + r = sd_bus_creds_get_uid(creds, &uid); if (r < 0) return r; if (uid == 0) return 1; + #ifdef ENABLE_POLKIT + sender = sd_bus_message_get_sender(m); + if (!sender) + return -EBADMSG; r = hashmap_ensure_allocated(registry, trivial_hash_func, trivial_compare_func); if (r < 0) @@ -403,21 +439,43 @@ int bus_open_system_systemd(sd_bus **_bus) { if (geteuid() != 0) return sd_bus_open_system(_bus); - /* If we are root, then let's talk directly to the system - * instance, instead of going via the bus */ + /* If we are root and kdbus is not available, then let's talk + * directly to the system instance, instead of going via the + * bus */ +#ifdef ENABLE_KDBUS r = sd_bus_new(&bus); if (r < 0) return r; - r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); + r = sd_bus_set_address(bus, "kernel:path=/dev/kdbus/0-system/bus"); if (r < 0) return r; + bus->bus_client = true; + r = sd_bus_start(bus); + if (r >= 0) { + *_bus = bus; + bus = NULL; + return 0; + } + + bus = sd_bus_unref(bus); +#endif + + r = sd_bus_new(&bus); if (r < 0) return r; + r = sd_bus_set_address(bus, "unix:path=/run/systemd/private"); + if (r < 0) + return r; + + r = sd_bus_start(bus); + if (r < 0) + return sd_bus_open_system(_bus); + r = bus_check_peercred(bus); if (r < 0) return r; @@ -430,33 +488,53 @@ int bus_open_system_systemd(sd_bus **_bus) { int bus_open_user_systemd(sd_bus **_bus) { _cleanup_bus_unref_ sd_bus *bus = NULL; - _cleanup_free_ char *p = NULL; + _cleanup_free_ char *ee = NULL; const char *e; int r; - /* If we are supposed to talk to the instance, try via - * XDG_RUNTIME_DIR first, then fallback to normal bus - * access */ + /* Try via kdbus first, and then directly */ assert(_bus); - e = secure_getenv("XDG_RUNTIME_DIR"); - if (e) { - if (asprintf(&p, "unix:path=%s/systemd/private", e) < 0) - return -ENOMEM; - } - +#ifdef ENABLE_KDBUS r = sd_bus_new(&bus); if (r < 0) return r; - r = sd_bus_set_address(bus, p); + if (asprintf(&bus->address, "kernel:path=/dev/kdbus/%lu-user/bus", (unsigned long) getuid()) < 0) + return -ENOMEM; + + bus->bus_client = true; + + r = sd_bus_start(bus); + if (r >= 0) { + *_bus = bus; + bus = NULL; + return 0; + } + + bus = sd_bus_unref(bus); +#endif + + e = secure_getenv("XDG_RUNTIME_DIR"); + if (!e) + return sd_bus_open_system(_bus); + + ee = bus_address_escape(e); + if (!ee) + return -ENOMEM; + + r = sd_bus_new(&bus); if (r < 0) return r; + bus->address = strjoin("unix:path=", ee, "/systemd/private", NULL); + if (!bus->address) + return -ENOMEM; + r = sd_bus_start(bus); if (r < 0) - return r; + return sd_bus_open_system(_bus); r = bus_check_peercred(bus); if (r < 0)