X-Git-Url: https://www.chiark.greenend.org.uk/ucgi/~ianmdlvl/git?a=blobdiff_plain;f=src%2Fcore%2Fdbus.c;h=d130e0974e92d30a15dc11d5a81defda8b8a9dd6;hb=e14c280244fc07a19d0acab2f08c9f783458af34;hp=35d185a601a950be0100350422ead136c264836b;hpb=718db96199eb307751264e4163555662c9a389fa;p=elogind.git diff --git a/src/core/dbus.c b/src/core/dbus.c index 35d185a60..d130e0974 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 @@ -71,7 +73,7 @@ int bus_send_queued_message(Manager *m) { return 0; } -static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata) { +static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; const char *cgroup; int r; @@ -100,7 +102,7 @@ static int signal_agent_released(sd_bus *bus, sd_bus_message *message, void *use return 0; } -static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata) { +static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { Manager *m = userdata; assert(bus); @@ -119,7 +121,7 @@ static int signal_disconnected(sd_bus *bus, sd_bus_message *message, void *userd return 0; } -static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata) { +static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *error) { const char *name, *old_owner, *new_owner; Manager *m = userdata; int r; @@ -142,7 +144,7 @@ static int signal_name_owner_changed(sd_bus *bus, sd_bus_message *message, void return 0; } -static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata) { +static int signal_activation_request(sd_bus *bus, sd_bus_message *message, void *userdata, sd_bus_error *ret_error) { _cleanup_bus_error_free_ sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_bus_message_unref_ sd_bus_message *reply = NULL; Manager *m = userdata; @@ -194,7 +196,7 @@ failed: return 0; } - r = sd_bus_message_append(reply, "sss", error.name, error.message); + r = sd_bus_message_append(reply, "sss", name, error.name, error.message); if (r < 0) { bus_log_create_error(r); return 0; @@ -209,7 +211,68 @@ failed: return 0; } -static int bus_job_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +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 *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Job *j; int r; @@ -228,7 +291,7 @@ static int bus_job_find(sd_bus *bus, const char *path, const char *interface, vo return 1; } -static Unit *find_unit(Manager *m, sd_bus *bus, const char *path) { +static int find_unit(Manager *m, sd_bus *bus, const char *path, Unit **unit, sd_bus_error *error) { Unit *u; int r; @@ -242,25 +305,28 @@ static Unit *find_unit(Manager *m, sd_bus *bus, const char *path) { message = sd_bus_get_current(bus); if (!message) - return NULL; + return 0; r = sd_bus_get_owner_pid(bus, sd_bus_message_get_sender(message), &pid); if (r < 0) - return NULL; + return 0; u = manager_get_unit_by_pid(m, pid); } else { - r = manager_load_unit_from_dbus_path(m, path, NULL, &u); + r = manager_load_unit_from_dbus_path(m, path, error, &u); if (r < 0) - return NULL; + return 0; } - return u; + if (!u) + return 0; + + *unit = u; + return 1; } -static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; - Unit *u; assert(bus); assert(path); @@ -268,17 +334,13 @@ static int bus_unit_find(sd_bus *bus, const char *path, const char *interface, v assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; - - *found = u; - return 1; + return find_unit(m, bus, path, (Unit**) found, error); } -static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Unit *u; + int r; assert(bus); assert(path); @@ -286,9 +348,9 @@ static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *in assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface)) return 0; @@ -297,9 +359,10 @@ static int bus_unit_interface_find(sd_bus *bus, const char *path, const char *in return 1; } -static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; Unit *u; + int r; assert(bus); assert(path); @@ -307,9 +370,9 @@ static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *inter assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface)) return 0; @@ -321,10 +384,11 @@ static int bus_unit_cgroup_find(sd_bus *bus, const char *path, const char *inter return 1; } -static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; CGroupContext *c; Unit *u; + int r; assert(bus); assert(path); @@ -332,9 +396,9 @@ static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *in assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface)) return 0; @@ -347,10 +411,11 @@ static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *in return 1; } -static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; ExecContext *c; Unit *u; + int r; assert(bus); assert(path); @@ -358,9 +423,9 @@ static int bus_exec_context_find(sd_bus *bus, const char *path, const char *inte assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface)) return 0; @@ -373,10 +438,11 @@ static int bus_exec_context_find(sd_bus *bus, const char *path, const char *inte return 1; } -static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void **found, void *userdata) { +static int bus_kill_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { Manager *m = userdata; KillContext *c; Unit *u; + int r; assert(bus); assert(path); @@ -384,9 +450,9 @@ static int bus_kill_context_find(sd_bus *bus, const char *path, const char *inte assert(found); assert(m); - u = find_unit(m, bus, path); - if (!u) - return 0; + r = find_unit(m, bus, path, &u, error); + if (r <= 0) + return r; if (!streq_ptr(interface, UNIT_VTABLE(u)->bus_interface)) return 0; @@ -399,7 +465,7 @@ static int bus_kill_context_find(sd_bus *bus, const char *path, const char *inte return 1; } -static int bus_job_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) { +static int bus_job_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_free_ char **l = NULL; Manager *m = userdata; unsigned k = 0; @@ -426,7 +492,7 @@ static int bus_job_enumerate(sd_bus *bus, const char *path, char ***nodes, void return k; } -static int bus_unit_enumerate(sd_bus *bus, const char *path, char ***nodes, void *userdata) { +static int bus_unit_enumerate(sd_bus *bus, const char *path, void *userdata, char ***nodes, sd_bus_error *error) { _cleanup_free_ char **l = NULL; Manager *m = userdata; unsigned k = 0; @@ -458,6 +524,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));