From: Lennart Poettering Date: Tue, 10 Dec 2013 16:41:39 +0000 (+0000) Subject: bus: introduce "trusted" bus concept and encode access control in object vtables X-Git-Tag: v209~1055 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=adacb9575a09981fcf11279f2f661e3fc21e58ff;p=thirdparty%2Fsystemd.git bus: introduce "trusted" bus concept and encode access control in object vtables Introduces a new concept of "trusted" vs. "untrusted" busses. For the latter libsystemd-bus will automatically do per-method access control, for the former all access is automatically granted. Per-method access control is encoded in the vtables: by default all methods are only accessible to privileged clients. If the SD_BUS_VTABLE_UNPRIVILEGED flag is set for a method it is accessible to unprivileged clients too. By default whether a client is privileged is determined via checking for its CAP_SYS_ADMIN capability, but this can be altered via the SD_BUS_VTABLE_CAPABILITY() macro that can be ORed into the flags field of the method. Writable properties are also subject to SD_BUS_VTABLE_UNPRIVILEGED and SD_BUS_VTABLE_CAPABILITY() for controlling write access to them. Note however that read access is unrestricted, as PropertiesChanged messages might send out the values anyway as an unrestricted broadcast. By default the system bus is set to "untrusted" and the user bus is "trusted" since per-method access control on the latter is unnecessary. On dbus1 busses we check the UID of the caller rather than the configured capability since the capability cannot be determined without race. On kdbus the capability is checked if possible from the attached meta-data of a message and otherwise queried from the sending peer. This also decorates the vtables of the various daemons we ship with these flags. --- diff --git a/TODO b/TODO index 253d0bf1b2e..dac44e0c6a6 100644 --- a/TODO +++ b/TODO @@ -112,8 +112,6 @@ Features: ReadOnlyDirectories=... for whitelisting files for a service. * libsystemd-bus: - - default policy (allow uid == 0 and our own uid) - - access policy as vtable flag - when kdbus doesn't take our message without memfds, try again with memfds - implement translator service - implement monitor logic diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index a2707ee9b74..9c2194b0e53 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -1566,9 +1566,9 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_WRITABLE_PROPERTY("RuntimeWatchdogUSec", "t", bus_property_get_usec, property_set_runtime_watchdog, offsetof(Manager, runtime_watchdog), 0), SD_BUS_WRITABLE_PROPERTY("ShutdownWatchdogUSec", "t", bus_property_get_usec, bus_property_set_usec, offsetof(Manager, shutdown_watchdog), 0), - SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, 0), - SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, 0), - SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, 0), + SD_BUS_METHOD("GetUnit", "s", "o", method_get_unit, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByPID", "u", "o", method_get_unit_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("LoadUnit", "s", "o", method_load_unit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnit", "ss", "o", method_start_unit, 0), SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, 0), SD_BUS_METHOD("StopUnit", "ss", "o", method_stop_unit, 0), @@ -1577,34 +1577,34 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("TryRestartUnit", "ss", "o", method_try_restart_unit, 0), SD_BUS_METHOD("ReloadOrRestartUnit", "ss", "o", method_reload_or_restart_unit, 0), SD_BUS_METHOD("ReloadOrTryRestartUnit", "ss", "o", method_reload_or_try_restart_unit, 0), - SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, 0), + SD_BUS_METHOD("KillUnit", "ssi", NULL, method_kill_unit, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_METHOD("ResetFailedUnit", "s", NULL, method_reset_failed_unit, 0), SD_BUS_METHOD("SetUnitProperties", "sba(sv)", NULL, method_set_unit_properties, 0), SD_BUS_METHOD("StartTransientUnit", "ssa(sv)a(sa(sv))", "o", method_start_transient_unit, 0), - SD_BUS_METHOD("GetJob", "u", "o", method_get_job, 0), + SD_BUS_METHOD("GetJob", "u", "o", method_get_job, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CancelJob", "u", NULL, method_cancel_job, 0), SD_BUS_METHOD("ClearJobs", NULL, NULL, method_clear_jobs, 0), SD_BUS_METHOD("ResetFailed", NULL, NULL, method_reset_failed, 0), - SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, 0), - SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, 0), - SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, 0), - SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, 0), - SD_BUS_METHOD("Dump", NULL, "s", method_dump, 0), + SD_BUS_METHOD("ListUnits", NULL, "a(ssssssouso)", method_list_units, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListJobs", NULL, "a(usssoo)", method_list_jobs, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Subscribe", NULL, NULL, method_subscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Unsubscribe", NULL, NULL, method_unsubscribe, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Dump", NULL, "s", method_dump, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_create_snapshot, 0), SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_remove_snapshot, 0), SD_BUS_METHOD("Reload", NULL, NULL, method_reload, 0), SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, 0), SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0), - SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, 0), - SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, 0), - SD_BUS_METHOD("Halt", NULL, NULL, method_halt, 0), - SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, 0), - SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, 0), + SD_BUS_METHOD("Reboot", NULL, NULL, method_reboot, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("PowerOff", NULL, NULL, method_poweroff, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("Halt", NULL, NULL, method_halt, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("KExec", NULL, NULL, method_kexec, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), + SD_BUS_METHOD("SwitchRoot", "ss", NULL, method_switch_root, SD_BUS_VTABLE_CAPABILITY(CAP_SYS_BOOT)), SD_BUS_METHOD("SetEnvironment", "as", NULL, method_set_environment, 0), SD_BUS_METHOD("UnsetEnvironment", "as", NULL, method_unset_environment, 0), SD_BUS_METHOD("UnsetAndSetEnvironment", "asas", NULL, method_unset_and_set_environment, 0), - SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, 0), - SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, 0), + SD_BUS_METHOD("ListUnitFiles", NULL, "a(ss)", method_list_unit_files, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitFileState", "s", "s", method_get_unit_file_state, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("EnableUnitFiles", "asbb", "ba(sss)", method_enable_unit_files, 0), SD_BUS_METHOD("DisableUnitFiles", "asb", "a(sss)", method_disable_unit_files, 0), SD_BUS_METHOD("ReenableUnitFiles", "asbb", "ba(sss)", method_reenable_unit_files, 0), @@ -1613,7 +1613,7 @@ const sd_bus_vtable bus_manager_vtable[] = { SD_BUS_METHOD("MaskUnitFiles", "asbb", "a(sss)", method_mask_unit_files, 0), SD_BUS_METHOD("UnmaskUnitFiles", "asb", "a(sss)", method_unmask_unit_files, 0), SD_BUS_METHOD("SetDefaultTarget", "sb", "a(sss)", method_set_default_target, 0), - SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, 0), + SD_BUS_METHOD("GetDefaultTarget", NULL, "s", method_get_default_target, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("UnitNew", "so", 0), SD_BUS_SIGNAL("UnitRemoved", "so", 0), diff --git a/src/hostname/hostnamed.c b/src/hostname/hostnamed.c index 90829660573..f7ae50dcd8a 100644 --- a/src/hostname/hostnamed.c +++ b/src/hostname/hostnamed.c @@ -546,11 +546,11 @@ static const sd_bus_vtable hostname_vtable[] = { SD_BUS_PROPERTY("PrettyHostname", "s", NULL, offsetof(Context, data) + sizeof(char*) * PROP_PRETTY_HOSTNAME, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IconName", "s", property_get_icon_name, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Chassis", "s", property_get_chassis, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, 0), - SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, 0), - SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, 0), - SD_BUS_METHOD("SetIconName", "sb", NULL, method_set_icon_name, 0), - SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, 0), + SD_BUS_METHOD("SetHostname", "sb", NULL, method_set_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetStaticHostname", "sb", NULL, method_set_static_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetPrettyHostname", "sb", NULL, method_set_pretty_hostname, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetIconName", "sb", NULL, method_set_icon_name, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetChassis", "sb", NULL, method_set_chassis, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, }; diff --git a/src/libsystemd-bus/bus-internal.h b/src/libsystemd-bus/bus-internal.h index 4881e0427c9..1be7488ab93 100644 --- a/src/libsystemd-bus/bus-internal.h +++ b/src/libsystemd-bus/bus-internal.h @@ -159,6 +159,7 @@ struct sd_bus { bool match_callbacks_modified:1; bool filter_callbacks_modified:1; bool nodes_modified:1; + bool trusted:1; int use_memfd; diff --git a/src/libsystemd-bus/bus-introspect.c b/src/libsystemd-bus/bus-introspect.c index 115b3ceae87..8bec017d639 100644 --- a/src/libsystemd-bus/bus-introspect.c +++ b/src/libsystemd-bus/bus-introspect.c @@ -77,7 +77,7 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) { if (flags & SD_BUS_VTABLE_DEPRECATED) fputs(" \n", i->f); - if (type == _SD_BUS_VTABLE_METHOD && flags & SD_BUS_VTABLE_METHOD_NO_REPLY) + if (type == _SD_BUS_VTABLE_METHOD && (flags & SD_BUS_VTABLE_METHOD_NO_REPLY)) fputs(" \n", i->f); if (type == _SD_BUS_VTABLE_PROPERTY || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) { @@ -86,6 +86,9 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) { else if (flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY) fputs(" \n", i->f); } + + if ((type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) && (flags & SD_BUS_VTABLE_UNPRIVILEGED)) + fputs(" \n", i->f); } static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) { diff --git a/src/libsystemd-bus/bus-objects.c b/src/libsystemd-bus/bus-objects.c index 7cd34c991b0..941c2810d87 100644 --- a/src/libsystemd-bus/bus-objects.c +++ b/src/libsystemd-bus/bus-objects.c @@ -19,6 +19,8 @@ along with systemd; If not, see . ***/ +#include + #include "strv.h" #include "set.h" #include "bus-internal.h" @@ -264,6 +266,64 @@ static int node_callbacks_run( return 0; } +#define CAPABILITY_SHIFT(x) (((x) >> __builtin_ctzll(_SD_BUS_VTABLE_CAPABILITY_MASK)) & 0xFFFF) + +static int check_access(sd_bus *bus, sd_bus_message *m, struct vtable_member *c, sd_bus_error *error) { + _cleanup_bus_creds_unref_ sd_bus_creds *creds = NULL; + uint64_t cap; + uid_t uid; + int r; + + assert(bus); + assert(m); + assert(c); + + /* If the entire bus is trusted let's grant access */ + if (bus->trusted) + return 0; + + /* If the member is marked UNPRIVILEGED let's grant access */ + if (c->vtable->flags & SD_BUS_VTABLE_UNPRIVILEGED) + return 0; + + /* If we are not connected to kdbus we cannot retrieve the + * effective capability set without race. Since we need this + * for a security decision we cannot use racy data, hence + * don't request it. */ + if (bus->is_kernel) + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID|SD_BUS_CREDS_EFFECTIVE_CAPS, &creds); + else + r = sd_bus_query_sender_creds(m, SD_BUS_CREDS_UID, &creds); + if (r < 0) + return r; + + /* Check have the caller has the requested capability + * set. Note that the flags value contains the capability + * number plus one, which we need to subtract here. We do this + * so that we have 0 as special value for "default + * capability". */ + cap = CAPABILITY_SHIFT(c->vtable->flags); + if (cap == 0) + cap = CAPABILITY_SHIFT(c->parent->vtable[0].flags); + if (cap == 0) + cap = CAP_SYS_ADMIN; + else + cap --; + + r = sd_bus_creds_has_effective_cap(creds, cap); + if (r > 0) + return 1; + + /* Caller has same UID as us, then let's grant access */ + r = sd_bus_creds_get_uid(creds, &uid); + if (r >= 0) { + if (uid == getuid()) + return 1; + } + + return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Access to %s.%s() not permitted.", c->interface, c->member); +} + static int method_callbacks_run( sd_bus *bus, sd_bus_message *m, @@ -284,6 +344,10 @@ static int method_callbacks_run( if (require_fallback && !c->parent->is_fallback) return 0; + r = check_access(bus, m, c, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + r = node_vtable_get_userdata(bus, m->path, c->parent, &u, &error); if (r <= 0) return bus_maybe_reply_error(m, r, &error); @@ -498,6 +562,11 @@ static int property_get_set_callbacks_run( if (r < 0) return r; + /* Note that we do not do an access check here. Read + * access to properties is always unrestricted, since + * PropertiesChanged signals broadcast contents + * anyway. */ + r = invoke_property_get(bus, c->vtable, m->path, c->interface, c->member, reply, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); @@ -525,6 +594,10 @@ static int property_get_set_callbacks_run( if (r < 0) return r; + r = check_access(bus, m, c, &error); + if (r < 0) + return bus_maybe_reply_error(m, r, &error); + r = invoke_property_set(bus, c->vtable, m->path, c->interface, c->member, m, u, &error); if (r < 0) return bus_maybe_reply_error(m, r, &error); @@ -1199,12 +1272,12 @@ int bus_process_object(sd_bus *bus, sd_bus_message *m) { if (m->header->type != SD_BUS_MESSAGE_METHOD_CALL) return 0; - if (!m->path) - return 0; - if (hashmap_isempty(bus->nodes)) return 0; + assert(m->path); + assert(m->member); + pl = strlen(m->path); do { char prefix[pl+1]; @@ -1636,7 +1709,8 @@ static int add_object_vtable_internal( !signature_is_single(v->x.property.signature, false) || !(v->x.property.get || bus_type_is_basic(v->x.property.signature[0]) || streq(v->x.property.signature, "as")) || v->flags & SD_BUS_VTABLE_METHOD_NO_REPLY || - (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE))) { + (v->flags & SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY && !(v->flags & SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE)) || + (v->flags & SD_BUS_VTABLE_UNPRIVILEGED && v->type == _SD_BUS_VTABLE_PROPERTY)) { r = -EINVAL; goto fail; } @@ -1666,7 +1740,8 @@ static int add_object_vtable_internal( case _SD_BUS_VTABLE_SIGNAL: if (!member_name_is_valid(v->x.signal.member) || - !signature_is_valid(strempty(v->x.signal.signature), false)) { + !signature_is_valid(strempty(v->x.signal.signature), false) || + v->flags & SD_BUS_VTABLE_UNPRIVILEGED) { r = -EINVAL; goto fail; } diff --git a/src/libsystemd-bus/libsystemd-bus.sym b/src/libsystemd-bus/libsystemd-bus.sym index 389efc32738..7bc1ef9ad20 100644 --- a/src/libsystemd-bus/libsystemd-bus.sym +++ b/src/libsystemd-bus/libsystemd-bus.sym @@ -25,6 +25,7 @@ global: sd_bus_set_bus_client; sd_bus_set_server; sd_bus_set_anonymous; + sd_bus_set_trusted; sd_bus_negotiate_fds; sd_bus_negotiate_attach_timestamp; sd_bus_negotiate_attach_creds; diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index fef122bf3ed..81bfe0d9220 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -318,6 +318,15 @@ _public_ int sd_bus_set_anonymous(sd_bus *bus, int b) { return 0; } +_public_ int sd_bus_set_trusted(sd_bus *bus, int b) { + assert_return(bus, -EINVAL); + assert_return(bus->state == BUS_UNSET, -EPERM); + assert_return(!bus_pid_changed(bus), -ECHILD); + + bus->trusted = !!b; + return 0; +} + static int hello_callback(sd_bus *bus, sd_bus_message *reply, void *userdata, sd_bus_error *error) { const char *s; int r; @@ -1005,6 +1014,11 @@ _public_ int sd_bus_open_system(sd_bus **ret) { b->bus_client = true; + /* Let's do per-method access control on the system bus. We + * need the caller's UID and capability set for that. */ + b->trusted = false; + b->attach_flags |= KDBUS_ATTACH_CAPS | KDBUS_ATTACH_CREDS; + r = sd_bus_start(b); if (r < 0) goto fail; @@ -1065,6 +1079,10 @@ _public_ int sd_bus_open_user(sd_bus **ret) { b->bus_client = true; + /* We don't do any per-method access control on the user + * bus. */ + b->trusted = true; + r = sd_bus_start(b); if (r < 0) goto fail; diff --git a/src/locale/localed.c b/src/locale/localed.c index 0382232167e..abb610d3325 100644 --- a/src/locale/localed.c +++ b/src/locale/localed.c @@ -1068,9 +1068,9 @@ static const sd_bus_vtable locale_vtable[] = { SD_BUS_PROPERTY("X11Options", "s", NULL, offsetof(Context, x11_options), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("VConsoleKeymap", "s", NULL, offsetof(Context, vc_keymap), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("VConsoleKeymapToggle", "s", NULL, offsetof(Context, vc_keymap_toggle), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, 0), - SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, 0), - SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, 0), + SD_BUS_METHOD("SetLocale", "asb", NULL, method_set_locale, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetVConsoleKeyboard", "ssbb", NULL, method_set_vc_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetX11Keyboard", "ssssbb", NULL, method_set_x11_keyboard, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/login/logind-dbus.c b/src/login/logind-dbus.c index 0461d1877e7..2568eb0364c 100644 --- a/src/login/logind-dbus.c +++ b/src/login/logind-dbus.c @@ -23,6 +23,7 @@ #include #include #include +#include #include "sd-id128.h" #include "sd-messages.h" @@ -1879,42 +1880,42 @@ const sd_bus_vtable manager_vtable[] = { SD_BUS_PROPERTY("PreparingForShutdown", "b", property_get_preparing, 0, 0), SD_BUS_PROPERTY("PreparingForSleep", "b", property_get_preparing, 0, 0), - SD_BUS_METHOD("GetSession", "s", "o", method_get_session, 0), - SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, 0), - SD_BUS_METHOD("GetUser", "u", "o", method_get_user, 0), - SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, 0), - SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, 0), - SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, 0), - SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, 0), - SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, 0), - SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, 0), + SD_BUS_METHOD("GetSession", "s", "o", method_get_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetSessionByPID", "u", "o", method_get_session_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUser", "u", "o", method_get_user, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUserByPID", "u", "o", method_get_user_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetSeat", "s", "o", method_get_seat, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListSessions", NULL, "a(susso)", method_list_sessions, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListUsers", NULL, "a(uso)", method_list_users, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListSeats", NULL, "a(so)", method_list_seats, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListInhibitors", NULL, "a(ssssuu)", method_list_inhibitors, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateSession", "uussssussbssa(sv)", "soshusub", method_create_session, 0), SD_BUS_METHOD("ReleaseSession", "s", NULL, method_release_session, 0), - SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0), - SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, 0), + SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ActivateSessionOnSeat", "ss", NULL, method_activate_session_on_seat, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("LockSession", "s", NULL, method_lock_session, 0), SD_BUS_METHOD("UnlockSession", "s", NULL, method_lock_session, 0), SD_BUS_METHOD("LockSessions", NULL, NULL, method_lock_sessions, 0), SD_BUS_METHOD("UnlockSessions", NULL, NULL, method_lock_sessions, 0), - SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, 0), - SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, 0), - SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, 0), - SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, 0), - SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, 0), - SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, 0), - SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, 0), - SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, 0), - SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, 0), - SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, 0), - SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, 0), - SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, 0), - SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, 0), - SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, 0), - SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, 0), - SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, 0), - SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, 0), - SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, 0), - SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, 0), + SD_BUS_METHOD("KillSession", "ssi", NULL, method_kill_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("KillUser", "ui", NULL, method_kill_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("TerminateSession", "s", NULL, method_terminate_session, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("TerminateUser", "u", NULL, method_terminate_user, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("TerminateSeat", "s", NULL, method_terminate_seat, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("SetUserLinger", "ubb", NULL, method_set_user_linger, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("AttachDevice", "ssb", NULL, method_attach_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("FlushDevices", "b", NULL, method_flush_devices, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PowerOff", "b", NULL, method_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Reboot", "b", NULL, method_reboot, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Suspend", "b", NULL, method_suspend, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Hibernate", "b", NULL, method_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("HybridSleep", "b", NULL, method_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanPowerOff", NULL, "s", method_can_poweroff, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanReboot", NULL, "s", method_can_reboot, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanSuspend", NULL, "s", method_can_suspend, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanHibernate", NULL, "s", method_can_hibernate, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CanHybridSleep", NULL, "s", method_can_hybrid_sleep, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Inhibit", "ssss", "h", method_inhibit, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("SessionNew", "so", 0), SD_BUS_SIGNAL("SessionRemoved", "so", 0), diff --git a/src/login/logind-seat-dbus.c b/src/login/logind-seat-dbus.c index 23f975bca7e..9271bcf81c5 100644 --- a/src/login/logind-seat-dbus.c +++ b/src/login/logind-seat-dbus.c @@ -21,6 +21,7 @@ #include #include +#include #include "util.h" #include "bus-util.h" @@ -248,8 +249,8 @@ const sd_bus_vtable seat_vtable[] = { SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0), - SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, 0), + SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("ActivateSession", "s", NULL, method_activate_session, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END }; diff --git a/src/login/logind-session-dbus.c b/src/login/logind-session-dbus.c index 4bbe75e428c..85958093960 100644 --- a/src/login/logind-session-dbus.c +++ b/src/login/logind-session-dbus.c @@ -21,6 +21,7 @@ #include #include +#include #include "util.h" #include "strv.h" @@ -455,17 +456,17 @@ const sd_bus_vtable session_vtable[] = { SD_BUS_PROPERTY("IdleSinceHint", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), - SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0), - SD_BUS_METHOD("Activate", NULL, NULL, method_activate, 0), + SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("Activate", NULL, NULL, method_activate, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Lock", NULL, NULL, method_lock, 0), SD_BUS_METHOD("Unlock", NULL, NULL, method_lock, 0), - SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, 0), - SD_BUS_METHOD("Kill", "si", NULL, method_kill, 0), - SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, 0), - SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, 0), - SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, 0), - SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, 0), - SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, 0), + SD_BUS_METHOD("SetIdleHint", "b", NULL, method_set_idle_hint, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("Kill", "si", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("TakeControl", "b", NULL, method_take_control, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseControl", NULL, NULL, method_release_control, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("TakeDevice", "uu", "hb", method_take_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ReleaseDevice", "uu", NULL, method_release_device, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("PauseDeviceComplete", "uu", NULL, method_pause_device_complete, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_SIGNAL("PauseDevice", "uus", 0), SD_BUS_SIGNAL("ResumeDevice", "uuh", 0), diff --git a/src/login/logind-user-dbus.c b/src/login/logind-user-dbus.c index b0345152034..817bbb87e7b 100644 --- a/src/login/logind-user-dbus.c +++ b/src/login/logind-user-dbus.c @@ -21,10 +21,10 @@ #include #include +#include #include "strv.h" #include "bus-util.h" - #include "logind.h" #include "logind-user.h" @@ -229,8 +229,8 @@ const sd_bus_vtable user_vtable[] = { SD_BUS_PROPERTY("IdleSinceHintMonotonic", "t", property_get_idle_since_hint, 0, SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), SD_BUS_PROPERTY("Linger", "b", property_get_linger, 0, 0), - SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, 0), - SD_BUS_METHOD("Kill", "i", NULL, method_kill, 0), + SD_BUS_METHOD("Terminate", NULL, NULL, method_terminate, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("Kill", "i", NULL, method_kill, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_VTABLE_END }; diff --git a/src/login/org.freedesktop.login1.conf b/src/login/org.freedesktop.login1.conf index 04e735eb591..d677f61f1d4 100644 --- a/src/login/org.freedesktop.login1.conf +++ b/src/login/org.freedesktop.login1.conf @@ -50,19 +50,19 @@ + send_member="GetUserByPID"/> + send_member="GetSeat"/> + send_member="ListSessions"/> + send_member="ListUsers"/> #include #include +#include #include "sd-id128.h" #include "sd-messages.h" @@ -342,12 +343,12 @@ static int method_kill_machine(sd_bus *bus, sd_bus_message *message, void *userd const sd_bus_vtable manager_vtable[] = { SD_BUS_VTABLE_START(0), - SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, 0), - SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, 0), - SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, 0), + SD_BUS_METHOD("GetMachine", "s", "o", method_get_machine, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetMachineByPID", "u", "o", method_get_machine_by_pid, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("ListMachines", NULL, "a(ssso)", method_list_machines, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("CreateMachine", "sayssusa(sv)", "o", method_create_machine, 0), - SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, 0), - SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, 0), + SD_BUS_METHOD("KillMachine", "ssi", NULL, method_kill_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), + SD_BUS_METHOD("TerminateMachine", "s", NULL, method_terminate_machine, SD_BUS_VTABLE_CAPABILITY(CAP_KILL)), SD_BUS_SIGNAL("MachineNew", "so", 0), SD_BUS_SIGNAL("MachineRemoved", "so", 0), SD_BUS_VTABLE_END diff --git a/src/machine/org.freedesktop.machine1.conf b/src/machine/org.freedesktop.machine1.conf index b2d6df31216..970ccd8d69d 100644 --- a/src/machine/org.freedesktop.machine1.conf +++ b/src/machine/org.freedesktop.machine1.conf @@ -44,6 +44,10 @@ send_interface="org.freedesktop.machine1.Manager" send_member="GetMachine"/> + + diff --git a/src/systemd/sd-bus-vtable.h b/src/systemd/sd-bus-vtable.h index 18fc30bd209..e6e0a72f8ab 100644 --- a/src/systemd/sd-bus-vtable.h +++ b/src/systemd/sd-bus-vtable.h @@ -31,28 +31,32 @@ typedef struct sd_bus_vtable sd_bus_vtable; #include "sd-bus.h" enum { - _SD_BUS_VTABLE_START = '<', - _SD_BUS_VTABLE_END = '>', - _SD_BUS_VTABLE_METHOD = 'M', - _SD_BUS_VTABLE_SIGNAL = 'S', - _SD_BUS_VTABLE_PROPERTY = 'P', + _SD_BUS_VTABLE_START = '<', + _SD_BUS_VTABLE_END = '>', + _SD_BUS_VTABLE_METHOD = 'M', + _SD_BUS_VTABLE_SIGNAL = 'S', + _SD_BUS_VTABLE_PROPERTY = 'P', _SD_BUS_VTABLE_WRITABLE_PROPERTY = 'W', - _SD_BUS_VTABLE_CHILDREN = 'C' + _SD_BUS_VTABLE_CHILDREN = 'C', }; enum { - SD_BUS_VTABLE_DEPRECATED = 1, - SD_BUS_VTABLE_METHOD_NO_REPLY = 2, - SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 4, - SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY = 8, + SD_BUS_VTABLE_DEPRECATED = 1ULL << 0, + SD_BUS_VTABLE_METHOD_NO_REPLY = 1ULL << 1, + SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE = 1ULL << 2, + SD_BUS_VTABLE_PROPERTY_INVALIDATE_ONLY = 1ULL << 3, + SD_BUS_VTABLE_UNPRIVILEGED = 1ULL << 4, + _SD_BUS_VTABLE_CAPABILITY_MASK = 0xFFFFULL << 40 }; +#define SD_BUS_VTABLE_CAPABILITY(x) ((uint64_t) (((x)+1) & 0xFFFF) << 40) + struct sd_bus_vtable { /* Please do not initialize this structure directly, use the * macros below instead */ - int type; - int flags; + uint8_t type:8; + uint64_t flags:56; union { struct { size_t element_size; diff --git a/src/systemd/sd-bus.h b/src/systemd/sd-bus.h index 1c0d12a0cc2..402fc55f93c 100644 --- a/src/systemd/sd-bus.h +++ b/src/systemd/sd-bus.h @@ -103,6 +103,7 @@ int sd_bus_set_exec(sd_bus *bus, const char *path, char *const argv[]); int sd_bus_set_bus_client(sd_bus *bus, int b); int sd_bus_set_server(sd_bus *bus, int b, sd_id128_t server_id); int sd_bus_set_anonymous(sd_bus *bus, int b); +int sd_bus_set_trusted(sd_bus *bus, int b); int sd_bus_negotiate_fds(sd_bus *bus, int b); int sd_bus_negotiate_attach_timestamp(sd_bus *bus, int b); int sd_bus_negotiate_attach_creds(sd_bus *bus, uint64_t creds_mask); diff --git a/src/timedate/timedatectl.c b/src/timedate/timedatectl.c index 6e0bc3cf831..9b81513c754 100644 --- a/src/timedate/timedatectl.c +++ b/src/timedate/timedatectl.c @@ -214,8 +214,10 @@ static int show_status(sd_bus *bus, char **args, unsigned n) { "/org/freedesktop/timedate1", map, &info); - if (r < 0) + if (r < 0) { + log_error("Failed to query server: %s", strerror(-r)); goto fail; + } print_status_info(&info); diff --git a/src/timedate/timedated.c b/src/timedate/timedated.c index 0641f395516..6d4388c70c1 100644 --- a/src/timedate/timedated.c +++ b/src/timedate/timedated.c @@ -750,6 +750,8 @@ static int method_set_ntp(sd_bus *bus, sd_bus_message *m, void *userdata, sd_bus return sd_bus_reply_method_return(m, NULL); } +#include + static const sd_bus_vtable timedate_vtable[] = { SD_BUS_VTABLE_START(0), SD_BUS_PROPERTY("Timezone", "s", NULL, offsetof(Context, zone), SD_BUS_VTABLE_PROPERTY_EMITS_CHANGE), @@ -759,10 +761,10 @@ static const sd_bus_vtable timedate_vtable[] = { SD_BUS_PROPERTY("NTPSynchronized", "b", property_get_ntp_sync, 0, 0), SD_BUS_PROPERTY("TimeUSec", "t", property_get_time, 0, 0), SD_BUS_PROPERTY("RTCTimeUSec", "t", property_get_rtc_time, 0, 0), - SD_BUS_METHOD("SetTime", "xbb", NULL, method_set_time, 0), - SD_BUS_METHOD("SetTimezone", "sb", NULL, method_set_timezone, 0), - SD_BUS_METHOD("SetLocalRTC", "bbb", NULL, method_set_local_rtc, 0), - SD_BUS_METHOD("SetNTP", "bb", NULL, method_set_ntp, 0), + SD_BUS_METHOD("SetTime", "xbb", NULL, method_set_time, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetTimezone", "sb", NULL, method_set_timezone, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetLocalRTC", "bbb", NULL, method_set_local_rtc, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("SetNTP", "bb", NULL, method_set_ntp, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_END, };