diff --git a/doc/CGROUP_DELEGATION.md b/doc/CGROUP_DELEGATION.md index f78211b3a0..412f0a5fa0 100644 --- a/doc/CGROUP_DELEGATION.md +++ b/doc/CGROUP_DELEGATION.md @@ -434,7 +434,17 @@ unified you (of course, I guess) need to provide only `/sys/fs/cgroup/` itself. replace it with an intermediary `tmpfs`, as long as the path to the delegated sub-tree remains accessible as-is. -5. ⚡ Think twice before delegating cgroupsv1 controllers to less privileged +5. ⚡ Currently, the algorithm for mapping between slice/scope/service unit + naming and their cgroup paths is not considered public API of systemd, and + may change in future versions. This means: it's best to avoid implementing a + local logic of translating cgroup paths to slice/scope/service names in your + program, or vice versa — it's likely going to break sooner or later. Use the + appropriate D-Bus API calls for that instead, so that systemd translates + this for you. (Specifically: each Unit object has a `ControlGroup` property + to get the cgroup for a unit. The method `GetUnitByControlGroup()` may be + used to get the unit for a cgroup.) + +6. ⚡ Think twice before delegating cgroupsv1 controllers to less privileged containers. It's not safe, you basically allow your containers to freeze the system with that and worse. Delegation is a strongpoint of cgroupsv2 though, and there it's safe to treat delegation boundaries as privilege boundaries. diff --git a/src/core/dbus-manager.c b/src/core/dbus-manager.c index 5e1741d2b1..de6aaba229 100644 --- a/src/core/dbus-manager.c +++ b/src/core/dbus-manager.c @@ -544,6 +544,32 @@ static int method_get_unit_by_invocation_id(sd_bus_message *message, void *userd return sd_bus_reply_method_return(message, "o", path); } +static int method_get_unit_by_control_group(sd_bus_message *message, void *userdata, sd_bus_error *error) { + _cleanup_free_ char *path = NULL; + Manager *m = userdata; + const char *cgroup; + Unit *u; + int r; + + r = sd_bus_message_read(message, "s", &cgroup); + if (r < 0) + return r; + + u = manager_get_unit_by_cgroup(m, cgroup); + if (!u) + return sd_bus_error_setf(error, BUS_ERROR_NO_SUCH_UNIT, "Control group '%s' is not valid or not managed by this instance", cgroup); + + r = mac_selinux_unit_access_check(u, message, "status", error); + if (r < 0) + return r; + + path = unit_dbus_path(u); + if (!path) + return -ENOMEM; + + return sd_bus_reply_method_return(message, "o", path); +} + static int method_load_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { _cleanup_free_ char *path = NULL; Manager *m = userdata; @@ -2540,6 +2566,7 @@ const sd_bus_vtable bus_manager_vtable[] = { 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("GetUnitByInvocationID", "ay", "o", method_get_unit_by_invocation_id, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("GetUnitByControlGroup", "s", "o", method_get_unit_by_control_group, 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, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("StartUnitReplace", "sss", "o", method_start_unit_replace, SD_BUS_VTABLE_UNPRIVILEGED), @@ -2571,8 +2598,8 @@ const sd_bus_vtable bus_manager_vtable[] = { 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_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED), - SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED), + SD_BUS_METHOD("CreateSnapshot", "sb", "o", method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN), + SD_BUS_METHOD("RemoveSnapshot", "s", NULL, method_refuse_snapshot, SD_BUS_VTABLE_UNPRIVILEGED|SD_BUS_VTABLE_HIDDEN), SD_BUS_METHOD("Reload", NULL, NULL, method_reload, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Reexecute", NULL, NULL, method_reexecute, SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_METHOD("Exit", NULL, NULL, method_exit, 0), diff --git a/src/core/org.freedesktop.systemd1.conf b/src/core/org.freedesktop.systemd1.conf index 5e72fe7e8e..0114128a57 100644 --- a/src/core/org.freedesktop.systemd1.conf +++ b/src/core/org.freedesktop.systemd1.conf @@ -60,6 +60,10 @@ send_interface="org.freedesktop.systemd1.Manager" send_member="GetUnitByInvocationID"/> + +