AttachProcessesToUnit(in s unit_name,
in s subcgroup,
in au pids);
+ RemoveSubgroupFromUnit(in s unit_name,
+ in s subcgroup,
+ in t flags);
AbandonScope(in s name);
GetJob(in u id,
out o job);
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcessesToUnit()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroupFromUnit()"/>
+
<variablelist class="dbus-method" generated="True" extra-ref="AbandonScope()"/>
<variablelist class="dbus-method" generated="True" extra-ref="GetJob()"/>
parameters. The possible values are <literal>configuration</literal>, <literal>state</literal>,
<literal>logs</literal>, <literal>cache</literal>, <literal>runtime</literal>,
<literal>fdstore</literal>, and <literal>all</literal>.</para>
+
+ <para><function>RemoveSubgroupFromUnit()</function> removes a subcgroup belonging to a unit's
+ cgroup. Takes three arguments: the unit name (if empty defaults to the caller's unit), a cgroup path
+ (which must start start with a slash <literal>/</literal>), which is taken relative to the unit's
+ cgroup, and a flags argument (which must be zero for now). This is primarily useful for unprivileged
+ service managers to ask the system service manager for removal of subcgroups it manages, in case one
+ was delegated to other UIDs.</para>
</refsect2>
<refsect2>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Type = '...';
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property Type is not documented!-->
<!--property ExitType is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="Type"/>
<variablelist class="dbus-property" generated="True" extra-ref="ExitType"/>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s BindIPv6Only = '...';
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property BindIPv6Only is not documented!-->
<!--property Backlog is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="BindIPv6Only"/>
<variablelist class="dbus-property" generated="True" extra-ref="Backlog"/>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s Where = '...';
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property Where is not documented!-->
<!--property What is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="Where"/>
<variablelist class="dbus-property" generated="True" extra-ref="What"/>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
properties:
readonly s What = '...';
readonly i Priority = ...;
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property What is not documented!-->
<!--property Priority is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="What"/>
<variablelist class="dbus-property" generated="True" extra-ref="Priority"/>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
properties:
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly s Slice = '...';
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property Slice is not documented!-->
<!--property ControlGroupId is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-property" generated="True" extra-ref="Slice"/>
<variablelist class="dbus-property" generated="True" extra-ref="ControlGroup"/>
GetProcesses(out a(sus) processes);
AttachProcesses(in s subcgroup,
in au pids);
+ RemoveSubgroup(in s subcgroup,
+ in t flags);
signals:
RequestStop();
properties:
<!--method AttachProcesses is not documented!-->
+ <!--method RemoveSubgroup is not documented!-->
+
<!--property RuntimeMaxUSec is not documented!-->
<!--property RuntimeRandomizedExtraUSec is not documented!-->
<variablelist class="dbus-method" generated="True" extra-ref="AttachProcesses()"/>
+ <variablelist class="dbus-method" generated="True" extra-ref="RemoveSubgroup()"/>
+
<variablelist class="dbus-signal" generated="True" extra-ref="RequestStop()"/>
<variablelist class="dbus-property" generated="True" extra-ref="Controller"/>
<varname>ShutdownStartTimestamp</varname>,
<varname>ShutdownStartTimestampMonotonic</varname>, and
<varname>SoftRebootsCount</varname> were added in version 256.</para>
+ <para><function>RemoveSubgroupFromUnit()</function> was added in version 258.</para>
</refsect2>
<refsect2>
<title>Unit Objects</title>
<varname>ProtectControlGroupsEx</varname>,
<varname>PrivateUsersEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para>
- <para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
+ <para><varname>ProtectHostnameEx</varname> and <function>RemoveSubGroup()</function> were added in version 258.</para>
</refsect2>
<refsect2>
<title>Socket Unit Objects</title>
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
<varname>ProtectControlGroupsEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para>
- <para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
+ <para><varname>ProtectHostnameEx</varname> and <function>RemoveSubgroup()</function> were added in version 258.</para>
</refsect2>
<refsect2>
<title>Mount Unit Objects</title>
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
<varname>ProtectControlGroupsEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para>
- <para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
+ <para><varname>ProtectHostnameEx</varname> and <function>RemoveSubgroup()</function> was added in version 258.</para>
</refsect2>
<refsect2>
<title>Swap Unit Objects</title>
<varname>ManagedOOMMemoryPressureDurationUSec</varname>,
<varname>ProtectControlGroupsEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para>
- <para><varname>ProtectHostnameEx</varname> was added in version 258.</para>
+ <para><varname>ProtectHostnameEx</varname> and <function>RemoveSubgroup()</function> were added in version 258.</para>
</refsect2>
<refsect2>
<title>Slice Unit Objects</title>
<varname>EffectiveTasksMax</varname>, and
<varname>MemoryZSwapWriteback</varname> were added in version 256.</para>
<para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para>
+ <para><function>RemoveSubgroup()</function> was added in version 258.</para>
</refsect2>
<refsect2>
<title>Scope Unit Objects</title>
<varname>EffectiveTasksMax</varname>, and
<varname>MemoryZSwapWriteback</varname> were added in version 256.</para>
<para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para>
+ <para><function>RemoveSubgroup()</function> was added in version 258.</para>
</refsect2>
<refsect2>
<title>Job Objects</title>
return sd_bus_reply_method_return(message, NULL);
}
+int bus_unit_method_remove_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error) {
+ Unit *u = ASSERT_PTR(userdata);
+ int r;
+
+ assert(message);
+
+ /* This removes a subcgroup of the unit, regardless which user owns the subcgroup. This is useful
+ * when cgroup delegation is enabled for a unit, and the unit subdelegates the cgroup further */
+
+ r = mac_selinux_unit_access_check(u, message, "stop", error);
+ if (r < 0)
+ return r;
+
+ const char *path;
+ uint64_t flags;
+ r = sd_bus_message_read(message, "st", &path, &flags);
+ if (r < 0)
+ return r;
+
+ /* No flags defined for now. */
+ if (flags != 0)
+ return sd_bus_reply_method_errorf(message, SD_BUS_ERROR_INVALID_ARGS, "Invalid 'flags' parameter '%" PRIu64 "'", flags);
+
+ if (!unit_cgroup_delegate(u))
+ return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Subcgroup removal not available on non-delegated units.");
+
+ if (!path_is_absolute(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not absolute: %s", path);
+
+ if (!path_is_normalized(path))
+ return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Control group path is not normalized: %s", path);
+
+ _cleanup_(sd_bus_creds_unrefp) sd_bus_creds *creds = NULL;
+ r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);
+ if (r < 0)
+ return r;
+
+ uid_t sender_uid;
+ r = sd_bus_creds_get_euid(creds, &sender_uid);
+ if (r < 0)
+ return r;
+
+ /* Allow this only if the client is privileged, is us, or is the user of the unit itself. */
+ if (sender_uid != 0 && sender_uid != getuid() && sender_uid != u->ref_uid)
+ return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Client is not permitted to alter cgroup.");
+
+ r = unit_remove_subcgroup(u, path);
+ if (r < 0)
+ return sd_bus_error_set_errnof(error, r, "Failed to remove subgroup %s: %m", path);
+
+ return sd_bus_reply_method_return(message, NULL);
+}
+
const sd_bus_vtable bus_unit_cgroup_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("Slice", "s", property_get_slice, 0, 0),
bus_unit_method_attach_processes,
SD_BUS_VTABLE_UNPRIVILEGED),
+ SD_BUS_METHOD_WITH_ARGS("RemoveSubgroup",
+ SD_BUS_ARGS("s", subcgroup, "t", flags),
+ SD_BUS_NO_RESULT,
+ bus_unit_method_remove_subgroup,
+ SD_BUS_VTABLE_UNPRIVILEGED),
+
SD_BUS_VTABLE_END
};