X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=blobdiff_plain;f=src%2Fbus-driverd%2Fbus-driverd.c;h=7e0ad1e0c05111235d12cf17b75fd74951e3873c;hp=de2344503fe56720cf57712e88d159863a6d9346;hb=950f87b7e569a12c3ee18b38017ccac830ae474e;hpb=76252ffbde7e8163c67d847db2445d8c49e32457 diff --git a/src/bus-driverd/bus-driverd.c b/src/bus-driverd/bus-driverd.c index de2344503..7e0ad1e0c 100644 --- a/src/bus-driverd/bus-driverd.c +++ b/src/bus-driverd/bus-driverd.c @@ -51,6 +51,7 @@ #include "def.h" #include "unit-name.h" #include "bus-control.h" +#include "cgroup-util.h" #define CLIENTS_MAX 1024 #define MATCHES_MAX 1024 @@ -346,7 +347,7 @@ static int driver_remove_match(sd_bus *bus, sd_bus_message *message, void *userd m = hashmap_get(c->matches, normalized); if (!m) { - r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found."); + r = sd_bus_error_setf(error, SD_BUS_ERROR_MATCH_RULE_NOT_FOUND, "Match rule \"%s\" not found.", normalized); goto finish; } @@ -364,19 +365,42 @@ finish: return r; } -static int driver_get_security_ctx(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; - char *arg0; +static int get_creds(sd_bus *bus, sd_bus_message *m, uint64_t mask, sd_bus_creds **_creds, sd_bus_error *error) { + _cleanup_bus_creds_unref_ sd_bus_creds *c = NULL; + const char *name; int r; - r = sd_bus_message_read(m, "s", &arg0); + assert(bus); + assert(m); + assert(_creds); + + r = sd_bus_message_read(m, "s", &name); if (r < 0) return r; - assert_return(service_name_is_valid(arg0), -EINVAL); + assert_return(service_name_is_valid(name), -EINVAL); + + r = sd_bus_get_owner(bus, name, mask, &c); + if (r == -ENOENT || r == -ENXIO) + return sd_bus_error_setf(error, SD_BUS_ERROR_NAME_HAS_NO_OWNER, "Name %s is currently not owned by anyone.", name); + if (r < 0) + return r; + + if ((c->mask & mask) != mask) + return -ENOTSUP; + + *_creds = c; + c = NULL; + + return 0; +} + +static int driver_get_security_context(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + int r; - r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_SELINUX_CONTEXT, &creds); + r = get_creds(bus, m, SD_BUS_CREDS_SELINUX_CONTEXT, &creds, error); if (r < 0) return r; @@ -393,38 +417,35 @@ static int driver_get_security_ctx(sd_bus *bus, sd_bus_message *m, void *userdat static int driver_get_pid(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - char *arg0; int r; - r = sd_bus_message_read(m, "s", &arg0); - if (r < 0) - return r; - - assert_return(service_name_is_valid(arg0), -EINVAL); - - r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_PID, &creds); + r = get_creds(bus, m, SD_BUS_CREDS_PID, &creds, error); if (r < 0) return r; - return sd_bus_reply_method_return(m, "u", creds->pid); + return sd_bus_reply_method_return(m, "u", (uint32_t) creds->pid); } static int driver_get_user(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - char *arg0; int r; - r = sd_bus_message_read(m, "s", &arg0); + r = get_creds(bus, m, SD_BUS_CREDS_UID, &creds, error); if (r < 0) return r; - assert_return(service_name_is_valid(arg0), -EINVAL); + return sd_bus_reply_method_return(m, "u", (uint32_t) creds->uid); +} + +static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + int r; - r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_UID, &creds); + r = get_creds(bus, m, SD_BUS_CREDS_UNIQUE_NAME, &creds, error); if (r < 0) return r; - return sd_bus_reply_method_return(m, "u", creds->uid); + return sd_bus_reply_method_return(m, "s", creds->unique_name); } static int driver_get_id(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { @@ -439,24 +460,6 @@ static int driver_get_id(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_ return sd_bus_reply_method_return(m, "s", sd_id128_to_string(server_id, buf)); } -static int driver_get_name_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; - char *arg0; - int r; - - r = sd_bus_message_read(m, "s", &arg0); - if (r < 0) - return r; - - assert_return(service_name_is_valid(arg0), -EINVAL); - - r = sd_bus_get_owner(bus, arg0, SD_BUS_CREDS_UNIQUE_NAME, &creds); - if (r < 0) - return r; - - return sd_bus_reply_method_return(m, "s", creds->unique_name); -} - static int driver_hello(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { return sd_bus_reply_method_return(m, "s", m->sender); } @@ -535,7 +538,7 @@ static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userd if (!streq(name->name, arg0)) continue; - if (asprintf(&n, ":1.%llu", (unsigned long long) name->id) < 0) + if (asprintf(&n, ":1.%llu", (unsigned long long) name->owner_id) < 0) return -ENOMEM; r = strv_push(&owners, n); @@ -553,17 +556,17 @@ static int driver_list_queued_owners(sd_bus *bus, sd_bus_message *m, void *userd } static int driver_name_has_owner(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { - char *arg0; + const char *name; int r; - r = sd_bus_message_read(m, "s", &arg0); + r = sd_bus_message_read(m, "s", &name); if (r < 0) return r; - assert_return(service_name_is_valid(arg0), -EINVAL); + assert_return(service_name_is_valid(name), -EINVAL); - r = sd_bus_get_owner(bus, arg0, 0, NULL); - if (r < 0 && r != -ENOENT) + r = sd_bus_get_owner(bus, name, 0, NULL); + if (r < 0 && r != -ENOENT && r != -ENXIO) return r; return sd_bus_reply_method_return(m, "b", r >= 0); @@ -597,7 +600,7 @@ static int driver_request_name(sd_bus *bus, sd_bus_message *m, void *userdata, s if (r < 0) return r; - n->id = id; + n->owner_id = id; r = ioctl(bus->input_fd, KDBUS_CMD_NAME_ACQUIRE, n); if (r < 0) { @@ -640,7 +643,7 @@ static int driver_release_name(sd_bus *bus, sd_bus_message *m, void *userdata, s if (r < 0) return r; - n->id = id; + n->owner_id = id; r = ioctl(bus->input_fd, KDBUS_CMD_NAME_RELEASE, n); if (r < 0) { @@ -692,8 +695,8 @@ static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *us if (r < 0) return r; - if (!t[0] || t[1]) - return -EIO; + if (!t || !t[0] || t[1]) + return sd_bus_error_setf(error, SD_BUS_ERROR_SERVICE_UNKNOWN, "Bus name %s not found.", name); r = sd_bus_call_method( bus, @@ -712,14 +715,73 @@ static int driver_start_service_by_name(sd_bus *bus, sd_bus_message *m, void *us return sd_bus_reply_method_return(m, "u", BUS_START_REPLY_SUCCESS); } +static int driver_update_environment(sd_bus*bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { + _cleanup_bus_message_unref_ sd_bus_message *msg = NULL; + _cleanup_strv_free_ char **args = NULL; + int r; + + r = sd_bus_message_enter_container(m, SD_BUS_TYPE_ARRAY, "{ss}"); + if (r < 0) + return r; + + while ((r = sd_bus_message_enter_container(m, SD_BUS_TYPE_DICT_ENTRY, "ss")) > 0) { + _cleanup_free_ char *s = NULL; + const char *key; + const char *value; + + r = sd_bus_message_read(m, "ss", &key, &value); + if (r < 0) + return r; + + s = strjoin(key, "=", value, NULL); + if (!s) + return ENOMEM; + + r = strv_extend(&args, s); + if (r < 0) + return r; + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + } + + r = sd_bus_message_exit_container(m); + if (r < 0) + return r; + + if (!args) + return -EINVAL; + + r = sd_bus_message_new_method_call( + bus, + "org.freedesktop.systemd1", + "/org/freedesktop/systemd1", + "org.freedesktop.systemd1.Manager", + "SetEnvironment", + &msg); + if (r < 0) + return r; + + r = sd_bus_message_append_strv(msg, args); + if (r < 0) + return r; + + r = sd_bus_call(bus, msg, 0, NULL, NULL); + if (r < 0) + return r; + + return sd_bus_reply_method_return(m, NULL); +} + static int driver_unsupported(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus_error *error) { return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED, "%s() is not supported", sd_bus_message_get_member(m)); } static const sd_bus_vtable driver_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, 0), - SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_ctx, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AddMatch", "s", NULL, driver_add_match, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetConnectionSELinuxSecurityContext", "s", "ay", driver_get_security_context, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetConnectionUnixProcessID", "s", "u", driver_get_pid, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetConnectionUnixUser", "s", "u", driver_get_user, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("GetId", NULL, "s", driver_get_id, SD_BUS_VTABLE_UNPRIVILEGED), @@ -734,7 +796,7 @@ static const sd_bus_vtable driver_vtable[] = { SD_BUS_METHOD("RemoveMatch", "s", NULL, driver_remove_match, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("RequestName", "su", "u", driver_request_name, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartServiceByName", "su", "u", driver_start_service_by_name, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_unsupported, SD_BUS_VTABLE_DEPRECATED), + SD_BUS_METHOD("UpdateActivationEnvironment", "a{ss}", NULL, driver_update_environment, 0), SD_BUS_SIGNAL("NameAcquired", "s", SD_BUS_VTABLE_DEPRECATED), SD_BUS_SIGNAL("NameLost", "s", SD_BUS_VTABLE_DEPRECATED), SD_BUS_SIGNAL("NameOwnerChanged", "sss", 0), @@ -746,7 +808,11 @@ static int connect_bus(Context *c) { assert(c); - r = sd_bus_default_system(&c->bus); + r = cg_pid_get_owner_uid(0, NULL); + if (r < 0) + r = sd_bus_default_system(&c->bus); + else + r = sd_bus_default_user(&c->bus); if (r < 0) { log_error("Failed to create bus: %s", strerror(-r)); return r; @@ -765,7 +831,7 @@ static int connect_bus(Context *c) { r = sd_bus_request_name(c->bus, "org.freedesktop.DBus", 0); if (r < 0) { - log_error("Unable to request name: %s\n", strerror(-r)); + log_error("Unable to request name: %s", strerror(-r)); return r; } @@ -826,5 +892,4 @@ finish: sd_event_unref(context.event); return r < 0 ? EXIT_FAILURE : EXIT_SUCCESS; - }