]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #8915 from yuwata/fix-8904
authorMichael Biebl <mbiebl@gmail.com>
Tue, 8 May 2018 13:03:27 +0000 (15:03 +0200)
committerGitHub <noreply@github.com>
Tue, 8 May 2018 13:03:27 +0000 (15:03 +0200)
 login: do not wall message on cancelling shutdown when Manager.enable_wall_messages is false

40 files changed:
TODO
doc/CGROUP_DELEGATION.md
doc/UIDS-GIDS.md
man/journal-remote.conf.xml
man/journal-upload.conf.xml
man/journalctl.xml
man/rules/meson.build
man/systemd-journal-remote.service.xml [moved from man/systemd-journal-remote.xml with 87% similarity]
man/systemd-journal-upload.service.xml [moved from man/systemd-journal-upload.xml with 90% similarity]
man/systemd-networkd-wait-online.service.xml
man/systemd.link.xml
man/systemd.network.xml
man/systemd.special.xml
meson.build
src/core/meson.build
src/core/namespace.c
src/libsystemd-network/dhcp-option.c
src/libsystemd-network/sd-dhcp-client.c
src/login/meson.build
src/network/networkd-dhcp4.c
src/network/networkd-network-gperf.gperf
src/network/networkd-network.c
src/network/networkd-network.h
src/nspawn/nspawn-cgroup.c
src/nspawn/nspawn-cgroup.h
src/nspawn/nspawn-mount.c
src/nspawn/nspawn-mount.h
src/nspawn/nspawn-register.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn.c
src/systemd/sd-dhcp-client.h
src/udev/net/ethtool-util.c
src/udev/net/ethtool-util.h
src/udev/net/link-config-gperf.gperf
src/udev/net/link-config.c
src/udev/net/link-config.h
sysusers.d/meson.build
tmpfiles.d/meson.build
tools/meson-apply-m4.sh [new file with mode: 0755]
units/meson.build

diff --git a/TODO b/TODO
index c8f75963905c35d0d325681513015fcc8a7b8b4c..5a0117260ed18d734da9616e46a268c0621a31e2 100644 (file)
--- a/TODO
+++ b/TODO
@@ -24,6 +24,10 @@ Janitorial Clean-ups:
 
 Features:
 
+* nspawn: greater control over hostname, resolv.conf, timezone, rlim
+
+* nspawn: when operating in a scope, also create /payload subcrgoup
+
 * the error paths in usbffs_dispatch_ep() leak memory
 
 * cgroups: figure out if we can somehow communicate in a cleaner way whether a
@@ -52,9 +56,6 @@ Features:
 
 * add --vacuum-xyz options to coredumpctl, matching those journalctl already has.
 
-* list the exit codes from the BSD/glibc <sysexits.h> in our own
-  exit-codes.[ch] tables.
-
 * SuccessExitStatus= and friends should probably also accept symbolic exit
   codes names, i.e. error codes from the list maintained in exit-codes.[ch]
 
index 412f0a5fa0e30a3ae1d43ccb178c27441ecce8d7..212283fd73d0b0e52432a76d011875c62235126d 100644 (file)
@@ -424,15 +424,16 @@ unified you (of course, I guess) need to provide only `/sys/fs/cgroup/` itself.
    cgroup tree of systemd itself is out of limits for you. It's fine to *read*
    from any attribute you like however. That's totally OK and welcome.
 
-4. ðŸš« When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a container
-   payload running systemd, then don't get the idea that you can bind mount
-   only a sub-tree of the host's cgroup tree into the container. Part of the
-   cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
+4. ðŸš« When not using `CLONE_NEWCGROUP` when delegating a sub-tree to a
+   container payload running systemd, then don't get the idea that you can bind
+   mount only a sub-tree of the host's cgroup tree into the container. Part of
+   the cgroup API is that `/proc/$PID/cgroup` reports the cgroup path of every
    process, and hence any path below `/sys/fs/cgroup/` needs to match what
    `/proc/$PID/cgroup` of the payload processes reports. What you can do safely
-   however, is mount the upper parts of the cgroup tree read-only or even
-   replace it with an intermediary `tmpfs`, as long as the path to the
-   delegated sub-tree remains accessible as-is.
+   however, is mount the upper parts of the cgroup tree read-only (or even
+   replace the middle bits with an intermediary `tmpfs` â€” but be careful not to
+   break the `statfs()` detection logic discussed above), as long as the path
+   to the delegated sub-tree remains accessible as-is.
 
 5. âš¡ Currently, the algorithm for mapping between slice/scope/service unit
    naming and their cgroup paths is not considered public API of systemd, and
index e19cc88162378b40c935639daa69c9f64923b8cc..c380bbe140a92da00615e5a7cdd2913588c047ff 100644 (file)
@@ -241,3 +241,38 @@ really unused. It just means that these ranges have no well-established
 pre-defined purposes between Linux, generic low-level distributions and
 `systemd`. There might very well be other packages that allocate from these
 ranges.
+
+## Notes on resolvability of user and group names
+
+User names, UIDs, group names and GIDs don't have to be resolvable using NSS
+(i.e. getpwuid() and getpwnam() and friends) all the time. However, systemd
+makes the following requirements:
+
+System users generally have to be resolvable during early boot already. This
+means they should not be provided by any networked service (as those usually
+become available during late boot only), except if a local cache is kept that
+makes them available during early boot too (i.e. before networking is
+up). Specifically, system users need to be resolvable at least before
+`systemd-udevd.service` and `systemd-tmpfiles.service` are started, as both
+need to resolve system users â€” but note that there might be more services
+requiring full resolvability of system users than just these two.
+
+Regular users do not need to be resolvable during early boot, it is sufficient
+if they become resolvable during late boot. Specifically, regular users need to
+be resolvable at the point in time the `nss-user-lookup.target` unit is
+reached. This target unit is generally used as synchronization point between
+providers of the user database and consumers of it. Services that require that
+the user database is fully available (for example, the login service
+`systemd-logind.service`) are ordered *after* it, while services that provide
+parts of the user database (for example an LDAP user database client) are
+ordered *before* it. Note that `nss-user-lookup.target` is a *passive* unit: in
+order to minimize synchronization points on systems that don't need it the unit
+is pulled into the initial transaction only if there's at least one service
+that really needs it, and that means only if there's a service providing the
+local user database somehow through IPC or suchlike. Or in other words: if you
+hack on some networked user database project, then make sure you order your
+service `Before=nss-user-lookup.target` and that you pull it in with
+`Wants=nss-user-lookup.target`. However, if you hack on some project that needs
+the user database to be up in full, then order your service
+`After=nss-user-lookup.target`, but do *not* pull it in via a `Wants=`
+dependency.
index db5e4efd5b25cef0846fb8825c354bf2f4d02b79..42ecabc807480fcbb47b8f4b37a885b216d7a010 100644 (file)
@@ -86,7 +86,7 @@
       <varlistentry>
         <term><varname>ServerCertificateFile=</varname></term>
 
-        <listitem><para>SSL CA certificate in PEM format.</para></listitem>
+        <listitem><para>SSL certificate in PEM format.</para></listitem>
       </varlistentry>
 
       <varlistentry>
   <refsect1>
       <title>See Also</title>
       <para>
-        <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+        <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       </para>
index 8e241370db001bf97545de94e3901ea239f79ba5..cd3335452afb28e889c1129840c3882baa68e3d5 100644 (file)
@@ -68,7 +68,8 @@
         <listitem><para>The URL to upload the journal entries to. See the description
         of <varname>--url=</varname> option in
         <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-        for the description of possible values.</para></listitem>
+        for the description of possible values. There is no default value, so either this
+        option or the command-line option must be always present to make an upload.</para></listitem>
       </varlistentry>
 
       <varlistentry>
@@ -96,7 +97,7 @@
   <refsect1>
       <title>See Also</title>
       <para>
-        <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+        <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
         <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
       </para>
index 1bec2b79fb5b4c815869915408c0db7f3d3f8128..12d6a80c573375b8f6afec685b12a89437538912 100644 (file)
@@ -976,8 +976,8 @@ journalctl _SYSTEMD_CGROUP=/user.slice/user-42.slice/session-c1.scope</programli
       <citerefentry><refentrytitle>systemd.journal-fields</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>journald.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd.time</refentrytitle><manvolnum>7</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
   </refsect1>
 </refentry>
index 6b07cfc4feb8eb339dcf1834ab98f58165e3f16c..e9759f16a15513f13cbf5fa3462cb86589a67879 100644 (file)
@@ -574,8 +574,14 @@ manpages = [
   '8',
   ['systemd-journal-gatewayd', 'systemd-journal-gatewayd.socket'],
   'HAVE_MICROHTTPD'],
- ['systemd-journal-remote', '8', [], 'HAVE_MICROHTTPD'],
- ['systemd-journal-upload', '8', [], 'HAVE_MICROHTTPD'],
+ ['systemd-journal-remote.service',
+  '8',
+  ['systemd-journal-remote', 'systemd-journal-remote.socket'],
+  'HAVE_MICROHTTPD'],
+ ['systemd-journal-upload.service',
+  '8',
+  ['systemd-journal-upload'],
+  'HAVE_MICROHTTPD'],
  ['systemd-journald.service',
   '8',
   ['systemd-journald',
similarity index 87%
rename from man/systemd-journal-remote.xml
rename to man/systemd-journal-remote.service.xml
index 1701495357937a671b7ca45e2fd87993990194f5..da7200c63a72d36293e7a905114766d3061dc951 100644 (file)
@@ -17,7 +17,7 @@
           xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
-    <title>systemd-journal-remote</title>
+    <title>systemd-journal-remote.service</title>
     <productname>systemd</productname>
 
     <authorgroup>
   </refentryinfo>
 
   <refmeta>
-    <refentrytitle>systemd-journal-remote</refentrytitle>
+    <refentrytitle>systemd-journal-remote.service</refentrytitle>
     <manvolnum>8</manvolnum>
   </refmeta>
 
   <refnamediv>
+    <refname>systemd-journal-remote.service</refname>
+    <refname>systemd-journal-remote.socket</refname>
     <refname>systemd-journal-remote</refname>
     <refpurpose>Receive journal messages over the network</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
+    <para><filename>systemd-journal-remote.service</filename></para>
+    <para><filename>systemd-journal-remote.socket</filename></para>
     <cmdsynopsis>
-      <command>systemd-journal-remote</command>
+      <command>/usr/lib/systemd/systemd-journal-remote</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="opt" rep="norepeat">-o/--output=<replaceable>DIR</replaceable>|<replaceable>FILE</replaceable></arg>
       <arg choice="opt" rep="repeat">SOURCES</arg>
   <refsect1>
     <title>Description</title>
 
-    <para>
-      <filename>systemd-journal-remote</filename> is a command to
-      receive serialized journal events and store them to the journal.
-      Input streams are in the
-      <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">
-        Journal Export Format
-      </ulink>,
-      i.e. like the output from
-      <command>journalctl --output=export</command>. For transport over
-      the network, this serialized stream is usually carried over an
-      HTTPS connection.
-    </para>
+    <para><command>systemd-journal-remote</command> is a command to receive serialized journal
+    events and store them to journal files. Input streams are in the
+    <ulink url="https://www.freedesktop.org/wiki/Software/systemd/export">Journal Export Format</ulink>,
+    i.e. like the output from <command>journalctl --output=export</command>. For transport over the
+    network, this serialized stream is usually carried over an HTTPS connection.</para>
+
+    <para><filename>systemd-journal-remote.service</filename> is a system service that uses
+    <command>systemd-journal-remote</command> to listen for connections.
+    <filename>systemd-journal-remote.socket</filename> configures the network address that
+    <filename>systemd-journal-remote.service</filename> listens on. By default this is port 19532.
+    What connections are accepted and how the received data is stored can be configured through the
+    <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+    configuration file.</para>
   </refsect1>
 
   <refsect1>
         interpreted as the (negated) file descriptor number, or an
         address suitable for <option>ListenStream=</option> (c.f.
         <citerefentry><refentrytitle>systemd.socket</refentrytitle><manvolnum>5</manvolnum></citerefentry>).
-        In the first case, matching file descriptor must be inherited
-        through
+        In the first case, the server listens on port 19532 by default,
+        and the matching file descriptor must be inherited through
         <varname>$LISTEN_FDS</varname>/<varname>$LISTEN_PID</varname>.
         In the second case, an HTTP or HTTPS server will be spawned on
         this port, respectively for <option>--listen-http=</option> and
@@ -351,11 +356,11 @@ systemd-journal-remote --url http://some.host:19531/entries?boot&amp;follow
   <refsect1>
     <title>See Also</title>
     <para>
-      <citerefentry><refentrytitle>systemd-journal-upload</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
-      <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
-      <citerefentry><refentrytitle>journal-remote.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>
+      <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-journal-upload.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
     </para>
   </refsect1>
 </refentry>
similarity index 90%
rename from man/systemd-journal-upload.xml
rename to man/systemd-journal-upload.service.xml
index 900706a34d640c096695bad6319f31b05c8d44c5..f923e53d29a60f6e1e6ff5f7bb15546bac353cb8 100644 (file)
@@ -17,7 +17,7 @@
           xmlns:xi="http://www.w3.org/2001/XInclude">
 
   <refentryinfo>
-    <title>systemd-journal-upload</title>
+    <title>systemd-journal-upload.service</title>
     <productname>systemd</productname>
 
     <authorgroup>
   </refentryinfo>
 
   <refmeta>
-    <refentrytitle>systemd-journal-upload</refentrytitle>
+    <refentrytitle>systemd-journal-upload.service</refentrytitle>
     <manvolnum>8</manvolnum>
   </refmeta>
 
   <refnamediv>
+    <refname>systemd-journal-upload.service</refname>
     <refname>systemd-journal-upload</refname>
     <refpurpose>Send journal messages over the network</refpurpose>
   </refnamediv>
 
   <refsynopsisdiv>
+    <para><filename>systemd-journal-upload.service</filename></para>
     <cmdsynopsis>
-      <command>systemd-journal-upload</command>
+      <command>/usr/lib/systemd/systemd-journal-upload</command>
       <arg choice="opt" rep="repeat">OPTIONS</arg>
       <arg choice="opt" rep="norepeat">-u/--url=<replaceable>URL</replaceable></arg>
       <arg choice="opt" rep="repeat">SOURCES</arg>
     Unless limited by one of the options specified below, all journal entries accessible to the user
     the program is running as will be uploaded, and then the program will wait and send new entries
     as they become available.</para>
+
+    <para><filename>systemd-journal-upload.service</filename> is a system service that uses
+    <command>systemd-journal-upload</command> to upload journal entries to a server. It uses the
+    configuration in
+    <citerefentry><refentrytitle>journal-upload.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>.
+    At least the <varname>URL=</varname> option must be specified.</para>
   </refsect1>
 
   <refsect1>
     <variablelist>
       <varlistentry>
         <term><option>-u</option></term>
-        <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable></option></term>
-        <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable></option></term>
+        <term><option>--url=<optional>https://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
+        <term><option>--url=<optional>http://</optional><replaceable>URL</replaceable>[:<replaceable>PORT</replaceable>]</option></term>
 
         <listitem><para>Upload to the specified
         address. <replaceable>URL</replaceable> may specify either
         just the hostname or both the protocol and
         hostname. <constant>https</constant> is the default.
+        The port number may be specified after a colon (<literal>:</literal>),
+        otherwise <constant>19532</constant> will be used by default.
         </para></listitem>
       </varlistentry>
 
@@ -281,7 +291,7 @@ openssl ca -batch -config ca.conf -notext -in $CLIENT.csr -out $CLIENT.pem
   <refsect1>
     <title>See Also</title>
     <para>
-      <citerefentry><refentrytitle>systemd-journal-remote</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
+      <citerefentry><refentrytitle>systemd-journal-remote.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>journalctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-journald.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>,
       <citerefentry><refentrytitle>systemd-journal-gatewayd.service</refentrytitle><manvolnum>8</manvolnum></citerefentry>
index 83186b4e2cc666e28bc1c71e1fa9f8cd2f3a02c7..3d5897bdad7e039a39c0529ea317d18dbf1174e9 100644 (file)
@@ -13,7 +13,7 @@
 <refentry id="systemd-networkd-wait-online.service" conditional='ENABLE_NETWORKD'>
 
   <refentryinfo>
-    <title>systemd-networkd.service</title>
+    <title>systemd-networkd-wait-online.service</title>
     <productname>systemd</productname>
 
     <authorgroup>
index c7c920913b373aada3eb36064a1e08228d2749f3..6857248ef3225fc675e10e27f42c6494e7dd6f54 100644 (file)
           Defaults to "unset".</para>
         </listitem>
       </varlistentry>
+      <varlistentry>
+        <term><varname>RxChannels=</varname></term>
+        <listitem>
+          <para>Sets the number of receive channels (a number between 1 and 4294967295) .</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>TxChannels=</varname></term>
+        <listitem>
+          <para>Sets the number of transmit channels (a number between 1 and 4294967295).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>OtherChannels=</varname></term>
+        <listitem>
+          <para>Sets the number of other channels (a number between 1 and 4294967295).</para>
+        </listitem>
+      </varlistentry>
+      <varlistentry>
+        <term><varname>CombinedChannels=</varname></term>
+        <listitem>
+          <para>Sets the number of combined set channels (a number between 1 and 4294967295).</para>
+        </listitem>
+      </varlistentry>
     </variablelist>
   </refsect1>
 
index 55db523e79c10490d1268746022a4205a4f1e893..da8b4663b8abd0901e212134541f0663a17a5a51 100644 (file)
           </listitem>
         </varlistentry>
 
+        <varlistentry>
+          <term><varname>UserClass=</varname></term>
+          <listitem>
+            <para>A DHCPv4 client can use UserClass option to identify the type or category of user or applications
+            it represents. The information contained in this option is a string that represents the user class of which
+            the client is a member. Each class sets an identifying string of information to be used by the DHCP
+            service to classify clients. Takes a whitespace-separated list of strings.</para>
+          </listitem>
+        </varlistentry>
+
         <varlistentry>
           <term><varname>DUIDType=</varname></term>
           <listitem>
index 4f96c3c4e68470aee16700a1005b431c9487f067..b6ac433f9c8789c1f07106eb759c4caa2ce72556 100644 (file)
       <varlistentry>
         <term><filename>nss-lookup.target</filename></term>
         <listitem>
-          <para>A target that should be used as synchronization point
-          for all host/network name service lookups. Note that this is
-          independent of user/group name lookups for which
-          <filename>nss-user-lookup.target</filename> should be used.
-          All services for which the availability of full host/network
-          name resolution is essential should be ordered after this
-          target, but not pull it in. systemd automatically adds
-          dependencies of type <varname>After=</varname> for this
-          target unit to all SysV init script service units with an
-          LSB header referring to the <literal>$named</literal>
-          facility.</para>
+          <para>A target that should be used as synchronization point for all host/network name service lookups. Note
+          that this is independent of UNIX user/group name lookups for which <filename>nss-user-lookup.target</filename>
+          should be used.  All services for which the availability of full host/network name resolution is essential
+          should be ordered after this target, but not pull it in. systemd automatically adds dependencies of type
+          <varname>After=</varname> for this target unit to all SysV init script service units with an LSB header
+          referring to the <literal>$named</literal> facility.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
         <term><filename>nss-user-lookup.target</filename></term>
         <listitem>
-          <para>A target that should be used as synchronization point
-          for all user/group name service lookups. Note that this is
-          independent of host/network name lookups for which
-          <filename>nss-lookup.target</filename> should be used. All
-          services for which the availability of the full user/group
-          database is essential should be ordered after this target,
-          but not pull it in. Note that system users are always
-          resolvable, and hence do not require any special ordering
-          against this target.</para>
+          <para>A target that should be used as synchronization point for all regular UNIX user/group name service
+          lookups. Note that this is independent of host/network name lookups for which
+          <filename>nss-lookup.target</filename> should be used. All services for which the availability of the full
+          user/group database is essential should be ordered after this target, but not pull it in. All services which
+          provide parts of the user/group database should be ordered before this target, and pull it in. Note that this
+          unit is only relevant for regular users and groups â€” system users and groups are required to be resolvable
+          during earliest boot already, and hence do not need any special ordering against this target.</para>
         </listitem>
       </varlistentry>
       <varlistentry>
index 3fa4f7f3271cd1aa97c365e4b7630c729f4d9407..eca424b784b9c65610a130a82a269b275b69fd9b 100644 (file)
@@ -17,7 +17,7 @@ project('systemd', 'c',
 libsystemd_version = '0.22.0'
 libudev_version = '1.6.10'
 
-# We need the same data in three different formats, ugh!
+# We need the same data in two different formats, ugh!
 # Also, for hysterical reasons, we use different variable
 # names, sometimes. Not all variables are included in every
 # set. Ugh, ugh, ugh!
@@ -29,8 +29,6 @@ substs = configuration_data()
 substs.set('PACKAGE_URL',          'https://www.freedesktop.org/wiki/Software/systemd')
 substs.set('PACKAGE_VERSION',      meson.project_version())
 
-m4_defines = []
-
 #####################################################################
 
 # Try to install the git pre-commit hook
@@ -67,10 +65,8 @@ endif
 
 sysvinit_path = get_option('sysvinit-path')
 sysvrcnd_path = get_option('sysvrcnd-path')
-have = sysvinit_path != '' and sysvrcnd_path != ''
-conf.set10('HAVE_SYSV_COMPAT', have,
+conf.set10('HAVE_SYSV_COMPAT', sysvinit_path != '' and sysvrcnd_path != '',
            description : 'SysV init scripts and rcN.d links are supported')
-m4_defines += have ? ['-DHAVE_SYSV_COMPAT'] : []
 
 # join_paths ignore the preceding arguments if an absolute component is
 # encountered, so this should canonicalize various paths when they are
@@ -754,13 +750,8 @@ else
 endif
 substs.set('USERS_GID', users_gid)
 
-if get_option('adm-group')
-        m4_defines += ['-DENABLE_ADM_GROUP']
-endif
-
-if get_option('wheel-group')
-        m4_defines += ['-DENABLE_WHEEL_GROUP']
-endif
+conf.set10('ENABLE_ADM_GROUP', get_option('adm-group'))
+conf.set10('ENABLE_WHEEL_GROUP', get_option('wheel-group'))
 
 substs.set('DEV_KVM_MODE', get_option('dev-kvm-mode'))
 substs.set('GROUP_RENDER_MODE', get_option('group-render-mode'))
@@ -828,7 +819,6 @@ else
         libseccomp = []
 endif
 conf.set10('HAVE_SECCOMP', have)
-m4_defines += have ? ['-DHAVE_SECCOMP'] : []
 
 want_selinux = get_option('selinux')
 if want_selinux != 'false' and not fuzzer_build
@@ -841,7 +831,6 @@ else
         libselinux = []
 endif
 conf.set10('HAVE_SELINUX', have)
-m4_defines += have ? ['-DHAVE_SELINUX'] : []
 
 want_apparmor = get_option('apparmor')
 if want_apparmor != 'false' and not fuzzer_build
@@ -853,12 +842,10 @@ else
         libapparmor = []
 endif
 conf.set10('HAVE_APPARMOR', have)
-m4_defines += have ? ['-DHAVE_APPARMOR'] : []
 
 smack_run_label = get_option('smack-run-label')
 if smack_run_label != ''
         conf.set_quoted('SMACK_RUN_LABEL', smack_run_label)
-        m4_defines += ['-DHAVE_SMACK_RUN_LABEL']
 endif
 
 want_polkit = get_option('polkit')
@@ -885,7 +872,6 @@ else
         libacl = []
 endif
 conf.set10('HAVE_ACL', have)
-m4_defines += have ? ['-DHAVE_ACL'] : []
 
 want_audit = get_option('audit')
 if want_audit != 'false' and not fuzzer_build
@@ -930,7 +916,6 @@ else
         libpam_misc = []
 endif
 conf.set10('HAVE_PAM', have)
-m4_defines += have ? ['-DHAVE_PAM'] : []
 
 want_microhttpd = get_option('microhttpd')
 if want_microhttpd != 'false' and not fuzzer_build
@@ -943,7 +928,6 @@ else
         libmicrohttpd = []
 endif
 conf.set10('HAVE_MICROHTTPD', have)
-m4_defines += have ? ['-DHAVE_MICROHTTPD'] : []
 
 want_libcryptsetup = get_option('libcryptsetup')
 if want_libcryptsetup != 'false' and not fuzzer_build
@@ -968,7 +952,6 @@ else
         libcurl = []
 endif
 conf.set10('HAVE_LIBCURL', have)
-m4_defines += have ? ['-DHAVE_LIBCURL'] : []
 
 want_libidn = get_option('libidn')
 want_libidn2 = get_option('libidn2')
@@ -985,7 +968,6 @@ else
         libidn = []
 endif
 conf.set10('HAVE_LIBIDN', have)
-m4_defines += have ? ['-DHAVE_LIBIDN'] : []
 if not have and want_libidn2 != 'false' and not fuzzer_build
         # libidn is used for both libidn and libidn2 objects
         libidn = dependency('libidn2',
@@ -995,7 +977,6 @@ else
         have = false
 endif
 conf.set10('HAVE_LIBIDN2', have)
-m4_defines += have ? ['-DHAVE_LIBIDN2'] : []
 
 want_libiptc = get_option('libiptc')
 if want_libiptc != 'false' and not fuzzer_build
@@ -1007,7 +988,6 @@ else
         libiptc = []
 endif
 conf.set10('HAVE_LIBIPTC', have)
-m4_defines += have ? ['-DHAVE_LIBIPTC'] : []
 
 want_qrencode = get_option('qrencode')
 if want_qrencode != 'false' and not fuzzer_build
@@ -1234,15 +1214,9 @@ foreach term : ['utmp',
         have = get_option(term)
         name = 'ENABLE_' + term.underscorify().to_upper()
         conf.set10(name, have)
-        m4_defines += have ? ['-D' + name] : []
 endforeach
 
-if get_option('timedated') or get_option('timesyncd')
-        conf.set10('ENABLE_TIMEDATECTL', true)
-        m4_defines += ['-DENABLE_TIMEDATECTL']
-else
-        conf.set10('ENABLE_TIMEDATECTL', false)
-endif
+conf.set10('ENABLE_TIMEDATECTL', get_option('timedated') or get_option('timesyncd'))
 
 want_tests = get_option('tests')
 install_tests = get_option('install-tests')
@@ -1289,6 +1263,8 @@ config_h = configure_file(
         output : 'config.h',
         configuration : conf)
 
+meson_apply_m4 = find_program('tools/meson-apply-m4.sh')
+
 includes = include_directories('src/basic',
                                'src/shared',
                                'src/systemd',
index e4b0a148098de1ff25e10fb8aebe8c40c4e19b8d..9df8c20a0ebc15ca326ee92eeb341b34ccbcceb7 100644 (file)
@@ -127,7 +127,7 @@ load_fragment_gperf_gperf = custom_target(
         'load-fragment-gperf.gperf',
         input : 'load-fragment-gperf.gperf.m4',
         output: 'load-fragment-gperf.gperf',
-        command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+        command : [meson_apply_m4, config_h, '@INPUT@'],
         capture : true)
 
 load_fragment_gperf_c = custom_target(
index 4a7fea920ec32fa53b3e891b25bc79c0f1db0456..3154cad58a17e88211b6f26da5040eef7f1ff216 100644 (file)
@@ -81,23 +81,26 @@ static const MountEntry apivfs_table[] = {
 
 /* ProtectKernelTunables= option and the related filesystem APIs */
 static const MountEntry protect_kernel_tunables_table[] = {
-        { "/proc/sys",           READONLY,     false },
-        { "/proc/sysrq-trigger", READONLY,     true  },
-        { "/proc/latency_stats", READONLY,     true  },
-        { "/proc/mtrr",          READONLY,     true  },
-        { "/proc/apm",           READONLY,     true  }, /* Obsolete API, there's no point in permitting access to this, ever */
         { "/proc/acpi",          READONLY,     true  },
-        { "/proc/timer_stats",   READONLY,     true  },
+        { "/proc/apm",           READONLY,     true  }, /* Obsolete API, there's no point in permitting access to this, ever */
         { "/proc/asound",        READONLY,     true  },
         { "/proc/bus",           READONLY,     true  },
         { "/proc/fs",            READONLY,     true  },
         { "/proc/irq",           READONLY,     true  },
+        { "/proc/kallsyms",      INACCESSIBLE, true  },
+        { "/proc/kcore",         INACCESSIBLE, true  },
+        { "/proc/latency_stats", READONLY,     true  },
+        { "/proc/mtrr",          READONLY,     true  },
+        { "/proc/scsi",          READONLY,     true  },
+        { "/proc/sys",           READONLY,     false },
+        { "/proc/sysrq-trigger", READONLY,     true  },
+        { "/proc/timer_stats",   READONLY,     true  },
         { "/sys",                READONLY,     false },
-        { "/sys/kernel/debug",   READONLY,     true  },
-        { "/sys/kernel/tracing", READONLY,     true  },
         { "/sys/fs/bpf",         READONLY,     true  },
         { "/sys/fs/cgroup",      READWRITE,    false }, /* READONLY is set by ProtectControlGroups= option */
         { "/sys/fs/selinux",     READWRITE,    true  },
+        { "/sys/kernel/debug",   READONLY,     true  },
+        { "/sys/kernel/tracing", READONLY,     true  },
 };
 
 /* ProtectKernelModules= option */
index c95597a00bbe05ed4249a0fee05fa969d299aeec..4832ee6a2cd95d47389426a830bf653b02cb8472 100644 (file)
@@ -12,6 +12,7 @@
 
 #include "alloc-util.h"
 #include "utf8.h"
+#include "strv.h"
 
 #include "dhcp-internal.h"
 
@@ -35,6 +36,34 @@ static int option_append(uint8_t options[], size_t size, size_t *offset,
                 *offset += 1;
                 break;
 
+        case SD_DHCP_OPTION_USER_CLASS: {
+                size_t len = 0;
+                char **s;
+
+                STRV_FOREACH(s, (char **) optval)
+                        len += strlen(*s) + 1;
+
+                if (size < *offset + len + 2)
+                        return -ENOBUFS;
+
+                options[*offset] = code;
+                options[*offset + 1] =  len;
+                *offset += 2;
+
+                STRV_FOREACH(s, (char **) optval) {
+                        len = strlen(*s);
+
+                        if (len > 255)
+                                return -ENAMETOOLONG;
+
+                        options[*offset] = len;
+
+                        memcpy_safe(&options[*offset + 1], *s, len);
+                        *offset += len + 1;
+                }
+
+                break;
+        }
         default:
                 if (size < *offset + optlen + 2)
                         return -ENOBUFS;
index 8305815df663a39816f0238f3197a597b66cc69b..5660271330c6137fc5a3b002b470e58ce4ecf34f 100644 (file)
@@ -27,6 +27,7 @@
 #include "random-util.h"
 #include "string-util.h"
 #include "util.h"
+#include "strv.h"
 
 #define MAX_CLIENT_ID_LEN (sizeof(uint32_t) + MAX_DUID_LEN)  /* Arbitrary limit */
 #define MAX_MAC_ADDR_LEN CONST_MAX(INFINIBAND_ALEN, ETH_ALEN)
@@ -83,6 +84,7 @@ struct sd_dhcp_client {
         size_t client_id_len;
         char *hostname;
         char *vendor_class_identifier;
+        char **user_class;
         uint32_t mtu;
         uint32_t xid;
         usec_t start_time;
@@ -440,6 +442,26 @@ int sd_dhcp_client_set_vendor_class_identifier(
         return free_and_strdup(&client->vendor_class_identifier, vci);
 }
 
+int sd_dhcp_client_set_user_class(
+                sd_dhcp_client *client,
+                const char* const* user_class) {
+
+        _cleanup_strv_free_ char **s = NULL;
+        char **p;
+
+        STRV_FOREACH(p, (char **) user_class)
+                if (strlen(*p) > 255)
+                        return -ENAMETOOLONG;
+
+        s = strv_copy((char **) user_class);
+        if (!s)
+                return -ENOMEM;
+
+        client->user_class = TAKE_PTR(s);
+
+        return 0;
+}
+
 int sd_dhcp_client_set_client_port(
                 sd_dhcp_client *client,
                 uint16_t port) {
@@ -763,6 +785,15 @@ static int client_send_discover(sd_dhcp_client *client) {
                         return r;
         }
 
+        if (client->user_class) {
+                r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
+                                       SD_DHCP_OPTION_USER_CLASS,
+                                       strv_length(client->user_class),
+                                       client->user_class);
+                if (r < 0)
+                        return r;
+        }
+
         r = dhcp_option_append(&discover->dhcp, optlen, &optoffset, 0,
                                SD_DHCP_OPTION_END, 0, NULL);
         if (r < 0)
@@ -1918,6 +1949,7 @@ sd_dhcp_client *sd_dhcp_client_unref(sd_dhcp_client *client) {
         free(client->req_opts);
         free(client->hostname);
         free(client->vendor_class_identifier);
+        client->user_class = strv_free(client->user_class);
         return mfree(client);
 }
 
index 1e2cf49c431d131e7cc8d14360cd7d0d0ea882d4..273fbed374a8e36dcbecc8552c78e954617e8a30 100644 (file)
@@ -98,7 +98,7 @@ if conf.get('ENABLE_LOGIND') == 1
                 '73-seat-late.rules',
                 input : '73-seat-late.rules.m4',
                 output: '73-seat-late.rules',
-                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                command : [meson_apply_m4, config_h, '@INPUT@'],
                 capture : true,
                 install : true,
                 install_dir : udevrulesdir)
@@ -107,7 +107,7 @@ if conf.get('ENABLE_LOGIND') == 1
                 'systemd-user',
                 input : 'systemd-user.m4',
                 output: 'systemd-user',
-                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                command : [meson_apply_m4, config_h, '@INPUT@'],
                 capture : true,
                 install : pamconfdir != 'no',
                 install_dir : pamconfdir)
index a1d300166bc56143a58a4cc0a7007993e1a73232..d2e79cdda609d3add41fe698df0641835dca57f2 100644 (file)
@@ -748,6 +748,12 @@ int dhcp4_configure(Link *link) {
                         return r;
         }
 
+        if (link->network->dhcp_user_class) {
+                r = sd_dhcp_client_set_user_class(link->dhcp_client, (const char **) link->network->dhcp_user_class);
+                if (r < 0)
+                        return r;
+        }
+
         if (link->network->dhcp_client_port) {
                 r = sd_dhcp_client_set_client_port(link->dhcp_client, link->network->dhcp_client_port);
                 if (r < 0)
index 1a0da586515b8eadce5751a666a15f4a2abfc522..216572aeb4a079740e64888e290645523f3685a8 100644 (file)
@@ -125,6 +125,7 @@ DHCP.Hostname,                          config_parse_hostname,
 DHCP.RequestBroadcast,                  config_parse_bool,                              0,                             offsetof(Network, dhcp_broadcast)
 DHCP.CriticalConnection,                config_parse_bool,                              0,                             offsetof(Network, dhcp_critical)
 DHCP.VendorClassIdentifier,             config_parse_string,                            0,                             offsetof(Network, dhcp_vendor_class_identifier)
+DHCP.UserClass,                         config_parse_dhcp_user_class,                   0,                             offsetof(Network, dhcp_user_class)
 DHCP.DUIDType,                          config_parse_duid_type,                         0,                             offsetof(Network, duid.type)
 DHCP.DUIDRawData,                       config_parse_duid_rawdata,                      0,                             offsetof(Network, duid)
 DHCP.RouteMetric,                       config_parse_unsigned,                          0,                             offsetof(Network, dhcp_route_metric)
index 2592377a6f748fd4d0198a8a462ff76edc4d59a6..aafb192baf0b6395fe0a761f857c819998e53c42 100644 (file)
@@ -361,6 +361,7 @@ void network_free(Network *network) {
 
         free(network->description);
         free(network->dhcp_vendor_class_identifier);
+        strv_free(network->dhcp_user_class);
         free(network->dhcp_hostname);
 
         free(network->mac);
@@ -1387,6 +1388,58 @@ int config_parse_ntp(
         return 0;
 }
 
+int config_parse_dhcp_user_class(
+                const char *unit,
+                const char *filename,
+                unsigned line,
+                const char *section,
+                unsigned section_line,
+                const char *lvalue,
+                int ltype,
+                const char *rvalue,
+                void *data,
+                void *userdata) {
+
+        char ***l = data;
+        int r;
+
+        assert(l);
+        assert(lvalue);
+        assert(rvalue);
+
+        if (isempty(rvalue)) {
+                *l = strv_free(*l);
+                return 0;
+        }
+
+        for (;;) {
+                _cleanup_free_ char *w = NULL;
+
+                r = extract_first_word(&rvalue, &w, NULL, 0);
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to split user classes option, ignoring: %s", rvalue);
+                        break;
+                }
+                if (r == 0)
+                        break;
+
+                if (strlen(w) > 255) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "%s length is not in the range 1-255, ignoring.", w);
+                        continue;
+                }
+
+                r = strv_push(l, w);
+                if (r < 0)
+                        return log_oom();
+
+                w = NULL;
+        }
+
+        return 0;
+}
+
 int config_parse_dhcp_route_table(const char *unit,
                                   const char *filename,
                                   unsigned line,
index 060c526b9ee8dde7666ff2a51fae490891667d3e..e4bb0ba83a39c4f9ea1f23b7551146ed73baa420 100644 (file)
@@ -126,6 +126,7 @@ struct Network {
         AddressFamilyBoolean dhcp;
         DHCPClientIdentifier dhcp_client_identifier;
         char *dhcp_vendor_class_identifier;
+        char **dhcp_user_class;
         char *dhcp_hostname;
         unsigned dhcp_route_metric;
         uint32_t dhcp_route_table;
@@ -288,7 +289,7 @@ int config_parse_dhcp_server_ntp(const char *unit, const char *filename, unsigne
 int config_parse_dnssec_negative_trust_anchors(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_dhcp_use_domains(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_lldp_mode(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
-int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_dhcp_route_table(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);int config_parse_dhcp_user_class(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_ntp(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 /* Legacy IPv4LL support */
 int config_parse_ipv4ll(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index 682ea65080c62b4d999e54f2941c5506b89d02f7..761d737dc9d8c044c76b3a11cc3ee056436ca6b4 100644 (file)
@@ -141,44 +141,53 @@ finish:
         return r;
 }
 
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested) {
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested) {
         _cleanup_free_ char *cgroup = NULL;
-        const char *child;
-        int r;
         CGroupMask supported;
+        const char *payload;
+        int r;
 
-        /* In the unified hierarchy inner nodes may only contain
-         * subgroups, but not processes. Hence, if we running in the
-         * unified hierarchy and the container does the same, and we
-         * did not create a scope unit for the container move us and
-         * the container into two separate subcgroups. */
-
-        if (unified_requested == CGROUP_UNIFIED_NONE)
-                return 0;
-
-        r = cg_unified_controller(SYSTEMD_CGROUP_CONTROLLER);
-        if (r < 0)
-                return log_error_errno(r, "Failed to determine whether the systemd controller is unified: %m");
-        if (r == 0)
-                return 0;
+        assert(pid > 1);
+
+        /* In the unified hierarchy inner nodes may only contain subgroups, but not processes. Hence, if we running in
+         * the unified hierarchy and the container does the same, and we did not create a scope unit for the container
+         * move us and the container into two separate subcgroups.
+         *
+         * Moreover, container payloads such as systemd try to manage the cgroup they run in in full (i.e. including
+         * its attributes), while the host systemd will only delegate cgroups for children of the cgroup created for a
+         * delegation unit, instead of the cgroup itself. This means, if we'd pass on the cgroup allocated from the
+         * host systemd directly to the payload, the host and payload systemd might fight for the cgroup
+         * attributes. Hence, let's insert an intermediary cgroup to cover that case too.
+         *
+         * Note that we only bother with the main hierarchy here, not with any secondary ones. On the unified setup
+         * that's fine because there's only one hiearchy anyway and controllers are enabled directly on it. On the
+         * legacy setup, this is fine too, since delegation of controllers is generally not safe there, hence we won't
+         * do it. */
 
         r = cg_mask_supported(&supported);
         if (r < 0)
                 return log_error_errno(r, "Failed to determine supported controllers: %m");
 
-        r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+        if (keep_unit)
+                r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, 0, &cgroup);
+        else
+                r = cg_pid_get_path(SYSTEMD_CGROUP_CONTROLLER, pid, &cgroup);
         if (r < 0)
                 return log_error_errno(r, "Failed to get our control group: %m");
 
-        child = strjoina(cgroup, "/payload");
-        r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, pid);
+        payload = strjoina(cgroup, "/payload");
+        r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, payload, pid);
         if (r < 0)
-                return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+                return log_error_errno(r, "Failed to create %s subcgroup: %m", payload);
 
-        child = strjoina(cgroup, "/supervisor");
-        r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, child, 0);
-        if (r < 0)
-                return log_error_errno(r, "Failed to create %s subcgroup: %m", child);
+        if (keep_unit) {
+                const char *supervisor;
+
+                supervisor = strjoina(cgroup, "/supervisor");
+                r = cg_create_and_attach(SYSTEMD_CGROUP_CONTROLLER, supervisor, 0);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to create %s subcgroup: %m", supervisor);
+        }
 
         /* Try to enable as many controllers as possible for the new payload. */
         (void) cg_enable_everywhere(supported, supported, cgroup);
index 3a8e98e12216e72ecfc7a519880b9ddae159fd53..7639b483ae79d9a8b52d95a494b28322902d7271 100644 (file)
@@ -14,4 +14,4 @@
 
 int chown_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
 int sync_cgroup(pid_t pid, CGroupUnified unified_requested, uid_t uid_shift);
-int create_subcgroup(pid_t pid, CGroupUnified unified_requested);
+int create_subcgroup(pid_t pid, bool keep_unit, CGroupUnified unified_requested);
index 1cc4a2da6b8a9092855d31edc0a9e8a123abcbc0..8a4634f53e93821c74119732efd8eef506679928 100644 (file)
@@ -27,7 +27,7 @@
 #include "user-util.h"
 #include "util.h"
 
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t) {
         CustomMount *c, *ret;
 
         assert(l);
@@ -48,8 +48,8 @@ CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t) {
         return ret;
 }
 
-void custom_mount_free_all(CustomMount *l, unsigned n) {
-        unsigned i;
+void custom_mount_free_all(CustomMount *l, size_t n) {
+        size_t i;
 
         for (i = 0; i < n; i++) {
                 CustomMount *m = l + i;
@@ -110,8 +110,8 @@ static char *resolve_source_path(const char *dest, const char *source) {
         return strdup(source);
 }
 
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
-        unsigned i;
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n) {
+        size_t i;
         int r;
 
         /* Prepare all custom mounts. This will make source we know all temporary directories. This is called in the
@@ -133,8 +133,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
                         if (!s)
                                 return log_oom();
 
-                        free(m->source);
-                        m->source = s;
+                        free_and_replace(m->source, s);
                 } else {
                         /* No source specified? In that case, use a throw-away temporary directory in /var/tmp */
 
@@ -165,8 +164,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
                                 if (!s)
                                         return log_oom();
 
-                                free(*j);
-                                *j = s;
+                                free_and_replace(*j, s);
                         }
 
                         if (m->work_dir) {
@@ -176,8 +174,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
                                 if (!s)
                                         return log_oom();
 
-                                free(m->work_dir);
-                                m->work_dir = s;
+                                free_and_replace(m->work_dir, s);
                         } else {
                                 assert(m->source);
 
@@ -193,7 +190,7 @@ int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n) {
         return 0;
 }
 
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
         _cleanup_free_ char *source = NULL, *destination = NULL, *opts = NULL;
         const char *p = s;
         CustomMount *m;
@@ -239,7 +236,7 @@ int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only
         return 0;
 }
 
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s) {
         _cleanup_free_ char *path = NULL, *opts = NULL;
         const char *p = s;
         CustomMount *m;
@@ -275,7 +272,7 @@ int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s) {
         return 0;
 }
 
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only) {
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only) {
         _cleanup_free_ char *upper = NULL, *destination = NULL;
         _cleanup_strv_free_ char **lower = NULL;
         CustomMount *m;
@@ -511,6 +508,18 @@ int mount_all(const char *dest,
               uid_t uid_shift, uid_t uid_range,
               const char *selinux_apifs_context) {
 
+#define PROC_INACCESSIBLE(path)                                         \
+        { NULL, (path), NULL, NULL, MS_BIND,                            \
+          MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_INACCESSIBLE_REG }, /* Bind mount first ... */ \
+        { NULL, (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+          MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
+#define PROC_READ_ONLY(path)                                            \
+        { (path), (path), NULL, NULL, MS_BIND,                          \
+          MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO }, /* Bind mount first ... */ \
+        { NULL,   (path), NULL, NULL, MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, \
+          MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO } /* Then, make it r/o */
+
         typedef struct MountPoint {
                 const char *what;
                 const char *where;
@@ -521,39 +530,72 @@ int mount_all(const char *dest,
         } MountPoint;
 
         static const MountPoint mount_table[] = {
-                /* inner child mounts */
-                { "proc",                "/proc",               "proc",  NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,                              MOUNT_FATAL|MOUNT_IN_USERNS },
-                { "/proc/sys",           "/proc/sys",           NULL,    NULL,        MS_BIND,                                                   MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },                          /* Bind mount first ... */
-                { "/proc/sys/net",       "/proc/sys/net",       NULL,    NULL,        MS_BIND,                                                   MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
-                { NULL,                  "/proc/sys",           NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },                          /* ... then, make it r/o */
-                { "/proc/sysrq-trigger", "/proc/sysrq-trigger", NULL,    NULL,        MS_BIND,                                                   MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },  /* Bind mount first ... */
-                { NULL,                  "/proc/sysrq-trigger", NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },  /* ... then, make it r/o */
-
-                /* outer child mounts */
-                { "tmpfs",               "/tmp",                "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         MOUNT_FATAL },
-                { "tmpfs",               "/sys",                "tmpfs", "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV,                              MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
-                { "sysfs",               "/sys",                "sysfs", NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,                    MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO },    /* skipped if above was mounted */
-                { "sysfs",               "/sys",                "sysfs", NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,                              MOUNT_FATAL },                          /* skipped if above was mounted */
-
-                { "tmpfs",               "/dev",                "tmpfs", "mode=755",  MS_NOSUID|MS_STRICTATIME,                                  MOUNT_FATAL },
-                { "tmpfs",               "/dev/shm",            "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         MOUNT_FATAL },
-                { "tmpfs",               "/run",                "tmpfs", "mode=755",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,                         MOUNT_FATAL },
+                /* 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 },
+
+                { "/proc/sys",       "/proc/sys",       NULL,    NULL,        MS_BIND,
+                  MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },                          /* Bind mount first ... */
+
+                { "/proc/sys/net",   "/proc/sys/net",   NULL,    NULL,        MS_BIND,
+                  MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO|MOUNT_APPLY_APIVFS_NETNS }, /* (except for this) */
+
+                { NULL,              "/proc/sys",       NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+                  MOUNT_FATAL|MOUNT_IN_USERNS|MOUNT_APPLY_APIVFS_RO },                          /* ... then, make it r/o */
+
+                /* Make these files inaccessible to container payloads: they potentially leak information about kernel
+                 * internals or the host's execution environment to the container */
+                PROC_INACCESSIBLE("/proc/kallsyms"),
+                PROC_INACCESSIBLE("/proc/kcore"),
+                PROC_INACCESSIBLE("/proc/keys"),
+                PROC_INACCESSIBLE("/proc/sysrq-trigger"),
+                PROC_INACCESSIBLE("/proc/timer_list"),
+
+                /* Make these directories read-only to container payloads: they show hardware information, and in some
+                 * cases contain tunables the container really shouldn't have access to. */
+                PROC_READ_ONLY("/proc/acpi"),
+                PROC_READ_ONLY("/proc/apm"),
+                PROC_READ_ONLY("/proc/asound"),
+                PROC_READ_ONLY("/proc/bus"),
+                PROC_READ_ONLY("/proc/fs"),
+                PROC_READ_ONLY("/proc/irq"),
+                PROC_READ_ONLY("/proc/scsi"),
+
+                /* 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 },
+                { "tmpfs",           "/sys",            "tmpfs", "mode=755",  MS_NOSUID|MS_NOEXEC|MS_NODEV,
+                  MOUNT_FATAL|MOUNT_APPLY_APIVFS_NETNS },
+                { "sysfs",           "/sys",            "sysfs", NULL,        MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV,
+                  MOUNT_FATAL|MOUNT_APPLY_APIVFS_RO },    /* skipped if above was mounted */
+                { "sysfs",           "/sys",            "sysfs", NULL,        MS_NOSUID|MS_NOEXEC|MS_NODEV,
+                  MOUNT_FATAL },                          /* skipped if above was mounted */
+                { "tmpfs",           "/dev",            "tmpfs", "mode=755",  MS_NOSUID|MS_STRICTATIME,
+                  MOUNT_FATAL },
+                { "tmpfs",           "/dev/shm",        "tmpfs", "mode=1777", MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+                  MOUNT_FATAL },
+                { "tmpfs",           "/run",            "tmpfs", "mode=755",  MS_NOSUID|MS_NODEV|MS_STRICTATIME,
+                  MOUNT_FATAL },
+
 #if HAVE_SELINUX
-                { "/sys/fs/selinux",     "/sys/fs/selinux",     NULL,    NULL,        MS_BIND,                                                   0 },  /* Bind mount first */
-                { NULL,                  "/sys/fs/selinux",     NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT, 0 },  /* Then, make it r/o */
+                { "/sys/fs/selinux", "/sys/fs/selinux", NULL,    NULL,        MS_BIND,
+                  0 },  /* Bind mount first */
+                { NULL,              "/sys/fs/selinux", NULL,    NULL,        MS_BIND|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV|MS_REMOUNT,
+                  0 },  /* Then, make it r/o */
 #endif
         };
 
-        unsigned k;
-        int r;
+        _cleanup_(unlink_and_freep) char *inaccessible = NULL;
         bool use_userns = (mount_settings & MOUNT_USE_USERNS);
         bool netns = (mount_settings & MOUNT_APPLY_APIVFS_NETNS);
         bool ro = (mount_settings & MOUNT_APPLY_APIVFS_RO);
         bool in_userns = (mount_settings & MOUNT_IN_USERNS);
+        size_t k;
+        int r;
 
         for (k = 0; k < ELEMENTSOF(mount_table); k++) {
                 _cleanup_free_ char *where = NULL, *options = NULL;
-                const char *o;
+                const char *o, *what;
                 bool fatal = (mount_table[k].mount_settings & MOUNT_FATAL);
 
                 if (in_userns != (bool)(mount_table[k].mount_settings & MOUNT_IN_USERNS))
@@ -569,12 +611,32 @@ int mount_all(const char *dest,
                 if (r < 0)
                         return log_error_errno(r, "Failed to resolve %s/%s: %m", dest, mount_table[k].where);
 
+                if (mount_table[k].mount_settings & MOUNT_INACCESSIBLE_REG) {
+
+                        if (!inaccessible) {
+                                _cleanup_free_ char *np = NULL;
+
+                                r = tempfn_random_child(NULL, "inaccessible", &np);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to generate inaccessible file node path: %m");
+
+                                r = touch_file(np, false, USEC_INFINITY, UID_INVALID, GID_INVALID, 0000);
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to create inaccessible file node '%s': %m", np);
+
+                                inaccessible = TAKE_PTR(np);
+                        }
+
+                        what = inaccessible;
+                } else
+                        what = mount_table[k].what;
+
                 r = path_is_mount_point(where, NULL, 0);
                 if (r < 0 && r != -ENOENT)
                         return log_error_errno(r, "Failed to detect whether %s is a mount point: %m", where);
 
                 /* Skip this entry if it is not a remount. */
-                if (mount_table[k].what && r > 0)
+                if (what && r > 0)
                         continue;
 
                 r = mkdir_userns_p(dest, where, 0755, mount_settings, uid_shift);
@@ -603,7 +665,7 @@ int mount_all(const char *dest,
                 }
 
                 r = mount_verbose(fatal ? LOG_ERR : LOG_DEBUG,
-                                  mount_table[k].what,
+                                  what,
                                   where,
                                   mount_table[k].type,
                                   mount_table[k].flags,
@@ -766,11 +828,11 @@ static int mount_overlay(const char *dest, CustomMount *m) {
 
 int mount_custom(
                 const char *dest,
-                CustomMount *mounts, unsigned n,
+                CustomMount *mounts, size_t n,
                 bool userns, uid_t uid_shift, uid_t uid_range,
                 const char *selinux_apifs_context) {
 
-        unsigned i;
+        size_t i;
         int r;
 
         assert(dest);
index 6d3aca76a087347d745c8ee22925844552972f21..db7aadc28e9c1bf8860dbffb4a10417a8b6dffc1 100644 (file)
 #include "volatile-util.h"
 
 typedef enum MountSettingsMask {
-        MOUNT_FATAL              = 1 << 0, /* if set, a mount error is considered fatal */
-        MOUNT_USE_USERNS         = 1 << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */
-        MOUNT_IN_USERNS          = 1 << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */
-        MOUNT_APPLY_APIVFS_RO    = 1 << 3, /* if set, /proc/sys, and /sysfs will be mounted read-only, otherwise read-write. */
-        MOUNT_APPLY_APIVFS_NETNS = 1 << 4, /* if set, /proc/sys/net will be mounted read-write.
-                                              Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+        MOUNT_FATAL              = 1U << 0, /* if set, a mount error is considered fatal */
+        MOUNT_USE_USERNS         = 1U << 1, /* if set, mounts are patched considering uid/gid shifts in a user namespace */
+        MOUNT_IN_USERNS          = 1U << 2, /* if set, the mount is executed in the inner child, otherwise in the outer child */
+        MOUNT_APPLY_APIVFS_RO    = 1U << 3, /* if set, /proc/sys, and /sys will be mounted read-only, otherwise read-write. */
+        MOUNT_APPLY_APIVFS_NETNS = 1U << 4, /* if set, /proc/sys/net will be mounted read-write.
+                                               Works only if MOUNT_APPLY_APIVFS_RO is also set. */
+        MOUNT_INACCESSIBLE_REG   = 1U << 5, /* if set, create an inaccessible regular file first and use as bind mount source */
 } MountSettingsMask;
 
 typedef enum CustomMountType {
@@ -40,13 +41,13 @@ typedef struct CustomMount {
         char *rm_rf_tmpdir;
 } CustomMount;
 
-CustomMount* custom_mount_add(CustomMount **l, unsigned *n, CustomMountType t);
-void custom_mount_free_all(CustomMount *l, unsigned n);
-int custom_mount_prepare_all(const char *dest, CustomMount *l, unsigned n);
+CustomMount* custom_mount_add(CustomMount **l, size_t *n, CustomMountType t);
+void custom_mount_free_all(CustomMount *l, size_t n);
+int custom_mount_prepare_all(const char *dest, CustomMount *l, size_t n);
 
-int bind_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
-int tmpfs_mount_parse(CustomMount **l, unsigned *n, const char *s);
-int overlay_mount_parse(CustomMount **l, unsigned *n, const char *s, bool read_only);
+int bind_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
+int tmpfs_mount_parse(CustomMount **l, size_t *n, const char *s);
+int overlay_mount_parse(CustomMount **l, size_t *n, const char *s, bool read_only);
 
 int mount_all(const char *dest, MountSettingsMask mount_settings, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
 int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
@@ -54,7 +55,7 @@ int mount_sysfs(const char *dest, MountSettingsMask mount_settings);
 int mount_cgroups(const char *dest, CGroupUnified unified_requested, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context, bool use_cgns);
 int mount_systemd_cgroup_writable(const char *dest, CGroupUnified unified_requested);
 
-int mount_custom(const char *dest, CustomMount *mounts, unsigned n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
+int mount_custom(const char *dest, CustomMount *mounts, size_t n, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
 
 int setup_volatile(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
 int setup_volatile_state(const char *directory, VolatileMode mode, bool userns, uid_t uid_shift, uid_t uid_range, const char *selinux_apifs_context);
index 643e00400f80d661726c26fb5ab78f3ea1d08731..c0cdb7c0d748b4207a9d7538f05754118fd41a54 100644 (file)
@@ -11,6 +11,7 @@
 #include "bus-unit-util.h"
 #include "bus-util.h"
 #include "nspawn-register.h"
+#include "special.h"
 #include "stat-util.h"
 #include "strv.h"
 #include "util.h"
@@ -309,7 +310,7 @@ int allocate_scope(
                                   "PIDs", "au", 1, pid,
                                   "Description", "s", description,
                                   "Delegate", "b", 1,
-                                  "Slice", "s", isempty(slice) ? "machine.slice" : slice);
+                                  "Slice", "s", isempty(slice) ? SPECIAL_MACHINE_SLICE : slice);
         if (r < 0)
                 return bus_log_create_error(r);
 
index bee7e9f53030353558e08bfdefdb8e5f65a05c21..731db87260689661dc753b6668de25c589565d9c 100644 (file)
@@ -76,7 +76,7 @@ typedef struct Settings {
         int read_only;
         VolatileMode volatile_mode;
         CustomMount *custom_mounts;
-        unsigned n_custom_mounts;
+        size_t n_custom_mounts;
         int userns_chown;
 
         /* [Network] */
index 23bc9402a8af22be1f779c3f8d3a6bc6868ee2aa..d7ceb4ed445a61a8c640d815c7bb67fc2c6d6d45 100644 (file)
@@ -165,7 +165,7 @@ static uint64_t arg_caps_retain =
         (1ULL << CAP_SYS_RESOURCE) |
         (1ULL << CAP_SYS_TTY_CONFIG);
 static CustomMount *arg_custom_mounts = NULL;
-static unsigned arg_n_custom_mounts = 0;
+static size_t arg_n_custom_mounts = 0;
 static char **arg_setenv = NULL;
 static bool arg_quiet = false;
 static bool arg_register = true;
@@ -291,7 +291,7 @@ static void help(void) {
 }
 
 static int custom_mount_check_all(void) {
-        unsigned i;
+        size_t i;
 
         for (i = 0; i < arg_n_custom_mounts; i++) {
                 CustomMount *m = &arg_custom_mounts[i];
@@ -1470,31 +1470,35 @@ static int setup_resolv_conf(const char *dest) {
 }
 
 static int setup_boot_id(void) {
+        _cleanup_(unlink_and_freep) char *from = NULL;
+        _cleanup_free_ char *path = NULL;
         sd_id128_t rnd = SD_ID128_NULL;
-        const char *from, *to;
+        const char *to;
         int r;
 
         /* Generate a new randomized boot ID, so that each boot-up of
          * the container gets a new one */
 
-        from = "/run/proc-sys-kernel-random-boot-id";
-        to = "/proc/sys/kernel/random/boot_id";
+        r = tempfn_random_child(NULL, "proc-sys-kernel-random-boot-id", &path);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate random boot ID path: %m");
 
         r = sd_id128_randomize(&rnd);
         if (r < 0)
                 return log_error_errno(r, "Failed to generate random boot id: %m");
 
-        r = id128_write(from, ID128_UUID, rnd, false);
+        r = id128_write(path, ID128_UUID, rnd, false);
         if (r < 0)
                 return log_error_errno(r, "Failed to write boot id: %m");
 
+        from = TAKE_PTR(path);
+        to = "/proc/sys/kernel/random/boot_id";
+
         r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
-        if (r >= 0)
-                r = mount_verbose(LOG_ERR, NULL, to, NULL,
-                                  MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NODEV, NULL);
+        if (r < 0)
+                return r;
 
-        (void) unlink(from);
-        return r;
+        return mount_verbose(LOG_ERR, NULL, to, NULL, MS_BIND|MS_REMOUNT|MS_RDONLY|MS_NOSUID|MS_NOEXEC|MS_NODEV, NULL);
 }
 
 static int copy_devnodes(const char *dest) {
@@ -1662,26 +1666,32 @@ static int setup_keyring(void) {
 }
 
 static int setup_kmsg(int kmsg_socket) {
-        const char *from, *to;
+        _cleanup_(unlink_and_freep) char *from = NULL;
+        _cleanup_free_ char *fifo = NULL;
+        _cleanup_close_ int fd = -1;
         _cleanup_umask_ mode_t u;
-        int fd, r;
+        const char *to;
+        int r;
 
         assert(kmsg_socket >= 0);
 
         u = umask(0000);
 
-        /* We create the kmsg FIFO as /run/kmsg, but immediately
-         * delete it after bind mounting it to /proc/kmsg. While FIFOs
-         * on the reading side behave very similar to /proc/kmsg,
-         * their writing side behaves differently from /dev/kmsg in
-         * that writing blocks when nothing is reading. In order to
-         * avoid any problems with containers deadlocking due to this
-         * we simply make /dev/kmsg unavailable to the container. */
-        from = "/run/kmsg";
-        to = "/proc/kmsg";
+        /* We create the kmsg FIFO as as temporary file in /tmp, but immediately delete it after bind mounting it to
+         * /proc/kmsg. While FIFOs on the reading side behave very similar to /proc/kmsg, their writing side behaves
+         * differently from /dev/kmsg in that writing blocks when nothing is reading. In order to avoid any problems
+         * with containers deadlocking due to this we simply make /dev/kmsg unavailable to the container. */
 
-        if (mkfifo(from, 0600) < 0)
+        r = tempfn_random_child(NULL, "proc-kmsg", &fifo);
+        if (r < 0)
+                return log_error_errno(r, "Failed to generate kmsg path: %m");
+
+        if (mkfifo(fifo, 0600) < 0)
                 return log_error_errno(errno, "mkfifo() for /run/kmsg failed: %m");
+
+        from = TAKE_PTR(fifo);
+        to = "/proc/kmsg";
+
         r = mount_verbose(LOG_ERR, from, to, NULL, MS_BIND, NULL);
         if (r < 0)
                 return r;
@@ -1690,17 +1700,11 @@ static int setup_kmsg(int kmsg_socket) {
         if (fd < 0)
                 return log_error_errno(errno, "Failed to open fifo: %m");
 
-        /* Store away the fd in the socket, so that it stays open as
-         * long as we run the child */
+        /* Store away the fd in the socket, so that it stays open as long as we run the child */
         r = send_one_fd(kmsg_socket, fd, 0);
-        safe_close(fd);
-
         if (r < 0)
                 return log_error_errno(r, "Failed to send FIFO fd: %m");
 
-        /* And now make the FIFO unavailable as /run/kmsg... */
-        (void) unlink(from);
-
         return 0;
 }
 
@@ -2265,7 +2269,7 @@ static int inner_child(
 
         _cleanup_free_ char *home = NULL;
         char as_uuid[37];
-        unsigned n_env = 1;
+        size_t n_env = 1;
         const char *envp[] = {
                 "PATH=" DEFAULT_PATH_COMPAT,
                 NULL, /* container */
@@ -3639,11 +3643,9 @@ static int run(int master,
         if (r < 0)
                 return r;
 
-        if (arg_keep_unit) {
-                r = create_subcgroup(*pid, arg_unified_cgroup_hierarchy);
-                if (r < 0)
-                        return r;
-        }
+        r = create_subcgroup(*pid, arg_keep_unit, arg_unified_cgroup_hierarchy);
+        if (r < 0)
+                return r;
 
         r = chown_cgroup(*pid, arg_unified_cgroup_hierarchy, arg_uid_shift);
         if (r < 0)
index 789cc50174c59239d0356de020f25abc3257a1ef..fd0a56936292d698a510c6e13f7f35b948c66ede 100644 (file)
@@ -82,6 +82,7 @@ enum {
         SD_DHCP_OPTION_REBINDING_T2_TIME           = 59,
         SD_DHCP_OPTION_VENDOR_CLASS_IDENTIFIER     = 60,
         SD_DHCP_OPTION_CLIENT_IDENTIFIER           = 61,
+        SD_DHCP_OPTION_USER_CLASS                  = 77,
         SD_DHCP_OPTION_FQDN                        = 81,
         SD_DHCP_OPTION_NEW_POSIX_TIMEZONE          = 100,
         SD_DHCP_OPTION_NEW_TZDB_TIMEZONE           = 101,
@@ -154,6 +155,9 @@ int sd_dhcp_client_set_hostname(
 int sd_dhcp_client_set_vendor_class_identifier(
                 sd_dhcp_client *client,
                 const char *vci);
+int sd_dhcp_client_set_user_class(
+                sd_dhcp_client *client,
+                const char* const *user_class);
 int sd_dhcp_client_get_lease(
                 sd_dhcp_client *client,
                 sd_dhcp_lease **ret);
index ccea64b5735c56ff4ffa51fd906411a715ba8387..37525ce841b2406f76afa575b349241bc3e1cc52 100644 (file)
@@ -568,3 +568,105 @@ int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *l
 
         return r;
 }
+
+int config_parse_channel(const char *unit,
+                         const char *filename,
+                         unsigned line,
+                         const char *section,
+                         unsigned section_line,
+                         const char *lvalue,
+                         int ltype,
+                         const char *rvalue,
+                         void *data,
+                         void *userdata) {
+        link_config *config = data;
+        uint32_t k;
+        int r;
+
+        assert(filename);
+        assert(section);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        r = safe_atou32(rvalue, &k);
+        if (r < 0) {
+                log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse channel value, ignoring: %s", rvalue);
+                return 0;
+        }
+
+        if (k < 1) {
+                log_syntax(unit, LOG_ERR, filename, line, -EINVAL, "Invalid %s value, ignoring: %s", lvalue, rvalue);
+                return 0;
+        }
+
+        if (streq(lvalue, "RxChannels")) {
+                config->channels.rx_count = k;
+                config->channels.rx_count_set = true;
+        } else if (streq(lvalue, "TxChannels")) {
+                config->channels.tx_count = k;
+                config->channels.tx_count_set = true;
+        } else if (streq(lvalue, "OtherChannels")) {
+                config->channels.other_count = k;
+                config->channels.other_count_set = true;
+        } else if (streq(lvalue, "CombinedChannels")) {
+                config->channels.combined_count = k;
+                config->channels.combined_count_set = true;
+        }
+
+        return 0;
+}
+
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels) {
+        struct ethtool_channels ecmd = {
+                .cmd = ETHTOOL_GCHANNELS
+        };
+        struct ifreq ifr = {
+                .ifr_data = (void*) &ecmd
+        };
+
+        bool need_update = false;
+        int r;
+
+        if (*fd < 0) {
+                r = ethtool_connect(fd);
+                if (r < 0)
+                        return log_warning_errno(r, "link_config: could not connect to ethtool: %m");
+        }
+
+        strscpy(ifr.ifr_name, IFNAMSIZ, ifname);
+
+        r = ioctl(*fd, SIOCETHTOOL, &ifr);
+        if (r < 0)
+                return -errno;
+
+        if (channels->rx_count_set && ecmd.rx_count != channels->rx_count) {
+                ecmd.rx_count = channels->rx_count;
+                need_update = true;
+        }
+
+        if (channels->tx_count_set && ecmd.tx_count != channels->tx_count) {
+                ecmd.tx_count = channels->tx_count;
+                need_update = true;
+        }
+
+        if (channels->other_count_set && ecmd.other_count != channels->other_count) {
+                ecmd.other_count = channels->other_count;
+                need_update = true;
+        }
+
+        if (channels->combined_count_set && ecmd.combined_count != channels->combined_count) {
+                ecmd.combined_count = channels->combined_count;
+                need_update = true;
+        }
+
+        if (need_update) {
+                ecmd.cmd = ETHTOOL_SCHANNELS;
+
+                r = ioctl(*fd, SIOCETHTOOL, &ifr);
+                if (r < 0)
+                        return -errno;
+        }
+
+        return 0;
+}
index 1db07dec53ae7350ff76e8bbf05efa4bbf302896..da2a2458f0ca6abce4d38c244aa5ab73e32f3c3d 100644 (file)
@@ -72,6 +72,18 @@ struct ethtool_link_usettings {
         } link_modes;
 };
 
+typedef struct netdev_channels {
+        uint32_t rx_count;
+        uint32_t tx_count;
+        uint32_t other_count;
+        uint32_t combined_count;
+
+        bool rx_count_set;
+        bool tx_count_set;
+        bool other_count_set;
+        bool combined_count_set;
+} netdev_channels;
+
 int ethtool_connect(int *ret);
 
 int ethtool_get_driver(int *fd, const char *ifname, char **ret);
@@ -79,6 +91,7 @@ int ethtool_set_speed(int *fd, const char *ifname, unsigned int speed, Duplex du
 int ethtool_set_wol(int *fd, const char *ifname, WakeOnLan wol);
 int ethtool_set_features(int *fd, const char *ifname, NetDevFeature *features);
 int ethtool_set_glinksettings(int *fd, const char *ifname, struct link_config *link);
+int ethtool_set_channels(int *fd, const char *ifname, netdev_channels *channels);
 
 const char *duplex_to_string(Duplex d) _const_;
 Duplex duplex_from_string(const char *d) _pure_;
@@ -92,3 +105,4 @@ NetDevPort port_from_string(const char *port) _pure_;
 int config_parse_duplex(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_wol(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
 int config_parse_port(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
+int config_parse_channel(const char *unit, const char *filename, unsigned line, const char *section, unsigned section_line, const char *lvalue, int ltype, const char *rvalue, void *data, void *userdata);
index 8bfa998dacf6a70d0c0b08074886f7242b3aac9a..dee305f3250ddea2cda5310d6b932db325448123 100644 (file)
@@ -47,3 +47,7 @@ Link.TCP6SegmentationOffload,    config_parse_tristate,      0,
 Link.UDPSegmentationOffload,     config_parse_warn_compat,   DISABLED_LEGACY,               0
 Link.GenericReceiveOffload,      config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_GRO])
 Link.LargeReceiveOffload,        config_parse_tristate,      0,                             offsetof(link_config, features[NET_DEV_FEAT_LRO])
+Link.RxChannels,                 config_parse_channel,       0,                             0
+Link.TxChannels,                 config_parse_channel,       0,                             0
+Link.OtherChannels,              config_parse_channel,       0,                             0
+Link.CombinedChannels,           config_parse_channel,       0,                             0
index c4fab4e63b1f940d17e2951affc54ef8c443231f..e33eae542176dd4000e0b8dfe901428e7233368b 100644 (file)
@@ -393,6 +393,12 @@ int link_config_apply(link_config_ctx *ctx, link_config *config,
         if (r < 0)
                 log_warning_errno(r, "Could not set offload features of %s: %m", old_name);
 
+        if (config->channels.rx_count_set || config->channels.tx_count_set || config->channels.other_count_set || config->channels.combined_count_set) {
+                r = ethtool_set_channels(&ctx->ethtool_fd, old_name, &config->channels);
+                if (r < 0)
+                        log_warning_errno(r, "Could not set channels of %s: %m", old_name);
+        }
+
         ifindex = udev_device_get_ifindex(device);
         if (ifindex <= 0) {
                 log_warning("Could not find ifindex");
index 9f411328105573a851426e654642ef8d05c866a9..bedb80ea4392cd594cd40dc30908ef671921910b 100644 (file)
@@ -62,6 +62,7 @@ struct link_config {
         WakeOnLan wol;
         NetDevPort port;
         NetDevFeature features[_NET_DEV_FEAT_MAX];
+        netdev_channels channels;
 
         LIST_FIELDS(link_config, links);
 };
index cc4b5d26347db7ff6e43eb9f4bbf1573e7295168..eba84e1d55c1d05495b73a6c27ab5cfa2b470753 100644 (file)
@@ -28,7 +28,7 @@ foreach file : m4_files
                 'sysusers.d_' + file,
                 input : file + '.m4',
                 output: file,
-                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                command : [meson_apply_m4, config_h, '@INPUT@'],
                 capture : true,
                 install : enable_sysusers,
                 install_dir : sysusersdir)
index a7a7d0a1d7aa0d909beef0f513acfa8cb8a22fd9..20b1e0d0bc91f18f3040fcaa93fddf0371bd2297 100644 (file)
@@ -37,7 +37,7 @@ foreach pair : m4_files
                         'tmpfiles.d_' + pair[0],
                          input : pair[0] + '.m4',
                          output: pair[0],
-                         command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                         command : [meson_apply_m4, config_h, '@INPUT@'],
                          capture : true,
                          install : true,
                          install_dir : tmpfilesdir)
diff --git a/tools/meson-apply-m4.sh b/tools/meson-apply-m4.sh
new file mode 100755 (executable)
index 0000000..6abe177
--- /dev/null
@@ -0,0 +1,24 @@
+#!/bin/sh
+set -eu
+
+CONFIG=$1
+TARGET=$2
+
+if [ $# -ne 2 ]; then
+        echo 'Invalid number of arguments.'
+        exit 1
+fi
+
+if [ ! -f $CONFIG ]; then
+        echo "$CONFIG not found."
+        exit 2
+fi
+
+if [ ! -f $TARGET ]; then
+        echo "$TARGET not found."
+        exit 3
+fi
+
+DEFINES=$(awk '$1 == "#define" && $3 == "1" { printf "-D%s ", $2 }' $CONFIG)
+
+m4 -P $DEFINES $TARGET
index fed2f107534816a293e8f7d792b1ba50a3a7672d..799fc5d5673b05ac93f8784b92ff0b24e7599068 100644 (file)
@@ -272,7 +272,7 @@ foreach tuple : m4_units
                 file,
                 input : input,
                 output: file,
-                command : [m4, '-P'] + m4_defines + ['@INPUT@'],
+                command : [meson_apply_m4, config_h, '@INPUT@'],
                 capture : true,
                 install : install,
                 install_dir : systemunitdir)