chiark / gitweb /
bus: introduce "trusted" bus concept and encode access control in object vtables
authorLennart Poettering <lennart@poettering.net>
Tue, 10 Dec 2013 16:41:39 +0000 (16:41 +0000)
committerLennart Poettering <lennart@poettering.net>
Tue, 10 Dec 2013 16:52:49 +0000 (16:52 +0000)
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.

20 files changed:
TODO
src/core/dbus-manager.c
src/hostname/hostnamed.c
src/libsystemd-bus/bus-internal.h
src/libsystemd-bus/bus-introspect.c
src/libsystemd-bus/bus-objects.c
src/libsystemd-bus/libsystemd-bus.sym
src/libsystemd-bus/sd-bus.c
src/locale/localed.c
src/login/logind-dbus.c
src/login/logind-seat-dbus.c
src/login/logind-session-dbus.c
src/login/logind-user-dbus.c
src/login/org.freedesktop.login1.conf
src/machine/machined-dbus.c
src/machine/org.freedesktop.machine1.conf
src/systemd/sd-bus-vtable.h
src/systemd/sd-bus.h
src/timedate/timedatectl.c
src/timedate/timedated.c

diff --git a/TODO b/TODO
index 253d0bf..dac44e0 100644 (file)
--- 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
index a2707ee..9c2194b 100644 (file)
@@ -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),
index 9082966..f7ae50d 100644 (file)
@@ -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,
 };
 
index 4881e04..1be7488 100644 (file)
@@ -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;
 
index 115b3ce..8bec017 100644 (file)
@@ -77,7 +77,7 @@ static void introspect_write_flags(struct introspect *i, int type, int flags) {
         if (flags & SD_BUS_VTABLE_DEPRECATED)
                 fputs("   <annotation name=\"org.freedesktop.DBus.Deprecated\" value=\"true\"/>\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("   <annotation name=\"org.freedesktop.DBus.Method.NoReply\" value=\"true\"/>\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("   <annotation name=\"org.freedesktop.DBus.Property.EmitsChangedSignal\" value=\"invalidates\"/>\n", i->f);
         }
+
+        if ((type == _SD_BUS_VTABLE_METHOD || type == _SD_BUS_VTABLE_WRITABLE_PROPERTY) && (flags & SD_BUS_VTABLE_UNPRIVILEGED))
+                fputs("   <annotation name=\"org.freedesktop.systemd1.Unprivileged\" value=\"true\"/>\n", i->f);
 }
 
 static int introspect_write_arguments(struct introspect *i, const char *signature, const char *direction) {
index 7cd34c9..941c281 100644 (file)
@@ -19,6 +19,8 @@
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
+#include <sys/capability.h>
+
 #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;
                         }
index 389efc3..7bc1ef9 100644 (file)
@@ -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;
index fef122b..81bfe0d 100644 (file)
@@ -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;
index 0382232..abb610d 100644 (file)
@@ -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
 };
 
index 0461d18..2568eb0 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <sys/capability.h>
 
 #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),
index 23f975b..9271bcf 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <errno.h>
 #include <string.h>
+#include <sys/capability.h>
 
 #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
 };
index 4bbe75e..8595809 100644 (file)
@@ -21,6 +21,7 @@
 
 #include <errno.h>
 #include <string.h>
+#include <sys/capability.h>
 
 #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),
index b034515..817bbb8 100644 (file)
 
 #include <errno.h>
 #include <string.h>
+#include <sys/capability.h>
 
 #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
 };
index 04e735e..d677f61 100644 (file)
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
-                       send_member="GetSeat"/>
+                       send_member="GetUserByPID"/>
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
-                       send_member="ListSessions"/>
+                       send_member="GetSeat"/>
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
-                       send_member="ListUsers"/>
+                       send_member="ListSessions"/>
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
-                       send_member="ListMachines"/>
+                       send_member="ListUsers"/>
 
                 <allow send_destination="org.freedesktop.login1"
                        send_interface="org.freedesktop.login1.Manager"
index 726cc4c..1087a1b 100644 (file)
@@ -23,6 +23,7 @@
 #include <string.h>
 #include <unistd.h>
 #include <pwd.h>
+#include <sys/capability.h>
 
 #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
index b2d6df3..970ccd8 100644 (file)
                        send_interface="org.freedesktop.machine1.Manager"
                        send_member="GetMachine"/>
 
+                <allow send_destination="org.freedesktop.machine1"
+                       send_interface="org.freedesktop.machine1.Manager"
+                       send_member="GetMachineByPID"/>
+
                 <allow receive_sender="org.freedesktop.machine1"/>
         </policy>
 
index 18fc30b..e6e0a72 100644 (file)
@@ -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;
index 1c0d12a..402fc55 100644 (file)
@@ -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);
index 6e0bc3c..9b81513 100644 (file)
@@ -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);
 
index 0641f39..6d4388c 100644 (file)
@@ -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 <sys/capability.h>
+
 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,
 };