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.
This commit is contained in:
Lennart Poettering 2013-12-10 16:41:39 +00:00
parent 85719154e7
commit adacb9575a
20 changed files with 217 additions and 104 deletions

2
TODO
View File

@ -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

View 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),

View 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,
};

View 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;

View 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) {

View 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;
}

View 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;

View 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;

View 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
};

View 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),

View 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
};

View 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),

View File

@ -21,10 +21,10 @@
#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
};

View File

@ -48,6 +48,10 @@
send_interface="org.freedesktop.login1.Manager"
send_member="GetUser"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="GetUserByPID"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="GetSeat"/>
@ -60,10 +64,6 @@
send_interface="org.freedesktop.login1.Manager"
send_member="ListUsers"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="ListMachines"/>
<allow send_destination="org.freedesktop.login1"
send_interface="org.freedesktop.login1.Manager"
send_member="ListSeats"/>

View 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

View File

@ -44,6 +44,10 @@
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>

View 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;

View 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);

View 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);

View 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,
};