New upstream version 247.3

This commit is contained in:
Michael Biebl 2021-02-03 00:12:14 +01:00
parent 9bb629ec19
commit 1ce460ce8d
87 changed files with 1177 additions and 751 deletions

4
README
View File

@ -192,8 +192,8 @@ REQUIREMENTS:
Any configuration options can be specified as -Darg=value... arguments
to meson. After the build directory is initially configured, meson will
refuse to run again, and options must be changed with:
mesonconf -Darg=value...
mesonconf without any arguments will print out available options and
meson configure -Darg=value build/
meson configure without any arguments will print out available options and
their current values.
Useful commands:

View File

@ -145,7 +145,7 @@ names for them in UIs.
## Links
[Boot Loader Specification](https://systemd.io/BOOT_LOADER_INTERFACE)<br>
[Boot Loader Specification](https://systemd.io/BOOT_LOADER_SPECIFICATION)<br>
[Discoverable Partitions Specification](https://systemd.io/DISCOVERABLE_PARTITIONS)<br>
[systemd-boot(7)](https://www.freedesktop.org/software/systemd/man/systemd-boot.html)<br>
[bootctl(1)](https://www.freedesktop.org/software/systemd/man/bootctl.html)<br>

View File

@ -277,6 +277,25 @@
</listitem>
</varlistentry>
<varlistentry>
<term><option>no-read-workqueue</option></term>
<listitem><para>Bypass dm-crypt internal workqueue and process read requests synchronously. The
default is to queue these requests and process them asynchronously.</para>
<para>This requires kernel 5.9 or newer.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>no-write-workqueue</option></term>
<listitem><para>Bypass dm-crypt internal workqueue and process write requests synchronously. The
default is to queue these requests and process them asynchronously.</para>
<para>This requires kernel 5.9 or newer.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><option>skip=</option></term>

View File

@ -41,6 +41,9 @@
symlink target name of <filename>/etc/localtime</filename>, this
file may not be a normal file or hardlink.</para>
<para>If <filename>/etc/localtime</filename> is missing, the
default <literal>UTC</literal> timezone is used.</para>
<para>The timezone may be overridden for individual programs by
using the <varname>$TZ</varname> environment variable. See
<citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>.</para>

View File

@ -1063,8 +1063,10 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<para><command>systemd</command> supports an environment block that is passed to processes the manager
spawns. The names of the variables can contain ASCII letters, digits, and the underscore
character. Variable names cannot be empty or start with a digit. In variable values, most characters
are allowed, but non-printable characters are currently rejected. The total length of the environment
block is limited to <constant>_SC_ARG_MAX</constant> value defined by
are allowed, but the whole sequence must be valid UTF-8. (Note that control characters like newline
(<constant>NL</constant>), tab (<constant>TAB</constant>), or the escape character
(<constant>ESC</constant>), <emphasis>are</emphasis> valid ASCII and thus valid UTF-8). The total
length of the environment block is limited to <constant>_SC_ARG_MAX</constant> value defined by
<citerefentry project='man-pages'><refentrytitle>sysconf</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para>
@ -1123,10 +1125,12 @@ Jan 12 10:46:45 example.com bluetoothd[8900]: gatt-time-server: Input/output err
<listitem>
<para>Import all, one or more environment variables set on the client into the systemd manager
environment block. If no arguments are passed, the entire environment block is imported.
Otherwise, a list of one or more environment variable names should be passed, whose client-side
values are then imported into the manager's environment block. This command will silently ignore
any assignments which do not conform to the rules listed above.</para>
environment block. If a list of environment variable names is passed, client-side values are then
imported into the manager's environment block. If any names are not valid environment variable
names or have invalid values according to the rules described above, an error is raised. If no
arguments are passed, the entire environment block inherited by the <command>systemctl</command>
process is imported. In this mode, any inherited invalid environment variables are quietly
ignored.</para>
</listitem>
</varlistentry>
</variablelist>

View File

@ -714,7 +714,8 @@
this way is used, similar to the behavior if "yes" is specified. If the check is not successful (and thus
the UID/GID range indicated in the root directory's file owner is already used elsewhere) a new currently
unused UID/GID range of 65536 UIDs/GIDs is randomly chosen between the host UID/GIDs of 524288 and
1878982656, always starting at a multiple of 65536. This setting implies
1878982656, always starting at a multiple of 65536, and, if possible, consistently hashed from the machine
name. This setting implies
<option>--private-users-chown</option> (see below), which has the effect that the files and directories in
the container's directory tree will be owned by the appropriate users of the range picked. Using this option
makes user namespace behavior fully automatic. Note that the first invocation of a previously unused

View File

@ -361,7 +361,8 @@
<listitem><para>Configure the default value for the per-unit <varname>TasksMax=</varname> setting. See
<citerefentry><refentrytitle>systemd.resource-control</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. This setting applies to all unit types that support resource control settings, with the exception
of slice units. Defaults to 15% of the sysctl setting <varname>kernel.pid_max=</varname> or root cgroup <varname>pids.max</varname>.
of slice units. Defaults to 15% of the minimum of <varname>kernel.pid_max=</varname>, <varname>kernel.threads-max=</varname>
and root cgroup <varname>pids.max</varname>.
Kernel has a default value for <varname>kernel.pid_max=</varname> and an algorithm of counting in case of more than 32 cores.
For example with the default <varname>kernel.pid_max=</varname>, <varname>DefaultTasksMax=</varname> defaults to 4915,
but might be greater in other systems or smaller in OS containers.</para></listitem>

View File

@ -2304,10 +2304,10 @@ SystemCallErrorNumber=EPERM</programlisting>
set by the service manager itself (such as <varname>$NOTIFY_SOCKET</varname> and such), or set by a PAM module
(in case <varname>PAMName=</varname> is used).</para>
<para>
See <citerefentry
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for details
about environment variables.</para></listitem>
<para>See "Environment Variables in Spawned Processes" below for a description of how those
settings combine to form the inherited environment. See <citerefentry
project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry> for general
information about environment variables.</para></listitem>
</varlistentry>
</variablelist>
@ -2809,7 +2809,7 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
</refsect1>
<refsect1>
<title>Environment variables in spawned processes</title>
<title>Environment Variables in Spawned Processes</title>
<para>Processes started by the service manager are executed with an environment variable block assembled from
multiple sources. Processes started by the system service manager generally do not inherit environment variables
@ -2822,410 +2822,427 @@ StandardInputData=SWNrIHNpdHplIGRhIHVuJyBlc3NlIEtsb3BzLAp1ZmYgZWVtYWwga2xvcHAncy
<itemizedlist>
<listitem><para>Variables globally configured for the service manager, using the
<varname>DefaultEnvironment=</varname> setting in
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, the kernel command line option <varname>systemd.setenv=</varname> (see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>) or via
<command>systemctl set-environment</command> (see <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para></listitem>
<citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
the kernel command line option <varname>systemd.setenv=</varname> understood by
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>, or via
<citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>
<command>set-environment</command> verb.</para></listitem>
<listitem><para>Variables defined by the service manager itself (see the list below)</para></listitem>
<listitem><para>Variables defined by the service manager itself (see the list below).</para></listitem>
<listitem><para>Variables set in the service manager's own environment variable block (subject to <varname>PassEnvironment=</varname> for the system service manager)</para></listitem>
<listitem><para>Variables set in the service manager's own environment variable block (subject to
<varname>PassEnvironment=</varname> for the system service manager).</para></listitem>
<listitem><para>Variables set via <varname>Environment=</varname> in the unit file</para></listitem>
<listitem><para>Variables set via <varname>Environment=</varname> in the unit file.</para></listitem>
<listitem><para>Variables read from files specified via <varname>EnvironmentFile=</varname> in the unit file</para></listitem>
<listitem><para>Variables read from files specified via <varname>EnvironmentFile=</varname> in the unit
file.</para></listitem>
<listitem><para>Variables set by any PAM modules in case <varname>PAMName=</varname> is in effect,
cf. <citerefentry
project='man-pages'><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry></para></listitem>
project='man-pages'><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
</para></listitem>
</itemizedlist>
<para>If the same environment variables are set by multiple of these sources, the later source — according to the
order of the list above — wins. Note that as final step all variables listed in
<varname>UnsetEnvironment=</varname> are removed again from the compiled environment variable list, immediately
<para>If the same environment variable is set by multiple of these sources, the later source — according
to the order of the list above — wins. Note that as the final step all variables listed in
<varname>UnsetEnvironment=</varname> are removed from the compiled environment variable list, immediately
before it is passed to the executed process.</para>
<para>The following environment variables are set or propagated by the service manager for each invoked
process:</para>
<para>The general philosophy is to expose a small curated list of environment variables to processes.
Services started by the system manager (PID 1) will be started, without additional service-specific
configuration, with just a few environment variables. The user manager inherits environment variables as
any other system service, but in addition may receive additional environment variables from PAM, and,
typically, additional imported variables when the user starts a graphical session. It is recommended to
keep the environment blocks in both the system and user managers managers lean.</para>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$PATH</varname></term>
<para>Hint: <command>systemd-run -P env</command> and <command>systemd-run --user -P env</command> print
the effective system and user service environment blocks.</para>
<listitem><para>Colon-separated list of directories to use when launching
executables. <command>systemd</command> uses a fixed value of
<literal><filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename></literal>
in the system manager. When compiled for systems with "unmerged /usr" (<filename>/bin</filename> is
not a symlink to <filename>/usr/bin</filename>),
<literal>:<filename>/sbin</filename>:<filename>/bin</filename></literal> is appended. In case of the
the user manager, a different path may be configured by the distribution. It is recommended to not
rely on the order of entries, and have only one program with a given name in
<varname>$PATH</varname>.</para></listitem>
</varlistentry>
<refsect2>
<title>Environment Variables Set or Propagated by the Service Manager</title>
<varlistentry>
<term><varname>$LANG</varname></term>
<para>The following environment variables are propagated by the service manager or generated internally
for each invoked process:</para>
<listitem><para>Locale. Can be set in
<citerefentry project='man-pages'><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
or on the kernel command line (see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>
and
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
<variablelist class='environment-variables'>
<varlistentry>
<term><varname>$PATH</varname></term>
<varlistentry>
<term><varname>$USER</varname></term>
<term><varname>$LOGNAME</varname></term>
<term><varname>$HOME</varname></term>
<term><varname>$SHELL</varname></term>
<listitem><para>Colon-separated list of directories to use when launching
executables. <command>systemd</command> uses a fixed value of
<literal><filename>/usr/local/sbin</filename>:<filename>/usr/local/bin</filename>:<filename>/usr/sbin</filename>:<filename>/usr/bin</filename></literal>
in the system manager. When compiled for systems with "unmerged <filename>/usr/</filename>"
(<filename>/bin</filename> is not a symlink to <filename>/usr/bin</filename>),
<literal>:<filename>/sbin</filename>:<filename>/bin</filename></literal> is appended. In case of
the the user manager, a different path may be configured by the distribution. It is recommended to
not rely on the order of entries, and have only one program with a given name in
<varname>$PATH</varname>.</para></listitem>
</varlistentry>
<listitem><para>User name (twice), home directory, and the
login shell. The variables are set for the units that have
<varname>User=</varname> set, which includes user
<command>systemd</command> instances. See
<citerefentry project='die-net'><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$LANG</varname></term>
<varlistentry>
<term><varname>$INVOCATION_ID</varname></term>
<listitem><para>Locale. Can be set in <citerefentry
project='man-pages'><refentrytitle>locale.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
or on the kernel command line (see
<citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry> and
<citerefentry><refentrytitle>kernel-command-line</refentrytitle><manvolnum>7</manvolnum></citerefentry>).
</para></listitem>
</varlistentry>
<listitem><para>Contains a randomized, unique 128bit ID identifying each runtime cycle of the unit, formatted
as 32 character hexadecimal string. A new ID is assigned each time the unit changes from an inactive state into
an activating or active state, and may be used to identify this specific runtime cycle, in particular in data
stored offline, such as the journal. The same ID is passed to all processes run as part of the
unit.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$USER</varname></term>
<term><varname>$LOGNAME</varname></term>
<term><varname>$HOME</varname></term>
<term><varname>$SHELL</varname></term>
<varlistentry>
<term><varname>$XDG_RUNTIME_DIR</varname></term>
<listitem><para>User name (twice), home directory, and the
login shell. The variables are set for the units that have
<varname>User=</varname> set, which includes user
<command>systemd</command> instances. See
<citerefentry project='die-net'><refentrytitle>passwd</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<listitem><para>The directory to use for runtime objects (such as IPC objects) and volatile state. Set for all
services run by the user <command>systemd</command> instance, as well as any system services that use
<varname>PAMName=</varname> with a PAM stack that includes <command>pam_systemd</command>. See below and
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry> for more
information.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$INVOCATION_ID</varname></term>
<varlistentry>
<term><varname>$RUNTIME_DIRECTORY</varname></term>
<term><varname>$STATE_DIRECTORY</varname></term>
<term><varname>$CACHE_DIRECTORY</varname></term>
<term><varname>$LOGS_DIRECTORY</varname></term>
<term><varname>$CONFIGURATION_DIRECTORY</varname></term>
<listitem><para>Contains a randomized, unique 128bit ID identifying each runtime cycle of the unit, formatted
as 32 character hexadecimal string. A new ID is assigned each time the unit changes from an inactive state into
an activating or active state, and may be used to identify this specific runtime cycle, in particular in data
stored offline, such as the journal. The same ID is passed to all processes run as part of the
unit.</para></listitem>
</varlistentry>
<listitem><para>Absolute paths to the directories defined with
<varname>RuntimeDirectory=</varname>, <varname>StateDirectory=</varname>,
<varname>CacheDirectory=</varname>, <varname>LogsDirectory=</varname>, and
<varname>ConfigurationDirectory=</varname> when those settings are used.</para>
</listitem>
</varlistentry>
<varlistentry>
<term><varname>$XDG_RUNTIME_DIR</varname></term>
<varlistentry>
<term><varname>$CREDENTIALS_DIRECTORY</varname></term>
<listitem><para>The directory to use for runtime objects (such as IPC objects) and volatile state. Set for all
services run by the user <command>systemd</command> instance, as well as any system services that use
<varname>PAMName=</varname> with a PAM stack that includes <command>pam_systemd</command>. See below and
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry> for more
information.</para></listitem>
</varlistentry>
<listitem><para>An absolute path to the per-unit directory with credentials configured via
<varname>LoadCredential=</varname>/<varname>SetCredential=</varname>. The directory is marked
read-only and is placed in unswappable memory (if supported and permitted), and is only accessible to
the UID associated with the unit via <varname>User=</varname> or <varname>DynamicUser=</varname> (and
the superuser).</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$RUNTIME_DIRECTORY</varname></term>
<term><varname>$STATE_DIRECTORY</varname></term>
<term><varname>$CACHE_DIRECTORY</varname></term>
<term><varname>$LOGS_DIRECTORY</varname></term>
<term><varname>$CONFIGURATION_DIRECTORY</varname></term>
<varlistentry>
<term><varname>$MAINPID</varname></term>
<listitem><para>Absolute paths to the directories defined with
<varname>RuntimeDirectory=</varname>, <varname>StateDirectory=</varname>,
<varname>CacheDirectory=</varname>, <varname>LogsDirectory=</varname>, and
<varname>ConfigurationDirectory=</varname> when those settings are used.</para>
</listitem>
</varlistentry>
<listitem><para>The PID of the unit's main process if it is
known. This is only set for control processes as invoked by
<varname>ExecReload=</varname> and similar. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$CREDENTIALS_DIRECTORY</varname></term>
<varlistentry>
<term><varname>$MANAGERPID</varname></term>
<listitem><para>An absolute path to the per-unit directory with credentials configured via
<varname>LoadCredential=</varname>/<varname>SetCredential=</varname>. The directory is marked
read-only and is placed in unswappable memory (if supported and permitted), and is only accessible to
the UID associated with the unit via <varname>User=</varname> or <varname>DynamicUser=</varname> (and
the superuser).</para></listitem>
</varlistentry>
<listitem><para>The PID of the user <command>systemd</command>
instance, set for processes spawned by it. </para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$MAINPID</varname></term>
<varlistentry>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_PID</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
<listitem><para>The PID of the unit's main process if it is
known. This is only set for control processes as invoked by
<varname>ExecReload=</varname> and similar. </para></listitem>
</varlistentry>
<listitem><para>Information about file descriptors passed to a
service for socket activation. See
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$MANAGERPID</varname></term>
<varlistentry>
<term><varname>$NOTIFY_SOCKET</varname></term>
<listitem><para>The PID of the user <command>systemd</command>
instance, set for processes spawned by it. </para></listitem>
</varlistentry>
<listitem><para>The socket
<function>sd_notify()</function> talks to. See
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$LISTEN_FDS</varname></term>
<term><varname>$LISTEN_PID</varname></term>
<term><varname>$LISTEN_FDNAMES</varname></term>
<varlistentry>
<term><varname>$WATCHDOG_PID</varname></term>
<term><varname>$WATCHDOG_USEC</varname></term>
<listitem><para>Information about file descriptors passed to a
service for socket activation. See
<citerefentry><refentrytitle>sd_listen_fds</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<listitem><para>Information about watchdog keep-alive notifications. See
<citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$NOTIFY_SOCKET</varname></term>
<varlistentry>
<term><varname>$TERM</varname></term>
<listitem><para>The socket
<function>sd_notify()</function> talks to. See
<citerefentry><refentrytitle>sd_notify</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<listitem><para>Terminal type, set only for units connected to
a terminal (<varname>StandardInput=tty</varname>,
<varname>StandardOutput=tty</varname>, or
<varname>StandardError=tty</varname>). See
<citerefentry project='man-pages'><refentrytitle>termcap</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$WATCHDOG_PID</varname></term>
<term><varname>$WATCHDOG_USEC</varname></term>
<varlistentry>
<term><varname>$LOG_NAMESPACE</varname></term>
<listitem><para>Information about watchdog keep-alive notifications. See
<citerefentry><refentrytitle>sd_watchdog_enabled</refentrytitle><manvolnum>3</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<listitem><para>Contains the name of the selected logging namespace when the
<varname>LogNamespace=</varname> service setting is used.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$TERM</varname></term>
<varlistentry>
<term><varname>$JOURNAL_STREAM</varname></term>
<listitem><para>Terminal type, set only for units connected to
a terminal (<varname>StandardInput=tty</varname>,
<varname>StandardOutput=tty</varname>, or
<varname>StandardError=tty</varname>). See
<citerefentry project='man-pages'><refentrytitle>termcap</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
</para></listitem>
</varlistentry>
<listitem><para>If the standard output or standard error output of the executed processes are connected to the
journal (for example, by setting <varname>StandardError=journal</varname>) <varname>$JOURNAL_STREAM</varname>
contains the device and inode numbers of the connection file descriptor, formatted in decimal, separated by a
colon (<literal>:</literal>). This permits invoked processes to safely detect whether their standard output or
standard error output are connected to the journal. The device and inode numbers of the file descriptors should
be compared with the values set in the environment variable to determine whether the process output is still
connected to the journal. Note that it is generally not sufficient to only check whether
<varname>$JOURNAL_STREAM</varname> is set at all as services might invoke external processes replacing their
standard output or standard error output, without unsetting the environment variable.</para>
<varlistentry>
<term><varname>$LOG_NAMESPACE</varname></term>
<para>If both standard output and standard error of the executed processes are connected to the journal via a
stream socket, this environment variable will contain information about the standard error stream, as that's
usually the preferred destination for log data. (Note that typically the same stream is used for both standard
output and standard error, hence very likely the environment variable contains device and inode information
matching both stream file descriptors.)</para>
<listitem><para>Contains the name of the selected logging namespace when the
<varname>LogNamespace=</varname> service setting is used.</para></listitem>
</varlistentry>
<para>This environment variable is primarily useful to allow services to optionally upgrade their used log
protocol to the native journal protocol (using
<citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and other
functions) if their standard output or standard error output is connected to the journal anyway, thus enabling
delivery of structured metadata along with logged messages.</para></listitem>
</varlistentry>
<varlistentry>
<term><varname>$JOURNAL_STREAM</varname></term>
<varlistentry>
<term><varname>$SERVICE_RESULT</varname></term>
<listitem><para>If the standard output or standard error output of the executed processes are connected to the
journal (for example, by setting <varname>StandardError=journal</varname>) <varname>$JOURNAL_STREAM</varname>
contains the device and inode numbers of the connection file descriptor, formatted in decimal, separated by a
colon (<literal>:</literal>). This permits invoked processes to safely detect whether their standard output or
standard error output are connected to the journal. The device and inode numbers of the file descriptors should
be compared with the values set in the environment variable to determine whether the process output is still
connected to the journal. Note that it is generally not sufficient to only check whether
<varname>$JOURNAL_STREAM</varname> is set at all as services might invoke external processes replacing their
standard output or standard error output, without unsetting the environment variable.</para>
<listitem><para>Only defined for the service unit type, this environment variable is passed to all
<varname>ExecStop=</varname> and <varname>ExecStopPost=</varname> processes, and encodes the service
"result". Currently, the following values are defined:</para>
<para>If both standard output and standard error of the executed processes are connected to the journal via a
stream socket, this environment variable will contain information about the standard error stream, as that's
usually the preferred destination for log data. (Note that typically the same stream is used for both standard
output and standard error, hence very likely the environment variable contains device and inode information
matching both stream file descriptors.)</para>
<table>
<title>Defined <varname>$SERVICE_RESULT</varname> values</title>
<tgroup cols='2'>
<colspec colname='result'/>
<colspec colname='meaning'/>
<thead>
<row>
<entry>Value</entry>
<entry>Meaning</entry>
</row>
</thead>
<para>This environment variable is primarily useful to allow services to optionally upgrade their used log
protocol to the native journal protocol (using
<citerefentry><refentrytitle>sd_journal_print</refentrytitle><manvolnum>3</manvolnum></citerefentry> and other
functions) if their standard output or standard error output is connected to the journal anyway, thus enabling
delivery of structured metadata along with logged messages.</para></listitem>
</varlistentry>
<tbody>
<row>
<entry><literal>success</literal></entry>
<entry>The service ran successfully and exited cleanly.</entry>
</row>
<row>
<entry><literal>protocol</literal></entry>
<entry>A protocol violation occurred: the service did not take the steps required by its unit configuration (specifically what is configured in its <varname>Type=</varname> setting).</entry>
</row>
<row>
<entry><literal>timeout</literal></entry>
<entry>One of the steps timed out.</entry>
</row>
<row>
<entry><literal>exit-code</literal></entry>
<entry>Service process exited with a non-zero exit code; see <varname>$EXIT_CODE</varname> below for the actual exit code returned.</entry>
</row>
<row>
<entry><literal>signal</literal></entry>
<entry>A service process was terminated abnormally by a signal, without dumping core. See <varname>$EXIT_CODE</varname> below for the actual signal causing the termination.</entry>
</row>
<row>
<entry><literal>core-dump</literal></entry>
<entry>A service process terminated abnormally with a signal and dumped core. See <varname>$EXIT_CODE</varname> below for the signal causing the termination.</entry>
</row>
<row>
<entry><literal>watchdog</literal></entry>
<entry>Watchdog keep-alive ping was enabled for the service, but the deadline was missed.</entry>
</row>
<row>
<entry><literal>start-limit-hit</literal></entry>
<entry>A start limit was defined for the unit and it was hit, causing the unit to fail to start. See <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s <varname>StartLimitIntervalSec=</varname> and <varname>StartLimitBurst=</varname> for details.</entry>
</row>
<row>
<entry><literal>resources</literal></entry>
<entry>A catch-all condition in case a system operation failed.</entry>
</row>
</tbody>
</tgroup>
</table>
<varlistentry>
<term><varname>$SERVICE_RESULT</varname></term>
<para>This environment variable is useful to monitor failure or successful termination of a service. Even
though this variable is available in both <varname>ExecStop=</varname> and <varname>ExecStopPost=</varname>, it
is usually a better choice to place monitoring tools in the latter, as the former is only invoked for services
that managed to start up correctly, and the latter covers both services that failed during their start-up and
those which failed during their runtime.</para></listitem>
</varlistentry>
<listitem><para>Only defined for the service unit type, this environment variable is passed to all
<varname>ExecStop=</varname> and <varname>ExecStopPost=</varname> processes, and encodes the service
"result". Currently, the following values are defined:</para>
<varlistentry>
<term><varname>$EXIT_CODE</varname></term>
<term><varname>$EXIT_STATUS</varname></term>
<table>
<title>Defined <varname>$SERVICE_RESULT</varname> values</title>
<tgroup cols='2'>
<colspec colname='result'/>
<colspec colname='meaning'/>
<thead>
<row>
<entry>Value</entry>
<entry>Meaning</entry>
</row>
</thead>
<listitem><para>Only defined for the service unit type, these environment variables are passed to all
<varname>ExecStop=</varname>, <varname>ExecStopPost=</varname> processes and contain exit status/code
information of the main process of the service. For the precise definition of the exit code and status, see
<citerefentry><refentrytitle>wait</refentrytitle><manvolnum>2</manvolnum></citerefentry>. <varname>$EXIT_CODE</varname>
is one of <literal>exited</literal>, <literal>killed</literal>,
<literal>dumped</literal>. <varname>$EXIT_STATUS</varname> contains the numeric exit code formatted as string
if <varname>$EXIT_CODE</varname> is <literal>exited</literal>, and the signal name in all other cases. Note
that these environment variables are only set if the service manager succeeded to start and identify the main
process of the service.</para>
<tbody>
<row>
<entry><literal>success</literal></entry>
<entry>The service ran successfully and exited cleanly.</entry>
</row>
<row>
<entry><literal>protocol</literal></entry>
<entry>A protocol violation occurred: the service did not take the steps required by its unit configuration (specifically what is configured in its <varname>Type=</varname> setting).</entry>
</row>
<row>
<entry><literal>timeout</literal></entry>
<entry>One of the steps timed out.</entry>
</row>
<row>
<entry><literal>exit-code</literal></entry>
<entry>Service process exited with a non-zero exit code; see <varname>$EXIT_CODE</varname> below for the actual exit code returned.</entry>
</row>
<row>
<entry><literal>signal</literal></entry>
<entry>A service process was terminated abnormally by a signal, without dumping core. See <varname>$EXIT_CODE</varname> below for the actual signal causing the termination.</entry>
</row>
<row>
<entry><literal>core-dump</literal></entry>
<entry>A service process terminated abnormally with a signal and dumped core. See <varname>$EXIT_CODE</varname> below for the signal causing the termination.</entry>
</row>
<row>
<entry><literal>watchdog</literal></entry>
<entry>Watchdog keep-alive ping was enabled for the service, but the deadline was missed.</entry>
</row>
<row>
<entry><literal>start-limit-hit</literal></entry>
<entry>A start limit was defined for the unit and it was hit, causing the unit to fail to start. See <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s <varname>StartLimitIntervalSec=</varname> and <varname>StartLimitBurst=</varname> for details.</entry>
</row>
<row>
<entry><literal>resources</literal></entry>
<entry>A catch-all condition in case a system operation failed.</entry>
</row>
</tbody>
</tgroup>
</table>
<table>
<title>Summary of possible service result variable values</title>
<tgroup cols='3'>
<colspec colname='result' />
<colspec colname='code' />
<colspec colname='status' />
<thead>
<row>
<entry><varname>$SERVICE_RESULT</varname></entry>
<entry><varname>$EXIT_CODE</varname></entry>
<entry><varname>$EXIT_STATUS</varname></entry>
</row>
</thead>
<para>This environment variable is useful to monitor failure or successful termination of a service. Even
though this variable is available in both <varname>ExecStop=</varname> and <varname>ExecStopPost=</varname>, it
is usually a better choice to place monitoring tools in the latter, as the former is only invoked for services
that managed to start up correctly, and the latter covers both services that failed during their start-up and
those which failed during their runtime.</para></listitem>
</varlistentry>
<tbody>
<row>
<entry morerows="1" valign="top"><literal>success</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>HUP</literal>, <literal>INT</literal>, <literal>TERM</literal>, <literal>PIPE</literal></entry>
</row>
<row>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>0</literal></entry>
</row>
<row>
<entry morerows="1" valign="top"><literal>protocol</literal></entry>
<entry valign="top">not set</entry>
<entry>not set</entry>
</row>
<row>
<entry><literal>exited</literal></entry>
<entry><literal>0</literal></entry>
</row>
<row>
<entry morerows="1" valign="top"><literal>timeout</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>exit-code</literal></entry>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>signal</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>HUP</literal>, <literal>INT</literal>, <literal>KILL</literal>, …</entry>
</row>
<row>
<entry valign="top"><literal>core-dump</literal></entry>
<entry valign="top"><literal>dumped</literal></entry>
<entry><literal>ABRT</literal>, <literal>SEGV</literal>, <literal>QUIT</literal>, …</entry>
</row>
<row>
<entry morerows="2" valign="top"><literal>watchdog</literal></entry>
<entry><literal>dumped</literal></entry>
<entry><literal>ABRT</literal></entry>
</row>
<row>
<entry><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry><literal>exited</literal></entry>
<entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>exec-condition</literal></entry>
<entry><literal>exited</literal></entry>
<entry><literal>1</literal>, <literal>2</literal>, <literal>3</literal>, <literal
>4</literal>, …, <literal>254</literal></entry>
</row>
<row>
<entry valign="top"><literal>oom-kill</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry><literal>start-limit-hit</literal></entry>
<entry>not set</entry>
<entry>not set</entry>
</row>
<row>
<entry><literal>resources</literal></entry>
<entry>any of the above</entry>
<entry>any of the above</entry>
</row>
<row>
<entry namest="results" nameend="status">Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the <literal>timeout</literal> and <literal>watchdog</literal> rows above only the signals that systemd sends have been included. Moreover, using <varname>SuccessExitStatus=</varname> additional exit statuses may be declared to indicate clean termination, which is not reflected by this table.</entry>
</row>
</tbody>
</tgroup>
</table>
<varlistentry>
<term><varname>$EXIT_CODE</varname></term>
<term><varname>$EXIT_STATUS</varname></term>
</listitem>
</varlistentry>
<listitem><para>Only defined for the service unit type, these environment variables are passed to all
<varname>ExecStop=</varname>, <varname>ExecStopPost=</varname> processes and contain exit status/code
information of the main process of the service. For the precise definition of the exit code and status, see
<citerefentry><refentrytitle>wait</refentrytitle><manvolnum>2</manvolnum></citerefentry>. <varname>$EXIT_CODE</varname>
is one of <literal>exited</literal>, <literal>killed</literal>,
<literal>dumped</literal>. <varname>$EXIT_STATUS</varname> contains the numeric exit code formatted as string
if <varname>$EXIT_CODE</varname> is <literal>exited</literal>, and the signal name in all other cases. Note
that these environment variables are only set if the service manager succeeded to start and identify the main
process of the service.</para>
<varlistentry>
<term><varname>$PIDFILE</varname></term>
<table>
<title>Summary of possible service result variable values</title>
<tgroup cols='3'>
<colspec colname='result' />
<colspec colname='code' />
<colspec colname='status' />
<thead>
<row>
<entry><varname>$SERVICE_RESULT</varname></entry>
<entry><varname>$EXIT_CODE</varname></entry>
<entry><varname>$EXIT_STATUS</varname></entry>
</row>
</thead>
<listitem><para>The path to the configured PID file, in case the process is forked off on behalf of a
service that uses the <varname>PIDFile=</varname> setting, see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. Service code may use this environment variable to automatically generate a PID file at
the location configured in the unit file. This field is set to an absolute path in the file
system.</para></listitem>
</varlistentry>
<tbody>
<row>
<entry morerows="1" valign="top"><literal>success</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>HUP</literal>, <literal>INT</literal>, <literal>TERM</literal>, <literal>PIPE</literal></entry>
</row>
<row>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>0</literal></entry>
</row>
<row>
<entry morerows="1" valign="top"><literal>protocol</literal></entry>
<entry valign="top">not set</entry>
<entry>not set</entry>
</row>
<row>
<entry><literal>exited</literal></entry>
<entry><literal>0</literal></entry>
</row>
<row>
<entry morerows="1" valign="top"><literal>timeout</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>exit-code</literal></entry>
<entry valign="top"><literal>exited</literal></entry>
<entry><literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>signal</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>HUP</literal>, <literal>INT</literal>, <literal>KILL</literal>, …</entry>
</row>
<row>
<entry valign="top"><literal>core-dump</literal></entry>
<entry valign="top"><literal>dumped</literal></entry>
<entry><literal>ABRT</literal>, <literal>SEGV</literal>, <literal>QUIT</literal>, …</entry>
</row>
<row>
<entry morerows="2" valign="top"><literal>watchdog</literal></entry>
<entry><literal>dumped</literal></entry>
<entry><literal>ABRT</literal></entry>
</row>
<row>
<entry><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry><literal>exited</literal></entry>
<entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
>3</literal>, …, <literal>255</literal></entry>
</row>
<row>
<entry valign="top"><literal>exec-condition</literal></entry>
<entry><literal>exited</literal></entry>
<entry><literal>1</literal>, <literal>2</literal>, <literal>3</literal>, <literal
>4</literal>, …, <literal>254</literal></entry>
</row>
<row>
<entry valign="top"><literal>oom-kill</literal></entry>
<entry valign="top"><literal>killed</literal></entry>
<entry><literal>TERM</literal>, <literal>KILL</literal></entry>
</row>
<row>
<entry><literal>start-limit-hit</literal></entry>
<entry>not set</entry>
<entry>not set</entry>
</row>
<row>
<entry><literal>resources</literal></entry>
<entry>any of the above</entry>
<entry>any of the above</entry>
</row>
<row>
<entry namest="results" nameend="status">Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the <literal>timeout</literal> and <literal>watchdog</literal> rows above only the signals that systemd sends have been included. Moreover, using <varname>SuccessExitStatus=</varname> additional exit statuses may be declared to indicate clean termination, which is not reflected by this table.</entry>
</row>
</tbody>
</tgroup>
</table></listitem>
</varlistentry>
</variablelist>
<varlistentry>
<term><varname>$PIDFILE</varname></term>
<listitem><para>The path to the configured PID file, in case the process is forked off on behalf of
a service that uses the <varname>PIDFile=</varname> setting, see
<citerefentry><refentrytitle>systemd.service</refentrytitle><manvolnum>5</manvolnum></citerefentry>
for details. Service code may use this environment variable to automatically generate a PID file at
the location configured in the unit file. This field is set to an absolute path in the file
system.</para></listitem>
</varlistentry>
</variablelist>
<para>For system services, when <varname>PAMName=</varname> is enabled and <command>pam_systemd</command> is part
of the selected PAM stack, additional environment variables defined by systemd may be set for
services. Specifically, these are <varname>$XDG_SEAT</varname>, <varname>$XDG_VTNR</varname>, see
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details.</para>
</refsect2>
<para>For system services, when <varname>PAMName=</varname> is enabled and <command>pam_systemd</command> is part
of the selected PAM stack, additional environment variables defined by systemd may be set for
services. Specifically, these are <varname>$XDG_SEAT</varname>, <varname>$XDG_VTNR</varname>, see
<citerefentry><refentrytitle>pam_systemd</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details.</para>
</refsect1>
<refsect1>
<title>Process exit codes</title>
<title>Process Exit Codes</title>
<para>When invoking a unit process the service manager possibly fails to apply the execution parameters configured
with the settings above. In that case the already created service process will exit with a non-zero exit code

View File

@ -1622,9 +1622,16 @@
<listitem>
<para>Sets a comma-separated list of IP (v4 or v6) addresses with CIDR masks
from which this peer is allowed to send incoming traffic and to
which outgoing traffic for this peer is directed. The catch-all
0.0.0.0/0 may be specified for matching all IPv4 addresses, and
::/0 may be specified for matching all IPv6 addresses. </para>
which outgoing traffic for this peer is directed.</para>
<para>The catch-all 0.0.0.0/0 may be specified for matching all IPv4 addresses,
and ::/0 may be specified for matching all IPv6 addresses.</para>
<para>Note that this only affects "routing inside the network interface itself",
as in, which wireguard peer packets with a specific destination address are sent to,
and what source addresses are accepted from which peer.</para>
<para>To cause packets to be sent via wireguard in first place, a route needs
to be added, as well - either in the <literal>[Routes]</literal> section on the
<literal>.network</literal> matching the wireguard interface, or outside of networkd.
</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -1032,8 +1032,11 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>Scope=</varname></term>
<listitem>
<para>The scope of the address, which can be <literal>global</literal>,
<literal>link</literal> or <literal>host</literal> or an unsigned integer in the range 0—255.
<para>The scope of the address, which can be
<literal>global</literal> (valid everywhere on the network, even through a gateway),
<literal>link</literal> (only valid on this device, will not traverse a gateway) or
<literal>host</literal> (only valid within the device itself, e.g. 127.0.0.1)
or an unsigned integer in the range 0—255.
Defaults to <literal>global</literal>.</para>
</listitem>
</varlistentry>
@ -1340,12 +1343,32 @@ IPv6Token=prefixstable:2002:da8:1::</programlisting></para>
<varlistentry>
<term><varname>Scope=</varname></term>
<listitem>
<para>The scope of the route, which can be <literal>global</literal>, <literal>site</literal>,
<literal>link</literal>, <literal>host</literal>, or <literal>nowhere</literal>. For IPv4 route,
defaults to <literal>host</literal> if <varname>Type=</varname> is <literal>local</literal>
or <literal>nat</literal>, and <literal>link</literal> if <varname>Type=</varname> is
<para>The scope of the IPv4 route, which can be <literal>global</literal>, <literal>site</literal>,
<literal>link</literal>, <literal>host</literal>, or
<literal>nowhere</literal>:</para>
<itemizedlist>
<listitem><para><literal>global</literal> means the route can reach
hosts more than one hop away.</para></listitem>
<listitem><para><literal>site</literal> means an interior route in
the local autonomous system.</para></listitem>
<listitem><para><literal>link</literal> means the route can only
reach hosts on the local network (one hop away).</para></listitem>
<listitem><para><literal>host</literal> means the route will not
leave the local machine (used for internal addresses like
127.0.0.1).</para></listitem>
<listitem><para><literal>nowhere</literal> means the destination
doesn't exist.</para></listitem>
</itemizedlist>
<para>For IPv4 route, defaults to <literal>host</literal> if <varname>Type=</varname> is
<literal>local</literal> or <literal>nat</literal>,
and <literal>link</literal> if <varname>Type=</varname> is
<literal>broadcast</literal>, <literal>multicast</literal>, or <literal>anycast</literal>.
In other cases, defaults to <literal>global</literal>.</para>
In other cases, defaults to <literal>global</literal>. The value is
not used for IPv6.</para>
</listitem>
</varlistentry>
<varlistentry>

View File

@ -110,7 +110,7 @@
symlink in the distribution package, rather than depending on <command>systemctl
enable</command> in the postinst scriptlets of your package. More specifically, for your
update script create a .service file, without [Install] section, and then add a symlink like
<filename index="false">/usr/lib/systemd/system-update.target.wants/foobar.service</filename>
<filename index="false">/usr/lib/systemd/system/system-update.target.wants/foobar.service</filename>
<filename index="false">../foobar.service</filename> to your package.</para>
</listitem>

View File

@ -235,7 +235,7 @@
<listitem>
<para>Restrict processes to be executed on specific memory NUMA nodes. Takes a list of memory NUMA nodes indices
or ranges separated by either whitespace or commas. Memory NUMA nodes ranges are specified by the lower and upper
CPU indices separated by a dash.</para>
NUMA nodes indices separated by a dash.</para>
<para>Setting <varname>AllowedMemoryNodes=</varname> doesn't guarantee that all of the memory NUMA nodes will
be used by the processes as it may be limited by parent units. The effective configuration is reported as

View File

@ -320,11 +320,20 @@ _systemctl () {
elif __contains_word "$verb" ${VERBS[JOBS]}; then
comps=$( __systemctl $mode list-jobs | { while read -r a b; do echo " $a"; done; } )
elif __contains_word "$verb" ${VERBS[ENVS]}; then
elif [ "$verb" = 'unset-environment' ]; then
comps=$( __systemctl $mode show-environment \
| while read -r line; do echo " ${line%%=*}"; done )
compopt -o nospace
elif [ "$verb" = 'set-environment' ]; then
comps=$( __systemctl $mode show-environment \
| while read -r line; do echo " ${line%%=*}="; done )
compopt -o nospace
elif [ "$verb" = 'import-environment' ]; then
COMPREPLY=( $(compgen -A variable -- "$cur_orig") )
return 0
elif __contains_word "$verb" ${VERBS[FILE]}; then
comps=$( compgen -A file -- "$cur" )
compopt -o filenames

View File

@ -365,6 +365,11 @@ for fun in set-environment unset-environment ; do
}
done
(( $+functions[_systemctl_import-environment] )) || _systemctl_import-environment()
{
_parameters
}
(( $+functions[_systemctl_link] )) || _systemctl_link() {
_sd_unit_files
}

View File

@ -59,16 +59,13 @@ bool env_value_is_valid(const char *e) {
if (!utf8_is_valid(e))
return false;
/* bash allows tabs and newlines in environment variables, and so
* should we */
if (string_has_cc(e, "\t\n"))
return false;
/* Note that variable *values* may contain control characters, in particular NL, TAB, BS, DEL, ESC…
* When printing those variables with show-environment, we'll escape them. Make sure to print
* environment variables carefully! */
/* POSIX says the overall size of the environment block cannot
* be > ARG_MAX, an individual assignment hence cannot be
* either. Discounting the shortest possible variable name of
* length 1, the equal sign and trailing NUL this hence leaves
* ARG_MAX-3 as longest possible variable value. */
/* POSIX says the overall size of the environment block cannot be > ARG_MAX, an individual assignment
* hence cannot be either. Discounting the shortest possible variable name of length 1, the equal
* sign and trailing NUL this hence leaves ARG_MAX-3 as longest possible variable value. */
if (strlen(e) > sc_arg_max() - 3)
return false;
@ -88,10 +85,8 @@ bool env_assignment_is_valid(const char *e) {
if (!env_value_is_valid(eq + 1))
return false;
/* POSIX says the overall size of the environment block cannot
* be > ARG_MAX, hence the individual variable assignments
* cannot be either, but let's leave room for one trailing NUL
* byte. */
/* POSIX says the overall size of the environment block cannot be > ARG_MAX, hence the individual
* variable assignments cannot be either, but let's leave room for one trailing NUL byte. */
if (strlen(e) > sc_arg_max() - 1)
return false;

View File

@ -1976,3 +1976,53 @@ IteratedCache* iterated_cache_free(IteratedCache *cache) {
return mfree(cache);
}
int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret) {
size_t separator_len, allocated = 0, len = 0;
_cleanup_free_ char *str = NULL;
const char *value;
bool first;
assert(ret);
if (set_isempty(s)) {
*ret = NULL;
return 0;
}
separator_len = strlen_ptr(separator);
if (separator_len == 0)
wrap_with_separator = false;
first = !wrap_with_separator;
SET_FOREACH(value, s) {
size_t l = strlen_ptr(value);
if (l == 0)
continue;
if (!GREEDY_REALLOC(str, allocated, len + l + (first ? 0 : separator_len) + (wrap_with_separator ? separator_len : 0) + 1))
return -ENOMEM;
if (separator_len > 0 && !first) {
memcpy(str + len, separator, separator_len);
len += separator_len;
}
memcpy(str + len, value, l);
len += l;
first = false;
}
if (wrap_with_separator) {
memcpy(str + len, separator, separator_len);
len += separator_len;
}
str[len] = '\0';
*ret = TAKE_PTR(str);
return 0;
}

View File

@ -132,6 +132,29 @@ static int fd_fdinfo_mnt_id(int fd, const char *filename, int flags, int *ret_mn
return safe_atoi(p, ret_mnt_id);
}
static bool filename_possibly_with_slash_suffix(const char *s) {
const char *slash, *copied;
/* Checks whether the specified string is either file name, or a filename with a suffix of
* slashes. But nothing else.
*
* this is OK: foo, bar, foo/, bar/, foo//, bar///
* this is not OK: "", "/", "/foo", "foo/bar", ".", ".." */
slash = strchr(s, '/');
if (!slash)
return filename_is_valid(s);
if (slash - s > FILENAME_MAX) /* We want to allocate on the stack below, hence do a size check first */
return false;
if (slash[strspn(slash, "/")] != 0) /* Check that the suffix consist only of one or more slashes */
return false;
copied = strndupa(s, slash - s);
return filename_is_valid(copied);
}
int fd_is_mount_point(int fd, const char *filename, int flags) {
_cleanup_free_ struct file_handle *h = NULL, *h_parent = NULL;
int mount_id = -1, mount_id_parent = -1;
@ -144,6 +167,11 @@ int fd_is_mount_point(int fd, const char *filename, int flags) {
assert(filename);
assert((flags & ~(AT_SYMLINK_FOLLOW|AT_EMPTY_PATH)) == 0);
/* Insist that the specified filename is actually a filename, and not a path, i.e. some inode further
* up or down the tree then immediately below the specified directory fd. */
if (!filename_possibly_with_slash_suffix(filename))
return -EINVAL;
/* First we will try statx()' STATX_ATTR_MOUNT_ROOT attribute, which is our ideal API, available
* since kernel 5.8.
*

View File

@ -150,3 +150,5 @@ DEFINE_TRIVIAL_CLEANUP_FUNC(Set*, set_free_free);
#define _cleanup_set_free_ _cleanup_(set_freep)
#define _cleanup_set_free_free_ _cleanup_(set_free_freep)
int set_strjoin(Set *s, const char *separator, bool wrap_with_separator, char **ret);

View File

@ -5,9 +5,9 @@
#include <inttypes.h>
#include <stddef.h>
#include <stdint.h>
#include <string.h>
#include <sys/types.h>
#include "string-util.h"
#include "time-util.h"
struct siphash {
@ -33,11 +33,15 @@ static inline void siphash24_compress_usec_t(usec_t in, struct siphash *state) {
siphash24_compress(&in, sizeof in, state);
}
static inline void siphash24_compress_string(const char *in, struct siphash *state) {
if (!in)
static inline void siphash24_compress_safe(const void *in, size_t inlen, struct siphash *state) {
if (inlen == 0)
return;
siphash24_compress(in, strlen(in), state);
siphash24_compress(in, inlen, state);
}
static inline void siphash24_compress_string(const char *in, struct siphash *state) {
siphash24_compress_safe(in, strlen_ptr(in), state);
}
uint64_t siphash24_finalize(struct siphash *state);

View File

@ -226,13 +226,12 @@ int fd_is_network_fs(int fd) {
}
int path_is_temporary_fs(const char *path) {
_cleanup_close_ int fd = -1;
struct statfs s;
fd = open(path, O_RDONLY|O_CLOEXEC|O_NOCTTY|O_PATH);
if (fd < 0)
if (statfs(path, &s) < 0)
return -errno;
return fd_is_temporary_fs(fd);
return is_temporary_fs(&s);
}
int stat_verify_regular(const struct stat *st) {

View File

@ -844,11 +844,14 @@ int bpf_firewall_supported(void) {
* CONFIG_CGROUP_BPF is turned off, then the call will fail early with EINVAL. If it is turned on the
* parameters are validated however, and that'll fail with EBADF then. */
attr = (union bpf_attr) {
.attach_type = BPF_CGROUP_INET_EGRESS,
.target_fd = -1,
.attach_bpf_fd = -1,
};
// FIXME: Clang doesn't 0-pad with structured initialization, causing
// the kernel to reject the bpf_attr as invalid. See:
// https://github.com/torvalds/linux/blob/v5.9/kernel/bpf/syscall.c#L65
// Ideally it should behave like GCC, so that we can remove these workarounds.
zero(attr);
attr.attach_type = BPF_CGROUP_INET_EGRESS;
attr.target_fd = -1;
attr.attach_bpf_fd = -1;
if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0) {
if (errno != EBADF) {
@ -868,12 +871,11 @@ int bpf_firewall_supported(void) {
* bpf() call and the BPF_F_ALLOW_MULTI flags value. Since the flags are checked early in the system call we'll
* get EINVAL if it's not supported, and EBADF as before if it is available. */
attr = (union bpf_attr) {
.attach_type = BPF_CGROUP_INET_EGRESS,
.target_fd = -1,
.attach_bpf_fd = -1,
.attach_flags = BPF_F_ALLOW_MULTI,
};
zero(attr);
attr.attach_type = BPF_CGROUP_INET_EGRESS;
attr.target_fd = -1;
attr.attach_bpf_fd = -1;
attr.attach_flags = BPF_F_ALLOW_MULTI;
if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0) {
if (errno == EBADF) {

View File

@ -24,7 +24,7 @@
#include "hexdecoct.h"
#include "io-util.h"
#include "ioprio.h"
#include "journal-util.h"
#include "journal-file.h"
#include "mountpoint-util.h"
#include "namespace.h"
#include "parse-util.h"

View File

@ -38,7 +38,7 @@
#include "io-util.h"
#include "ioprio.h"
#include "ip-protocol-list.h"
#include "journal-util.h"
#include "journal-file.h"
#include "limits-util.h"
#include "load-fragment.h"
#include "log.h"

View File

@ -5,6 +5,7 @@
# RPM macros for packages installing systemd unit files
%_systemd_util_dir @rootlibexecdir@
%_unitdir @systemunitdir@
%_userunitdir @userunitdir@
%_presetdir @systempresetdir@

View File

@ -2387,6 +2387,10 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
n = recvmsg_safe(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
if (IN_SET(n, -EAGAIN, -EINTR))
return 0; /* Spurious wakeup, try again */
if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0;
}
if (n < 0)
/* If this is any other, real error, then let's stop processing this socket. This of course
* means we won't take notification messages anymore, but that's still better than busy

View File

@ -55,6 +55,8 @@ static bool arg_verify = false;
static bool arg_discards = false;
static bool arg_same_cpu_crypt = false;
static bool arg_submit_from_crypt_cpus = false;
static bool arg_no_read_workqueue = false;
static bool arg_no_write_workqueue = false;
static bool arg_tcrypt_hidden = false;
static bool arg_tcrypt_system = false;
static bool arg_tcrypt_veracrypt = false;
@ -218,6 +220,10 @@ static int parse_one_option(const char *option) {
arg_same_cpu_crypt = true;
else if (streq(option, "submit-from-crypt-cpus"))
arg_submit_from_crypt_cpus = true;
else if (streq(option, "no-read-workqueue"))
arg_no_read_workqueue = true;
else if (streq(option, "no-write-workqueue"))
arg_no_write_workqueue = true;
else if (streq(option, "luks"))
arg_type = ANY_LUKS;
/* since cryptsetup 2.3.0 (Feb 2020) */
@ -805,6 +811,12 @@ static uint32_t determine_flags(void) {
if (arg_submit_from_crypt_cpus)
flags |= CRYPT_ACTIVATE_SUBMIT_FROM_CRYPT_CPUS;
if (arg_no_read_workqueue)
flags |= CRYPT_ACTIVATE_NO_READ_WORKQUEUE;
if (arg_no_write_workqueue)
flags |= CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE;
#ifdef CRYPT_ACTIVATE_SERIALIZE_MEMORY_HARD_PBKDF
/* Try to decrease the risk of OOM event if memory hard key derivation function is in use */
/* https://gitlab.com/cryptsetup/cryptsetup/issues/446/ */

View File

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65536

View File

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65536

View File

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65536

View File

@ -0,0 +1,2 @@
[libfuzzer]
max_len = 65536

View File

@ -296,9 +296,8 @@ static void tar_pull_job_on_finished(PullJob *j) {
goto finish;
}
/* This is invoked if either the download completed
* successfully, or the download was skipped because we
* already have the etag. */
/* This is invoked if either the download completed successfully, or the download was skipped because
* we already have the etag. */
if (!tar_pull_is_done(i))
return;
@ -340,6 +339,10 @@ static void tar_pull_job_on_finished(PullJob *j) {
tar_pull_report_progress(i, TAR_FINALIZING);
r = import_mangle_os_tree(i->temp_path);
if (r < 0)
goto finish;
r = import_make_read_only(i->temp_path);
if (r < 0)
goto finish;

View File

@ -1525,6 +1525,44 @@ int journal_file_find_data_object(
ret, ret_offset);
}
bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
const char *a;
/* We kinda enforce POSIX syntax recommendations for
environment variables here, but make a couple of additional
requirements.
http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
if (l == (size_t) -1)
l = strlen(p);
/* No empty field names */
if (l <= 0)
return false;
/* Don't allow names longer than 64 chars */
if (l > 64)
return false;
/* Variables starting with an underscore are protected */
if (!allow_protected && p[0] == '_')
return false;
/* Don't allow digits as first character */
if (p[0] >= '0' && p[0] <= '9')
return false;
/* Only allow A-Z0-9 and '_' */
for (a = p; a < p + l; a++)
if ((*a < 'A' || *a > 'Z') &&
(*a < '0' || *a > '9') &&
*a != '_')
return false;
return true;
}
static int journal_file_append_field(
JournalFile *f,
const void *field, uint64_t size,
@ -1538,6 +1576,9 @@ static int journal_file_append_field(
assert(f);
assert(field && size > 0);
if (!journal_field_valid(field, size, true))
return -EBADMSG;
hash = journal_file_hash_data(f, field, size);
r = journal_file_find_field_object_with_hash(f, field, size, hash, &o, &p);

View File

@ -272,3 +272,5 @@ static inline bool JOURNAL_FILE_COMPRESS(JournalFile *f) {
}
uint64_t journal_file_hash_data(JournalFile *f, const void *data, size_t sz);
bool journal_field_valid(const char *p, size_t l, bool allow_protected);

View File

@ -15,6 +15,7 @@
int main(int argc, char *argv[]) {
const char *namespace;
LogTarget log_target;
Server server;
int r;
@ -25,8 +26,13 @@ int main(int argc, char *argv[]) {
namespace = argc > 1 ? empty_to_null(argv[1]) : NULL;
log_set_prohibit_ipc(true);
log_set_target(LOG_TARGET_AUTO);
/* So here's the deal: journald can't be considered as regular daemon when it comes to
* logging hence LOG_TARGET_AUTO won't do the right thing for it. Hence explicitly log to
* the console if we're started from a console or to kmsg otherwise. */
log_target = isatty(STDERR_FILENO) > 0 ? LOG_TARGET_CONSOLE : LOG_TARGET_KMSG;
log_set_prohibit_ipc(true); /* better safe than sorry */
log_set_target(log_target);
log_set_facility(LOG_SYSLOG);
log_parse_environment();
log_open();

View File

@ -38,11 +38,14 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
size_t total = 0;
char **s;
if (strv_isempty((char **) optval))
return -EINVAL;
STRV_FOREACH(s, (char **) optval) {
size_t len = strlen(*s);
if (len > 255)
return -ENAMETOOLONG;
if (len > 255 || len == 0)
return -EINVAL;
total += 1 + len;
}
@ -51,14 +54,13 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
return -ENOBUFS;
options[*offset] = code;
options[*offset + 1] = total;
options[*offset + 1] = total;
*offset += 2;
STRV_FOREACH(s, (char **) optval) {
size_t len = strlen(*s);
options[*offset] = len;
memcpy(&options[*offset + 1], *s, len);
*offset += 1 + len;
}

View File

@ -99,8 +99,8 @@ int dhcp6_option_append(uint8_t **buf, size_t *buflen, uint16_t code,
int dhcp6_option_append_ia(uint8_t **buf, size_t *buflen, const DHCP6IA *ia);
int dhcp6_option_append_pd(uint8_t *buf, size_t len, const DHCP6IA *pd, DHCP6Address *hint_pd_prefix);
int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn);
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class);
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **user_class);
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class);
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *user_class);
int dhcp6_option_append_vendor_option(uint8_t **buf, size_t *buflen, OrderedHashmap *vendor_options);
int dhcp6_option_parse(uint8_t **buf, size_t *buflen, uint16_t *optcode,
size_t *optlen, uint8_t **optvalue);

View File

@ -200,19 +200,22 @@ int dhcp6_option_append_fqdn(uint8_t **buf, size_t *buflen, const char *fqdn) {
return r;
}
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_class) {
int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char * const *user_class) {
_cleanup_free_ uint8_t *p = NULL;
size_t total = 0, offset = 0;
char **s;
char * const *s;
assert_return(buf && *buf && buflen && user_class, -EINVAL);
assert(buf);
assert(*buf);
assert(buflen);
assert(!strv_isempty(user_class));
STRV_FOREACH(s, user_class) {
size_t len = strlen(*s);
uint8_t *q;
if (len > 0xffff)
return -ENAMETOOLONG;
if (len > 0xffff || len == 0)
return -EINVAL;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;
@ -229,16 +232,16 @@ int dhcp6_option_append_user_class(uint8_t **buf, size_t *buflen, char **user_cl
return dhcp6_option_append(buf, buflen, SD_DHCP6_OPTION_USER_CLASS, total, p);
}
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendor_class) {
int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char * const *vendor_class) {
_cleanup_free_ uint8_t *p = NULL;
uint32_t enterprise_identifier;
size_t total, offset;
char **s;
char * const *s;
assert(buf);
assert(*buf);
assert(buflen);
assert(vendor_class);
assert(!strv_isempty(vendor_class));
enterprise_identifier = htobe32(SYSTEMD_PEN);
@ -253,6 +256,9 @@ int dhcp6_option_append_vendor_class(uint8_t **buf, size_t *buflen, char **vendo
size_t len = strlen(*s);
uint8_t *q;
if (len > UINT16_MAX || len == 0)
return -EINVAL;
q = realloc(p, total + len + 2);
if (!q)
return -ENOMEM;

View File

@ -566,22 +566,26 @@ int sd_dhcp_client_set_mud_url(
int sd_dhcp_client_set_user_class(
sd_dhcp_client *client,
const char* const* user_class) {
char * const *user_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
char * const *p;
char **s = NULL;
STRV_FOREACH(p, (char **) user_class)
if (strlen(*p) > 255)
return -ENAMETOOLONG;
assert_return(client, -EINVAL);
assert_return(!strv_isempty(user_class), -EINVAL);
s = strv_copy((char **) user_class);
STRV_FOREACH(p, user_class) {
size_t n = strlen(*p);
if (n > 255 || n == 0)
return -EINVAL;
}
s = strv_copy(user_class);
if (!s)
return -ENOMEM;
client->user_class = TAKE_PTR(s);
return 0;
return strv_free_and_replace(client->user_class, s);
}
int sd_dhcp_client_set_client_port(

View File

@ -464,47 +464,48 @@ int sd_dhcp6_client_set_request_mud_url(sd_dhcp6_client *client, const char *mud
return free_and_strdup(&client->mudurl, mudurl);
}
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char **user_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
int sd_dhcp6_client_set_request_user_class(sd_dhcp6_client *client, char * const *user_class) {
char * const *p;
char **s;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(!strv_isempty(user_class), -EINVAL);
assert_return(user_class, -EINVAL);
STRV_FOREACH(p, user_class) {
size_t len = strlen(*p);
STRV_FOREACH(p, user_class)
if (strlen(*p) > UINT16_MAX)
return -ENAMETOOLONG;
if (len > UINT16_MAX || len == 0)
return -EINVAL;
}
s = strv_copy(user_class);
if (!s)
return -ENOMEM;
client->user_class = TAKE_PTR(s);
return 0;
return strv_free_and_replace(client->user_class, s);
}
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char **vendor_class) {
_cleanup_strv_free_ char **s = NULL;
char **p;
int sd_dhcp6_client_set_request_vendor_class(sd_dhcp6_client *client, char * const *vendor_class) {
char * const *p;
char **s;
assert_return(client, -EINVAL);
assert_return(client->state == DHCP6_STATE_STOPPED, -EBUSY);
assert_return(vendor_class, -EINVAL);
assert_return(!strv_isempty(vendor_class), -EINVAL);
STRV_FOREACH(p, vendor_class)
if (strlen(*p) > UINT8_MAX)
return -ENAMETOOLONG;
STRV_FOREACH(p, vendor_class) {
size_t len = strlen(*p);
if (len > UINT16_MAX || len == 0)
return -EINVAL;
}
s = strv_copy(vendor_class);
if (!s)
return -ENOMEM;
client->vendor_class = TAKE_PTR(s);
return 0;
return strv_free_and_replace(client->vendor_class, s);
}
int sd_dhcp6_client_get_prefix_delegation(sd_dhcp6_client *client, int *delegation) {

View File

@ -713,7 +713,7 @@ _public_ int sd_bus_get_name_creds(
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
if (r < 0 && r != -ESRCH) /* Return the error, but ignore ESRCH which just means the process is already gone */
return r;
}
@ -788,7 +788,7 @@ _public_ int sd_bus_get_owner_creds(sd_bus *bus, uint64_t mask, sd_bus_creds **r
}
r = bus_creds_add_more(c, mask, pid, 0);
if (r < 0)
if (r < 0 && r != -ESRCH) /* If the process vanished, then don't complain, just return what we got */
return r;
*ret = TAKE_PTR(c);

View File

@ -603,13 +603,15 @@ _public_ int sd_bus_set_property(
return r;
}
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **creds) {
_public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_bus_creds **ret) {
sd_bus_creds *c;
int r;
assert_return(call, -EINVAL);
assert_return(call->sealed, -EPERM);
assert_return(call->bus, -EINVAL);
assert_return(!bus_pid_changed(call->bus), -ECHILD);
assert_return(ret, -EINVAL);
if (!BUS_IS_OPEN(call->bus->state))
return -ENOTCONN;
@ -618,7 +620,7 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
/* All data we need? */
if (c && (mask & ~c->mask) == 0) {
*creds = sd_bus_creds_ref(c);
*ret = sd_bus_creds_ref(c);
return 0;
}
@ -629,15 +631,22 @@ _public_ int sd_bus_query_sender_creds(sd_bus_message *call, uint64_t mask, sd_b
if (call->sender)
/* There's a sender, but the creds are missing. */
return sd_bus_get_name_creds(call->bus, call->sender, mask, creds);
return sd_bus_get_name_creds(call->bus, call->sender, mask, ret);
else
/* There's no sender. For direct connections
* the credentials of the AF_UNIX peer matter,
* which may be queried via sd_bus_get_owner_creds(). */
return sd_bus_get_owner_creds(call->bus, mask, creds);
return sd_bus_get_owner_creds(call->bus, mask, ret);
}
return bus_creds_extend_by_pid(c, mask, creds);
r = bus_creds_extend_by_pid(c, mask, ret);
if (r == -ESRCH) {
/* Process doesn't exist anymore? propagate the few things we have */
*ret = sd_bus_creds_ref(c);
return 0;
}
return r;
}
_public_ int sd_bus_query_sender_privilege(sd_bus_message *call, int capability) {

View File

@ -319,7 +319,10 @@ static int device_amend(sd_device *device, const char *key, const char *value) {
for (const char *p = value;;) {
_cleanup_free_ char *word = NULL;
r = extract_first_word(&p, &word, NULL, 0);
/* udev rules may set escaped strings, and sd-device does not modify the input
* strings. So, it is also necessary to keep the strings received through
* sd-device-monitor. */
r = extract_first_word(&p, &word, NULL, EXTRACT_RETAIN_ESCAPE);
if (r < 0)
return r;
if (r == 0)

View File

@ -1518,30 +1518,6 @@ _public_ const char *sd_device_get_devlink_next(sd_device *device) {
return v;
}
static char *join_string_set(Set *s) {
size_t ret_allocated = 0, ret_len;
_cleanup_free_ char *ret = NULL;
const char *tag;
if (!GREEDY_REALLOC(ret, ret_allocated, 2))
return NULL;
strcpy(ret, ":");
ret_len = 1;
SET_FOREACH(tag, s) {
char *e;
if (!GREEDY_REALLOC(ret, ret_allocated, ret_len + strlen(tag) + 2))
return NULL;
e = stpcpy(stpcpy(ret + ret_len, tag), ":");
ret_len = e - ret;
}
return TAKE_PTR(ret);
}
int device_properties_prepare(sd_device *device) {
int r;
@ -1557,46 +1533,39 @@ int device_properties_prepare(sd_device *device) {
if (device->property_devlinks_outdated) {
_cleanup_free_ char *devlinks = NULL;
size_t devlinks_allocated = 0, devlinks_len = 0;
const char *devlink;
for (devlink = sd_device_get_devlink_first(device); devlink; devlink = sd_device_get_devlink_next(device)) {
char *e;
if (!GREEDY_REALLOC(devlinks, devlinks_allocated, devlinks_len + strlen(devlink) + 2))
return -ENOMEM;
if (devlinks_len > 0)
stpcpy(devlinks + devlinks_len++, " ");
e = stpcpy(devlinks + devlinks_len, devlink);
devlinks_len = e - devlinks;
}
r = device_add_property_internal(device, "DEVLINKS", devlinks);
r = set_strjoin(device->devlinks, " ", false, &devlinks);
if (r < 0)
return r;
if (!isempty(devlinks)) {
r = device_add_property_internal(device, "DEVLINKS", devlinks);
if (r < 0)
return r;
}
device->property_devlinks_outdated = false;
}
if (device->property_tags_outdated) {
_cleanup_free_ char *tags = NULL;
tags = join_string_set(device->all_tags);
if (!tags)
return -ENOMEM;
r = set_strjoin(device->all_tags, ":", true, &tags);
if (r < 0)
return r;
if (!streq(tags, ":")) {
if (!isempty(tags)) {
r = device_add_property_internal(device, "TAGS", tags);
if (r < 0)
return r;
}
free(tags);
tags = join_string_set(device->current_tags);
if (!tags)
return -ENOMEM;
tags = mfree(tags);
r = set_strjoin(device->current_tags, ":", true, &tags);
if (r < 0)
return r;
if (!streq(tags, ":")) {
if (!isempty(tags)) {
r = device_add_property_internal(device, "CURRENT_TAGS", tags);
if (r < 0)
return r;

View File

@ -112,68 +112,74 @@ static void test_login(void) {
if (session) {
r = sd_session_is_active(session);
assert_se(r >= 0);
log_info("sd_session_is_active(\"%s\") → %s", session, yes_no(r));
if (r == -ENXIO)
log_notice("sd_session_is_active() failed with ENXIO, it seems logind is not running.");
else {
/* All those tests will fail with ENXIO, so let's skip them. */
r = sd_session_is_remote(session);
assert_se(r >= 0);
log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
assert_se(r >= 0);
log_info("sd_session_is_active(\"%s\") → %s", session, yes_no(r));
r = sd_session_get_state(session, &state);
assert_se(r == 0);
log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
r = sd_session_is_remote(session);
assert_se(r >= 0);
log_info("sd_session_is_remote(\"%s\") → %s", session, yes_no(r));
assert_se(sd_session_get_uid(session, &u) >= 0);
log_info("sd_session_get_uid(\"%s\") → "UID_FMT, session, u);
assert_se(u == u2);
r = sd_session_get_state(session, &state);
assert_se(r == 0);
log_info("sd_session_get_state(\"%s\") → \"%s\"", session, state);
assert_se(sd_session_get_type(session, &type) >= 0);
log_info("sd_session_get_type(\"%s\") → \"%s\"", session, type);
assert_se(sd_session_get_uid(session, &u) >= 0);
log_info("sd_session_get_uid(\"%s\") → "UID_FMT, session, u);
assert_se(u == u2);
assert_se(sd_session_get_class(session, &class) >= 0);
log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
assert_se(sd_session_get_type(session, &type) >= 0);
log_info("sd_session_get_type(\"%s\") → \"%s\"", session, type);
r = sd_session_get_display(session, &display);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
assert_se(sd_session_get_class(session, &class) >= 0);
log_info("sd_session_get_class(\"%s\") → \"%s\"", session, class);
r = sd_session_get_remote_user(session, &remote_user);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
session, strna(remote_user));
r = sd_session_get_display(session, &display);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_display(\"%s\") → \"%s\"", session, strna(display));
r = sd_session_get_remote_host(session, &remote_host);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
session, strna(remote_host));
r = sd_session_get_remote_user(session, &remote_user);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_user(\"%s\") → \"%s\"",
session, strna(remote_user));
r = sd_session_get_seat(session, &seat);
if (r >= 0) {
assert_se(seat);
r = sd_session_get_remote_host(session, &remote_host);
assert_se(IN_SET(r, 0, -ENODATA));
log_info("sd_session_get_remote_host(\"%s\") → \"%s\"",
session, strna(remote_host));
log_info("sd_session_get_seat(\"%s\") → \"%s\"", session, seat);
r = sd_session_get_seat(session, &seat);
if (r >= 0) {
assert_se(seat);
log_info("sd_session_get_seat(\"%s\") → \"%s\"", session, seat);
#pragma GCC diagnostic push
#pragma GCC diagnostic ignored "-Wdeprecated-declarations"
r = sd_seat_can_multi_session(seat);
r = sd_seat_can_multi_session(seat);
#pragma GCC diagnostic pop
assert_se(r == 1);
log_info("sd_session_can_multi_seat(\"%s\") → %s", seat, yes_no(r));
assert_se(r == 1);
log_info("sd_session_can_multi_seat(\"%s\") → %s", seat, yes_no(r));
r = sd_seat_can_tty(seat);
assert_se(r >= 0);
log_info("sd_session_can_tty(\"%s\") → %s", seat, yes_no(r));
r = sd_seat_can_tty(seat);
assert_se(r >= 0);
log_info("sd_session_can_tty(\"%s\") → %s", seat, yes_no(r));
r = sd_seat_can_graphical(seat);
assert_se(r >= 0);
log_info("sd_session_can_graphical(\"%s\") → %s", seat, yes_no(r));
} else {
log_info_errno(r, "sd_session_get_seat(\"%s\"): %m", session);
assert_se(r == -ENODATA);
r = sd_seat_can_graphical(seat);
assert_se(r >= 0);
log_info("sd_session_can_graphical(\"%s\") → %s", seat, yes_no(r));
} else {
log_info_errno(r, "sd_session_get_seat(\"%s\"): %m", session);
assert_se(r == -ENODATA);
}
assert_se(sd_uid_get_state(u, &state2) == 0);
log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
}
assert_se(sd_uid_get_state(u, &state2) == 0);
log_info("sd_uid_get_state("UID_FMT", …) → %s", u, state2);
}
if (seat) {
@ -214,7 +220,7 @@ static void test_login(void) {
assert_se(sd_get_seats(NULL) == r);
r = sd_seat_get_active(NULL, &t, NULL);
assert_se(IN_SET(r, 0, -ENODATA));
assert_se(IN_SET(r, 0, -ENODATA, -ENXIO));
log_info("sd_seat_get_active(NULL, …) (active session on current seat) → %s / \"%s\"", e(r), strnull(t));
free(t);

View File

@ -532,6 +532,7 @@ int config_parse_dhcp_user_class(
for (const char *p = rvalue;;) {
_cleanup_free_ char *w = NULL;
size_t len;
r = extract_first_word(&p, &w, NULL, EXTRACT_CUNESCAPE|EXTRACT_UNQUOTE);
if (r == -ENOMEM)
@ -544,25 +545,24 @@ int config_parse_dhcp_user_class(
if (r == 0)
return 0;
len = strlen(w);
if (ltype == AF_INET) {
if (strlen(w) > UINT8_MAX) {
if (len > UINT8_MAX || len == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s length is not in the range 1-255, ignoring.", w);
continue;
}
} else {
if (strlen(w) > UINT16_MAX) {
if (len > UINT16_MAX || len == 0) {
log_syntax(unit, LOG_WARNING, filename, line, 0,
"%s length is not in the range 1-65535, ignoring.", w);
continue;
}
}
r = strv_push(l, w);
r = strv_consume(l, TAKE_PTR(w));
if (r < 0)
return log_oom();
w = NULL;
}
}

View File

@ -1452,7 +1452,7 @@ int dhcp4_configure(Link *link) {
}
if (link->network->dhcp_user_class) {
r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
r = sd_dhcp_client_set_user_class(link->dhcp_client, link->network->dhcp_user_class);
if (r < 0)
return log_link_error_errno(link, r, "DHCP4 CLIENT: Failed to set user class: %m");
}

View File

@ -38,7 +38,7 @@ static int ipv6_proxy_ndp_address_configure(Link *link, const struct in6_addr *a
if (r < 0)
return log_link_error_errno(link, r, "Could not create RTM_NEWNEIGH message: %m");
r = sd_rtnl_message_neigh_set_flags(req, NLM_F_REQUEST | NTF_PROXY);
r = sd_rtnl_message_neigh_set_flags(req, NTF_PROXY);
if (r < 0)
return log_link_error_errno(link, r, "Could not set neighbor flags: %m");

View File

@ -308,8 +308,6 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli
if (r < 0)
return r;
rule->manager = m;
r = routing_policy_rule_copy(rule, in);
if (r < 0)
return r;
@ -322,6 +320,8 @@ static int routing_policy_rule_add_internal(Manager *m, Set **rules, RoutingPoli
if (r == 0)
return -EEXIST;
rule->manager = m;
if (ret)
*ret = rule;

View File

@ -100,6 +100,10 @@ static int link_set_ipv6_privacy_extensions(Link *link) {
if (!link->network)
return 0;
// this is the special "kernel" value
if (link->network->ipv6_privacy_extensions == _IPV6_PRIVACY_EXTENSIONS_INVALID)
return 0;
return sysctl_write_ip_property_int(AF_INET6, link->ifname, "use_tempaddr", (int) link->network->ipv6_privacy_extensions);
}
@ -194,7 +198,7 @@ int link_set_sysctl(Link *link) {
r = link_set_ipv6_privacy_extensions(link);
if (r < 0)
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extension for interface, ignoring: %m");
log_link_warning_errno(link, r, "Cannot configure IPv6 privacy extensions for interface, ignoring: %m");
r = link_set_ipv6_accept_ra(link);
if (r < 0)

View File

@ -3965,6 +3965,10 @@ static int nspawn_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t r
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
if (IN_SET(n, -EAGAIN, -EINTR))
return 0;
if (n == -EXFULL) {
log_warning("Got message with truncated control data (too many fds sent?), ignoring.");
return 0;
}
if (n < 0)
return log_warning_errno(n, "Couldn't read notification socket: %m");

View File

@ -26,6 +26,7 @@ static int dns_query_candidate_new(DnsQueryCandidate **ret, DnsQuery *q, DnsScop
return -ENOMEM;
*c = (DnsQueryCandidate) {
.n_ref = 1,
.query = q,
.scope = s,
};
@ -49,8 +50,7 @@ static void dns_query_candidate_stop(DnsQueryCandidate *c) {
}
}
DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
static DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
if (!c)
return NULL;
@ -68,8 +68,10 @@ DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c) {
return mfree(c);
}
DEFINE_PUBLIC_TRIVIAL_REF_UNREF_FUNC(DnsQueryCandidate, dns_query_candidate, dns_query_candidate_free);
static int dns_query_candidate_next_search_domain(DnsQueryCandidate *c) {
DnsSearchDomain *next = NULL;
DnsSearchDomain *next;
assert(c);
@ -130,12 +132,16 @@ static int dns_query_candidate_add_transaction(DnsQueryCandidate *c, DnsResource
}
static int dns_query_candidate_go(DnsQueryCandidate *c) {
_cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *keep_c = NULL;
DnsTransaction *t;
int r;
unsigned n = 0;
assert(c);
/* Let's keep a reference to the query while we're operating */
keep_c = dns_query_candidate_ref(c);
/* Start the transactions that are not started yet */
SET_FOREACH(t, c->transactions) {
if (t->state != DNS_TRANSACTION_NULL)
@ -297,11 +303,11 @@ static void dns_query_stop(DnsQuery *q) {
dns_query_candidate_stop(c);
}
static void dns_query_free_candidates(DnsQuery *q) {
static void dns_query_unref_candidates(DnsQuery *q) {
assert(q);
while (q->candidates)
dns_query_candidate_free(q->candidates);
dns_query_candidate_unref(q->candidates);
}
static void dns_query_reset_answer(DnsQuery *q) {
@ -330,7 +336,7 @@ DnsQuery *dns_query_free(DnsQuery *q) {
LIST_REMOVE(auxiliary_queries, q->auxiliary_for->auxiliary_queries, q);
}
dns_query_free_candidates(q);
dns_query_unref_candidates(q);
dns_question_unref(q->question_idna);
dns_question_unref(q->question_utf8);
@ -505,7 +511,7 @@ static int on_query_timeout(sd_event_source *s, usec_t usec, void *userdata) {
}
static int dns_query_add_candidate(DnsQuery *q, DnsScope *s) {
_cleanup_(dns_query_candidate_freep) DnsQueryCandidate *c = NULL;
_cleanup_(dns_query_candidate_unrefp) DnsQueryCandidate *c = NULL;
int r;
assert(q);
@ -592,8 +598,8 @@ static int dns_query_try_etc_hosts(DnsQuery *q) {
assert(q);
/* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is done. The
* data from /etc/hosts hence takes precedence over the network. */
/* Looks in /etc/hosts for matching entries. Note that this is done *before* the normal lookup is
* done. The data from /etc/hosts hence takes precedence over the network. */
r = manager_etc_hosts_lookup(
q->manager,
@ -926,7 +932,7 @@ static int dns_query_cname_redirect(DnsQuery *q, const DnsResourceRecord *cname)
dns_question_unref(q->question_utf8);
q->question_utf8 = TAKE_PTR(nq_utf8);
dns_query_free_candidates(q);
dns_query_unref_candidates(q);
dns_query_reset_answer(q);
q->state = DNS_TRANSACTION_NULL;

View File

@ -16,12 +16,14 @@ typedef struct DnsStubListenerExtra DnsStubListenerExtra;
#include "resolved-dns-transaction.h"
struct DnsQueryCandidate {
unsigned n_ref;
int error_code;
DnsQuery *query;
DnsScope *scope;
DnsSearchDomain *search_domain;
int error_code;
Set *transactions;
LIST_FIELDS(DnsQueryCandidate, candidates_by_query);
@ -31,19 +33,19 @@ struct DnsQueryCandidate {
struct DnsQuery {
Manager *manager;
/* When resolving a service, we first create a TXT+SRV query,
* and then for the hostnames we discover auxiliary A+AAAA
* queries. This pointer always points from the auxiliary
* queries back to the TXT+SRV query. */
/* When resolving a service, we first create a TXT+SRV query, and then for the hostnames we discover
* auxiliary A+AAAA queries. This pointer always points from the auxiliary queries back to the
* TXT+SRV query. */
DnsQuery *auxiliary_for;
LIST_HEAD(DnsQuery, auxiliary_queries);
unsigned n_auxiliary_queries;
int auxiliary_result;
/* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note that even
* on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names (in contrast to their
* domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference between these two fields is mostly
* relevant only for explicit *hostname* lookups as well as the domain suffixes of service lookups. */
/* The question, formatted in IDNA for use on classic DNS, and as UTF8 for use in LLMNR or mDNS. Note
* that even on classic DNS some labels might use UTF8 encoding. Specifically, DNS-SD service names
* (in contrast to their domain suffixes) use UTF-8 encoding even on DNS. Thus, the difference
* between these two fields is mostly relevant only for explicit *hostname* lookups as well as the
* domain suffixes of service lookups. */
DnsQuestion *question_idna;
DnsQuestion *question_utf8;
@ -101,8 +103,9 @@ enum {
DNS_QUERY_RESTARTED,
};
DnsQueryCandidate* dns_query_candidate_free(DnsQueryCandidate *c);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_free);
DnsQueryCandidate* dns_query_candidate_ref(DnsQueryCandidate*);
DnsQueryCandidate* dns_query_candidate_unref(DnsQueryCandidate*);
DEFINE_TRIVIAL_CLEANUP_FUNC(DnsQueryCandidate*, dns_query_candidate_unref);
void dns_query_candidate_notify(DnsQueryCandidate *c);

View File

@ -1373,7 +1373,7 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
DnsTxtItem *j;
LIST_FOREACH(items, j, rr->txt.items) {
siphash24_compress(j->data, j->length, state);
siphash24_compress_safe(j->data, j->length, state);
/* Add an extra NUL byte, so that "a" followed by "b" doesn't result in the same hash as "ab"
* followed by "". */
@ -1418,14 +1418,14 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
case DNS_TYPE_SSHFP:
siphash24_compress(&rr->sshfp.algorithm, sizeof(rr->sshfp.algorithm), state);
siphash24_compress(&rr->sshfp.fptype, sizeof(rr->sshfp.fptype), state);
siphash24_compress(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
siphash24_compress_safe(rr->sshfp.fingerprint, rr->sshfp.fingerprint_size, state);
break;
case DNS_TYPE_DNSKEY:
siphash24_compress(&rr->dnskey.flags, sizeof(rr->dnskey.flags), state);
siphash24_compress(&rr->dnskey.protocol, sizeof(rr->dnskey.protocol), state);
siphash24_compress(&rr->dnskey.algorithm, sizeof(rr->dnskey.algorithm), state);
siphash24_compress(rr->dnskey.key, rr->dnskey.key_size, state);
siphash24_compress_safe(rr->dnskey.key, rr->dnskey.key_size, state);
break;
case DNS_TYPE_RRSIG:
@ -1437,7 +1437,7 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
siphash24_compress(&rr->rrsig.inception, sizeof(rr->rrsig.inception), state);
siphash24_compress(&rr->rrsig.key_tag, sizeof(rr->rrsig.key_tag), state);
dns_name_hash_func(rr->rrsig.signer, state);
siphash24_compress(rr->rrsig.signature, rr->rrsig.signature_size, state);
siphash24_compress_safe(rr->rrsig.signature, rr->rrsig.signature_size, state);
break;
case DNS_TYPE_NSEC:
@ -1451,15 +1451,15 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
siphash24_compress(&rr->ds.key_tag, sizeof(rr->ds.key_tag), state);
siphash24_compress(&rr->ds.algorithm, sizeof(rr->ds.algorithm), state);
siphash24_compress(&rr->ds.digest_type, sizeof(rr->ds.digest_type), state);
siphash24_compress(rr->ds.digest, rr->ds.digest_size, state);
siphash24_compress_safe(rr->ds.digest, rr->ds.digest_size, state);
break;
case DNS_TYPE_NSEC3:
siphash24_compress(&rr->nsec3.algorithm, sizeof(rr->nsec3.algorithm), state);
siphash24_compress(&rr->nsec3.flags, sizeof(rr->nsec3.flags), state);
siphash24_compress(&rr->nsec3.iterations, sizeof(rr->nsec3.iterations), state);
siphash24_compress(rr->nsec3.salt, rr->nsec3.salt_size, state);
siphash24_compress(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
siphash24_compress_safe(rr->nsec3.salt, rr->nsec3.salt_size, state);
siphash24_compress_safe(rr->nsec3.next_hashed_name, rr->nsec3.next_hashed_name_size, state);
/* FIXME: We leave the bitmaps out */
break;
@ -1467,18 +1467,18 @@ void dns_resource_record_hash_func(const DnsResourceRecord *rr, struct siphash *
siphash24_compress(&rr->tlsa.cert_usage, sizeof(rr->tlsa.cert_usage), state);
siphash24_compress(&rr->tlsa.selector, sizeof(rr->tlsa.selector), state);
siphash24_compress(&rr->tlsa.matching_type, sizeof(rr->tlsa.matching_type), state);
siphash24_compress(rr->tlsa.data, rr->tlsa.data_size, state);
siphash24_compress_safe(rr->tlsa.data, rr->tlsa.data_size, state);
break;
case DNS_TYPE_CAA:
siphash24_compress(&rr->caa.flags, sizeof(rr->caa.flags), state);
string_hash_func(rr->caa.tag, state);
siphash24_compress(rr->caa.value, rr->caa.value_size, state);
siphash24_compress_safe(rr->caa.value, rr->caa.value_size, state);
break;
case DNS_TYPE_OPENPGPKEY:
default:
siphash24_compress(rr->generic.data, rr->generic.data_size, state);
siphash24_compress_safe(rr->generic.data, rr->generic.data_size, state);
break;
}
}

View File

@ -105,7 +105,7 @@ DnsScope* dns_scope_free(DnsScope *s) {
dns_scope_abort_transactions(s);
while (s->query_candidates)
dns_query_candidate_free(s->query_candidates);
dns_query_candidate_unref(s->query_candidates);
hashmap_free(s->transactions_by_key);

View File

@ -152,8 +152,8 @@ bool dns_transaction_gc(DnsTransaction *t) {
static uint16_t pick_new_id(Manager *m) {
uint16_t new_id;
/* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the number of
* transactions, and it's much lower than the space of IDs. */
/* Find a fresh, unused transaction id. Note that this loop is bounded because there's a limit on the
* number of transactions, and it's much lower than the space of IDs. */
assert_cc(TRANSACTIONS_MAX < 0xFFFF);
@ -1338,6 +1338,10 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
assert(t);
/* Returns 0 if dns_transaction_complete() has been called. In that case the transaction and query
* candidate objects may have been invalidated and must not be accessed. Returns 1 if the transaction
* has been prepared. */
dns_transaction_stop_timeout(t);
if (!dns_scope_network_good(t->scope)) {
@ -1465,7 +1469,6 @@ static int dns_transaction_prepare(DnsTransaction *t, usec_t ts) {
}
static int dns_transaction_make_packet_mdns(DnsTransaction *t) {
_cleanup_(dns_packet_unrefp) DnsPacket *p = NULL;
bool add_known_answers = false;
DnsTransaction *other;
@ -1633,8 +1636,9 @@ int dns_transaction_go(DnsTransaction *t) {
assert(t);
/* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has finished
* now. */
/* Returns > 0 if the transaction is now pending, returns 0 if could be processed immediately and has
* finished now. In the latter case, the transaction and query candidate objects must not be accessed.
*/
assert_se(sd_event_now(t->scope->manager->event, clock_boottime_or_monotonic(), &ts) >= 0);
@ -1692,7 +1696,7 @@ int dns_transaction_go(DnsTransaction *t) {
t->state = DNS_TRANSACTION_PENDING;
log_debug("Delaying %s transaction for " USEC_FMT "us.", dns_protocol_to_string(t->scope->protocol), jitter);
return 0;
return 1;
}
/* Otherwise, we need to ask the network */

View File

@ -943,6 +943,10 @@ int ask_password_agent(
n = recvmsg_safe(socket_fd, &msghdr, 0);
if (IN_SET(n, -EAGAIN, -EINTR))
continue;
if (n == -EXFULL) {
log_debug("Got message with truncated control data, ignoring.");
continue;
}
if (n < 0) {
r = (int) n;
goto finish;

View File

@ -76,15 +76,18 @@ int bpf_program_load_kernel(BPFProgram *p, char *log_buf, size_t log_size) {
return 0;
}
attr = (union bpf_attr) {
.prog_type = p->prog_type,
.insns = PTR_TO_UINT64(p->instructions),
.insn_cnt = p->n_instructions,
.license = PTR_TO_UINT64("GPL"),
.log_buf = PTR_TO_UINT64(log_buf),
.log_level = !!log_buf,
.log_size = log_size,
};
// FIXME: Clang doesn't 0-pad with structured initialization, causing
// the kernel to reject the bpf_attr as invalid. See:
// https://github.com/torvalds/linux/blob/v5.9/kernel/bpf/syscall.c#L65
// Ideally it should behave like GCC, so that we can remove these workarounds.
zero(attr);
attr.prog_type = p->prog_type;
attr.insns = PTR_TO_UINT64(p->instructions);
attr.insn_cnt = p->n_instructions;
attr.license = PTR_TO_UINT64("GPL");
attr.log_buf = PTR_TO_UINT64(log_buf);
attr.log_level = !!log_buf;
attr.log_size = log_size;
p->kernel_fd = bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
if (p->kernel_fd < 0)
@ -101,9 +104,8 @@ int bpf_program_load_from_bpf_fs(BPFProgram *p, const char *path) {
if (p->kernel_fd >= 0) /* don't overwrite an assembled or loaded program */
return -EBUSY;
attr = (union bpf_attr) {
.pathname = PTR_TO_UINT64(path),
};
zero(attr);
attr.pathname = PTR_TO_UINT64(path);
p->kernel_fd = bpf(BPF_OBJ_GET, &attr, sizeof(attr));
if (p->kernel_fd < 0)
@ -158,12 +160,11 @@ int bpf_program_cgroup_attach(BPFProgram *p, int type, const char *path, uint32_
if (fd < 0)
return -errno;
attr = (union bpf_attr) {
.attach_type = type,
.target_fd = fd,
.attach_bpf_fd = p->kernel_fd,
.attach_flags = flags,
};
zero(attr);
attr.attach_type = type;
attr.target_fd = fd;
attr.attach_bpf_fd = p->kernel_fd;
attr.attach_flags = flags;
if (bpf(BPF_PROG_ATTACH, &attr, sizeof(attr)) < 0)
return -errno;
@ -194,11 +195,10 @@ int bpf_program_cgroup_detach(BPFProgram *p) {
} else {
union bpf_attr attr;
attr = (union bpf_attr) {
.attach_type = p->attached_type,
.target_fd = fd,
.attach_bpf_fd = p->kernel_fd,
};
zero(attr);
attr.attach_type = p->attached_type;
attr.target_fd = fd;
attr.attach_bpf_fd = p->kernel_fd;
if (bpf(BPF_PROG_DETACH, &attr, sizeof(attr)) < 0)
return -errno;
@ -210,15 +210,16 @@ int bpf_program_cgroup_detach(BPFProgram *p) {
}
int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size_t max_entries, uint32_t flags) {
union bpf_attr attr = {
.map_type = type,
.key_size = key_size,
.value_size = value_size,
.max_entries = max_entries,
.map_flags = flags,
};
union bpf_attr attr;
int fd;
zero(attr);
attr.map_type = type;
attr.key_size = key_size;
attr.value_size = value_size;
attr.max_entries = max_entries;
attr.map_flags = flags;
fd = bpf(BPF_MAP_CREATE, &attr, sizeof(attr));
if (fd < 0)
return -errno;
@ -227,12 +228,12 @@ int bpf_map_new(enum bpf_map_type type, size_t key_size, size_t value_size, size
}
int bpf_map_update_element(int fd, const void *key, void *value) {
union bpf_attr attr;
union bpf_attr attr = {
.map_fd = fd,
.key = PTR_TO_UINT64(key),
.value = PTR_TO_UINT64(value),
};
zero(attr);
attr.map_fd = fd;
attr.key = PTR_TO_UINT64(key);
attr.value = PTR_TO_UINT64(value);
if (bpf(BPF_MAP_UPDATE_ELEM, &attr, sizeof(attr)) < 0)
return -errno;
@ -241,12 +242,12 @@ int bpf_map_update_element(int fd, const void *key, void *value) {
}
int bpf_map_lookup_element(int fd, const void *key, void *value) {
union bpf_attr attr;
union bpf_attr attr = {
.map_fd = fd,
.key = PTR_TO_UINT64(key),
.value = PTR_TO_UINT64(value),
};
zero(attr);
attr.map_fd = fd;
attr.key = PTR_TO_UINT64(key);
attr.value = PTR_TO_UINT64(value);
if (bpf(BPF_MAP_LOOKUP_ELEM, &attr, sizeof(attr)) < 0)
return -errno;

View File

@ -9,6 +9,7 @@
#include "sd-bus.h"
#include "sd-event.h"
#include "errno-util.h"
#include "macro.h"
#include "string-util.h"
#include "time-util.h"
@ -39,13 +40,21 @@ int bus_connect_transport(BusTransport transport, const char *host, bool user, s
int bus_connect_transport_systemd(BusTransport transport, const char *host, bool user, sd_bus **bus);
#define bus_log_address_error(r) \
log_error_errno(r, \
r == -ENOMEDIUM ? "Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
"Failed to set bus address: %m")
({ \
int _k = (r); \
log_error_errno(_k, \
_k == -ENOMEDIUM ? "Failed to set bus address: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
"Failed to set bus address: %m"); \
})
#define bus_log_connect_error(r) \
log_error_errno(r, \
r == -ENOMEDIUM ? "Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined" : \
"Failed to connect to bus: %m")
({ \
int _k = (r); \
log_error_errno(_k, \
_k == -ENOMEDIUM ? "Failed to connect to bus: $DBUS_SESSION_BUS_ADDRESS and $XDG_RUNTIME_DIR not defined (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
ERRNO_IS_PRIVILEGE(_k) ? "Failed to connect to bus: Operation not permitted (consider using --machine=<user>@.host --user to connect to bus of other user)" : \
"Failed to connect to bus: %m"); \
})
#define bus_log_parse_error(r) \
log_error_errno(r, "Failed to parse bus message: %m")

View File

@ -6,6 +6,14 @@
#if HAVE_LIBCRYPTSETUP
#include <libcryptsetup.h>
/* These next two are defined in libcryptsetup.h from cryptsetup version 2.3.4 forwards. */
#ifndef CRYPT_ACTIVATE_NO_READ_WORKQUEUE
#define CRYPT_ACTIVATE_NO_READ_WORKQUEUE (1 << 24)
#endif
#ifndef CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE
#define CRYPT_ACTIVATE_NO_WRITE_WORKQUEUE (1 << 25)
#endif
extern int (*sym_crypt_activate_by_passphrase)(struct crypt_device *cd, const char *name, int keyslot, const char *passphrase, size_t passphrase_size, uint32_t flags);
#if HAVE_CRYPT_ACTIVATE_BY_SIGNED_KEY
extern int (*sym_crypt_activate_by_signed_key)(struct crypt_device *cd, const char *name, const char *volume_key, size_t volume_key_size, const char *signature, size_t signature_size, uint32_t flags);

View File

@ -2123,7 +2123,7 @@ int verity_settings_load(
}
}
if (verity->root_hash && !verity->root_hash_sig) {
if ((root_hash || verity->root_hash) && !verity->root_hash_sig) {
if (root_hash_sig_path) {
r = read_full_file_full(AT_FDCWD, root_hash_sig_path, 0, NULL, (char**) &root_hash_sig, &root_hash_sig_size);
if (r < 0 && r != -ENOENT)

View File

@ -1277,7 +1277,7 @@ int dns_name_apply_idna(const char *name, char **ret) {
int r;
r = dlopen_idn();
if (r == EOPNOTSUPP) {
if (r == -EOPNOTSUPP) {
*ret = NULL;
return 0;
}

View File

@ -334,6 +334,16 @@ int journal_importer_process_data(JournalImporter *imp) {
if (r < 0)
return r;
} else {
if (!journal_field_valid(line, n - 1, true)) {
char buf[64], *t;
t = strndupa(line, n - 1);
log_debug("Ignoring invalid field: \"%s\"",
cellescape(buf, sizeof buf, t));
return 0;
}
/* replace \n with = */
line[n-1] = '=';

View File

@ -137,41 +137,3 @@ int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_use
return r;
}
bool journal_field_valid(const char *p, size_t l, bool allow_protected) {
const char *a;
/* We kinda enforce POSIX syntax recommendations for
environment variables here, but make a couple of additional
requirements.
http://pubs.opengroup.org/onlinepubs/000095399/basedefs/xbd_chap08.html */
if (l == (size_t) -1)
l = strlen(p);
/* No empty field names */
if (l <= 0)
return false;
/* Don't allow names longer than 64 chars */
if (l > 64)
return false;
/* Variables starting with an underscore are protected */
if (!allow_protected && p[0] == '_')
return false;
/* Don't allow digits as first character */
if (p[0] >= '0' && p[0] <= '9')
return false;
/* Only allow A-Z0-9 and '_' */
for (a = p; a < p + l; a++)
if ((*a < 'A' || *a > 'Z') &&
(*a < '0' || *a > '9') &&
*a != '_')
return false;
return true;
}

View File

@ -6,6 +6,5 @@
#include "sd-journal.h"
bool journal_field_valid(const char *p, size_t l, bool allow_protected);
int journal_access_blocked(sd_journal *j);
int journal_access_check_and_warn(sd_journal *j, bool quiet, bool want_other_users);

View File

@ -702,9 +702,11 @@ static int output_verbose(
c = memchr(data, '=', length);
if (!c)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid field.");
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid field.");
fieldlen = c - (const char*) data;
if (!journal_field_valid(data, fieldlen, true))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid field.");
r = field_set_test(output_fields, data, fieldlen);
if (r < 0)
@ -798,6 +800,7 @@ static int output_export(
sd_id128_to_string(boot_id, sid));
JOURNAL_FOREACH_DATA_RETVAL(j, data, length, r) {
size_t fieldlen;
const char *c;
/* We already printed the boot id from the data in the header, hence let's suppress it here */
@ -806,10 +809,13 @@ static int output_export(
c = memchr(data, '=', length);
if (!c)
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Invalid field.");
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid field.");
r = field_set_test(output_fields, data, c - (const char *) data);
fieldlen = c - (const char*) data;
if (!journal_field_valid(data, fieldlen, true))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid field.");
r = field_set_test(output_fields, data, fieldlen);
if (r < 0)
return r;
if (!r)
@ -820,11 +826,11 @@ static int output_export(
else {
uint64_t le64;
fwrite(data, c - (const char*) data, 1, f);
fwrite(data, fieldlen, 1, f);
fputc('\n', f);
le64 = htole64(length - (c - (const char*) data) - 1);
le64 = htole64(length - fieldlen - 1);
fwrite(&le64, sizeof(le64), 1, f);
fwrite(c + 1, length - (c - (const char*) data) - 1, 1, f);
fwrite(c + 1, length - fieldlen - 1, 1, f);
}
fputc('\n', f);
@ -961,6 +967,7 @@ static int update_json_data_split(
const void *data,
size_t size) {
size_t fieldlen;
const char *eq;
char *name;
@ -974,14 +981,15 @@ static int update_json_data_split(
if (!eq)
return 0;
if (eq == data)
return 0;
fieldlen = eq - (const char*) data;
if (!journal_field_valid(data, fieldlen, true))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Invalid field.");
name = strndupa(data, eq - (const char*) data);
name = strndupa(data, fieldlen);
if (output_fields && !set_contains(output_fields, name))
return 0;
return update_json_data(h, flags, name, eq + 1, size - (eq - (const char*) data) - 1);
return update_json_data(h, flags, name, eq + 1, size - fieldlen - 1);
}
static int output_json(

View File

@ -1,12 +1,6 @@
/* SPDX-License-Identifier: LGPL-2.1-or-later */
#include <net/ethernet.h>
#include <linux/nl80211.h>
#include "sd-bus.h"
#include "log.h"
#include "netlink-util.h"
#include "wifi-util.h"
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid) {
@ -35,8 +29,10 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
}
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi interface %d: %m", ifindex);
if (!reply)
if (!reply) {
log_debug_errno(r, "No reply received to request for information about wifi interface %d, ignoring.", ifindex);
goto nodata;
}
r = sd_netlink_message_get_errno(reply);
if (r < 0)
@ -62,8 +58,8 @@ int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftyp
if (ssid) {
r = sd_netlink_message_read_string_strdup(reply, NL80211_ATTR_SSID, ssid);
if (r == -ENODATA)
goto nodata;
if (r < 0)
*ssid = NULL;
else if (r < 0)
return log_debug_errno(r, "Failed to get NL80211_ATTR_SSID attribute: %m");
}
@ -101,8 +97,10 @@ int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid) {
r = sd_netlink_call(genl, m, 0, &reply);
if (r < 0)
return log_debug_errno(r, "Failed to request information about wifi station: %m");
if (!reply)
if (!reply) {
log_debug_errno(r, "No reply received to request for information about wifi station, ignoring.");
goto nodata;
}
r = sd_netlink_message_get_errno(reply);
if (r < 0)

View File

@ -3,8 +3,9 @@
#pragma once
#include <linux/nl80211.h>
#include <net/ethernet.h>
#include "netlink-util.h"
#include "sd-netlink.h"
int wifi_get_interface(sd_netlink *genl, int ifindex, enum nl80211_iftype *iftype, char **ssid);
int wifi_get_station(sd_netlink *genl, int ifindex, struct ether_addr *bssid);

View File

@ -398,16 +398,14 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
/* If loading of the unit failed server side complete, then the server won't tell us
* the unit file path. In that case, find the file client side. */
log_debug_errno(r, "Unit '%s' was not loaded correctly, retrying client-side.", *name);
r = unit_find_paths(bus, *name, &lp, true, &cached_name_map, &cached_id_map, &path, NULL);
r = unit_find_paths(bus, *name, &lp, true, &cached_name_map, &cached_id_map, &path, &unit_paths);
}
if (r == -ERFKILL)
return log_error_errno(r, "Unit '%s' masked, cannot edit.", *name);
if (r < 0)
return r;
if (r == 0) {
assert(!path);
if (!path) {
if (!arg_force) {
log_info("Run 'systemctl edit%s --force --full %s' to create a new unit.",
arg_scope == UNIT_FILE_GLOBAL ? " --global" :
@ -422,8 +420,6 @@ static int find_paths_to_edit(sd_bus *bus, char **names, char ***paths) {
arg_full ? NULL : ".d/override.conf",
NULL, &new_path, &tmp_path);
} else {
assert(path);
unit_name = basename(path);
/* We follow unit aliases, but we need to propagate the instance */
if (unit_name_is_valid(*name, UNIT_NAME_INSTANCE) &&

View File

@ -120,7 +120,7 @@ int unit_is_enabled(int argc, char *argv[], void *userdata) {
if (r < 0)
return bus_log_parse_error(r);
if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "indirect", "generated"))
if (STR_IN_SET(s, "enabled", "enabled-runtime", "static", "alias", "indirect", "generated"))
enabled = true;
if (!arg_quiet) {

View File

@ -127,6 +127,12 @@ int import_environment(int argc, char *argv[], void *userdata) {
strv_env_clean_with_callback(copy, invalid_callback, NULL);
char **e;
STRV_FOREACH(e, copy)
if (string_has_cc(*e, NULL))
log_notice("Environment variable $%.*s contains control characters, importing anyway.",
(int) strcspn(*e, "="), *e);
r = sd_bus_message_append_strv(m, copy);
} else {
@ -139,21 +145,30 @@ int import_environment(int argc, char *argv[], void *userdata) {
STRV_FOREACH(a, strv_skip(argv, 1)) {
if (!env_name_is_valid(*a))
return log_error_errno(SYNTHETIC_ERRNO(EINVAL), "Not a valid environment variable name: %s", *a);
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
"Not a valid environment variable name: %s", *a);
bool found = false;
STRV_FOREACH(b, environ) {
const char *eq;
eq = startswith(*b, *a);
if (eq && *eq == '=') {
if (string_has_cc(eq + 1, NULL))
log_notice("Environment variable $%.*s contains control characters, importing anyway.",
(int) (eq - *b), *b);
r = sd_bus_message_append(m, "s", *b);
if (r < 0)
return bus_log_create_error(r);
found = true;
break;
}
}
if (!found)
log_notice("Environment variable $%s not set, ignoring.", *a);
}
r = sd_bus_message_close_container(m);

View File

@ -16,7 +16,7 @@
#include "hexdecoct.h"
#include "hostname-util.h"
#include "in-addr-util.h"
#include "journal-util.h"
#include "journal-file.h"
#include "list.h"
#include "locale-util.h"
#include "memory-util.h"

View File

@ -179,7 +179,7 @@ int sd_dhcp_client_set_mud_url(
const char *mudurl);
int sd_dhcp_client_set_user_class(
sd_dhcp_client *client,
const char* const *user_class);
char * const *user_class);
int sd_dhcp_client_get_lease(
sd_dhcp_client *client,
sd_dhcp_lease **ret);

View File

@ -133,10 +133,10 @@ int sd_dhcp6_client_set_request_mud_url(
const char *mudurl);
int sd_dhcp6_client_set_request_user_class(
sd_dhcp6_client *client,
char** user_class);
char * const *user_class);
int sd_dhcp6_client_set_request_vendor_class(
sd_dhcp6_client *client,
char** vendor_class);
char * const *vendor_class);
int sd_dhcp6_client_set_prefix_delegation_hint(
sd_dhcp6_client *client,
uint8_t prefixlen,

View File

@ -15,6 +15,7 @@
#include "hashmap.h"
#include "main-func.h"
#include "mount-util.h"
#include "nscd-flush.h"
#include "pager.h"
#include "path-util.h"
#include "pretty-print.h"
@ -798,6 +799,9 @@ static int write_files(void) {
return r;
group_tmp = mfree(group_tmp);
if (!arg_root && !arg_image)
(void) nscd_flush_cache(STRV_MAKE("group"));
}
if (gshadow) {
r = rename_and_apply_smack_floor_label(gshadow_tmp, gshadow_path);
@ -813,6 +817,9 @@ static int write_files(void) {
return r;
passwd_tmp = mfree(passwd_tmp);
if (!arg_root && !arg_image)
(void) nscd_flush_cache(STRV_MAKE("passwd"));
}
if (shadow) {
r = rename_and_apply_smack_floor_label(shadow_tmp, shadow_path);

View File

@ -8,6 +8,7 @@
#include "bpf-program.h"
#include "load-fragment.h"
#include "manager.h"
#include "memory-util.h"
#include "rm-rf.h"
#include "service.h"
#include "tests.h"
@ -77,11 +78,10 @@ int main(int argc, char *argv[]) {
assert(r >= 0);
if (test_custom_filter) {
attr = (union bpf_attr) {
.pathname = PTR_TO_UINT64(test_prog),
.bpf_fd = p->kernel_fd,
.file_flags = 0,
};
zero(attr);
attr.pathname = PTR_TO_UINT64(test_prog);
attr.bpf_fd = p->kernel_fd;
attr.file_flags = 0;
(void) unlink(test_prog);

View File

@ -265,6 +265,7 @@ static void test_env_clean(void) {
"another=one",
"another=final one",
"CRLF=\r\n",
"LESS_TERMCAP_mb=\x1b[01;31m",
"BASH_FUNC_foo%%=() { echo foo\n}");
assert_se(e);
assert_se(!strv_env_is_valid(e));
@ -277,7 +278,9 @@ static void test_env_clean(void) {
assert_se(streq(e[3], "abcd=äöüß"));
assert_se(streq(e[4], "xyz=xyz\n"));
assert_se(streq(e[5], "another=final one"));
assert_se(e[6] == NULL);
assert_se(streq(e[6], "CRLF=\r\n"));
assert_se(streq(e[7], "LESS_TERMCAP_mb=\x1b[01;31m"));
assert_se(e[8] == NULL);
}
static void test_env_name_is_valid(void) {
@ -302,8 +305,11 @@ static void test_env_value_is_valid(void) {
assert_se(env_value_is_valid("printf \"\\x1b]0;<mock-chroot>\\x07<mock-chroot>\""));
assert_se(env_value_is_valid("tab\tcharacter"));
assert_se(env_value_is_valid("new\nline"));
assert_se(!env_value_is_valid("Show this?\rNope. Show that!"));
assert_se(!env_value_is_valid("new DOS\r\nline"));
assert_se(env_value_is_valid("Show this?\rNope. Show that!"));
assert_se(env_value_is_valid("new DOS\r\nline"));
assert_se(!env_value_is_valid("\xc5")); /* A truncated utf-8-encoded "ł".
* We currently disallow that. */
}
static void test_env_assignment_is_valid(void) {

View File

@ -256,6 +256,37 @@ static void test_path_is_mount_point(void) {
assert_se(rm_rf(tmp_dir, REMOVE_ROOT|REMOVE_PHYSICAL) == 0);
}
static void test_fd_is_mount_point(void) {
_cleanup_close_ int fd = -1;
log_info("/* %s */", __func__);
fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
assert_se(fd >= 0);
/* Not allowed, since "/" is a path, not a plain filename */
assert_se(fd_is_mount_point(fd, "/", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, ".", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "./", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "..", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "../", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "/proc", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "/proc/", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "proc/sys", 0) == -EINVAL);
assert_se(fd_is_mount_point(fd, "proc/sys/", 0) == -EINVAL);
/* This one definitely is a mount point */
assert_se(fd_is_mount_point(fd, "proc", 0) > 0);
assert_se(fd_is_mount_point(fd, "proc/", 0) > 0);
/* /root's entire raison d'etre is to be on the root file system (i.e. not in /home/ which might be
* split off), so that the user can always log in, so it cannot be a mount point unless the system is
* borked. Let's allow for it to be missing though. */
assert_se(IN_SET(fd_is_mount_point(fd, "root", 0), -ENOENT, 0));
assert_se(IN_SET(fd_is_mount_point(fd, "root/", 0), -ENOENT, 0));
}
int main(int argc, char *argv[]) {
test_setup_logging(LOG_DEBUG);
@ -279,6 +310,7 @@ int main(int argc, char *argv[]) {
test_mnt_id();
test_path_is_mount_point();
test_fd_is_mount_point();
return 0;
}

View File

@ -6,7 +6,6 @@
#include "alloc-util.h"
#include "fd-util.h"
#include "macro.h"
#include "mountpoint-util.h"
#include "path-util.h"
#include "rm-rf.h"
#include "stat-util.h"
@ -40,8 +39,6 @@ static void test_path_simplify(const char *in, const char *out, const char *out_
}
static void test_path(void) {
_cleanup_close_ int fd = -1;
log_info("/* %s */", __func__);
test_path_compare("/goo", "/goo", 0);
@ -80,10 +77,6 @@ static void test_path(void) {
assert_se(streq(basename("/aa///file..."), "file..."));
assert_se(streq(basename("file.../"), ""));
fd = open("/", O_RDONLY|O_CLOEXEC|O_DIRECTORY|O_NOCTTY);
assert_se(fd >= 0);
assert_se(fd_is_mount_point(fd, "/", 0) > 0);
test_path_simplify("aaa/bbb////ccc", "aaa/bbb/ccc", "aaa/bbb/ccc");
test_path_simplify("//aaa/.////ccc", "/aaa/./ccc", "/aaa/ccc");
test_path_simplify("///", "/", "/");

View File

@ -150,6 +150,83 @@ static void test_set_ensure_consume(void) {
assert_se(set_size(m) == 2);
}
static void test_set_strjoin(void) {
_cleanup_set_free_ Set *m = NULL;
_cleanup_free_ char *joined = NULL;
/* Empty set */
assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, "", false, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, " ", false, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, "", true, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, " ", true, &joined) >= 0);
assert_se(!joined);
assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
assert_se(!joined);
/* Single entry */
assert_se(set_put_strdup(&m, "aaa") == 1);
assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "", false, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, " ", false, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "", true, &joined) >= 0);
assert_se(streq(joined, "aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, " ", true, &joined) >= 0);
assert_se(streq(joined, " aaa "));
joined = mfree(joined);
assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
assert_se(streq(joined, "xxxaaaxxx"));
/* Two entries */
assert_se(set_put_strdup(&m, "bbb") == 1);
assert_se(set_put_strdup(&m, "aaa") == 0);
joined = mfree(joined);
assert_se(set_strjoin(m, NULL, false, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "", false, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, " ", false, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaa bbb", "bbb aaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "xxx", false, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaaxxxbbb", "bbbxxxaaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, NULL, true, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, "", true, &joined) >= 0);
assert_se(STR_IN_SET(joined, "aaabbb", "bbbaaa"));
joined = mfree(joined);
assert_se(set_strjoin(m, " ", true, &joined) >= 0);
assert_se(STR_IN_SET(joined, " aaa bbb ", " bbb aaa "));
joined = mfree(joined);
assert_se(set_strjoin(m, "xxx", true, &joined) >= 0);
assert_se(STR_IN_SET(joined, "xxxaaaxxxbbbxxx", "xxxbbbxxxaaaxxx"));
}
int main(int argc, const char *argv[]) {
test_set_steal_first();
test_set_free_with_destructor();
@ -160,6 +237,7 @@ int main(int argc, const char *argv[]) {
test_set_ensure_allocated();
test_set_ensure_put();
test_set_ensure_consume();
test_set_strjoin();
return 0;
}

View File

@ -28,7 +28,7 @@ static void test_fgetxattrat_fake(void) {
assert_se(touch(x) >= 0);
r = setxattr(x, "user.foo", "bar", 3, 0);
if (r < 0 && errno == EOPNOTSUPP) /* no xattrs supported on /var/tmp... */
if (r < 0 && ERRNO_IS_NOT_SUPPORTED(errno)) /* no xattrs supported on /var/tmp... */
goto cleanup;
assert_se(r >= 0);
@ -42,7 +42,8 @@ static void test_fgetxattrat_fake(void) {
safe_close(fd);
fd = open("/", O_RDONLY|O_DIRECTORY|O_CLOEXEC|O_NOCTTY);
assert_se(fd >= 0);
assert_se(fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0, &size) == -ENODATA);
r = fgetxattrat_fake(fd, "usr", "user.idontexist", v, 3, 0, &size);
assert_se(r == -ENODATA || ERRNO_IS_NOT_SUPPORTED(r));
cleanup:
assert_se(unlink(x) >= 0);

View File

@ -771,7 +771,7 @@ static int method_set_local_rtc(sd_bus_message *m, void *userdata, sd_bus_error
log_debug_errno(r, "Failed to get hardware clock, ignoring: %m");
else {
/* And set the system clock with this */
mktime_or_timegm(&tm, !c->local_rtc);
ts.tv_sec = mktime_or_timegm(&tm, !c->local_rtc);
if (clock_settime(CLOCK_REALTIME, &ts) < 0)
log_debug_errno(errno, "Failed to update system clock, ignoring: %m");

View File

@ -194,7 +194,7 @@ static int link_find_prioritized(sd_device *dev, bool add, const char *stackdir,
/* manage "stack of names" with possibly specified device priorities */
static int link_update(sd_device *dev, const char *slink, bool add) {
_cleanup_free_ char *target = NULL, *filename = NULL, *dirname = NULL;
_cleanup_free_ char *filename = NULL, *dirname = NULL;
char name_enc[PATH_MAX];
const char *id_filename;
int i, r, retries;
@ -237,6 +237,7 @@ static int link_update(sd_device *dev, const char *slink, bool add) {
retries = sd_device_get_is_initialized(dev) > 0 ? LINK_UPDATE_MAX_RETRIES : 1;
for (i = 0; i < retries; i++) {
_cleanup_free_ char *target = NULL;
struct stat st1 = {}, st2 = {};
r = stat(dirname, &st1);

View File

@ -3,7 +3,11 @@ set -e
TEST_DESCRIPTION="test MUMAPolicy= and NUMAMask= options"
TEST_NO_NSPAWN=1
QEMU_OPTIONS="-numa node,nodeid=0"
. $TEST_BASE_DIR/test-functions
if qemu_min_version "5.2.0"; then
QEMU_OPTIONS="-object memory-backend-ram,id=mem0,size=512M -numa node,memdev=mem0,nodeid=0"
else
QEMU_OPTIONS="-numa node,nodeid=0"
fi
do_test "$@" 36

Binary file not shown.

Binary file not shown.

View File

@ -227,6 +227,24 @@ function find_qemu_bin() {
fi
}
# Compares argument #1=X.Y.Z (X&Y&Z = numeric) to the version of the installed qemu
# returns 0 if newer or equal
# returns 1 if older
# returns 2 if failing
function qemu_min_version() {
find_qemu_bin || return 2
# get version from binary
qemu_ver=$($QEMU_BIN --version | awk '/^QEMU emulator version ([0-9]*\.[0-9]*\.[0-9]*) / {print $4}')
# Check version string format
echo "$qemu_ver" | grep -q '^[0-9]*\.[0-9]*\.[0-9]*$' || return 2
echo "$1" | grep -q '^[0-9]*\.[0-9]*\.[0-9]*$' || return 2
# compare as last command to return that value
printf "%s\n%s\n" "$1" "$qemu_ver" | sort -V -C
}
# Return 0 if QEMU did run (then you must check the result state/logs for actual
# success), or 1 if QEMU is not available.
run_qemu() {

View File

@ -18,6 +18,11 @@ try:
except ImportError as e:
shlex_join = e
try:
from shlex import quote as shlex_quote
except ImportError as e:
shlex_quote = e
class NoCommand(Exception):
pass
@ -186,10 +191,13 @@ def subst_output(document, programlisting, stats):
interface = programlisting.get('interface')
argv = [f'{opts.build_dir}/{executable}', f'--bus-introspect={interface}']
print(f'COMMAND: {shlex_join(argv)}')
if isinstance(shlex_join, Exception):
print(f'COMMAND: {" ".join(shlex_quote(arg) for arg in argv)}')
else:
print(f'COMMAND: {shlex_join(argv)}')
try:
out = subprocess.check_output(argv, text=True)
out = subprocess.check_output(argv, universal_newlines=True)
except FileNotFoundError:
print(f'{executable} not found, ignoring', file=sys.stderr)
return
@ -296,7 +304,7 @@ def parse_args():
if __name__ == '__main__':
opts = parse_args()
for item in (etree, shlex_join):
for item in (etree, shlex_quote):
if isinstance(item, Exception):
print(item, file=sys.stderr)
exit(77 if opts.test else 1)
@ -308,7 +316,7 @@ if __name__ == '__main__':
# Let's print all statistics at the end
mlen = max(len(page) for page in stats)
total = sum((item['stats'] for item in stats.values()), start=collections.Counter())
total = sum((item['stats'] for item in stats.values()), collections.Counter())
total = 'total', dict(stats=total, outdated=False)
outdated = []
for page, info in sorted(stats.items()) + [total]: