1
0
mirror of https://github.com/systemd/systemd synced 2025-10-09 21:54:44 +02:00

Compare commits

..

No commits in common. "18eafedb1aa7647dc2348c09dd7a4a3584e8c175" and "a2123bf9d482f8d7f8679802fa9e5386d15cfde4" have entirely different histories.

64 changed files with 322 additions and 1905 deletions

4
TODO
View File

@ -122,10 +122,6 @@ Deprecations and removals:
https://github.com/util-linux/util-linux/commit/508fb0e7ac103b68531a59db2a4473897853ab52 https://github.com/util-linux/util-linux/commit/508fb0e7ac103b68531a59db2a4473897853ab52
has hit the prominent distributions, revert --issue-file= hack in units/*getty*service.in has hit the prominent distributions, revert --issue-file= hack in units/*getty*service.in
* Once kernel baseline is 5.7, obsolete DefaultMemoryMin/Low= and DefaultStartupMemoryLow=
since we can systematically enable memory_recursiveprot on cgroupfs and have those
enforced by the kernel
Features: Features:
* replace bootctl's PE version check to actually use APIs from pe-binary.[ch] * replace bootctl's PE version check to actually use APIs from pe-binary.[ch]

View File

@ -1,14 +0,0 @@
---
title: Project IDs for Disk Quotas on Exec Directories
category: Exec directories
layout: default
SPDX-License-Identifier: LGPL-2.1-or-later
---
# Project IDs on systemd Systems
Project IDs are needed to enforce disk quotas for Exec Directories.
Project IDs are unsigned, 32-bit integers. For disk quota enforcement,
the range used is 2147483648 - 4294967294, which is the highest range
inspired from `UIDS-GUID.md`. The range is defined through `PROJ_ID_MIN`
and `PROJ_ID_MAX` in `exec-invoke.c`.

View File

@ -257,16 +257,10 @@ All execution-related settings are available for transient units.
✓ RuntimeDirectoryMode= ✓ RuntimeDirectoryMode=
✓ RuntimeDirectory= ✓ RuntimeDirectory=
✓ StateDirectoryMode= ✓ StateDirectoryMode=
✓ StateDirectoryAccounting=
✓ StateDirectoryQuota=
✓ StateDirectory= ✓ StateDirectory=
✓ CacheDirectoryMode= ✓ CacheDirectoryMode=
✓ CacheDirectoryAccounting=
✓ CacheDirectoryQuota=
✓ CacheDirectory= ✓ CacheDirectory=
✓ LogsDirectoryMode= ✓ LogsDirectoryMode=
✓ LogsDirectoryAccounting=
✓ LogsDirectoryQuota=
✓ LogsDirectory= ✓ LogsDirectory=
✓ ConfigurationDirectoryMode= ✓ ConfigurationDirectoryMode=
✓ ConfigurationDirectory= ✓ ConfigurationDirectory=

View File

@ -112,10 +112,6 @@ node /org/freedesktop/systemd1 {
KillUnit(in s name, KillUnit(in s name,
in s whom, in s whom,
in i signal); in i signal);
KillUnitSubgroup(in s name,
in s whom,
in s subgroup,
in i signal);
QueueSignalUnit(in s name, QueueSignalUnit(in s name,
in s whom, in s whom,
in i signal, in i signal,
@ -835,8 +831,6 @@ node /org/freedesktop/systemd1 {
<variablelist class="dbus-method" generated="True" extra-ref="KillUnit()"/> <variablelist class="dbus-method" generated="True" extra-ref="KillUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="KillUnitSubgroup()"/>
<variablelist class="dbus-method" generated="True" extra-ref="QueueSignalUnit()"/> <variablelist class="dbus-method" generated="True" extra-ref="QueueSignalUnit()"/>
<variablelist class="dbus-method" generated="True" extra-ref="CleanUnit()"/> <variablelist class="dbus-method" generated="True" extra-ref="CleanUnit()"/>
@ -1321,24 +1315,12 @@ node /org/freedesktop/systemd1 {
<para><function>KillUnit()</function> may be used to kill (i.e. send a signal to) all processes of a <para><function>KillUnit()</function> may be used to kill (i.e. send a signal to) all processes of a
unit. It takes the unit <varname>name</varname>, an enum <varname>who</varname> and a UNIX unit. It takes the unit <varname>name</varname>, an enum <varname>who</varname> and a UNIX
<varname>signal</varname> number to send. The <varname>who</varname> enum is one of <varname>signal</varname> number to send. The <varname>who</varname> enum is one of
<literal>main</literal>, <literal>control</literal>, <literal>cgroup</literal> or <literal>main</literal>, <literal>control</literal> or <literal>all</literal>. If
<literal>all</literal>. If <literal>main</literal>, only the main process of the unit is killed. If <literal>main</literal>, only the main process of the unit is killed. If <literal>control</literal>, only
<literal>control</literal>, only the control process of the unit is killed. If the control process of the unit is killed. If <literal>all</literal>, all processes are killed. A
<literal>cgroup</literal> is specified only the processes in the control group of the unit are killed,
which might or might not include the main and control processes too. If <literal>all</literal>, all
processes are killed, i.e. the main process, the control process and those in the control group. A
<literal>control</literal> process is for example a process that is configured via <literal>control</literal> process is for example a process that is configured via
<varname>ExecStop=</varname> and is spawned in parallel to the main daemon process in order to shut it <varname>ExecStop=</varname> and is spawned in parallel to the main daemon process in order to shut it
down. The value may be suffixed by <literal>-fail</literal> in which case the operation will fail of no down.</para>
matching process was found (otherwise it will return successfully, executing no operation).</para>
<para><function>KillUnitSubgroup()</function> is just like <function>KillUnit()</function> but takes an
additional path argument that selects a sub-control-group of the unit's control group. Only processes
in that subgroup are killed. The path my be specified with our without leading <literal>/</literal>, in
both cases it is taken relatively to the unit's control group. If the subgroup path is specified as an
empty string or as <literal>/</literal> it has the same effect as <function>KillUnit()</function>. If
it is specified as anything else the <literal>who</literal> parameter must be set to either
<literal>cgroup</literal> or <literal>cgroup-fail</literal>.</para>
<para><function>QueueSignalUnit()</function> is similar to <function>KillUnit()</function> but may be <para><function>QueueSignalUnit()</function> is similar to <function>KillUnit()</function> but may be
used to enqueue a POSIX Realtime Signal (i.e. <constant>SIGRTMIN+…</constant> and used to enqueue a POSIX Realtime Signal (i.e. <constant>SIGRTMIN+…</constant> and
@ -1904,8 +1886,8 @@ node /org/freedesktop/systemd1 {
<para>Read access is generally granted to all clients. Additionally, for unprivileged clients, some <para>Read access is generally granted to all clients. Additionally, for unprivileged clients, some
operations are allowed through the polkit privilege system. Operations which modify unit state operations are allowed through the polkit privilege system. Operations which modify unit state
(<function>StartUnit()</function>, <function>StopUnit()</function>, <function>KillUnit()</function>, (<function>StartUnit()</function>, <function>StopUnit()</function>, <function>KillUnit()</function>,
<function>KillUnitSubgroup()</function>, <function>QueueSignalUnit()</function>, <function>QueueSignalUnit()</function>, <function>RestartUnit()</function> and similar,
<function>RestartUnit()</function> and similar, <function>SetProperty()</function>) require <function>SetProperty()</function>) require
<interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file <interfacename>org.freedesktop.systemd1.manage-units</interfacename>. Operations which modify unit file
enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>, enablement state (<function>EnableUnitFiles()</function>, <function>DisableUnitFiles()</function>,
<function>EnableUnitFilesWithFlags()</function>, <function>DisableUnitFilesWithFlags()</function>, <function>EnableUnitFilesWithFlags()</function>, <function>DisableUnitFilesWithFlags()</function>,
@ -1954,8 +1936,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
out a(uosos) affected_jobs); out a(uosos) affected_jobs);
Kill(in s whom, Kill(in s whom,
in i signal); in i signal);
KillSubgroup(in s subgroup,
in i signal);
QueueSignal(in s whom, QueueSignal(in s whom,
in i signal, in i signal,
in i value); in i value);
@ -2279,8 +2259,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-method" generated="True" extra-ref="Kill()"/> <variablelist class="dbus-method" generated="True" extra-ref="Kill()"/>
<variablelist class="dbus-method" generated="True" extra-ref="KillSubgroup()"/>
<variablelist class="dbus-method" generated="True" extra-ref="QueueSignal()"/> <variablelist class="dbus-method" generated="True" extra-ref="QueueSignal()"/>
<variablelist class="dbus-method" generated="True" extra-ref="ResetFailed()"/> <variablelist class="dbus-method" generated="True" extra-ref="ResetFailed()"/>
@ -2509,13 +2487,13 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<para><function>Start()</function>, <function>Stop()</function>, <function>Reload()</function>, <para><function>Start()</function>, <function>Stop()</function>, <function>Reload()</function>,
<function>Restart()</function>, <function>TryRestart()</function>, <function>Restart()</function>, <function>TryRestart()</function>,
<function>ReloadOrRestart()</function>, <function>ReloadOrTryRestart()</function>, <function>ReloadOrRestart()</function>, <function>ReloadOrTryRestart()</function>,
<function>Kill()</function>, <function>KillSubgroup()</function>, <function>QueueSignal()</function>, <function>Kill()</function>, <function>QueueSignal()</function>, <function>ResetFailed()</function>,
<function>ResetFailed()</function>, and <function>SetProperties()</function> implement the same and <function>SetProperties()</function> implement the same operation as the respective methods on the
operation as the respective methods on the <interfacename>Manager</interfacename> object (see <interfacename>Manager</interfacename> object (see above). However, these methods operate on the unit
above). However, these methods operate on the unit object and hence do not take a unit name object and hence do not take a unit name parameter. Invoking the methods directly on the Manager object
parameter. Invoking the methods directly on the Manager object has the advantage of not requiring a has the advantage of not requiring a <function>GetUnit()</function> call to get the unit object for a
<function>GetUnit()</function> call to get the unit object for a specific unit name. Calling the specific unit name. Calling the methods on the Manager object is hence a round trip
methods on the Manager object is hence a round trip optimization.</para> optimization.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
@ -3310,30 +3288,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...; readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...]; readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...]; readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...; readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...]; readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...]; readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...; readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...]; readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...; readonly u ConfigurationDirectoryMode = ...;
@ -3385,12 +3351,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
readonly s MountImagePolicy = '...'; readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...'; readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...'; readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -3925,22 +3885,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property StateDirectoryMode is not documented!--> <!--property StateDirectoryMode is not documented!-->
<!--property StateDirectoryAccounting is not documented!-->
<!--property StateDirectoryQuota is not documented!-->
<!--property CacheDirectoryMode is not documented!--> <!--property CacheDirectoryMode is not documented!-->
<!--property CacheDirectoryAccounting is not documented!-->
<!--property CacheDirectoryQuota is not documented!-->
<!--property LogsDirectoryMode is not documented!--> <!--property LogsDirectoryMode is not documented!-->
<!--property LogsDirectoryAccounting is not documented!-->
<!--property LogsDirectoryQuota is not documented!-->
<!--property ConfigurationDirectoryMode is not documented!--> <!--property ConfigurationDirectoryMode is not documented!-->
<!--property ConfigurationDirectory is not documented!--> <!--property ConfigurationDirectory is not documented!-->
@ -3987,12 +3935,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<!--property ExtensionImagePolicy is not documented!--> <!--property ExtensionImagePolicy is not documented!-->
<!--property StateDirectoryQuotaUsage is not documented!-->
<!--property CacheDirectoryQuotaUsage is not documented!-->
<!--property LogsDirectoryQuotaUsage is not documented!-->
<!--property KillMode is not documented!--> <!--property KillMode is not documented!-->
<!--property KillSignal is not documented!--> <!--property KillSignal is not documented!-->
@ -4637,30 +4579,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/>
@ -4713,12 +4643,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2eservice {
<variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/> <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@ -5519,30 +5443,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...; readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...]; readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...]; readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...; readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...]; readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...]; readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...; readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...]; readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...; readonly u ConfigurationDirectoryMode = ...;
@ -5594,12 +5506,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
readonly s MountImagePolicy = '...'; readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...'; readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...'; readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -6154,22 +6060,10 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property StateDirectoryMode is not documented!--> <!--property StateDirectoryMode is not documented!-->
<!--property StateDirectoryAccounting is not documented!-->
<!--property StateDirectoryQuota is not documented!-->
<!--property CacheDirectoryMode is not documented!--> <!--property CacheDirectoryMode is not documented!-->
<!--property CacheDirectoryAccounting is not documented!-->
<!--property CacheDirectoryQuota is not documented!-->
<!--property LogsDirectoryMode is not documented!--> <!--property LogsDirectoryMode is not documented!-->
<!--property LogsDirectoryAccounting is not documented!-->
<!--property LogsDirectoryQuota is not documented!-->
<!--property ConfigurationDirectoryMode is not documented!--> <!--property ConfigurationDirectoryMode is not documented!-->
<!--property ConfigurationDirectory is not documented!--> <!--property ConfigurationDirectory is not documented!-->
@ -6216,12 +6110,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<!--property ExtensionImagePolicy is not documented!--> <!--property ExtensionImagePolicy is not documented!-->
<!--property StateDirectoryQuotaUsage is not documented!-->
<!--property CacheDirectoryQuotaUsage is not documented!-->
<!--property LogsDirectoryQuotaUsage is not documented!-->
<!--property KillMode is not documented!--> <!--property KillMode is not documented!-->
<!--property KillSignal is not documented!--> <!--property KillSignal is not documented!-->
@ -6846,30 +6734,18 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/>
@ -6922,12 +6798,6 @@ node /org/freedesktop/systemd1/unit/avahi_2ddaemon_2esocket {
<variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/> <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@ -7552,30 +7422,18 @@ node /org/freedesktop/systemd1/unit/home_2emount {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...; readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...]; readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...]; readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...; readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...]; readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...]; readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...; readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...]; readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...; readonly u ConfigurationDirectoryMode = ...;
@ -7627,12 +7485,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
readonly s MountImagePolicy = '...'; readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...'; readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...'; readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -8109,22 +7961,10 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property StateDirectoryMode is not documented!--> <!--property StateDirectoryMode is not documented!-->
<!--property StateDirectoryAccounting is not documented!-->
<!--property StateDirectoryQuota is not documented!-->
<!--property CacheDirectoryMode is not documented!--> <!--property CacheDirectoryMode is not documented!-->
<!--property CacheDirectoryAccounting is not documented!-->
<!--property CacheDirectoryQuota is not documented!-->
<!--property LogsDirectoryMode is not documented!--> <!--property LogsDirectoryMode is not documented!-->
<!--property LogsDirectoryAccounting is not documented!-->
<!--property LogsDirectoryQuota is not documented!-->
<!--property ConfigurationDirectoryMode is not documented!--> <!--property ConfigurationDirectoryMode is not documented!-->
<!--property ConfigurationDirectory is not documented!--> <!--property ConfigurationDirectory is not documented!-->
@ -8171,12 +8011,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<!--property ExtensionImagePolicy is not documented!--> <!--property ExtensionImagePolicy is not documented!-->
<!--property StateDirectoryQuotaUsage is not documented!-->
<!--property CacheDirectoryQuotaUsage is not documented!-->
<!--property LogsDirectoryQuotaUsage is not documented!-->
<!--property KillMode is not documented!--> <!--property KillMode is not documented!-->
<!--property KillSignal is not documented!--> <!--property KillSignal is not documented!-->
@ -8709,30 +8543,18 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/>
@ -8785,12 +8607,6 @@ node /org/freedesktop/systemd1/unit/home_2emount {
<variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/> <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@ -9548,30 +9364,18 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u StateDirectoryMode = ...; readonly u StateDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b StateDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) StateDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as StateDirectory = ['...', ...]; readonly as StateDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) CacheDirectorySymlink = [...]; readonly a(sst) CacheDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u CacheDirectoryMode = ...; readonly u CacheDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b CacheDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) CacheDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as CacheDirectory = ['...', ...]; readonly as CacheDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly a(sst) LogsDirectorySymlink = [...]; readonly a(sst) LogsDirectorySymlink = [...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u LogsDirectoryMode = ...; readonly u LogsDirectoryMode = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly b LogsDirectoryAccounting = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly (tus) LogsDirectoryQuota = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly as LogsDirectory = ['...', ...]; readonly as LogsDirectory = ['...', ...];
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly u ConfigurationDirectoryMode = ...; readonly u ConfigurationDirectoryMode = ...;
@ -9623,12 +9427,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
readonly s MountImagePolicy = '...'; readonly s MountImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s ExtensionImagePolicy = '...'; readonly s ExtensionImagePolicy = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) StateDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) CacheDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("false")
readonly (tt) LogsDirectoryQuotaUsage = ...;
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
readonly s KillMode = '...'; readonly s KillMode = '...';
@org.freedesktop.DBus.Property.EmitsChangedSignal("const") @org.freedesktop.DBus.Property.EmitsChangedSignal("const")
@ -10087,22 +9885,10 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property StateDirectoryMode is not documented!--> <!--property StateDirectoryMode is not documented!-->
<!--property StateDirectoryAccounting is not documented!-->
<!--property StateDirectoryQuota is not documented!-->
<!--property CacheDirectoryMode is not documented!--> <!--property CacheDirectoryMode is not documented!-->
<!--property CacheDirectoryAccounting is not documented!-->
<!--property CacheDirectoryQuota is not documented!-->
<!--property LogsDirectoryMode is not documented!--> <!--property LogsDirectoryMode is not documented!-->
<!--property LogsDirectoryAccounting is not documented!-->
<!--property LogsDirectoryQuota is not documented!-->
<!--property ConfigurationDirectoryMode is not documented!--> <!--property ConfigurationDirectoryMode is not documented!-->
<!--property ConfigurationDirectory is not documented!--> <!--property ConfigurationDirectory is not documented!-->
@ -10149,12 +9935,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<!--property ExtensionImagePolicy is not documented!--> <!--property ExtensionImagePolicy is not documented!-->
<!--property StateDirectoryQuotaUsage is not documented!-->
<!--property CacheDirectoryQuotaUsage is not documented!-->
<!--property LogsDirectoryQuotaUsage is not documented!-->
<!--property KillMode is not documented!--> <!--property KillMode is not documented!-->
<!--property KillSignal is not documented!--> <!--property KillSignal is not documented!-->
@ -10669,30 +10449,18 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="StateDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="CacheDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectorySymlink"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryAccounting"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuota"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/> <variablelist class="dbus-property" generated="True" extra-ref="LogsDirectory"/>
<variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/> <variablelist class="dbus-property" generated="True" extra-ref="ConfigurationDirectoryMode"/>
@ -10745,12 +10513,6 @@ node /org/freedesktop/systemd1/unit/dev_2dsda3_2eswap {
<variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/> <variablelist class="dbus-property" generated="True" extra-ref="ExtensionImagePolicy"/>
<variablelist class="dbus-property" generated="True" extra-ref="StateDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="CacheDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="LogsDirectoryQuotaUsage"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillMode"/> <variablelist class="dbus-property" generated="True" extra-ref="KillMode"/>
<variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/> <variablelist class="dbus-property" generated="True" extra-ref="KillSignal"/>
@ -12246,8 +12008,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<para><varname>ShutdownStartTimestamp</varname>, <para><varname>ShutdownStartTimestamp</varname>,
<varname>ShutdownStartTimestampMonotonic</varname>, and <varname>ShutdownStartTimestampMonotonic</varname>, and
<varname>SoftRebootsCount</varname> were added in version 256.</para> <varname>SoftRebootsCount</varname> were added in version 256.</para>
<para><function>RemoveSubgroupFromUnit()</function>, and <para><function>RemoveSubgroupFromUnit()</function> was added in version 258.</para>
<function>KillUnitSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Unit Objects</title> <title>Unit Objects</title>
@ -12315,18 +12076,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>PrivateUsersEx</varname>, and <varname>PrivateUsersEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para> <varname>PrivatePIDs</varname> were added in version 257.</para>
<para><varname>ProtectHostnameEx</varname>, <para><varname>ProtectHostnameEx</varname>,
<varname>DelegateNamespaces</varname>, <varname>DelegateNamespaces</varname>, and
<function>RemoveSubGroup()</function>, <function>RemoveSubGroup()</function> were added in version 258.</para>
<varname>StateDirectoryQuota</varname>,
<varname>StateDirectoryQuotaUsage</varname>,
<varname>StateDirectoryAccounting</varname>,
<varname>CacheDirectoryQuota</varname>,
<varname>CacheDirectoryQuotaUsage</varname>,
<varname>CacheDirectoryAccounting</varname>,
<varname>LogsDirectoryQuota</varname>,
<varname>LogsDirectoryQuotaUsage</varname>,
<varname>LogsDirectoryAccounting</varname>, and
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Socket Unit Objects</title> <title>Socket Unit Objects</title>
@ -12375,18 +12126,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>AcceptFileDescriptors</varname>, <varname>AcceptFileDescriptors</varname>,
<varname>DelegateNamespaces</varname>, <varname>DelegateNamespaces</varname>,
<function>RemoveSubgroup()</function>, <function>RemoveSubgroup()</function>,
<varname>DeferTrigger</varname>, <varname>DeferTrigger</varname>, and
<varname>DeferTriggerMaxUSec</varname>, <varname>DeferTriggerMaxUSec</varname> were added in version 258.</para>
<varname>StateDirectoryQuota</varname>,
<varname>StateDirectoryQuotaUsage</varname>,
<varname>StateDirectoryAccounting</varname>,
<varname>CacheDirectoryQuota</varname>,
<varname>CacheDirectoryQuotaUsage</varname>,
<varname>CacheDirectoryAccounting</varname>,
<varname>LogsDirectoryQuota</varname>,
<varname>LogsDirectoryQuotaUsage</varname>,
<varname>LogsDirectoryAccounting</varname>, and
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Mount Unit Objects</title> <title>Mount Unit Objects</title>
@ -12430,18 +12171,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<para><varname>ProtectHostnameEx</varname>, <para><varname>ProtectHostnameEx</varname>,
<varname>DelegateNamespaces</varname>, <varname>DelegateNamespaces</varname>,
<function>RemoveSubgroup()</function>, <function>RemoveSubgroup()</function>,
<varname>ReloadResult</varname>, <varname>ReloadResult</varname>, and
<varname>CleanResult</varname>, <varname>CleanResult</varname> were added in version 258.</para>
<varname>StateDirectoryQuota</varname>,
<varname>StateDirectoryQuotaUsage</varname>,
<varname>StateDirectoryAccounting</varname>,
<varname>CacheDirectoryQuota</varname>,
<varname>CacheDirectoryQuotaUsage</varname>,
<varname>CacheDirectoryAccounting</varname>,
<varname>LogsDirectoryQuota</varname>,
<varname>LogsDirectoryQuotaUsage</varname>,
<varname>LogsDirectoryAccounting</varname>, and
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Swap Unit Objects</title> <title>Swap Unit Objects</title>
@ -12483,18 +12214,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>ProtectControlGroupsEx</varname>, and <varname>ProtectControlGroupsEx</varname>, and
<varname>PrivatePIDs</varname> were added in version 257.</para> <varname>PrivatePIDs</varname> were added in version 257.</para>
<para><varname>ProtectHostnameEx</varname>, <para><varname>ProtectHostnameEx</varname>,
<varname>DelegateNamespaces</varname>, <varname>DelegateNamespaces</varname>, and
<function>RemoveSubgroup()</function>, <function>RemoveSubgroup()</function> were added in version 258.</para>
<varname>StateDirectoryQuota</varname>,
<varname>StateDirectoryQuotaUsage</varname>,
<varname>StateDirectoryAccounting</varname>,
<varname>CacheDirectoryQuota</varname>,
<varname>CacheDirectoryQuotaUsage</varname>,
<varname>CacheDirectoryAccounting</varname>,
<varname>LogsDirectoryQuota</varname>,
<varname>LogsDirectoryQuotaUsage</varname>,
<varname>LogsDirectoryAccounting</varname>, and
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Slice Unit Objects</title> <title>Slice Unit Objects</title>
@ -12522,9 +12243,8 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para> <para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para>
<para><varname>ConcurrencyHardMax</varname>, <para><varname>ConcurrencyHardMax</varname>,
<varname>ConcurrencySoftMax</varname>, <varname>ConcurrencySoftMax</varname>,
<varname>NCurrentlyActive</varname>, <varname>NCurrentlyActive</varname> and
<function>RemoveSubgroup()</function>, and <function>RemoveSubgroup()</function> were added in version 258.</para>
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Scope Unit Objects</title> <title>Scope Unit Objects</title>
@ -12551,8 +12271,7 @@ $ gdbus introspect --system --dest org.freedesktop.systemd1 \
<varname>EffectiveTasksMax</varname>, and <varname>EffectiveTasksMax</varname>, and
<varname>MemoryZSwapWriteback</varname> were added in version 256.</para> <varname>MemoryZSwapWriteback</varname> were added in version 256.</para>
<para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para> <para><varname>ManagedOOMMemoryPressureDurationUSec</varname> was added in version 257.</para>
<para><function>RemoveSubgroup()</function> and <para><function>RemoveSubgroup()</function> was added in version 258.</para>
<function>KillSubgroup()</function> were added in version 258.</para>
</refsect2> </refsect2>
<refsect2> <refsect2>
<title>Job Objects</title> <title>Job Objects</title>

View File

@ -8,9 +8,8 @@
<refsect1> <refsect1>
<title/> <title/>
<para id="controllers-text">The following controller names may be specified: <option>cpu</option>, <para id="controllers-text">The following controller names may be specified: <option>cpu</option>, <option>cpuacct</option>,
<option>cpuset</option>, <option>io</option>, <option>memory</option>, <option>pids</option>, <option>cpuset</option>, <option>io</option>, <option>blkio</option>, <option>memory</option>, <option>devices</option>,
<option>bpf-firewall</option>, <option>bpf-devices</option>, <option>bpf-foreign</option>, <option>pids</option>, <option>bpf-firewall</option>, and <option>bpf-devices</option>.</para>
<option>bpf-socket-bind</option>, and <option>bpf-restrict-network-interfaces</option>.</para>
</refsect1> </refsect1>

View File

@ -2481,25 +2481,23 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem> <listitem>
<para>When used with <command>kill</command>, choose which processes to send a UNIX process signal <para>When used with <command>kill</command>, choose which processes to send a UNIX process signal
to. Must be one of <option>main</option>, <option>control</option>, <option>cgroup</option> or to. Must be one of <option>main</option>, <option>control</option> or <option>all</option> to
<option>all</option> to select whether to kill only the main process, the control process, all select whether to kill only the main process, the control process or all processes of the unit. The
processes in the unit's control group or all processes of the unit. The main process of the unit is main process of the unit is the one that defines the life-time of it. A control process of a unit
the one that defines the life-time of it. A control process of a unit is one that is invoked by the is one that is invoked by the manager to induce state changes of it. For example, all processes
manager to induce state changes of it. For example, all processes started due to the started due to the <varname>ExecStartPre=</varname>, <varname>ExecStop=</varname> or
<varname>ExecStartPre=</varname>, <varname>ExecStop=</varname> or <varname>ExecReload=</varname> <varname>ExecReload=</varname> settings of service units are control processes. Note that there is
settings of service units are control processes. Note that there is only one control process per only one control process per unit at a time, as only one state change is executed at a time. For
unit at a time, as only one state change is executed at a time. For services of type services of type <varname>Type=forking</varname>, the initial process started by the manager for
<varname>Type=forking</varname>, the initial process started by the manager for
<varname>ExecStart=</varname> is a control process, while the process ultimately forked off by that <varname>ExecStart=</varname> is a control process, while the process ultimately forked off by that
one is then considered the main process of the unit (if it can be determined). This is different one is then considered the main process of the unit (if it can be determined). This is different
for service units of other types, where the process forked off by the manager for for service units of other types, where the process forked off by the manager for
<varname>ExecStart=</varname> is always the main process itself. A service unit consists of zero or <varname>ExecStart=</varname> is always the main process itself. A service unit consists of zero or
one main process, zero or one control process plus any number of additional processes part of the one main process, zero or one control process plus any number of additional processes. Not all unit
unit's control group. Not all unit types manage processes of these types however. For example, for types manage processes of these types however. For example, for mount units, control processes are
mount units, control processes are defined (which are the invocations of defined (which are the invocations of <filename>&MOUNT_PATH;</filename> and
<filename>&MOUNT_PATH;</filename> and <filename>&UMOUNT_PATH;</filename>), but no main process is <filename>&UMOUNT_PATH;</filename>), but no main process is defined. If omitted, defaults to
defined. If omitted, defaults to <option>all</option>, except if <option>--kill-subgroup=</option> <option>all</option>.</para>
is used in which case defaults to <option>cgroup</option>.</para>
<xi:include href="version-info.xml" xpointer="v252"/> <xi:include href="version-info.xml" xpointer="v252"/>
</listitem> </listitem>
@ -2526,28 +2524,6 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<xi:include href="version-info.xml" xpointer="v254"/></listitem> <xi:include href="version-info.xml" xpointer="v254"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><option>--kill-subgroup=<replaceable>PATH</replaceable></option></term>
<listitem><para>Takes a control group sub-path to send signals to, for use with the
<command>kill</command> command. By default the chosen signal is delivered to all processes of the
unit's cgroups (as well as the main/control processes (if outside) subject to
<option>--kill-whom=</option>). But with this option a subgroup can be selelected instead. This
functionality is only available if <literal>cgroup</literal> or <literal>cgroup-fail</literal> are
used with <option>--kill-whom=</option>, and in fact the former is the default if
<option>--kill-subgroup=</option> is used.</para>
<para>The specified path may, but doesn't have to be prefixed with a slash, and its absence or
presence has no effect, the path is either way taken relative to the unit's main control group
path.</para>
<para>This functionality is only available on units where control group delegation is enabled (see
<varname>Delegate=</varname> in
<member><citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry></member>).</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<xi:include href="standard-options.xml" xpointer="signal" /> <xi:include href="standard-options.xml" xpointer="signal" />
<varlistentry> <varlistentry>

View File

@ -1680,46 +1680,6 @@ StateDirectory=aaa/bbb ccc</programlisting>
<xi:include href="version-info.xml" xpointer="v234"/></listitem> <xi:include href="version-info.xml" xpointer="v234"/></listitem>
</varlistentry> </varlistentry>
<varlistentry>
<term><varname>StateDirectoryQuota=</varname></term>
<term><varname>CacheDirectoryQuota=</varname></term>
<term><varname>LogsDirectoryQuota=</varname></term>
<listitem><para>Specifies the storage limits for the directories specified in <varname>StateDirectory=</varname>,
<varname>CacheDirectory=</varname>, or <varname>LogsDirectory=</varname> respectively.</para>
<para>The storage quota is defined in terms of disk blocks and inodes, as per
<ulink url="https://man7.org/linux/man-pages/man2/quotactl.2.html">quotactl</ulink>. Takes an absolute size limit
in bytes. If the value is suffixed with K, M, G or T, the specified size is parsed as Kilobytes, Megabytes, Gigabytes,
or Terabytes (with the base 1024), respectively. If an absolute size limit is specified, only the block quota is set
(rounded up to the nearest block). Alternatively, a percentage value may be specified, which applies the same percent
quota to both blocks and inodes. Defaults to <constant>off</constant>, in which case no storage limits will be set.</para>
<para>Only hard limits are set, not soft limits. If the underlying filesystem for the specified directories does not
support project quotas, the specified storage limits will not be set. In addition to enabling per-unit quotas with
these settings, it is necessary to enable <constant>prjquota</constant> on the file system level as well
(i.e. <command>tune2fs -Q prjquota</command>). Quotas must also be turned on with
<ulink url="https://linux.die.net/man/8/quotaon">quotaon.</ulink></para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry>
<term><varname>StateDirectoryAccounting=</varname></term>
<term><varname>CacheDirectoryAccounting=</varname></term>
<term><varname>LogsDirectoryAccounting=</varname></term>
<listitem><para>Takes a boolean argument. If true, a project ID is assigned to the directories specified in
<varname>StateDirectory=</varname>, <varname>CacheDirectory=</varname>, or <varname>LogsDirectory=</varname>
respectively, which is used for tracking disk usage when disk quotas are turned on
(see <ulink url="https://man7.org/linux/man-pages/man8/repquota.8.html">repquota</ulink>). Defaults to false.</para>
<para>To set and enforce disk quotas, <varname>StateDirectoryQuota=</varname>, <varname>CacheDirectoryQuota=</varname>,
or <varname>LogsDirectoryQuota=</varname> must be specified.</para>
<xi:include href="version-info.xml" xpointer="v258"/></listitem>
</varlistentry>
<varlistentry> <varlistentry>
<term><varname>RuntimeDirectoryPreserve=</varname></term> <term><varname>RuntimeDirectoryPreserve=</varname></term>

View File

@ -1695,7 +1695,7 @@ WantedBy=multi-user.target</programlisting>
just starts one process in the background:</para> just starts one process in the background:</para>
<programlisting>[Unit] <programlisting>[Unit]
Description=My Simple Daemon Description=Some simple daemon
[Service] [Service]
Type=forking Type=forking
@ -1721,7 +1721,7 @@ WantedBy=multi-user.target</programlisting>
The following example shows a typical DBus service:</para> The following example shows a typical DBus service:</para>
<programlisting>[Unit] <programlisting>[Unit]
Description=Simple DBus Service Description=Simple DBus service
[Service] [Service]
Type=dbus Type=dbus
@ -1760,7 +1760,7 @@ SystemdService=simple-dbus-service.service</programlisting>
daemon would look like this:</para> daemon would look like this:</para>
<programlisting>[Unit] <programlisting>[Unit]
Description=Simple Notifying Service Description=Simple notifying service
[Service] [Service]
Type=notify-reload Type=notify-reload

View File

@ -607,7 +607,6 @@ foreach ident : [
['pivot_root', '''#include <sys/syscall.h>'''], # no known header declares pivot_root ['pivot_root', '''#include <sys/syscall.h>'''], # no known header declares pivot_root
['setxattrat', '''#include <sys/xattr.h>'''], # no known header declares setxattrat ['setxattrat', '''#include <sys/xattr.h>'''], # no known header declares setxattrat
['removexattrat', '''#include <sys/xattr.h>'''], # no known header declares removexattrat ['removexattrat', '''#include <sys/xattr.h>'''], # no known header declares removexattrat
['open_tree_attr', '''#include <sys/mount.h>'''], # no known header declares open_tree_attr
] ]
have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE') have = cc.has_function(ident[0], prefix : ident[1], args : '-D_GNU_SOURCE')

View File

@ -1,5 +0,0 @@
[Partition]
Type=linux-generic
Format=ext4
SizeMinBytes=498M
SizeMaxBytes=498M

View File

@ -10,7 +10,6 @@
#include "fd-util.h" #include "fd-util.h"
#include "fs-util.h" #include "fs-util.h"
#include "log.h" #include "log.h"
#include "recurse-dir.h"
#include "string-util.h" #include "string-util.h"
int chattr_full( int chattr_full(
@ -170,81 +169,3 @@ int read_attr_at(int dir_fd, const char *path, unsigned *ret) {
return read_attr_fd(fd, ret); return read_attr_fd(fd, ret);
} }
int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid) {
struct fsxattr attrs;
_cleanup_close_ int fd_reopened = -EBADF;
assert(fd >= 0);
fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
if (fd < 0)
return fd;
if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
return -errno;
if (ret_xflags)
*ret_xflags = attrs.fsx_xflags;
if (ret_projid)
*ret_projid = attrs.fsx_projid;
return 0;
}
int set_proj_id(int fd, uint32_t proj_id) {
struct fsxattr attrs;
_cleanup_close_ int fd_reopened = -EBADF;
assert(fd >= 0);
fd = fd_reopen_condition(fd, O_RDONLY|O_CLOEXEC|O_NOCTTY, O_PATH, &fd_reopened);
if (fd < 0)
return fd;
if (ioctl(fd, FS_IOC_FSGETXATTR, &attrs) < 0)
return -errno;
struct stat statbuf;
if (fstat(fd, &statbuf) < 0)
return -errno;
if (attrs.fsx_projid == proj_id && (!S_ISDIR(statbuf.st_mode) || FLAGS_SET(attrs.fsx_xflags, FS_XFLAG_PROJINHERIT)))
return 0;
attrs.fsx_projid = proj_id;
if (S_ISDIR(statbuf.st_mode))
attrs.fsx_xflags |= FS_XFLAG_PROJINHERIT;
return RET_NERRNO(ioctl(fd, FS_IOC_FSSETXATTR, &attrs));
}
static int set_proj_id_cb(
RecurseDirEvent event,
const char *path,
int dir_fd,
int inode_fd,
const struct dirent *de,
const struct statx *sx,
void *userdata) {
if (!IN_SET(event, RECURSE_DIR_ENTER, RECURSE_DIR_ENTRY))
return RECURSE_DIR_CONTINUE;
if (de && !IN_SET(de->d_type, DT_DIR, DT_REG))
return RECURSE_DIR_CONTINUE;
return set_proj_id(inode_fd, PTR_TO_UINT32(userdata));
}
int set_proj_id_recursive(int fd, uint32_t proj_id) {
return recurse_dir_at(
fd,
/* path = */ NULL,
/* statx_mask = */ 0,
/* n_depth_max = */ UINT_MAX,
RECURSE_DIR_ENSURE_TYPE|RECURSE_DIR_TOPLEVEL|RECURSE_DIR_INODE_FD,
set_proj_id_cb,
UINT32_TO_PTR(proj_id));
}

View File

@ -50,10 +50,6 @@ static inline int chattr_path(const char *path, unsigned value, unsigned mask) {
int read_attr_fd(int fd, unsigned *ret); int read_attr_fd(int fd, unsigned *ret);
int read_attr_at(int dir_fd, const char *path, unsigned *ret); int read_attr_at(int dir_fd, const char *path, unsigned *ret);
int read_fs_xattr_fd(int fd, uint32_t *ret_xflags, uint32_t *ret_projid);
int set_proj_id(int fd, uint32_t proj_id);
int set_proj_id_recursive(int fd, uint32_t proj_id);
/* Combination of chattr flags, that should be appropriate for secrets stored on disk: Secure Remove + /* Combination of chattr flags, that should be appropriate for secrets stored on disk: Secure Remove +
* Exclusion from Dumping + Synchronous Writing (i.e. not caching in memory) + In-Place Updating (i.e. not * Exclusion from Dumping + Synchronous Writing (i.e. not caching in memory) + In-Place Updating (i.e. not

View File

@ -36,7 +36,6 @@ struct in_addr;
struct in6_addr; struct in6_addr;
struct inotify_event; struct inotify_event;
struct iovec; struct iovec;
struct mount_attr;
struct msghdr; struct msghdr;
struct passwd; struct passwd;
struct pollfd; struct pollfd;

View File

@ -120,13 +120,3 @@ static inline int missing_mount_setattr(int dfd, const char *path, unsigned flag
} }
# define mount_setattr missing_mount_setattr # define mount_setattr missing_mount_setattr
#endif #endif
#if HAVE_OPEN_TREE_ATTR
extern int open_tree_attr(int __dfd, const char *__filename, unsigned int __flags, struct mount_attr *__uattr, size_t __usize) __THROW;
#else
static inline int missing_open_tree_attr(int dfd, const char *filename, unsigned int flags, struct mount_attr *attr, size_t size) {
return syscall(__NR_open_tree_attr, dfd, filename, flags, attr, size);
}
# define open_tree_attr missing_open_tree_attr
#endif

View File

@ -6,6 +6,8 @@
*/ */
#pragma once #pragma once
#include "forward.h"
/* Note: if this code looks strange, this is because it is derived from the same /* Note: if this code looks strange, this is because it is derived from the same
* template as the per-syscall blocks below. */ * template as the per-syscall blocks below. */
# if defined(__aarch64__) # if defined(__aarch64__)
@ -98,7 +100,7 @@
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_close_range && __NR_close_range >= 0 # if defined __NR_close_range && __NR_close_range >= 0
# if defined systemd_NR_close_range # if defined systemd_NR_close_range
_Static_assert(__NR_close_range == systemd_NR_close_range, ""); assert_cc(__NR_close_range == systemd_NR_close_range);
# endif # endif
# else # else
# if defined __NR_close_range # if defined __NR_close_range
@ -166,7 +168,7 @@ _Static_assert(__NR_close_range == systemd_NR_close_range, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0 # if defined __NR_fchmodat2 && __NR_fchmodat2 >= 0
# if defined systemd_NR_fchmodat2 # if defined systemd_NR_fchmodat2
_Static_assert(__NR_fchmodat2 == systemd_NR_fchmodat2, ""); assert_cc(__NR_fchmodat2 == systemd_NR_fchmodat2);
# endif # endif
# else # else
# if defined __NR_fchmodat2 # if defined __NR_fchmodat2
@ -234,7 +236,7 @@ _Static_assert(__NR_fchmodat2 == systemd_NR_fchmodat2, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_mount_setattr && __NR_mount_setattr >= 0 # if defined __NR_mount_setattr && __NR_mount_setattr >= 0
# if defined systemd_NR_mount_setattr # if defined systemd_NR_mount_setattr
_Static_assert(__NR_mount_setattr == systemd_NR_mount_setattr, ""); assert_cc(__NR_mount_setattr == systemd_NR_mount_setattr);
# endif # endif
# else # else
# if defined __NR_mount_setattr # if defined __NR_mount_setattr
@ -302,7 +304,7 @@ _Static_assert(__NR_mount_setattr == systemd_NR_mount_setattr, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_openat2 && __NR_openat2 >= 0 # if defined __NR_openat2 && __NR_openat2 >= 0
# if defined systemd_NR_openat2 # if defined systemd_NR_openat2
_Static_assert(__NR_openat2 == systemd_NR_openat2, ""); assert_cc(__NR_openat2 == systemd_NR_openat2);
# endif # endif
# else # else
# if defined __NR_openat2 # if defined __NR_openat2
@ -370,7 +372,7 @@ _Static_assert(__NR_openat2 == systemd_NR_openat2, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_quotactl_fd && __NR_quotactl_fd >= 0 # if defined __NR_quotactl_fd && __NR_quotactl_fd >= 0
# if defined systemd_NR_quotactl_fd # if defined systemd_NR_quotactl_fd
_Static_assert(__NR_quotactl_fd == systemd_NR_quotactl_fd, ""); assert_cc(__NR_quotactl_fd == systemd_NR_quotactl_fd);
# endif # endif
# else # else
# if defined __NR_quotactl_fd # if defined __NR_quotactl_fd
@ -438,7 +440,7 @@ _Static_assert(__NR_quotactl_fd == systemd_NR_quotactl_fd, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_removexattrat && __NR_removexattrat >= 0 # if defined __NR_removexattrat && __NR_removexattrat >= 0
# if defined systemd_NR_removexattrat # if defined systemd_NR_removexattrat
_Static_assert(__NR_removexattrat == systemd_NR_removexattrat, ""); assert_cc(__NR_removexattrat == systemd_NR_removexattrat);
# endif # endif
# else # else
# if defined __NR_removexattrat # if defined __NR_removexattrat
@ -506,7 +508,7 @@ _Static_assert(__NR_removexattrat == systemd_NR_removexattrat, "");
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_setxattrat && __NR_setxattrat >= 0 # if defined __NR_setxattrat && __NR_setxattrat >= 0
# if defined systemd_NR_setxattrat # if defined systemd_NR_setxattrat
_Static_assert(__NR_setxattrat == systemd_NR_setxattrat, ""); assert_cc(__NR_setxattrat == systemd_NR_setxattrat);
# endif # endif
# else # else
# if defined __NR_setxattrat # if defined __NR_setxattrat
@ -517,71 +519,3 @@ _Static_assert(__NR_setxattrat == systemd_NR_setxattrat, "");
# endif # endif
# endif # endif
#endif #endif
#ifndef __IGNORE_open_tree_attr
# if defined(__aarch64__)
# define systemd_NR_open_tree_attr 467
# elif defined(__alpha__)
# define systemd_NR_open_tree_attr 577
# elif defined(__arc__) || defined(__tilegx__)
# define systemd_NR_open_tree_attr 467
# elif defined(__arm__)
# define systemd_NR_open_tree_attr 467
# elif defined(__i386__)
# define systemd_NR_open_tree_attr 467
# elif defined(__ia64__)
# define systemd_NR_open_tree_attr -1
# elif defined(__loongarch_lp64)
# define systemd_NR_open_tree_attr 467
# elif defined(__m68k__)
# define systemd_NR_open_tree_attr 467
# elif defined(_MIPS_SIM)
# if _MIPS_SIM == _MIPS_SIM_ABI32
# define systemd_NR_open_tree_attr 4467
# elif _MIPS_SIM == _MIPS_SIM_NABI32
# define systemd_NR_open_tree_attr 6467
# elif _MIPS_SIM == _MIPS_SIM_ABI64
# define systemd_NR_open_tree_attr 5467
# else
# error "Unknown MIPS ABI"
# endif
# elif defined(__hppa__)
# define systemd_NR_open_tree_attr 467
# elif defined(__powerpc__)
# define systemd_NR_open_tree_attr 467
# elif defined(__riscv)
# if __riscv_xlen == 32
# define systemd_NR_open_tree_attr 467
# elif __riscv_xlen == 64
# define systemd_NR_open_tree_attr 467
# else
# error "Unknown RISC-V ABI"
# endif
# elif defined(__s390__)
# define systemd_NR_open_tree_attr 467
# elif defined(__sparc__)
# define systemd_NR_open_tree_attr 467
# elif defined(__x86_64__)
# if defined(__ILP32__)
# define systemd_NR_open_tree_attr (467 | /* __X32_SYSCALL_BIT */ 0x40000000)
# else
# define systemd_NR_open_tree_attr 467
# endif
# elif !defined(missing_arch_template)
# warning "open_tree_attr() syscall number is unknown for your architecture"
# endif
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_open_tree_attr && __NR_open_tree_attr >= 0
# if defined systemd_NR_open_tree_attr
_Static_assert(__NR_open_tree_attr == systemd_NR_open_tree_attr, "");
# endif
# else
# if defined __NR_open_tree_attr
# undef __NR_open_tree_attr
# endif
# if defined systemd_NR_open_tree_attr && systemd_NR_open_tree_attr >= 0
# define __NR_open_tree_attr systemd_NR_open_tree_attr
# endif
# endif
#endif

View File

@ -9,7 +9,6 @@ SYSCALLS = [
'close_range', # defined in glibc header since glibc-2.33 'close_range', # defined in glibc header since glibc-2.33
'fchmodat2', # defined in glibc header since glibc-2.39 'fchmodat2', # defined in glibc header since glibc-2.39
'mount_setattr', # defined in glibc header since glibc-2.34 'mount_setattr', # defined in glibc header since glibc-2.34
'open_tree_attr',
'openat2', # defined in glibc header since glibc-2.32 'openat2', # defined in glibc header since glibc-2.32
'quotactl_fd', # defined in glibc header since glibc-2.35 'quotactl_fd', # defined in glibc header since glibc-2.35
'removexattrat', 'removexattrat',
@ -97,7 +96,7 @@ DEF_TEMPLATE_C = '''\
/* may be an (invalid) negative number due to libseccomp, see PR 13319 */ /* may be an (invalid) negative number due to libseccomp, see PR 13319 */
# if defined __NR_{syscall} && __NR_{syscall} >= 0 # if defined __NR_{syscall} && __NR_{syscall} >= 0
# if defined systemd_NR_{syscall} # if defined systemd_NR_{syscall}
_Static_assert(__NR_{syscall} == systemd_NR_{syscall}, ""); assert_cc(__NR_{syscall} == systemd_NR_{syscall});
# endif # endif
# else # else
# if defined __NR_{syscall} # if defined __NR_{syscall}

View File

@ -57,7 +57,7 @@
#include "bpf/restrict_fs/restrict-fs-skel.h" #include "bpf/restrict_fs/restrict-fs-skel.h"
#endif #endif
#define CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC (100 * USEC_PER_MSEC) #define CGROUP_CPU_QUOTA_DEFAULT_PERIOD_USEC ((usec_t) 100 * USEC_PER_MSEC)
/* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access /* Returns the log level to use when cgroup attribute writes fail. When an attribute is missing or we have access
* problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask * problems we downgrade to LOG_DEBUG. This is supposed to be nice to container managers and kernels which want to mask
@ -90,19 +90,6 @@ bool manager_owns_host_root_cgroup(Manager *m) {
return empty_or_root(m->cgroup_root); return empty_or_root(m->cgroup_root);
} }
bool unit_has_host_root_cgroup(const Unit *u) {
assert(u);
assert(u->manager);
/* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
* the manager manages the root cgroup. */
if (!manager_owns_host_root_cgroup(u->manager))
return false;
return unit_has_name(u, SPECIAL_ROOT_SLICE);
}
bool unit_has_startup_cgroup_constraints(Unit *u) { bool unit_has_startup_cgroup_constraints(Unit *u) {
assert(u); assert(u);
@ -125,21 +112,32 @@ bool unit_has_startup_cgroup_constraints(Unit *u) {
c->startup_memory_low_set; c->startup_memory_low_set;
} }
static int set_attribute_and_warn(Unit *u, const char *attribute, const char *value) { bool unit_has_host_root_cgroup(const Unit *u) {
assert(u);
assert(u->manager);
/* Returns whether this unit manages the root cgroup. This will return true if this unit is the root slice and
* the manager manages the root cgroup. */
if (!manager_owns_host_root_cgroup(u->manager))
return false;
return unit_has_name(u, SPECIAL_ROOT_SLICE);
}
static int set_attribute_and_warn(Unit *u, const char *controller, const char *attribute, const char *value) {
int r; int r;
assert(u); assert(u);
assert(attribute);
assert(value);
CGroupRuntime *crt = unit_get_cgroup_runtime(u); CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt || !crt->cgroup_path) if (!crt || !crt->cgroup_path)
return -EOWNERDEAD; return -EOWNERDEAD;
r = cg_set_attribute(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, attribute, value); r = cg_set_attribute(controller, crt->cgroup_path, attribute, value);
if (r < 0) if (r < 0)
log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m", log_unit_full_errno(u, LOG_LEVEL_CGROUP_WRITE(r), r, "Failed to set '%s' attribute on '%s' to '%.*s': %m",
attribute, empty_to_root(crt->cgroup_path), (int) strcspn(value, NEWLINE), value); strna(attribute), empty_to_root(crt->cgroup_path), (int) strcspn(value, NEWLINE), value);
return r; return r;
} }
@ -1123,7 +1121,7 @@ static void cgroup_apply_cpu_weight(Unit *u, uint64_t weight) {
if (weight == CGROUP_WEIGHT_IDLE) if (weight == CGROUP_WEIGHT_IDLE)
return; return;
xsprintf(buf, "%" PRIu64 "\n", weight); xsprintf(buf, "%" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "cpu.weight", buf); (void) set_attribute_and_warn(u, "cpu", "cpu.weight", buf);
} }
static void cgroup_apply_cpu_idle(Unit *u, uint64_t weight) { static void cgroup_apply_cpu_idle(Unit *u, uint64_t weight) {
@ -1156,7 +1154,7 @@ static void cgroup_apply_cpu_quota(Unit *u, usec_t quota, usec_t period) {
MAX(quota * period / USEC_PER_SEC, USEC_PER_MSEC), period); MAX(quota * period / USEC_PER_SEC, USEC_PER_MSEC), period);
else else
xsprintf(buf, "max " USEC_FMT "\n", period); xsprintf(buf, "max " USEC_FMT "\n", period);
(void) set_attribute_and_warn(u, "cpu.max", buf); (void) set_attribute_and_warn(u, "cpu", "cpu.max", buf);
} }
static void cgroup_apply_cpuset(Unit *u, const CPUSet *cpus, const char *name) { static void cgroup_apply_cpuset(Unit *u, const CPUSet *cpus, const char *name) {
@ -1168,7 +1166,7 @@ static void cgroup_apply_cpuset(Unit *u, const CPUSet *cpus, const char *name) {
return; return;
} }
(void) set_attribute_and_warn(u, name, buf); (void) set_attribute_and_warn(u, "cpuset", name, buf);
} }
static bool cgroup_context_has_io_config(CGroupContext *c) { static bool cgroup_context_has_io_config(CGroupContext *c) {
@ -1189,8 +1187,10 @@ static uint64_t cgroup_context_io_weight(CGroupContext *c, ManagerState state) {
return CGROUP_WEIGHT_DEFAULT; return CGROUP_WEIGHT_DEFAULT;
} }
static int set_bfq_weight(Unit *u, dev_t dev, uint64_t io_weight) { static int set_bfq_weight(Unit *u, const char *controller, dev_t dev, uint64_t io_weight) {
static bool warned = false;
char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")]; char buf[DECIMAL_STR_MAX(dev_t)*2+2+DECIMAL_STR_MAX(uint64_t)+STRLEN("\n")];
const char *p;
uint64_t bfq_weight; uint64_t bfq_weight;
int r; int r;
@ -1203,6 +1203,7 @@ static int set_bfq_weight(Unit *u, dev_t dev, uint64_t io_weight) {
/* FIXME: drop this function when distro kernels properly support BFQ through "io.weight" /* FIXME: drop this function when distro kernels properly support BFQ through "io.weight"
* See also: https://github.com/systemd/systemd/pull/13335 and * See also: https://github.com/systemd/systemd/pull/13335 and
* https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. */ * https://github.com/torvalds/linux/commit/65752aef0a407e1ef17ec78a7fc31ba4e0b360f9. */
p = strjoina(controller, ".bfq.weight");
/* Adjust to kernel range is 1..1000, the default is 100. */ /* Adjust to kernel range is 1..1000, the default is 100. */
bfq_weight = BFQ_WEIGHT(io_weight); bfq_weight = BFQ_WEIGHT(io_weight);
@ -1211,11 +1212,22 @@ static int set_bfq_weight(Unit *u, dev_t dev, uint64_t io_weight) {
else else
xsprintf(buf, "%" PRIu64 "\n", bfq_weight); xsprintf(buf, "%" PRIu64 "\n", bfq_weight);
r = cg_set_attribute(SYSTEMD_CGROUP_CONTROLLER, crt->cgroup_path, "io.bfq.weight", buf); r = cg_set_attribute(controller, crt->cgroup_path, p, buf);
if (r >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%s=%" PRIu64 " scaled to io.bfq.weight=%" PRIu64, /* FIXME: drop this when kernels prior
* 795fe54c2a82 ("bfq: Add per-device weight") v5.4
* are not interesting anymore. Old kernels will fail with EINVAL, while new kernels won't return
* EINVAL on properly formatted input by us. Treat EINVAL accordingly. */
if (r == -EINVAL && major(dev) > 0) {
if (!warned) {
log_unit_warning(u, "Kernel version does not accept per-device setting in %s.", p);
warned = true;
}
r = -EOPNOTSUPP; /* mask as unconfigured device */
} else if (r >= 0 && io_weight != bfq_weight)
log_unit_debug(u, "%s=%" PRIu64 " scaled to %s=%" PRIu64,
major(dev) > 0 ? "IODeviceWeight" : "IOWeight", major(dev) > 0 ? "IODeviceWeight" : "IOWeight",
io_weight, bfq_weight); io_weight, p, bfq_weight);
return r; return r;
} }
@ -1233,7 +1245,7 @@ static void cgroup_apply_io_device_weight(Unit *u, const char *dev_path, uint64_
if (lookup_block_device(dev_path, &dev) < 0) if (lookup_block_device(dev_path, &dev) < 0)
return; return;
r1 = set_bfq_weight(u, dev, io_weight); r1 = set_bfq_weight(u, "io", dev, io_weight);
xsprintf(buf, DEVNUM_FORMAT_STR " %" PRIu64 "\n", DEVNUM_FORMAT_VAL(dev), io_weight); xsprintf(buf, DEVNUM_FORMAT_STR " %" PRIu64 "\n", DEVNUM_FORMAT_VAL(dev), io_weight);
r2 = cg_set_attribute("io", crt->cgroup_path, "io.weight", buf); r2 = cg_set_attribute("io", crt->cgroup_path, "io.weight", buf);
@ -1261,7 +1273,7 @@ static void cgroup_apply_io_device_latency(Unit *u, const char *dev_path, usec_t
else else
xsprintf(buf, DEVNUM_FORMAT_STR " target=max\n", DEVNUM_FORMAT_VAL(dev)); xsprintf(buf, DEVNUM_FORMAT_STR " target=max\n", DEVNUM_FORMAT_VAL(dev));
(void) set_attribute_and_warn(u, "io.latency", buf); (void) set_attribute_and_warn(u, "io", "io.latency", buf);
} }
static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) { static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t *limits) {
@ -1281,7 +1293,7 @@ static void cgroup_apply_io_device_limit(Unit *u, const char *dev_path, uint64_t
xsprintf(buf, DEVNUM_FORMAT_STR " rbps=%s wbps=%s riops=%s wiops=%s\n", DEVNUM_FORMAT_VAL(dev), xsprintf(buf, DEVNUM_FORMAT_STR " rbps=%s wbps=%s riops=%s wiops=%s\n", DEVNUM_FORMAT_VAL(dev),
limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX], limit_bufs[CGROUP_IO_RBPS_MAX], limit_bufs[CGROUP_IO_WBPS_MAX],
limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]); limit_bufs[CGROUP_IO_RIOPS_MAX], limit_bufs[CGROUP_IO_WIOPS_MAX]);
(void) set_attribute_and_warn(u, "io.max", buf); (void) set_attribute_and_warn(u, "io", "io.max", buf);
} }
static bool unit_has_memory_config(Unit *u) { static bool unit_has_memory_config(Unit *u) {
@ -1305,7 +1317,7 @@ static void cgroup_apply_memory_limit(Unit *u, const char *file, uint64_t v) {
if (v != CGROUP_LIMIT_MAX) if (v != CGROUP_LIMIT_MAX)
xsprintf(buf, "%" PRIu64 "\n", v); xsprintf(buf, "%" PRIu64 "\n", v);
(void) set_attribute_and_warn(u, file, buf); (void) set_attribute_and_warn(u, "memory", file, buf);
} }
static void cgroup_apply_firewall(Unit *u) { static void cgroup_apply_firewall(Unit *u) {
@ -1450,10 +1462,10 @@ static void set_io_weight(Unit *u, uint64_t weight) {
assert(u); assert(u);
(void) set_bfq_weight(u, makedev(0, 0), weight); (void) set_bfq_weight(u, "io", makedev(0, 0), weight);
xsprintf(buf, "default %" PRIu64 "\n", weight); xsprintf(buf, "default %" PRIu64 "\n", weight);
(void) set_attribute_and_warn(u, "io.weight", buf); (void) set_attribute_and_warn(u, "io", "io.weight", buf);
} }
static void cgroup_apply_bpf_foreign_program(Unit *u) { static void cgroup_apply_bpf_foreign_program(Unit *u) {
@ -1558,8 +1570,8 @@ static void cgroup_context_apply(
cgroup_apply_memory_limit(u, "memory.swap.max", swap_max); cgroup_apply_memory_limit(u, "memory.swap.max", swap_max);
cgroup_apply_memory_limit(u, "memory.zswap.max", zswap_max); cgroup_apply_memory_limit(u, "memory.zswap.max", zswap_max);
(void) set_attribute_and_warn(u, "memory.oom.group", one_zero(c->memory_oom_group)); (void) set_attribute_and_warn(u, "memory", "memory.oom.group", one_zero(c->memory_oom_group));
(void) set_attribute_and_warn(u, "memory.zswap.writeback", one_zero(c->memory_zswap_writeback)); (void) set_attribute_and_warn(u, "memory", "memory.zswap.writeback", one_zero(c->memory_zswap_writeback));
} }
if (apply_mask & CGROUP_MASK_PIDS) { if (apply_mask & CGROUP_MASK_PIDS) {
@ -1597,9 +1609,9 @@ static void cgroup_context_apply(
char buf[DECIMAL_STR_MAX(uint64_t) + 1]; char buf[DECIMAL_STR_MAX(uint64_t) + 1];
xsprintf(buf, "%" PRIu64 "\n", cgroup_tasks_max_resolve(&c->tasks_max)); xsprintf(buf, "%" PRIu64 "\n", cgroup_tasks_max_resolve(&c->tasks_max));
(void) set_attribute_and_warn(u, "pids.max", buf); (void) set_attribute_and_warn(u, "pids", "pids.max", buf);
} else } else
(void) set_attribute_and_warn(u, "pids.max", "max\n"); (void) set_attribute_and_warn(u, "pids", "pids.max", "max\n");
} }
} }
@ -1702,14 +1714,15 @@ static CGroupMask unit_get_cgroup_mask(Unit *u) {
mask |= CGROUP_MASK_CPUSET; mask |= CGROUP_MASK_CPUSET;
if (cgroup_context_has_io_config(c)) if (cgroup_context_has_io_config(c))
mask |= CGROUP_MASK_IO; mask |= CGROUP_MASK_IO | CGROUP_MASK_BLKIO;
if (c->memory_accounting || if (c->memory_accounting ||
unit_has_memory_config(u)) unit_has_memory_config(u))
mask |= CGROUP_MASK_MEMORY; mask |= CGROUP_MASK_MEMORY;
if (cgroup_context_has_device_policy(c)) if (c->device_allow ||
mask |= CGROUP_MASK_BPF_DEVICES; c->device_policy != CGROUP_DEVICE_POLICY_AUTO)
mask |= CGROUP_MASK_DEVICES | CGROUP_MASK_BPF_DEVICES;
if (c->tasks_accounting || if (c->tasks_accounting ||
cgroup_tasks_max_isset(&c->tasks_max)) cgroup_tasks_max_isset(&c->tasks_max))
@ -1827,7 +1840,7 @@ static CGroupMask unit_get_disable_mask(Unit *u) {
return c->disable_controllers; return c->disable_controllers;
} }
static CGroupMask unit_get_ancestor_disable_mask(Unit *u) { CGroupMask unit_get_ancestor_disable_mask(Unit *u) {
CGroupMask mask; CGroupMask mask;
Unit *slice; Unit *slice;
@ -2473,6 +2486,7 @@ static int unit_realize_cgroup_now_disable(Unit *u, ManagerState state) {
continue; continue;
/* We must disable those below us first in order to release the controller. */ /* We must disable those below us first in order to release the controller. */
if (m->type == UNIT_SLICE)
(void) unit_realize_cgroup_now_disable(m, state); (void) unit_realize_cgroup_now_disable(m, state);
target_mask = unit_get_target_mask(m); target_mask = unit_get_target_mask(m);
@ -3940,38 +3954,46 @@ int unit_reset_accounting(Unit *u) {
return r; return r;
} }
bool unit_invalidate_cgroup(Unit *u, CGroupMask m) { void unit_invalidate_cgroup(Unit *u, CGroupMask m) {
assert(u); assert(u);
if (!UNIT_HAS_CGROUP_CONTEXT(u)) if (!UNIT_HAS_CGROUP_CONTEXT(u))
return false; return;
CGroupRuntime *crt = unit_get_cgroup_runtime(u); CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt) if (!crt)
return false; return;
if (FLAGS_SET(crt->cgroup_invalidated_mask, m)) /* NOP? */ if (FLAGS_SET(crt->cgroup_invalidated_mask, m)) /* NOP? */
return false; return;
crt->cgroup_invalidated_mask |= m; crt->cgroup_invalidated_mask |= m;
unit_add_to_cgroup_realize_queue(u); unit_add_to_cgroup_realize_queue(u);
return true;
} }
void unit_invalidate_cgroup_bpf_firewall(Unit *u) { void unit_invalidate_cgroup_bpf(Unit *u) {
assert(u); assert(u);
if (!unit_invalidate_cgroup(u, CGROUP_MASK_BPF_FIREWALL)) if (!UNIT_HAS_CGROUP_CONTEXT(u))
return; return;
CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (!crt)
return;
if (crt->cgroup_invalidated_mask & CGROUP_MASK_BPF_FIREWALL) /* NOP? */
return;
crt->cgroup_invalidated_mask |= CGROUP_MASK_BPF_FIREWALL;
unit_add_to_cgroup_realize_queue(u);
/* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access /* If we are a slice unit, we also need to put compile a new BPF program for all our children, as the IP access
* list of our children includes our own. */ * list of our children includes our own. */
if (u->type == UNIT_SLICE) { if (u->type == UNIT_SLICE) {
Unit *member; Unit *member;
UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_SLICE_OF) UNIT_FOREACH_DEPENDENCY(member, u, UNIT_ATOM_SLICE_OF)
unit_invalidate_cgroup_bpf_firewall(member); unit_invalidate_cgroup_bpf(member);
} }
} }
@ -4011,7 +4033,7 @@ void manager_invalidate_startup_units(Manager *m) {
assert(m); assert(m);
SET_FOREACH(u, m->startup_units) SET_FOREACH(u, m->startup_units)
unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_CPUSET); unit_invalidate_cgroup(u, CGROUP_MASK_CPU|CGROUP_MASK_IO|CGROUP_MASK_BLKIO|CGROUP_MASK_CPUSET);
} }
static int unit_cgroup_freezer_kernel_state(Unit *u, FreezerState *ret) { static int unit_cgroup_freezer_kernel_state(Unit *u, FreezerState *ret) {

View File

@ -14,7 +14,7 @@ typedef struct CGroupTasksMax {
uint64_t scale; uint64_t scale;
} CGroupTasksMax; } CGroupTasksMax;
#define CGROUP_TASKS_MAX_UNSET ((const CGroupTasksMax) { .value = UINT64_MAX, .scale = 0 }) #define CGROUP_TASKS_MAX_UNSET ((CGroupTasksMax) { .value = UINT64_MAX, .scale = 0 })
static inline bool cgroup_tasks_max_isset(const CGroupTasksMax *tasks_max) { static inline bool cgroup_tasks_max_isset(const CGroupTasksMax *tasks_max) {
return tasks_max->value != UINT64_MAX || tasks_max->scale != 0; return tasks_max->value != UINT64_MAX || tasks_max->scale != 0;
@ -339,8 +339,8 @@ uint64_t cgroup_context_cpu_weight(CGroupContext *c, ManagerState state);
usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution, usec_t max_period); usec_t cgroup_cpu_adjust_period(usec_t period, usec_t quota, usec_t resolution, usec_t max_period);
void cgroup_context_init(CGroupContext *c); void cgroup_context_init(CGroupContext *c);
int cgroup_context_copy(CGroupContext *dst, const CGroupContext *src);
void cgroup_context_done(CGroupContext *c); void cgroup_context_done(CGroupContext *c);
void cgroup_context_dump(Unit *u, FILE* f, const char *prefix); void cgroup_context_dump(Unit *u, FILE* f, const char *prefix);
void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f); void cgroup_context_dump_socket_bind_item(const CGroupSocketBindItem *item, FILE *f);
void cgroup_context_dump_socket_bind_items(const CGroupSocketBindItem *items, FILE *f); void cgroup_context_dump_socket_bind_items(const CGroupSocketBindItem *items, FILE *f);
@ -359,13 +359,6 @@ static inline bool cgroup_context_want_memory_pressure(const CGroupContext *c) {
(c->memory_pressure_watch == CGROUP_PRESSURE_WATCH_AUTO && c->memory_accounting); (c->memory_pressure_watch == CGROUP_PRESSURE_WATCH_AUTO && c->memory_accounting);
} }
static inline bool cgroup_context_has_device_policy(const CGroupContext *c) {
assert(c);
return c->device_policy != CGROUP_DEVICE_POLICY_AUTO ||
c->device_allow;
}
int cgroup_context_add_device_allow(CGroupContext *c, const char *dev, CGroupDevicePermissions p); int cgroup_context_add_device_allow(CGroupContext *c, const char *dev, CGroupDevicePermissions p);
int cgroup_context_add_or_update_device_allow(CGroupContext *c, const char *dev, CGroupDevicePermissions p); int cgroup_context_add_or_update_device_allow(CGroupContext *c, const char *dev, CGroupDevicePermissions p);
int cgroup_context_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *path); int cgroup_context_add_bpf_foreign_program(CGroupContext *c, uint32_t attach_type, const char *path);
@ -376,6 +369,7 @@ CGroupMask unit_get_own_mask(Unit *u);
CGroupMask unit_get_delegate_mask(Unit *u); CGroupMask unit_get_delegate_mask(Unit *u);
CGroupMask unit_get_members_mask(Unit *u); CGroupMask unit_get_members_mask(Unit *u);
CGroupMask unit_get_siblings_mask(Unit *u); CGroupMask unit_get_siblings_mask(Unit *u);
CGroupMask unit_get_ancestor_disable_mask(Unit *u);
CGroupMask unit_get_target_mask(Unit *u); CGroupMask unit_get_target_mask(Unit *u);
CGroupMask unit_get_enable_mask(Unit *u); CGroupMask unit_get_enable_mask(Unit *u);
@ -436,8 +430,8 @@ bool unit_has_host_root_cgroup(const Unit *u);
bool unit_has_startup_cgroup_constraints(Unit *u); bool unit_has_startup_cgroup_constraints(Unit *u);
bool unit_invalidate_cgroup(Unit *u, CGroupMask m); void unit_invalidate_cgroup(Unit *u, CGroupMask m);
void unit_invalidate_cgroup_bpf_firewall(Unit *u); void unit_invalidate_cgroup_bpf(Unit *u);
void manager_invalidate_startup_units(Manager *m); void manager_invalidate_startup_units(Manager *m);

View File

@ -614,7 +614,7 @@ static int bus_cgroup_set_transient_property(
if (n == 0) if (n == 0)
*filters = strv_free(*filters); *filters = strv_free(*filters);
unit_invalidate_cgroup_bpf_firewall(u); unit_invalidate_cgroup_bpf(u);
f = memstream_init(&m); f = memstream_init(&m);
if (!f) if (!f)
@ -1527,7 +1527,7 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->device_policy = p; c->device_policy = p;
unit_invalidate_cgroup(u, CGROUP_MASK_BPF_DEVICES); unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy); unit_write_settingf(u, flags, name, "DevicePolicy=%s", policy);
} }
@ -1579,7 +1579,7 @@ int bus_cgroup_set_property(
while (c->device_allow) while (c->device_allow)
cgroup_context_free_device_allow(c, c->device_allow); cgroup_context_free_device_allow(c, c->device_allow);
unit_invalidate_cgroup(u, CGROUP_MASK_BPF_DEVICES); unit_invalidate_cgroup(u, CGROUP_MASK_DEVICES);
f = memstream_init(&m); f = memstream_init(&m);
if (!f) if (!f)
@ -1608,7 +1608,7 @@ int bus_cgroup_set_property(
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
c->ip_accounting = b; c->ip_accounting = b;
unit_invalidate_cgroup_bpf_firewall(u); unit_invalidate_cgroup_bpf(u);
unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b)); unit_write_settingf(u, flags, name, "IPAccounting=%s", yes_no(b));
} }
@ -1670,7 +1670,7 @@ int bus_cgroup_set_property(
bool *reduced; bool *reduced;
FILE *f; FILE *f;
unit_invalidate_cgroup_bpf_firewall(u); unit_invalidate_cgroup_bpf(u);
f = memstream_init(&m); f = memstream_init(&m);
if (!f) if (!f)

View File

@ -31,9 +31,7 @@
#include "namespace.h" #include "namespace.h"
#include "nsflags.h" #include "nsflags.h"
#include "ordered-set.h" #include "ordered-set.h"
#include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "percent-util.h"
#include "pcre2-util.h" #include "pcre2-util.h"
#include "process-util.h" #include "process-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
@ -1002,22 +1000,6 @@ static int property_get_exec_dir_symlink(
return sd_bus_message_close_container(reply); return sd_bus_message_close_container(reply);
} }
static int property_get_exec_quota(sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
QuotaLimit *q = ASSERT_PTR(userdata);
assert(bus);
assert(reply);
return sd_bus_message_append(reply, "(tus)", q->quota_absolute, q->quota_scale, yes_no(q->quota_enforce));
}
static int property_get_image_policy( static int property_get_image_policy(
sd_bus *bus, sd_bus *bus,
const char *path, const char *path,
@ -1284,18 +1266,12 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_PROPERTY("RuntimeDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("RuntimeDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_RUNTIME]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StateDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StateDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StateDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StateDirectoryAccounting", "b", bus_property_get_bool, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].exec_quota.quota_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StateDirectoryQuota", "(tus)", property_get_exec_quota, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE].exec_quota), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("StateDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("StateDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_STATE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CacheDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CacheDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CacheDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CacheDirectoryAccounting", "b", bus_property_get_bool, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].exec_quota.quota_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CacheDirectoryQuota", "(tus)", property_get_exec_quota, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE].exec_quota), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("CacheDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("CacheDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CACHE]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogsDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LogsDirectorySymlink", "a(sst)", property_get_exec_dir_symlink, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LogsDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogsDirectoryAccounting", "b", bus_property_get_bool, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].exec_quota.quota_accounting), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogsDirectoryQuota", "(tus)", property_get_exec_quota, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS].exec_quota), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("LogsDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("LogsDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_LOGS]), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConfigurationDirectoryMode", "u", bus_property_get_mode, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION].mode), SD_BUS_VTABLE_PROPERTY_CONST),
SD_BUS_PROPERTY("ConfigurationDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION]), SD_BUS_VTABLE_PROPERTY_CONST), SD_BUS_PROPERTY("ConfigurationDirectory", "as", property_get_exec_dir, offsetof(ExecContext, directories[EXEC_DIRECTORY_CONFIGURATION]), SD_BUS_VTABLE_PROPERTY_CONST),
@ -1333,60 +1309,6 @@ const sd_bus_vtable bus_exec_vtable[] = {
SD_BUS_VTABLE_END SD_BUS_VTABLE_END
}; };
static int property_get_quota_usage(
sd_bus *bus,
const char *path,
const char *interface,
const char *property,
sd_bus_message *reply,
void *userdata,
sd_bus_error *error) {
Unit *u = ASSERT_PTR(userdata);
ExecContext *c = ASSERT_PTR(unit_get_exec_context(u));
uint64_t current_usage_bytes = UINT64_MAX, limit_bytes = UINT64_MAX;
int r;
assert(bus);
assert(reply);
ExecDirectoryType dt;
if (streq(property, "StateDirectoryQuotaUsage"))
dt = EXEC_DIRECTORY_STATE;
else if (streq(property, "CacheDirectoryQuotaUsage"))
dt = EXEC_DIRECTORY_CACHE;
else if (streq(property, "LogsDirectoryQuotaUsage"))
dt = EXEC_DIRECTORY_LOGS;
else
assert_not_reached();
const QuotaLimit *q;
q = &c->directories[dt].exec_quota;
if (q->quota_enforce || q->quota_accounting) {
r = unit_get_exec_quota_stats(u, c, dt, &current_usage_bytes, &limit_bytes);
if (r < 0)
return r;
}
if (!q->quota_enforce)
limit_bytes = UINT64_MAX;
if (!q->quota_accounting)
current_usage_bytes = UINT64_MAX;
return sd_bus_message_append(reply, "(tt)", current_usage_bytes, limit_bytes);
}
const sd_bus_vtable bus_unit_exec_vtable[] = {
SD_BUS_VTABLE_START(0),
SD_BUS_PROPERTY("StateDirectoryQuotaUsage", "(tt)", property_get_quota_usage, 0, 0),
SD_BUS_PROPERTY("CacheDirectoryQuotaUsage", "(tt)", property_get_quota_usage, 0, 0),
SD_BUS_PROPERTY("LogsDirectoryQuotaUsage", "(tt)", property_get_quota_usage, 0, 0),
SD_BUS_VTABLE_END
};
static int append_exec_command(sd_bus_message *reply, ExecCommand *c) { static int append_exec_command(sd_bus_message *reply, ExecCommand *c) {
int r; int r;
@ -2288,15 +2210,6 @@ int bus_exec_context_set_transient_property(
if (streq(name, "RuntimeDirectoryMode")) if (streq(name, "RuntimeDirectoryMode"))
return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error); return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_RUNTIME].mode, message, flags, error);
if (streq(name, "StateDirectoryAccounting"))
return bus_set_transient_bool(u, name, &c->directories[EXEC_DIRECTORY_STATE].exec_quota.quota_accounting, message, flags, error);
if (streq(name, "CacheDirectoryAccounting"))
return bus_set_transient_bool(u, name, &c->directories[EXEC_DIRECTORY_CACHE].exec_quota.quota_accounting, message, flags, error);
if (streq(name, "LogsDirectoryAccounting"))
return bus_set_transient_bool(u, name, &c->directories[EXEC_DIRECTORY_LOGS].exec_quota.quota_accounting, message, flags, error);
if (streq(name, "StateDirectoryMode")) if (streq(name, "StateDirectoryMode"))
return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error); return bus_set_transient_mode_t(u, name, &c->directories[EXEC_DIRECTORY_STATE].mode, message, flags, error);
@ -2402,7 +2315,7 @@ int bus_exec_context_set_transient_property(
STRV_FOREACH(p, l) STRV_FOREACH(p, l)
if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN)) if (!isempty(*p) && !valid_user_group_name(*p, VALID_USER_ALLOW_NUMERIC|VALID_USER_RELAX|VALID_USER_WARN))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid supplementary group names"); "Invalid supplementary group names");
if (!UNIT_WRITE_FLAGS_NOOP(flags)) { if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
@ -3690,47 +3603,6 @@ int bus_exec_context_set_transient_property(
return 1; return 1;
} else if (STR_IN_SET(name, "StateDirectoryQuota", "CacheDirectoryQuota", "LogsDirectoryQuota")) {
uint64_t quota_absolute = UINT64_MAX;
uint32_t quota_scale = UINT32_MAX;
const char *enforce_flag;
int quota_enforce;
r = sd_bus_message_read(message, "(tus)", &quota_absolute, &quota_scale, &enforce_flag);
if (r < 0)
return r;
quota_enforce = parse_boolean(enforce_flag);
if (quota_enforce < 0)
return quota_enforce;
if (!UNIT_WRITE_FLAGS_NOOP(flags)) {
ExecDirectoryType dt;
if (streq(name, "StateDirectoryQuota"))
dt = EXEC_DIRECTORY_STATE;
else if (streq(name, "CacheDirectoryQuota"))
dt = EXEC_DIRECTORY_CACHE;
else if (streq(name, "LogsDirectoryQuota"))
dt = EXEC_DIRECTORY_LOGS;
else
assert_not_reached();
if (quota_enforce) {
c->directories[dt].exec_quota.quota_absolute = quota_absolute;
c->directories[dt].exec_quota.quota_scale = quota_scale;
if (quota_absolute != UINT64_MAX)
unit_write_settingf(u, flags, name, "%s=%" PRIu64, name, quota_absolute);
else
unit_write_settingf(u, flags, name, "%s=%d%%", name, UINT32_SCALE_TO_PERCENT(quota_scale));
} else
unit_write_settingf(u, flags, name, "%s=", name);
c->directories[dt].exec_quota.quota_enforce = quota_enforce;
}
return 1;
} else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) { } else if (STR_IN_SET(name, "AppArmorProfile", "SmackProcessLabel")) {
int ignore; int ignore;
const char *s; const char *s;

View File

@ -24,7 +24,6 @@
SD_BUS_PROPERTY(name, "a(sasasttttuii)", bus_property_get_exec_ex_command_list, offset, flags) SD_BUS_PROPERTY(name, "a(sasasttttuii)", bus_property_get_exec_ex_command_list, offset, flags)
extern const sd_bus_vtable bus_exec_vtable[]; extern const sd_bus_vtable bus_exec_vtable[];
extern const sd_bus_vtable bus_unit_exec_vtable[];
int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); int bus_property_get_exec_output(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);
int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error); int bus_property_get_exec_command(sd_bus *bus, const char *path, const char *interface, const char *property, sd_bus_message *reply, void *userdata, sd_bus_error *ret_error);

View File

@ -831,12 +831,6 @@ static int method_kill_unit(sd_bus_message *message, void *userdata, sd_bus_erro
return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0); return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill, 0);
} }
static int method_kill_unit_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error) {
/* We don't bother with GENERIC_UNIT_LOAD nor GENERIC_UNIT_VALIDATE_LOADED here, as it shouldn't
* matter whether a unit is loaded for killing any processes possibly in the unit's cgroup. */
return method_generic_unit_operation(message, userdata, error, bus_unit_method_kill_subgroup, 0);
}
static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) { static int method_clean_unit(sd_bus_message *message, void *userdata, sd_bus_error *error) {
/* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be /* Load the unit if necessary, in order to load it, and insist on the unit being loaded to be
* cleaned */ * cleaned */
@ -995,7 +989,7 @@ static int transient_unit_from_message(
t = unit_name_to_type(name); t = unit_name_to_type(name);
if (t < 0) if (t < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid unit name or type: %s", name); "Invalid unit name or type.");
if (!unit_vtable[t]->can_transient) if (!unit_vtable[t]->can_transient)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@ -1548,7 +1542,7 @@ static int method_reload(sd_bus_message *message, void *userdata, sd_bus_error *
/* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */ /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */
if (!ratelimit_below(&m->reload_reexec_ratelimit)) { if (!ratelimit_below(&m->reload_reexec_ratelimit)) {
log_warning("Reloading request rejected due to rate limit."); log_warning("Reloading request rejected due to rate limit.");
return sd_bus_error_set(error, return sd_bus_error_setf(error,
SD_BUS_ERROR_LIMITS_EXCEEDED, SD_BUS_ERROR_LIMITS_EXCEEDED,
"Reload() request rejected due to rate limit."); "Reload() request rejected due to rate limit.");
} }
@ -1590,7 +1584,7 @@ static int method_reexecute(sd_bus_message *message, void *userdata, sd_bus_erro
/* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */ /* Check the rate limit after the authorization succeeds, to avoid denial-of-service issues. */
if (!ratelimit_below(&m->reload_reexec_ratelimit)) { if (!ratelimit_below(&m->reload_reexec_ratelimit)) {
log_warning("Reexecution request rejected due to rate limit."); log_warning("Reexecution request rejected due to rate limit.");
return sd_bus_error_set(error, return sd_bus_error_setf(error,
SD_BUS_ERROR_LIMITS_EXCEEDED, SD_BUS_ERROR_LIMITS_EXCEEDED,
"Reexecute() request rejected due to rate limit."); "Reexecute() request rejected due to rate limit.");
} }
@ -1889,7 +1883,7 @@ static int method_unset_environment(sd_bus_message *message, void *userdata, sd_
return r; return r;
if (!strv_env_name_or_assignment_is_valid(minus)) if (!strv_env_name_or_assignment_is_valid(minus))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid environment variable names or assignments"); "Invalid environment variable names or assignments");
r = bus_verify_set_environment_async(m, message, error); r = bus_verify_set_environment_async(m, message, error);
@ -1925,10 +1919,10 @@ static int method_unset_and_set_environment(sd_bus_message *message, void *userd
return r; return r;
if (!strv_env_name_or_assignment_is_valid(minus)) if (!strv_env_name_or_assignment_is_valid(minus))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid environment variable names or assignments"); "Invalid environment variable names or assignments");
if (!strv_env_is_valid(plus)) if (!strv_env_is_valid(plus))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Invalid environment assignments"); "Invalid environment assignments");
r = bus_verify_set_environment_async(m, message, error); r = bus_verify_set_environment_async(m, message, error);
@ -1977,7 +1971,7 @@ static int method_lookup_dynamic_user_by_name(sd_bus_message *message, void *use
return r; return r;
if (!MANAGER_IS_SYSTEM(m)) if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Dynamic users are only supported in the system instance."); "Dynamic users are only supported in the system instance.");
if (!valid_user_group_name(name, VALID_USER_RELAX)) if (!valid_user_group_name(name, VALID_USER_RELAX))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@ -2007,7 +2001,7 @@ static int method_lookup_dynamic_user_by_uid(sd_bus_message *message, void *user
return r; return r;
if (!MANAGER_IS_SYSTEM(m)) if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Dynamic users are only supported in the system instance."); "Dynamic users are only supported in the system instance.");
if (!uid_is_valid(uid)) if (!uid_is_valid(uid))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
@ -2034,7 +2028,7 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_
assert_cc(sizeof(uid_t) == sizeof(uint32_t)); assert_cc(sizeof(uid_t) == sizeof(uint32_t));
if (!MANAGER_IS_SYSTEM(m)) if (!MANAGER_IS_SYSTEM(m))
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Dynamic users are only supported in the system instance."); "Dynamic users are only supported in the system instance.");
r = sd_bus_message_new_method_return(message, &reply); r = sd_bus_message_new_method_return(message, &reply);
@ -2052,7 +2046,7 @@ static int method_get_dynamic_users(sd_bus_message *message, void *userdata, sd_
if (r == -EAGAIN) /* not realized yet? */ if (r == -EAGAIN) /* not realized yet? */
continue; continue;
if (r < 0) if (r < 0)
return sd_bus_error_set(error, SD_BUS_ERROR_FAILED, return sd_bus_error_setf(error, SD_BUS_ERROR_FAILED,
"Failed to look up a dynamic user."); "Failed to look up a dynamic user.");
r = sd_bus_message_append(reply, "(us)", uid, d->name); r = sd_bus_message_append(reply, "(us)", uid, d->name);
@ -2235,7 +2229,7 @@ static int method_get_default_target(sd_bus_message *message, void *userdata, sd
r = unit_file_get_default(m->runtime_scope, NULL, &default_target); r = unit_file_get_default(m->runtime_scope, NULL, &default_target);
if (r == -ERFKILL) if (r == -ERFKILL)
return sd_bus_error_set(error, BUS_ERROR_UNIT_MASKED, "Default target unit file is masked."); sd_bus_error_setf(error, BUS_ERROR_UNIT_MASKED, "Unit file is masked.");
if (r < 0) if (r < 0)
return r; return r;
@ -3031,11 +3025,6 @@ const sd_bus_vtable bus_manager_vtable[] = {
SD_BUS_NO_RESULT, SD_BUS_NO_RESULT,
method_kill_unit, method_kill_unit,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("KillUnitSubgroup",
SD_BUS_ARGS("s", name, "s", whom, "s", subgroup, "i", signal),
SD_BUS_NO_RESULT,
method_kill_unit_subgroup,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("QueueSignalUnit", SD_BUS_METHOD_WITH_ARGS("QueueSignalUnit",
SD_BUS_ARGS("s", name, "s", whom, "i", signal, "i", value), SD_BUS_ARGS("s", name, "s", whom, "i", signal, "i", value),
SD_BUS_NO_RESULT, SD_BUS_NO_RESULT,

View File

@ -572,60 +572,7 @@ int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *
if (r == 0) if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */ return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = unit_kill(u, whom, /* subgroup= */ NULL, signo, code, value, error); r = unit_kill(u, whom, signo, code, value, error);
if (r < 0)
return r;
return sd_bus_reply_method_return(message, NULL);
}
int bus_unit_method_kill_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error) {
Unit *u = ASSERT_PTR(userdata);
int r;
assert(message);
r = mac_selinux_unit_access_check(u, message, "stop", error);
if (r < 0)
return r;
const char *swhom, *subgroup;
int32_t signo;
r = sd_bus_message_read(message, "ssi", &swhom, &subgroup, &signo);
if (r < 0)
return r;
KillWhom whom;
if (isempty(swhom))
whom = KILL_CGROUP;
else {
whom = kill_whom_from_string(swhom);
if (whom < 0)
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid whom argument: %s", swhom);
}
if (isempty(subgroup))
subgroup = NULL;
else if (!path_is_normalized(subgroup))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Specified cgroup sub-path is not valid.");
else if (!IN_SET(whom, KILL_CGROUP, KILL_CGROUP_FAIL))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Subgroup can only be specified in combination with 'cgroup' or 'cgroup-fail'.");
if (!SIGNAL_VALID(signo))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Signal number out of range.");
r = bus_verify_manage_units_async_full(
u,
"kill-subgroup",
N_("Authentication is required to send a UNIX signal to the processes of subgroup of '$(unit)'."),
message,
error);
if (r < 0)
return r;
if (r == 0)
return 1; /* No authorization for now, but the async polkit stuff will call us again when it has it */
r = unit_kill(u, whom, subgroup, signo, SI_USER, /* value= */ 0, error);
if (r < 0) if (r < 0)
return r; return r;
@ -1039,11 +986,6 @@ const sd_bus_vtable bus_unit_vtable[] = {
SD_BUS_NO_RESULT, SD_BUS_NO_RESULT,
bus_unit_method_kill, bus_unit_method_kill,
SD_BUS_VTABLE_UNPRIVILEGED), SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("KillSubgroup",
SD_BUS_ARGS("s", subgroup, "i", signal),
SD_BUS_NO_RESULT,
bus_unit_method_kill_subgroup,
SD_BUS_VTABLE_UNPRIVILEGED),
SD_BUS_METHOD_WITH_ARGS("QueueSignal", SD_BUS_METHOD_WITH_ARGS("QueueSignal",
SD_BUS_ARGS("s", whom, "i", signal, "i", value), SD_BUS_ARGS("s", whom, "i", signal, "i", value),
SD_BUS_NO_RESULT, SD_BUS_NO_RESULT,
@ -1677,7 +1619,7 @@ int bus_unit_method_remove_subgroup(sd_bus_message *message, void *userdata, sd_
/* Allow this only if the client is privileged, is us, or is the user of the unit itself. */ /* 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) if (sender_uid != 0 && sender_uid != getuid() && sender_uid != u->ref_uid)
return sd_bus_error_set(error, SD_BUS_ERROR_ACCESS_DENIED, "Client is not permitted to alter cgroup."); return sd_bus_error_setf(error, SD_BUS_ERROR_ACCESS_DENIED, "Client is not permitted to alter cgroup.");
r = unit_remove_subcgroup(u, path); r = unit_remove_subcgroup(u, path);
if (r < 0) if (r < 0)

View File

@ -16,7 +16,6 @@ void bus_unit_send_removed_signal(Unit *u);
int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error); int bus_unit_method_start_generic(sd_bus_message *message, Unit *u, JobType job_type, bool reload_if_possible, sd_bus_error *error);
int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_enqueue_job(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_kill(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_kill_subgroup(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error); int bus_unit_method_reset_failed(sd_bus_message *message, void *userdata, sd_bus_error *error);
int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitWriteFlags flags, bool commit, sd_bus_error *error); int bus_unit_set_properties(Unit *u, sd_bus_message *message, UnitWriteFlags flags, bool commit, sd_bus_error *error);

View File

@ -338,8 +338,9 @@ static int bus_cgroup_context_find(sd_bus *bus, const char *path, const char *in
return 1; return 1;
} }
static int bus_unit_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) { 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 = ASSERT_PTR(userdata); Manager *m = ASSERT_PTR(userdata);
ExecContext *c;
Unit *u; Unit *u;
int r; int r;
@ -355,27 +356,6 @@ static int bus_unit_exec_context_find(sd_bus *bus, const char *path, const char
if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type))) if (!streq_ptr(interface, unit_dbus_interface_from_type(u->type)))
return 0; return 0;
if (!UNIT_HAS_EXEC_CONTEXT(u))
return 0;
*found = u;
return 1;
}
static int bus_exec_context_find(sd_bus *bus, const char *path, const char *interface, void *userdata, void **found, sd_bus_error *error) {
ExecContext *c;
int r;
assert(bus);
assert(path);
assert(interface);
assert(found);
Unit *u;
r = bus_unit_exec_context_find(bus, path, interface, userdata, (void**) &u, error);
if (r <= 0)
return r;
c = unit_get_exec_context(u); c = unit_get_exec_context(u);
if (!c) if (!c)
return 0; return 0;
@ -463,7 +443,6 @@ static const BusObjectImplementation bus_mount_object = {
{ bus_unit_cgroup_vtable, bus_unit_cgroup_find }, { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
{ bus_cgroup_vtable, bus_cgroup_context_find }, { bus_cgroup_vtable, bus_cgroup_context_find },
{ bus_exec_vtable, bus_exec_context_find }, { bus_exec_vtable, bus_exec_context_find },
{ bus_unit_exec_vtable, bus_unit_exec_context_find },
{ bus_kill_vtable, bus_kill_context_find }), { bus_kill_vtable, bus_kill_context_find }),
}; };
@ -492,7 +471,6 @@ static const BusObjectImplementation bus_service_object = {
{ bus_unit_cgroup_vtable, bus_unit_cgroup_find }, { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
{ bus_cgroup_vtable, bus_cgroup_context_find }, { bus_cgroup_vtable, bus_cgroup_context_find },
{ bus_exec_vtable, bus_exec_context_find }, { bus_exec_vtable, bus_exec_context_find },
{ bus_unit_exec_vtable, bus_unit_exec_context_find },
{ bus_kill_vtable, bus_kill_context_find }), { bus_kill_vtable, bus_kill_context_find }),
}; };
@ -513,7 +491,6 @@ static const BusObjectImplementation bus_socket_object = {
{ bus_unit_cgroup_vtable, bus_unit_cgroup_find }, { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
{ bus_cgroup_vtable, bus_cgroup_context_find }, { bus_cgroup_vtable, bus_cgroup_context_find },
{ bus_exec_vtable, bus_exec_context_find }, { bus_exec_vtable, bus_exec_context_find },
{ bus_unit_exec_vtable, bus_unit_exec_context_find },
{ bus_kill_vtable, bus_kill_context_find }), { bus_kill_vtable, bus_kill_context_find }),
}; };
@ -525,7 +502,6 @@ static const BusObjectImplementation bus_swap_object = {
{ bus_unit_cgroup_vtable, bus_unit_cgroup_find }, { bus_unit_cgroup_vtable, bus_unit_cgroup_find },
{ bus_cgroup_vtable, bus_cgroup_context_find }, { bus_cgroup_vtable, bus_cgroup_context_find },
{ bus_exec_vtable, bus_exec_context_find }, { bus_exec_vtable, bus_exec_context_find },
{ bus_unit_exec_vtable, bus_unit_exec_context_find },
{ bus_kill_vtable, bus_kill_context_find }), { bus_kill_vtable, bus_kill_context_find }),
}; };
@ -1184,7 +1160,6 @@ void dump_bus_properties(FILE *f) {
vtable_dump_bus_properties(f, bus_cgroup_vtable); vtable_dump_bus_properties(f, bus_cgroup_vtable);
vtable_dump_bus_properties(f, bus_device_vtable); vtable_dump_bus_properties(f, bus_device_vtable);
vtable_dump_bus_properties(f, bus_exec_vtable); vtable_dump_bus_properties(f, bus_exec_vtable);
vtable_dump_bus_properties(f, bus_unit_exec_vtable);
vtable_dump_bus_properties(f, bus_job_vtable); vtable_dump_bus_properties(f, bus_job_vtable);
vtable_dump_bus_properties(f, bus_kill_vtable); vtable_dump_bus_properties(f, bus_kill_vtable);
vtable_dump_bus_properties(f, bus_manager_vtable); vtable_dump_bus_properties(f, bus_manager_vtable);

View File

@ -445,7 +445,8 @@ static bool device_nodes_restricted(
if (c->private_devices) if (c->private_devices)
return true; return true;
if (cgroup_context_has_device_policy(cgroup_context)) if (cgroup_context->device_policy != CGROUP_DEVICE_POLICY_AUTO ||
cgroup_context->device_allow)
return true; return true;
return false; return false;

View File

@ -10,7 +10,6 @@
#include <sys/ioctl.h> #include <sys/ioctl.h>
#include <sys/mount.h> #include <sys/mount.h>
#include <sys/prctl.h> #include <sys/prctl.h>
#include <sys/statvfs.h>
#include <unistd.h> #include <unistd.h>
#if HAVE_PAM #if HAVE_PAM
@ -31,7 +30,6 @@
#include "cgroup-setup.h" #include "cgroup-setup.h"
#include "cgroup.h" #include "cgroup.h"
#include "chase.h" #include "chase.h"
#include "chattr-util.h"
#include "chown-recursive.h" #include "chown-recursive.h"
#include "constants.h" #include "constants.h"
#include "copy.h" #include "copy.h"
@ -62,19 +60,15 @@
#include "open-file.h" #include "open-file.h"
#include "osc-context.h" #include "osc-context.h"
#include "path-util.h" #include "path-util.h"
#include "percent-util.h"
#include "pidref.h" #include "pidref.h"
#include "proc-cmdline.h" #include "proc-cmdline.h"
#include "process-util.h" #include "process-util.h"
#include "psi-util.h" #include "psi-util.h"
#include "quota-util.h"
#include "random-util.h"
#include "rlimit-util.h" #include "rlimit-util.h"
#include "seccomp-util.h" #include "seccomp-util.h"
#include "selinux-util.h" #include "selinux-util.h"
#include "set.h" #include "set.h"
#include "signal-util.h" #include "signal-util.h"
#include "siphash24.h"
#include "smack-util.h" #include "smack-util.h"
#include "socket-util.h" #include "socket-util.h"
#include "stat-util.h" #include "stat-util.h"
@ -90,11 +84,6 @@
#define SNDBUF_SIZE (8*1024*1024) #define SNDBUF_SIZE (8*1024*1024)
/* Project id range for disk quotas */
#define PROJ_ID_MIN UINT32_C(2147483648)
#define PROJ_ID_MAX UINT32_C(4294967294)
#define PROJ_ID_CLAMP_INTO_QUOTA_RANGE(id) ((uint32_t) ((id) % (PROJ_ID_MAX - PROJ_ID_MIN + 1)) + PROJ_ID_MIN)
static int flag_fds( static int flag_fds(
const int fds[], const int fds[],
size_t n_socket_fds, size_t n_socket_fds,
@ -2586,217 +2575,6 @@ static int create_many_symlinks(const char *root, const char *source, char **sym
return 0; return 0;
} }
static int set_exec_storage_quota(int fd, uint32_t proj_id, const QuotaLimit *ql) {
int r;
uint64_t block_limit = 0, inode_limit = 0;
assert(fd >= 0);
assert(ql);
if (ql->quota_absolute == 0 || ql->quota_scale == 0)
/* Limit of 0 means no usage is allowed. For quotactl, use 1 as the limit, since 0 means that
* hard limits are disabled */
block_limit = inode_limit = 1;
else if (ql->quota_absolute == UINT64_MAX) {
_cleanup_close_ int fd_parent = -EBADF;
/* Use target_dir's parent when setting quotas. If a FD for target_dir has been previously
* used for quotactl_fd(SET) and is passed again for fstatvfs(), the total number of blocks is not
* reported accurately (instead, the block limit is reported as total blocks). Thus, use the FD
* associated with the parent, so that total blocks is accurate */
fd_parent = openat(fd, "..", O_PATH|O_CLOEXEC|O_DIRECTORY);
if (fd_parent < 0)
return -errno;
uint32_t xattr_flags = 0;
r = read_fs_xattr_fd(fd_parent, &xattr_flags, /* ret_projid = */ NULL);
if (r < 0)
return r;
/* Refuse if parent has FS_XFLAG_PROJINHERIT since this will mean the total number of blocks will not
* be reported accurately */
if (FLAGS_SET(xattr_flags, FS_XFLAG_PROJINHERIT))
return -ENOMEDIUM;
struct statvfs disk_st;
if (fstatvfs(fd_parent, &disk_st) < 0)
return -errno;
block_limit = (uint64_t) DIV_ROUND_UP((uint64_t)((double) (disk_st.f_frsize * disk_st.f_blocks) / UINT32_MAX * ql->quota_scale), QIF_DQBLKSIZE);
inode_limit = (uint64_t) ((double) disk_st.f_files / UINT32_MAX * ql->quota_scale);
} else
block_limit = (uint64_t) DIV_ROUND_UP(ql->quota_absolute, QIF_DQBLKSIZE);
struct dqblk req = {
.dqb_bhardlimit = block_limit,
.dqb_ihardlimit = inode_limit,
.dqb_valid = QIF_LIMITS,
};
r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_SETQUOTA, PRJQUOTA), proj_id, &req);
if (r < 0)
return r;
log_debug("Storage quotas set for project id %" PRIu32 ". Block limit = %" PRIu64 ", inode limit = %" PRIu64, proj_id, block_limit, inode_limit);
return 0;
}
static int unset_exec_storage_quota(int fd, uint32_t proj_id, bool quota_accounting) {
int r, quota_supported;
struct dqblk req;
assert(fd >= 0);
quota_supported = quota_query_proj_id(fd, proj_id, &req);
if (quota_supported < 0)
return log_debug_errno(quota_supported, "Failed to query disk quota for project ID %" PRIu32 ": %m", proj_id);
/* Do not enforce quotas anymore */
if (quota_supported && FLAGS_SET(req.dqb_valid, QIF_BLIMITS) && (req.dqb_bhardlimit > 0 || req.dqb_ihardlimit > 0)) {
req.dqb_bhardlimit = 0, req.dqb_ihardlimit = 0;
r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_SETQUOTA, PRJQUOTA), proj_id, &req);
if (r < 0)
return log_debug_errno(r, "Failed to disable project quotas for project ID %" PRIu32 ": %m", proj_id);
log_debug("Storage quotas for project ID %" PRIu32 " were disabled", proj_id);
}
/* Release project ID if no accounting needed */
if (!quota_accounting) {
r = set_proj_id_recursive(fd, 0);
if (r < 0)
log_warning_errno(r, "Failed to release project ID %" PRIu32 ", ignoring: %m", proj_id);
}
return 0;
}
static int apply_exec_quotas(
const char *target_dir,
const char *cgroup_path,
ExecDirectoryType type,
const QuotaLimit *ql,
uint32_t *exec_dt_proj_id, /* in/out */
bool *already_enforced) { /* in/out */
_cleanup_close_ int fd = -EBADF;
int r, quota_supported = 0;
assert(target_dir);
assert(cgroup_path);
assert(ql);
assert(exec_dt_proj_id);
assert(already_enforced);
/* Do not apply to the Runtime directory since tmpfs does not support project IDs yet */
if (!IN_SET(type, EXEC_DIRECTORY_STATE, EXEC_DIRECTORY_CACHE, EXEC_DIRECTORY_LOGS))
return 0;
fd = open(target_dir, O_PATH|O_CLOEXEC|O_DIRECTORY);
if (fd < 0)
return log_debug_errno(errno, "Failed to open %s: %m", target_dir);
/* Get the project ID of the current directory */
uint32_t proj_id;
r = read_fs_xattr_fd(fd, /* ret_xflags = */ NULL, &proj_id);
if (ERRNO_IS_NEG_IOCTL_NOT_SUPPORTED(r)) {
log_debug_errno(r, "Not applying storage quotas. FS_IOC_FSGETXATTR not supported for %s: %m", target_dir);
return 0;
}
if (r < 0)
return log_debug_errno(r, "Failed to retrieve project ID for %s: %m", target_dir);
/* If the first directory of this ExecType already has a project ID, adopt it as the project ID for all dirs of this ExecType */
bool proj_id_exists = PROJ_ID_MIN <= proj_id && proj_id <= PROJ_ID_MAX;
if (proj_id_exists && *exec_dt_proj_id == 0)
*exec_dt_proj_id = proj_id;
/* Check if enforcement should be disabled. Do not release project ID if accounting is enabled */
if (!ql->quota_enforce) {
if (proj_id_exists) {
r = unset_exec_storage_quota(fd, proj_id, ql->quota_accounting);
if (r < 0)
return log_debug_errno(r, "Failed to unset project quotas for %s: %m", target_dir);
}
if (!ql->quota_accounting)
return 0;
}
if (*exec_dt_proj_id > 0 && *exec_dt_proj_id != proj_id) {
/* Set the existing project ID only if the current directory's ID does not exist or does not match */
proj_id = *exec_dt_proj_id;
r = quota_proj_id_set_recursive(fd, proj_id, false);
if (r < 0)
return log_debug_errno(r, "Failed to set project ID for %s: %m", target_dir);
} else if (*exec_dt_proj_id == 0) {
/* Only generate a new project ID if it's the first directory of this ExecType to be processed and does not have an existing ID */
static const sd_id128_t k = SD_ID128_ARRAY(e1,4a,79,9b,64,40,41,4a,a8,46,c2,f3,f9,19,4f,01);
_cleanup_free_ char *proj_id_plain = NULL;
/* Generate candidate project id */
proj_id_plain = strjoin(cgroup_path, "|", exec_directory_type_to_string(type));
if (!proj_id_plain)
return log_oom_debug();
struct siphash state;
siphash24_init(&state, k.bytes);
siphash24_compress_string(proj_id_plain, &state);
proj_id = PROJ_ID_CLAMP_INTO_QUOTA_RANGE(siphash24_finalize(&state));
#define MAX_PROJ_ID_RETRIES 10
for (unsigned attempt = 0;; attempt++) {
if (attempt >= MAX_PROJ_ID_RETRIES)
return log_debug_errno(SYNTHETIC_ERRNO(EBUSY), "Failed to generate unique project ID for %s: %m", target_dir);
/* Check if project quotas are supported */
struct dqblk req;
quota_supported = quota_query_proj_id(fd, proj_id, &req);
if (quota_supported < 0)
return log_debug_errno(quota_supported, "Failed to query disk quota for project ID %" PRIu32 ": %m", proj_id);
if (!quota_supported) {
log_debug("Not applying storage quotas. Project quotas are not supported for %s", target_dir);
return 0;
}
if (!quota_dqblk_is_populated(&req)) {
int proj_id_was_set = quota_proj_id_set_recursive(fd, proj_id, true);
if (proj_id_was_set < 0)
return log_debug_errno(proj_id_was_set, "Failed to set project ID for %s: %m", target_dir);
if (proj_id_was_set) {
*exec_dt_proj_id = proj_id;
log_debug("Project ID %u generated for %s", proj_id, target_dir);
break;
}
}
proj_id = (uint32_t) (random_u64_range(PROJ_ID_MAX - PROJ_ID_MIN + 1) + PROJ_ID_MIN);
}
}
if (ql->quota_enforce && !*already_enforced) {
if (!quota_supported) {
struct dqblk req;
quota_supported = quota_query_proj_id(fd, proj_id, &req);
if (quota_supported < 0)
return log_debug_errno(quota_supported, "Failed to query disk quota for project ID %" PRIu32 ": %m", proj_id);
if (!quota_supported) {
log_debug("Not applying storage quotas. Project quotas are not supported for %s", target_dir);
return 0;
}
}
r = set_exec_storage_quota(fd, proj_id, ql);
if (r < 0)
return log_debug_errno(r, "Failed to set storage quotas for %s: %m", target_dir);
*already_enforced = true;
}
return r;
}
static int setup_exec_directory( static int setup_exec_directory(
const ExecContext *context, const ExecContext *context,
const ExecParameters *params, const ExecParameters *params,
@ -2830,9 +2608,6 @@ static int setup_exec_directory(
gid = 0; gid = 0;
} }
uint32_t exec_dt_proj_id = 0;
bool quota_already_enforced = false;
FOREACH_ARRAY(i, context->directories[type].items, context->directories[type].n_items) { FOREACH_ARRAY(i, context->directories[type].items, context->directories[type].n_items) {
_cleanup_free_ char *p = NULL, *pp = NULL; _cleanup_free_ char *p = NULL, *pp = NULL;
@ -3123,11 +2898,6 @@ static int setup_exec_directory(
if (r < 0) if (r < 0)
goto fail; goto fail;
} }
/* Apply storage quotas and accounting */
r = apply_exec_quotas(target_dir, params->cgroup_path, type, &context->directories[type].exec_quota, &exec_dt_proj_id, &quota_already_enforced);
if (r < 0)
goto fail;
} }
/* If we are not going to run in a namespace, set up the symlinks - otherwise /* If we are not going to run in a namespace, set up the symlinks - otherwise

View File

@ -1848,28 +1848,6 @@ static int exec_context_serialize(const ExecContext *c, FILE *f) {
r = serialize_item(f, key, value); r = serialize_item(f, key, value);
if (r < 0) if (r < 0)
return r; return r;
if (c->directories[dt].exec_quota.quota_enforce) {
_cleanup_free_ char *key_quota = NULL;
key_quota = strjoin("exec-context-quota-directories-", exec_directory_type_to_string(dt));
if (!key_quota)
return log_oom_debug();
r = serialize_item_format(f, key_quota, "%" PRIu64 " %" PRIu32, c->directories[dt].exec_quota.quota_absolute,
c->directories[dt].exec_quota.quota_scale);
if (r < 0)
return r;
} else if (c->directories[dt].exec_quota.quota_accounting) {
_cleanup_free_ char *key_quota = NULL;
key_quota = strjoin("exec-context-quota-accounting-directories-", exec_directory_type_to_string(dt));
if (!key_quota)
return log_oom_debug();
r = serialize_bool(f, key_quota, c->directories[dt].exec_quota.quota_accounting);
if (r < 0)
return r;
}
} }
r = serialize_usec(f, "exec-context-timeout-clean-usec", c->timeout_clean_usec); r = serialize_usec(f, "exec-context-timeout-clean-usec", c->timeout_clean_usec);
@ -2757,7 +2735,7 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
dt = exec_directory_type_from_string(type); dt = exec_directory_type_from_string(type);
if (dt < 0) if (dt < 0)
return dt; return -EINVAL;
r = parse_mode(mode, &c->directories[dt].mode); r = parse_mode(mode, &c->directories[dt].mode);
if (r < 0) if (r < 0)
@ -2815,48 +2793,6 @@ static int exec_context_deserialize(ExecContext *c, FILE *f) {
return r; return r;
} }
} }
} else if ((val = startswith(l, "exec-context-quota-accounting-directories-"))) {
_cleanup_free_ char *type = NULL, *quota_accounting = NULL;
ExecDirectoryType dt;
r = split_pair(val, "=", &type, &quota_accounting);
if (r < 0)
return r;
dt = exec_directory_type_from_string(type);
if (dt < 0)
return dt;
r = parse_boolean(quota_accounting);
if (r < 0)
return r;
c->directories[dt].exec_quota.quota_accounting = r;
} else if ((val = startswith(l, "exec-context-quota-directories-"))) {
_cleanup_free_ char *type = NULL, *quota_info = NULL, *quota_absolute = NULL, *quota_scale = NULL;
ExecDirectoryType dt;
r = split_pair(val, "=", &type, &quota_info);
if (r < 0)
return r;
r = split_pair(quota_info, " ", &quota_absolute, &quota_scale);
if (r < 0)
return r;
dt = exec_directory_type_from_string(type);
if (dt < 0)
return dt;
r = safe_atou64(quota_absolute, &c->directories[dt].exec_quota.quota_absolute);
if (r < 0)
return r;
r = safe_atou32(quota_scale, &c->directories[dt].exec_quota.quota_scale);
if (r < 0)
return r;
c->directories[dt].exec_quota.quota_enforce = true;
} else if ((val = startswith(l, "exec-context-timeout-clean-usec="))) { } else if ((val = startswith(l, "exec-context-timeout-clean-usec="))) {
r = deserialize_usec(val, &c->timeout_clean_usec); r = deserialize_usec(val, &c->timeout_clean_usec);
if (r < 0) if (r < 0)

View File

@ -3000,6 +3000,17 @@ static const char* const exec_preserve_mode_table[_EXEC_PRESERVE_MODE_MAX] = {
DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES); DEFINE_STRING_TABLE_LOOKUP_WITH_BOOLEAN(exec_preserve_mode, ExecPreserveMode, EXEC_PRESERVE_YES);
/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
[EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
[EXEC_DIRECTORY_STATE] = "StateDirectory",
[EXEC_DIRECTORY_CACHE] = "CacheDirectory",
[EXEC_DIRECTORY_LOGS] = "LogsDirectory",
[EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
};
DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);
/* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */ /* This table maps ExecDirectoryType to the symlink setting it is configured with in the unit */
static const char* const exec_directory_type_symlink_table[_EXEC_DIRECTORY_TYPE_MAX] = { static const char* const exec_directory_type_symlink_table[_EXEC_DIRECTORY_TYPE_MAX] = {
[EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectorySymlink", [EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectorySymlink",

View File

@ -7,7 +7,6 @@
#include "cgroup-util.h" #include "cgroup-util.h"
#include "core-forward.h" #include "core-forward.h"
#include "cpu-set-util.h" #include "cpu-set-util.h"
#include "exec-directory-util.h"
#include "exec-util.h" #include "exec-util.h"
#include "list.h" #include "list.h"
#include "log-context.h" #include "log-context.h"
@ -127,19 +126,22 @@ typedef struct ExecRuntime {
int ephemeral_storage_socket[2]; int ephemeral_storage_socket[2];
} ExecRuntime; } ExecRuntime;
typedef enum ExecDirectoryType {
EXEC_DIRECTORY_RUNTIME,
EXEC_DIRECTORY_STATE,
EXEC_DIRECTORY_CACHE,
EXEC_DIRECTORY_LOGS,
EXEC_DIRECTORY_CONFIGURATION,
_EXEC_DIRECTORY_TYPE_MAX,
_EXEC_DIRECTORY_TYPE_INVALID = -EINVAL,
} ExecDirectoryType;
static inline bool EXEC_DIRECTORY_TYPE_SHALL_CHOWN(ExecDirectoryType t) { static inline bool EXEC_DIRECTORY_TYPE_SHALL_CHOWN(ExecDirectoryType t) {
/* Returns true for the ExecDirectoryTypes that we shall chown()ing for the user to. We do this for /* Returns true for the ExecDirectoryTypes that we shall chown()ing for the user to. We do this for
* all of them, except for configuration */ * all of them, except for configuration */
return t >= 0 && t < _EXEC_DIRECTORY_TYPE_MAX && t != EXEC_DIRECTORY_CONFIGURATION; return t >= 0 && t < _EXEC_DIRECTORY_TYPE_MAX && t != EXEC_DIRECTORY_CONFIGURATION;
} }
typedef struct QuotaLimit {
uint64_t quota_absolute; /* absolute quota in bytes; if UINT64_MAX relative quota configured, see below */
uint32_t quota_scale; /* relative quota to backend size, scaled to 0…UINT32_MAX */
bool quota_enforce;
bool quota_accounting;
} QuotaLimit;
typedef struct ExecDirectoryItem { typedef struct ExecDirectoryItem {
char *path; char *path;
char **symlinks; char **symlinks;
@ -151,7 +153,6 @@ typedef struct ExecDirectory {
mode_t mode; mode_t mode;
size_t n_items; size_t n_items;
ExecDirectoryItem *items; ExecDirectoryItem *items;
QuotaLimit exec_quota;
} ExecDirectory; } ExecDirectory;
typedef enum ExecCleanMask { typedef enum ExecCleanMask {
@ -580,6 +581,9 @@ ExecPreserveMode exec_preserve_mode_from_string(const char *s) _pure_;
const char* exec_keyring_mode_to_string(ExecKeyringMode i) _const_; const char* exec_keyring_mode_to_string(ExecKeyringMode i) _const_;
ExecKeyringMode exec_keyring_mode_from_string(const char *s) _pure_; ExecKeyringMode exec_keyring_mode_from_string(const char *s) _pure_;
const char* exec_directory_type_to_string(ExecDirectoryType i) _const_;
ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_;
const char* exec_directory_type_symlink_to_string(ExecDirectoryType i) _const_; const char* exec_directory_type_symlink_to_string(ExecDirectoryType i) _const_;
ExecDirectoryType exec_directory_type_symlink_from_string(const char *s) _pure_; ExecDirectoryType exec_directory_type_symlink_from_string(const char *s) _pure_;

View File

@ -54,8 +54,6 @@ static const char* const kill_whom_table[_KILL_WHOM_MAX] = {
[KILL_MAIN_FAIL] = "main-fail", [KILL_MAIN_FAIL] = "main-fail",
[KILL_CONTROL_FAIL] = "control-fail", [KILL_CONTROL_FAIL] = "control-fail",
[KILL_ALL_FAIL] = "all-fail", [KILL_ALL_FAIL] = "all-fail",
[KILL_CGROUP] = "cgroup",
[KILL_CGROUP_FAIL] = "cgroup-fail",
}; };
DEFINE_STRING_TABLE_LOOKUP(kill_whom, KillWhom); DEFINE_STRING_TABLE_LOOKUP(kill_whom, KillWhom);

View File

@ -31,8 +31,6 @@ typedef enum KillWhom {
KILL_MAIN_FAIL, KILL_MAIN_FAIL,
KILL_CONTROL_FAIL, KILL_CONTROL_FAIL,
KILL_ALL_FAIL, KILL_ALL_FAIL,
KILL_CGROUP,
KILL_CGROUP_FAIL,
_KILL_WHOM_MAX, _KILL_WHOM_MAX,
_KILL_WHOM_INVALID = -EINVAL, _KILL_WHOM_INVALID = -EINVAL,
} KillWhom; } KillWhom;

View File

@ -145,16 +145,10 @@
{{type}}.RuntimeDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode) {{type}}.RuntimeDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME].mode)
{{type}}.RuntimeDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME]) {{type}}.RuntimeDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_RUNTIME])
{{type}}.StateDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE].mode) {{type}}.StateDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE].mode)
{{type}}.StateDirectoryAccounting, config_parse_bool, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE].exec_quota.quota_accounting)
{{type}}.StateDirectoryQuota, config_parse_exec_quota, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE].exec_quota)
{{type}}.StateDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE]) {{type}}.StateDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_STATE])
{{type}}.CacheDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE].mode) {{type}}.CacheDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE].mode)
{{type}}.CacheDirectoryAccounting, config_parse_bool, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE].exec_quota.quota_accounting)
{{type}}.CacheDirectoryQuota, config_parse_exec_quota, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE].exec_quota)
{{type}}.CacheDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE]) {{type}}.CacheDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CACHE])
{{type}}.LogsDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS].mode) {{type}}.LogsDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS].mode)
{{type}}.LogsDirectoryAccounting, config_parse_bool, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS].exec_quota.quota_accounting)
{{type}}.LogsDirectoryQuota, config_parse_exec_quota, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS].exec_quota)
{{type}}.LogsDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS]) {{type}}.LogsDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_LOGS])
{{type}}.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode) {{type}}.ConfigurationDirectoryMode, config_parse_mode, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION].mode)
{{type}}.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION]) {{type}}.ConfigurationDirectory, config_parse_exec_directories, 0, offsetof({{type}}, exec_context.directories[EXEC_DIRECTORY_CONFIGURATION])

View File

@ -4602,48 +4602,6 @@ int config_parse_exec_directories(
} }
} }
int config_parse_exec_quota(
const char *unit,
const char *filename,
unsigned line,
const char *section,
unsigned section_line,
const char *lvalue,
int ltype,
const char *rvalue,
void *data,
void *userdata) {
QuotaLimit *quota_limit = ASSERT_PTR(data);
uint64_t quota_absolute = UINT64_MAX;
uint32_t quota_scale = UINT32_MAX;
int r;
if (isempty(rvalue) || streq(rvalue, "off")) {
quota_limit->quota_enforce = false;
quota_limit->quota_absolute = UINT64_MAX;
quota_limit->quota_scale = UINT32_MAX;
return 0;
}
r = parse_permyriad(rvalue);
if (r < 0) {
r = parse_size(rvalue, 1024, &quota_absolute);
if (r < 0) {
log_syntax(unit, LOG_WARNING, filename, line, r, "Failed to parse disk quota value, ignoring: %s", rvalue);
return 0;
}
} else
/* Normalize to 2^32-1 == 100% */
quota_scale = UINT32_SCALE_FROM_PERMYRIAD(r);
quota_limit->quota_absolute = quota_absolute;
quota_limit->quota_scale = quota_scale;
quota_limit->quota_enforce = true;
return 0;
}
int config_parse_set_credential( int config_parse_set_credential(
const char *unit, const char *unit,
const char *filename, const char *filename,

View File

@ -101,7 +101,6 @@ CONFIG_PARSER_PROTOTYPE(config_parse_exec_smack_process_label);
CONFIG_PARSER_PROTOTYPE(config_parse_address_families); CONFIG_PARSER_PROTOTYPE(config_parse_address_families);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_preserve_mode); CONFIG_PARSER_PROTOTYPE(config_parse_exec_preserve_mode);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories); CONFIG_PARSER_PROTOTYPE(config_parse_exec_directories);
CONFIG_PARSER_PROTOTYPE(config_parse_exec_quota);
CONFIG_PARSER_PROTOTYPE(config_parse_set_credential); CONFIG_PARSER_PROTOTYPE(config_parse_set_credential);
CONFIG_PARSER_PROTOTYPE(config_parse_load_credential); CONFIG_PARSER_PROTOTYPE(config_parse_load_credential);
CONFIG_PARSER_PROTOTYPE(config_parse_import_credential); CONFIG_PARSER_PROTOTYPE(config_parse_import_credential);

View File

@ -246,10 +246,6 @@
send_interface="org.freedesktop.systemd1.Manager" send_interface="org.freedesktop.systemd1.Manager"
send_member="KillUnit"/> send_member="KillUnit"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager"
send_member="KillUnitSubgroup"/>
<allow send_destination="org.freedesktop.systemd1" <allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Manager" send_interface="org.freedesktop.systemd1.Manager"
send_member="QueueSignalUnit"/> send_member="QueueSignalUnit"/>
@ -414,10 +410,6 @@
send_interface="org.freedesktop.systemd1.Unit" send_interface="org.freedesktop.systemd1.Unit"
send_member="Kill"/> send_member="Kill"/>
<allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Unit"
send_member="KillSubgroup"/>
<allow send_destination="org.freedesktop.systemd1" <allow send_destination="org.freedesktop.systemd1"
send_interface="org.freedesktop.systemd1.Unit" send_interface="org.freedesktop.systemd1.Unit"
send_member="QueueSignal"/> send_member="QueueSignal"/>

View File

@ -376,7 +376,7 @@ int unit_deserialize_state(Unit *u, FILE *f, FDSet *fds) {
unit_release_cgroup(u, /* drop_cgroup_runtime = */ false); unit_release_cgroup(u, /* drop_cgroup_runtime = */ false);
else { else {
unit_invalidate_cgroup(u, _CGROUP_MASK_ALL); unit_invalidate_cgroup(u, _CGROUP_MASK_ALL);
unit_invalidate_cgroup_bpf_firewall(u); unit_invalidate_cgroup_bpf(u);
} }
} }

View File

@ -19,7 +19,6 @@
#include "cgroup-setup.h" #include "cgroup-setup.h"
#include "cgroup-util.h" #include "cgroup-util.h"
#include "chase.h" #include "chase.h"
#include "chattr-util.h"
#include "condition.h" #include "condition.h"
#include "dbus-unit.h" #include "dbus-unit.h"
#include "dropin.h" #include "dropin.h"
@ -46,7 +45,6 @@
#include "mountpoint-util.h" #include "mountpoint-util.h"
#include "path-util.h" #include "path-util.h"
#include "process-util.h" #include "process-util.h"
#include "quota-util.h"
#include "rm-rf.h" #include "rm-rf.h"
#include "serialize.h" #include "serialize.h"
#include "set.h" #include "set.h"
@ -4041,7 +4039,6 @@ static int unit_kill_one(
int unit_kill( int unit_kill(
Unit *u, Unit *u,
KillWhom whom, KillWhom whom,
const char *subgroup,
int signo, int signo,
int code, int code,
int value, int value,
@ -4061,19 +4058,11 @@ int unit_kill(
assert(SIGNAL_VALID(signo)); assert(SIGNAL_VALID(signo));
assert(IN_SET(code, SI_USER, SI_QUEUE)); assert(IN_SET(code, SI_USER, SI_QUEUE));
if (subgroup) {
if (!IN_SET(whom, KILL_CGROUP, KILL_CGROUP_FAIL))
return sd_bus_error_set(ret_error, SD_BUS_ERROR_NOT_SUPPORTED, "Killing by subgroup is only supported for 'cgroup' or 'cgroup-kill' modes.");
if (!unit_cgroup_delegate(u))
return sd_bus_error_set(ret_error, SD_BUS_ERROR_NOT_SUPPORTED, "Killing by subgroup is only available for units with control group delegation enabled.");
}
main_pid = unit_main_pid(u); main_pid = unit_main_pid(u);
control_pid = unit_control_pid(u); control_pid = unit_control_pid(u);
if (!UNIT_HAS_CGROUP_CONTEXT(u) && !main_pid && !control_pid) if (!UNIT_HAS_CGROUP_CONTEXT(u) && !main_pid && !control_pid)
return sd_bus_error_set(ret_error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit type does not support process killing."); return sd_bus_error_setf(ret_error, SD_BUS_ERROR_NOT_SUPPORTED, "Unit type does not support process killing.");
if (IN_SET(whom, KILL_MAIN, KILL_MAIN_FAIL)) { if (IN_SET(whom, KILL_MAIN, KILL_MAIN_FAIL)) {
if (!main_pid) if (!main_pid)
@ -4104,66 +4093,54 @@ int unit_kill(
/* Note: if we shall enqueue rather than kill we won't do this via the cgroup mechanism, since it /* Note: if we shall enqueue rather than kill we won't do this via the cgroup mechanism, since it
* doesn't really make much sense (and given that enqueued values are a relatively expensive * doesn't really make much sense (and given that enqueued values are a relatively expensive
* resource, and we shouldn't allow us to be subjects for such allocation sprees) */ * resource, and we shouldn't allow us to be subjects for such allocation sprees) */
if (IN_SET(whom, KILL_ALL, KILL_ALL_FAIL, KILL_CGROUP, KILL_CGROUP_FAIL) && code == SI_USER) { if (IN_SET(whom, KILL_ALL, KILL_ALL_FAIL) && code == SI_USER) {
CGroupRuntime *crt = unit_get_cgroup_runtime(u); CGroupRuntime *crt = unit_get_cgroup_runtime(u);
if (crt && crt->cgroup_path) { if (crt && crt->cgroup_path) {
_cleanup_set_free_ Set *pid_set = NULL; _cleanup_set_free_ Set *pid_set = NULL;
_cleanup_free_ char *joined = NULL;
const char *p;
if (empty_or_root(subgroup))
p = crt->cgroup_path;
else {
joined = path_join(crt->cgroup_path, subgroup);
if (!joined)
return -ENOMEM;
p = joined;
}
if (signo == SIGKILL) { if (signo == SIGKILL) {
r = cg_kill_kernel_sigkill(p); r = cg_kill_kernel_sigkill(crt->cgroup_path);
if (r >= 0) { if (r >= 0) {
killed = true; killed = true;
log_unit_info(u, "Killed unit cgroup '%s' with SIGKILL on client request.", p); log_unit_info(u, "Killed unit cgroup with SIGKILL on client request.");
goto finish; goto finish;
} }
if (r != -EOPNOTSUPP) { if (r != -EOPNOTSUPP) {
if (ret >= 0) if (ret >= 0)
sd_bus_error_set_errnof(ret_error, r, sd_bus_error_set_errnof(ret_error, r,
"Failed to kill unit cgroup: %m"); "Failed to kill unit cgroup: %m");
RET_GATHER(ret, log_unit_warning_errno(u, r, "Failed to kill unit cgroup '%s': %m", p)); RET_GATHER(ret, log_unit_warning_errno(u, r, "Failed to kill unit cgroup: %m"));
goto finish; goto finish;
} }
/* Fall back to manual enumeration */ /* Fall back to manual enumeration */
} else if (IN_SET(whom, KILL_ALL, KILL_ALL_FAIL)) { } else {
/* Exclude the main/control pids from being killed via the cgroup if not /* Exclude the main/control pids from being killed via the cgroup if
* SIGKILL */ * not SIGKILL */
r = unit_pid_set(u, &pid_set); r = unit_pid_set(u, &pid_set);
if (r < 0) if (r < 0)
return log_oom(); return log_oom();
} }
r = cg_kill_recursive(p, signo, /* flags= */ 0, pid_set, kill_common_log, u); r = cg_kill_recursive(crt->cgroup_path, signo, 0, pid_set, kill_common_log, u);
if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT)) { if (r < 0 && !IN_SET(r, -ESRCH, -ENOENT)) {
if (ret >= 0) if (ret >= 0)
sd_bus_error_set_errnof( sd_bus_error_set_errnof(
ret_error, r, ret_error, r,
"Failed to send signal SIG%s to processes in unit cgroup '%s': %m", "Failed to send signal SIG%s to auxiliary processes: %m",
signal_to_string(signo), p); signal_to_string(signo));
RET_GATHER(ret, log_unit_warning_errno( RET_GATHER(ret, log_unit_warning_errno(
u, r, u, r,
"Failed to send signal SIG%s to processes in unit cgroup '%s' on client request: %m", "Failed to send signal SIG%s to auxiliary processes on client request: %m",
signal_to_string(signo), p)); signal_to_string(signo)));
} }
killed = killed || r > 0; killed = killed || r >= 0;
} }
} }
finish: finish:
/* If the "fail" versions of the operation are requested, then complain if the set of processes we killed is empty */ /* If the "fail" versions of the operation are requested, then complain if the set of processes we killed is empty */
if (ret >= 0 && !killed && IN_SET(whom, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_MAIN_FAIL, KILL_CGROUP_FAIL)) if (ret >= 0 && !killed && IN_SET(whom, KILL_ALL_FAIL, KILL_CONTROL_FAIL, KILL_MAIN_FAIL))
return sd_bus_error_set_const(ret_error, BUS_ERROR_NO_SUCH_PROCESS, "No matching processes to kill"); return sd_bus_error_set_const(ret_error, BUS_ERROR_NO_SUCH_PROCESS, "No matching processes to kill");
return ret; return ret;
@ -4448,7 +4425,7 @@ int unit_patch_contexts(Unit *u) {
cc->device_policy = CGROUP_DEVICE_POLICY_CLOSED; cc->device_policy = CGROUP_DEVICE_POLICY_CLOSED;
/* Only add these if needed, as they imply that everything else is blocked. */ /* Only add these if needed, as they imply that everything else is blocked. */
if (cgroup_context_has_device_policy(cc)) { if (cc->device_policy != CGROUP_DEVICE_POLICY_AUTO || cc->device_allow) {
if (ec->root_image || ec->mount_images) { if (ec->root_image || ec->mount_images) {
/* When RootImage= or MountImages= is specified, the following devices are touched. */ /* When RootImage= or MountImages= is specified, the following devices are touched. */
@ -6099,7 +6076,7 @@ int unit_pid_attachable(Unit *u, PidRef *pid, sd_bus_error *error) {
/* First, a simple range check */ /* First, a simple range check */
if (!pidref_is_set(pid)) if (!pidref_is_set(pid))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Process identifier is not valid."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Process identifier is not valid.");
/* Some extra safety check */ /* Some extra safety check */
if (pid->pid == 1 || pidref_is_self(pid)) if (pid->pid == 1 || pidref_is_self(pid))
@ -6745,52 +6722,6 @@ static uint64_t unit_get_cpu_weight(Unit *u) {
return cc ? cgroup_context_cpu_weight(cc, manager_state(u->manager)) : CGROUP_WEIGHT_DEFAULT; return cc ? cgroup_context_cpu_weight(cc, manager_state(u->manager)) : CGROUP_WEIGHT_DEFAULT;
} }
int unit_get_exec_quota_stats(Unit *u, ExecContext *c, ExecDirectoryType dt, uint64_t *ret_usage, uint64_t *ret_limit) {
int r;
_cleanup_close_ int fd = -EBADF;
_cleanup_free_ char *p = NULL, *pp = NULL;
assert(u);
assert(c);
if (c->directories[dt].n_items == 0) {
*ret_usage = UINT64_MAX;
*ret_limit = UINT64_MAX;
return 0;
}
ExecDirectoryItem *i = &c->directories[dt].items[0];
p = path_join(u->manager->prefix[dt], i->path);
if (!p)
return log_oom_debug();
if (exec_directory_is_private(c, dt)) {
pp = path_join(u->manager->prefix[dt], "private", i->path);
if (!pp)
return log_oom_debug();
}
const char *target_dir = pp ?: p;
fd = open(target_dir, O_PATH | O_CLOEXEC | O_DIRECTORY);
if (fd < 0)
return log_unit_debug_errno(u, errno, "Failed to get exec quota stats: %m");
uint32_t proj_id;
r = read_fs_xattr_fd(fd, /* ret_xflags = */ NULL, &proj_id);
if (r < 0)
return log_unit_debug_errno(u, r, "Failed to get project ID for exec quota stats: %m");
struct dqblk req;
r = quota_query_proj_id(fd, proj_id, &req);
if (r <= 0)
return log_unit_debug_errno(u, r, "Failed to query project ID for exec quota stats: %m");
*ret_usage = req.dqb_curspace;
*ret_limit = req.dqb_bhardlimit * QIF_DQBLKSIZE;
return r;
}
int unit_compare_priority(Unit *a, Unit *b) { int unit_compare_priority(Unit *a, Unit *b) {
int ret; int ret;

View File

@ -886,7 +886,7 @@ int unit_start(Unit *u, ActivationDetails *details);
int unit_stop(Unit *u); int unit_stop(Unit *u);
int unit_reload(Unit *u); int unit_reload(Unit *u);
int unit_kill(Unit *u, KillWhom w, const char *subgroup, int signo, int code, int value, sd_bus_error *ret_error); int unit_kill(Unit *u, KillWhom w, int signo, int code, int value, sd_bus_error *ret_error);
void unit_notify_cgroup_oom(Unit *u, bool managed_oom); void unit_notify_cgroup_oom(Unit *u, bool managed_oom);
@ -938,8 +938,6 @@ int unit_add_default_target_dependency(Unit *u, Unit *target);
void unit_start_on_termination_deps(Unit *u, UnitDependencyAtom atom); void unit_start_on_termination_deps(Unit *u, UnitDependencyAtom atom);
void unit_trigger_notify(Unit *u); void unit_trigger_notify(Unit *u);
int unit_get_exec_quota_stats(Unit *u, ExecContext *c, ExecDirectoryType dt, uint64_t *ret_usage, uint64_t *ret_limit);
UnitFileState unit_get_unit_file_state(Unit *u); UnitFileState unit_get_unit_file_state(Unit *u);
PresetAction unit_get_unit_file_preset(Unit *u); PresetAction unit_get_unit_file_preset(Unit *u);

View File

@ -442,7 +442,7 @@ int bus_home_update_record(
return r; return r;
if ((flags & ~SD_HOMED_UPDATE_FLAGS_ALL) != 0) if ((flags & ~SD_HOMED_UPDATE_FLAGS_ALL) != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags provided."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags provided.");
if (blobs) { if (blobs) {
const char *failed = NULL; const char *failed = NULL;

View File

@ -549,7 +549,7 @@ static int method_adopt_home(
if (!path_is_absolute(image_path) || !path_is_safe(image_path)) if (!path_is_absolute(image_path) || !path_is_safe(image_path))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path is not absolute or not valid: %s", image_path); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Specified path is not absolute or not valid: %s", image_path);
if (flags != 0) if (flags != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags field must be zero."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Flags field must be zero.");
r = bus_verify_polkit_async( r = bus_verify_polkit_async(
message, message,
@ -598,7 +598,7 @@ static int method_create_home(sd_bus_message *message, void *userdata, sd_bus_er
if (r < 0) if (r < 0)
return r; return r;
if ((flags & ~SD_HOMED_CREATE_FLAGS_ALL) != 0) if ((flags & ~SD_HOMED_CREATE_FLAGS_ALL) != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags provided."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid flags provided.");
} }
r = bus_verify_polkit_async( r = bus_verify_polkit_async(
@ -963,11 +963,11 @@ static int method_add_signing_key(sd_bus_message *message, void *userdata, sd_bu
return r; return r;
if (flags != 0) if (flags != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags parameter must be zero."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Flags parameter must be zero.");
if (!valid_public_key_name(fn)) if (!valid_public_key_name(fn))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name not valid: %s", fn); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name not valid: %s", fn);
if (streq(fn, "local.public")) if (streq(fn, "local.public"))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Refusing to write local public key."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Refusing to write local public key.");
_cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL; _cleanup_(EVP_PKEY_freep) EVP_PKEY *pkey = NULL;
r = openssl_pubkey_from_pem(pem, /* pem_size= */ SIZE_MAX, &pkey); r = openssl_pubkey_from_pem(pem, /* pem_size= */ SIZE_MAX, &pkey);
@ -1040,13 +1040,13 @@ static int method_remove_signing_key(sd_bus_message *message, void *userdata, sd
return r; return r;
if (flags != 0) if (flags != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Flags parameter must be zero."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Flags parameter must be zero.");
if (!valid_public_key_name(fn)) if (!valid_public_key_name(fn))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name not valid: %s", fn); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name not valid: %s", fn);
if (streq(fn, "local.public")) if (streq(fn, "local.public"))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, "Refusing to remove local key."); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Refusing to remove local key.");
if (!hashmap_contains(m->public_keys, fn)) if (!hashmap_contains(m->public_keys, fn))
return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name does not exist: %s", fn); return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Public key name does not exist: %s", fn);

View File

@ -128,7 +128,7 @@ static int get_sender_session(
session = hashmap_get(m->sessions, name); session = hashmap_get(m->sessions, name);
if (!session) if (!session)
return sd_bus_error_set(error, BUS_ERROR_NO_SESSION_FOR_PID, return sd_bus_error_setf(error, BUS_ERROR_NO_SESSION_FOR_PID,
consult_display ? consult_display ?
"Caller does not belong to any known session and doesn't own any suitable session." : "Caller does not belong to any known session and doesn't own any suitable session." :
"Caller does not belong to any known session."); "Caller does not belong to any known session.");
@ -183,7 +183,7 @@ static int get_sender_user(Manager *m, sd_bus_message *message, sd_bus_error *er
user = hashmap_get(m->users, UID_TO_PTR(uid)); user = hashmap_get(m->users, UID_TO_PTR(uid));
if (!user) if (!user)
return sd_bus_error_set(error, BUS_ERROR_NO_USER_FOR_PID, return sd_bus_error_setf(error, BUS_ERROR_NO_USER_FOR_PID,
"Caller does not belong to any logged in or lingering user"); "Caller does not belong to any logged in or lingering user");
*ret = user; *ret = user;
@ -1183,7 +1183,7 @@ static int manager_create_session_by_bus(
if (vtnr == 0) if (vtnr == 0)
vtnr = (uint32_t) v; vtnr = (uint32_t) v;
else if (vtnr != (uint32_t) v) else if (vtnr != (uint32_t) v)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Specified TTY and VT number do not match"); "Specified TTY and VT number do not match");
} else if (tty_is_console(tty)) { } else if (tty_is_console(tty)) {
@ -1191,22 +1191,22 @@ static int manager_create_session_by_bus(
if (!seat) if (!seat)
seat = m->seat0; seat = m->seat0;
else if (seat != m->seat0) else if (seat != m->seat0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Console TTY specified but seat is not seat0"); "Console TTY specified but seat is not seat0");
if (vtnr != 0) if (vtnr != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Console TTY specified but VT number is not 0"); "Console TTY specified but VT number is not 0");
} }
if (seat) { if (seat) {
if (seat_has_vts(seat)) { if (seat_has_vts(seat)) {
if (!vtnr_is_valid(vtnr)) if (!vtnr_is_valid(vtnr))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"VT number out of range"); "VT number out of range");
} else { } else {
if (vtnr != 0) if (vtnr != 0)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Seat has no VTs but VT number not 0"); "Seat has no VTs but VT number not 0");
} }
} }
@ -1229,7 +1229,7 @@ static int manager_create_session_by_bus(
remote_host, remote_host,
&session); &session);
if (r == -EBUSY) if (r == -EBUSY)
return sd_bus_error_set(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice"); return sd_bus_error_setf(error, BUS_ERROR_SESSION_BUSY, "Already running in a session or user slice");
if (r == -EADDRNOTAVAIL) if (r == -EADDRNOTAVAIL)
return sd_bus_error_set(error, BUS_ERROR_SESSION_BUSY, "Virtual terminal already occupied by a session"); return sd_bus_error_set(error, BUS_ERROR_SESSION_BUSY, "Virtual terminal already occupied by a session");
if (r == -EUSERS) if (r == -EUSERS)
@ -2240,7 +2240,7 @@ static int verify_shutdown_creds(
if (!FLAGS_SET(flags, SD_LOGIND_SKIP_INHIBITORS) && if (!FLAGS_SET(flags, SD_LOGIND_SKIP_INHIBITORS) &&
(offending->mode != INHIBIT_BLOCK_WEAK || (offending->mode != INHIBIT_BLOCK_WEAK ||
(uid == 0 && FLAGS_SET(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS)))) (uid == 0 && FLAGS_SET(flags, SD_LOGIND_ROOT_CHECK_INHIBITORS))))
return sd_bus_error_set(error, BUS_ERROR_BLOCKED_BY_INHIBITOR_LOCK, return sd_bus_error_setf(error, BUS_ERROR_BLOCKED_BY_INHIBITOR_LOCK,
"Operation denied due to active block inhibitor"); "Operation denied due to active block inhibitor");
/* We want to always ask here, even for root, to only allow bypassing if explicitly allowed /* We want to always ask here, even for root, to only allow bypassing if explicitly allowed
@ -3136,7 +3136,7 @@ static int method_set_reboot_parameter(
if (r < 0) if (r < 0)
return r; return r;
if (r > 0) if (r > 0)
return sd_bus_error_set(error, SD_BUS_ERROR_NOT_SUPPORTED, return sd_bus_error_setf(error, SD_BUS_ERROR_NOT_SUPPORTED,
"Reboot parameter not supported in containers, refusing."); "Reboot parameter not supported in containers, refusing.");
r = bus_verify_polkit_async( r = bus_verify_polkit_async(
@ -3801,7 +3801,7 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
/* Delay is only supported for shutdown/sleep */ /* Delay is only supported for shutdown/sleep */
if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP))) if (mm == INHIBIT_DELAY && (w & ~(INHIBIT_SHUTDOWN|INHIBIT_SLEEP)))
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Delay inhibitors only supported for shutdown and sleep"); "Delay inhibitors only supported for shutdown and sleep");
/* Don't allow taking delay locks while we are already /* Don't allow taking delay locks while we are already
@ -3809,7 +3809,7 @@ static int method_inhibit(sd_bus_message *message, void *userdata, sd_bus_error
* that the lock was successful if the machine is about to go * that the lock was successful if the machine is about to go
* down/suspend any moment. */ * down/suspend any moment. */
if (m->delayed_action && m->delayed_action->inhibit_what & w) if (m->delayed_action && m->delayed_action->inhibit_what & w)
return sd_bus_error_set(error, BUS_ERROR_OPERATION_IN_PROGRESS, return sd_bus_error_setf(error, BUS_ERROR_OPERATION_IN_PROGRESS,
"The operation inhibition has been requested for is already running"); "The operation inhibition has been requested for is already running");
BIT_FOREACH(i, w) { BIT_FOREACH(i, w) {

View File

@ -470,17 +470,17 @@ static int method_set_class(sd_bus_message *message, void *userdata, sd_bus_erro
/* For now, we'll allow only upgrades user-incomplete → user */ /* For now, we'll allow only upgrades user-incomplete → user */
if (class != SESSION_USER) if (class != SESSION_USER)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Class may only be set to 'user'"); "Class may only be set to 'user'");
if (s->class == SESSION_USER) /* No change, shortcut */ if (s->class == SESSION_USER) /* No change, shortcut */
return sd_bus_reply_method_return(message, NULL); return sd_bus_reply_method_return(message, NULL);
if (s->class != SESSION_USER_INCOMPLETE) if (s->class != SESSION_USER_INCOMPLETE)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Only sessions with class 'user-incomplete' may change class"); "Only sessions with class 'user-incomplete' may change class");
if (s->upgrade_message) if (s->upgrade_message)
return sd_bus_error_set(error, SD_BUS_ERROR_INVALID_ARGS, return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS,
"Set session class operation already in progress"); "Set session class operation already in progress");
r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds); r = sd_bus_query_sender_creds(message, SD_BUS_CREDS_EUID, &creds);

View File

@ -6,7 +6,6 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "chase.h" #include "chase.h"
#include "errno-util.h"
#include "escape.h" #include "escape.h"
#include "extract-word.h" #include "extract-word.h"
#include "fd-util.h" #include "fd-util.h"
@ -815,28 +814,7 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u
if (m->rm_rf_tmpdir && chown(m->source, uid_shift, uid_shift) < 0) if (m->rm_rf_tmpdir && chown(m->source, uid_shift, uid_shift) < 0)
return log_error_errno(errno, "Failed to chown %s: %m", m->source); return log_error_errno(errno, "Failed to chown %s: %m", m->source);
/* UID/GIDs of idmapped mounts are always resolved in the caller's user namespace. In other if (stat(m->source, &source_st) < 0)
* words, they're not nested. If we're doing an idmapped mount from a bind mount that's
* already idmapped itself, the old idmap is replaced with the new one. This means that the
* source uid which we put in the idmap userns has to be the uid of mount source in the
* caller's userns *without* any mount idmapping in place. To get that uid, we clone the
* mount source tree and clear any existing idmapping and temporarily mount that tree over
* the mount source before we stat the mount source to figure out the source uid. */
_cleanup_close_ int fd_clone = open_tree_attr_fallback(
AT_FDCWD,
m->source,
OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC,
&(struct mount_attr) {
.attr_clr = MOUNT_ATTR_IDMAP,
});
if (ERRNO_IS_NEG_NOT_SUPPORTED(fd_clone))
/* We can only clear idmapped mounts with open_tree_attr(), but there might not be one in
* the first place, so we keep going if we get a not supported error. */
fd_clone = open_tree(AT_FDCWD, m->source, OPEN_TREE_CLONE|OPEN_TREE_CLOEXEC);
if (fd_clone < 0)
return log_error_errno(errno, "Failed to clone %s: %m", m->source);
if (fstat(fd_clone, &source_st) < 0)
return log_error_errno(errno, "Failed to stat %s: %m", m->source); return log_error_errno(errno, "Failed to stat %s: %m", m->source);
r = chase(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL); r = chase(m->destination, dest, CHASE_PREFIX_ROOT|CHASE_NONEXISTENT, &where, NULL);
@ -881,10 +859,9 @@ static int mount_bind(const char *dest, CustomMount *m, uid_t uid_shift, uid_t u
dest_uid = uid_shift; dest_uid = uid_shift;
} }
if (move_mount(fd_clone, "", AT_FDCWD, where, MOVE_MOUNT_F_EMPTY_PATH) < 0) r = mount_nofollow_verbose(LOG_ERR, m->source, where, NULL, mount_flags, mount_opts);
return log_error_errno(errno, "Failed to mount %s to %s: %m", m->source, where); if (r < 0)
return r;
fd_clone = safe_close(fd_clone);
if (m->read_only) { if (m->read_only) {
r = bind_remount_recursive(where, MS_RDONLY, MS_RDONLY, NULL); r = bind_remount_recursive(where, MS_RDONLY, MS_RDONLY, NULL);

View File

@ -32,37 +32,37 @@
#include "strv.h" #include "strv.h"
#include "uki.h" #include "uki.h"
static const char* const boot_entry_type_description_table[_BOOT_ENTRY_TYPE_MAX] = {
[BOOT_ENTRY_TYPE1] = "Boot Loader Specification Type #1 (.conf)",
[BOOT_ENTRY_TYPE2] = "Boot Loader Specification Type #2 (UKI, .efi)",
[BOOT_ENTRY_LOADER] = "Reported by Boot Loader",
[BOOT_ENTRY_AUTO] = "Automatic",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type_description, BootEntryType);
static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = { static const char* const boot_entry_type_table[_BOOT_ENTRY_TYPE_MAX] = {
[BOOT_ENTRY_TYPE1] = "type1", [BOOT_ENTRY_CONF] = "Boot Loader Specification Type #1 (.conf)",
[BOOT_ENTRY_TYPE2] = "type2", [BOOT_ENTRY_UNIFIED] = "Boot Loader Specification Type #2 (.efi)",
[BOOT_ENTRY_LOADER] = "loader", [BOOT_ENTRY_LOADER] = "Reported by Boot Loader",
[BOOT_ENTRY_AUTO] = "auto", [BOOT_ENTRY_LOADER_AUTO] = "Automatic",
}; };
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType); DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type, BootEntryType);
static const char* const boot_entry_source_description_table[_BOOT_ENTRY_SOURCE_MAX] = { static const char* const boot_entry_type_json_table[_BOOT_ENTRY_TYPE_MAX] = {
[BOOT_ENTRY_CONF] = "type1",
[BOOT_ENTRY_UNIFIED] = "type2",
[BOOT_ENTRY_LOADER] = "loader",
[BOOT_ENTRY_LOADER_AUTO] = "auto",
};
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_type_json, BootEntryType);
static const char* const boot_entry_source_table[_BOOT_ENTRY_SOURCE_MAX] = {
[BOOT_ENTRY_ESP] = "EFI System Partition", [BOOT_ENTRY_ESP] = "EFI System Partition",
[BOOT_ENTRY_XBOOTLDR] = "Extended Boot Loader Partition", [BOOT_ENTRY_XBOOTLDR] = "Extended Boot Loader Partition",
}; };
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source_description, BootEntrySource); DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source, BootEntrySource);
static const char* const boot_entry_source_table[_BOOT_ENTRY_SOURCE_MAX] = { static const char* const boot_entry_source_json_table[_BOOT_ENTRY_SOURCE_MAX] = {
[BOOT_ENTRY_ESP] = "esp", [BOOT_ENTRY_ESP] = "esp",
[BOOT_ENTRY_XBOOTLDR] = "xbootldr", [BOOT_ENTRY_XBOOTLDR] = "xbootldr",
}; };
DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source, BootEntrySource); DEFINE_STRING_TABLE_LOOKUP_TO_STRING(boot_entry_source_json, BootEntrySource);
static void boot_entry_addons_done(BootEntryAddons *addons) { static void boot_entry_addons_done(BootEntryAddons *addons) {
assert(addons); assert(addons);
@ -319,7 +319,7 @@ static int boot_entry_load_type1(
const char *fname, const char *fname,
BootEntry *ret) { BootEntry *ret) {
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_TYPE1, source); _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_CONF, source);
char *c; char *c;
int r; int r;
@ -759,7 +759,7 @@ static int boot_entry_load_unified(
if (r < 0) if (r < 0)
return log_error_errno(r, "Failed to extract file name from '%s': %m", path); return log_error_errno(r, "Failed to extract file name from '%s': %m", path);
_cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_TYPE2, source); _cleanup_(boot_entry_free) BootEntry tmp = BOOT_ENTRY_INIT(BOOT_ENTRY_UNIFIED, source);
r = boot_filename_extract_tries(fname, &tmp.id, &tmp.tries_left, &tmp.tries_done); r = boot_filename_extract_tries(fname, &tmp.id, &tmp.tries_left, &tmp.tries_done);
if (r < 0) if (r < 0)
@ -1620,7 +1620,7 @@ int boot_config_augment_from_loader(
return log_oom(); return log_oom();
config->entries[config->n_entries++] = (BootEntry) { config->entries[config->n_entries++] = (BootEntry) {
.type = startswith(*i, "auto-") ? BOOT_ENTRY_AUTO : BOOT_ENTRY_LOADER, .type = startswith(*i, "auto-") ? BOOT_ENTRY_LOADER_AUTO : BOOT_ENTRY_LOADER,
.id = TAKE_PTR(c), .id = TAKE_PTR(c),
.title = TAKE_PTR(t), .title = TAKE_PTR(t),
.path = TAKE_PTR(p), .path = TAKE_PTR(p),
@ -1823,7 +1823,7 @@ int show_boot_entry(
assert(e); assert(e);
printf(" type: %s\n", printf(" type: %s\n",
boot_entry_type_description_to_string(e->type)); boot_entry_type_to_string(e->type));
printf(" title: %s%s%s", printf(" title: %s%s%s",
ansi_highlight(), boot_entry_title(e), ansi_normal()); ansi_highlight(), boot_entry_title(e), ansi_normal());
@ -1840,7 +1840,7 @@ int show_boot_entry(
if (e->type == BOOT_ENTRY_LOADER) if (e->type == BOOT_ENTRY_LOADER)
printf(" %s(reported/absent)%s", printf(" %s(reported/absent)%s",
ansi_highlight_red(), ansi_normal()); ansi_highlight_red(), ansi_normal());
else if (!e->reported_by_loader && e->type != BOOT_ENTRY_AUTO) else if (!e->reported_by_loader && e->type != BOOT_ENTRY_LOADER_AUTO)
printf(" %s(not reported/new)%s", printf(" %s(not reported/new)%s",
ansi_highlight_green(), ansi_normal()); ansi_highlight_green(), ansi_normal());
} }
@ -1867,12 +1867,12 @@ int show_boot_entry(
/* Let's urlify the link to make it easy to view in an editor, but only if it is a text /* Let's urlify the link to make it easy to view in an editor, but only if it is a text
* file. Unified images are binary ELFs, and EFI variables are not pure text either. */ * file. Unified images are binary ELFs, and EFI variables are not pure text either. */
if (e->type == BOOT_ENTRY_TYPE1) if (e->type == BOOT_ENTRY_CONF)
(void) terminal_urlify_path(e->path, text, &link); (void) terminal_urlify_path(e->path, text, &link);
printf(" source: %s (on the %s)\n", printf(" source: %s (on the %s)\n",
link ?: text ?: e->path, link ?: text ?: e->path,
boot_entry_source_description_to_string(e->source)); boot_entry_source_to_string(e->source));
} }
if (e->tries_left != UINT_MAX) { if (e->tries_left != UINT_MAX) {
printf(" tries: %u left", e->tries_left); printf(" tries: %u left", e->tries_left);
@ -1942,8 +1942,8 @@ int boot_entry_to_json(const BootConfig *c, size_t i, sd_json_variant **ret) {
r = sd_json_variant_merge_objectbo( r = sd_json_variant_merge_objectbo(
&v, &v,
SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(boot_entry_type_to_string(e->type))), SD_JSON_BUILD_PAIR("type", SD_JSON_BUILD_STRING(boot_entry_type_json_to_string(e->type))),
SD_JSON_BUILD_PAIR("source", SD_JSON_BUILD_STRING(boot_entry_source_to_string(e->source))), SD_JSON_BUILD_PAIR("source", SD_JSON_BUILD_STRING(boot_entry_source_json_to_string(e->source))),
SD_JSON_BUILD_PAIR_CONDITION(!!e->id, "id", SD_JSON_BUILD_STRING(e->id)), SD_JSON_BUILD_PAIR_CONDITION(!!e->id, "id", SD_JSON_BUILD_STRING(e->id)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->path, "path", SD_JSON_BUILD_STRING(e->path)), SD_JSON_BUILD_PAIR_CONDITION(!!e->path, "path", SD_JSON_BUILD_STRING(e->path)),
SD_JSON_BUILD_PAIR_CONDITION(!!e->root, "root", SD_JSON_BUILD_STRING(e->root)), SD_JSON_BUILD_PAIR_CONDITION(!!e->root, "root", SD_JSON_BUILD_STRING(e->root)),

View File

@ -5,10 +5,10 @@
#include "forward.h" #include "forward.h"
typedef enum BootEntryType { typedef enum BootEntryType {
BOOT_ENTRY_TYPE1, /* Boot Loader Specification Type #1 entries: *.conf files */ BOOT_ENTRY_CONF, /* Boot Loader Specification Type #1 entries: *.conf files */
BOOT_ENTRY_TYPE2, /* Boot Loader Specification Type #2 entries: *.efi files (UKIs) */ BOOT_ENTRY_UNIFIED, /* Boot Loader Specification Type #2 entries: *.efi files */
BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */ BOOT_ENTRY_LOADER, /* Additional entries augmented from LoaderEntries EFI variable (regular entries) */
BOOT_ENTRY_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */ BOOT_ENTRY_LOADER_AUTO, /* Additional entries augmented from LoaderEntries EFI variable (special "automatic" entries) */
_BOOT_ENTRY_TYPE_MAX, _BOOT_ENTRY_TYPE_MAX,
_BOOT_ENTRY_TYPE_INVALID = -EINVAL, _BOOT_ENTRY_TYPE_INVALID = -EINVAL,
} BootEntryType; } BootEntryType;
@ -91,11 +91,11 @@ typedef struct BootConfig {
.selected_entry = -1, \ .selected_entry = -1, \
} }
const char* boot_entry_type_description_to_string(BootEntryType) _const_;
const char* boot_entry_type_to_string(BootEntryType) _const_; const char* boot_entry_type_to_string(BootEntryType) _const_;
const char* boot_entry_type_json_to_string(BootEntryType) _const_;
const char* boot_entry_source_description_to_string(BootEntrySource) _const_;
const char* boot_entry_source_to_string(BootEntrySource) _const_; const char* boot_entry_source_to_string(BootEntrySource) _const_;
const char* boot_entry_source_json_to_string(BootEntrySource) _const_;
BootEntry* boot_config_find_entry(BootConfig *config, const char *id); BootEntry* boot_config_find_entry(BootConfig *config, const char *id);

View File

@ -2059,31 +2059,6 @@ static int bus_append_directory(sd_bus_message *m, const char *field, const char
return 1; return 1;
} }
static int bus_append_quota_directory(sd_bus_message *m, const char *field, const char *eq) {
uint64_t quota_absolute = UINT64_MAX;
uint32_t quota_scale = UINT32_MAX;
int quota_enforce = false;
int r;
if (!isempty(eq) && !streq(eq, "off")) {
r = parse_permyriad(eq);
if (r < 0) {
r = parse_size(eq, 1024, &quota_absolute);
if (r < 0)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Failed to parse argument: %s=%s", field, eq);
} else
quota_scale = UINT32_SCALE_FROM_PERMYRIAD(r);
quota_enforce = true;
}
r = sd_bus_message_append(m, "(sv)", field, "(tus)", quota_absolute, quota_scale, yes_no(quota_enforce));
if (r < 0)
return bus_log_create_error(r);
return 1;
}
static int bus_append_protect_hostname(sd_bus_message *m, const char *field, const char *eq) { static int bus_append_protect_hostname(sd_bus_message *m, const char *field, const char *eq) {
int r; int r;
@ -2539,12 +2514,6 @@ static const BusProperty execute_properties[] = {
{ "ProtectControlGroupsEx", bus_append_boolean_or_ex_string }, /* compat */ { "ProtectControlGroupsEx", bus_append_boolean_or_ex_string }, /* compat */
{ "PrivateUsers", bus_append_boolean_or_ex_string }, { "PrivateUsers", bus_append_boolean_or_ex_string },
{ "PrivateUsersEx", bus_append_boolean_or_ex_string }, /* compat */ { "PrivateUsersEx", bus_append_boolean_or_ex_string }, /* compat */
{ "StateDirectoryQuota", bus_append_quota_directory },
{ "CacheDirectoryQuota", bus_append_quota_directory },
{ "LogsDirectoryQuota", bus_append_quota_directory },
{ "StateDirectoryAccounting", bus_append_parse_boolean },
{ "CacheDirectoryAccounting", bus_append_parse_boolean },
{ "LogsDirectoryAccounting", bus_append_parse_boolean },
{ NULL, bus_try_append_resource_limit, dump_resource_limits }, { NULL, bus_try_append_resource_limit, dump_resource_limits },
{} {}

View File

@ -1,15 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include "exec-directory-util.h"
#include "string-table.h"
/* This table maps ExecDirectoryType to the setting it is configured with in the unit */
static const char* const exec_directory_type_table[_EXEC_DIRECTORY_TYPE_MAX] = {
[EXEC_DIRECTORY_RUNTIME] = "RuntimeDirectory",
[EXEC_DIRECTORY_STATE] = "StateDirectory",
[EXEC_DIRECTORY_CACHE] = "CacheDirectory",
[EXEC_DIRECTORY_LOGS] = "LogsDirectory",
[EXEC_DIRECTORY_CONFIGURATION] = "ConfigurationDirectory",
};
DEFINE_STRING_TABLE_LOOKUP(exec_directory_type, ExecDirectoryType);

View File

@ -1,19 +0,0 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#pragma once
#include <errno.h>
#include "macro-fundamental.h"
typedef enum ExecDirectoryType {
EXEC_DIRECTORY_RUNTIME,
EXEC_DIRECTORY_STATE,
EXEC_DIRECTORY_CACHE,
EXEC_DIRECTORY_LOGS,
EXEC_DIRECTORY_CONFIGURATION,
_EXEC_DIRECTORY_TYPE_MAX,
_EXEC_DIRECTORY_TYPE_INVALID = -EINVAL,
} ExecDirectoryType;
const char* exec_directory_type_to_string(ExecDirectoryType i) _const_;
ExecDirectoryType exec_directory_type_from_string(const char *s) _pure_;

View File

@ -69,7 +69,6 @@ shared_sources = files(
'elf-util.c', 'elf-util.c',
'enable-mempool.c', 'enable-mempool.c',
'ethtool-util.c', 'ethtool-util.c',
'exec-directory-util.c',
'exec-util.c', 'exec-util.c',
'exit-status.c', 'exit-status.c',
'extension-util.c', 'extension-util.c',

View File

@ -1441,28 +1441,6 @@ int make_userns(uid_t uid_shift,
return TAKE_FD(userns_fd); return TAKE_FD(userns_fd);
} }
int open_tree_attr_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr) {
assert(attr);
_cleanup_close_ int fd = open_tree_attr(dir_fd, path, flags, attr, sizeof(struct mount_attr));
if (fd >= 0)
return TAKE_FD(fd);
if (!ERRNO_IS_NOT_SUPPORTED(errno))
return log_debug_errno(errno, "Failed to open tree and set mount attributes: %m");
if (attr->attr_clr & MOUNT_ATTR_IDMAP)
return log_debug_errno(SYNTHETIC_ERRNO(EOPNOTSUPP), "Cannot clear idmap from mount without open_tree_attr()");
fd = open_tree(dir_fd, path, flags);
if (fd < 0)
return log_debug_errno(errno, "Failed to open tree: %m");
if (mount_setattr(fd, "", AT_EMPTY_PATH | (flags & AT_RECURSIVE), attr, sizeof(struct mount_attr)) < 0)
return log_debug_errno(errno, "Failed to change mount attributes: %m");
return TAKE_FD(fd);
}
int remount_idmap_fd( int remount_idmap_fd(
char **paths, char **paths,
int userns_fd, int userns_fd,
@ -1491,19 +1469,22 @@ int remount_idmap_fd(
CLEANUP_ARRAY(mount_fds, n_mounts_fds, close_many_and_free); CLEANUP_ARRAY(mount_fds, n_mounts_fds, close_many_and_free);
for (size_t i = 0; i < n; i++) { for (size_t i = 0; i < n; i++) {
/* Clone the mount point and et the user namespace mapping attribute on the cloned mount point. */ int mntfd;
mount_fds[n_mounts_fds] = open_tree_attr_fallback(
/* dir_fd= */ -EBADF, /* Clone the mount point */
paths[i], mntfd = mount_fds[n_mounts_fds] = open_tree(-EBADF, paths[i], OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC, if (mount_fds[n_mounts_fds] < 0)
return log_debug_errno(errno, "Failed to open tree of mounted filesystem '%s': %m", paths[i]);
n_mounts_fds++;
/* Set the user namespace mapping attribute on the cloned mount point */
if (mount_setattr(mntfd, "", AT_EMPTY_PATH,
&(struct mount_attr) { &(struct mount_attr) {
.attr_set = MOUNT_ATTR_IDMAP | extra_mount_attr_set, .attr_set = MOUNT_ATTR_IDMAP | extra_mount_attr_set,
.userns_fd = userns_fd, .userns_fd = userns_fd,
}); }, sizeof(struct mount_attr)) < 0)
if (mount_fds[n_mounts_fds] < 0) return log_debug_errno(errno, "Failed to change bind mount attributes for clone of '%s': %m", paths[i]);
return mount_fds[n_mounts_fds];
n_mounts_fds++;
} }
for (size_t i = n; i > 0; i--) { /* Unmount the paths right-to-left */ for (size_t i = n; i > 0; i--) { /* Unmount the paths right-to-left */

View File

@ -148,8 +148,6 @@ typedef enum RemountIdmapping {
_REMOUNT_IDMAPPING_INVALID = -EINVAL, _REMOUNT_IDMAPPING_INVALID = -EINVAL,
} RemountIdmapping; } RemountIdmapping;
int open_tree_attr_fallback(int dir_fd, const char *path, unsigned int flags, struct mount_attr *attr);
int make_userns(uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping); int make_userns(uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping);
int remount_idmap_fd(char **p, int userns_fd, uint64_t extra_mount_attr_set); int remount_idmap_fd(char **p, int userns_fd, uint64_t extra_mount_attr_set);
int remount_idmap(char **p, uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping); int remount_idmap(char **p, uid_t uid_shift, uid_t uid_range, uid_t host_owner, uid_t dest_owner, RemountIdmapping idmapping);

View File

@ -5,7 +5,6 @@
#include "alloc-util.h" #include "alloc-util.h"
#include "blockdev-util.h" #include "blockdev-util.h"
#include "chattr-util.h"
#include "device-util.h" #include "device-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "missing_syscall.h" #include "missing_syscall.h"
@ -34,66 +33,3 @@ int quotactl_fd_with_fallback(int fd, int cmd, int id, void *addr) {
return RET_NERRNO(quotactl(cmd, devnode, id, addr)); return RET_NERRNO(quotactl(cmd, devnode, id, addr));
} }
int quota_query_proj_id(int fd, uint32_t proj_id, struct dqblk *ret_req) {
int r;
assert(fd >= 0);
assert(ret_req);
r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_GETQUOTA, PRJQUOTA), proj_id, ret_req);
if (r == -ESRCH || ERRNO_IS_NEG_NOT_SUPPORTED(r) || ERRNO_IS_NEG_PRIVILEGE(r)) {
zero(ret_req);
return false;
}
if (r < 0)
return r;
return true;
}
int quota_proj_id_set_recursive(int fd, uint32_t proj_id, bool verify_exclusive) {
int r;
assert(fd >= 0);
/* Confirm only the current inode has the project id (in case of race conditions) */
if (verify_exclusive) {
/* Set to top level first because of the case where directories already exist with multiple subdirectories,
* in which case, number of inodes will be > 1 if applied recursively only */
r = set_proj_id(fd, proj_id);
if (r < 0)
return r;
struct dqblk req;
r = quotactl_fd_with_fallback(fd, QCMD_FIXED(Q_GETQUOTA, PRJQUOTA), proj_id, &req);
if (r < 0)
return r;
if (req.dqb_curinodes == 0)
return -ENOTRECOVERABLE;
if (req.dqb_curinodes != 1)
return false;
}
r = set_proj_id_recursive(fd, proj_id);
if (r < 0)
return r;
return true;
}
bool quota_dqblk_is_populated(const struct dqblk *req) {
assert(req);
return FLAGS_SET(req->dqb_valid, QIF_BLIMITS|QIF_SPACE|QIF_ILIMITS|QIF_INODES|QIF_BTIME|QIF_ITIME) &&
(req->dqb_bhardlimit > 0 ||
req->dqb_bsoftlimit > 0 ||
req->dqb_ihardlimit > 0 ||
req->dqb_isoftlimit > 0 ||
req->dqb_curspace > 0 ||
req->dqb_curinodes > 0 ||
req->dqb_btime > 0 ||
req->dqb_itime > 0);
}

View File

@ -16,6 +16,3 @@ static inline int QCMD_FIXED(uint32_t cmd, uint32_t type) {
} }
int quotactl_fd_with_fallback(int fd, int cmd, int id, void *addr); int quotactl_fd_with_fallback(int fd, int cmd, int id, void *addr);
int quota_query_proj_id(int fd, uint32_t proj_id, struct dqblk *ret_req);
int quota_proj_id_set_recursive(int fd, uint32_t proj_id, bool verify_exclusive);
bool quota_dqblk_is_populated(const struct dqblk *dqblk);

View File

@ -20,9 +20,6 @@ int verb_kill(int argc, char *argv[], void *userdata) {
sd_bus *bus; sd_bus *bus;
int r, q; int r, q;
if (arg_kill_subgroup && arg_kill_value_set)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "--kill-subgroup= and --kill-value= may not be combined.");
r = acquire_bus(BUS_MANAGER, &bus); r = acquire_bus(BUS_MANAGER, &bus);
if (r < 0) if (r < 0)
return r; return r;
@ -35,7 +32,7 @@ int verb_kill(int argc, char *argv[], void *userdata) {
polkit_agent_open_maybe(); polkit_agent_open_maybe();
kill_whom = arg_kill_whom ?: arg_kill_subgroup ? "cgroup" : "all"; kill_whom = arg_kill_whom ?: "all";
/* --fail was specified */ /* --fail was specified */
if (streq(arg_job_mode(), "fail")) if (streq(arg_job_mode(), "fail"))
@ -56,14 +53,6 @@ int verb_kill(int argc, char *argv[], void *userdata) {
&error, &error,
NULL, NULL,
"ssii", *name, kill_whom, arg_signal, arg_kill_value); "ssii", *name, kill_whom, arg_signal, arg_kill_value);
else if (arg_kill_subgroup)
q = bus_call_method(
bus,
bus_systemd_mgr,
"KillUnitSubgroup",
&error,
NULL,
"sssi", *name, kill_whom, arg_kill_subgroup, arg_signal);
else else
q = bus_call_method( q = bus_call_method(
bus, bus,

View File

@ -15,10 +15,8 @@
#include "cgroup-show.h" #include "cgroup-show.h"
#include "cpu-set-util.h" #include "cpu-set-util.h"
#include "errno-util.h" #include "errno-util.h"
#include "exec-directory-util.h"
#include "exec-util.h" #include "exec-util.h"
#include "exit-status.h" #include "exit-status.h"
#include "extract-word.h"
#include "format-util.h" #include "format-util.h"
#include "hexdecoct.h" #include "hexdecoct.h"
#include "hostname-setup.h" #include "hostname-setup.h"
@ -35,7 +33,6 @@
#include "pager.h" #include "pager.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h" #include "path-util.h"
#include "percent-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "process-util.h" #include "process-util.h"
#include "set.h" #include "set.h"
@ -164,13 +161,6 @@ typedef struct UnitCondition {
LIST_FIELDS(struct UnitCondition, conditions); LIST_FIELDS(struct UnitCondition, conditions);
} UnitCondition; } UnitCondition;
typedef struct QuotaInfo {
bool quota_enforce;
bool quota_accounting;
uint64_t quota_usage;
uint64_t quota_limit;
} QuotaInfo;
static UnitCondition* unit_condition_free(UnitCondition *c) { static UnitCondition* unit_condition_free(UnitCondition *c) {
if (!c) if (!c)
return NULL; return NULL;
@ -309,9 +299,6 @@ typedef struct UnitStatusInfo {
uint64_t default_memory_low; uint64_t default_memory_low;
uint64_t default_startup_memory_low; uint64_t default_startup_memory_low;
/* Exec Quotas */
QuotaInfo exec_directories_quota[_EXEC_DIRECTORY_TYPE_MAX];
LIST_HEAD(ExecStatusInfo, exec_status_info_list); LIST_HEAD(ExecStatusInfo, exec_status_info_list);
} UnitStatusInfo; } UnitStatusInfo;
@ -351,22 +338,6 @@ static void format_enable_state(const char *enable_state, const char **enable_on
*enable_on = *enable_off = ""; *enable_on = *enable_off = "";
} }
static void print_exec_directory_quota(UnitStatusInfo *i, ExecDirectoryType dt) {
assert(i);
if (!IN_SET(dt, EXEC_DIRECTORY_STATE, EXEC_DIRECTORY_CACHE, EXEC_DIRECTORY_LOGS))
return;
if (i->exec_directories_quota[dt].quota_accounting) {
printf(" %s: %s", exec_directory_type_to_string(dt), FORMAT_BYTES(i->exec_directories_quota[dt].quota_usage));
if (i->exec_directories_quota[dt].quota_enforce)
printf(" (max: %s)", FORMAT_BYTES(i->exec_directories_quota[dt].quota_limit));
printf("\n");
}
}
static void print_status_info( static void print_status_info(
sd_bus *bus, sd_bus *bus,
UnitStatusInfo *i, UnitStatusInfo *i,
@ -906,9 +877,6 @@ static void print_status_info(
if (i->cpu_usage_nsec != UINT64_MAX) if (i->cpu_usage_nsec != UINT64_MAX)
printf(" CPU: %s\n", FORMAT_TIMESPAN(i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC)); printf(" CPU: %s\n", FORMAT_TIMESPAN(i->cpu_usage_nsec / NSEC_PER_USEC, USEC_PER_MSEC));
for (ExecDirectoryType dt = 0; dt < _EXEC_DIRECTORY_TYPE_MAX; dt++)
print_exec_directory_quota(i, dt);
if (i->control_group) { if (i->control_group) {
_cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL; _cleanup_(sd_bus_error_free) sd_bus_error error = SD_BUS_ERROR_NULL;
static const char prefix[] = " "; static const char prefix[] = " ";
@ -1154,25 +1122,6 @@ static int map_exec(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_e
return 0; return 0;
} }
static int map_quota(sd_bus *bus, const char *member, sd_bus_message *m, sd_bus_error *error, void *userdata) {
int r;
QuotaInfo *qi = ASSERT_PTR(userdata);
uint64_t quota_usage, quota_limit;
r = sd_bus_message_read(m, "(tt)", &quota_usage, &quota_limit);
if (r < 0)
return r;
*qi = (QuotaInfo) {
.quota_enforce = quota_limit != UINT64_MAX,
.quota_accounting = quota_usage != UINT64_MAX,
.quota_usage = quota_usage,
.quota_limit = quota_limit
};
return 0;
}
static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) { static int print_property(const char *name, const char *expected_value, sd_bus_message *m, BusPrintPropertyFlags flags) {
char bus_type; char bus_type;
const char *contents; const char *contents;
@ -1389,27 +1338,6 @@ static int print_property(const char *name, const char *expected_value, sd_bus_m
fputc('\n', stdout); fputc('\n', stdout);
} }
return 1; return 1;
} else if (STR_IN_SET(name, "StateDirectoryQuota", "CacheDirectoryQuota", "LogsDirectoryQuota")) {
uint64_t quota_absolute;
uint32_t quota_scale;
const char *quota_enforce;
r = sd_bus_message_read(m, "(tus)", &quota_absolute, &quota_scale, &quota_enforce);
if (r < 0)
return r;
r = parse_boolean(quota_enforce);
if (r < 0)
return r;
if (!r)
bus_print_property_value(name, expected_value, flags, "[not set]");
else if (quota_absolute != UINT64_MAX)
bus_print_property_valuef(name, expected_value, flags, "%" PRIu64, quota_absolute);
else
bus_print_property_valuef(name, expected_value, flags, "%d%%", UINT32_SCALE_TO_PERCENT(quota_scale));
return 1;
} }
break; break;
@ -2273,9 +2201,6 @@ static int show_one(
{ "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) }, { "IPEgressBytes", "t", NULL, offsetof(UnitStatusInfo, ip_egress_bytes) },
{ "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) }, { "IOReadBytes", "t", NULL, offsetof(UnitStatusInfo, io_read_bytes) },
{ "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) }, { "IOWriteBytes", "t", NULL, offsetof(UnitStatusInfo, io_write_bytes) },
{ "StateDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_STATE]) },
{ "CacheDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_CACHE]) },
{ "LogsDirectoryQuotaUsage", "(tt)", map_quota, offsetof(UnitStatusInfo, exec_directories_quota[EXEC_DIRECTORY_LOGS]) },
{ "ExecCondition", "a(sasbttttuii)", map_exec, 0 }, { "ExecCondition", "a(sasbttttuii)", map_exec, 0 },
{ "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 }, { "ExecConditionEx", "a(sasasttttuii)", map_exec, 0 },
{ "ExecStartPre", "a(sasbttttuii)", map_exec, 0 }, { "ExecStartPre", "a(sasbttttuii)", map_exec, 0 },

View File

@ -16,7 +16,6 @@
#include "pager.h" #include "pager.h"
#include "parse-argument.h" #include "parse-argument.h"
#include "parse-util.h" #include "parse-util.h"
#include "path-util.h"
#include "pretty-print.h" #include "pretty-print.h"
#include "static-destruct.h" #include "static-destruct.h"
#include "string-table.h" #include "string-table.h"
@ -89,7 +88,6 @@ bool arg_mkdir = false;
bool arg_marked = false; bool arg_marked = false;
const char *arg_drop_in = NULL; const char *arg_drop_in = NULL;
ImagePolicy *arg_image_policy = NULL; ImagePolicy *arg_image_policy = NULL;
char *arg_kill_subgroup = NULL;
STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_types, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_states, strv_freep);
@ -105,7 +103,6 @@ STATIC_DESTRUCTOR_REGISTER(arg_boot_loader_entry, unsetp);
STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep); STATIC_DESTRUCTOR_REGISTER(arg_clean_what, strv_freep);
STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp); STATIC_DESTRUCTOR_REGISTER(arg_drop_in, unsetp);
STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep); STATIC_DESTRUCTOR_REGISTER(arg_image_policy, image_policy_freep);
STATIC_DESTRUCTOR_REGISTER(arg_kill_subgroup, freep);
static int systemctl_help(void) { static int systemctl_help(void) {
_cleanup_free_ char *link = NULL; _cleanup_free_ char *link = NULL;
@ -256,11 +253,9 @@ static int systemctl_help(void) {
" Whether to check inhibitors before shutting down,\n" " Whether to check inhibitors before shutting down,\n"
" sleeping, or hibernating\n" " sleeping, or hibernating\n"
" -i Shortcut for --check-inhibitors=no\n" " -i Shortcut for --check-inhibitors=no\n"
" -s --signal=SIGNAL Which signal to send\n"
" --kill-whom=WHOM Whom to send signal to\n" " --kill-whom=WHOM Whom to send signal to\n"
" --kill-value=INT Signal value to enqueue\n" " --kill-value=INT Signal value to enqueue\n"
" --kill-subgroup=PATH\n" " -s --signal=SIGNAL Which signal to send\n"
" Send signal to sub-control-group only\n"
" --what=RESOURCES Which types of resources to remove\n" " --what=RESOURCES Which types of resources to remove\n"
" --now Start or stop unit after enabling or disabling it\n" " --now Start or stop unit after enabling or disabling it\n"
" --dry-run Only print what would be done\n" " --dry-run Only print what would be done\n"
@ -443,7 +438,6 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
ARG_DROP_IN, ARG_DROP_IN,
ARG_WHEN, ARG_WHEN,
ARG_STDIN, ARG_STDIN,
ARG_KILL_SUBGROUP,
}; };
static const struct option options[] = { static const struct option options[] = {
@ -513,7 +507,6 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
{ "drop-in", required_argument, NULL, ARG_DROP_IN }, { "drop-in", required_argument, NULL, ARG_DROP_IN },
{ "when", required_argument, NULL, ARG_WHEN }, { "when", required_argument, NULL, ARG_WHEN },
{ "stdin", no_argument, NULL, ARG_STDIN }, { "stdin", no_argument, NULL, ARG_STDIN },
{ "kill-subgroup", required_argument, NULL, ARG_KILL_SUBGROUP },
{} {}
}; };
@ -1028,23 +1021,6 @@ static int systemctl_parse_argv(int argc, char *argv[]) {
arg_stdin = true; arg_stdin = true;
break; break;
case ARG_KILL_SUBGROUP: {
if (empty_or_root(optarg)) {
arg_kill_subgroup = mfree(arg_kill_subgroup);
break;
}
_cleanup_free_ char *p = NULL;
if (path_simplify_alloc(optarg, &p) < 0)
return log_oom();
if (!path_is_safe(p))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Control group sub-path '%s' is not valid.", p);
free_and_replace(arg_kill_subgroup, p);
break;
}
case '.': case '.':
/* Output an error mimicking getopt, and print a hint afterwards */ /* Output an error mimicking getopt, and print a hint afterwards */
log_error("%s: invalid option -- '.'", program_invocation_name); log_error("%s: invalid option -- '.'", program_invocation_name);

View File

@ -100,7 +100,6 @@ extern bool arg_mkdir;
extern bool arg_marked; extern bool arg_marked;
extern const char *arg_drop_in; extern const char *arg_drop_in;
extern ImagePolicy *arg_image_policy; extern ImagePolicy *arg_image_policy;
extern char *arg_kill_subgroup;
static inline const char* arg_job_mode(void) { static inline const char* arg_job_mode(void) {
return _arg_job_mode ?: "replace"; return _arg_job_mode ?: "replace";

View File

@ -73,9 +73,9 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
ASSERT_CGROUP_MASK(unit_get_own_mask(son), CGROUP_MASK_CPU); ASSERT_CGROUP_MASK(unit_get_own_mask(son), CGROUP_MASK_CPU);
ASSERT_CGROUP_MASK(unit_get_own_mask(grandchild), 0); ASSERT_CGROUP_MASK(unit_get_own_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY); ASSERT_CGROUP_MASK(unit_get_own_mask(parent_deep), CGROUP_MASK_MEMORY);
ASSERT_CGROUP_MASK(unit_get_own_mask(parent), CGROUP_MASK_IO); ASSERT_CGROUP_MASK(unit_get_own_mask(parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO));
ASSERT_CGROUP_MASK(unit_get_own_mask(nomem_parent), 0); ASSERT_CGROUP_MASK(unit_get_own_mask(nomem_parent), 0);
ASSERT_CGROUP_MASK(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_own_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_own_mask(root), 0); ASSERT_CGROUP_MASK(unit_get_own_mask(root), 0);
/* Verify aggregation of member masks */ /* Verify aggregation of member masks */
@ -84,29 +84,29 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
ASSERT_CGROUP_MASK(unit_get_members_mask(grandchild), 0); ASSERT_CGROUP_MASK(unit_get_members_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_members_mask(parent_deep), 0); ASSERT_CGROUP_MASK(unit_get_members_mask(parent_deep), 0);
ASSERT_CGROUP_MASK(unit_get_members_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_members_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_members_mask(nomem_parent), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_members_mask(nomem_leaf), 0); ASSERT_CGROUP_MASK(unit_get_members_mask(nomem_leaf), 0);
ASSERT_CGROUP_MASK(unit_get_members_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_members_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of sibling masks. */ /* Verify aggregation of sibling masks. */
ASSERT_CGROUP_MASK(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(son), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(daughter), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(grandchild), 0); ASSERT_CGROUP_MASK(unit_get_siblings_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(parent_deep), (CGROUP_MASK_CPU | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(parent), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(nomem_parent), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(nomem_leaf), (CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
ASSERT_CGROUP_MASK(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY)); ASSERT_CGROUP_MASK(unit_get_siblings_mask(root), (CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY));
/* Verify aggregation of target masks. */ /* Verify aggregation of target masks. */
ASSERT_CGROUP_MASK(unit_get_target_mask(son), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(son), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(daughter), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild), 0); ASSERT_CGROUP_MASK(unit_get_target_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(parent_deep), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(parent), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(parent), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent), ((CGROUP_MASK_CPU | CGROUP_MASK_IO) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_parent), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), (CGROUP_MASK_IO & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(nomem_leaf), ((CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_target_mask(root), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_target_mask(root), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
/* Verify aggregation of enable masks. */ /* Verify aggregation of enable masks. */
ASSERT_CGROUP_MASK(unit_get_enable_mask(son), 0); ASSERT_CGROUP_MASK(unit_get_enable_mask(son), 0);
@ -114,9 +114,9 @@ TEST_RET(cgroup_mask, .sd_booted = true) {
ASSERT_CGROUP_MASK(unit_get_enable_mask(grandchild), 0); ASSERT_CGROUP_MASK(unit_get_enable_mask(grandchild), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(parent_deep), 0); ASSERT_CGROUP_MASK(unit_get_enable_mask(parent_deep), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(parent), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_enable_mask(parent), ((CGROUP_MASK_CPU | CGROUP_MASK_MEMORY) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_parent), (CGROUP_MASK_IO & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_parent), ((CGROUP_MASK_IO | CGROUP_MASK_BLKIO) & m->cgroup_supported));
ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_leaf), 0); ASSERT_CGROUP_MASK(unit_get_enable_mask(nomem_leaf), 0);
ASSERT_CGROUP_MASK(unit_get_enable_mask(root), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_MEMORY) & m->cgroup_supported)); ASSERT_CGROUP_MASK(unit_get_enable_mask(root), ((CGROUP_MASK_CPU | CGROUP_MASK_IO | CGROUP_MASK_BLKIO | CGROUP_MASK_MEMORY) & m->cgroup_supported));
return 0; return 0;
} }

View File

@ -63,7 +63,7 @@ static int time_handler(sd_event_source *s, uint64_t usec, void *userdata) {
int r; int r;
log_error("Test timeout when testing %s", unit->id); log_error("Test timeout when testing %s", unit->id);
r = unit_kill(unit, KILL_ALL, /* subgroup= */ NULL, SIGKILL, SI_USER, /* value= */ 0, /* ret_error= */ NULL); r = unit_kill(unit, KILL_ALL, SIGKILL, SI_USER, 0, NULL);
if (r < 0) if (r < 0)
log_error_errno(r, "Failed to kill %s, ignoring: %m", unit->id); log_error_errno(r, "Failed to kill %s, ignoring: %m", unit->id);

View File

@ -1350,7 +1350,7 @@ static int discover_boot_entry(const char *root, char **ret_linux, char ***ret_i
const BootEntry *boot_entry = boot_config_default_entry(&config); const BootEntry *boot_entry = boot_config_default_entry(&config);
if (boot_entry && !IN_SET(boot_entry->type, BOOT_ENTRY_TYPE1, BOOT_ENTRY_TYPE2)) if (boot_entry && !IN_SET(boot_entry->type, BOOT_ENTRY_UNIFIED, BOOT_ENTRY_CONF))
boot_entry = NULL; boot_entry = NULL;
/* If we cannot determine a default entry search for UKIs (Type #2 EFI Unified Kernel Images) /* If we cannot determine a default entry search for UKIs (Type #2 EFI Unified Kernel Images)
@ -1358,14 +1358,14 @@ static int discover_boot_entry(const char *root, char **ret_linux, char ***ret_i
* https://uapi-group.org/specifications/specs/boot_loader_specification */ * https://uapi-group.org/specifications/specs/boot_loader_specification */
if (!boot_entry) if (!boot_entry)
FOREACH_ARRAY(entry, config.entries, config.n_entries) FOREACH_ARRAY(entry, config.entries, config.n_entries)
if (entry->type == BOOT_ENTRY_TYPE2) { /* UKI */ if (entry->type == BOOT_ENTRY_UNIFIED) {
boot_entry = entry; boot_entry = entry;
break; break;
} }
if (!boot_entry) if (!boot_entry)
FOREACH_ARRAY(entry, config.entries, config.n_entries) FOREACH_ARRAY(entry, config.entries, config.n_entries)
if (entry->type == BOOT_ENTRY_TYPE1) { /* .conf */ if (entry->type == BOOT_ENTRY_CONF) {
boot_entry = entry; boot_entry = entry;
break; break;
} }
@ -1373,15 +1373,15 @@ static int discover_boot_entry(const char *root, char **ret_linux, char ***ret_i
if (!boot_entry) if (!boot_entry)
return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Failed to discover any boot entries."); return log_error_errno(SYNTHETIC_ERRNO(ENOENT), "Failed to discover any boot entries.");
log_debug("Discovered boot entry %s (%s)", boot_entry->id, boot_entry_type_description_to_string(boot_entry->type)); log_debug("Discovered boot entry %s (%s)", boot_entry->id, boot_entry_type_to_string(boot_entry->type));
_cleanup_free_ char *linux_kernel = NULL; _cleanup_free_ char *linux_kernel = NULL;
_cleanup_strv_free_ char **initrds = NULL; _cleanup_strv_free_ char **initrds = NULL;
if (boot_entry->type == BOOT_ENTRY_TYPE2) { /* UKI */ if (boot_entry->type == BOOT_ENTRY_UNIFIED) {
linux_kernel = path_join(boot_entry->root, boot_entry->kernel); linux_kernel = path_join(boot_entry->root, boot_entry->kernel);
if (!linux_kernel) if (!linux_kernel)
return log_oom(); return log_oom();
} else if (boot_entry->type == BOOT_ENTRY_TYPE1) { /* .conf */ } else if (boot_entry->type == BOOT_ENTRY_CONF) {
linux_kernel = path_join(boot_entry->root, boot_entry->kernel); linux_kernel = path_join(boot_entry->root, boot_entry->kernel);
if (!linux_kernel) if (!linux_kernel)
return log_oom(); return log_oom();

View File

@ -784,8 +784,6 @@ CPUSchedulingPriority=
CPUSchedulingResetOnFork= CPUSchedulingResetOnFork=
CacheDirectory= CacheDirectory=
CacheDirectoryMode= CacheDirectoryMode=
CacheDirectoryAccounting=
CacheDirectoryQuota=
Capability= Capability=
Compress= Compress=
ConfigurationDirectory= ConfigurationDirectory=
@ -863,8 +861,6 @@ LogRateLimitBurst=
LogFilterPatterns= LogFilterPatterns=
LogsDirectory= LogsDirectory=
LogsDirectoryMode= LogsDirectoryMode=
LogsDirectoryAccounting=
LogsDirectoryQuota=
MACVLAN= MACVLAN=
MachineID= MachineID=
MaxFileSec= MaxFileSec=
@ -947,8 +943,6 @@ StandardInputText=
StandardOutput= StandardOutput=
StateDirectory= StateDirectory=
StateDirectoryMode= StateDirectoryMode=
StateDirectoryAccounting=
StateDirectoryQuota=
Storage= Storage=
SuspendKeyIgnoreInhibited= SuspendKeyIgnoreInhibited=
SyncIntervalSec= SyncIntervalSec=

View File

@ -1,95 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
# shellcheck disable=SC2016
set -eux
set -o pipefail
systemd-analyze log-level debug
test_quotas() {
local directory="$1"
local exec_directory_directive="$2"
local exec_quota_directive="$3"
local mountpoint="/datadrive"
dev_num=$(lsblk | grep "498M" | awk '{print $1}' | sed 's/[^a-zA-Z0-9]*//g')
if ! tune2fs -Q prjquota "/dev/${dev_num}"; then
return
fi
mkdir -p "${mountpoint}"
mount "/dev/${dev_num}" "${mountpoint}"
mv /var/lib/ "${mountpoint}"
rm -rf /var/lib/ && ln -s "${mountpoint}/lib/" /var/
rm -rf "${directory}/quotadir"
cat >/run/systemd/system/testservice-07-check-quotas.service <<EOF
[Unit]
Description=Check quotas with ExecDirectory
[Service]
# Relevant only for sanitizer runs
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
Type=oneshot
MountAPIVFS=yes
DynamicUser=yes
PrivateUsers=yes
TemporaryFileSystem=/run /var/opt /var/lib /vol
${exec_directory_directive}
${exec_quota_directive}
ExecStart=/bin/bash -c ' \
set -eux; \
set -o pipefail; \
touch ${directory}/quotadir/testfile; \
'
EOF
systemctl daemon-reload
systemctl start testservice-07-check-quotas.service
proj_id=$(lsattr -p "${directory}" | grep "quotadir" | awk '{print $1}')
[[ $proj_id -gt 0 ]]
block_limit=$(repquota -P "${mountpoint}" | grep -E "#$proj_id " | awk '{print $5}')
inode_limit=$(repquota -P "${mountpoint}" | grep -E "#$proj_id " | awk '{print $8}')
[[ $block_limit -gt 0 ]]
[[ $inode_limit -gt 0 ]]
# Test exceed limit
rm -rf "${directory}/quotadir"
cat >/run/systemd/system/testservice-07-check-quotas.service <<EOF
[Unit]
Description=Check quotas with ExecDirectory
[Service]
# Relevant only for sanitizer runs
EnvironmentFile=-/usr/lib/systemd/systemd-asan-env
Type=oneshot
MountAPIVFS=yes
DynamicUser=yes
PrivateUsers=yes
TemporaryFileSystem=/run /var/opt /var/lib /vol
${exec_directory_directive}
${exec_quota_directive}
ExecStart=/bin/bash -c ' \
set -eux; \
set -o pipefail; \
(! fallocate -l 10000G ${directory}/quotadir/largefile); \
'
EOF
systemctl daemon-reload
systemctl start testservice-07-check-quotas.service
}
test_quotas "/var/lib/private" "StateDirectory=quotadir" "StateDirectoryQuota=1%"
systemd-analyze log-level info
touch /testok

View File

@ -1,39 +0,0 @@
#!/usr/bin/env bash
# SPDX-License-Identifier: LGPL-2.1-or-later
# shellcheck disable=SC2016
set -eux
set -o pipefail
# shellcheck source=test/units/test-control.sh
. "$(dirname "$0")"/test-control.sh
# shellcheck source=test/units/util.sh
. "$(dirname "$0")"/util.sh
at_exit() {
loginctl disable-linger testuser ||:
run0 -u testuser systemctl --user stop subgroup-test.service ||:
}
trap at_exit EXIT
loginctl enable-linger testuser
run0 -u testuser systemd-run --user --unit=subgroup-test.service sleep infinity
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=waldo
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=/waldo
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=waldo/knurz
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=/waldo/knurz
(! systemctl kill user@"$(id -u testuser)".service --kill-subgroup=waldo --kill-whom=cgroup-fail)
(! systemctl kill user@"$(id -u testuser)".service --kill-subgroup=/waldo --kill-whom=cgroup-fail)
(! systemctl kill user@"$(id -u testuser)".service --kill-subgroup=waldo/knurz --kill-whom=cgroup-fail)
(! systemctl kill user@"$(id -u testuser)".service --kill-subgroup=/waldo/knurz --kill-whom=cgroup-fail)
run0 -u testuser systemctl --user is-active subgroup-test.service
(! systemctl kill user@"$(id -u testuser)".service --kill-subgroup=app.slice/subgroup-test.service/waldo --kill-whom=cgroup-fail)
run0 -u testuser systemctl --user is-active subgroup-test.service
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=app.slice/subgroup-test.service/waldo
run0 -u testuser systemctl --user is-active subgroup-test.service
systemctl kill user@"$(id -u testuser)".service --kill-subgroup=app.slice/subgroup-test.service --kill-whom=cgroup-fail
timeout 60 bash -c 'while run0 -u testuser systemctl --user is-active subgroup-test.service ; do sleep 1 ; done'