mirror of
https://git.proxmox.com/git/systemd
synced 2025-06-03 01:10:41 +00:00
New upstream version 245.6
This commit is contained in:
parent
d0648cfe4f
commit
20a6e51f0f
3
NEWS
3
NEWS
@ -805,6 +805,9 @@ CHANGES WITH 243:
|
||||
* systemd-networkd's TUN support gained a new setting VnetHeader= for
|
||||
tweaking Generic Segment Offload support.
|
||||
|
||||
* The address family for policy rules may be specified using the new
|
||||
Family= option in the [RoutingPolicyRule] section.
|
||||
|
||||
* networkctl gained a new "delete" command for removing virtual network
|
||||
devices, as well as a new "--stats" switch for showing device
|
||||
statistics.
|
||||
|
3
TODO
3
TODO
@ -446,9 +446,6 @@ Features:
|
||||
|
||||
* support projid-based quota in machinectl for containers
|
||||
|
||||
* maybe use SOURCE_DATE_EPOCH (i.e. the env var the reproducible builds folks
|
||||
introduced) as the RTC epoch, instead of the mtime of NEWS.
|
||||
|
||||
* add a way to lock down cgroup migration: a boolean, which when set for a unit
|
||||
makes sure the processes in it can never migrate out of it
|
||||
|
||||
|
@ -1,9 +1,5 @@
|
||||
<?xml version='1.0'?> <!--*-nxml-*-->
|
||||
|
||||
<!--
|
||||
SPDX-License-Identifier: LGPL-2.1+
|
||||
|
||||
-->
|
||||
<!-- SPDX-License-Identifier: LGPL-2.1+ -->
|
||||
|
||||
<xsl:stylesheet xmlns:xsl="http://www.w3.org/1999/XSL/Transform" version="1.0">
|
||||
|
||||
@ -96,6 +92,21 @@
|
||||
</a>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="citerefentry[@project='debian']">
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
<xsl:text>https://manpages.debian.org/unstable/</xsl:text>
|
||||
<xsl:value-of select="refentrytitle"/>
|
||||
<xsl:text>/</xsl:text>
|
||||
<xsl:value-of select="refentrytitle"/>
|
||||
<xsl:text>.</xsl:text>
|
||||
<xsl:value-of select="manvolnum"/>
|
||||
<xsl:text>.en.html</xsl:text>
|
||||
</xsl:attribute>
|
||||
<xsl:call-template name="inline.charseq"/>
|
||||
</a>
|
||||
</xsl:template>
|
||||
|
||||
<xsl:template match="citerefentry[@project='freebsd']">
|
||||
<a>
|
||||
<xsl:attribute name="href">
|
||||
|
@ -140,7 +140,7 @@
|
||||
<literal>us</literal>. To turn off any kind of rate limiting,
|
||||
set either value to 0.</para>
|
||||
|
||||
<para>Note that the effective rate limit is multiplied with a
|
||||
<para>Note that the effective rate limit is multiplied by a
|
||||
factor derived from the available free disk space for the journal.
|
||||
Currently, this factor is calculated using the base 2 logarithm.</para>
|
||||
|
||||
@ -402,6 +402,18 @@
|
||||
this option is enabled by default, it is disabled in all others.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>Audit=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean value. If enabled <command>systemd-journal</command> will turn on
|
||||
kernel auditing on start-up. If disabled it will turn it off. If unset it will neither enable nor
|
||||
disable it, leaving the previous state unchanged. Note that this option does not control whether
|
||||
<command>systemd-journald</command> collects generated audit records, it just controls whether it
|
||||
tells the kernel to generate them. This means if another tool turns on auditing even if
|
||||
<command>systemd-journald</command> left it off, it will still collect the generated
|
||||
messages. Defaults to on.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>TTYPath=</varname></term>
|
||||
|
||||
|
@ -259,31 +259,31 @@
|
||||
|
||||
<variablelist class='pam-directives'>
|
||||
<varlistentry>
|
||||
<term><varname>systemd.memory_max</varname></term>
|
||||
<term><varname>systemd.memory_max=</varname></term>
|
||||
|
||||
<listitem><para>Sets unit <varname>MemoryMax=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.tasks_max</varname></term>
|
||||
<term><varname>systemd.tasks_max=</varname></term>
|
||||
|
||||
<listitem><para>Sets unit <varname>TasksMax=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.cpu_weight</varname></term>
|
||||
<term><varname>systemd.cpu_weight=</varname></term>
|
||||
|
||||
<listitem><para>Sets unit <varname>CPUWeight=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.io_weight</varname></term>
|
||||
<term><varname>systemd.io_weight=</varname></term>
|
||||
|
||||
<listitem><para>Sets unit <varname>IOWeight=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>systemd.runtime_max_sec</varname></term>
|
||||
<term><varname>systemd.runtime_max_sec=</varname></term>
|
||||
|
||||
<listitem><para>Sets unit <varname>RuntimeMaxSec=</varname>.</para></listitem>
|
||||
</varlistentry>
|
||||
@ -308,19 +308,24 @@ pam_set_data(handle, "systemd.runtime_max_sec", (void *)"3600", cleanup);
|
||||
<filename>systemd-logind.service</filename>:</para>
|
||||
|
||||
<programlisting>#%PAM-1.0
|
||||
auth sufficient pam_unix.so
|
||||
auth required pam_deny.so
|
||||
auth sufficient pam_unix.so
|
||||
-auth sufficient pam_systemd_home.so
|
||||
auth required pam_deny.so
|
||||
|
||||
account required pam_nologin.so
|
||||
account sufficient pam_unix.so
|
||||
account required pam_permit.so
|
||||
account required pam_nologin.so
|
||||
-account sufficient pam_systemd_home.so
|
||||
account sufficient pam_unix.so
|
||||
account required pam_permit.so
|
||||
|
||||
password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
|
||||
password required pam_deny.so
|
||||
-password sufficient pam_systemd_home.so
|
||||
password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
|
||||
password required pam_deny.so
|
||||
|
||||
-session optional pam_loginuid.so
|
||||
-session optional pam_systemd.so
|
||||
session required pam_unix.so</programlisting>
|
||||
-session optional pam_keyinit.so revoke
|
||||
-session optional pam_loginuid.so
|
||||
-session optional pam_systemd_home.so
|
||||
<command>-session optional pam_systemd.so</command>
|
||||
session required pam_unix.so</programlisting>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -95,21 +95,21 @@
|
||||
|
||||
<programlisting>#%PAM-1.0
|
||||
auth sufficient pam_unix.so
|
||||
-auth sufficient pam_systemd_home.so
|
||||
<command>-auth sufficient pam_systemd_home.so</command>
|
||||
auth required pam_deny.so
|
||||
|
||||
account required pam_nologin.so
|
||||
-account sufficient pam_systemd_home.so
|
||||
<command>-account sufficient pam_systemd_home.so</command>
|
||||
account sufficient pam_unix.so
|
||||
account required pam_permit.so
|
||||
|
||||
-password sufficient pam_systemd_home.so
|
||||
<command>-password sufficient pam_systemd_home.so</command>
|
||||
password sufficient pam_unix.so sha512 shadow try_first_pass try_authtok
|
||||
password required pam_deny.so
|
||||
|
||||
-session optional pam_keyinit.so revoke
|
||||
-session optional pam_loginuid.so
|
||||
-session optional pam_systemd_home.so
|
||||
<command>-session optional pam_systemd_home.so</command>
|
||||
-session optional pam_systemd.so
|
||||
session required pam_unix.so</programlisting>
|
||||
</refsect1>
|
||||
|
@ -288,17 +288,27 @@
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
<title>Compatibility with <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry></title>
|
||||
<title>Compatibility with
|
||||
<citerefentry project="debian"><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry></title>
|
||||
|
||||
<para><command>resolvectl</command> is a multi-call binary. When invoked as <literal>resolvconf</literal>
|
||||
(generally achieved by means of a symbolic link of this name to the <command>resolvectl</command> binary) it
|
||||
is run in a limited <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
is run in a limited
|
||||
<citerefentry project="debian"><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
compatibility mode. It accepts mostly the same arguments and pushes all data into
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
|
||||
similar to how <option>dns</option> and <option>domain</option> commands operate. Note that
|
||||
<command>systemd-resolved.service</command> is the only supported backend, which is different from other
|
||||
implementations of this command. Note that not all operations supported by other implementations are supported
|
||||
natively. Specifically:</para>
|
||||
implementations of this command.</para>
|
||||
|
||||
<para><filename>/etc/resolv.conf</filename> will only be updated with servers added with this command
|
||||
when <filename>/etc/resolv.conf</filename> is a symlink to
|
||||
<filename>/run/systemd/resolve/resolv.conf</filename>, and not a static file. See the discussion of
|
||||
<filename>/etc/resolv.conf</filename> handling in
|
||||
<citerefentry><refentrytitle>systemd-resolved.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.
|
||||
</para>
|
||||
|
||||
<para>Not all operations supported by other implementations are supported natively. Specifically:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
@ -359,7 +369,9 @@
|
||||
|
||||
</variablelist>
|
||||
|
||||
<para>See <citerefentry><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry> for details on this command line options.</para>
|
||||
<para>See
|
||||
<citerefentry project="debian"><refentrytitle>resolvconf</refentrytitle><manvolnum>8</manvolnum></citerefentry>
|
||||
for details on those command line options.</para>
|
||||
</refsect1>
|
||||
|
||||
<refsect1>
|
||||
|
@ -70,10 +70,9 @@
|
||||
|
||||
<para>These prefixes are intended to be used in conjunction with stderr-based logging (or stdout-based
|
||||
logging) as implemented by systemd. If a systemd service definition file is configured with
|
||||
<varname>StandardError=journal</varname>, <varname>StandardError=syslog</varname> or
|
||||
<varname>StandardError=kmsg</varname> (and similar with <varname>StandardOutput=</varname>), these
|
||||
prefixes can be used to encode a log level in lines printed. This is similar to the kernel
|
||||
<function>printk()</function>-style logging. See
|
||||
<varname>StandardError=journal</varname> or <varname>StandardError=kmsg</varname> (and similar with
|
||||
<varname>StandardOutput=</varname>), these prefixes can be used to encode a log level in lines
|
||||
printed. This is similar to the kernel <function>printk()</function>-style logging. See
|
||||
<citerefentry><refentrytitle>klogctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> for more
|
||||
information.</para>
|
||||
|
||||
|
@ -34,7 +34,7 @@
|
||||
<funcdef>int sd_bus_message_append_array</funcdef>
|
||||
<paramdef>sd_bus_message *<parameter>m</parameter></paramdef>
|
||||
<paramdef>char <parameter>type</parameter></paramdef>
|
||||
<paramdef>char void *<parameter>ptr</parameter></paramdef>
|
||||
<paramdef>void *<parameter>ptr</parameter></paramdef>
|
||||
<paramdef>size_t <parameter>size</parameter></paramdef>
|
||||
</funcprototype>
|
||||
|
||||
|
@ -159,7 +159,7 @@ net.bridge.bridge-nf-call-arptables = 0
|
||||
|
||||
<example>
|
||||
<title>Set network routing properties for all interfaces</title>
|
||||
<para><filename>/etc/systemd/20-rp_filter.conf</filename>:</para>
|
||||
<para><filename>/etc/sysctl.d/20-rp_filter.conf</filename>:</para>
|
||||
|
||||
<programlisting>net.ipv4.conf.default.rp_filter = 2
|
||||
net.ipv4.conf.*.rp_filter = 2
|
||||
|
@ -41,6 +41,14 @@
|
||||
|
||||
<refsect1><title>Options</title>
|
||||
<variablelist>
|
||||
|
||||
<varlistentry>
|
||||
<term><option>--unregister</option></term>
|
||||
<listitem><para>If passed, instead of registering configured binary formats in the kernel, the
|
||||
reverse operation is executed: all currently registered binary formats are unregistered from the
|
||||
kernel.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<xi:include href="standard-options.xml" xpointer="cat-config" />
|
||||
<xi:include href="standard-options.xml" xpointer="no-pager" />
|
||||
<xi:include href="standard-options.xml" xpointer="help" />
|
||||
|
@ -175,8 +175,8 @@
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>The following keys may be used during bootup or in the boot menu to
|
||||
directly boot a specific entry:</para>
|
||||
<para>The following keys may be pressed during bootup or in the boot menu to directly boot a specific
|
||||
entry:</para>
|
||||
|
||||
<variablelist>
|
||||
<varlistentry>
|
||||
@ -213,6 +213,17 @@
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>The boot menu is shown when a non-zero menu timeout has been configured. If the menu timeout has
|
||||
been set to zero, it is sufficient to press any key — before the boot loader initializes — to bring up
|
||||
the boot menu, except for the keys listed immediately above as they directly boot into the selected boot
|
||||
menu item. Note that depending on the firmware implementation the time window where key presses are
|
||||
accepted before the boot loader initializes might be short. If the window is missed, reboot and try
|
||||
again, possibly pressing a suitable key (e.g. the space bar) continuously; on most systems it should be
|
||||
possible to hit the time window after a few attempts. To avoid this problem, consider setting a non-zero
|
||||
timeout, thus showing the boot menu unconditionally. Some desktop environments might offer an option to
|
||||
directly boot into the boot menu, to avoid the problem altogether. Alternatively, use the command line
|
||||
<command>systemctl reboot --boot-loader-menu=0</command> from the shell.</para>
|
||||
|
||||
<para>In the editor, most keys simply insert themselves, but the following keys
|
||||
may be used to perform additional actions:</para>
|
||||
|
||||
|
@ -86,6 +86,10 @@
|
||||
<listitem><para>Automount units acquire automatic <varname>Before=</varname> and
|
||||
<varname>Conflicts=</varname> on <filename>umount.target</filename> in order to be stopped during
|
||||
shutdown.</para></listitem>
|
||||
|
||||
<listitem><para>Automount units automatically gain an <varname>After=</varname> dependency
|
||||
on <filename>local-fs-pre.target</filename>, and a <varname>Before=</varname> dependency on
|
||||
<filename>local-fs.target</filename>.</para></listitem>
|
||||
</itemizedlist>
|
||||
</refsect2>
|
||||
</refsect1>
|
||||
|
@ -66,9 +66,9 @@
|
||||
will also gain an automatic <varname>After=</varname> dependency on
|
||||
<citerefentry><refentrytitle>systemd-tmpfiles-setup.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para></listitem>
|
||||
|
||||
<listitem><para>Units whose standard output or error output is connected to <option>journal</option>,
|
||||
<option>syslog</option> or <option>kmsg</option> (or their combinations with console output, see below)
|
||||
automatically acquire dependencies of type <varname>After=</varname> on
|
||||
<listitem><para>Units whose standard output or error output is connected to <option>journal</option> or
|
||||
<option>kmsg</option> (or their combinations with console output, see below) automatically acquire
|
||||
dependencies of type <varname>After=</varname> on
|
||||
<filename>systemd-journald.socket</filename>.</para></listitem>
|
||||
|
||||
<listitem><para>Units using <varname>LogNamespace=</varname> will automatically gain ordering and
|
||||
@ -857,10 +857,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
|
||||
<term><varname>ProtectSystem=</varname></term>
|
||||
|
||||
<listitem><para>Takes a boolean argument or the special values <literal>full</literal> or
|
||||
<literal>strict</literal>. If true, mounts the <filename>/usr</filename> and <filename>/boot</filename>
|
||||
directories read-only for processes invoked by this unit. If set to <literal>full</literal>, the
|
||||
<filename>/etc</filename> directory is mounted read-only, too. If set to <literal>strict</literal> the entire
|
||||
file system hierarchy is mounted read-only, except for the API file system subtrees <filename>/dev</filename>,
|
||||
<literal>strict</literal>. If true, mounts the <filename>/usr</filename> and the boot loader
|
||||
directories (<filename>/boot</filename> and <filename>/efi</filename>) read-only for processes
|
||||
invoked by this unit. If set to <literal>full</literal>, the <filename>/etc</filename> directory is
|
||||
mounted read-only, too. If set to <literal>strict</literal> the entire file system hierarchy is
|
||||
mounted read-only, except for the API file system subtrees <filename>/dev</filename>,
|
||||
<filename>/proc</filename> and <filename>/sys</filename> (protect these directories using
|
||||
<varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
|
||||
<varname>ProtectControlGroups=</varname>). This setting ensures that any modification of the vendor-supplied
|
||||
|
@ -691,13 +691,15 @@
|
||||
<varlistentry>
|
||||
<term><varname>RxBufferSize=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a integer. Specifies the NIC receive ring buffer size. When unset, the kernel's default will be used.</para>
|
||||
<para>Takes an integer. Specifies the maximum number of pending packets in the NIC receive buffer.
|
||||
When unset, the kernel's default will be used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
<varlistentry>
|
||||
<term><varname>TxBufferSize=</varname></term>
|
||||
<listitem>
|
||||
<para>Takes a integer. Specifies the NIC transmit ring buffer size. When unset, the kernel's default will be used.</para>
|
||||
<para>Takes an integer. Specifies the maximum number of pending packets in the NIC transmit buffer.
|
||||
When unset, the kernel's default will be used.</para>
|
||||
</listitem>
|
||||
</varlistentry>
|
||||
|
||||
|
@ -469,18 +469,16 @@
|
||||
<varlistentry>
|
||||
<term><varname>VirtualEthernetExtra=</varname></term>
|
||||
|
||||
<listitem><para>Takes a colon-separated pair of interface
|
||||
names. Configures an additional virtual Ethernet connection
|
||||
(<literal>veth</literal>) between host and the container. The
|
||||
first specified name is the interface name on the host, the
|
||||
second the interface name in the container. The latter may be
|
||||
omitted in which case it is set to the same name as the host
|
||||
side interface. This setting implies
|
||||
<varname>Private=yes</varname>. This setting corresponds to
|
||||
the <option>--network-veth-extra=</option> command line
|
||||
switch, and maybe be used multiple times. It is independent of
|
||||
<varname>VirtualEthernet=</varname>. This option is privileged
|
||||
(see above).</para></listitem>
|
||||
<listitem><para>Takes a colon-separated pair of interface names. Configures an additional virtual
|
||||
Ethernet connection (<literal>veth</literal>) between host and the container. The first specified
|
||||
name is the interface name on the host, the second the interface name in the container. The latter
|
||||
may be omitted in which case it is set to the same name as the host side interface. This setting
|
||||
implies <varname>Private=yes</varname>. This setting corresponds to the
|
||||
<option>--network-veth-extra=</option> command line switch, and maybe be used multiple times. It is
|
||||
independent of <varname>VirtualEthernet=</varname>. Note that this option is unrelated to the
|
||||
<varname>Bridge=</varname> setting below, and thus any connections created this way are not
|
||||
automatically added to any bridge device on the host side. This option is privileged (see
|
||||
above).</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
|
@ -845,35 +845,41 @@
|
||||
|
||||
<varlistentry>
|
||||
<term><varname>SuccessExitStatus=</varname></term>
|
||||
|
||||
<listitem><para>Takes a list of exit status definitions that, when returned by the main service
|
||||
process, will be considered successful termination, in addition to the normal successful exit code 0
|
||||
and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
|
||||
process, will be considered successful termination, in addition to the normal successful exit status
|
||||
0 and the signals <constant>SIGHUP</constant>, <constant>SIGINT</constant>,
|
||||
<constant>SIGTERM</constant>, and <constant>SIGPIPE</constant>. Exit status definitions can be
|
||||
numeric exit codes, termination code names, or termination signal names, separated by spaces. See the
|
||||
Process Exit Codes section in
|
||||
numeric termination statuses, termination status names, or termination signal names, separated by
|
||||
spaces. See the Process Exit Codes section in
|
||||
<citerefentry><refentrytitle>systemd.exec</refentrytitle><manvolnum>5</manvolnum></citerefentry> for
|
||||
a list of termination codes names (for this setting only the part without the
|
||||
<literal>EXIT_</literal> or <literal>EX_</literal> prefix should be used). See
|
||||
<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
a list of termination status names (for this setting only the part without the
|
||||
<literal>EXIT_</literal> or <literal>EX_</literal> prefix should be used). See <citerefentry
|
||||
project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>7</manvolnum></citerefentry> for
|
||||
a list of signal names.</para>
|
||||
|
||||
<para>This option may appear more than once, in which case the
|
||||
list of successful exit statuses is merged. If the empty
|
||||
string is assigned to this option, the list is reset, all
|
||||
prior assignments of this option will have no
|
||||
effect.</para>
|
||||
<para>Note that this setting does not change the the mapping between numeric exit statuses and their
|
||||
names, i.e. regardless how this setting is used 0 will still be mapped to <literal>SUCCESS</literal>
|
||||
(and thus typically shown as <literal>0/SUCCESS</literal> in tool outputs) and 1 to
|
||||
<literal>FAILURE</literal> (and thus typically shown as <literal>1/FAILURE</literal>), and so on. It
|
||||
only controls what happens as effect of these exit statuses, and how it propagates to the state of
|
||||
the service as a whole.</para>
|
||||
|
||||
<para>This option may appear more than once, in which case the list of successful exit statuses is
|
||||
merged. If the empty string is assigned to this option, the list is reset, all prior assignments of
|
||||
this option will have no effect.</para>
|
||||
|
||||
<example>
|
||||
<title>A service with with the <varname>SuccessExitStatus=</varname> setting</title>
|
||||
|
||||
<programlisting>SuccessExitStatus=TEMPFAIL 250 SIGUSR1</programlisting>
|
||||
|
||||
<para>Exit codes 75 (<constant>TEMPFAIL</constant>), 250, and the termination signal
|
||||
<para>Exit status 75 (<constant>TEMPFAIL</constant>), 250, and the termination signal
|
||||
<constant>SIGKILL</constant> are considered clean service terminations.</para>
|
||||
</example>
|
||||
|
||||
<para>Note: <command>systemd-analyze exit-codes</command> may be used to list exit
|
||||
codes and translate between numerical code values and names.</para></listitem>
|
||||
<para>Note: <command>systemd-analyze exit-status</command> may be used to list exit statuses and
|
||||
translate between numerical status values and names.</para></listitem>
|
||||
</varlistentry>
|
||||
|
||||
<varlistentry>
|
||||
@ -1106,10 +1112,10 @@
|
||||
|
||||
<para>Basic environment variable substitution is supported. Use
|
||||
<literal>${FOO}</literal> as part of a word, or as a word of its
|
||||
own, on the command line, in which case it will be replaced by the
|
||||
value of the environment variable including all whitespace it
|
||||
contains, resulting in a single argument. Use
|
||||
<literal>$FOO</literal> as a separate word on the command line, in
|
||||
own, on the command line, in which case it will be erased and replaced
|
||||
by the exact value of the environment variable (if any) including all
|
||||
whitespace it contains, always resulting in exactly a single argument.
|
||||
Use <literal>$FOO</literal> as a separate word on the command line, in
|
||||
which case it will be replaced by the value of the environment
|
||||
variable split at whitespace, resulting in zero or more arguments.
|
||||
For this type of expansion, quotes are respected when splitting
|
||||
|
@ -199,15 +199,14 @@ tomorrow Pacific/Auckland → Thu 2012-11-23 19:00:00
|
||||
continuous weekdays. <literal>,</literal> and <literal>..</literal>
|
||||
may be combined freely.</para>
|
||||
|
||||
<para>In the date and time specifications, any component may be
|
||||
specified as <literal>*</literal> in which case any value will
|
||||
match. Alternatively, each component can be specified as a list of
|
||||
values separated by commas. Values may be suffixed with
|
||||
<literal>/</literal> and a repetition value, which indicates that
|
||||
the value itself and the value plus all multiples of the repetition value
|
||||
are matched. Two values separated by <literal>..</literal> may be used
|
||||
to indicate a range of values; ranges may also be followed with
|
||||
<literal>/</literal> and a repetition value.</para>
|
||||
<para>In the date and time specifications, any component may be specified as <literal>*</literal> in
|
||||
which case any value will match. Alternatively, each component can be specified as a list of values
|
||||
separated by commas. Values may be suffixed with <literal>/</literal> and a repetition value, which
|
||||
indicates that the value itself and the value plus all multiples of the repetition value are matched.
|
||||
Two values separated by <literal>..</literal> may be used to indicate a range of values; ranges may also
|
||||
be followed with <literal>/</literal> and a repetition value, in which case the expression matches all
|
||||
times starting with the start value, and continuing with all multiples of the repetition value relative
|
||||
to the start value, ending at the end value the latest.</para>
|
||||
|
||||
<para>A date specification may use <literal>~</literal> to indicate the
|
||||
last day(s) in a month. For example, <literal>*-02~03</literal> means
|
||||
|
@ -1263,7 +1263,7 @@
|
||||
<term><varname>ConditionNeedsUpdate=</varname></term>
|
||||
|
||||
<listitem><para>Takes one of <filename>/var</filename> or <filename>/etc</filename> as argument,
|
||||
possibly prefixed with a <literal>!</literal> (to inverting the condition). This condition may be
|
||||
possibly prefixed with a <literal>!</literal> (to invert the condition). This condition may be
|
||||
used to conditionalize units on whether the specified directory requires an update because
|
||||
<filename>/usr</filename>'s modification time is newer than the stamp file
|
||||
<filename>.updated</filename> in the specified directory. This is useful to implement offline
|
||||
|
@ -120,16 +120,19 @@ A+ /path-or-glob/to/append/acls/recursively - - - - POSIX
|
||||
<filename>/usr/lib/tmpfiles.d</filename> and <filename>/run/tmpfiles.d</filename>. Files in
|
||||
<filename>/run/tmpfiles.d</filename> override files with the same name in
|
||||
<filename>/usr/lib/tmpfiles.d</filename>. Packages should install their configuration files in
|
||||
<filename>/usr/lib/tmpfiles.d</filename>. Files in <filename>/etc/tmpfiles.d</filename> are reserved for the local
|
||||
administrator, who may use this logic to override the configuration files installed by vendor packages. All
|
||||
configuration files are sorted by their filename in lexicographic order, regardless of which of the directories
|
||||
they reside in. If multiple files specify the same path, the entry in the file with the lexicographically earliest
|
||||
name will be applied. All other conflicting entries will be logged as errors. When two lines are prefix path and
|
||||
suffix path of each other, then the prefix line is always created first, the suffix later (and if removal applies
|
||||
to the line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are
|
||||
applied after those accepting no globs. If multiple operations shall be applied on the same file (such as ACL,
|
||||
xattr, file attribute adjustments), these are always done in the same fixed order. Except for those cases, the
|
||||
files/directories are processed in the order they are listed.</para>
|
||||
<filename>/usr/lib/tmpfiles.d</filename>. Files in <filename>/etc/tmpfiles.d</filename> are reserved for
|
||||
the local administrator, who may use this logic to override the configuration files installed by vendor
|
||||
packages. All configuration files are sorted by their filename in lexicographic order, regardless of
|
||||
which of the directories they reside in. If multiple files specify the same path, the entry in the file
|
||||
with the lexicographically earliest name will be applied (note that lines suppressed due to the
|
||||
<literal>!</literal> are filtered before application, meaning that if an early line carries the
|
||||
exclamation mark and is suppressed because of that, a later line matching in path will be applied). All
|
||||
other conflicting entries will be logged as errors. When two lines are prefix path and suffix path of
|
||||
each other, then the prefix line is always created first, the suffix later (and if removal applies to the
|
||||
line, the order is reversed: the suffix is removed first, the prefix later). Lines that take globs are
|
||||
applied after those accepting no globs. If multiple operations shall be applied on the same file (such as
|
||||
ACL, xattr, file attribute adjustments), these are always done in the same fixed order. Except for those
|
||||
cases, the files/directories are processed in the order they are listed.</para>
|
||||
|
||||
<para>If the administrator wants to disable a configuration file
|
||||
supplied by the vendor, the recommended way is to place a symlink
|
||||
@ -153,8 +156,8 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||
<refsect2>
|
||||
<title>Type</title>
|
||||
|
||||
<para>The type consists of a single letter and optionally an
|
||||
exclamation mark and/or minus sign.</para>
|
||||
<para>The type consists of a single letter and optionally an exclamation mark (<literal>!</literal>)
|
||||
and/or minus sign (<literal>-</literal>).</para>
|
||||
|
||||
<para>The following line types are understood:</para>
|
||||
|
||||
@ -452,13 +455,10 @@ L /tmp/foobar - - - - /dev/null</programlisting>
|
||||
</varlistentry>
|
||||
</variablelist>
|
||||
|
||||
<para>If the exclamation mark is used, this line is only safe to
|
||||
execute during boot, and can break a running system. Lines
|
||||
without the exclamation mark are presumed to be safe to execute
|
||||
at any time, e.g. on package upgrades.
|
||||
<command>systemd-tmpfiles</command> will execute line with an
|
||||
exclamation mark only if option <option>--boot</option> is
|
||||
given.</para>
|
||||
<para>If the exclamation mark (<literal>!</literal>) is used, this line is only safe to execute during
|
||||
boot, and can break a running system. Lines without the exclamation mark are presumed to be safe to
|
||||
execute at any time, e.g. on package upgrades. <command>systemd-tmpfiles</command> will take lines with
|
||||
an exclamation mark only into consideration, if the <option>--boot</option> option is given.</para>
|
||||
|
||||
<para>For example:
|
||||
<programlisting># Make sure these are created by default so that nobody else can
|
||||
@ -470,9 +470,8 @@ r! /tmp/.X[0-9]*-lock</programlisting>
|
||||
running system, and will only be executed with
|
||||
<option>--boot</option>.</para>
|
||||
|
||||
<para>If the minus sign is used, this line failing to run
|
||||
successfully during create (and only create) will not cause
|
||||
the execution of <command>systemd-tmpfiles</command> to return
|
||||
<para>If the minus sign (<literal>-</literal>) is used, this line failing to run successfully during
|
||||
create (and only create) will not cause the execution of <command>systemd-tmpfiles</command> to return
|
||||
an error.</para>
|
||||
|
||||
<para>For example:
|
||||
|
12
meson.build
12
meson.build
@ -423,6 +423,9 @@ add_project_arguments(cc.get_supported_arguments(basic_disabled_warnings), langu
|
||||
add_project_arguments(cc.get_supported_arguments(possible_cc_flags), language : 'c')
|
||||
add_project_link_arguments(cc.get_supported_link_arguments(possible_link_flags), language : 'c')
|
||||
|
||||
have = cc.has_argument('-Wzero-length-bounds')
|
||||
conf.set10('HAVE_ZERO_LENGTH_BOUNDS', have)
|
||||
|
||||
if cc.compiles('''
|
||||
#include <time.h>
|
||||
#include <inttypes.h>
|
||||
@ -671,8 +674,13 @@ conf.set_quoted('DEFAULT_NET_NAMING_SCHEME', default_net_naming_scheme)
|
||||
|
||||
time_epoch = get_option('time-epoch')
|
||||
if time_epoch == -1
|
||||
NEWS = files('NEWS')
|
||||
time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int()
|
||||
source_date_epoch = run_command('sh', ['-c', 'echo "$SOURCE_DATE_EPOCH"']).stdout().strip()
|
||||
if source_date_epoch != ''
|
||||
time_epoch = source_date_epoch.to_int()
|
||||
else
|
||||
NEWS = files('NEWS')
|
||||
time_epoch = run_command(stat, '-c', '%Y', NEWS).stdout().to_int()
|
||||
endif
|
||||
endif
|
||||
conf.set('TIME_EPOCH', time_epoch)
|
||||
|
||||
|
@ -53,9 +53,10 @@
|
||||
openpgp:"Retrieve openpgp keys for an email"
|
||||
query:"Resolve domain names, IPv4 and IPv6 addresses"
|
||||
reset-server-features:"Flushes all feature level information the resolver has learned about specific servers"
|
||||
reset-statistics:"Resets the statistics counter show in statistics to zero"
|
||||
reset-statistics:"Resets the statistics counter shown in statistics to zero"
|
||||
revert:"Revert the per-interfce DNS configuration"
|
||||
service:"Resolve DNS-SD and SRV services"
|
||||
statistics:"Show resolver statistics"
|
||||
status:"Show the global and per-link DNS settings currently in effect"
|
||||
tlsa:"Query tlsa public keys stored as TLSA resource records"
|
||||
)
|
||||
@ -78,10 +79,6 @@ _arguments \
|
||||
'--service[Resolve services]' \
|
||||
'--service-address=no[Do not resolve address for services]' \
|
||||
'--service-txt=no[Do not resolve TXT records for services]' \
|
||||
'--openpgp[Query OpenPGP public key]' \
|
||||
'--tlsa[Query TLS public key]' \
|
||||
'--cname=no[Do not follow CNAME redirects]' \
|
||||
'--search=no[Do not use search domains]' \
|
||||
'--statistics[Show resolver statistics]' \
|
||||
'--reset-statistics[Reset resolver statistics]' \
|
||||
'*::default: _resolvectl_commands'
|
||||
|
@ -221,7 +221,11 @@ __systemctl()
|
||||
_systemctl_failed_units() {_sys_failed_units=( ${${(f)"$(__systemctl list-units --state=failed "$PREFIX*" )"}%% *} ) }
|
||||
|
||||
(( $+functions[_systemctl_unit_state] )) ||
|
||||
_systemctl_unit_state() { typeset -gA _sys_unit_state; _sys_unit_state=( $(__systemctl list-unit-files "$PREFIX*" ) ) }
|
||||
_systemctl_unit_state() {
|
||||
setopt localoptions extendedglob
|
||||
typeset -gA _sys_unit_state
|
||||
_sys_unit_state=( ${=${${(f)"$(__systemctl list-unit-files "$PREFIX*" )"}%%[[:space:]]#}% *} )
|
||||
}
|
||||
|
||||
local fun
|
||||
# Completion functions for ALL_UNITS
|
||||
|
@ -27,6 +27,16 @@
|
||||
_describe -t state 'state' _states || compadd "$@"
|
||||
}
|
||||
|
||||
(( $+functions[_systemd-analyze_cat-config] )) ||
|
||||
_systemd-analyze_cat-config() {
|
||||
_files -W '(/run/systemd/ /etc/systemd/ /usr/lib/systemd/)' -P 'systemd/'
|
||||
}
|
||||
|
||||
(( $+functions[_systemd-analyze_security] )) ||
|
||||
_systemd-analyze_security() {
|
||||
_sd_unit_files
|
||||
}
|
||||
|
||||
(( $+functions[_systemd-analyze_commands] )) ||
|
||||
_systemd-analyze_commands(){
|
||||
local -a _systemd_analyze_cmds
|
||||
@ -38,13 +48,20 @@
|
||||
'plot:Output SVG graphic showing service initialization'
|
||||
'dot:Dump dependency graph (in dot(1) format)'
|
||||
'dump:Dump server status'
|
||||
'cat-config:Cat systemd config files'
|
||||
'unit-files:List files and symlinks for units'
|
||||
'unit-paths:List unit load paths'
|
||||
'log-level:Get/set systemd log threshold'
|
||||
'log-target:Get/set systemd log target'
|
||||
'service-watchdogs:Get/set service watchdog status'
|
||||
'exit-status:List known exit statuses'
|
||||
'syscall-filter:List syscalls in seccomp filter'
|
||||
'condition:Evaluate Condition*= and Assert*= assignments'
|
||||
'verify:Check unit files for correctness'
|
||||
'calendar:Validate repetitive calendar time events'
|
||||
'timestamp:Parse a systemd syntax timestamp'
|
||||
'timespan:Parse a systemd syntax timespan'
|
||||
'security:Analyze security settings of a service'
|
||||
# 'log-level:Get/set systemd log threshold'
|
||||
# 'log-target:Get/set systemd log target'
|
||||
# 'service-watchdogs:Get/set service watchdog status'
|
||||
)
|
||||
|
||||
if (( CURRENT == 1 )); then
|
||||
|
@ -29,6 +29,8 @@ int block_get_whole_disk(dev_t d, dev_t *ret) {
|
||||
*ret = d;
|
||||
return 0;
|
||||
}
|
||||
if (errno != ENOENT)
|
||||
return -errno;
|
||||
|
||||
/* If it is a partition find the originating device */
|
||||
xsprintf_sys_block_path(p, "/partition", d);
|
||||
|
@ -107,6 +107,18 @@ int capability_ambient_set_apply(uint64_t set, bool also_inherit) {
|
||||
unsigned long i;
|
||||
int r;
|
||||
|
||||
/* Remove capabilities requested in ambient set, but not in the bounding set */
|
||||
for (i = 0; i <= cap_last_cap(); i++) {
|
||||
if (set == 0)
|
||||
break;
|
||||
|
||||
if (FLAGS_SET(set, (UINT64_C(1) << i)) && prctl(PR_CAPBSET_READ, i) != 1) {
|
||||
log_debug("Ambient capability %s requested but missing from bounding set,"
|
||||
" suppressing automatically.", capability_to_name(i));
|
||||
set &= ~(UINT64_C(1) << i);
|
||||
}
|
||||
}
|
||||
|
||||
/* Add the capabilities to the ambient set (an possibly also the inheritable set) */
|
||||
|
||||
/* Check that we can use PR_CAP_AMBIENT or quit early. */
|
||||
|
@ -1989,6 +1989,9 @@ int cg_unified_cached(bool flush) {
|
||||
unified_cache = CGROUP_UNIFIED_NONE;
|
||||
}
|
||||
}
|
||||
} else if (F_TYPE_EQUAL(fs.f_type, SYSFS_MAGIC)) {
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
|
||||
"No filesystem is currently mounted on /sys/fs/cgroup.");
|
||||
} else
|
||||
return log_debug_errno(SYNTHETIC_ERRNO(ENOMEDIUM),
|
||||
"Unknown filesystem type %llx mounted on /sys/fs/cgroup.",
|
||||
|
@ -381,7 +381,7 @@ int read_full_virtual_file(const char *filename, char **ret_contents, size_t *re
|
||||
break;
|
||||
}
|
||||
|
||||
if (errno != -EINTR)
|
||||
if (errno != EINTR)
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
@ -692,28 +692,30 @@ int unlink_or_warn(const char *filename) {
|
||||
|
||||
int inotify_add_watch_fd(int fd, int what, uint32_t mask) {
|
||||
char path[STRLEN("/proc/self/fd/") + DECIMAL_STR_MAX(int) + 1];
|
||||
int r;
|
||||
int wd;
|
||||
|
||||
/* This is like inotify_add_watch(), except that the file to watch is not referenced by a path, but by an fd */
|
||||
xsprintf(path, "/proc/self/fd/%i", what);
|
||||
|
||||
r = inotify_add_watch(fd, path, mask);
|
||||
if (r < 0)
|
||||
wd = inotify_add_watch(fd, path, mask);
|
||||
if (wd < 0)
|
||||
return -errno;
|
||||
|
||||
return r;
|
||||
return wd;
|
||||
}
|
||||
|
||||
int inotify_add_watch_and_warn(int fd, const char *pathname, uint32_t mask) {
|
||||
int wd;
|
||||
|
||||
if (inotify_add_watch(fd, pathname, mask) < 0) {
|
||||
wd = inotify_add_watch(fd, pathname, mask);
|
||||
if (wd < 0) {
|
||||
if (errno == ENOSPC)
|
||||
return log_error_errno(errno, "Failed to add a watch for %s: inotify watch limit reached", pathname);
|
||||
|
||||
return log_error_errno(errno, "Failed to add a watch for %s: %m", pathname);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return wd;
|
||||
}
|
||||
|
||||
static bool unsafe_transition(const struct stat *a, const struct stat *b) {
|
||||
|
@ -61,11 +61,11 @@ int glob_exists(const char *path) {
|
||||
return true;
|
||||
}
|
||||
|
||||
int glob_extend(char ***strv, const char *path) {
|
||||
int glob_extend(char ***strv, const char *path, int flags) {
|
||||
_cleanup_globfree_ glob_t g = {};
|
||||
int k;
|
||||
|
||||
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE, &g);
|
||||
k = safe_glob(path, GLOB_NOSORT|GLOB_BRACE|flags, &g);
|
||||
if (k < 0)
|
||||
return k;
|
||||
|
||||
|
@ -11,7 +11,7 @@
|
||||
int safe_glob(const char *path, int flags, glob_t *pglob);
|
||||
|
||||
int glob_exists(const char *path);
|
||||
int glob_extend(char ***strv, const char *path);
|
||||
int glob_extend(char ***strv, const char *path, int flags);
|
||||
|
||||
#define _cleanup_globfree_ _cleanup_(globfree)
|
||||
|
||||
|
@ -599,13 +599,13 @@ ssize_t base64mem(const void *p, size_t l, char **out) {
|
||||
|
||||
static int base64_append_width(
|
||||
char **prefix, int plen,
|
||||
const char *sep, int indent,
|
||||
char sep, int indent,
|
||||
const void *p, size_t l,
|
||||
int width) {
|
||||
|
||||
_cleanup_free_ char *x = NULL;
|
||||
char *t, *s;
|
||||
ssize_t len, slen, avail, line, lines;
|
||||
ssize_t len, avail, line, lines;
|
||||
|
||||
len = base64mem(p, l, &x);
|
||||
if (len <= 0)
|
||||
@ -613,21 +613,20 @@ static int base64_append_width(
|
||||
|
||||
lines = DIV_ROUND_UP(len, width);
|
||||
|
||||
slen = strlen_ptr(sep);
|
||||
if (plen >= SSIZE_MAX - 1 - slen ||
|
||||
lines > (SSIZE_MAX - plen - 1 - slen) / (indent + width + 1))
|
||||
if ((size_t) plen >= SSIZE_MAX - 1 - 1 ||
|
||||
lines > (SSIZE_MAX - plen - 1 - 1) / (indent + width + 1))
|
||||
return -ENOMEM;
|
||||
|
||||
t = realloc(*prefix, (ssize_t) plen + 1 + slen + (indent + width + 1) * lines);
|
||||
t = realloc(*prefix, (ssize_t) plen + 1 + 1 + (indent + width + 1) * lines);
|
||||
if (!t)
|
||||
return -ENOMEM;
|
||||
|
||||
memcpy_safe(t + plen, sep, slen);
|
||||
t[plen] = sep;
|
||||
|
||||
for (line = 0, s = t + plen + slen, avail = len; line < lines; line++) {
|
||||
for (line = 0, s = t + plen + 1, avail = len; line < lines; line++) {
|
||||
int act = MIN(width, avail);
|
||||
|
||||
if (line > 0 || sep) {
|
||||
if (line > 0 || sep == '\n') {
|
||||
memset(s, ' ', indent);
|
||||
s += indent;
|
||||
}
|
||||
@ -650,10 +649,10 @@ int base64_append(
|
||||
|
||||
if (plen > width / 2 || plen + indent > width)
|
||||
/* leave indent on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, "\n", indent, p, l, width - indent - 1);
|
||||
return base64_append_width(prefix, plen, '\n', indent, p, l, width - indent - 1);
|
||||
else
|
||||
/* leave plen on the left, keep last column free */
|
||||
return base64_append_width(prefix, plen, " ", plen, p, l, width - plen - 1);
|
||||
return base64_append_width(prefix, plen, ' ', plen + 1, p, l, width - plen - 1);
|
||||
}
|
||||
|
||||
static int unbase64_next(const char **p, size_t *l) {
|
||||
|
@ -41,6 +41,11 @@ uint64_t physical_memory(void) {
|
||||
}
|
||||
if (r > 0) {
|
||||
r = cg_get_attribute("memory", root, "memory.max", &value);
|
||||
if (r == -ENOENT) /* Field does not exist on the system's top-level cgroup, hence don't
|
||||
* complain. (Note that it might exist on our own root though, if we live
|
||||
* in a cgroup namespace, hence check anyway instead of not even
|
||||
* trying.) */
|
||||
return mem;
|
||||
if (r < 0) {
|
||||
log_debug_errno(r, "Failed to read memory.max cgroup attribute, ignoring cgroup memory limit: %m");
|
||||
return mem;
|
||||
|
@ -1051,7 +1051,7 @@ int systemd_installation_has_version(const char *root, unsigned minimal_version)
|
||||
if (!path)
|
||||
return -ENOMEM;
|
||||
|
||||
r = glob_extend(&names, path);
|
||||
r = glob_extend(&names, path, 0);
|
||||
if (r == -ENOENT)
|
||||
continue;
|
||||
if (r < 0)
|
||||
|
@ -19,6 +19,7 @@
|
||||
#endif
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "errno-util.h"
|
||||
#include "fd-util.h"
|
||||
#include "fileio.h"
|
||||
#include "io-util.h"
|
||||
@ -237,7 +238,7 @@ int genuine_random_bytes(void *p, size_t n, RandomFlags flags) {
|
||||
have_syscall = true;
|
||||
return -EIO;
|
||||
|
||||
} else if (errno == ENOSYS) {
|
||||
} else if (ERRNO_IS_NOT_SUPPORTED(errno)) {
|
||||
/* We lack the syscall, continue with reading from /dev/urandom. */
|
||||
have_syscall = false;
|
||||
break;
|
||||
|
@ -901,9 +901,9 @@ ssize_t receive_one_fd_iov(
|
||||
* combination with send_one_fd().
|
||||
*/
|
||||
|
||||
k = recvmsg(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
|
||||
k = recvmsg_safe(transport_fd, &mh, MSG_CMSG_CLOEXEC | flags);
|
||||
if (k < 0)
|
||||
return (ssize_t) -errno;
|
||||
return k;
|
||||
|
||||
CMSG_FOREACH(cmsg, &mh) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
@ -915,12 +915,13 @@ ssize_t receive_one_fd_iov(
|
||||
}
|
||||
}
|
||||
|
||||
if (!found)
|
||||
if (!found) {
|
||||
cmsg_close_all(&mh);
|
||||
|
||||
/* If didn't receive an FD or any data, return an error. */
|
||||
if (k == 0 && !found)
|
||||
return -EIO;
|
||||
/* If didn't receive an FD or any data, return an error. */
|
||||
if (k == 0)
|
||||
return -EIO;
|
||||
}
|
||||
|
||||
if (found)
|
||||
*ret_fd = *(int*) CMSG_DATA(found);
|
||||
@ -1171,3 +1172,24 @@ int socket_bind_to_ifindex(int fd, int ifindex) {
|
||||
|
||||
return socket_bind_to_ifname(fd, ifname);
|
||||
}
|
||||
|
||||
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags) {
|
||||
ssize_t n;
|
||||
|
||||
/* A wrapper around recvmsg() that checks for MSG_CTRUNC, and turns it into an error, in a reasonably
|
||||
* safe way, closing any SCM_RIGHTS fds in the error path.
|
||||
*
|
||||
* Note that unlike our usual coding style this might modify *msg on failure. */
|
||||
|
||||
n = recvmsg(sockfd, msg, flags);
|
||||
if (n < 0)
|
||||
return -errno;
|
||||
|
||||
if (FLAGS_SET(msg->msg_flags, MSG_CTRUNC)) {
|
||||
cmsg_close_all(msg);
|
||||
return -EXFULL; /* a recognizable error code */
|
||||
}
|
||||
|
||||
return n;
|
||||
|
||||
}
|
||||
|
@ -199,3 +199,5 @@ static inline int setsockopt_int(int fd, int level, int optname, int value) {
|
||||
|
||||
int socket_bind_to_ifname(int fd, const char *ifname);
|
||||
int socket_bind_to_ifindex(int fd, int ifindex);
|
||||
|
||||
ssize_t recvmsg_safe(int sockfd, struct msghdr *msg, int flags);
|
||||
|
@ -94,10 +94,10 @@ bool null_or_empty(struct stat *st) {
|
||||
if (S_ISREG(st->st_mode) && st->st_size <= 0)
|
||||
return true;
|
||||
|
||||
/* We don't want to hardcode the major/minor of /dev/null,
|
||||
* hence we do a simpler "is this a device node?" check. */
|
||||
/* We don't want to hardcode the major/minor of /dev/null, hence we do a simpler "is this a character
|
||||
* device node?" check. */
|
||||
|
||||
if (S_ISCHR(st->st_mode) || S_ISBLK(st->st_mode))
|
||||
if (S_ISCHR(st->st_mode))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
@ -108,6 +108,10 @@ int null_or_empty_path(const char *fn) {
|
||||
|
||||
assert(fn);
|
||||
|
||||
/* If we have the path, let's do an easy text comparison first. */
|
||||
if (path_equal(fn, "/dev/null"))
|
||||
return true;
|
||||
|
||||
if (stat(fn, &st) < 0)
|
||||
return -errno;
|
||||
|
||||
@ -178,13 +182,12 @@ int fd_is_fs_type(int fd, statfs_f_type_t magic_value) {
|
||||
}
|
||||
|
||||
int path_is_fs_type(const char *path, statfs_f_type_t magic_value) {
|
||||
_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_fs_type(fd, magic_value);
|
||||
return is_fs_type(&s, magic_value);
|
||||
}
|
||||
|
||||
bool is_temporary_fs(const struct statfs *s) {
|
||||
|
@ -101,7 +101,7 @@ bool strv_overlap(char * const *a, char * const *b) _pure_;
|
||||
(s)--)
|
||||
|
||||
#define STRV_FOREACH_PAIR(x, y, l) \
|
||||
for ((x) = (l), (y) = (x+1); (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
|
||||
for ((x) = (l), (y) = (x) ? (x+1) : NULL; (x) && *(x) && *(y); (x) += 2, (y) = (x + 1))
|
||||
|
||||
char **strv_sort(char **l);
|
||||
void strv_print(char * const *l);
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include <sys/types.h>
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "binfmt-util.h"
|
||||
#include "conf-files.h"
|
||||
#include "def.h"
|
||||
#include "fd-util.h"
|
||||
@ -24,6 +25,7 @@
|
||||
|
||||
static bool arg_cat_config = false;
|
||||
static PagerFlags arg_pager_flags = 0;
|
||||
static bool arg_unregister = false;
|
||||
|
||||
static int delete_rule(const char *rule) {
|
||||
_cleanup_free_ char *x = NULL, *fn = NULL;
|
||||
@ -32,18 +34,17 @@ static int delete_rule(const char *rule) {
|
||||
assert(rule);
|
||||
assert(rule[0]);
|
||||
|
||||
x = strdup(rule);
|
||||
e = strchrnul(rule + 1, rule[0]);
|
||||
x = strndup(rule + 1, e - rule - 1);
|
||||
if (!x)
|
||||
return log_oom();
|
||||
|
||||
e = strchrnul(x+1, x[0]);
|
||||
*e = 0;
|
||||
|
||||
if (!filename_is_valid(x + 1))
|
||||
if (!filename_is_valid(x) ||
|
||||
STR_IN_SET(x, "register", "status"))
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Rule file name '%s' is not valid, refusing.", x + 1);
|
||||
"Rule file name '%s' is not valid, refusing.", x);
|
||||
|
||||
fn = path_join("/proc/sys/fs/binfmt_misc", x+1);
|
||||
fn = path_join("/proc/sys/fs/binfmt_misc", x);
|
||||
if (!fn)
|
||||
return log_oom();
|
||||
|
||||
@ -116,6 +117,7 @@ static int help(void) {
|
||||
" --version Show package version\n"
|
||||
" --cat-config Show configuration files\n"
|
||||
" --no-pager Do not pipe output into a pager\n"
|
||||
" --unregister Unregister all existing entries\n"
|
||||
"\nSee the %s for details.\n"
|
||||
, program_invocation_short_name
|
||||
, link
|
||||
@ -129,6 +131,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
ARG_VERSION = 0x100,
|
||||
ARG_CAT_CONFIG,
|
||||
ARG_NO_PAGER,
|
||||
ARG_UNREGISTER,
|
||||
};
|
||||
|
||||
static const struct option options[] = {
|
||||
@ -136,6 +139,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
{ "version", no_argument, NULL, ARG_VERSION },
|
||||
{ "cat-config", no_argument, NULL, ARG_CAT_CONFIG },
|
||||
{ "no-pager", no_argument, NULL, ARG_NO_PAGER },
|
||||
{ "unregister", no_argument, NULL, ARG_UNREGISTER },
|
||||
{}
|
||||
};
|
||||
|
||||
@ -162,6 +166,10 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
arg_pager_flags |= PAGER_DISABLE;
|
||||
break;
|
||||
|
||||
case ARG_UNREGISTER:
|
||||
arg_unregister = true;
|
||||
break;
|
||||
|
||||
case '?':
|
||||
return -EINVAL;
|
||||
|
||||
@ -169,9 +177,9 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
assert_not_reached("Unhandled option");
|
||||
}
|
||||
|
||||
if (arg_cat_config && argc > optind)
|
||||
if ((arg_unregister || arg_cat_config) && argc > optind)
|
||||
return log_error_errno(SYNTHETIC_ERRNO(EINVAL),
|
||||
"Positional arguments are not allowed with --cat-config");
|
||||
"Positional arguments are not allowed with --cat-config or --unregister");
|
||||
|
||||
return 1;
|
||||
}
|
||||
@ -189,6 +197,9 @@ static int run(int argc, char *argv[]) {
|
||||
|
||||
r = 0;
|
||||
|
||||
if (arg_unregister)
|
||||
return disable_binfmt();
|
||||
|
||||
if (argc > optind) {
|
||||
int i;
|
||||
|
||||
|
@ -517,7 +517,7 @@ static int copy_file_with_version_check(const char *from, const char *to, bool f
|
||||
if (!force) {
|
||||
fd_to = open(to, O_RDONLY|O_CLOEXEC|O_NOCTTY);
|
||||
if (fd_to < 0) {
|
||||
if (errno != -ENOENT)
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to open \"%s\" for reading: %m", to);
|
||||
} else {
|
||||
r = version_check(fd_from, from, fd_to, to);
|
||||
|
@ -152,6 +152,10 @@ static int automount_add_default_dependencies(Automount *a) {
|
||||
if (!MANAGER_IS_SYSTEM(UNIT(a)->manager))
|
||||
return 0;
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(a), UNIT_BEFORE, SPECIAL_LOCAL_FS_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(a), UNIT_AFTER, SPECIAL_LOCAL_FS_PRE_TARGET, true, UNIT_DEPENDENCY_DEFAULT);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
@ -289,11 +289,13 @@ int manager_varlink_init(Manager *m) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to register varlink methods: %m");
|
||||
|
||||
(void) mkdir_p("/run/systemd/userdb", 0755);
|
||||
if (!MANAGER_IS_TEST_RUN(m)) {
|
||||
(void) mkdir_p("/run/systemd/userdb", 0755);
|
||||
|
||||
r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to varlink socket: %m");
|
||||
r = varlink_server_listen_address(s, "/run/systemd/userdb/io.systemd.DynamicUser", 0666);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to bind to varlink socket: %m");
|
||||
}
|
||||
|
||||
r = varlink_server_attach_event(s, m->event, SD_EVENT_PRIORITY_NORMAL);
|
||||
if (r < 0)
|
||||
|
@ -1064,7 +1064,6 @@ const UnitVTable device_vtable = {
|
||||
"Device\0"
|
||||
"Install\0",
|
||||
|
||||
.refuse_after = true,
|
||||
.gc_jobs = true,
|
||||
|
||||
.init = device_init,
|
||||
|
@ -1647,8 +1647,6 @@ static int apply_lock_personality(const Unit* u, const ExecContext *c) {
|
||||
#endif
|
||||
|
||||
static int apply_protect_hostname(const Unit *u, const ExecContext *c, int *ret_exit_status) {
|
||||
int r;
|
||||
|
||||
assert(u);
|
||||
assert(c);
|
||||
|
||||
@ -1668,6 +1666,8 @@ static int apply_protect_hostname(const Unit *u, const ExecContext *c, int *ret_
|
||||
log_unit_warning(u, "ProtectHostname=yes is configured, but the kernel does not support UTS namespaces, ignoring namespace setup.");
|
||||
|
||||
#if HAVE_SECCOMP
|
||||
int r;
|
||||
|
||||
if (skip_seccomp_unavailable(u, "ProtectHostname="))
|
||||
return 0;
|
||||
|
||||
@ -1820,12 +1820,13 @@ static int build_environment(
|
||||
|
||||
tty_path = exec_context_tty_path(c);
|
||||
|
||||
/* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try to inherit
|
||||
* the $TERM set for PID 1. This is useful for containers so that the $TERM the container manager
|
||||
* passes to PID 1 ends up all the way in the console login shown. */
|
||||
/* If we are forked off PID 1 and we are supposed to operate on /dev/console, then let's try
|
||||
* to inherit the $TERM set for PID 1. This is useful for containers so that the $TERM the
|
||||
* container manager passes to PID 1 ends up all the way in the console login shown. */
|
||||
|
||||
if (path_equal(tty_path, "/dev/console") && getppid() == 1)
|
||||
if (path_equal_ptr(tty_path, "/dev/console") && getppid() == 1)
|
||||
term = getenv("TERM");
|
||||
|
||||
if (!term)
|
||||
term = default_term_for_tty(tty_path);
|
||||
|
||||
|
@ -516,12 +516,20 @@ static bool job_is_runnable(Job *j) {
|
||||
return true;
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_AFTER], i)
|
||||
if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0)
|
||||
if (other->job && job_compare(j, other->job, UNIT_AFTER) > 0) {
|
||||
log_unit_debug(j->unit,
|
||||
"starting held back, waiting for: %s",
|
||||
other->id);
|
||||
return false;
|
||||
}
|
||||
|
||||
HASHMAP_FOREACH_KEY(v, other, j->unit->dependencies[UNIT_BEFORE], i)
|
||||
if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0)
|
||||
if (other->job && job_compare(j, other->job, UNIT_BEFORE) > 0) {
|
||||
log_unit_debug(j->unit,
|
||||
"stopping held back, waiting for: %s",
|
||||
other->id);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
@ -2850,7 +2850,7 @@ int config_parse_syscall_filter(
|
||||
void *userdata) {
|
||||
|
||||
ExecContext *c = data;
|
||||
const Unit *u = userdata;
|
||||
_unused_ const Unit *u = userdata;
|
||||
bool invert = false;
|
||||
const char *p;
|
||||
int r;
|
||||
@ -4729,7 +4729,7 @@ int unit_load_fragment(Unit *u) {
|
||||
&u->manager->unit_name_map,
|
||||
&u->manager->unit_path_cache);
|
||||
if (r < 0)
|
||||
log_error_errno(r, "Failed to rebuild name map: %m");
|
||||
return log_error_errno(r, "Failed to rebuild name map: %m");
|
||||
|
||||
r = unit_file_find_fragment(u->manager->unit_id_map,
|
||||
u->manager->unit_name_map,
|
||||
@ -5090,7 +5090,7 @@ int config_parse_swap_priority(
|
||||
|
||||
r = safe_atoi(rvalue, &priority);
|
||||
if (r < 0) {
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap pririty '%s', ignoring.", rvalue);
|
||||
log_syntax(unit, LOG_ERR, filename, line, r, "Invalid swap priority '%s', ignoring.", rvalue);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -1196,6 +1196,7 @@ static int bump_rlimit_nofile(struct rlimit *saved_rlimit) {
|
||||
|
||||
static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
|
||||
struct rlimit new_rlimit;
|
||||
uint64_t mm;
|
||||
int r;
|
||||
|
||||
/* BPF_MAP_TYPE_LPM_TRIE bpf maps are charged against RLIMIT_MEMLOCK, even if we have CAP_IPC_LOCK which should
|
||||
@ -1206,9 +1207,12 @@ static int bump_rlimit_memlock(struct rlimit *saved_rlimit) {
|
||||
* must be unsigned, hence this is a given, but let's make this clear here. */
|
||||
assert_cc(RLIM_INFINITY > 0);
|
||||
|
||||
mm = physical_memory() / 8; /* Let's scale how much we allow to be locked by the amount of physical
|
||||
* RAM. We allow an eigth to be locked by us, just to pick a value. */
|
||||
|
||||
new_rlimit = (struct rlimit) {
|
||||
.rlim_cur = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur),
|
||||
.rlim_max = MAX(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max),
|
||||
.rlim_cur = MAX3(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_cur, mm),
|
||||
.rlim_max = MAX3(HIGH_RLIMIT_MEMLOCK, saved_rlimit->rlim_max, mm),
|
||||
};
|
||||
|
||||
if (saved_rlimit->rlim_max >= new_rlimit.rlim_cur &&
|
||||
|
@ -312,9 +312,9 @@ static int manager_check_ask_password(Manager *m) {
|
||||
m->ask_password_inotify_fd, EPOLLIN,
|
||||
manager_dispatch_ask_password_fd, m);
|
||||
if (r < 0) {
|
||||
log_error_errno(errno, "Failed to add event source for /run/systemd/ask-password: %m");
|
||||
log_error_errno(r, "Failed to add event source for /run/systemd/ask-password: %m");
|
||||
manager_close_ask_password(m);
|
||||
return -errno;
|
||||
return r;
|
||||
}
|
||||
|
||||
(void) sd_event_source_set_description(m->ask_password_event_source, "manager-ask-password");
|
||||
@ -1967,7 +1967,6 @@ int manager_load_unit_prepare(
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
assert(name || path);
|
||||
assert(_ret);
|
||||
|
||||
/* This will prepare the unit for loading, but not actually
|
||||
@ -1976,8 +1975,13 @@ int manager_load_unit_prepare(
|
||||
if (path && !is_path(path))
|
||||
return sd_bus_error_setf(e, SD_BUS_ERROR_INVALID_ARGS, "Path %s is not absolute.", path);
|
||||
|
||||
if (!name)
|
||||
if (!name) {
|
||||
/* 'name' and 'path' must not both be null. Check here 'path' using assert_se() to
|
||||
* workaround a bug in gcc that generates a -Wnonnull warning when calling basename(),
|
||||
* but this cannot be possible in any code path (See #6119). */
|
||||
assert_se(path);
|
||||
name = basename(path);
|
||||
}
|
||||
|
||||
t = unit_name_to_type(name);
|
||||
|
||||
@ -2359,20 +2363,20 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
return 0;
|
||||
}
|
||||
|
||||
n = recvmsg(m->notify_fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC|MSG_TRUNC);
|
||||
if (n < 0) {
|
||||
if (IN_SET(errno, EAGAIN, EINTR))
|
||||
return 0; /* Spurious wakeup, try again */
|
||||
|
||||
/* 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 looping around this:
|
||||
* being woken up over and over again but being unable to actually read the message off the socket. */
|
||||
return log_error_errno(errno, "Failed to receive notification message: %m");
|
||||
}
|
||||
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 < 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
|
||||
* looping around this: being woken up over and over again but being unable to actually read
|
||||
* the message off the socket. */
|
||||
return log_error_errno(n, "Failed to receive notification message: %m");
|
||||
|
||||
CMSG_FOREACH(cmsg, &msghdr) {
|
||||
if (cmsg->cmsg_level == SOL_SOCKET && cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
|
||||
assert(!fd_array);
|
||||
fd_array = (int*) CMSG_DATA(cmsg);
|
||||
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
|
||||
@ -2380,6 +2384,7 @@ static int manager_dispatch_notify_fd(sd_event_source *source, int fd, uint32_t
|
||||
cmsg->cmsg_type == SCM_CREDENTIALS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
||||
|
||||
assert(!ucred);
|
||||
ucred = (struct ucred*) CMSG_DATA(cmsg);
|
||||
}
|
||||
}
|
||||
|
140
src/core/mount.c
140
src/core/mount.c
@ -66,6 +66,14 @@ static bool MOUNT_STATE_WITH_PROCESS(MountState state) {
|
||||
MOUNT_CLEANING);
|
||||
}
|
||||
|
||||
static bool mount_is_automount(const MountParameters *p) {
|
||||
assert(p);
|
||||
|
||||
return fstab_test_option(p->options,
|
||||
"comment=systemd.automount\0"
|
||||
"x-systemd.automount\0");
|
||||
}
|
||||
|
||||
static bool mount_is_network(const MountParameters *p) {
|
||||
assert(p);
|
||||
|
||||
@ -78,6 +86,15 @@ static bool mount_is_network(const MountParameters *p) {
|
||||
return false;
|
||||
}
|
||||
|
||||
static bool mount_is_nofail(const Mount *m) {
|
||||
assert(m);
|
||||
|
||||
if (!m->from_fragment)
|
||||
return false;
|
||||
|
||||
return fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0");
|
||||
}
|
||||
|
||||
static bool mount_is_loop(const MountParameters *p) {
|
||||
assert(p);
|
||||
|
||||
@ -400,42 +417,72 @@ static bool mount_is_extrinsic(Mount *m) {
|
||||
MountParameters *p;
|
||||
assert(m);
|
||||
|
||||
/* Returns true for all units that are "magic" and should be excluded from the usual start-up and shutdown
|
||||
* dependencies. We call them "extrinsic" here, as they are generally mounted outside of the systemd dependency
|
||||
* logic. We shouldn't attempt to manage them ourselves but it's fine if the user operates on them with us. */
|
||||
/* Returns true for all units that are "magic" and should be excluded from the usual
|
||||
* start-up and shutdown dependencies. We call them "extrinsic" here, as they are generally
|
||||
* mounted outside of the systemd dependency logic. We shouldn't attempt to manage them
|
||||
* ourselves but it's fine if the user operates on them with us. */
|
||||
|
||||
if (!MANAGER_IS_SYSTEM(UNIT(m)->manager)) /* We only automatically manage mounts if we are in system mode */
|
||||
/* We only automatically manage mounts if we are in system mode */
|
||||
if (!MANAGER_IS_SYSTEM(UNIT(m)->manager))
|
||||
return true;
|
||||
|
||||
if (UNIT(m)->perpetual) /* All perpetual units never change state */
|
||||
return true;
|
||||
|
||||
if (PATH_IN_SET(m->where, /* Don't bother with the OS data itself */
|
||||
"/", /* (strictly speaking redundant: should already be covered by the perpetual flag check above) */
|
||||
"/usr",
|
||||
"/etc"))
|
||||
return true;
|
||||
|
||||
if (PATH_STARTSWITH_SET(m->where,
|
||||
"/run/initramfs", /* This should stay around from before we boot until after we shutdown */
|
||||
"/proc", /* All of this is API VFS */
|
||||
"/sys", /* … dito … */
|
||||
"/dev")) /* … dito … */
|
||||
return true;
|
||||
|
||||
/* If this is an initrd mount, and we are not in the initrd, then leave this around forever, too. */
|
||||
p = get_mount_parameters(m);
|
||||
if (p && fstab_test_option(p->options, "x-initrd.mount\0") && !in_initrd())
|
||||
if (p && fstab_is_extrinsic(m->where, p->options))
|
||||
return true;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
static int mount_add_default_ordering_dependencies(
|
||||
Mount *m,
|
||||
MountParameters *p,
|
||||
UnitDependencyMask mask) {
|
||||
|
||||
const char *after, *before, *e;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
|
||||
e = path_startswith(m->where, "/sysroot");
|
||||
if (e && in_initrd()) {
|
||||
/* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW,
|
||||
* it's not technically part of the basic initrd filesystem itself, and so
|
||||
* shouldn't inherit the default Before=local-fs.target dependency. */
|
||||
|
||||
after = NULL;
|
||||
before = isempty(e) ? SPECIAL_INITRD_ROOT_FS_TARGET : SPECIAL_INITRD_FS_TARGET;
|
||||
|
||||
} else if (mount_is_network(p)) {
|
||||
after = SPECIAL_REMOTE_FS_PRE_TARGET;
|
||||
before = SPECIAL_REMOTE_FS_TARGET;
|
||||
|
||||
} else {
|
||||
after = SPECIAL_LOCAL_FS_PRE_TARGET;
|
||||
before = SPECIAL_LOCAL_FS_TARGET;
|
||||
}
|
||||
|
||||
if (!mount_is_nofail(m) && !mount_is_automount(p)) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
if (after) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
return unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS,
|
||||
SPECIAL_UMOUNT_TARGET, true, mask);
|
||||
}
|
||||
|
||||
static int mount_add_default_dependencies(Mount *m) {
|
||||
const char *after, *before;
|
||||
UnitDependencyMask mask;
|
||||
MountParameters *p;
|
||||
bool nofail;
|
||||
int r;
|
||||
|
||||
assert(m);
|
||||
@ -443,9 +490,10 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
if (!UNIT(m)->default_dependencies)
|
||||
return 0;
|
||||
|
||||
/* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are guaranteed to stay
|
||||
* mounted the whole time, since our system is on it. Also, don't bother with anything mounted below virtual
|
||||
* file systems, it's also going to be virtual, and hence not worth the effort. */
|
||||
/* We do not add any default dependencies to /, /usr or /run/initramfs/, since they are
|
||||
* guaranteed to stay mounted the whole time, since our system is on it. Also, don't
|
||||
* bother with anything mounted below virtual file systems, it's also going to be virtual,
|
||||
* and hence not worth the effort. */
|
||||
if (mount_is_extrinsic(m))
|
||||
return 0;
|
||||
|
||||
@ -454,51 +502,31 @@ static int mount_add_default_dependencies(Mount *m) {
|
||||
return 0;
|
||||
|
||||
mask = m->from_fragment ? UNIT_DEPENDENCY_FILE : UNIT_DEPENDENCY_MOUNTINFO_DEFAULT;
|
||||
nofail = m->from_fragment ? fstab_test_yes_no_option(m->parameters_fragment.options, "nofail\0" "fail\0") : false;
|
||||
|
||||
r = mount_add_default_ordering_dependencies(m, p, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
if (mount_is_network(p)) {
|
||||
/* We order ourselves after network.target. This is
|
||||
* primarily useful at shutdown: services that take
|
||||
* down the network should order themselves before
|
||||
* network.target, so that they are shut down only
|
||||
* after this mount unit is stopped. */
|
||||
/* We order ourselves after network.target. This is primarily useful at shutdown:
|
||||
* services that take down the network should order themselves before
|
||||
* network.target, so that they are shut down only after this mount unit is
|
||||
* stopped. */
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_NETWORK_TARGET, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We pull in network-online.target, and order
|
||||
* ourselves after it. This is useful at start-up to
|
||||
* actively pull in tools that want to be started
|
||||
* before we start mounting network file systems, and
|
||||
* whose purpose it is to delay this until the network
|
||||
* is "up". */
|
||||
/* We pull in network-online.target, and order ourselves after it. This is useful
|
||||
* at start-up to actively pull in tools that want to be started before we start
|
||||
* mounting network file systems, and whose purpose it is to delay this until the
|
||||
* network is "up". */
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_WANTS, UNIT_AFTER, SPECIAL_NETWORK_ONLINE_TARGET, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
after = SPECIAL_REMOTE_FS_PRE_TARGET;
|
||||
before = SPECIAL_REMOTE_FS_TARGET;
|
||||
} else {
|
||||
after = SPECIAL_LOCAL_FS_PRE_TARGET;
|
||||
before = SPECIAL_LOCAL_FS_TARGET;
|
||||
}
|
||||
|
||||
if (!nofail) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_BEFORE, before, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
}
|
||||
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, after, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
r = unit_add_two_dependencies_by_name(UNIT(m), UNIT_BEFORE, UNIT_CONFLICTS, SPECIAL_UMOUNT_TARGET, true, mask);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* If this is a tmpfs mount then we have to unmount it before we try to deactivate swaps */
|
||||
if (streq_ptr(p->fstype, "tmpfs")) {
|
||||
r = unit_add_dependency_by_name(UNIT(m), UNIT_AFTER, SPECIAL_SWAP_TARGET, true, mask);
|
||||
|
@ -1619,8 +1619,9 @@ int setup_namespace(
|
||||
r = 0;
|
||||
|
||||
finish:
|
||||
for (m = mounts; m < mounts + n_mounts; m++)
|
||||
mount_entry_done(m);
|
||||
if (n_mounts > 0)
|
||||
for (m = mounts; m < mounts + n_mounts; m++)
|
||||
mount_entry_done(m);
|
||||
|
||||
free(mounts);
|
||||
|
||||
|
@ -223,11 +223,10 @@ static void path_spec_mkdir(PathSpec *s, mode_t mode) {
|
||||
}
|
||||
|
||||
static void path_spec_dump(PathSpec *s, FILE *f, const char *prefix) {
|
||||
fprintf(f,
|
||||
"%s%s: %s\n",
|
||||
prefix,
|
||||
path_type_to_string(s->type),
|
||||
s->path);
|
||||
const char *type;
|
||||
|
||||
assert_se(type = path_type_to_string(s->type));
|
||||
fprintf(f, "%s%s: %s\n", prefix, type, s->path);
|
||||
}
|
||||
|
||||
void path_spec_done(PathSpec *s) {
|
||||
@ -607,14 +606,16 @@ static int path_serialize(Unit *u, FILE *f, FDSet *fds) {
|
||||
(void) serialize_item(f, "result", path_result_to_string(p->result));
|
||||
|
||||
LIST_FOREACH(spec, s, p->specs) {
|
||||
const char *type;
|
||||
_cleanup_free_ char *escaped = NULL;
|
||||
|
||||
escaped = cescape(s->path);
|
||||
if (!escaped)
|
||||
return log_oom();
|
||||
|
||||
assert_se(type = path_type_to_string(s->type));
|
||||
(void) serialize_item_format(f, "path-spec", "%s %i %s",
|
||||
path_type_to_string(s->type),
|
||||
type,
|
||||
s->previous_exists,
|
||||
s->path);
|
||||
}
|
||||
|
@ -2704,7 +2704,7 @@ void unit_unwatch_pid(Unit *u, pid_t pid) {
|
||||
|
||||
if (m == 0) {
|
||||
/* The array is now empty, remove the entire entry */
|
||||
assert(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array);
|
||||
assert_se(hashmap_remove(u->manager->watch_pids, PID_TO_PTR(-pid)) == array);
|
||||
free(array);
|
||||
}
|
||||
}
|
||||
@ -2957,13 +2957,10 @@ int unit_add_dependency(
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (d == UNIT_AFTER && UNIT_VTABLE(u)->refuse_after) {
|
||||
log_unit_warning(u, "Requested dependency After=%s ignored (%s units cannot be delayed).", other->id, unit_type_to_string(u->type));
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (d == UNIT_BEFORE && UNIT_VTABLE(other)->refuse_after) {
|
||||
log_unit_warning(u, "Requested dependency Before=%s ignored (%s units cannot be delayed).", other->id, unit_type_to_string(other->type));
|
||||
/* Note that ordering a device unit after a unit is permitted since it
|
||||
* allows to start its job running timeout at a specific time. */
|
||||
if (d == UNIT_BEFORE && other->type == UNIT_DEVICE) {
|
||||
log_unit_warning(u, "Dependency Before=%s ignored (.device units cannot be delayed)", other->id);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -610,9 +610,6 @@ typedef struct UnitVTable {
|
||||
/* True if the unit type knows a failure state, and thus can be source of an OnFailure= dependency */
|
||||
bool can_fail:1;
|
||||
|
||||
/* True if After= dependencies should be refused */
|
||||
bool refuse_after:1;
|
||||
|
||||
/* True if units of this type shall be startable only once and then never again */
|
||||
bool once_only:1;
|
||||
|
||||
@ -883,8 +880,9 @@ int unit_can_clean(Unit *u, ExecCleanMask *ret_mask);
|
||||
#define log_unit_full(unit, level, error, ...) \
|
||||
({ \
|
||||
const Unit *_u = (unit); \
|
||||
_u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
|
||||
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
|
||||
(log_get_max_level() < LOG_PRI(level)) ? -ERRNO_VALUE(error) : \
|
||||
_u ? log_object_internal(level, error, PROJECT_FILE, __LINE__, __func__, _u->manager->unit_log_field, _u->id, _u->manager->invocation_log_field, _u->invocation_id_string, ##__VA_ARGS__) : \
|
||||
log_internal(level, error, PROJECT_FILE, __LINE__, __func__, ##__VA_ARGS__); \
|
||||
})
|
||||
|
||||
#define log_unit_debug(unit, ...) log_unit_full(unit, LOG_DEBUG, 0, ##__VA_ARGS__)
|
||||
|
@ -913,10 +913,10 @@ static int process_socket(int fd) {
|
||||
|
||||
mh.msg_iov = &iovec;
|
||||
|
||||
n = recvmsg(fd, &mh, MSG_CMSG_CLOEXEC);
|
||||
n = recvmsg_safe(fd, &mh, MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
free(iovec.iov_base);
|
||||
r = log_error_errno(errno, "Failed to receive datagram: %m");
|
||||
r = log_error_errno(n, "Failed to receive datagram: %m");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
@ -937,15 +937,17 @@ static int process_socket(int fd) {
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
log_error("Coredump file descriptor missing.");
|
||||
r = -EBADMSG;
|
||||
cmsg_close_all(&mh);
|
||||
r = log_error_errno(SYNTHETIC_ERRNO(EBADMSG),
|
||||
"Coredump file descriptor missing.");
|
||||
goto finish;
|
||||
}
|
||||
|
||||
assert(input_fd < 0);
|
||||
input_fd = *(int*) CMSG_DATA(found);
|
||||
break;
|
||||
}
|
||||
} else
|
||||
cmsg_close_all(&mh);
|
||||
|
||||
/* Add trailing NUL byte, in case these are strings */
|
||||
((char*) iovec.iov_base)[n] = 0;
|
||||
@ -954,8 +956,6 @@ static int process_socket(int fd) {
|
||||
r = iovw_put(&iovw, iovec.iov_base, iovec.iov_len);
|
||||
if (r < 0)
|
||||
goto finish;
|
||||
|
||||
cmsg_close_all(&mh);
|
||||
}
|
||||
|
||||
/* Make sure we got all data we really need */
|
||||
|
@ -237,7 +237,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
break;
|
||||
|
@ -385,12 +385,6 @@ static int add_mount(
|
||||
"SourcePath=%s\n",
|
||||
source);
|
||||
|
||||
/* All mounts under /sysroot need to happen later, at initrd-fs.target time. IOW, it's not
|
||||
* technically part of the basic initrd filesystem itself, and so shouldn't inherit the default
|
||||
* Before=local-fs.target dependency. */
|
||||
if (in_initrd() && path_startswith(where, "/sysroot"))
|
||||
fprintf(f, "DefaultDependencies=no\n");
|
||||
|
||||
if (STRPTR_IN_SET(fstype, "nfs", "nfs4") && !(flags & AUTOMOUNT) &&
|
||||
fstab_test_yes_no_option(opts, "bg\0" "fg\0")) {
|
||||
/* The default retry timeout that mount.nfs uses for 'bg' mounts
|
||||
@ -405,9 +399,6 @@ static int add_mount(
|
||||
SET_FLAG(flags, NOFAIL, true);
|
||||
}
|
||||
|
||||
if (!(flags & NOFAIL) && !(flags & AUTOMOUNT))
|
||||
fprintf(f, "Before=%s\n", post);
|
||||
|
||||
if (!(flags & AUTOMOUNT) && opts) {
|
||||
r = write_after(f, opts);
|
||||
if (r < 0)
|
||||
@ -529,8 +520,6 @@ static int add_mount(
|
||||
"Documentation=man:fstab(5) man:systemd-fstab-generator(8)\n",
|
||||
source);
|
||||
|
||||
fprintf(f, "Before=%s\n", post);
|
||||
|
||||
if (opts) {
|
||||
r = write_after(f, opts);
|
||||
if (r < 0)
|
||||
|
@ -192,9 +192,9 @@ static int list_homes(int argc, char *argv[], void *userdata) {
|
||||
|
||||
if (arg_legend && !arg_json) {
|
||||
if (table_get_rows(table) > 1)
|
||||
printf("\n%zu homes listed.\n", table_get_rows(table) - 1);
|
||||
printf("\n%zu home areas listed.\n", table_get_rows(table) - 1);
|
||||
else
|
||||
printf("No homes.\n");
|
||||
printf("No home areas.\n");
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -2263,20 +2263,20 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
printf("%1$s [OPTIONS...] COMMAND ...\n\n"
|
||||
"%2$sCreate, manipulate or inspect home directories.%3$s\n"
|
||||
"\n%4$sCommands:%5$s\n"
|
||||
" list List homes\n"
|
||||
" activate USER… Activate home\n"
|
||||
" deactivate USER… Deactivate home\n"
|
||||
" inspect USER… Inspect home\n"
|
||||
" authenticate USER… Authenticate home\n"
|
||||
" list List home areas\n"
|
||||
" activate USER… Activate a home area\n"
|
||||
" deactivate USER… Deactivate a home area\n"
|
||||
" inspect USER… Inspect a home area\n"
|
||||
" authenticate USER… Authenticate a home area\n"
|
||||
" create USER Create a home area\n"
|
||||
" remove USER… Remove a home area\n"
|
||||
" update USER Update a home area\n"
|
||||
" passwd USER Change password of a home area\n"
|
||||
" resize USER SIZE Resize a home area\n"
|
||||
" lock USER… Temporarily lock an active home\n"
|
||||
" unlock USER… Unlock a temporarily locked home\n"
|
||||
" lock-all Lock all suitable homes\n"
|
||||
" with USER [COMMAND…] Run shell or command with access to home\n"
|
||||
" lock USER… Temporarily lock an active home area\n"
|
||||
" unlock USER… Unlock a temporarily locked home area\n"
|
||||
" lock-all Lock all suitable home areas\n"
|
||||
" with USER [COMMAND…] Run shell or command with access to a home area\n"
|
||||
"\n%4$sOptions:%5$s\n"
|
||||
" -h --help Show this help\n"
|
||||
" --version Show package version\n"
|
||||
@ -2377,7 +2377,7 @@ static int help(int argc, char *argv[], void *userdata) {
|
||||
"\n%4$sCIFS User Record Properties:%5$s\n"
|
||||
" --cifs-domain=DOMAIN CIFS (Windows) domain\n"
|
||||
" --cifs-user-name=USER CIFS (Windows) user name\n"
|
||||
" --cifs-service=SERVICE CIFS (Windows) service to mount as home\n"
|
||||
" --cifs-service=SERVICE CIFS (Windows) service to mount as home area\n"
|
||||
"\n%4$sLogin Behaviour User Record Properties:%5$s\n"
|
||||
" --stop-delay=SECS How long to leave user services running after\n"
|
||||
" logout\n"
|
||||
|
@ -976,9 +976,9 @@ static ssize_t read_datagram(int fd, struct ucred *ret_sender, void **ret) {
|
||||
.msg_controllen = sizeof(control),
|
||||
};
|
||||
|
||||
m = recvmsg(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
m = recvmsg_safe(fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (m < 0)
|
||||
return -errno;
|
||||
return m;
|
||||
|
||||
cmsg_close_all(&mh);
|
||||
|
||||
|
@ -985,7 +985,7 @@ static int home_remove(UserRecord *h) {
|
||||
assert(ip);
|
||||
|
||||
if (stat(ip, &st) < 0) {
|
||||
if (errno != -ENOENT)
|
||||
if (errno != ENOENT)
|
||||
return log_error_errno(errno, "Failed to stat() %s: %m", ip);
|
||||
|
||||
} else {
|
||||
|
@ -258,8 +258,10 @@ static int handle_generic_user_record_error(
|
||||
|
||||
if (strv_isempty(secret->password))
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password: ");
|
||||
else
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password incorrect or not sufficient for authentication of user %s, please try again: ", user_name);
|
||||
else {
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Password incorrect or not sufficient for authentication of user %s.", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, try again: ");
|
||||
}
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -277,10 +279,13 @@ static int handle_generic_user_record_error(
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_BAD_PASSWORD_AND_NO_TOKEN)) {
|
||||
_cleanup_(erase_and_freep) char *newp = NULL;
|
||||
|
||||
if (strv_isempty(secret->password))
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token of user %s not inserted, please enter password: ", user_name);
|
||||
else
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Password incorrect or not sufficient, and configured security token of user %s not inserted, please enter password: ", user_name);
|
||||
if (strv_isempty(secret->password)) {
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token of user %s not inserted.", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Try again with password: ");
|
||||
} else {
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Password incorrect or not sufficient, and configured security token of user %s not inserted.", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Try again with password: ");
|
||||
}
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -298,7 +303,7 @@ static int handle_generic_user_record_error(
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_PIN_NEEDED)) {
|
||||
_cleanup_(erase_and_freep) char *newp = NULL;
|
||||
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Please enter security token PIN: ");
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN: ");
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -326,7 +331,8 @@ static int handle_generic_user_record_error(
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN)) {
|
||||
_cleanup_(erase_and_freep) char *newp = NULL;
|
||||
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect, please enter PIN for security token of user %s again: ", user_name);
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN incorrect for user %s.", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: ");
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -344,7 +350,8 @@ static int handle_generic_user_record_error(
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN_FEW_TRIES_LEFT)) {
|
||||
_cleanup_(erase_and_freep) char *newp = NULL;
|
||||
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect (only a few tries left!), please enter PIN for security token of user %s again: ", user_name);
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN of user %s incorrect (only a few tries left!)", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: ");
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -362,7 +369,8 @@ static int handle_generic_user_record_error(
|
||||
} else if (sd_bus_error_has_name(error, BUS_ERROR_TOKEN_BAD_PIN_ONE_TRY_LEFT)) {
|
||||
_cleanup_(erase_and_freep) char *newp = NULL;
|
||||
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Security token PIN incorrect (only one try left!), please enter PIN for security token of user %s again: ", user_name);
|
||||
(void) pam_prompt(handle, PAM_ERROR_MSG, NULL, "Security token PIN of user %s incorrect (only one try left!)", user_name);
|
||||
r = pam_prompt(handle, PAM_PROMPT_ECHO_OFF, &newp, "Sorry, retry security token PIN: ");
|
||||
if (r != PAM_SUCCESS)
|
||||
return PAM_CONV_ERR; /* no logging here */
|
||||
|
||||
@ -411,7 +419,7 @@ static int acquire_home(
|
||||
|
||||
/* If we already have acquired the fd, let's shortcut this */
|
||||
r = pam_get_data(handle, "systemd-home-fd", &home_fd_ptr);
|
||||
if (r == PAM_SUCCESS && PTR_TO_INT(home_fd_ptr) >= 0)
|
||||
if (r == PAM_SUCCESS && PTR_TO_FD(home_fd_ptr) >= 0)
|
||||
return PAM_SUCCESS;
|
||||
|
||||
r = pam_acquire_bus_connection(handle, &bus);
|
||||
|
@ -148,7 +148,7 @@ int suggest_passwords(void) {
|
||||
|
||||
pwquality_maybe_disable_dictionary(pwq);
|
||||
|
||||
suggestions = new0(char*, N_SUGGESTIONS);
|
||||
suggestions = new0(char*, N_SUGGESTIONS+1);
|
||||
if (!suggestions)
|
||||
return log_oom();
|
||||
|
||||
|
@ -172,8 +172,8 @@ static int import_fs(int argc, char *argv[], void *userdata) {
|
||||
progress.limit = (RateLimit) { 200*USEC_PER_MSEC, 1 };
|
||||
|
||||
/* Hook into SIGINT/SIGTERM, so that we can cancel things then */
|
||||
assert(sigaction(SIGINT, &sa, &old_sigint_sa) >= 0);
|
||||
assert(sigaction(SIGTERM, &sa, &old_sigterm_sa) >= 0);
|
||||
assert_se(sigaction(SIGINT, &sa, &old_sigint_sa) >= 0);
|
||||
assert_se(sigaction(SIGTERM, &sa, &old_sigterm_sa) >= 0);
|
||||
|
||||
r = btrfs_subvol_snapshot_fd_full(
|
||||
fd,
|
||||
@ -220,8 +220,8 @@ static int import_fs(int argc, char *argv[], void *userdata) {
|
||||
|
||||
finish:
|
||||
/* Put old signal handlers into place */
|
||||
assert(sigaction(SIGINT, &old_sigint_sa, NULL) >= 0);
|
||||
assert(sigaction(SIGTERM, &old_sigterm_sa, NULL) >= 0);
|
||||
assert_se(sigaction(SIGINT, &old_sigint_sa, NULL) >= 0);
|
||||
assert_se(sigaction(SIGTERM, &old_sigterm_sa, NULL) >= 0);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -565,13 +565,11 @@ static int manager_on_notify(sd_event_source *s, int fd, uint32_t revents, void
|
||||
ssize_t n;
|
||||
int r;
|
||||
|
||||
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (IN_SET(errno, EAGAIN, EINTR))
|
||||
return 0;
|
||||
|
||||
return -errno;
|
||||
}
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (IN_SET(n, -EAGAIN, -EINTR))
|
||||
return 0;
|
||||
if (n < 0)
|
||||
return (int) n;
|
||||
|
||||
cmsg_close_all(&msghdr);
|
||||
|
||||
|
@ -410,5 +410,5 @@ int open_journal_for_upload(Uploader *u,
|
||||
cursor);
|
||||
}
|
||||
|
||||
return process_journal_input(u, 1 + !!after_cursor);
|
||||
return process_journal_input(u, !!after_cursor);
|
||||
}
|
||||
|
@ -679,7 +679,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
break;
|
||||
|
||||
case ARG_FILE:
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
break;
|
||||
|
@ -60,7 +60,7 @@ static void mpi_export(void *buf, size_t buflen, const gcry_mpi_t x) {
|
||||
|
||||
static gcry_mpi_t mpi_import(const void *buf, size_t buflen) {
|
||||
gcry_mpi_t h;
|
||||
unsigned len;
|
||||
_unused_ unsigned len;
|
||||
|
||||
assert_se(gcry_mpi_scan(&h, GCRYMPI_FMT_USG, buf, buflen, NULL) == 0);
|
||||
len = (gcry_mpi_get_nbits(h) + 7) / 8;
|
||||
|
@ -705,7 +705,7 @@ static int parse_argv(int argc, char *argv[]) {
|
||||
* STDIN. To avoid confusion we hence don't document this feature. */
|
||||
arg_file_stdin = true;
|
||||
else {
|
||||
r = glob_extend(&arg_file, optarg);
|
||||
r = glob_extend(&arg_file, optarg, GLOB_NOCHECK);
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add paths: %m");
|
||||
}
|
||||
|
@ -539,10 +539,16 @@ int server_open_audit(Server *s) {
|
||||
if (r < 0)
|
||||
return log_error_errno(r, "Failed to add audit fd to event loop: %m");
|
||||
|
||||
/* We are listening now, try to enable audit */
|
||||
r = enable_audit(s->audit_fd, true);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to issue audit enable call: %m");
|
||||
if (s->set_audit >= 0) {
|
||||
/* We are listening now, try to enable audit if configured so */
|
||||
r = enable_audit(s->audit_fd, s->set_audit);
|
||||
if (r < 0)
|
||||
log_warning_errno(r, "Failed to issue audit enable call: %m");
|
||||
else if (s->set_audit > 0)
|
||||
log_debug("Auditing in kernel turned on.");
|
||||
else
|
||||
log_debug("Auditing in kernel turned off.");
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -22,6 +22,7 @@ Journal.Storage, config_parse_storage, 0, offsetof(Server, storage
|
||||
Journal.Compress, config_parse_compress, 0, offsetof(Server, compress)
|
||||
Journal.Seal, config_parse_bool, 0, offsetof(Server, seal)
|
||||
Journal.ReadKMsg, config_parse_bool, 0, offsetof(Server, read_kmsg)
|
||||
Journal.Audit, config_parse_tristate, 0, offsetof(Server, set_audit)
|
||||
Journal.SyncIntervalSec, config_parse_sec, 0, offsetof(Server, sync_interval_usec)
|
||||
# The following is a legacy name for compatibility
|
||||
Journal.RateLimitInterval, config_parse_sec, 0, offsetof(Server, ratelimit_interval)
|
||||
|
@ -1317,29 +1317,35 @@ int server_process_datagram(
|
||||
|
||||
iovec = IOVEC_MAKE(s->buffer, s->buffer_size - 1); /* Leave room for trailing NUL we add later */
|
||||
|
||||
n = recvmsg(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (n < 0) {
|
||||
if (IN_SET(errno, EINTR, EAGAIN))
|
||||
return 0;
|
||||
|
||||
return log_error_errno(errno, "recvmsg() failed: %m");
|
||||
n = recvmsg_safe(fd, &msghdr, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (IN_SET(n, -EINTR, -EAGAIN))
|
||||
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_error_errno(n, "recvmsg() failed: %m");
|
||||
|
||||
CMSG_FOREACH(cmsg, &msghdr)
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_CREDENTIALS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred)))
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
||||
assert(!ucred);
|
||||
ucred = (struct ucred*) CMSG_DATA(cmsg);
|
||||
else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_SECURITY) {
|
||||
assert(!label);
|
||||
label = (char*) CMSG_DATA(cmsg);
|
||||
label_len = cmsg->cmsg_len - CMSG_LEN(0);
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SO_TIMESTAMP &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval)))
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct timeval))) {
|
||||
assert(!tv);
|
||||
tv = (struct timeval*) CMSG_DATA(cmsg);
|
||||
else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
} else if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_RIGHTS) {
|
||||
assert(!fds);
|
||||
fds = (int*) CMSG_DATA(cmsg);
|
||||
n_fds = (cmsg->cmsg_len - CMSG_LEN(0)) / sizeof(int);
|
||||
}
|
||||
@ -2208,6 +2214,8 @@ int server_init(Server *s, const char *namespace) {
|
||||
.compress.threshold_bytes = (uint64_t) -1,
|
||||
.seal = true,
|
||||
|
||||
.set_audit = true,
|
||||
|
||||
.watchdog_usec = USEC_INFINITY,
|
||||
|
||||
.sync_interval_usec = DEFAULT_SYNC_INTERVAL_USEC,
|
||||
|
@ -108,6 +108,7 @@ struct Server {
|
||||
JournalCompressOptions compress;
|
||||
bool seal;
|
||||
bool read_kmsg;
|
||||
int set_audit;
|
||||
|
||||
bool forward_to_kmsg;
|
||||
bool forward_to_syslog;
|
||||
|
@ -512,8 +512,8 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
|
||||
goto terminate;
|
||||
}
|
||||
|
||||
/* If the buffer is full already (discounting the extra NUL we need), add room for another 1K */
|
||||
if (s->length + 1 >= s->allocated) {
|
||||
/* If the buffer is almost full, add room for another 1K */
|
||||
if (s->length + 512 >= s->allocated) {
|
||||
if (!GREEDY_REALLOC(s->buffer, s->allocated, s->length + 1 + 1024)) {
|
||||
log_oom();
|
||||
goto terminate;
|
||||
@ -545,6 +545,7 @@ static int stdout_stream_process(sd_event_source *es, int fd, uint32_t revents,
|
||||
if (cmsg->cmsg_level == SOL_SOCKET &&
|
||||
cmsg->cmsg_type == SCM_CREDENTIALS &&
|
||||
cmsg->cmsg_len == CMSG_LEN(sizeof(struct ucred))) {
|
||||
assert(!ucred);
|
||||
ucred = (struct ucred *)CMSG_DATA(cmsg);
|
||||
break;
|
||||
}
|
||||
|
@ -41,3 +41,4 @@
|
||||
#MaxLevelWall=emerg
|
||||
#LineMax=48K
|
||||
#ReadKMsg=yes
|
||||
#Audit=yes
|
||||
|
@ -22,4 +22,5 @@ static void test_audit_type(void) {
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
test_audit_type();
|
||||
return 0;
|
||||
}
|
||||
|
@ -1837,7 +1837,7 @@ static int client_receive_message_raw(
|
||||
|
||||
sd_dhcp_client *client = userdata;
|
||||
_cleanup_free_ DHCPPacket *packet = NULL;
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct tpacket_auxdata))];
|
||||
uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct tpacket_auxdata))];
|
||||
struct iovec iov = {};
|
||||
struct msghdr msg = {
|
||||
.msg_iov = &iov,
|
||||
|
@ -263,7 +263,7 @@ static int dhcp_server_send_udp(sd_dhcp_server *server, be32_t destination,
|
||||
.iov_base = message,
|
||||
.iov_len = len,
|
||||
};
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))] = {};
|
||||
uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))] = {};
|
||||
struct msghdr msg = {
|
||||
.msg_name = &dest,
|
||||
.msg_namelen = sizeof(dest.in),
|
||||
@ -930,7 +930,7 @@ int dhcp_server_handle_message(sd_dhcp_server *server, DHCPMessage *message,
|
||||
static int server_receive_message(sd_event_source *s, int fd,
|
||||
uint32_t revents, void *userdata) {
|
||||
_cleanup_free_ DHCPMessage *message = NULL;
|
||||
uint8_t cmsgbuf[CMSG_LEN(sizeof(struct in_pktinfo))];
|
||||
uint8_t cmsgbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
|
||||
sd_dhcp_server *server = userdata;
|
||||
struct iovec iov = {};
|
||||
struct msghdr msg = {
|
||||
|
@ -590,8 +590,7 @@ _public_ int sd_radv_add_prefix(sd_radv *ra, sd_radv_prefix *p, int dynamic) {
|
||||
cur->valid_until = valid_until;
|
||||
cur->preferred_until = preferred_until;
|
||||
|
||||
log_radv("%s prefix %s/%u preferred %s valid %s",
|
||||
cur? "Updated": "Added",
|
||||
log_radv("Updated prefix %s/%u preferred %s valid %s",
|
||||
addr_p, p->opt.prefixlen,
|
||||
format_timespan(time_string_preferred, FORMAT_TIMESPAN_MAX,
|
||||
preferred, USEC_PER_SEC),
|
||||
@ -691,8 +690,7 @@ _public_ int sd_radv_add_route_prefix(sd_radv *ra, sd_radv_route_prefix *p, int
|
||||
if (valid_until == USEC_INFINITY)
|
||||
return -EOVERFLOW;
|
||||
|
||||
log_radv("%s route prefix %s/%u valid %s",
|
||||
cur? "Updated": "Added",
|
||||
log_radv("Updated route prefix %s/%u valid %s",
|
||||
strempty(pretty), p->opt.prefixlen,
|
||||
format_timespan(time_string_valid, FORMAT_TIMESPAN_MAX, valid, USEC_PER_SEC));
|
||||
|
||||
|
@ -87,4 +87,5 @@ int main(int argc, char *argv[]) {
|
||||
test_dhcp_lease_parse_search_domains_no_data();
|
||||
test_dhcp_lease_parse_search_domains_loops();
|
||||
test_dhcp_lease_parse_search_domains_wrong_len();
|
||||
return 0;
|
||||
}
|
||||
|
@ -451,7 +451,7 @@ int bus_message_from_header(
|
||||
if (!IN_SET(h->version, 1, 2))
|
||||
return -EBADMSG;
|
||||
|
||||
if (h->type == _SD_BUS_MESSAGE_TYPE_INVALID)
|
||||
if (h->type <= _SD_BUS_MESSAGE_TYPE_INVALID || h->type >= _SD_BUS_MESSAGE_TYPE_MAX)
|
||||
return -EBADMSG;
|
||||
|
||||
if (!IN_SET(h->endian, BUS_LITTLE_ENDIAN, BUS_BIG_ENDIAN))
|
||||
@ -590,7 +590,7 @@ _public_ int sd_bus_message_new(
|
||||
assert_return(bus, -ENOTCONN);
|
||||
assert_return(bus->state != BUS_UNSET, -ENOTCONN);
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
|
||||
assert_return(type > _SD_BUS_MESSAGE_TYPE_INVALID && type < _SD_BUS_MESSAGE_TYPE_MAX, -EINVAL);
|
||||
|
||||
t = malloc0(ALIGN(sizeof(sd_bus_message)) + sizeof(struct bus_header));
|
||||
if (!t)
|
||||
@ -1297,19 +1297,18 @@ static int message_add_offset(sd_bus_message *m, size_t offset) {
|
||||
}
|
||||
|
||||
static void message_extend_containers(sd_bus_message *m, size_t expand) {
|
||||
struct bus_container *c;
|
||||
|
||||
assert(m);
|
||||
|
||||
if (expand <= 0)
|
||||
return;
|
||||
|
||||
/* Update counters */
|
||||
for (c = m->containers; c < m->containers + m->n_containers; c++) {
|
||||
if (m->n_containers <= 0)
|
||||
return;
|
||||
|
||||
/* Update counters */
|
||||
for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
|
||||
if (c->array_size)
|
||||
*c->array_size += expand;
|
||||
}
|
||||
}
|
||||
|
||||
static void *message_extend_body(
|
||||
@ -1372,7 +1371,6 @@ static void *message_extend_body(
|
||||
if (r < 0)
|
||||
return NULL;
|
||||
} else {
|
||||
struct bus_container *c;
|
||||
void *op;
|
||||
size_t os, start_part, end_part;
|
||||
|
||||
@ -1393,8 +1391,9 @@ static void *message_extend_body(
|
||||
}
|
||||
|
||||
/* Readjust pointers */
|
||||
for (c = m->containers; c < m->containers + m->n_containers; c++)
|
||||
c->array_size = adjust_pointer(c->array_size, op, os, part->data);
|
||||
if (m->n_containers > 0)
|
||||
for (struct bus_container *c = m->containers; c < m->containers + m->n_containers; c++)
|
||||
c->array_size = adjust_pointer(c->array_size, op, os, part->data);
|
||||
|
||||
m->error.message = (const char*) adjust_pointer(m->error.message, op, os, part->data);
|
||||
}
|
||||
@ -5202,29 +5201,34 @@ int bus_message_parse_fields(sd_bus_message *m) {
|
||||
* table */
|
||||
m->user_body_size = m->body_size - ((char*) m->footer + m->footer_accessible - p);
|
||||
|
||||
/* Pull out the offset table for the fields array */
|
||||
sz = bus_gvariant_determine_word_size(m->fields_size, 0);
|
||||
if (sz > 0) {
|
||||
size_t framing;
|
||||
void *q;
|
||||
/* Pull out the offset table for the fields array, if any */
|
||||
if (m->fields_size > 0) {
|
||||
sz = bus_gvariant_determine_word_size(m->fields_size, 0);
|
||||
if (sz > 0) {
|
||||
size_t framing;
|
||||
void *q;
|
||||
|
||||
ri = m->fields_size - sz;
|
||||
r = message_peek_fields(m, &ri, 1, sz, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
if (m->fields_size < sz)
|
||||
return -EBADMSG;
|
||||
|
||||
framing = bus_gvariant_read_word_le(q, sz);
|
||||
if (framing >= m->fields_size - sz)
|
||||
return -EBADMSG;
|
||||
if ((m->fields_size - framing) % sz != 0)
|
||||
return -EBADMSG;
|
||||
ri = m->fields_size - sz;
|
||||
r = message_peek_fields(m, &ri, 1, sz, &q);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
ri = framing;
|
||||
r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
|
||||
if (r < 0)
|
||||
return r;
|
||||
framing = bus_gvariant_read_word_le(q, sz);
|
||||
if (framing >= m->fields_size - sz)
|
||||
return -EBADMSG;
|
||||
if ((m->fields_size - framing) % sz != 0)
|
||||
return -EBADMSG;
|
||||
|
||||
n_offsets = (m->fields_size - framing) / sz;
|
||||
ri = framing;
|
||||
r = message_peek_fields(m, &ri, 1, m->fields_size - framing, &offsets);
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
n_offsets = (m->fields_size - framing) / sz;
|
||||
}
|
||||
}
|
||||
} else
|
||||
m->user_body_size = m->body_size;
|
||||
@ -5492,6 +5496,9 @@ int bus_message_parse_fields(sd_bus_message *m) {
|
||||
if (m->reply_cookie == 0 || !m->error.name)
|
||||
return -EBADMSG;
|
||||
break;
|
||||
|
||||
default:
|
||||
assert_not_reached("Bad message type");
|
||||
}
|
||||
|
||||
/* Refuse non-local messages that claim they are local */
|
||||
|
@ -56,12 +56,18 @@ static int node_vtable_get_userdata(
|
||||
static void *vtable_method_convert_userdata(const sd_bus_vtable *p, void *u) {
|
||||
assert(p);
|
||||
|
||||
if (!u)
|
||||
return SIZE_TO_PTR(p->x.method.offset); /* don't add offset on NULL, to make ubsan happy */
|
||||
|
||||
return (uint8_t*) u + p->x.method.offset;
|
||||
}
|
||||
|
||||
static void *vtable_property_convert_userdata(const sd_bus_vtable *p, void *u) {
|
||||
assert(p);
|
||||
|
||||
if (!u)
|
||||
return SIZE_TO_PTR(p->x.property.offset); /* as above */
|
||||
|
||||
return (uint8_t*) u + p->x.property.offset;
|
||||
}
|
||||
|
||||
|
@ -557,17 +557,24 @@ static int bus_socket_read_auth(sd_bus *b) {
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
k = recvmsg(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (k < 0 && errno == ENOTSOCK) {
|
||||
k = recvmsg_safe(b->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (k == -ENOTSOCK) {
|
||||
b->prefer_readv = true;
|
||||
k = readv(b->input_fd, &iov, 1);
|
||||
if (k < 0)
|
||||
k = -errno;
|
||||
} else
|
||||
handle_cmsg = true;
|
||||
}
|
||||
if (k == -EAGAIN)
|
||||
return 0;
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
if (k == 0)
|
||||
return (int) k;
|
||||
if (k == 0) {
|
||||
if (handle_cmsg)
|
||||
cmsg_close_all(&mh); /* paranoia, we shouldn't have gotten any fds on EOF */
|
||||
return -ECONNRESET;
|
||||
}
|
||||
|
||||
b->rbuffer_size += k;
|
||||
|
||||
@ -1030,8 +1037,10 @@ int bus_socket_write_message(sd_bus *bus, sd_bus_message *m, size_t *idx) {
|
||||
if (m->n_fds > 0 && *idx == 0) {
|
||||
struct cmsghdr *control;
|
||||
|
||||
mh.msg_control = control = alloca(CMSG_SPACE(sizeof(int) * m->n_fds));
|
||||
mh.msg_controllen = control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
|
||||
mh.msg_controllen = CMSG_SPACE(sizeof(int) * m->n_fds);
|
||||
mh.msg_control = alloca0(mh.msg_controllen);
|
||||
control = CMSG_FIRSTHDR(&mh);
|
||||
control->cmsg_len = CMSG_LEN(sizeof(int) * m->n_fds);
|
||||
control->cmsg_level = SOL_SOCKET;
|
||||
control->cmsg_type = SCM_RIGHTS;
|
||||
memcpy(CMSG_DATA(control), m->fds, sizeof(int) * m->n_fds);
|
||||
@ -1193,17 +1202,24 @@ int bus_socket_read_message(sd_bus *bus) {
|
||||
mh.msg_control = &control;
|
||||
mh.msg_controllen = sizeof(control);
|
||||
|
||||
k = recvmsg(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (k < 0 && errno == ENOTSOCK) {
|
||||
k = recvmsg_safe(bus->input_fd, &mh, MSG_DONTWAIT|MSG_CMSG_CLOEXEC);
|
||||
if (k == -ENOTSOCK) {
|
||||
bus->prefer_readv = true;
|
||||
k = readv(bus->input_fd, &iov, 1);
|
||||
if (k < 0)
|
||||
k = -errno;
|
||||
} else
|
||||
handle_cmsg = true;
|
||||
}
|
||||
if (k == -EAGAIN)
|
||||
return 0;
|
||||
if (k < 0)
|
||||
return errno == EAGAIN ? 0 : -errno;
|
||||
if (k == 0)
|
||||
return (int) k;
|
||||
if (k == 0) {
|
||||
if (handle_cmsg)
|
||||
cmsg_close_all(&mh); /* On EOF we shouldn't have gotten an fd, but let's make sure */
|
||||
return -ECONNRESET;
|
||||
}
|
||||
|
||||
bus->rbuffer_size += k;
|
||||
|
||||
|
@ -317,7 +317,7 @@ static void* client1(void *p) {
|
||||
|
||||
finish:
|
||||
if (bus) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL;
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
@ -485,7 +485,7 @@ static void* client2(void *p) {
|
||||
|
||||
finish:
|
||||
if (bus) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *q;
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *q = NULL;
|
||||
|
||||
r = sd_bus_message_new_method_call(
|
||||
bus,
|
||||
|
@ -12,7 +12,6 @@
|
||||
|
||||
#define RTNL_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
|
||||
|
||||
#define RTNL_WQUEUE_MAX 1024
|
||||
#define RTNL_RQUEUE_MAX 64*1024
|
||||
|
||||
#define RTNL_CONTAINER_DEPTH 32
|
||||
|
@ -15,8 +15,7 @@
|
||||
#include "socket-util.h"
|
||||
#include "strv.h"
|
||||
|
||||
#define GET_CONTAINER(m, i) ((i) < (m)->n_containers ? (struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset) : NULL)
|
||||
#define PUSH_CONTAINER(m, new) (m)->container_offsets[(m)->n_containers++] = (uint8_t*)(new) - (uint8_t*)(m)->hdr;
|
||||
#define GET_CONTAINER(m, i) ((struct rtattr*)((uint8_t*)(m)->hdr + (m)->containers[i].offset))
|
||||
|
||||
#define RTA_TYPE(rta) ((rta)->rta_type & NLA_TYPE_MASK)
|
||||
#define RTA_FLAGS(rta) ((rta)->rta_type & ~NLA_TYPE_MASK)
|
||||
@ -452,7 +451,8 @@ int sd_netlink_message_open_container(sd_netlink_message *m, unsigned short type
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -ERANGE);
|
||||
/* m->containers[m->n_containers + 1] is accessed both in read and write. Prevent access out of bound */
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = message_attribute_has_type(m, &size, type, NETLINK_TYPE_NESTED);
|
||||
if (r < 0) {
|
||||
@ -499,6 +499,7 @@ int sd_netlink_message_open_container_union(sd_netlink_message *m, unsigned shor
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = type_system_get_type_system_union(m->containers[m->n_containers].type_system, &type_system_union, type);
|
||||
if (r < 0)
|
||||
@ -541,6 +542,7 @@ int sd_netlink_message_open_array(sd_netlink_message *m, uint16_t type) {
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(!m->sealed, -EPERM);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -ERANGE);
|
||||
|
||||
r = add_rtattr(m, type | NLA_F_NESTED, NULL, 0);
|
||||
if (r < 0)
|
||||
@ -939,7 +941,7 @@ int sd_netlink_message_enter_container(sd_netlink_message *m, unsigned short typ
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
r = type_system_get_type(m->containers[m->n_containers].type_system,
|
||||
&nl_type,
|
||||
@ -1030,7 +1032,7 @@ int sd_netlink_message_enter_array(sd_netlink_message *m, unsigned short type_id
|
||||
int r;
|
||||
|
||||
assert_return(m, -EINVAL);
|
||||
assert_return(m->n_containers < RTNL_CONTAINER_DEPTH, -EINVAL);
|
||||
assert_return(m->n_containers < (RTNL_CONTAINER_DEPTH - 1), -EINVAL);
|
||||
|
||||
r = netlink_message_read_internal(m, type_id, &container, NULL);
|
||||
if (r < 0)
|
||||
|
@ -128,7 +128,7 @@ static void test_address_get(sd_netlink *rtnl, int ifindex) {
|
||||
}
|
||||
|
||||
static void test_route(sd_netlink *rtnl) {
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req;
|
||||
_cleanup_(sd_netlink_message_unrefp) sd_netlink_message *req = NULL;
|
||||
struct in_addr addr, addr_data;
|
||||
uint32_t index = 2, u32_data;
|
||||
int r;
|
||||
|
@ -2567,7 +2567,7 @@ static int method_can_reboot_parameter(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
@ -2699,7 +2699,7 @@ static int method_can_reboot_to_firmware_setup(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
@ -2888,7 +2888,7 @@ static int method_can_reboot_to_boot_loader_menu(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
@ -3079,7 +3079,7 @@ static int method_can_reboot_to_boot_loader_entry(
|
||||
void *userdata,
|
||||
sd_bus_error *error) {
|
||||
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
int r;
|
||||
|
||||
assert(message);
|
||||
|
@ -963,11 +963,23 @@ _public_ PAM_EXTERN int pam_sm_close_session(
|
||||
int argc, const char **argv) {
|
||||
|
||||
const void *existing = NULL;
|
||||
bool debug = false;
|
||||
const char *id;
|
||||
int r;
|
||||
|
||||
assert(handle);
|
||||
|
||||
if (parse_argv(handle,
|
||||
argc, argv,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
&debug) < 0)
|
||||
return PAM_SESSION_ERR;
|
||||
|
||||
if (debug)
|
||||
pam_syslog(handle, LOG_DEBUG, "pam-systemd shutting down");
|
||||
|
||||
/* Only release session if it wasn't pre-existing when we
|
||||
* tried to create it */
|
||||
(void) pam_get_data(handle, "systemd.existing", &existing);
|
||||
|
@ -2,11 +2,19 @@
|
||||
#
|
||||
# Used by systemd --user instances.
|
||||
|
||||
account required pam_unix.so
|
||||
m4_ifdef(`ENABLE_HOMED',
|
||||
-account sufficient pam_systemd_home.so
|
||||
)m4_dnl
|
||||
account sufficient pam_unix.so
|
||||
account required pam_permit.so
|
||||
|
||||
m4_ifdef(`HAVE_SELINUX',
|
||||
session required pam_selinux.so close
|
||||
session required pam_selinux.so nottys open
|
||||
)m4_dnl
|
||||
session required pam_loginuid.so
|
||||
session optional pam_keyinit.so force revoke
|
||||
m4_ifdef(`ENABLE_HOMED',
|
||||
-session optional pam_systemd_home.so
|
||||
)m4_dnl
|
||||
session optional pam_systemd.so
|
||||
|
@ -112,7 +112,7 @@ static int method_get_machine(sd_bus_message *message, void *userdata, sd_bus_er
|
||||
|
||||
static int method_get_image(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_free_ char *p = NULL;
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
const char *name;
|
||||
int r;
|
||||
|
||||
@ -471,7 +471,7 @@ static int method_get_machine_os_release(sd_bus_message *message, void *userdata
|
||||
static int method_list_images(sd_bus_message *message, void *userdata, sd_bus_error *error) {
|
||||
_cleanup_(sd_bus_message_unrefp) sd_bus_message *reply = NULL;
|
||||
_cleanup_hashmap_free_ Hashmap *images = NULL;
|
||||
Manager *m = userdata;
|
||||
_unused_ Manager *m = userdata;
|
||||
Image *image;
|
||||
Iterator i;
|
||||
int r;
|
||||
|
@ -44,7 +44,7 @@ static void l2tp_session_free(L2tpSession *s) {
|
||||
return;
|
||||
|
||||
if (s->tunnel && s->section)
|
||||
ordered_hashmap_remove(s->tunnel->sessions_by_section, s);
|
||||
ordered_hashmap_remove(s->tunnel->sessions_by_section, s->section);
|
||||
|
||||
network_config_section_free(s->section);
|
||||
|
||||
|
@ -828,7 +828,7 @@ int config_parse_macsec_key_id(
|
||||
|
||||
_cleanup_(macsec_transmit_association_free_or_set_invalidp) TransmitAssociation *a = NULL;
|
||||
_cleanup_(macsec_receive_association_free_or_set_invalidp) ReceiveAssociation *b = NULL;
|
||||
_cleanup_free_ void *p;
|
||||
_cleanup_free_ void *p = NULL;
|
||||
MACsec *s = userdata;
|
||||
uint8_t *dest;
|
||||
size_t l;
|
||||
|
@ -949,8 +949,8 @@ int config_parse_lifetime(const char *unit,
|
||||
if (r < 0)
|
||||
return r;
|
||||
|
||||
/* We accept only "forever", "infinity", or "0". */
|
||||
if (STR_IN_SET(rvalue, "forever", "infinity"))
|
||||
/* We accept only "forever", "infinity", empty, or "0". */
|
||||
if (STR_IN_SET(rvalue, "forever", "infinity", ""))
|
||||
k = CACHE_INFO_INFINITY_LIFE_TIME;
|
||||
else if (streq(rvalue, "0"))
|
||||
k = 0;
|
||||
|
@ -3969,7 +3969,7 @@ int link_save(Link *link) {
|
||||
if (link->dhcp6_client) {
|
||||
r = sd_dhcp6_client_get_lease(link->dhcp6_client, &dhcp6_lease);
|
||||
if (r < 0 && r != -ENOMSG)
|
||||
log_link_debug(link, "No DHCPv6 lease");
|
||||
log_link_debug_errno(link, r, "Failed to get DHCPv6 lease: %m");
|
||||
}
|
||||
|
||||
fprintf(f, "NETWORK_FILE=%s\n", link->network->filename);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "networkd-network.h"
|
||||
#include "string-table.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "tmpfile-util.h"
|
||||
|
||||
DEFINE_CONFIG_PARSE_ENUM(config_parse_lldp_mode, lldp_mode, LLDPMode, "Failed to parse LLDP= setting.");
|
||||
@ -36,10 +37,10 @@ bool link_lldp_rx_enabled(Link *link) {
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
/* LLDP should be handled on bridge slaves as those have a direct
|
||||
* connection to their peers not on the bridge master. Linux doesn't
|
||||
* even (by default) forward lldp packets to the bridge master.*/
|
||||
if (streq_ptr("bridge", link->kind))
|
||||
/* LLDP should be handled on bridge and bond slaves as those have a direct connection to their peers,
|
||||
* not on the bridge/bond master. Linux doesn't even (by default) forward lldp packets to the bridge
|
||||
* master.*/
|
||||
if (link->kind && STR_IN_SET(link->kind, "bridge", "bond"))
|
||||
return false;
|
||||
|
||||
return link->network->lldp_mode != LLDP_MODE_NO;
|
||||
|
@ -7,6 +7,7 @@
|
||||
|
||||
#include "alloc-util.h"
|
||||
#include "env-file.h"
|
||||
#include "escape.h"
|
||||
#include "fd-util.h"
|
||||
#include "hostname-util.h"
|
||||
#include "missing_network.h"
|
||||
@ -17,6 +18,7 @@
|
||||
#include "random-util.h"
|
||||
#include "socket-util.h"
|
||||
#include "string-util.h"
|
||||
#include "strv.h"
|
||||
#include "unaligned.h"
|
||||
|
||||
/* The LLDP spec calls this "txFastInit", see 9.2.5.19 */
|
||||
@ -52,6 +54,9 @@ bool link_lldp_emit_enabled(Link *link) {
|
||||
if (!link->network)
|
||||
return false;
|
||||
|
||||
if (link->kind && STR_IN_SET(link->kind, "bridge", "bond"))
|
||||
return false;
|
||||
|
||||
return link->network->lldp_emit != LLDP_EMIT_NO;
|
||||
}
|
||||
|
||||
|
@ -2190,7 +2190,7 @@ void manager_dirty(Manager *manager) {
|
||||
}
|
||||
|
||||
static int set_hostname_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
Manager *manager = userdata;
|
||||
_unused_ Manager *manager = userdata;
|
||||
const sd_bus_error *e;
|
||||
|
||||
assert(m);
|
||||
@ -2236,7 +2236,7 @@ int manager_set_hostname(Manager *m, const char *hostname) {
|
||||
}
|
||||
|
||||
static int set_timezone_handler(sd_bus_message *m, void *userdata, sd_bus_error *ret_error) {
|
||||
Manager *manager = userdata;
|
||||
_unused_ Manager *manager = userdata;
|
||||
const sd_bus_error *e;
|
||||
|
||||
assert(m);
|
||||
|
@ -253,4 +253,5 @@ int main(void) {
|
||||
test_network_get(manager, loopback);
|
||||
|
||||
assert_se(manager_rtnl_enumerate_links(manager) >= 0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -569,7 +569,7 @@ int mount_all(const char *dest,
|
||||
static const MountPoint mount_table[] = {
|
||||
/* First we list inner child mounts (i.e. mounts applied *after* entering user namespacing) */
|
||||
{ "proc", "/proc", "proc", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
MOUNT_FATAL|MOUNT_IN_USERNS },
|
||||
MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_MKDIR },
|
||||
|
||||
{ "/proc/sys", "/proc/sys", NULL, NULL, MS_BIND,
|
||||
MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */
|
||||
@ -599,23 +599,23 @@ int mount_all(const char *dest,
|
||||
PROC_READ_ONLY("/proc/scsi"),
|
||||
|
||||
{ "mqueue", "/dev/mqueue", "mqueue", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
MOUNT_IN_USERNS },
|
||||
MOUNT_IN_USERNS|MOUNT_MKDIR },
|
||||
|
||||
/* Then we list outer child mounts (i.e. mounts applied *before* entering user namespacing) */
|
||||
{ "tmpfs", "/tmp", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
|
||||
MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP },
|
||||
MOUNT_FATAL|MOUNT_APPLY_TMPFS_TMP|MOUNT_MKDIR },
|
||||
{ "tmpfs", "/sys", "tmpfs", "mode=555", MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
|
||||
MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS|MOUNT_MKDIR },
|
||||
{ "sysfs", "/sys", "sysfs", NULL, MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO }, /* skipped if above was mounted */
|
||||
MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO|MOUNT_MKDIR }, /* skipped if above was mounted */
|
||||
{ "sysfs", "/sys", "sysfs", NULL, MS_NOSUID|MS_NOEXEC|MS_NODEV,
|
||||
MOUNT_FATAL }, /* skipped if above was mounted */
|
||||
MOUNT_FATAL|MOUNT_MKDIR }, /* skipped if above was mounted */
|
||||
{ "tmpfs", "/dev", "tmpfs", "mode=755", MS_NOSUID|MS_STRICTATIME,
|
||||
MOUNT_FATAL },
|
||||
MOUNT_FATAL|MOUNT_MKDIR },
|
||||
{ "tmpfs", "/dev/shm", "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
|
||||
MOUNT_FATAL },
|
||||
MOUNT_FATAL|MOUNT_MKDIR },
|
||||
{ "tmpfs", "/run", "tmpfs", "mode=755", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
|
||||
MOUNT_FATAL },
|
||||
MOUNT_FATAL|MOUNT_MKDIR },
|
||||
|
||||
#if HAVE_SELINUX
|
||||
{ "/sys/fs/selinux", "/sys/fs/selinux", NULL, NULL, MS_BIND,
|
||||
@ -663,17 +663,19 @@ int mount_all(const char *dest,
|
||||
continue;
|
||||
}
|
||||
|
||||
r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
if (fatal && r != -EROFS)
|
||||
return log_error_errno(r, "Failed to create directory %s: %m", where);
|
||||
if (FLAGS_SET(mount_table[k].mount_settings, MOUNT_MKDIR)) {
|
||||
r = mkdir_userns_p(dest, where, 0755, (use_userns && !in_userns) ? uid_shift : UID_INVALID);
|
||||
if (r < 0 && r != -EEXIST) {
|
||||
if (fatal && r != -EROFS)
|
||||
return log_error_errno(r, "Failed to create directory %s: %m", where);
|
||||
|
||||
log_debug_errno(r, "Failed to create directory %s: %m", where);
|
||||
/* If we failed mkdir() or chown() due to the root
|
||||
* directory being read only, attempt to mount this fs
|
||||
* anyway and let mount_verbose log any errors */
|
||||
if (r != -EROFS)
|
||||
continue;
|
||||
log_debug_errno(r, "Failed to create directory %s: %m", where);
|
||||
|
||||
/* If we failed mkdir() or chown() due to the root directory being read only,
|
||||
* attempt to mount this fs anyway and let mount_verbose log any errors */
|
||||
if (r != -EROFS)
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
o = mount_table[k].options;
|
||||
|
@ -16,6 +16,7 @@ typedef enum MountSettingsMask {
|
||||
MOUNT_APPLY_TMPFS_TMP = 1 << 5, /* if set, /tmp will be mounted as tmpfs */
|
||||
MOUNT_ROOT_ONLY = 1 << 6, /* if set, only root mounts are mounted */
|
||||
MOUNT_NON_ROOT_ONLY = 1 << 7, /* if set, only non-root mounts are mounted */
|
||||
MOUNT_MKDIR = 1 << 8, /* if set, make directory to mount over first */
|
||||
} MountSettingsMask;
|
||||
|
||||
typedef enum CustomMountType {
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user