From: Lennart Poettering Date: Thu, 21 Nov 2013 22:36:51 +0000 (+0100) Subject: bus: restore selinux access control to PID 1 for properties X-Git-Tag: v209~1345 X-Git-Url: http://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?p=elogind.git;a=commitdiff_plain;h=969987ea93a7fdcd2c87b551eb0adf0bd9338b32 bus: restore selinux access control to PID 1 for properties --- diff --git a/TODO b/TODO index 04d92aba0..6805fd6d1 100644 --- a/TODO +++ b/TODO @@ -23,7 +23,7 @@ Bugfixes: Fedora 20: -* external: ps should gain colums for slice and machine +* external: ps should gain colums for slice * localed: - localectl: support new converted x11→console keymaps @@ -49,17 +49,12 @@ Features: * sd-event: allow multiple signal handlers per signal -* timer: expose accuracy as unit setting - * when we detect low battery and no AC on boot, show pretty splash and refuse boot * move libasyncns into systemd as libsystemd-asyncns * calendarspec: support value ranges with ".." notation. Example: 2013-4..8-1 -* pid1 porting: - - restore selinux access control on properties - * sd-bus: when triggering property change events, allow a NULL strv indicate that all properties listed as such are send out as changed * sd-bus: enforce signatures on response messages diff --git a/src/core/dbus.c b/src/core/dbus.c index 3d8da1e6a..1cb4d0fa7 100644 --- a/src/core/dbus.c +++ b/src/core/dbus.c @@ -42,6 +42,8 @@ #include "bus-errors.h" #include "strxcpyx.h" #include "dbus-client-track.h" +#include "bus-internal.h" +#include "selinux-access.h" #define CONNECTIONS_MAX 512 @@ -209,6 +211,67 @@ failed: return 0; } +static int selinux_filter(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { + Manager *m = userdata; + const char *verb, *path; + Unit *u = NULL; + Job *j; + int r; + + assert(bus); + assert(message); + + /* Our own method calls are all protected individually with + * selinux checks, but the built-in interfaces need to be + * protected too. */ + + if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", "Set")) + verb = "reload"; + else if (sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Introspectable", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Properties", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.ObjectManager", NULL) || + sd_bus_message_is_method_call(message, "org.freedesktop.DBus.Peer", NULL)) + verb = "status"; + else + return 0; + + path = sd_bus_message_get_path(message); + + if (object_path_startswith("/org/freedesktop/systemd1", path)) { + + r = selinux_access_check(bus, message, verb, error); + if (r < 0) + return r; + + return 0; + } + + if (streq_ptr(path, "/org/freedesktop/systemd1/unit/self")) { + pid_t pid; + + r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid); + if (r < 0) + return 0; + + u = manager_get_unit_by_pid(m, pid); + } else { + r = manager_get_job_from_dbus_path(m, path, &j); + if (r >= 0) + u = j->unit; + else + manager_load_unit_from_dbus_path(m, path, NULL, &u); + } + + if (!u) + return 0; + + r = selinux_unit_access_check(u, bus, message, verb, error); + if (r < 0) + return r; + + return 0; +} + static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { Manager *m = userdata; Job *j; @@ -458,6 +521,12 @@ static int bus_setup_api_vtables(Manager *m, sd_bus *bus) { assert(m); assert(bus); + r = sd_bus_add_filter(bus, selinux_filter, m); + if (r < 0) { + log_error("Failed to add SELinux access filter: %s", strerror(-r)); + return r; + } + r = sd_bus_add_object_vtable(bus, "/org/freedesktop/systemd1", "org.freedesktop.systemd1.Manager", bus_manager_vtable, m); if (r < 0) { log_error("Failed to register Manager vtable: %s", strerror(-r)); diff --git a/src/libsystemd-bus/sd-bus.c b/src/libsystemd-bus/sd-bus.c index 260443446..4df649c9f 100644 --- a/src/libsystemd-bus/sd-bus.c +++ b/src/libsystemd-bus/sd-bus.c @@ -1945,7 +1945,7 @@ static int process_filter(sd_bus *bus, sd_bus_message *m) { if (r < 0) return r; - r = l->callback(bus, m, &error_buffer, l->userdata); + r = l->callback(bus, m, l->userdata, &error_buffer); r = bus_maybe_reply_error(m, r, &error_buffer); if (r != 0) return r;