]> git.ipfire.org Git - thirdparty/systemd.git/commitdiff
Merge pull request #6801 from johnlinp/master
authorLennart Poettering <lennart@poettering.net>
Thu, 14 Sep 2017 19:41:13 +0000 (21:41 +0200)
committerGitHub <noreply@github.com>
Thu, 14 Sep 2017 19:41:13 +0000 (21:41 +0200)
man: explicitly distinguish "implicit dependencies" and "default dependencies"

93 files changed:
TODO
hwdb/60-sensor.hwdb
man/standard-conf.xml
man/systemd-nspawn.xml
man/systemd-run.xml
man/systemd-sysusers.xml
man/systemd.device.xml
man/systemd.exec.xml
man/systemd.link.xml
man/systemd.nspawn.xml
man/systemd.socket.xml
man/sysusers.d.xml
man/tmpfiles.d.xml
rules/60-persistent-storage.rules
rules/80-drivers.rules
src/basic/conf-files.c
src/basic/conf-files.h
src/basic/env-util.c
src/basic/env-util.h
src/basic/exec-util.c
src/basic/missing.h
src/basic/util.c
src/basic/util.h
src/binfmt/binfmt.c
src/core/dbus-execute.c
src/core/device.c
src/core/execute.c
src/core/execute.h
src/core/load-fragment-gperf.gperf.m4
src/core/load-fragment.c
src/core/load-fragment.h
src/core/main.c
src/core/timer.c
src/core/umount.c
src/core/unit.c
src/environment-d-generator/environment-d-generator.c
src/gpt-auto-generator/gpt-auto-generator.c
src/hwdb/hwdb.c
src/journal/catalog.c
src/libsystemd/sd-bus/bus-internal.h
src/libsystemd/sd-bus/bus-socket.c
src/modules-load/modules-load.c
src/network/netdev/netdev.c
src/network/networkd-network.c
src/nspawn/nspawn-gperf.gperf
src/nspawn/nspawn-seccomp.c
src/nspawn/nspawn-seccomp.h
src/nspawn/nspawn-settings.c
src/nspawn/nspawn-settings.h
src/nspawn/nspawn.c
src/nss-mymachines/nss-mymachines.c
src/nss-systemd/nss-systemd.c
src/resolve/resolved-dns-trust-anchor.c
src/run/run.c
src/shared/bus-unit-util.c
src/shared/conf-parser.c
src/shared/dropin.c
src/shared/install.c
src/shared/pager.c
src/shared/seccomp-util.c
src/shared/seccomp-util.h
src/shared/specifier.c
src/sleep/sleep.c
src/sysctl/sysctl.c
src/sysusers/sysusers.c
src/test/test-conf-files.c
src/test/test-execute.c
src/test/test-seccomp.c
src/test/test-unit-name.c
src/tmpfiles/tmpfiles.c
src/udev/net/link-config.c
src/udev/udev-rules.c
src/udev/udevadm-hwdb.c
test/meson.build
test/test-execute/exec-unset-environment.service [new file with mode: 0644]
tmpfiles.d/journal-nocow.conf
units/debug-shell.service.in
units/getty@.service.m4
units/systemd-coredump@.service.in
units/systemd-hostnamed.service.in
units/systemd-importd.service.in
units/systemd-journal-gatewayd.service.in
units/systemd-journal-remote.service.in
units/systemd-journal-upload.service.in
units/systemd-journald.service.in
units/systemd-localed.service.in
units/systemd-logind.service.in
units/systemd-machined.service.in
units/systemd-networkd.service.in
units/systemd-resolved.service.in
units/systemd-timedated.service.in
units/systemd-timesyncd.service.in
units/systemd-udevd.service.in

diff --git a/TODO b/TODO
index 4e5a28d3f1f8ac92f712a93467a5febb59736e24..cabba100a521ad08eee4af7a93dab0d0c2bb04cb 100644 (file)
--- a/TODO
+++ b/TODO
@@ -27,11 +27,6 @@ Features:
 * dissect: when we discover squashfs, don't claim we had a "writable" partition
   in systemd-dissect
 
-* systemd-run should have a way how to connect a pair of pipes to
-  stdout/stderr/stdin of the invoked service
-
-* set LockPersonality= on all our services
-
 * Add AddUser= setting to unit files, similar to DynamicUser=1 which however
   creates a static, persistent user rather than a dynamic, transient user. We
   can leverage code from sysusers.d for this.
@@ -45,8 +40,6 @@ Features:
   diffs remain minimal (in particular: the OUI databases we import are not
   sorted, and not stable)
 
-* set SystemCallArchitectures=native on all our services
-
 * maybe add call sd_journal_set_block_timeout() or so to set SO_SNDTIMEO for
   the sd-journal logging socket, and, if the timeout is set to 0, sets
   O_NONBLOCK on it. That way people can control if and when to block for
@@ -55,13 +48,6 @@ Features:
 * tighten sd_notify() MAINPID= checks a bit: don't accept foreign PIDs (i.e.
   PIDs not managed by the service manager)
 
-* journald: when we recv a log datagram via the native or syslog transports,
-  search for the PID in the active stream connections, and let's make sure to
-  always process the datagrams before the streams. Then, cache client metadata
-  per stream in the stream object. This way we can somewhat fix the race with
-  quickly exiting processes which log as long as they had their own stream
-  connection...
-
 * hostnamed: populate form factor data from a new hwdb database, so that old
   yogas can be recognized as "convertible" too, even if they predate the DMI
   "convertible" form factor
@@ -102,8 +88,6 @@ Features:
 
 * maybe introduce gpt auto discovery for /var/tmp?
 
-* set ProtectSystem=strict for all our usual services.
-
 * fix PrivateNetwork= so that we fall back gracefully on kernels lacking
   namespacing support (similar for the other namespacing options)
 
@@ -148,8 +132,6 @@ Features:
 
 * enable LockMLOCK to take a percentage value relative to physical memory
 
-* switch to ProtectSystem=strict for all our long-running services where that's possible
-
 * Permit masking specific netlink APIs with RestrictAddressFamily=
 
 * nspawn: start UID allocation loop from hash of container name
@@ -474,8 +456,6 @@ Features:
 
 * maybe add a generator that looks for "systemd.run=" on the kernel cmdline for container usercases...
 
-* cgtop: make cgtop useful in a container
-
 * test/:
   - add 'set -e' to scripts in test/
   - make stuff in test/ work with separate output dir
@@ -725,8 +705,6 @@ Features:
 
 * cryptsetup:
   - cryptsetup-generator: allow specification of passwords in crypttab itself
-  - move cryptsetup key caching into kernel keyctl?
-    https://bugs.freedesktop.org/show_bug.cgi?id=54982
   - support rd.luks.allow-discards= kernel cmdline params in cryptsetup generator
 
 * hw watchdog: optionally try to use the preset watchdog timeout instead of always overriding it
@@ -746,8 +724,6 @@ Features:
   - add trigger --subsystem-match=usb/usb_device device
   - reimport udev db after MOVE events for devices without dev_t
 
-* when a service has the same env var set twice we actually store it twice and return that in systemctl show -p... We should only show the last setting
-
 * There's currently no way to cancel fsck (used to be possible via C-c or c on the console)
 
 * add option to sockets to avoid activation. Instead just drop packets/connections, see http://cyberelk.net/tim/2012/02/15/portreserve-systemd-solution/
@@ -806,10 +782,7 @@ Features:
 
 * dot output for --test showing the 'initial transaction'
 
-* fingerprint.target, wireless.target, gps.target, netdevice.target
-
 * pid1:
-  - .timer units should optionally support CLOCK_BOOTTIME in addition to CLOCK_MONOTONIC
   - When logging about multiple units (stopping BoundTo units, conflicts, etc.),
     log both units as UNIT=, so that journalctl -u triggers on both.
   - generate better errors when people try to set transient properties
@@ -845,12 +818,9 @@ Features:
   - load-fragment: when loading a unit file via a chain of symlinks
     verify that it is not masked via any of the names traversed.
   - introduce Type=pid-file
-  - ExecOnFailure=/usr/bin/foo
   - introduce mix of BindTo and Requisite
   - add a concept of RemainAfterExit= to scope units
-  - Set NoNewPrivileges= on all of our own services, where that makes sense
   - Allow multiple ExecStart= for all Type= settings, so that we can cover rescue.service nicely
-  - consider adding RuntimeDirectoryUser= + RuntimeDirectoryGroup=
 
 * udev-link-config:
    - Make sure ID_PATH is always exported and complete for
@@ -892,7 +862,6 @@ Features:
 
 * dhcp:
    - figure out how much we can increase Maximum Message Size
-   - support RFC4702 (pass FQDN)
 
 * dhcp6:
    - add functions to set previously stored IPv6 addresses on startup and get
@@ -924,8 +893,6 @@ External:
 
 * drop accountsservice's StandardOutput=syslog and Type=dbus fields
 
-* dbus: in fedora, make /var/lib/dbus/machine-id a symlink to /etc/machine-id
-
 * /usr/bin/service should actually show the new command line
 
 * fedora: suggest auto-restart on failure, but not on success and not on coredump. also, ask people to think about changing the start limit logic. Also point people to RestartPreventExitStatus=, SuccessExitStatus=
index 10de01ca45051b5fd2f9cc4e3802a2b9bbac7083..403ebba5841595119493c4f3aea4cd5fa5ad59ad 100644 (file)
@@ -135,6 +135,12 @@ sensor:modalias:acpi:SMO8500*:dmi:*svnLamina*:*pnT701BR.SE*
 sensor:modalias:acpi:KIOX000A*:dmi:*svnLAMINA:pnT-1016BNORD*
  ACCEL_MOUNT_MATRIX=0, 1, 0; 1, 0, 0; 0, 0, 1
 
+#########################################
+# Lenovo
+#########################################
+sensor:modalias:acpi:NCPE0388*:dmi:*:rnLenovoYOGA510-14IKB:*
+ ACCEL_MOUNT_MATRIX=-1, 0, 0; 0, -1, 0; 0, 0, 1
+
 #########################################
 # Peaq
 #########################################
index 6edbb7ff83aa925aa2910bc76ce8dbff718910cf..40764f525b28fcf63242ddfac333a069d0192ad4 100644 (file)
@@ -32,7 +32,6 @@
     <filename>/etc/</filename>, with the same filename as the vendor
     configuration file. If the vendor configuration file is included in
     the initrd image, the image has to be regenerated.</para>
-
   </refsection>
 
   <refsection id='main-conf'>
index 5d3212dec7e60243899ffdd1fb871d23619702bc..3951e32e8f5e7074cdd7327733a2556c0a7f9f56 100644 (file)
         above).</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><option>--system-call-filter=</option></term>
+
+        <listitem><para>Alter the system call filter applied to containers. Takes a space-separated list of system call
+        names or group names (the latter prefixed with <literal>@</literal>, as listed by the
+        <command>syscall-filter</command> command of <citerefentry
+        project='man-pages'><refentrytitle>systemd-analyze</refentrytitle><manvolnum>1</manvolnum></citerefentry>). Passed
+        system calls will be permitted. The list may optionally be prefixed by <literal>~</literal>, in which case all
+        listed system calls are prohibited. If this command line option is used multiple times the configured lists are
+        combined. If both a positive and a negative list (that is one system call list without and one with the
+        <literal>~</literal> prefix) are configured, the negative list takes precedence over the positive list. Note
+        that <command>systemd-nspawn</command> always implements a system call whitelist (as opposed to a blacklist),
+        and this command line option hence adds or removes entries from the default whitelist, depending on the
+        <literal>~</literal> prefix. Note that the applied system call filter is also altered implicitly if additional
+        capabilities are passed using the <command>--capabilities=</command>.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><option>--kill-signal=</option></term>
 
index 5e44b1523ddd0ae4643124e027791e5c96635876..7477195dabd87e6ec1ab26ab517c1c18e70ea68f 100644 (file)
         <term><option>--pty</option></term>
         <term><option>-t</option></term>
 
-        <listitem><para>When invoking the command, the transient service connects its standard input and output to the
-        terminal <command>systemd-run</command> is invoked on, via a pseudo TTY device. This allows running binaries
-        that expect interactive user input as services, such as interactive command shells.</para>
+        <listitem><para>When invoking the command, the transient service connects its standard input, output and error
+        to the terminal <command>systemd-run</command> is invoked on, via a pseudo TTY device. This allows running
+        programs that expect interactive user input/output as services, such as interactive command shells.</para>
 
         <para>Note that
         <citerefentry><refentrytitle>machinectl</refentrytitle><manvolnum>1</manvolnum></citerefentry>'s
         <command>shell</command> command is usually a better alternative for requesting a new, interactive login
-        session on the local host or a local container.</para></listitem>
+        session on the local host or a local container.</para>
+
+        <para>See below for details on how this switch combines with <option>--pipe</option>.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><option>--pipe</option></term>
+        <term><option>-P</option></term>
+
+        <listitem><para>If specified, standard input, output, and error of the transient service are inherited from the
+        <command>systemd-run</command> command itself. This allows <command>systemd-run</command>
+        to be used within shell pipelines.
+        Note that this mode is not suitable for interactive command shells and similar, as the
+        service process will not become a TTY controller when invoked on a terminal. Use <option>--pty</option> instead
+        in that case.</para>
+
+        <para>When both <option>--pipe</option> and <option>--pty</option> are used in combination the more appropriate
+        option is automatically determined and used. Specifically, when invoked with standard input, output and error
+        connected to a TTY <option>--pty</option> is used, and otherwise <option>--pipe</option>.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 4892caad12937a73f41add5d9f92444d816ca14c..990b935cf214c3ef480801001cce44fca232e314 100644 (file)
@@ -74,7 +74,7 @@
     specified in
     <citerefentry><refentrytitle>sysusers.d</refentrytitle><manvolnum>5</manvolnum></citerefentry>
     are searched for a matching file. If the string
-    <filename>-</filename> is specified as filename, entries from the
+    <literal>-</literal> is specified instead of a filename, entries from the
     standard input of the process are read.</para>
   </refsect1>
 
index c60b9c035ef98081c71f7d65895b591103b70bc7..6edf1090d0e0409b66b62d8336e86bcefadf0b67 100644 (file)
     the escaping logic used to convert a file system path to a unit
     name see
     <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>.</para>
+
+    <para>Device units will be reloaded by systemd whenever the
+    corresponding device generates a <literal>changed</literal> event.
+    Other units can use <varname>ReloadPropagatedFrom=</varname> to react
+    to that event</para>
+
   </refsect1>
 
   <refsect1>
index 0661fa8b39c9fe5af2d02f015851ca590060d6fb..7821b69cd0b168898a9b066686da5e11102f052d 100644 (file)
       <varlistentry>
         <term><varname>PassEnvironment=</varname></term>
 
-        <listitem><para>Pass environment variables from the systemd system
-        manager to executed processes. Takes a space-separated list of variable
-        names. This option may be specified more than once, in which case all
-        listed variables will be set. If the empty string is assigned to this
-        option, the list of environment variables is reset, all prior
-        assignments have no effect. Variables that are not set in the system
-        manager will not be passed and will be silently ignored.</para>
-
-        <para>Variables passed from this setting are overridden by those passed
-        from <varname>Environment=</varname> or
-        <varname>EnvironmentFile=</varname>.</para>
+        <listitem><para>Pass environment variables set for the system service manager to executed processes. Takes a
+        space-separated list of variable names. This option may be specified more than once, in which case all listed
+        variables will be passed. If the empty string is assigned to this option, the list of environment variables to
+        pass is reset, all prior assignments have no effect. Variables specified that are not set for the system
+        manager will not be passed and will be silently ignored. Note that this option is only relevant for the system
+        service manager, as system services by default do not automatically inherit any environment variables set for
+        the service manager itself. However, in case of the user service manager all environment variables are passed
+        to the executed processes anyway, hence this option is without effect for the user service manager.</para>
+
+        <para>Variables set for invoked processes due to this setting are subject to being overridden by those
+        configured with <varname>Environment=</varname> or <varname>EnvironmentFile=</varname>.</para>
 
         <para>Example:
         <programlisting>PassEnvironment=VAR1 VAR2 VAR3</programlisting>
         for details about environment variables.</para></listitem>
       </varlistentry>
 
+      <varlistentry>
+        <term><varname>UnsetEnvironment=</varname></term>
+
+        <listitem><para>Explicitly unset environment variable assignments that would normally be passed from the
+        service manager to invoked processes of this unit. Takes a space-separated list of variable names or variable
+        assignments. This option may be specified more than once, in which case all listed variables/assignments will
+        be unset. If the empty string is assigned to this option, the list of environment variables/assignments to
+        unset is reset. If a variable assignment is specified (that is: a variable name, followed by
+        <literal>=</literal>, followed by its value), then any environment variable matching this precise assignment is
+        removed. If a variable name is specified (that is a variable name without any following <literal>=</literal> or
+        value), then any assignment matching the variable name, regardless of its value is removed. Note that the
+        effect of <varname>UnsetEnvironment=</varname> is applied as final step when the environment list passed to
+        executed processes is compiled. That means it may undo assignments from any configuration source, including
+        assignments made through <varname>Environment=</varname> or <varname>EnvironmentFile=</varname>, inherited from
+        the system manager's global set of environment variables, inherited via <varname>PassEnvironment=</varname>,
+        set by the service manager itself (such as <varname>$NOTIFY_SOCKET</varname> and such), or set by a PAM module
+        (in case <varname>PAMName=</varname> is used).</para>
+
+        <para>
+        See
+        <citerefentry project='man-pages'><refentrytitle>environ</refentrytitle><manvolnum>7</manvolnum></citerefentry>
+        for details about environment variables.</para></listitem>
+      </varlistentry>
+
       <varlistentry>
         <term><varname>StandardInput=</varname></term>
         <listitem><para>Controls where file descriptor 0 (STDIN) of
@@ -1464,6 +1488,10 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry>@cpu-emulation</entry>
                 <entry>System calls for CPU emulation functionality (<citerefentry project='man-pages'><refentrytitle>vm86</refentrytitle><manvolnum>2</manvolnum></citerefentry> and related calls)</entry>
               </row>
+              <row>
+                <entry>@credentials</entry>
+                <entry>System calls for querying process credentials (<citerefentry project='man-pages'><refentrytitle>getuid</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>capget</refentrytitle><manvolnum>2</manvolnum></citerefentry>, and related calls)</entry>
+              </row>
               <row>
                 <entry>@debug</entry>
                 <entry>Debugging, performance monitoring and tracing functionality (<citerefentry project='man-pages'><refentrytitle>ptrace</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>perf_event_open</refentrytitle><manvolnum>2</manvolnum></citerefentry> and related calls)</entry>
@@ -1484,6 +1512,10 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry>@keyring</entry>
                 <entry>Kernel keyring access (<citerefentry project='man-pages'><refentrytitle>keyctl</refentrytitle><manvolnum>2</manvolnum></citerefentry> and related calls)</entry>
               </row>
+              <row>
+                <entry>@memlock</entry>
+                <entry>Locking of memory into RAM (<citerefentry project='man-pages'><refentrytitle>mlock</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>mlockall</refentrytitle><manvolnum>2</manvolnum></citerefentry> and related calls)</entry>
+              </row>
               <row>
                 <entry>@module</entry>
                 <entry>Loading and unloading of kernel modules (<citerefentry project='man-pages'><refentrytitle>init_module</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>delete_module</refentrytitle><manvolnum>2</manvolnum></citerefentry> and related calls)</entry>
@@ -1524,10 +1556,18 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry>@setuid</entry>
                 <entry>System calls for changing user ID and group ID credentials, (<citerefentry project='man-pages'><refentrytitle>setuid</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>setgid</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>setresuid</refentrytitle><manvolnum>2</manvolnum></citerefentry>, â€¦)</entry>
               </row>
+              <row>
+                <entry>@signal</entry>
+                <entry>System calls for manipulating and handling process signals (<citerefentry project='man-pages'><refentrytitle>signal</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>sigprocmask</refentrytitle><manvolnum>2</manvolnum></citerefentry>, â€¦)</entry>
+              </row>
               <row>
                 <entry>@swap</entry>
                 <entry>System calls for enabling/disabling swap devices (<citerefentry project='man-pages'><refentrytitle>swapon</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>swapoff</refentrytitle><manvolnum>2</manvolnum></citerefentry>)</entry>
               </row>
+              <row>
+                <entry>@timer</entry>
+                <entry>System calls for scheduling operations by time (<citerefentry project='man-pages'><refentrytitle>alarm</refentrytitle><manvolnum>2</manvolnum></citerefentry>, <citerefentry project='man-pages'><refentrytitle>timer_create</refentrytitle><manvolnum>2</manvolnum></citerefentry>, â€¦)</entry>
+              </row>
             </tbody>
           </tgroup>
         </table>
@@ -1802,12 +1842,38 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
   <refsect1>
     <title>Environment variables in spawned processes</title>
 
-    <para>Processes started by the system are executed in a clean
-    environment in which select variables listed below are set. System
-    processes started by systemd do not inherit variables from PID 1,
-    but processes started by user systemd instances inherit all
-    environment variables from the user systemd instance.
-    </para>
+    <para>Processes started by the service manager are executed with an environment variable block assembled from
+    multiple sources. Processes started by the system service manager generally do not inherit environment variables
+    set for the service manager itself (but this may be altered via <varname>PassEnvironment=</varname>), but processes
+    started by the user service manager instances generally do inherit all environment variables set for the service
+    manager itself.</para>
+
+    <para>For each invoked process the list of environment variables set is compiled from the following sources:</para>
+
+    <itemizedlist>
+      <listitem><para>Variables globally configured for the service manager, using the
+      <varname>DefaultEnvironment=</varname> setting in
+      <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>, the kernel command line option <varname>systemd.setenv=</varname> (see
+    <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>) or via
+      <command>systemctl set-environment</command> (see <citerefentry><refentrytitle>systemctl</refentrytitle><manvolnum>1</manvolnum></citerefentry>).</para></listitem>
+
+      <listitem><para>Variables defined by the service manager itself (see the list below)</para></listitem>
+
+      <listitem><para>Variables set in the service manager's own environment variable block (subject to <varname>PassEnvironment=</varname> for the system service manager)</para></listitem>
+
+      <listitem><para>Variables set via <varname>Environment=</varname> in the unit file</para></listitem>
+
+      <listitem><para>Variables read from files specified via <varname>EnvironmentFiles=</varname> in the unit file</para></listitem>
+
+      <listitem><para>Variables set by any PAM modules in case <varname>PAMName=</varname> is in effect, cf. <citerefentry project='man-pages'><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry></para></listitem>
+    </itemizedlist>
+
+    <para>If the same environment variables are set by multiple of these sources, the later source â€” according to the
+    order of the list above â€” wins. Note that as final step all variables listed in
+    <varname>UnsetEnvironment=</varname> are removed again from the compiled environment variable list, immediately
+    before it is passed to the executed process.</para>
+
+    <para>The following select environment variables are set by the service manager itself for each invoked process:</para>
 
     <variablelist class='environment-variables'>
       <varlistentry>
@@ -1958,15 +2024,60 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
 
         <listitem><para>Only defined for the service unit type, this environment variable is passed to all
         <varname>ExecStop=</varname> and <varname>ExecStopPost=</varname> processes, and encodes the service
-        "result". Currently, the following values are defined: <literal>protocol</literal> (in case of a protocol
-        violation; if a service did not take the steps required by its unit configuration), <literal>timeout</literal>
-        (in case of an operation timeout), <literal>exit-code</literal> (if a service process exited with a non-zero
-        exit code; see <varname>$EXIT_CODE</varname> below for the actual exit code returned), <literal>signal</literal>
-        (if a service process was terminated abnormally by a signal; see <varname>$EXIT_CODE</varname> below for the
-        actual signal used for the termination), <literal>core-dump</literal> (if a service process terminated
-        abnormally and dumped core), <literal>watchdog</literal> (if the watchdog keep-alive ping was enabled for the
-        service but it missed the deadline), or <literal>resources</literal> (a catch-all condition in case a system
-        operation failed).</para>
+        "result". Currently, the following values are defined:</para>
+
+        <table>
+          <title>Defined <varname>$SERVICE_RESULT</varname> values</title>
+          <tgroup cols='2'>
+            <colspec colname='result'/>
+            <colspec colname='meaning'/>
+            <thead>
+              <row>
+                <entry>Value</entry>
+                <entry>Meaning</entry>
+              </row>
+            </thead>
+
+            <tbody>
+              <row>
+                <entry><literal>success</literal></entry>
+                <entry>The service ran successfully and exited cleanly.</entry>
+              </row>
+              <row>
+                <entry><literal>protocol</literal></entry>
+                <entry>A protocol violation occurred: the service did not take the steps required by its unit configuration (specifically what is configured in its <varname>Type=</varname> setting).</entry>
+              </row>
+              <row>
+                <entry><literal>timeout</literal></entry>
+                <entry>One of the steps timed out.</entry>
+              </row>
+              <row>
+                <entry><literal>exit-code</literal></entry>
+                <entry>Service process exited with a non-zero exit code; see <varname>$EXIT_CODE</varname> below for the actual exit code returned.</entry>
+              </row>
+              <row>
+                <entry><literal>signal</literal></entry>
+                <entry>A service process was terminated abnormally by a signal, without dumping core. See <varname>$EXIT_CODE</varname> below for the actual signal causing the termination.</entry>
+              </row>
+              <row>
+                <entry><literal>core-dump</literal></entry>
+                <entry>A service process terminated abnormally with a signal and dumped core. See <varname>$EXIT_CODE</varname> below for the signal causing the termination.</entry>
+              </row>
+              <row>
+                <entry><literal>watchdog</literal></entry>
+                <entry>Watchdog keep-alive ping was enabled for the service, but the deadline was missed.</entry>
+              </row>
+              <row>
+                <entry><literal>start-limit-hit</literal></entry>
+                <entry>A start limit was defined for the unit and it was hit, causing the unit to fail to start. See <citerefentry><refentrytitle>systemd.unit</refentrytitle><manvolnum>5</manvolnum></citerefentry>'s <varname>StartLimitIntervalSec=</varname> and <varname>StartLimitBurst=</varname> for details.</entry>
+              </row>
+              <row>
+                <entry><literal>resources</literal></entry>
+                <entry>A catch-all condition in case a system operation failed.</entry>
+              </row>
+            </tbody>
+          </tgroup>
+        </table>
 
         <para>This environment variable is useful to monitor failure or successful termination of a service. Even
         though this variable is available in both <varname>ExecStop=</varname> and <varname>ExecStopPost=</varname>, it
@@ -2004,6 +2115,11 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
             </thead>
 
             <tbody>
+              <row>
+                <entry valign="top"><literal>success</literal></entry>
+                <entry valign="top"><literal>exited</literal></entry>
+                <entry><literal>0</literal></entry>
+              </row>
               <row>
                 <entry morerows="1" valign="top"><literal>protocol</literal></entry>
                 <entry valign="top">not set</entry>
@@ -2013,7 +2129,6 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry><literal>exited</literal></entry>
                 <entry><literal>0</literal></entry>
               </row>
-
               <row>
                 <entry morerows="1" valign="top"><literal>timeout</literal></entry>
                 <entry valign="top"><literal>killed</literal></entry>
@@ -2024,26 +2139,22 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
                 >3</literal>, â€¦, <literal>255</literal></entry>
               </row>
-
               <row>
                 <entry valign="top"><literal>exit-code</literal></entry>
                 <entry valign="top"><literal>exited</literal></entry>
-                <entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
+                <entry><literal>1</literal>, <literal>2</literal>, <literal
                 >3</literal>, â€¦, <literal>255</literal></entry>
               </row>
-
               <row>
                 <entry valign="top"><literal>signal</literal></entry>
                 <entry valign="top"><literal>killed</literal></entry>
                 <entry><literal>HUP</literal>, <literal>INT</literal>, <literal>KILL</literal>, â€¦</entry>
               </row>
-
               <row>
                 <entry valign="top"><literal>core-dump</literal></entry>
                 <entry valign="top"><literal>dumped</literal></entry>
                 <entry><literal>ABRT</literal>, <literal>SEGV</literal>, <literal>QUIT</literal>, â€¦</entry>
               </row>
-
               <row>
                 <entry morerows="2" valign="top"><literal>watchdog</literal></entry>
                 <entry><literal>dumped</literal></entry>
@@ -2058,15 +2169,18 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
                 <entry><literal>0</literal>, <literal>1</literal>, <literal>2</literal>, <literal
                 >3</literal>, â€¦, <literal>255</literal></entry>
               </row>
-
+              <row>
+                <entry><literal>start-limit-hit</literal></entry>
+                <entry>not set</entry>
+                <entry>not set</entry>
+              </row>
               <row>
                 <entry><literal>resources</literal></entry>
                 <entry>any of the above</entry>
                 <entry>any of the above</entry>
               </row>
-
               <row>
-                <entry namest="results" nameend="code">Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the <literal>timeout</literal> and <literal>watchdog</literal> rows above only the signals that systemd sends have been included.</entry>
+                <entry namest="results" nameend="status">Note: the process may be also terminated by a signal not sent by systemd. In particular the process may send an arbitrary signal to itself in a handler for any of the non-maskable signals. Nevertheless, in the <literal>timeout</literal> and <literal>watchdog</literal> rows above only the signals that systemd sends have been included. Moreover, using <varname>SuccessExitStatus=</varname> additional exit statuses may be declared to indicate clean termination, which is not reflected by this table.</entry>
               </row>
             </tbody>
           </tgroup>
@@ -2075,18 +2189,6 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
         </listitem>
       </varlistentry>
     </variablelist>
-
-    <para>Additional variables may be configured by the following
-    means: for processes spawned in specific units, use the
-    <varname>Environment=</varname>, <varname>EnvironmentFile=</varname>
-    and <varname>PassEnvironment=</varname> options above; to specify
-    variables globally, use <varname>DefaultEnvironment=</varname>
-    (see
-    <citerefentry><refentrytitle>systemd-system.conf</refentrytitle><manvolnum>5</manvolnum></citerefentry>)
-    or the kernel option <varname>systemd.setenv=</varname> (see
-    <citerefentry><refentrytitle>systemd</refentrytitle><manvolnum>1</manvolnum></citerefentry>).
-    Additional variables may also be set through PAM,
-    cf. <citerefentry project='man-pages'><refentrytitle>pam_env</refentrytitle><manvolnum>8</manvolnum></citerefentry>.</para>
   </refsect1>
 
   <refsect1>
index 1a13a22877f9e34b864a15b7a1bb6acc3bee070a..066bed126b84c7c9944037cdaaa36abfe18bc851 100644 (file)
@@ -79,7 +79,7 @@
     how the device should be configured. The first (in lexical order)
     of the link files that matches a given device is applied. Note
     that a default file <filename>99-default.link</filename> is
-    shipped by the system, any user-supplied
+    shipped by the system. Any user-supplied
     <filename>.link</filename> should hence have a lexically earlier
     name to be considered at all.</para>
 
           <varname>NamePolicy=</varname> fail, or in case
           <varname>NamePolicy=</varname> is missing or
           disabled.</para>
+
+          <para>Note that specifying a name that the kernel might use for another
+          interface (for example <literal>eth0</literal>) is dangerous because the
+          name assignment done by udev will race with the assignment done by the
+          kernel, and only one interface may use the name. Depending on the order of
+          operations, either udev or the kernel will win, making the naming
+          unpredictable. It is best to use some different prefix, for example
+          <literal>internal0</literal>/<literal>external0</literal> or
+          <literal>lan0</literal>/<literal>lan1</literal>/<literal>lan3</literal>.
+          </para>
         </listitem>
       </varlistentry>
       <varlistentry>
index 4f3f0529119fafc766696ab9afdb7307fe2765cc..58024a071d545f579083ad9cc8594997e1ff8f40 100644 (file)
       <varlistentry>
         <term><varname>NotifyReady=</varname></term>
 
-        <listitem><para>Configures support for notifications from the container's init process.
-        This is equivalent to use <option>--notify-ready=</option> command line switch,
-        and takes the same options. See <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry>
-        for details about the specific options supported.</para></listitem>
+        <listitem><para>Configures support for notifications from the container's init process.  This is equivalent to
+        the <option>--notify-ready=</option> command line switch, and takes the same paramaters. See
+        <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for details
+        about the specific options supported.</para></listitem>
+      </varlistentry>
+
+      <varlistentry>
+        <term><varname>SystemCallFilter=</varname></term>
+
+        <listitem><para>Configures the system call filter applied to containers. This is equivalent to the
+        <option>--system-call-filter=</option> command line switch, and takes the same list parameter. See
+        <citerefentry><refentrytitle>systemd-nspawn</refentrytitle><manvolnum>1</manvolnum></citerefentry> for
+        details.</para></listitem>
       </varlistentry>
+
     </variablelist>
   </refsect1>
 
index 5bec53ac1ef37b5c6246e386aea853c7b9f6a98d..2dfca713e4bd51ffdf9661376a44081bb3adfbe6 100644 (file)
         is used, only one AF_UNIX socket in the file system or one
         FIFO may be configured for the socket unit. Use this option to
         manage one or more symlinked alias names for a socket, binding
-        their lifecycle together. Defaults to the empty
-        list.</para></listitem>
+        their lifecycle together. If the empty string is assigned, the
+        list of paths is reset. Defaults to the empty list.</para></listitem>
       </varlistentry>
 
       <varlistentry>
index 2b87385d9c3abe756103259ea50c8723dde3e40b..fbe97544d767c9a0f502b494dcae313cb8a702a7 100644 (file)
@@ -63,7 +63,7 @@
   </refsect1>
 
   <refsect1>
-    <title>Configuration Format</title>
+    <title>Configuration Directories and Precedence</title>
 
     <para>Each configuration file shall be named in the style of
     <filename><replaceable>package</replaceable>.conf</filename> or
     The second variant should be used when it is desirable to make it
     easy to override just this part of configuration.</para>
 
+    <para>Files in <filename>/etc/sysusers.d</filename> override files
+    with the same name in <filename>/usr/lib/sysusers.d</filename> and
+    <filename>/run/sysusers.d</filename>. Files in
+    <filename>/run/sysusers.d</filename> override files with the same
+    name in <filename>/usr/lib/sysusers.d</filename>. Packages should
+    install their configuration files in
+    <filename>/usr/lib/sysusers.d</filename>. Files in
+    <filename>/etc/sysusers.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 later
+    entries for the same user and group names will be logged as warnings.
+    </para>
+
+    <para>If the administrator wants to disable a configuration file
+    supplied by the vendor, the recommended way is to place a symlink
+    to <filename>/dev/null</filename> in
+    <filename>/etc/sysusers.d/</filename> bearing the same filename.
+    </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Configuration File Format</title>
+
     <para>The file format is one line per user or group containing
     name, ID, GECOS field description and home directory:</para>
 
-    <programlisting># Type Name ID GECOS
-u httpd 440 "HTTP User"
-u authd /usr/bin/authd "Authorization user"
-g input - -
-m authd input
-u root 0 "Superuser" /root</programlisting>
+    <programlisting>#Type  Name   ID              GECOS                 Home directory
+u      httpd  440             "HTTP User"
+u      authd  /usr/bin/authd  "Authorization user"
+g      input  -               -
+m      authd  input
+u      root   0               "Superuser"           /root</programlisting>
 
     <para>Empty lines and lines beginning with the <literal>#</literal> character are ignored, and may be used for
     commenting.</para>
@@ -198,11 +225,8 @@ u root 0 "Superuser" /root</programlisting>
       should otherwise be left unset, or be set to
       <literal>-</literal>.</para>
     </refsect2>
-
   </refsect1>
 
-  <xi:include href="standard-conf.xml" xpointer="confd" />
-
   <refsect1>
     <title>Idempotence</title>
 
index 29f85531967fe211821b26363f53a4d02c07ac85..a5c2b59e7e1f50e3d5057310aaca3af00cf03172 100644 (file)
@@ -76,7 +76,7 @@
   </refsect1>
 
   <refsect1>
-    <title>Configuration Format</title>
+    <title>Configuration Directories and Precedence</title>
 
     <para>Each configuration file shall be named in the style of
     <filename><replaceable>package</replaceable>.conf</filename> or
     to <filename>/dev/null</filename> in
     <filename>/etc/tmpfiles.d/</filename> bearing the same filename.
     </para>
+  </refsect1>
+
+  <refsect1>
+    <title>Configuration File Format</title>
 
     <para>The configuration format is one line per path containing
     type, path, mode, ownership, age, and argument fields:</para>
index d2745f65f4e0f2927f13fc8562ce454d7568dd02..72fec5c88482c032e6409680bd4dded72ee29ff3 100644 (file)
@@ -57,6 +57,9 @@ KERNEL=="mmcblk[0-9]", SUBSYSTEMS=="mmc", ATTRS{name}=="?*", ATTRS{serial}=="?*"
   ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}"
 KERNEL=="mmcblk[0-9]p[0-9]*", ENV{ID_NAME}=="?*", ENV{ID_SERIAL}=="?*", SYMLINK+="disk/by-id/mmc-$env{ID_NAME}_$env{ID_SERIAL}-part%n"
 
+# UBI-MTD
+SUBSYSTEM=="ubi", KERNEL=="ubi*_*", ATTRS{mtd_num}=="*", SYMLINK+="ubi_mtd%s{mtd_num}_%s{name}"
+
 # Memstick
 KERNEL=="msblk[0-9]|mspblk[0-9]", SUBSYSTEMS=="memstick", ATTRS{name}=="?*", ATTRS{serial}=="?*", \
   ENV{ID_NAME}="$attr{name}", ENV{ID_SERIAL}="$attr{serial}", SYMLINK+="disk/by-id/memstick-$env{ID_NAME}_$env{ID_SERIAL}"
index 8551f47a4b433b85d131bdbb2acb4052f0b39b2d..16fa5d8e3233b9026240e71e2453ec4c1e10a489 100644 (file)
@@ -1,6 +1,6 @@
 # do not edit this file, it will be overwritten on update
 
-ACTION=="remove", GOTO="drivers_end"
+ACTION!="add", GOTO="drivers_end"
 
 ENV{MODALIAS}=="?*", RUN{builtin}+="kmod load $env{MODALIAS}"
 SUBSYSTEM=="tifm", ENV{TIFM_CARD_TYPE}=="SD", RUN{builtin}+="kmod load tifm_sd"
index b8f0f5d03d227e370d0db4b6a5aa07e152b89016..d776583c05d9532e1571b19a8ef5873f358bb84b 100644 (file)
 #include "macro.h"
 #include "missing.h"
 #include "path-util.h"
+#include "stat-util.h"
 #include "string-util.h"
 #include "strv.h"
 #include "util.h"
 
-static int files_add(Hashmap *h, const char *root, const char *path, const char *suffix) {
+static int files_add(Hashmap *h, const char *suffix, const char *root, unsigned flags, const char *path) {
         _cleanup_closedir_ DIR *dir = NULL;
         const char *dirpath;
         struct dirent *de;
@@ -56,8 +57,35 @@ static int files_add(Hashmap *h, const char *root, const char *path, const char
         FOREACH_DIRENT(de, dir, return -errno) {
                 char *p;
 
-                if (!dirent_is_file_with_suffix(de, suffix))
+                if (!dirent_is_file_with_suffix(de, suffix)) {
+                        log_debug("Ignoring %s/%s, because it's not a regular file with suffix %s.", dirpath, de->d_name, strna(suffix));
                         continue;
+                }
+
+                if (flags & CONF_FILES_EXECUTABLE) {
+                        struct stat st;
+
+                        /* As requested: check if the file is marked exectuable. Note that we don't check access(X_OK)
+                         * here, as we care about whether the file is marked executable at all, and not whether it is
+                         * executable for us, because if such errors are stuff we should log about. */
+
+                        if (fstatat(dirfd(dir), de->d_name, &st, 0) < 0) {
+                                log_debug_errno(errno, "Failed to stat %s/%s, ignoring: %m", dirpath, de->d_name);
+                                continue;
+                        }
+
+                        /* We only want executable regular files (or symlinks to them), or symlinks to /dev/null */
+                        if (S_ISREG(st.st_mode)) {
+                                if ((st.st_mode & 0111) == 0) { /* not executable */
+                                        log_debug("Ignoring %s/%s, as it is not marked executable.", dirpath, de->d_name);
+                                        continue;
+                                }
+
+                        } else if (!null_or_empty(&st)) { /* /dev/null? */
+                                log_debug("Ignoring %s/%s, as it is not a regular file (or symlink to /dev/null).", dirpath, de->d_name);
+                                continue;
+                        }
+                }
 
                 p = strjoin(dirpath, "/", de->d_name);
                 if (!p)
@@ -87,7 +115,7 @@ static int base_cmp(const void *a, const void *b) {
         return strcmp(basename(s1), basename(s2));
 }
 
-static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, char **dirs) {
+static int conf_files_list_strv_internal(char ***strv, const char *suffix, const char *root, unsigned flags, char **dirs) {
         _cleanup_hashmap_free_ Hashmap *fh = NULL;
         char **files, **p;
         int r;
@@ -103,7 +131,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
                 return -ENOMEM;
 
         STRV_FOREACH(p, dirs) {
-                r = files_add(fh, root, *p, suffix);
+                r = files_add(fh, suffix, root, flags, *p);
                 if (r == -ENOMEM)
                         return r;
                 if (r < 0)
@@ -120,7 +148,7 @@ static int conf_files_list_strv_internal(char ***strv, const char *suffix, const
         return 0;
 }
 
-int conf_files_list_strv(char ***strv, const char *suffix, const char *root, const char* const* dirs) {
+int conf_files_list_strv(char ***strv, const char *suffix, const char *root, unsigned flags, const char* const* dirs) {
         _cleanup_strv_free_ char **copy = NULL;
 
         assert(strv);
@@ -129,10 +157,10 @@ int conf_files_list_strv(char ***strv, const char *suffix, const char *root, con
         if (!copy)
                 return -ENOMEM;
 
-        return conf_files_list_strv_internal(strv, suffix, root, copy);
+        return conf_files_list_strv_internal(strv, suffix, root, flags, copy);
 }
 
-int conf_files_list(char ***strv, const char *suffix, const char *root, const char *dir, ...) {
+int conf_files_list(char ***strv, const char *suffix, const char *root, unsigned flags, const char *dir, ...) {
         _cleanup_strv_free_ char **dirs = NULL;
         va_list ap;
 
@@ -145,10 +173,10 @@ int conf_files_list(char ***strv, const char *suffix, const char *root, const ch
         if (!dirs)
                 return -ENOMEM;
 
-        return conf_files_list_strv_internal(strv, suffix, root, dirs);
+        return conf_files_list_strv_internal(strv, suffix, root, flags, dirs);
 }
 
-int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, const char *d) {
+int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, unsigned flags, const char *d) {
         _cleanup_strv_free_ char **dirs = NULL;
 
         assert(strv);
@@ -157,5 +185,5 @@ int conf_files_list_nulstr(char ***strv, const char *suffix, const char *root, c
         if (!dirs)
                 return -ENOMEM;
 
-        return conf_files_list_strv_internal(strv, suffix, root, dirs);
+        return conf_files_list_strv_internal(strv, suffix, root, flags, dirs);
 }
index e00e0e81fbd3713e5a5d8d49f1285e2227c6a6a5..20ecf6e5f15da0ec9dd8d70ce0adccb67b44d9e0 100644 (file)
   along with systemd; If not, see <http://www.gnu.org/licenses/>.
 ***/
 
-int conf_files_list(char ***ret, const char *suffix, const char *root, const char *dir, ...);
-int conf_files_list_strv(char ***ret, const char *suffix, const char *root, const char* const* dirs);
-int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, const char *dirs);
+enum {
+        CONF_FILES_EXECUTABLE = 1,
+};
+
+int conf_files_list(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dir, ...);
+int conf_files_list_strv(char ***ret, const char *suffix, const char *root, unsigned flags, const char* const* dirs);
+int conf_files_list_nulstr(char ***ret, const char *suffix, const char *root, unsigned flags, const char *dirs);
index 56e7b6fd8c1d92b33032179bc91d6ed114c0da80..d72940acb3858bc34927bfb5c71ee0c4f3f4d2f1 100644 (file)
@@ -769,6 +769,16 @@ int getenv_bool(const char *p) {
         return parse_boolean(e);
 }
 
+int getenv_bool_secure(const char *p) {
+        const char *e;
+
+        e = secure_getenv(p);
+        if (!e)
+                return -ENXIO;
+
+        return parse_boolean(e);
+}
+
 int serialize_environment(FILE *f, char **environment) {
         char **e;
 
index e88fa6aac04e5568e3b3b91ec17555b820b0896f..d5da8cd67b254ca4ca3fd46802c9b8f3dd895f91 100644 (file)
@@ -61,6 +61,7 @@ char *strv_env_get_n(char **l, const char *name, size_t k, unsigned flags) _pure
 char *strv_env_get(char **x, const char *n) _pure_;
 
 int getenv_bool(const char *p);
+int getenv_bool_secure(const char *p);
 
 int serialize_environment(FILE *f, char **environment);
 int deserialize_environment(char ***environment, const char *line);
index aced9e8e3db80004d2b5d398ed36640bf032e3a2..ade8511466c81d1cdef6983b35424be88f72d818 100644 (file)
@@ -111,7 +111,7 @@ static int do_execute(
 
         assert_se(prctl(PR_SET_PDEATHSIG, SIGTERM) == 0);
 
-        r = conf_files_list_strv(&paths, NULL, NULL, (const char* const*) directories);
+        r = conf_files_list_strv(&paths, NULL, NULL, CONF_FILES_EXECUTABLE, (const char* const*) directories);
         if (r < 0)
                 return r;
 
index 7830a4f415b927e7217d6b03d93c382bd2507556..0269066427cc2762127da470e3549c0b17eaaa60 100644 (file)
@@ -606,14 +606,13 @@ struct input_mask {
 #else
 #define __O_TMPFILE     020000000
 #endif
+#endif
 
 /* a horrid kludge trying to make sure that this will fail on old kernels */
 #ifndef O_TMPFILE
 #define O_TMPFILE (__O_TMPFILE | O_DIRECTORY)
 #endif
 
-#endif
-
 #if !HAVE_DECL_LO_FLAGS_PARTSCAN
 #define LO_FLAGS_PARTSCAN 8
 #endif
index 2f45128ed4160550102e6222c352617c579a2358..daaee99284ce9894ea433e63c1792864398e818c 100644 (file)
@@ -34,6 +34,7 @@
 #include <unistd.h>
 
 #include "alloc-util.h"
+#include "btrfs-util.h"
 #include "build.h"
 #include "cgroup-util.h"
 #include "def.h"
@@ -719,3 +720,133 @@ int version(void) {
              SYSTEMD_FEATURES);
         return 0;
 }
+
+int get_block_device(const char *path, dev_t *dev) {
+        struct stat st;
+        struct statfs sfs;
+
+        assert(path);
+        assert(dev);
+
+        /* Get's the block device directly backing a file system. If
+         * the block device is encrypted, returns the device mapper
+         * block device. */
+
+        if (lstat(path, &st))
+                return -errno;
+
+        if (major(st.st_dev) != 0) {
+                *dev = st.st_dev;
+                return 1;
+        }
+
+        if (statfs(path, &sfs) < 0)
+                return -errno;
+
+        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
+                return btrfs_get_block_device(path, dev);
+
+        return 0;
+}
+
+int get_block_device_harder(const char *path, dev_t *dev) {
+        _cleanup_closedir_ DIR *d = NULL;
+        _cleanup_free_ char *p = NULL, *t = NULL;
+        struct dirent *de, *found = NULL;
+        const char *q;
+        unsigned maj, min;
+        dev_t dt;
+        int r;
+
+        assert(path);
+        assert(dev);
+
+        /* Gets the backing block device for a file system, and
+         * handles LUKS encrypted file systems, looking for its
+         * immediate parent, if there is one. */
+
+        r = get_block_device(path, &dt);
+        if (r <= 0)
+                return r;
+
+        if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
+                return -ENOMEM;
+
+        d = opendir(p);
+        if (!d) {
+                if (errno == ENOENT)
+                        goto fallback;
+
+                return -errno;
+        }
+
+        FOREACH_DIRENT_ALL(de, d, return -errno) {
+
+                if (dot_or_dot_dot(de->d_name))
+                        continue;
+
+                if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
+                        continue;
+
+                if (found) {
+                        _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
+
+                        /* We found a device backed by multiple other devices. We don't really support automatic
+                         * discovery on such setups, with the exception of dm-verity partitions. In this case there are
+                         * two backing devices: the data partition and the hash partition. We are fine with such
+                         * setups, however, only if both partitions are on the same physical device. Hence, let's
+                         * verify this. */
+
+                        u = strjoin(p, "/", de->d_name, "/../dev");
+                        if (!u)
+                                return -ENOMEM;
+
+                        v = strjoin(p, "/", found->d_name, "/../dev");
+                        if (!v)
+                                return -ENOMEM;
+
+                        r = read_one_line_file(u, &a);
+                        if (r < 0) {
+                                log_debug_errno(r, "Failed to read %s: %m", u);
+                                goto fallback;
+                        }
+
+                        r = read_one_line_file(v, &b);
+                        if (r < 0) {
+                                log_debug_errno(r, "Failed to read %s: %m", v);
+                                goto fallback;
+                        }
+
+                        /* Check if the parent device is the same. If not, then the two backing devices are on
+                         * different physical devices, and we don't support that. */
+                        if (!streq(a, b))
+                                goto fallback;
+                }
+
+                found = de;
+        }
+
+        if (!found)
+                goto fallback;
+
+        q = strjoina(p, "/", found->d_name, "/dev");
+
+        r = read_one_line_file(q, &t);
+        if (r == -ENOENT)
+                goto fallback;
+        if (r < 0)
+                return r;
+
+        if (sscanf(t, "%u:%u", &maj, &min) != 2)
+                return -EINVAL;
+
+        if (maj == 0)
+                goto fallback;
+
+        *dev = makedev(maj, min);
+        return 1;
+
+fallback:
+        *dev = dt;
+        return 1;
+}
index c7da6c39bf6426fa25126bd6f5b7420ec1272645..b31dfd1c92fc9ae542425db365c3165eeff0a8d0 100644 (file)
@@ -192,3 +192,6 @@ uint64_t system_tasks_max_scale(uint64_t v, uint64_t max);
 int update_reboot_parameter_and_warn(const char *param);
 
 int version(void);
+
+int get_block_device(const char *path, dev_t *dev);
+int get_block_device_harder(const char *path, dev_t *dev);
index eeef04fb1ce4da627e594ea880867983e4214be1..17af233ef88d0595d9d6fe90ea36dfba1c0e0a08 100644 (file)
@@ -182,7 +182,7 @@ int main(int argc, char *argv[]) {
                 _cleanup_strv_free_ char **files = NULL;
                 char **f;
 
-                r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+                r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
                 if (r < 0) {
                         log_error_errno(r, "Failed to enumerate binfmt.d files: %m");
                         goto finish;
index eb0af2445094c8e9509dce69ad5551110d4d3cf7..2c0124229b31280ce6c880bfb16f1cc03463c884 100644 (file)
@@ -758,6 +758,7 @@ const sd_bus_vtable bus_exec_vtable[] = {
         SD_BUS_PROPERTY("Environment", "as", NULL, offsetof(ExecContext, environment), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("EnvironmentFiles", "a(sb)", property_get_environment_files, 0, SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("PassEnvironment", "as", NULL, offsetof(ExecContext, pass_environment), SD_BUS_VTABLE_PROPERTY_CONST),
+        SD_BUS_PROPERTY("UnsetEnvironment", "as", NULL, offsetof(ExecContext, unset_environment), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("UMask", "u", bus_property_get_mode, offsetof(ExecContext, umask), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitCPU", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
         SD_BUS_PROPERTY("LimitCPUSoft", "t", bus_property_get_rlimit, offsetof(ExecContext, rlimit[RLIMIT_CPU]), SD_BUS_VTABLE_PROPERTY_CONST),
@@ -1816,13 +1817,13 @@ int bus_exec_context_set_transient_property(
                 if (r < 0)
                         return r;
 
-                if (!strv_env_is_valid(l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
-
                 r = unit_full_printf_strv(u, l, &q);
                 if (r < 0)
                         return r;
 
+                if (!strv_env_is_valid(q))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid environment block.");
+
                 if (mode != UNIT_CHECK) {
                         if (strv_length(q) == 0) {
                                 c->environment = strv_free(c->environment);
@@ -1839,7 +1840,7 @@ int bus_exec_context_set_transient_property(
                                 c->environment = e;
 
                                 /* We write just the new settings out to file, with unresolved specifiers */
-                                joined = strv_join_quoted(q);
+                                joined = strv_join_quoted(l);
                                 if (!joined)
                                         return -ENOMEM;
 
@@ -1849,6 +1850,47 @@ int bus_exec_context_set_transient_property(
 
                 return 1;
 
+        } else if (streq(name, "UnsetEnvironment")) {
+
+                _cleanup_strv_free_ char **l = NULL, **q = NULL;
+
+                r = sd_bus_message_read_strv(message, &l);
+                if (r < 0)
+                        return r;
+
+                r = unit_full_printf_strv(u, l, &q);
+                if (r < 0)
+                        return r;
+
+                if (!strv_env_name_or_assignment_is_valid(q))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid UnsetEnvironment= list.");
+
+                if (mode != UNIT_CHECK) {
+                        if (strv_length(q) == 0) {
+                                c->unset_environment = strv_free(c->unset_environment);
+                                unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=");
+                        } else {
+                                _cleanup_free_ char *joined = NULL;
+                                char **e;
+
+                                e = strv_env_merge(2, c->unset_environment, q);
+                                if (!e)
+                                        return -ENOMEM;
+
+                                strv_free(c->unset_environment);
+                                c->unset_environment = e;
+
+                                /* We write just the new settings out to file, with unresolved specifiers */
+                                joined = strv_join_quoted(l);
+                                if (!joined)
+                                        return -ENOMEM;
+
+                                unit_write_drop_in_private_format(u, mode, name, "UnsetEnvironment=%s", joined);
+                        }
+                }
+
+                return 1;
+
         } else if (streq(name, "TimerSlackNSec")) {
 
                 nsec_t n;
@@ -1958,14 +2000,18 @@ int bus_exec_context_set_transient_property(
 
         } else if (streq(name, "PassEnvironment")) {
 
-                _cleanup_strv_free_ char **l = NULL;
+                _cleanup_strv_free_ char **l = NULL, **q = NULL;
 
                 r = sd_bus_message_read_strv(message, &l);
                 if (r < 0)
                         return r;
 
-                if (!strv_env_name_is_valid(l))
-                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment block.");
+                r = unit_full_printf_strv(u, l, &q);
+                if (r < 0)
+                        return r;
+
+                if (!strv_env_name_is_valid(q))
+                        return sd_bus_error_setf(error, SD_BUS_ERROR_INVALID_ARGS, "Invalid PassEnvironment= block.");
 
                 if (mode != UNIT_CHECK) {
                         if (strv_isempty(l)) {
@@ -1974,11 +2020,12 @@ int bus_exec_context_set_transient_property(
                         } else {
                                 _cleanup_free_ char *joined = NULL;
 
-                                r = strv_extend_strv(&c->pass_environment, l, true);
+                                r = strv_extend_strv(&c->pass_environment, q, true);
                                 if (r < 0)
                                         return r;
 
-                                joined = strv_join_quoted(c->pass_environment);
+                                /* We write just the new settings out to file, with unresolved specifiers. */
+                                joined = strv_join_quoted(l);
                                 if (!joined)
                                         return -ENOMEM;
 
index 87186f135bf817f15fcd5205980a94f49aa08dd9..5366ba050ffc7d6e6da54d4955092c144b7729cf 100644 (file)
@@ -766,7 +766,27 @@ static int device_dispatch_io(sd_event_source *source, int fd, uint32_t revents,
                 return 0;
         }
 
-        if (streq(action, "remove"))  {
+        if (streq(action, "change"))  {
+                _cleanup_free_ char *e = NULL;
+                Unit *u;
+
+                r = unit_name_from_path(sysfs, ".device", &e);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to generate unit name from device path: %m");
+
+                u = manager_get_unit(m, e);
+                if (!u) {
+                        log_error("Failed to get unit from sysfs name.");
+                        return 0;
+                }
+
+                r = manager_add_job(m, JOB_RELOAD, u, JOB_REPLACE, NULL, NULL);
+                if (r < 0) {
+                        log_error_errno(r, "Failed to add job to manager : %m");
+                        return 0;
+                }
+
+        } else if (streq(action, "remove"))  {
                 r = swap_process_device_remove(m, dev);
                 if (r < 0)
                         log_error_errno(r, "Failed to process swap device remove event: %m");
index 21c0149e2255ab2a42fdad90c1ced0b276e746cf..9dcc02aaa49aecdc5df4ce8deefda08c3198ee57 100644 (file)
@@ -1673,8 +1673,10 @@ static int build_pass_environment(const ExecContext *c, char ***ret) {
                 x = strjoin(*i, "=", v);
                 if (!x)
                         return -ENOMEM;
+
                 if (!GREEDY_REALLOC(pass_env, n_bufsize, n_env + 2))
                         return -ENOMEM;
+
                 pass_env[n_env++] = x;
                 pass_env[n_env] = NULL;
                 x = NULL;
@@ -3031,6 +3033,19 @@ static int exec_child(
 #endif
         }
 
+        if (!strv_isempty(context->unset_environment)) {
+                char **ee = NULL;
+
+                ee = strv_env_delete(accum_env, 1, context->unset_environment);
+                if (!ee) {
+                        *exit_status = EXIT_MEMORY;
+                        return -ENOMEM;
+                }
+
+                strv_free(accum_env);
+                accum_env = ee;
+        }
+
         final_argv = replace_env_argv(argv, accum_env);
         if (!final_argv) {
                 *exit_status = EXIT_MEMORY;
@@ -3222,6 +3237,7 @@ void exec_context_done(ExecContext *c) {
         c->environment = strv_free(c->environment);
         c->environment_files = strv_free(c->environment_files);
         c->pass_environment = strv_free(c->pass_environment);
+        c->unset_environment = strv_free(c->unset_environment);
 
         for (l = 0; l < ELEMENTSOF(c->rlimit); l++)
                 c->rlimit[l] = mfree(c->rlimit[l]);
@@ -3582,6 +3598,9 @@ void exec_context_dump(ExecContext *c, FILE* f, const char *prefix) {
         STRV_FOREACH(e, c->pass_environment)
                 fprintf(f, "%sPassEnvironment: %s\n", prefix, *e);
 
+        STRV_FOREACH(e, c->unset_environment)
+                fprintf(f, "%sUnsetEnvironment: %s\n", prefix, *e);
+
         fprintf(f, "%sRuntimeDirectoryPreserve: %s\n", prefix, exec_preserve_mode_to_string(c->runtime_directory_preserve_mode));
 
         for (dt = 0; dt < _EXEC_DIRECTORY_MAX; dt++) {
index 8a7ce8449b9bf761f2e537a7548165ea91a4b5ed..f7c20dbcb3b513f44b5eb96db96356ec875c1256 100644 (file)
@@ -133,6 +133,7 @@ struct ExecContext {
         char **environment;
         char **environment_files;
         char **pass_environment;
+        char **unset_environment;
 
         struct rlimit *rlimit[_RLIMIT_MAX];
         char *working_directory, *root_directory, *root_image;
index 94f3d657f6b056880d33ff5c1e6e243c6654313e..94e29397f3dab6483757e314bbaa82c2cff17d87 100644 (file)
@@ -35,6 +35,7 @@ $1.UMask,                        config_parse_mode,                  0,
 $1.Environment,                  config_parse_environ,               0,                             offsetof($1, exec_context.environment)
 $1.EnvironmentFile,              config_parse_unit_env_file,         0,                             offsetof($1, exec_context.environment_files)
 $1.PassEnvironment,              config_parse_pass_environ,          0,                             offsetof($1, exec_context.pass_environment)
+$1.UnsetEnvironment,             config_parse_unset_environ,         0,                             offsetof($1, exec_context.unset_environment)
 $1.DynamicUser,                  config_parse_bool,                  true,                          offsetof($1, exec_context.dynamic_user)
 $1.StandardInput,                config_parse_exec_input,            0,                             offsetof($1, exec_context)
 $1.StandardOutput,               config_parse_exec_output,           0,                             offsetof($1, exec_context)
index 7fa1bafaef71af0800f922a433cb9604759c38d6..66ad92d460593db06b61a38c26b3643b69c3aef9 100644 (file)
@@ -283,6 +283,23 @@ int config_parse_unit_path_strv_printf(
         assert(rvalue);
         assert(u);
 
+        if (isempty(rvalue)) {
+                char **empty;
+
+                /* Empty assignment resets the list. As a special rule
+                 * we actually fill in a real empty array here rather
+                 * than NULL, since some code wants to know if
+                 * something was set at all... */
+                empty = new0(char*, 1);
+                if (!empty)
+                        return log_oom();
+
+                strv_free(*x);
+                *x = empty;
+
+                return 0;
+        }
+
         for (p = rvalue;;) {
                 _cleanup_free_ char *word = NULL, *k = NULL;
 
@@ -2108,16 +2125,17 @@ int config_parse_unit_env_file(const char *unit,
         return 0;
 }
 
-int config_parse_environ(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_environ(
+                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) {
 
         Unit *u = userdata;
         char ***env = data;
@@ -2153,7 +2171,7 @@ int config_parse_environ(const char *unit,
                         r = unit_full_printf(u, word, &k);
                         if (r < 0) {
                                 log_syntax(unit, LOG_ERR, filename, line, r,
-                                           "Failed to resolve specifiers, ignoring: %s", k);
+                                           "Failed to resolve specifiers, ignoring: %s", word);
                                 continue;
                         }
                 } else {
@@ -2170,25 +2188,28 @@ int config_parse_environ(const char *unit,
                 r = strv_env_replace(env, k);
                 if (r < 0)
                         return log_oom();
+
                 k = NULL;
         }
 }
 
-int config_parse_pass_environ(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_pass_environ(
+                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) {
 
         const char *whole_rvalue = rvalue;
-        char*** passenv = data;
         _cleanup_strv_free_ char **n = NULL;
         size_t nlen = 0, nbufsize = 0;
+        char*** passenv = data;
+        Unit *u = userdata;
         int r;
 
         assert(filename);
@@ -2203,7 +2224,7 @@ int config_parse_pass_environ(const char *unit,
         }
 
         for (;;) {
-                _cleanup_free_ char *word = NULL;
+                _cleanup_free_ char *word = NULL, *k = NULL;
 
                 r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
                 if (r == 0)
@@ -2216,17 +2237,30 @@ int config_parse_pass_environ(const char *unit,
                         break;
                 }
 
-                if (!env_name_is_valid(word)) {
-                        log_syntax(unit, LOG_ERR, filename, line, EINVAL,
-                                   "Invalid environment name for %s, ignoring: %s", lvalue, word);
+                if (u) {
+                        r = unit_full_printf(u, word, &k);
+                        if (r < 0) {
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to resolve specifiers, ignoring: %s", word);
+                                continue;
+                        }
+                } else {
+                        k = word;
+                        word = NULL;
+                }
+
+                if (!env_name_is_valid(k)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid environment name for %s, ignoring: %s", lvalue, k);
                         continue;
                 }
 
                 if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
                         return log_oom();
-                n[nlen++] = word;
+
+                n[nlen++] = k;
                 n[nlen] = NULL;
-                word = NULL;
+                k = NULL;
         }
 
         if (n) {
@@ -2238,6 +2272,85 @@ int config_parse_pass_environ(const char *unit,
         return 0;
 }
 
+int config_parse_unset_environ(
+                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) {
+
+        _cleanup_strv_free_ char **n = NULL;
+        const char *whole_rvalue = rvalue;
+        size_t nlen = 0, nbufsize = 0;
+        char*** unsetenv = data;
+        Unit *u = userdata;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+        assert(data);
+
+        if (isempty(rvalue)) {
+                /* Empty assignment resets the list */
+                *unsetenv = strv_free(*unsetenv);
+                return 0;
+        }
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL, *k = NULL;
+
+                r = extract_first_word(&rvalue, &word, NULL, EXTRACT_QUOTES);
+                if (r == 0)
+                        break;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r,
+                                   "Trailing garbage in %s, ignoring: %s", lvalue, whole_rvalue);
+                        break;
+                }
+
+                if (u) {
+                        r = unit_full_printf(u, word, &k);
+                        if (r < 0) {
+                                log_syntax(unit, LOG_ERR, filename, line, r,
+                                           "Failed to resolve specifiers, ignoring: %s", word);
+                                continue;
+                        }
+                } else {
+                        k = word;
+                        word = NULL;
+                }
+
+                if (!env_assignment_is_valid(k) && !env_name_is_valid(k)) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0,
+                                   "Invalid environment name or assignment %s, ignoring: %s", lvalue, k);
+                        continue;
+                }
+
+                if (!GREEDY_REALLOC(n, nbufsize, nlen + 2))
+                        return log_oom();
+
+                n[nlen++] = k;
+                n[nlen] = NULL;
+                k = NULL;
+        }
+
+        if (n) {
+                r = strv_extend_strv(unsetenv, n, true);
+                if (r < 0)
+                        return r;
+        }
+
+        return 0;
+}
+
 int config_parse_ip_tos(const char *unit,
                         const char *filename,
                         unsigned line,
index ec338ccb9a3f65767e85a5bb59a2da6a239eb5dc..49b3b405df3a7a4c6db9ae4c4dd4589c1bdd141b 100644 (file)
@@ -79,6 +79,7 @@ int config_parse_syscall_archs(const char *unit, const char *filename, unsigned
 int config_parse_syscall_errno(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_environ(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_pass_environ(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_unset_environ(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_unit_slice(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_cpu_weight(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_cpu_shares(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 11ac9cf7a0eb9605ef57ab420b5b6d41d23b089f..d1a53a57fd480512d164d91e6b03d56a2b61cf56 100644 (file)
@@ -1679,20 +1679,22 @@ int main(int argc, char *argv[]) {
         log_close();
 
         /* Remember open file descriptors for later deserialization */
-        r = fdset_new_fill(&fds);
-        if (r < 0) {
-                log_emergency_errno(r, "Failed to allocate fd set: %m");
-                error_message = "Failed to allocate fd set";
-                goto finish;
-        } else
-                fdset_cloexec(fds, true);
+        if (arg_action == ACTION_RUN) {
+                r = fdset_new_fill(&fds);
+                if (r < 0) {
+                        log_emergency_errno(r, "Failed to allocate fd set: %m");
+                        error_message = "Failed to allocate fd set";
+                        goto finish;
+                } else
+                        fdset_cloexec(fds, true);
 
-        if (arg_serialization)
-                assert_se(fdset_remove(fds, fileno(arg_serialization)) >= 0);
+                if (arg_serialization)
+                        assert_se(fdset_remove(fds, fileno(arg_serialization)) >= 0);
 
-        if (arg_system)
-                /* Become a session leader if we aren't one yet. */
-                setsid();
+                if (arg_system)
+                        /* Become a session leader if we aren't one yet. */
+                        setsid();
+        }
 
         /* Move out of the way, so that we won't block unmounts */
         assert_se(chdir("/") == 0);
@@ -1762,56 +1764,58 @@ int main(int argc, char *argv[]) {
                           arg_action == ACTION_TEST ? " test" : "", getuid(), t);
         }
 
-        if (arg_system && !skip_setup) {
-                if (arg_show_status > 0)
-                        status_welcome();
+        if (arg_action == ACTION_RUN) {
+                if (arg_system && !skip_setup) {
+                        if (arg_show_status > 0)
+                                status_welcome();
 
-                hostname_setup();
-                machine_id_setup(NULL, arg_machine_id, NULL);
-                loopback_setup();
-                bump_unix_max_dgram_qlen();
+                        hostname_setup();
+                        machine_id_setup(NULL, arg_machine_id, NULL);
+                        loopback_setup();
+                        bump_unix_max_dgram_qlen();
 
-                test_usr();
-        }
+                        test_usr();
+                }
 
-        if (arg_system && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
-                watchdog_set_timeout(&arg_runtime_watchdog);
+                if (arg_system && arg_runtime_watchdog > 0 && arg_runtime_watchdog != USEC_INFINITY)
+                        watchdog_set_timeout(&arg_runtime_watchdog);
 
-        if (arg_timer_slack_nsec != NSEC_INFINITY)
-                if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
-                        log_error_errno(errno, "Failed to adjust timer slack: %m");
+                if (arg_timer_slack_nsec != NSEC_INFINITY)
+                        if (prctl(PR_SET_TIMERSLACK, arg_timer_slack_nsec) < 0)
+                                log_error_errno(errno, "Failed to adjust timer slack: %m");
 
-        if (arg_system && !cap_test_all(arg_capability_bounding_set)) {
-                r = capability_bounding_set_drop_usermode(arg_capability_bounding_set);
-                if (r < 0) {
-                        log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
-                        error_message = "Failed to drop capability bounding set of usermode helpers";
-                        goto finish;
-                }
-                r = capability_bounding_set_drop(arg_capability_bounding_set, true);
-                if (r < 0) {
-                        log_emergency_errno(r, "Failed to drop capability bounding set: %m");
-                        error_message = "Failed to drop capability bounding set";
-                        goto finish;
+                if (arg_system && !cap_test_all(arg_capability_bounding_set)) {
+                        r = capability_bounding_set_drop_usermode(arg_capability_bounding_set);
+                        if (r < 0) {
+                                log_emergency_errno(r, "Failed to drop capability bounding set of usermode helpers: %m");
+                                error_message = "Failed to drop capability bounding set of usermode helpers";
+                                goto finish;
+                        }
+                        r = capability_bounding_set_drop(arg_capability_bounding_set, true);
+                        if (r < 0) {
+                                log_emergency_errno(r, "Failed to drop capability bounding set: %m");
+                                error_message = "Failed to drop capability bounding set";
+                                goto finish;
+                        }
                 }
-        }
 
-        if (arg_syscall_archs) {
-                r = enforce_syscall_archs(arg_syscall_archs);
-                if (r < 0) {
-                        error_message = "Failed to set syscall architectures";
-                        goto finish;
+                if (arg_syscall_archs) {
+                        r = enforce_syscall_archs(arg_syscall_archs);
+                        if (r < 0) {
+                                error_message = "Failed to set syscall architectures";
+                                goto finish;
+                        }
                 }
-        }
 
-        if (!arg_system)
-                /* Become reaper of our children */
-                if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0)
-                        log_warning_errno(errno, "Failed to make us a subreaper: %m");
+                if (!arg_system)
+                        /* Become reaper of our children */
+                        if (prctl(PR_SET_CHILD_SUBREAPER, 1) < 0)
+                                log_warning_errno(errno, "Failed to make us a subreaper: %m");
 
-        if (arg_system)
-                /* Bump up RLIMIT_NOFILE for systemd itself */
-                (void) bump_rlimit_nofile(&saved_rlimit_nofile);
+                if (arg_system)
+                        /* Bump up RLIMIT_NOFILE for systemd itself */
+                        (void) bump_rlimit_nofile(&saved_rlimit_nofile);
+        }
 
         r = manager_new(arg_system ? UNIT_FILE_SYSTEM : UNIT_FILE_USER, arg_action == ACTION_TEST, &m);
         if (r < 0) {
index 701949fd60df580a3c84ce81f476bdd8d53f5cd8..3032a237b17cf7f009e938312444f4c54e3b1abb 100644 (file)
@@ -614,9 +614,23 @@ static int timer_start(Unit *u) {
         if (t->stamp_path) {
                 struct stat st;
 
-                if (stat(t->stamp_path, &st) >= 0)
-                        t->last_trigger.realtime = timespec_load(&st.st_atim);
-                else if (errno == ENOENT)
+                if (stat(t->stamp_path, &st) >= 0) {
+                        usec_t ft;
+
+                        /* Load the file timestamp, but only if it is actually in the past. If it is in the future,
+                         * something is wrong with the system clock. */
+
+                        ft = timespec_load(&st.st_mtim);
+                        if (ft < now(CLOCK_REALTIME))
+                                t->last_trigger.realtime = ft;
+                        else {
+                                char z[FORMAT_TIMESTAMP_MAX];
+
+                                log_unit_warning(u, "Not using persistent file timestamp %s as it is in the future.",
+                                                 format_timestamp(z, sizeof(z), ft));
+                        }
+
+                } else if (errno == ENOENT)
                         /* The timer has never run before,
                          * make sure a stamp file exists.
                          */
index b83f63114125ca36046f27aaa30fd1efbeaed3aa..7e9ea2038816cdd3b71ba6964e86ea95ea5d1862 100644 (file)
@@ -97,7 +97,7 @@ static int mount_points_list_get(MountPoint **head) {
                            "%ms"        /* (11) mount options */
                            "%*[^\n]",   /* some rubbish at the end */
                            &path, &type, &options);
-                if (k != 2) {
+                if (k != 3) {
                         if (k == EOF)
                                 break;
 
@@ -517,22 +517,22 @@ static int loopback_points_list_detach(MountPoint **head, bool *changed) {
 
 static int dm_points_list_detach(MountPoint **head, bool *changed) {
         MountPoint *m, *n;
-        int n_failed = 0, k;
-        struct stat root_st;
+        int n_failed = 0, r;
+        dev_t rootdev;
 
         assert(head);
 
-        k = lstat("/", &root_st);
+        r = get_block_device("/", &rootdev);
+        if (r <= 0)
+                rootdev = 0;
 
         LIST_FOREACH_SAFE(mount_point, m, n, *head) {
-                int r;
 
-                if (k >= 0 &&
-                    major(root_st.st_dev) != 0 &&
-                    root_st.st_dev == m->devnum) {
-                        n_failed++;
-                        continue;
-                }
+                if (major(rootdev) != 0)
+                        if (rootdev == m->devnum) {
+                                n_failed ++;
+                                continue;
+                        }
 
                 log_info("Detaching DM %u:%u.", major(m->devnum), minor(m->devnum));
                 r = delete_dm(m->devnum);
index 2037de6d332e7f51dfc477edcc0c9f17c2a15387..9eda9643f6039f182e73efa774f921186aa15d0d 100644 (file)
@@ -1759,19 +1759,25 @@ int unit_reload(Unit *u) {
 
         unit_add_to_dbus_queue(u);
 
+        if (!UNIT_VTABLE(u)->reload) {
+                /* Unit doesn't have a reload function, but we need to propagate the reload anyway */
+                unit_notify(u, unit_active_state(u), unit_active_state(u), true);
+                return 0;
+        }
+
         return UNIT_VTABLE(u)->reload(u);
 }
 
 bool unit_can_reload(Unit *u) {
         assert(u);
 
-        if (!UNIT_VTABLE(u)->reload)
-                return false;
+        if (UNIT_VTABLE(u)->can_reload)
+                return UNIT_VTABLE(u)->can_reload(u);
 
-        if (!UNIT_VTABLE(u)->can_reload)
+        if (!set_isempty(u->dependencies[UNIT_PROPAGATES_RELOAD_TO]))
                 return true;
 
-        return UNIT_VTABLE(u)->can_reload(u);
+        return UNIT_VTABLE(u)->reload;
 }
 
 static void unit_check_unneeded(Unit *u) {
index 9c7250237340a3814e4e3db23edeef6a19559f85..55de68550d10447e74442d4e42ee05b1231b2b8c 100644 (file)
@@ -58,7 +58,7 @@ static int load_and_print(void) {
         if (r < 0)
                 return r;
 
-        r = conf_files_list_strv(&files, ".conf", NULL, (const char **) dirs);
+        r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char **) dirs);
         if (r < 0)
                 return r;
 
index a6c0b33fbb3e734c89bb5d8131fbbcac04439653..dcbf3ff061069611c7d5ed48654eea2fc6e0ac7e 100644 (file)
@@ -571,136 +571,6 @@ static int enumerate_partitions(dev_t devnum) {
         return r;
 }
 
-static int get_block_device(const char *path, dev_t *dev) {
-        struct stat st;
-        struct statfs sfs;
-
-        assert(path);
-        assert(dev);
-
-        /* Get's the block device directly backing a file system. If
-         * the block device is encrypted, returns the device mapper
-         * block device. */
-
-        if (lstat(path, &st))
-                return -errno;
-
-        if (major(st.st_dev) != 0) {
-                *dev = st.st_dev;
-                return 1;
-        }
-
-        if (statfs(path, &sfs) < 0)
-                return -errno;
-
-        if (F_TYPE_EQUAL(sfs.f_type, BTRFS_SUPER_MAGIC))
-                return btrfs_get_block_device(path, dev);
-
-        return 0;
-}
-
-static int get_block_device_harder(const char *path, dev_t *dev) {
-        _cleanup_closedir_ DIR *d = NULL;
-        _cleanup_free_ char *p = NULL, *t = NULL;
-        struct dirent *de, *found = NULL;
-        const char *q;
-        unsigned maj, min;
-        dev_t dt;
-        int r;
-
-        assert(path);
-        assert(dev);
-
-        /* Gets the backing block device for a file system, and
-         * handles LUKS encrypted file systems, looking for its
-         * immediate parent, if there is one. */
-
-        r = get_block_device(path, &dt);
-        if (r <= 0)
-                return r;
-
-        if (asprintf(&p, "/sys/dev/block/%u:%u/slaves", major(dt), minor(dt)) < 0)
-                return -ENOMEM;
-
-        d = opendir(p);
-        if (!d) {
-                if (errno == ENOENT)
-                        goto fallback;
-
-                return -errno;
-        }
-
-        FOREACH_DIRENT_ALL(de, d, return -errno) {
-
-                if (dot_or_dot_dot(de->d_name))
-                        continue;
-
-                if (!IN_SET(de->d_type, DT_LNK, DT_UNKNOWN))
-                        continue;
-
-                if (found) {
-                        _cleanup_free_ char *u = NULL, *v = NULL, *a = NULL, *b = NULL;
-
-                        /* We found a device backed by multiple other devices. We don't really support automatic
-                         * discovery on such setups, with the exception of dm-verity partitions. In this case there are
-                         * two backing devices: the data partition and the hash partition. We are fine with such
-                         * setups, however, only if both partitions are on the same physical device. Hence, let's
-                         * verify this. */
-
-                        u = strjoin(p, "/", de->d_name, "/../dev");
-                        if (!u)
-                                return -ENOMEM;
-
-                        v = strjoin(p, "/", found->d_name, "/../dev");
-                        if (!v)
-                                return -ENOMEM;
-
-                        r = read_one_line_file(u, &a);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to read %s: %m", u);
-                                goto fallback;
-                        }
-
-                        r = read_one_line_file(v, &b);
-                        if (r < 0) {
-                                log_debug_errno(r, "Failed to read %s: %m", v);
-                                goto fallback;
-                        }
-
-                        /* Check if the parent device is the same. If not, then the two backing devices are on
-                         * different physical devices, and we don't support that. */
-                        if (!streq(a, b))
-                                goto fallback;
-                }
-
-                found = de;
-        }
-
-        if (!found)
-                goto fallback;
-
-        q = strjoina(p, "/", found->d_name, "/dev");
-
-        r = read_one_line_file(q, &t);
-        if (r == -ENOENT)
-                goto fallback;
-        if (r < 0)
-                return r;
-
-        if (sscanf(t, "%u:%u", &maj, &min) != 2)
-                return -EINVAL;
-
-        if (maj == 0)
-                goto fallback;
-
-        *dev = makedev(maj, min);
-        return 1;
-
-fallback:
-        *dev = dt;
-        return 1;
-}
-
 static int parse_proc_cmdline_item(const char *key, const char *value, void *data) {
         int r;
 
index ead4e1770b953727349578f97b3b7a291ff9f6dc..c964a28bce588d5cdcc3d542f3143bc06bb5493f 100644 (file)
@@ -653,7 +653,7 @@ static int hwdb_update(int argc, char *argv[], void *userdata) {
 
         trie->nodes_count++;
 
-        r = conf_files_list_strv(&files, ".hwdb", arg_root, conf_file_dirs);
+        r = conf_files_list_strv(&files, ".hwdb", arg_root, 0, conf_file_dirs);
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate hwdb files: %m");
 
index 886f6efd8bd2da917f24b75c36c6843accdfd56a..f42be0adf945a5dd732a96d0b1e6813459d6b253 100644 (file)
@@ -479,7 +479,7 @@ int catalog_update(const char* database, const char* root, const char* const* di
                 goto finish;
         }
 
-        r = conf_files_list_strv(&files, ".catalog", root, dirs);
+        r = conf_files_list_strv(&files, ".catalog", root, 0, dirs);
         if (r < 0) {
                 log_error_errno(r, "Failed to get catalog files: %m");
                 goto finish;
index 3a181e7a28211eb924cd77a10fdb8d8db1f8f822..9a3bc9dd98917b2b7fe809b272d65be980328cc8 100644 (file)
@@ -27,6 +27,7 @@
 #include "bus-error.h"
 #include "bus-kernel.h"
 #include "bus-match.h"
+#include "def.h"
 #include "hashmap.h"
 #include "list.h"
 #include "prioq.h"
@@ -316,8 +317,13 @@ struct sd_bus {
         LIST_HEAD(sd_bus_track, tracks);
 };
 
+/* For method calls we time-out at 25s, like in the D-Bus reference implementation */
 #define BUS_DEFAULT_TIMEOUT ((usec_t) (25 * USEC_PER_SEC))
 
+/* For the authentication phase we grant 90s, to provide extra room during boot, when RNGs and such are not filled up
+ * with enough entropy yet and might delay the boot */
+#define BUS_AUTH_TIMEOUT ((usec_t) DEFAULT_TIMEOUT_USEC)
+
 #define BUS_WQUEUE_MAX (192*1024)
 #define BUS_RQUEUE_MAX (192*1024)
 
index 982af68c016a00ddde284983d468c71f4c42b41c..6e4bd541bffcc791bd4354a433500952c77d9adf 100644 (file)
@@ -660,7 +660,7 @@ int bus_socket_start_auth(sd_bus *b) {
         bus_get_peercred(b);
 
         b->state = BUS_AUTHENTICATING;
-        b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_DEFAULT_TIMEOUT;
+        b->auth_timeout = now(CLOCK_MONOTONIC) + BUS_AUTH_TIMEOUT;
 
         if (sd_is_socket(b->input_fd, AF_UNIX, 0, 0) <= 0)
                 b->hello_flags &= ~KDBUS_HELLO_ACCEPT_FD;
index 615998a6f60d679a04e2c87b0716e3e18ed9e801..6efebcd94fdecfeec784f98adf97ce5e939e4be8 100644 (file)
@@ -264,7 +264,7 @@ int main(int argc, char *argv[]) {
                                 r = k;
                 }
 
-                k = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+                k = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
                 if (k < 0) {
                         log_error_errno(k, "Failed to enumerate modules-load.d files: %m");
                         if (r == 0)
index 1cf72bf6d29d4418a8857315c4963cdcc786e084..0e1a7d1335e9902d6411dadcff13eade68c6e6de 100644 (file)
@@ -766,7 +766,7 @@ int netdev_load(Manager *manager) {
         while ((netdev = hashmap_first(manager->netdevs)))
                 netdev_unref(netdev);
 
-        r = conf_files_list_strv(&files, ".netdev", NULL, network_dirs);
+        r = conf_files_list_strv(&files, ".netdev", NULL, 0, network_dirs);
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate netdev files: %m");
 
index a873e55d4c2740f4adfdb816aade5e19b00bb00d..3b52a8a5b96f97d19d03f3f1e7bbcb855181cd4c 100644 (file)
@@ -322,7 +322,7 @@ int network_load(Manager *manager) {
         while ((network = manager->networks))
                 network_free(network);
 
-        r = conf_files_list_strv(&files, ".network", NULL, network_dirs);
+        r = conf_files_list_strv(&files, ".network", NULL, 0, network_dirs);
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate network files: %m");
 
index e5fdf63162f25951f39ac2d123d80e1429840f24..b61b347ee7c514fec1d92e1eaf6a325864935549 100644 (file)
@@ -29,6 +29,7 @@ Exec.WorkingDirectory,        config_parse_path,          0, offsetof(Settings,
 Exec.PivotRoot,               config_parse_pivot_root,    0, 0
 Exec.PrivateUsers,            config_parse_private_users, 0, 0
 Exec.NotifyReady,             config_parse_bool,          0, offsetof(Settings, notify_ready)
+Exec.SystemCallFilter,        config_parse_syscall_filter,0, 0,
 Files.ReadOnly,               config_parse_tristate,      0, offsetof(Settings, read_only)
 Files.Volatile,               config_parse_volatile_mode, 0, offsetof(Settings, volatile_mode)
 Files.Bind,                   config_parse_bind,          0, 0
index 72ecc51b16bdc936055effb5b26e4fabeac2b713..db3d098e7f86169cd6f68f64e5f4faa7afdc5276 100644 (file)
 #include "seccomp-util.h"
 #endif
 #include "string-util.h"
+#include "strv.h"
 
 #ifdef HAVE_SECCOMP
 
 static int seccomp_add_default_syscall_filter(
                 scmp_filter_ctx ctx,
                 uint32_t arch,
-                uint64_t cap_list_retain) {
+                uint64_t cap_list_retain,
+                char **syscall_whitelist,
+                char **syscall_blacklist) {
 
         static const struct {
                 uint64_t capability;
-                int syscall_num;
-        } blacklist[] = {
-                { 0,              SCMP_SYS(_sysctl)             }, /* obsolete syscall */
-                { 0,              SCMP_SYS(add_key)             }, /* keyring is not namespaced */
-                { 0,              SCMP_SYS(afs_syscall)         }, /* obsolete syscall */
-                { 0,              SCMP_SYS(bdflush)             },
-#ifdef __NR_bpf
-                { 0,              SCMP_SYS(bpf)                 },
-#endif
-                { 0,              SCMP_SYS(break)               }, /* obsolete syscall */
-                { 0,              SCMP_SYS(create_module)       }, /* obsolete syscall */
-                { 0,              SCMP_SYS(ftime)               }, /* obsolete syscall */
-                { 0,              SCMP_SYS(get_kernel_syms)     }, /* obsolete syscall */
-                { 0,              SCMP_SYS(getpmsg)             }, /* obsolete syscall */
-                { 0,              SCMP_SYS(gtty)                }, /* obsolete syscall */
-#ifdef __NR_kexec_file_load
-                { 0,              SCMP_SYS(kexec_file_load)     },
-#endif
-                { 0,              SCMP_SYS(kexec_load)          },
-                { 0,              SCMP_SYS(keyctl)              }, /* keyring is not namespaced */
-                { 0,              SCMP_SYS(lock)                }, /* obsolete syscall */
-                { 0,              SCMP_SYS(lookup_dcookie)      },
-                { 0,              SCMP_SYS(mpx)                 }, /* obsolete syscall */
-                { 0,              SCMP_SYS(nfsservctl)          }, /* obsolete syscall */
-                { 0,              SCMP_SYS(open_by_handle_at)   },
-                { 0,              SCMP_SYS(perf_event_open)     },
-                { 0,              SCMP_SYS(prof)                }, /* obsolete syscall */
-                { 0,              SCMP_SYS(profil)              }, /* obsolete syscall */
-                { 0,              SCMP_SYS(putpmsg)             }, /* obsolete syscall */
-                { 0,              SCMP_SYS(query_module)        }, /* obsolete syscall */
-                { 0,              SCMP_SYS(quotactl)            },
-                { 0,              SCMP_SYS(request_key)         }, /* keyring is not namespaced */
-                { 0,              SCMP_SYS(security)            }, /* obsolete syscall */
-                { 0,              SCMP_SYS(sgetmask)            }, /* obsolete syscall */
-                { 0,              SCMP_SYS(ssetmask)            }, /* obsolete syscall */
-                { 0,              SCMP_SYS(stty)                }, /* obsolete syscall */
-                { 0,              SCMP_SYS(swapoff)             },
-                { 0,              SCMP_SYS(swapon)              },
-                { 0,              SCMP_SYS(sysfs)               }, /* obsolete syscall */
-                { 0,              SCMP_SYS(tuxcall)             }, /* obsolete syscall */
-                { 0,              SCMP_SYS(ulimit)              }, /* obsolete syscall */
-                { 0,              SCMP_SYS(uselib)              }, /* obsolete syscall */
-                { 0,              SCMP_SYS(ustat)               }, /* obsolete syscall */
-                { 0,              SCMP_SYS(vserver)             }, /* obsolete syscall */
-                { CAP_SYSLOG,     SCMP_SYS(syslog)              },
-                { CAP_SYS_MODULE, SCMP_SYS(delete_module)       },
-                { CAP_SYS_MODULE, SCMP_SYS(finit_module)        },
-                { CAP_SYS_MODULE, SCMP_SYS(init_module)         },
-                { CAP_SYS_PACCT,  SCMP_SYS(acct)                },
-                { CAP_SYS_PTRACE, SCMP_SYS(process_vm_readv)    },
-                { CAP_SYS_PTRACE, SCMP_SYS(process_vm_writev)   },
-                { CAP_SYS_PTRACE, SCMP_SYS(ptrace)              },
-                { CAP_SYS_RAWIO,  SCMP_SYS(ioperm)              },
-                { CAP_SYS_RAWIO,  SCMP_SYS(iopl)                },
-                { CAP_SYS_RAWIO,  SCMP_SYS(pciconfig_iobase)    },
-                { CAP_SYS_RAWIO,  SCMP_SYS(pciconfig_read)      },
-                { CAP_SYS_RAWIO,  SCMP_SYS(pciconfig_write)     },
-#ifdef __NR_s390_pci_mmio_read
-                { CAP_SYS_RAWIO,  SCMP_SYS(s390_pci_mmio_read)  },
-#endif
-#ifdef __NR_s390_pci_mmio_write
-                { CAP_SYS_RAWIO,  SCMP_SYS(s390_pci_mmio_write) },
-#endif
-                { CAP_SYS_TIME,   SCMP_SYS(adjtimex)            },
-                { CAP_SYS_TIME,   SCMP_SYS(clock_adjtime)       },
-                { CAP_SYS_TIME,   SCMP_SYS(clock_settime)       },
-                { CAP_SYS_TIME,   SCMP_SYS(settimeofday)        },
-                { CAP_SYS_TIME,   SCMP_SYS(stime)               },
+                const char* name;
+        } whitelist[] = {
+                /* Let's use set names where we can */
+                { 0,                  "@basic-io"              },
+                { 0,                  "@credentials"           },
+                { 0,                  "@default"               },
+                { 0,                  "@file-system"           },
+                { 0,                  "@io-event"              },
+                { 0,                  "@ipc"                   },
+                { 0,                  "@mount"                 },
+                { 0,                  "@network-io"            },
+                { 0,                  "@process"               },
+                { 0,                  "@resources"             },
+                { 0,                  "@setuid"                },
+                { 0,                  "@signal"                },
+                { 0,                  "@timer"                 },
+
+                /* The following four are sets we optionally enable, in case the caps have been configured for it */
+                { CAP_SYS_TIME,       "@clock"                 },
+                { CAP_SYS_MODULE,     "@module"                },
+                { CAP_SYS_RAWIO,      "@raw-io"                },
+                { CAP_IPC_LOCK,       "@memlock"               },
+
+                /* Plus a good set of additional syscalls which are not part of any of the groups above */
+                { 0,                  "brk"                    },
+                { 0,                  "capset"                 },
+                { 0,                  "chown"                  },
+                { 0,                  "chown32"                },
+                { 0,                  "copy_file_range"        },
+                { 0,                  "fadvise64"              },
+                { 0,                  "fadvise64_64"           },
+                { 0,                  "fchown"                 },
+                { 0,                  "fchown32"               },
+                { 0,                  "fchownat"               },
+                { 0,                  "fdatasync"              },
+                { 0,                  "flock"                  },
+                { 0,                  "fsync"                  },
+                { 0,                  "get_mempolicy"          },
+                { 0,                  "getcpu"                 },
+                { 0,                  "getpriority"            },
+                { 0,                  "getrandom"              },
+                { 0,                  "io_cancel"              },
+                { 0,                  "io_destroy"             },
+                { 0,                  "io_getevents"           },
+                { 0,                  "io_setup"               },
+                { 0,                  "io_submit"              },
+                { 0,                  "ioctl"                  },
+                { 0,                  "ioprio_get"             },
+                { 0,                  "kcmp"                   },
+                { 0,                  "lchown"                 },
+                { 0,                  "lchown32"               },
+                { 0,                  "madvise"                },
+                { 0,                  "mincore"                },
+                { 0,                  "mprotect"               },
+                { 0,                  "mremap"                 },
+                { 0,                  "msync"                  },
+                { 0,                  "name_to_handle_at"      },
+                { 0,                  "oldolduname"            },
+                { 0,                  "olduname"               },
+                { 0,                  "personality"            },
+                { 0,                  "preadv2"                },
+                { 0,                  "pwritev2"               },
+                { 0,                  "readahead"              },
+                { 0,                  "readdir"                },
+                { 0,                  "remap_file_pages"       },
+                { 0,                  "sched_get_priority_max" },
+                { 0,                  "sched_get_priority_min" },
+                { 0,                  "sched_getaffinity"      },
+                { 0,                  "sched_getattr"          },
+                { 0,                  "sched_getparam"         },
+                { 0,                  "sched_getscheduler"     },
+                { 0,                  "sched_rr_get_interval"  },
+                { 0,                  "sched_yield"            },
+                { 0,                  "seccomp"                },
+                { 0,                  "sendfile"               },
+                { 0,                  "sendfile64"             },
+                { 0,                  "setdomainname"          },
+                { 0,                  "setfsgid"               },
+                { 0,                  "setfsgid32"             },
+                { 0,                  "setfsuid"               },
+                { 0,                  "setfsuid32"             },
+                { 0,                  "sethostname"            },
+                { 0,                  "setpgid"                },
+                { 0,                  "setsid"                 },
+                { 0,                  "splice"                 },
+                { 0,                  "sync"                   },
+                { 0,                  "sync_file_range"        },
+                { 0,                  "syncfs"                 },
+                { 0,                  "sysinfo"                },
+                { 0,                  "tee"                    },
+                { 0,                  "ugetrlimit"             },
+                { 0,                  "umask"                  },
+                { 0,                  "uname"                  },
+                { 0,                  "userfaultfd"            },
+                { 0,                  "vmsplice"               },
+
+                /* The following individual syscalls are added depending on specified caps */
+                { CAP_SYS_PACCT,      "acct"                   },
+                { CAP_SYS_PTRACE,     "process_vm_readv"       },
+                { CAP_SYS_PTRACE,     "process_vm_writev"      },
+                { CAP_SYS_PTRACE,     "ptrace"                 },
+                { CAP_SYS_BOOT,       "reboot"                 },
+                { CAP_SYSLOG,         "syslog"                 },
+                { CAP_SYS_TTY_CONFIG, "vhangup"                },
+
+                /*
+                 * The following syscalls and groups are knowingly excluded:
+                 *
+                 * @cpu-emulation
+                 * @keyring           (NB: keyring is not namespaced!)
+                 * @obsolete
+                 * @swap
+                 *
+                 * bpf                (NB: bpffs is not namespaced!)
+                 * fanotify_init
+                 * fanotify_mark
+                 * kexec_file_load
+                 * kexec_load
+                 * lookup_dcookie
+                 * nfsservctl
+                 * open_by_handle_at
+                 * perf_event_open
+                 * pkey_alloc
+                 * pkey_free
+                 * pkey_mprotect
+                 * quotactl
+                 */
         };
-        unsigned i;
+
         int r, c = 0;
+        size_t i;
+        char **p;
 
-        for (i = 0; i < ELEMENTSOF(blacklist); i++) {
-                if (blacklist[i].capability != 0 && (cap_list_retain & (1ULL << blacklist[i].capability)))
+        for (i = 0; i < ELEMENTSOF(whitelist); i++) {
+                if (whitelist[i].capability != 0 && (cap_list_retain & (1ULL << whitelist[i].capability)) == 0)
                         continue;
 
-                r = seccomp_rule_add_exact(ctx, SCMP_ACT_ERRNO(EPERM), blacklist[i].syscall_num, 0);
-                if (r < 0) {
+                r = seccomp_add_syscall_filter_item(ctx, whitelist[i].name, SCMP_ACT_ALLOW, syscall_blacklist);
+                if (r < 0)
                         /* If the system call is not known on this architecture, then that's fine, let's ignore it */
-                        _cleanup_free_ char *n = NULL;
+                        log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", whitelist[i].name, seccomp_arch_to_string(arch));
+                else
+                        c++;
+        }
 
-                        n = seccomp_syscall_resolve_num_arch(arch, blacklist[i].syscall_num);
-                        log_debug_errno(r, "Failed to add rule for system call %s, ignoring: %m", strna(n));
-                } else
+        STRV_FOREACH(p, syscall_whitelist) {
+                r = seccomp_add_syscall_filter_item(ctx, *p, SCMP_ACT_ALLOW, syscall_blacklist);
+                if (r < 0)
+                        log_debug_errno(r, "Failed to add rule for system call %s on %s, ignoring: %m", *p, seccomp_arch_to_string(arch));
+                else
                         c++;
         }
 
         return c;
 }
 
-int setup_seccomp(uint64_t cap_list_retain) {
+int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) {
         uint32_t arch;
         int r;
 
         if (!is_seccomp_available()) {
-                log_debug("SECCOMP features not detected in the kernel, disabling SECCOMP audit filter");
+                log_debug("SECCOMP features not detected in the kernel, disabling SECCOMP filterering");
                 return 0;
         }
 
         SECCOMP_FOREACH_LOCAL_ARCH(arch) {
                 _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
-                int n;
 
-                log_debug("Operating on architecture: %s", seccomp_arch_to_string(arch));
+                log_debug("Applying whitelist on architecture: %s", seccomp_arch_to_string(arch));
 
-                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ERRNO(EPERM));
                 if (r < 0)
                         return log_error_errno(r, "Failed to allocate seccomp object: %m");
 
-                n = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain);
-                if (n < 0)
-                        return n;
+                r = seccomp_add_default_syscall_filter(seccomp, arch, cap_list_retain, syscall_whitelist, syscall_blacklist);
+                if (r < 0)
+                        return r;
+
+                r = seccomp_load(seccomp);
+                if (IN_SET(r, -EPERM, -EACCES))
+                        return log_error_errno(r, "Failed to install seccomp filter: %m");
+                if (r < 0)
+                        log_debug_errno(r, "Failed to install filter set for architecture %s, skipping: %m", seccomp_arch_to_string(arch));
+        }
+
+        SECCOMP_FOREACH_LOCAL_ARCH(arch) {
+                _cleanup_(seccomp_releasep) scmp_filter_ctx seccomp = NULL;
+
+                log_debug("Applying NETLINK_AUDIT mask on architecture: %s", seccomp_arch_to_string(arch));
+
+                r = seccomp_init_for_arch(&seccomp, arch, SCMP_ACT_ALLOW);
+                if (r < 0)
+                        return log_error_errno(r, "Failed to allocate seccomp object: %m");
 
                 /*
                   Audit is broken in containers, much of the userspace audit hookup will fail if running inside a
@@ -171,13 +255,10 @@ int setup_seccomp(uint64_t cap_list_retain) {
                                 2,
                                 SCMP_A0(SCMP_CMP_EQ, AF_NETLINK),
                                 SCMP_A2(SCMP_CMP_EQ, NETLINK_AUDIT));
-                if (r < 0)
+                if (r < 0) {
                         log_debug_errno(r, "Failed to add audit seccomp rule, ignoring: %m");
-                else
-                        n++;
-
-                if (n <= 0) /* no rule added? then skip this architecture */
                         continue;
+                }
 
                 r = seccomp_load(seccomp);
                 if (IN_SET(r, -EPERM, -EACCES))
@@ -191,7 +272,7 @@ int setup_seccomp(uint64_t cap_list_retain) {
 
 #else
 
-int setup_seccomp(uint64_t cap_list_retain) {
+int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist) {
         return 0;
 }
 
index 5bde16faf978429a9a19f32be542bbfe65689de9..5cf5ad1e141adf082dce65115205dbad690dcba7 100644 (file)
@@ -21,4 +21,4 @@
 
 #include <sys/types.h>
 
-int setup_seccomp(uint64_t cap_list_retain);
+int setup_seccomp(uint64_t cap_list_retain, char **syscall_whitelist, char **syscall_blacklist);
index 5217d10665d7058c321a2de09d1db8c7d41531af..c02c1ea697d70c985fa904c99a60081d8335dda8 100644 (file)
@@ -93,6 +93,8 @@ Settings* settings_free(Settings *s) {
         free(s->pivot_root_new);
         free(s->pivot_root_old);
         free(s->working_directory);
+        strv_free(s->syscall_whitelist);
+        strv_free(s->syscall_blacklist);
 
         strv_free(s->network_interfaces);
         strv_free(s->network_macvlan);
@@ -568,3 +570,51 @@ int config_parse_private_users(
 
         return 0;
 }
+
+int config_parse_syscall_filter(
+                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) {
+
+        Settings *settings = data;
+        bool negative;
+        const char *items;
+        int r;
+
+        assert(filename);
+        assert(lvalue);
+        assert(rvalue);
+
+        negative = rvalue[0] == '~';
+        items = negative ? rvalue + 1 : rvalue;
+
+        for (;;) {
+                _cleanup_free_ char *word = NULL;
+
+                r = extract_first_word(&items, &word, NULL, 0);
+                if (r == 0)
+                        break;
+                if (r == -ENOMEM)
+                        return log_oom();
+                if (r < 0) {
+                        log_syntax(unit, LOG_ERR, filename, line, r, "Failed to parse SystemCallFilter= parameter %s, ignoring: %m", rvalue);
+                        return 0;
+                }
+
+                if (negative)
+                        r = strv_extend(&settings->syscall_blacklist, word);
+                else
+                        r = strv_extend(&settings->syscall_whitelist, word);
+                if (r < 0)
+                        return log_oom();
+        }
+
+        return 0;
+}
index 021403258ff674b20016e93d19b00959e0d45cba..75d68ce4cfb1c2e36f215191a67ddea098cdeea8 100644 (file)
@@ -58,7 +58,8 @@ typedef enum SettingsMask {
         SETTING_USERNS            = 1 << 13,
         SETTING_NOTIFY_READY      = 1 << 14,
         SETTING_PIVOT_ROOT        = 1 << 15,
-        _SETTINGS_MASK_ALL        = (1 << 16) -1
+        SETTING_SYSCALL_FILTER    = 1 << 16,
+        _SETTINGS_MASK_ALL        = (1 << 17) -1
 } SettingsMask;
 
 typedef struct Settings {
@@ -78,6 +79,8 @@ typedef struct Settings {
         UserNamespaceMode userns_mode;
         uid_t uid_shift, uid_range;
         bool notify_ready;
+        char **syscall_whitelist;
+        char **syscall_blacklist;
 
         /* [Image] */
         int read_only;
@@ -121,3 +124,4 @@ int config_parse_network_zone(const char *unit, const char *filename, unsigned l
 int config_parse_boot(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_pid2(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_private_users(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_syscall_filter(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 24a3da68ca3cb582028e2dcebe7a3c07f7eab91e..cf804ed1b356b9840cca4d457c12b438903be427 100644 (file)
@@ -208,6 +208,8 @@ static unsigned long arg_clone_ns_flags = CLONE_NEWIPC|CLONE_NEWPID|CLONE_NEWUTS
 static MountSettingsMask arg_mount_settings = MOUNT_APPLY_APIVFS_RO;
 static void *arg_root_hash = NULL;
 static size_t arg_root_hash_size = 0;
+static char **arg_syscall_whitelist = NULL;
+static char **arg_syscall_blacklist = NULL;
 
 static void help(void) {
         printf("%s [OPTIONS...] [PATH] [ARGUMENTS...]\n\n"
@@ -267,6 +269,8 @@ static void help(void) {
                "     --capability=CAP       In addition to the default, retain specified\n"
                "                            capability\n"
                "     --drop-capability=CAP  Drop the specified capability from the default set\n"
+               "     --system-call-filter=LIST|~LIST\n"
+               "                            Permit/prohibit specific system calls\n"
                "     --kill-signal=SIGNAL   Select signal to use for shutting down PID 1\n"
                "     --link-journal=MODE    Link up guest journal, one of no, auto, guest, \n"
                "                            host, try-guest, try-host\n"
@@ -431,6 +435,7 @@ static int parse_argv(int argc, char *argv[]) {
                 ARG_PRIVATE_USERS_CHOWN,
                 ARG_NOTIFY_READY,
                 ARG_ROOT_HASH,
+                ARG_SYSTEM_CALL_FILTER,
         };
 
         static const struct option options[] = {
@@ -482,6 +487,7 @@ static int parse_argv(int argc, char *argv[]) {
                 { "pivot-root",            required_argument, NULL, ARG_PIVOT_ROOT          },
                 { "notify-ready",          required_argument, NULL, ARG_NOTIFY_READY        },
                 { "root-hash",             required_argument, NULL, ARG_ROOT_HASH           },
+                { "system-call-filter",    required_argument, NULL, ARG_SYSTEM_CALL_FILTER  },
                 {}
         };
 
@@ -1051,6 +1057,36 @@ static int parse_argv(int argc, char *argv[]) {
                         break;
                 }
 
+                case ARG_SYSTEM_CALL_FILTER: {
+                        bool negative;
+                        const char *items;
+
+                        negative = optarg[0] == '~';
+                        items = negative ? optarg + 1 : optarg;
+
+                        for (;;) {
+                                _cleanup_free_ char *word = NULL;
+
+                                r = extract_first_word(&items, &word, NULL, 0);
+                                if (r == 0)
+                                        break;
+                                if (r == -ENOMEM)
+                                        return log_oom();
+                                if (r < 0)
+                                        return log_error_errno(r, "Failed to parse system call filter: %m");
+
+                                if (negative)
+                                        r = strv_extend(&arg_syscall_blacklist, word);
+                                else
+                                        r = strv_extend(&arg_syscall_whitelist, word);
+                                if (r < 0)
+                                        return log_oom();
+                        }
+
+                        arg_settings_mask |= SETTING_SYSCALL_FILTER;
+                        break;
+                }
+
                 case '?':
                         return -EINVAL;
 
@@ -2606,7 +2642,7 @@ static int outer_child(
         if (r < 0)
                 return r;
 
-        r = setup_seccomp(arg_caps_retain);
+        r = setup_seccomp(arg_caps_retain, arg_syscall_whitelist, arg_syscall_blacklist);
         if (r < 0)
                 return r;
 
@@ -3111,6 +3147,21 @@ static int load_settings(void) {
         if ((arg_settings_mask & SETTING_NOTIFY_READY) == 0)
                 arg_notify_ready = settings->notify_ready;
 
+        if ((arg_settings_mask & SETTING_SYSCALL_FILTER) == 0) {
+
+                if (!arg_settings_trusted && !strv_isempty(arg_syscall_whitelist))
+                        log_warning("Ignoring SystemCallFilter= settings, file %s is not trusted.", p);
+                else {
+                        strv_free(arg_syscall_whitelist);
+                        strv_free(arg_syscall_blacklist);
+
+                        arg_syscall_whitelist = settings->syscall_whitelist;
+                        arg_syscall_blacklist = settings->syscall_blacklist;
+
+                        settings->syscall_whitelist = settings->syscall_blacklist = NULL;
+                }
+        }
+
         return 0;
 }
 
index ea90953abbf3ec956dda1f55a74a6d96ea820999..6e468853a280914c80d2fd8d9d9b4c7cd07b529a 100644 (file)
@@ -435,7 +435,7 @@ enum nss_status _nss_mymachines_getpwnam_r(
         if (!machine_name_is_valid(machine))
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
                 /* Make sure we can't deadlock if we are invoked by dbus-daemon. This way, it won't be able to resolve
                  * these UIDs, but that should be unproblematic as containers should never be able to connect to a bus
                  * running on the host. */
@@ -519,7 +519,7 @@ enum nss_status _nss_mymachines_getpwuid_r(
         if (uid < HOST_UID_LIMIT)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
                 goto not_found;
 
         r = sd_bus_open_system(&bus);
@@ -613,7 +613,7 @@ enum nss_status _nss_mymachines_getgrnam_r(
         if (!machine_name_is_valid(machine))
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
                 goto not_found;
 
         r = sd_bus_open_system(&bus);
@@ -691,7 +691,7 @@ enum nss_status _nss_mymachines_getgrgid_r(
         if (gid < HOST_GID_LIMIT)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0)
                 goto not_found;
 
         r = sd_bus_open_system(&bus);
index f404755dac17cede238faf3cda6354c10f3a33fb..dcb32e1e2babc5f3a7f8bc9d1fe0a5d25993579e 100644 (file)
@@ -129,22 +129,24 @@ enum nss_status _nss_systemd_getpwnam_r(
                 goto not_found;
 
         /* Synthesize entries for the root and nobody users, in case they are missing in /etc/passwd */
-        if (streq(name, root_passwd.pw_name)) {
-                *pwd = root_passwd;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
-        }
-        if (streq(name, nobody_passwd.pw_name)) {
-                *pwd = nobody_passwd;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+                if (streq(name, root_passwd.pw_name)) {
+                        *pwd = root_passwd;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
+                if (streq(name, nobody_passwd.pw_name)) {
+                        *pwd = nobody_passwd;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
         }
 
         /* Make sure that we don't go in circles when allocating a dynamic UID by checking our own database */
-        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) {
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) {
 
                 /* Access the dynamic UID allocation directly if we are called from dbus-daemon, see above. */
                 r = direct_lookup_name(name, (uid_t*) &translated);
@@ -231,24 +233,26 @@ enum nss_status _nss_systemd_getpwuid_r(
                 goto not_found;
 
         /* Synthesize data for the root user and for nobody in case they are missing from /etc/passwd */
-        if (uid == root_passwd.pw_uid) {
-                *pwd = root_passwd;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
-        }
-        if (uid == nobody_passwd.pw_uid) {
-                *pwd = nobody_passwd;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+                if (uid == root_passwd.pw_uid) {
+                        *pwd = root_passwd;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
+                if (uid == nobody_passwd.pw_uid) {
+                        *pwd = nobody_passwd;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
         }
 
         if (uid <= SYSTEM_UID_MAX)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) {
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) {
 
                 r = direct_lookup_uid(uid, &direct);
                 if (r == -ENOENT)
@@ -331,21 +335,23 @@ enum nss_status _nss_systemd_getgrnam_r(
                 goto not_found;
 
         /* Synthesize records for root and nobody, in case they are missing form /etc/group */
-        if (streq(name, root_group.gr_name)) {
-                *gr = root_group;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
-        }
-        if (streq(name, nobody_group.gr_name)) {
-                *gr = nobody_group;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+                if (streq(name, root_group.gr_name)) {
+                        *gr = root_group;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
+                if (streq(name, nobody_group.gr_name)) {
+                        *gr = nobody_group;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
         }
 
-        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) {
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) {
 
                 /* Access the dynamic GID allocation directly if we are called from dbus-daemon, see above. */
                 r = direct_lookup_name(name, (uid_t*) &translated);
@@ -430,24 +436,26 @@ enum nss_status _nss_systemd_getgrgid_r(
                 goto not_found;
 
         /* Synthesize records for root and nobody, in case they are missing from /etc/group */
-        if (gid == root_group.gr_gid) {
-                *gr = root_group;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
-        }
-        if (gid == nobody_group.gr_gid) {
-                *gr = nobody_group;
-                *errnop = 0;
-                return NSS_STATUS_SUCCESS;
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_SYNTHETIC") <= 0) {
+                if (gid == root_group.gr_gid) {
+                        *gr = root_group;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
+                if (gid == nobody_group.gr_gid) {
+                        *gr = nobody_group;
+                        *errnop = 0;
+                        return NSS_STATUS_SUCCESS;
+                }
         }
 
         if (gid <= SYSTEM_GID_MAX)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
+        if (getenv_bool_secure("SYSTEMD_NSS_DYNAMIC_BYPASS") > 0)
                 goto not_found;
 
-        if (getenv_bool("SYSTEMD_NSS_BYPASS_BUS") > 0) {
+        if (getenv_bool_secure("SYSTEMD_NSS_BYPASS_BUS") > 0) {
 
                 r = direct_lookup_uid(gid, &direct);
                 if (r == -ENOENT)
index dda98750632c496733d1349170f30027f3f9828e..e169c8f02f887a22110607dfbdc7b492cdf9e19a 100644 (file)
@@ -435,7 +435,7 @@ static int dns_trust_anchor_load_files(
         assert(suffix);
         assert(loader);
 
-        r = conf_files_list_nulstr(&files, suffix, NULL, trust_anchor_dirs);
+        r = conf_files_list_nulstr(&files, suffix, NULL, 0, trust_anchor_dirs);
         if (r < 0)
                 return log_error_errno(r, "Failed to enumerate %s trust anchor files: %m", suffix);
 
index 86e304091832e2f4ff068e3d7fc6310cbbddc821..2e24f46b175e29af1abafc1e0341bd21dac9b727 100644 (file)
@@ -61,7 +61,12 @@ static int arg_nice = 0;
 static bool arg_nice_set = false;
 static char **arg_environment = NULL;
 static char **arg_property = NULL;
-static bool arg_pty = false;
+static enum {
+        ARG_STDIO_NONE,      /* The default, as it is for normal services, stdin connected to /dev/null, and stdout+stderr to the journal */
+        ARG_STDIO_PTY,       /* Interactive behaviour, requested by --pty: we allocate a pty and connect it to the TTY we are invoked from */
+        ARG_STDIO_DIRECT,    /* Directly pass our stdin/stdout/stderr to the activated service, useful for usage in shell pipelines, requested by --pipe */
+        ARG_STDIO_AUTO,      /* If --pipe and --pty are used together we use --pty when invoked on a TTY, and --pipe otherwise */
+} arg_stdio = ARG_STDIO_NONE;
 static usec_t arg_on_active = 0;
 static usec_t arg_on_boot = 0;
 static usec_t arg_on_startup = 0;
@@ -106,7 +111,9 @@ static void help(void) {
                "     --gid=GROUP                  Run as system group\n"
                "     --nice=NICE                  Nice level\n"
                "  -E --setenv=NAME=VALUE          Set environment\n"
-               "  -t --pty                        Run service on pseudo tty\n"
+               "  -t --pty                        Run service on pseudo TTY as STDIN/STDOUT/\n"
+               "                                  STDERR\n"
+               "  -P --pipe                       Pass STDIN/STDOUT/STDERR directly to service\n"
                "  -q --quiet                      Suppress information messages during runtime\n\n"
                "Timer options:\n"
                "     --on-active=SECONDS          Run after SECONDS delay\n"
@@ -170,8 +177,9 @@ static int parse_argv(int argc, char *argv[]) {
                 { "nice",              required_argument, NULL, ARG_NICE             },
                 { "setenv",            required_argument, NULL, 'E'                  },
                 { "property",          required_argument, NULL, 'p'                  },
-                { "tty",               no_argument,       NULL, 't'                  }, /* deprecated */
+                { "tty",               no_argument,       NULL, 't'                  }, /* deprecated alias */
                 { "pty",               no_argument,       NULL, 't'                  },
+                { "pipe",              no_argument,       NULL, 'P'                  },
                 { "quiet",             no_argument,       NULL, 'q'                  },
                 { "on-active",         required_argument, NULL, ARG_ON_ACTIVE        },
                 { "on-boot",           required_argument, NULL, ARG_ON_BOOT          },
@@ -190,7 +198,7 @@ static int parse_argv(int argc, char *argv[]) {
         assert(argc >= 0);
         assert(argv);
 
-        while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tq", options, NULL)) >= 0)
+        while ((c = getopt_long(argc, argv, "+hrH:M:E:p:tPq", options, NULL)) >= 0)
 
                 switch (c) {
 
@@ -279,8 +287,18 @@ static int parse_argv(int argc, char *argv[]) {
 
                         break;
 
-                case 't':
-                        arg_pty = true;
+                case 't': /* --pty */
+                        if (IN_SET(arg_stdio, ARG_STDIO_DIRECT, ARG_STDIO_AUTO)) /* if --pipe is already used, upgrade to auto mode */
+                                arg_stdio = ARG_STDIO_AUTO;
+                        else
+                                arg_stdio = ARG_STDIO_PTY;
+                        break;
+
+                case 'P': /* --pipe */
+                        if (IN_SET(arg_stdio, ARG_STDIO_PTY, ARG_STDIO_AUTO)) /* If --pty is already used, upgrade to auto mode */
+                                arg_stdio = ARG_STDIO_AUTO;
+                        else
+                                arg_stdio = ARG_STDIO_DIRECT;
                         break;
 
                 case 'q':
@@ -373,6 +391,16 @@ static int parse_argv(int argc, char *argv[]) {
                         assert_not_reached("Unhandled option");
                 }
 
+
+        if (arg_stdio == ARG_STDIO_AUTO) {
+                /* If we both --pty and --pipe are specified we'll automatically pick --pty if we are connected fully
+                 * to a TTY and pick direct fd passing otherwise. This way, we automatically adapt to usage in a shell
+                 * pipeline, but we are neatly interactive with tty-level isolation otherwise. */
+                arg_stdio = isatty(STDIN_FILENO) && isatty(STDOUT_FILENO) && isatty(STDERR_FILENO) ?
+                        ARG_STDIO_PTY :
+                        ARG_STDIO_DIRECT;
+        }
+
         if ((optind >= argc) && (!arg_unit || !with_timer())) {
                 log_error("Command line to execute required.");
                 return -EINVAL;
@@ -393,18 +421,18 @@ static int parse_argv(int argc, char *argv[]) {
                 return -EINVAL;
         }
 
-        if (arg_pty && (with_timer() || arg_scope)) {
-                log_error("--pty is not compatible in timer or --scope mode.");
+        if (arg_stdio != ARG_STDIO_NONE && (with_timer() || arg_scope)) {
+                log_error("--pty/--pipe is not compatible in timer or --scope mode.");
                 return -EINVAL;
         }
 
-        if (arg_pty && arg_transport == BUS_TRANSPORT_REMOTE) {
-                log_error("--pty is only supported when connecting to the local system or containers.");
+        if (arg_stdio != ARG_STDIO_NONE && arg_transport == BUS_TRANSPORT_REMOTE) {
+                log_error("--pty/--pipe is only supported when connecting to the local system or containers.");
                 return -EINVAL;
         }
 
-        if (arg_pty && arg_no_block) {
-                log_error("--pty is not compatible with --no-block.");
+        if (arg_stdio != ARG_STDIO_NONE && arg_no_block) {
+                log_error("--pty/--pipe is not compatible with --no-block.");
                 return -EINVAL;
         }
 
@@ -481,6 +509,7 @@ static int transient_kill_set_properties(sd_bus_message *m) {
 }
 
 static int transient_service_set_properties(sd_bus_message *m, char **argv, const char *pty_path) {
+        bool send_term = false;
         int r;
 
         assert(m);
@@ -497,7 +526,7 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
         if (r < 0)
                 return r;
 
-        if (arg_wait || arg_pty) {
+        if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
                 r = sd_bus_message_append(m, "(sv)", "AddRef", "b", 1);
                 if (r < 0)
                         return r;
@@ -534,8 +563,6 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
         }
 
         if (pty_path) {
-                const char *e;
-
                 r = sd_bus_message_append(m,
                                           "(sv)(sv)(sv)(sv)",
                                           "StandardInput", "s", "tty",
@@ -545,6 +572,23 @@ static int transient_service_set_properties(sd_bus_message *m, char **argv, cons
                 if (r < 0)
                         return r;
 
+                send_term = true;
+
+        } else if (arg_stdio == ARG_STDIO_DIRECT) {
+                r = sd_bus_message_append(m,
+                                          "(sv)(sv)(sv)",
+                                          "StandardInputFileDescriptor", "h", STDIN_FILENO,
+                                          "StandardOutputFileDescriptor", "h", STDOUT_FILENO,
+                                          "StandardErrorFileDescriptor", "h", STDERR_FILENO);
+                if (r < 0)
+                        return r;
+
+                send_term = isatty(STDIN_FILENO) || isatty(STDOUT_FILENO) || isatty(STDERR_FILENO);
+        }
+
+        if (send_term) {
+                const char *e;
+
                 e = getenv("TERM");
                 if (e) {
                         char *n;
@@ -875,7 +919,7 @@ static int start_transient_service(
         assert(argv);
         assert(retval);
 
-        if (arg_pty) {
+        if (arg_stdio == ARG_STDIO_PTY) {
 
                 if (arg_transport == BUS_TRANSPORT_LOCAL) {
                         master = posix_openpt(O_RDWR|O_NOCTTY|O_CLOEXEC|O_NDELAY);
@@ -1000,7 +1044,7 @@ static int start_transient_service(
         if (!arg_quiet)
                 log_info("Running as unit: %s", service);
 
-        if (arg_wait || master >= 0) {
+        if (arg_wait || arg_stdio != ARG_STDIO_NONE) {
                 _cleanup_(run_context_free) RunContext c = {};
                 _cleanup_free_ char *path = NULL;
                 const char *mt;
@@ -1440,7 +1484,7 @@ int main(int argc, char* argv[]) {
 
         /* If --wait is used connect via the bus, unconditionally, as ref/unref is not supported via the limited direct
          * connection */
-        if (arg_wait || arg_pty)
+        if (arg_wait || arg_stdio != ARG_STDIO_NONE)
                 r = bus_connect_transport(arg_transport, arg_host, arg_user, &bus);
         else
                 r = bus_connect_transport_systemd(arg_transport, arg_host, arg_user, &bus);
index c024f64ca92452dc430c367c7f8e708f0b37f52d..40f1d74d8a0f3d98ec4e823d7c2eae7c36a204fe 100644 (file)
@@ -641,7 +641,7 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
 
                 r = sd_bus_message_append(m, "v", "i", (int32_t) q);
 
-        } else if (STR_IN_SET(field, "Environment", "PassEnvironment")) {
+        } else if (STR_IN_SET(field, "Environment", "UnsetEnvironment", "PassEnvironment")) {
                 const char *p;
 
                 r = sd_bus_message_open_container(m, 'v', "as");
@@ -668,6 +668,11 @@ int bus_append_unit_property_assignment(sd_bus_message *m, const char *assignmen
                                         log_error("Invalid environment assignment: %s", word);
                                         return -EINVAL;
                                 }
+                        } else if (streq(field, "UnsetEnvironment")) {
+                                if (!env_assignment_is_valid(word) && !env_name_is_valid(word)) {
+                                        log_error("Invalid environment name or assignment: %s", word);
+                                        return -EINVAL;
+                                }
                         } else {  /* PassEnvironment */
                                 if (!env_name_is_valid(word)) {
                                         log_error("Invalid environment variable name: %s", word);
index e08402e3d22ea54e785c8d4bac71f490d9e8a797..a84b61243e0e9ffb0de4cece9a6d164d0ec4dd6a 100644 (file)
@@ -436,7 +436,7 @@ int config_parse_many_nulstr(
         _cleanup_strv_free_ char **files = NULL;
         int r;
 
-        r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+        r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
         if (r < 0)
                 return r;
 
@@ -465,7 +465,7 @@ int config_parse_many(
         if (r < 0)
                 return r;
 
-        r = conf_files_list_strv(&files, ".conf", NULL, (const char* const*) dropin_dirs);
+        r = conf_files_list_strv(&files, ".conf", NULL, 0, (const char* const*) dropin_dirs);
         if (r < 0)
                 return r;
 
@@ -725,6 +725,11 @@ int config_parse_path(
         assert(rvalue);
         assert(data);
 
+        if (isempty(rvalue)) {
+                n = NULL;
+                goto finalize;
+        }
+
         if (!utf8_is_valid(rvalue)) {
                 log_syntax_invalid_utf8(unit, LOG_ERR, filename, line, rvalue);
                 return fatal ? -ENOEXEC : 0;
@@ -743,22 +748,24 @@ int config_parse_path(
 
         path_kill_slashes(n);
 
+finalize:
         free(*s);
         *s = n;
 
         return 0;
 }
 
-int config_parse_strv(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_strv(
+                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 ***sv = data;
         int r;
@@ -769,19 +776,7 @@ int config_parse_strv(const char *unit,
         assert(data);
 
         if (isempty(rvalue)) {
-                char **empty;
-
-                /* Empty assignment resets the list. As a special rule
-                 * we actually fill in a real empty array here rather
-                 * than NULL, since some code wants to know if
-                 * something was set at all... */
-                empty = new0(char*, 1);
-                if (!empty)
-                        return log_oom();
-
-                strv_free(*sv);
-                *sv = empty;
-
+                *sv = strv_free(*sv);
                 return 0;
         }
 
@@ -803,6 +798,7 @@ int config_parse_strv(const char *unit,
                         free(word);
                         continue;
                 }
+
                 r = strv_consume(sv, word);
                 if (r < 0)
                         return log_oom();
@@ -920,10 +916,14 @@ int config_parse_personality(
         assert(rvalue);
         assert(personality);
 
-        p = personality_from_string(rvalue);
-        if (p == PERSONALITY_INVALID) {
-                log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
-                return 0;
+        if (isempty(rvalue))
+                p = PERSONALITY_INVALID;
+        else {
+                p = personality_from_string(rvalue);
+                if (p == PERSONALITY_INVALID) {
+                        log_syntax(unit, LOG_ERR, filename, line, 0, "Failed to parse personality, ignoring: %s", rvalue);
+                        return 0;
+                }
         }
 
         *personality = p;
index 7d8fbeb4359b43cedc02a904c17a04065d6021bc..059b50dbd0e26c47d33ff8e9abcd83390c3d0a00 100644 (file)
@@ -203,7 +203,7 @@ int unit_file_find_dropin_paths(
                 return 0;
         }
 
-        r = conf_files_list_strv(ret, file_suffix, NULL, (const char**) dirs);
+        r = conf_files_list_strv(ret, file_suffix, NULL, 0, (const char**) dirs);
         if (r < 0)
                 return log_warning_errno(r, "Failed to create the list of configuration files: %m");
 
index d0a291b819b6714bc97c1a0217749a9d9184c69c..9e4e0eaf6fd7a89cc33ad5a57605a7486e4b4c82 100644 (file)
@@ -2662,7 +2662,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
         assert(presets);
 
         if (scope == UNIT_FILE_SYSTEM)
-                r = conf_files_list(&files, ".preset", root_dir,
+                r = conf_files_list(&files, ".preset", root_dir, 0,
                                     "/etc/systemd/system-preset",
                                     "/usr/local/lib/systemd/system-preset",
                                     "/usr/lib/systemd/system-preset",
@@ -2671,7 +2671,7 @@ static int read_presets(UnitFileScope scope, const char *root_dir, Presets *pres
 #endif
                                     NULL);
         else if (scope == UNIT_FILE_GLOBAL)
-                r = conf_files_list(&files, ".preset", root_dir,
+                r = conf_files_list(&files, ".preset", root_dir, 0,
                                     "/etc/systemd/user-preset",
                                     "/usr/local/lib/systemd/user-preset",
                                     "/usr/lib/systemd/user-preset",
index ad48652527865e4f934c360691312b9cef0cd6ef..0661ff0bb9b21e9b748039182b7fc1ff763ee931 100644 (file)
@@ -84,7 +84,7 @@ int pager_open(bool no_pager, bool jump_to_end) {
          * pager so that we get the value from the actual tty */
         (void) columns();
 
-        if (pipe(fd) < 0)
+        if (pipe2(fd, O_CLOEXEC) < 0)
                 return log_error_errno(errno, "Failed to create pager pipe: %m");
 
         parent_pid = getpid_cached();
index 0857f5907ed513df4136d4f3df5df0434b00ab71..5e78a088e9f9031672c651c64b459b6e3c82be4d 100644 (file)
@@ -278,11 +278,19 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "execve\0"
                 "exit\0"
                 "exit_group\0"
+                "futex\0"
+                "get_robust_list\0"
+                "get_thread_area\0"
                 "getrlimit\0"      /* make sure processes can query stack size and such */
                 "gettimeofday\0"
+                "membarrier\0"
                 "nanosleep\0"
                 "pause\0"
+                "restart_syscall\0"
                 "rt_sigreturn\0"
+                "set_robust_list\0"
+                "set_thread_area\0"
+                "set_tid_address\0"
                 "sigreturn\0"
                 "time\0"
         },
@@ -290,10 +298,11 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 .name = "@basic-io",
                 .help = "Basic IO",
                 .value =
+                "_llseek\0"
                 "close\0"
+                "dup\0"
                 "dup2\0"
                 "dup3\0"
-                "dup\0"
                 "lseek\0"
                 "pread64\0"
                 "preadv\0"
@@ -324,6 +333,32 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "vm86\0"
                 "vm86old\0"
         },
+        [SYSCALL_FILTER_SET_CREDENTIALS] = {
+                .name = "@credentials",
+                .help = "Query own process credentials",
+                .value =
+                "capget\0"
+                "getegid\0"
+                "getegid32\0"
+                "geteuid\0"
+                "geteuid32\0"
+                "getgid\0"
+                "getgid32\0"
+                "getgroups\0"
+                "getgroups32\0"
+                "getpgid\0"
+                "getpgrp\0"
+                "getpid\0"
+                "getppid\0"
+                "getresgid\0"
+                "getresgid32\0"
+                "getresuid\0"
+                "getresuid32\0"
+                "getsid\0"
+                "gettid\0"
+                "getuid\0"
+                "getuid32\0"
+        },
         [SYSCALL_FILTER_SET_DEBUG] = {
                 .name = "@debug",
                 .help = "Debugging, performance monitoring and tracing functionality",
@@ -353,24 +388,26 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "fchdir\0"
                 "fchmod\0"
                 "fchmodat\0"
-                "fcntl64\0"
                 "fcntl\0"
+                "fcntl64\0"
                 "fgetxattr\0"
                 "flistxattr\0"
+                "fremovexattr\0"
                 "fsetxattr\0"
-                "fstat64\0"
                 "fstat\0"
+                "fstat64\0"
                 "fstatat64\0"
-                "fstatfs64\0"
                 "fstatfs\0"
-                "ftruncate64\0"
+                "fstatfs64\0"
                 "ftruncate\0"
+                "ftruncate64\0"
                 "futimesat\0"
                 "getcwd\0"
-                "getdents64\0"
                 "getdents\0"
+                "getdents64\0"
                 "getxattr\0"
                 "inotify_add_watch\0"
+                "inotify_init\0"
                 "inotify_init1\0"
                 "inotify_rm_watch\0"
                 "lgetxattr\0"
@@ -380,36 +417,43 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "llistxattr\0"
                 "lremovexattr\0"
                 "lsetxattr\0"
-                "lstat64\0"
                 "lstat\0"
+                "lstat64\0"
                 "mkdir\0"
                 "mkdirat\0"
                 "mknod\0"
                 "mknodat\0"
-                "mmap2\0"
                 "mmap\0"
+                "mmap2\0"
                 "munmap\0"
                 "newfstatat\0"
+                "oldfstat\0"
+                "oldlstat\0"
+                "oldstat\0"
                 "open\0"
                 "openat\0"
                 "readlink\0"
                 "readlinkat\0"
                 "removexattr\0"
                 "rename\0"
-                "renameat2\0"
                 "renameat\0"
+                "renameat2\0"
                 "rmdir\0"
                 "setxattr\0"
-                "stat64\0"
                 "stat\0"
+                "stat64\0"
                 "statfs\0"
+                "statfs64\0"
+#ifdef __PNR_statx
                 "statx\0"
+#endif
                 "symlink\0"
                 "symlinkat\0"
-                "truncate64\0"
                 "truncate\0"
+                "truncate64\0"
                 "unlink\0"
                 "unlinkat\0"
+                "utime\0"
                 "utimensat\0"
                 "utimes\0"
         },
@@ -418,15 +462,15 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 .help = "Event loop system calls",
                 .value =
                 "_newselect\0"
-                "epoll_create1\0"
                 "epoll_create\0"
+                "epoll_create1\0"
                 "epoll_ctl\0"
                 "epoll_ctl_old\0"
                 "epoll_pwait\0"
                 "epoll_wait\0"
                 "epoll_wait_old\0"
-                "eventfd2\0"
                 "eventfd\0"
+                "eventfd2\0"
                 "poll\0"
                 "ppoll\0"
                 "pselect6\0"
@@ -448,8 +492,8 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "msgget\0"
                 "msgrcv\0"
                 "msgsnd\0"
-                "pipe2\0"
                 "pipe\0"
+                "pipe2\0"
                 "process_vm_readv\0"
                 "process_vm_writev\0"
                 "semctl\0"
@@ -469,6 +513,16 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "keyctl\0"
                 "request_key\0"
         },
+        [SYSCALL_FILTER_SET_MEMLOCK] = {
+                .name = "@memlock",
+                .help = "Memory locking control",
+                .value =
+                "mlock\0"
+                "mlock2\0"
+                "mlockall\0"
+                "munlock\0"
+                "munlockall\0"
+        },
         [SYSCALL_FILTER_SET_MODULE] = {
                 .name = "@module",
                 .help = "Loading and unloading of kernel modules",
@@ -484,15 +538,15 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "chroot\0"
                 "mount\0"
                 "pivot_root\0"
-                "umount2\0"
                 "umount\0"
+                "umount2\0"
         },
         [SYSCALL_FILTER_SET_NETWORK_IO] = {
                 .name = "@network-io",
                 .help = "Network or Unix socket IO, should not be needed if not network facing",
                 .value =
-                "accept4\0"
                 "accept\0"
+                "accept4\0"
                 "bind\0"
                 "connect\0"
                 "getpeername\0"
@@ -527,6 +581,7 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "get_kernel_syms\0"
                 "getpmsg\0"
                 "gtty\0"
+                "idle\0"
                 "lock\0"
                 "mpx\0"
                 "prof\0"
@@ -551,38 +606,38 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "@clock\0"
                 "@module\0"
                 "@raw-io\0"
+                "_sysctl\0"
                 "acct\0"
                 "bpf\0"
                 "capset\0"
-                "chown32\0"
                 "chown\0"
+                "chown32\0"
                 "chroot\0"
-                "fchown32\0"
                 "fchown\0"
+                "fchown32\0"
                 "fchownat\0"
                 "kexec_file_load\0"
                 "kexec_load\0"
-                "lchown32\0"
                 "lchown\0"
+                "lchown32\0"
                 "nfsservctl\0"
                 "pivot_root\0"
                 "quotactl\0"
                 "reboot\0"
                 "setdomainname\0"
-                "setfsuid32\0"
                 "setfsuid\0"
-                "setgroups32\0"
+                "setfsuid32\0"
                 "setgroups\0"
+                "setgroups32\0"
                 "sethostname\0"
-                "setresuid32\0"
                 "setresuid\0"
-                "setreuid32\0"
+                "setresuid32\0"
                 "setreuid\0"
-                "setuid32\0"
+                "setreuid32\0"
                 "setuid\0"
+                "setuid32\0"
                 "swapoff\0"
                 "swapon\0"
-                "_sysctl\0"
                 "vhangup\0"
         },
         [SYSCALL_FILTER_SET_PROCESS] = {
@@ -593,13 +648,23 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "clone\0"
                 "execveat\0"
                 "fork\0"
+                "getpid\0"
+                "getppid\0"
+                "getrusage\0"
+                "gettid\0"
                 "kill\0"
                 "prctl\0"
+                "rt_sigqueueinfo\0"
+                "rt_tgsigqueueinfo\0"
                 "setns\0"
                 "tgkill\0"
+                "times\0"
                 "tkill\0"
                 "unshare\0"
                 "vfork\0"
+                "wait4\0"
+                "waitid\0"
+                "waitpid\0"
         },
         [SYSCALL_FILTER_SET_RAW_IO] = {
                 .name = "@raw-io",
@@ -629,36 +694,56 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 .name = "@resources",
                 .help = "Alter resource settings",
                 .value =
+                "ioprio_set\0"
+                "mbind\0"
+                "migrate_pages\0"
+                "move_pages\0"
+                "nice\0"
+                "prlimit64\0"
+                "sched_setaffinity\0"
+                "sched_setattr\0"
                 "sched_setparam\0"
                 "sched_setscheduler\0"
-                "sched_setaffinity\0"
+                "set_mempolicy\0"
                 "setpriority\0"
                 "setrlimit\0"
-                "set_mempolicy\0"
-                "migrate_pages\0"
-                "move_pages\0"
-                "mbind\0"
-                "sched_setattr\0"
-                "prlimit64\0"
         },
         [SYSCALL_FILTER_SET_SETUID] = {
                 .name = "@setuid",
                 .help = "Operations for changing user/group credentials",
                 .value =
-                "setgid32\0"
                 "setgid\0"
-                "setgroups32\0"
+                "setgid32\0"
                 "setgroups\0"
-                "setregid32\0"
+                "setgroups32\0"
                 "setregid\0"
-                "setresgid32\0"
+                "setregid32\0"
                 "setresgid\0"
-                "setresuid32\0"
+                "setresgid32\0"
                 "setresuid\0"
-                "setreuid32\0"
+                "setresuid32\0"
                 "setreuid\0"
-                "setuid32\0"
+                "setreuid32\0"
                 "setuid\0"
+                "setuid32\0"
+        },
+        [SYSCALL_FILTER_SET_SIGNAL] = {
+                .name = "@signal",
+                .help = "Process signal handling",
+                .value =
+                "rt_sigaction\0"
+                "rt_sigpending\0"
+                "rt_sigprocmask\0"
+                "rt_sigsuspend\0"
+                "rt_sigtimedwait\0"
+                "sigaction\0"
+                "sigaltstack\0"
+                "signal\0"
+                "signalfd\0"
+                "signalfd4\0"
+                "sigpending\0"
+                "sigprocmask\0"
+                "sigsuspend\0"
         },
         [SYSCALL_FILTER_SET_SWAP] = {
                 .name = "@swap",
@@ -667,6 +752,23 @@ const SyscallFilterSet syscall_filter_sets[_SYSCALL_FILTER_SET_MAX] = {
                 "swapoff\0"
                 "swapon\0"
         },
+        [SYSCALL_FILTER_SET_TIMER] = {
+                .name = "@timer",
+                .help = "Schedule operations by time",
+                .value =
+                "alarm\0"
+                "getitimer\0"
+                "setitimer\0"
+                "timer_create\0"
+                "timer_delete\0"
+                "timer_getoverrun\0"
+                "timer_gettime\0"
+                "timer_settime\0"
+                "timerfd_create\0"
+                "timerfd_gettime\0"
+                "timerfd_settime\0"
+                "times\0"
+        },
 };
 
 const SyscallFilterSet *syscall_filter_set_find(const char *name) {
@@ -682,11 +784,52 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name) {
         return NULL;
 }
 
+static int seccomp_add_syscall_filter_set(scmp_filter_ctx seccomp, const SyscallFilterSet *set, uint32_t action, char **exclude);
+
+int seccomp_add_syscall_filter_item(scmp_filter_ctx *seccomp, const char *name, uint32_t action, char **exclude) {
+        int r;
+
+        assert(seccomp);
+        assert(name);
+
+        if (strv_contains(exclude, name))
+                return 0;
+
+        if (name[0] == '@') {
+                const SyscallFilterSet *other;
+
+                other = syscall_filter_set_find(name);
+                if (!other) {
+                        log_debug("Filter set %s is not known!", name);
+                        return -EINVAL;
+                }
+
+                r = seccomp_add_syscall_filter_set(seccomp, other, action, exclude);
+                if (r < 0)
+                        return r;
+        } else {
+                int id;
+
+                id = seccomp_syscall_resolve_name(name);
+                if (id == __NR_SCMP_ERROR) {
+                        log_debug("System call %s is not known!", name);
+                        return -EINVAL; /* Not known at all? Then that's a real error */
+                }
+
+                r = seccomp_rule_add_exact(seccomp, action, id, 0);
+                if (r < 0)
+                        /* If the system call is not known on this architecture, then that's fine, let's ignore it */
+                        log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", name, id);
+        }
+
+        return 0;
+}
+
 static int seccomp_add_syscall_filter_set(
                 scmp_filter_ctx seccomp,
-                uint32_t default_action,
                 const SyscallFilterSet *set,
-                uint32_t action) {
+                uint32_t action,
+                char **exclude) {
 
         const char *sys;
         int r;
@@ -695,28 +838,9 @@ static int seccomp_add_syscall_filter_set(
         assert(set);
 
         NULSTR_FOREACH(sys, set->value) {
-                int id;
-
-                if (sys[0] == '@') {
-                        const SyscallFilterSet *other;
-
-                        other = syscall_filter_set_find(sys);
-                        if (!other)
-                                return -EINVAL;
-
-                        r = seccomp_add_syscall_filter_set(seccomp, default_action, other, action);
-                        if (r < 0)
-                                return r;
-                } else {
-                        id = seccomp_syscall_resolve_name(sys);
-                        if (id == __NR_SCMP_ERROR)
-                                return -EINVAL; /* Not known at all? Then that's a real error */
-
-                        r = seccomp_rule_add_exact(seccomp, action, id, 0);
-                        if (r < 0)
-                                /* If the system call is not known on this architecture, then that's fine, let's ignore it */
-                                log_debug_errno(r, "Failed to add rule for system call %s() / %d, ignoring: %m", sys, id);
-                }
+                r = seccomp_add_syscall_filter_item(seccomp, sys, action, exclude);
+                if (r < 0)
+                        return r;
         }
 
         return 0;
@@ -740,7 +864,7 @@ int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilter
                 if (r < 0)
                         return r;
 
-                r = seccomp_add_syscall_filter_set(seccomp, default_action, set, action);
+                r = seccomp_add_syscall_filter_set(seccomp, set, action, NULL);
                 if (r < 0) {
                         log_debug_errno(r, "Failed to add filter set, ignoring: %m");
                         continue;
index ca43ba8659a5ebae5b18c23f1ed1733ad8b3d44b..d4ff027df8b3b0f82a8e25cd2bc56e635b1257e1 100644 (file)
@@ -44,11 +44,13 @@ enum {
         SYSCALL_FILTER_SET_BASIC_IO,
         SYSCALL_FILTER_SET_CLOCK,
         SYSCALL_FILTER_SET_CPU_EMULATION,
+        SYSCALL_FILTER_SET_CREDENTIALS,
         SYSCALL_FILTER_SET_DEBUG,
         SYSCALL_FILTER_SET_FILE_SYSTEM,
         SYSCALL_FILTER_SET_IO_EVENT,
         SYSCALL_FILTER_SET_IPC,
         SYSCALL_FILTER_SET_KEYRING,
+        SYSCALL_FILTER_SET_MEMLOCK,
         SYSCALL_FILTER_SET_MODULE,
         SYSCALL_FILTER_SET_MOUNT,
         SYSCALL_FILTER_SET_NETWORK_IO,
@@ -59,7 +61,9 @@ enum {
         SYSCALL_FILTER_SET_REBOOT,
         SYSCALL_FILTER_SET_RESOURCES,
         SYSCALL_FILTER_SET_SETUID,
+        SYSCALL_FILTER_SET_SIGNAL,
         SYSCALL_FILTER_SET_SWAP,
+        SYSCALL_FILTER_SET_TIMER,
         _SYSCALL_FILTER_SET_MAX
 };
 
@@ -69,6 +73,8 @@ const SyscallFilterSet *syscall_filter_set_find(const char *name);
 
 int seccomp_filter_set_add(Set *s, bool b, const SyscallFilterSet *set);
 
+int seccomp_add_syscall_filter_item(scmp_filter_ctx *ctx, const char *name, uint32_t action, char **exclude);
+
 int seccomp_load_syscall_filter_set(uint32_t default_action, const SyscallFilterSet *set, uint32_t action);
 int seccomp_load_syscall_filter_set_raw(uint32_t default_action, Set* set, uint32_t action);
 
index 1c17eb52514490a8caffb4ea77d4b4142e50b237..81379041cc9bc1ff978c8a5c3be76e4fb88f88d8 100644 (file)
@@ -107,6 +107,10 @@ int specifier_printf(const char *text, const Specifier table[], void *userdata,
                         *(t++) = *f;
         }
 
+        /* if string ended with a stray %, also end with % */
+        if (percent)
+                *(t++) = '%';
+
         *t = 0;
         *_ret = ret;
         return 0;
index 3bac78b3e4cc84529bb1637175bbda3df51dda92..4c171a2fe5da8d585803f6b5c4adafefa25e394b 100644 (file)
@@ -91,7 +91,10 @@ static int execute(char **modes, char **states) {
                 arg_verb,
                 NULL
         };
-        static const char* const dirs[] = {SYSTEM_SLEEP_PATH, NULL};
+        static const char* const dirs[] = {
+                SYSTEM_SLEEP_PATH,
+                NULL
+        };
 
         int r;
         _cleanup_fclose_ FILE *f = NULL;
index 41a6dcbd1b0264905f01dd25b3de6214069b11b9..ce4ff8c8a3ea25afb13fdeabd481a0a3e927663f 100644 (file)
@@ -280,7 +280,7 @@ int main(int argc, char *argv[]) {
                 _cleanup_strv_free_ char **files = NULL;
                 char **f;
 
-                r = conf_files_list_nulstr(&files, ".conf", NULL, conf_file_dirs);
+                r = conf_files_list_nulstr(&files, ".conf", NULL, 0, conf_file_dirs);
                 if (r < 0) {
                         log_error_errno(r, "Failed to enumerate sysctl.d files: %m");
                         goto finish;
index 448f584733629112a8abe1f53ffe48cc1cc5f958..e9e6dae10c7293920e765341eb23d5a3977ef16a 100644 (file)
@@ -1798,7 +1798,7 @@ int main(int argc, char *argv[]) {
                 _cleanup_strv_free_ char **files = NULL;
                 char **f;
 
-                r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
+                r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, conf_file_dirs);
                 if (r < 0) {
                         log_error_errno(r, "Failed to enumerate sysusers.d files: %m");
                         goto finish;
@@ -1811,6 +1811,16 @@ int main(int argc, char *argv[]) {
                 }
         }
 
+        /* Let's tell nss-systemd not to synthesize the "root" and "nobody" entries for it, so that our detection
+         * whether the names or UID/GID area already used otherwise doesn't get confused. After all, even though
+         * nss-systemd synthesizes these users/groups, they should still appear in /etc/passwd and /etc/group, as the
+         * synthesizing logic is merely supposed to be fallback for cases where we run with a completely unpopulated
+         * /etc. */
+        if (setenv("SYSTEMD_NSS_BYPASS_SYNTHETIC", "1", 1) < 0) {
+                r = log_error_errno(errno, "Failed to set SYSTEMD_NSS_BYPASS_SYNTHETIC environment variable: %m");
+                goto finish;
+        }
+
         if (!uid_range) {
                 /* Default to default range of 1..SYSTEMD_UID_MAX */
                 r = uid_range_add(&uid_range, &n_uid_range, 1, SYSTEM_UID_MAX);
index 22b7c61204acab2a228a4e36ed3d743311e33e19..777b5ca32b0ec8d4ae61c4581e876e0c440e19f5 100644 (file)
@@ -75,7 +75,7 @@ static void test_conf_files_list(bool use_root) {
 
         log_debug("/* Check when filtered by suffix */");
 
-        assert_se(conf_files_list(&found_files, ".conf", root_dir, search_1, search_2, NULL) == 0);
+        assert_se(conf_files_list(&found_files, ".conf", root_dir, 0, search_1, search_2, NULL) == 0);
         strv_print(found_files);
 
         assert_se(found_files);
@@ -84,7 +84,7 @@ static void test_conf_files_list(bool use_root) {
         assert_se(found_files[2] == NULL);
 
         log_debug("/* Check when unfiltered */");
-        assert_se(conf_files_list(&found_files2, NULL, root_dir, search_1, search_2, NULL) == 0);
+        assert_se(conf_files_list(&found_files2, NULL, root_dir, 0, search_1, search_2, NULL) == 0);
         strv_print(found_files2);
 
         assert_se(found_files2);
index ac2cdd50ed9ca49c0ee67c670a661b1c68324b01..9d1dcfc58ecedf0f733e313a82700ccb849cbced 100644 (file)
@@ -453,6 +453,10 @@ static void test_exec_read_only_path_suceed(Manager *m) {
         test(m, "exec-read-only-path-succeed.service", 0, CLD_EXITED);
 }
 
+static void test_exec_unset_environment(Manager *m) {
+        test(m, "exec-unset-environment.service", 0, CLD_EXITED);
+}
+
 static int run_tests(UnitFileScope scope, const test_function_t *tests) {
         const test_function_t *test = NULL;
         Manager *m = NULL;
@@ -508,6 +512,7 @@ int main(int argc, char *argv[]) {
                 test_exec_ioschedulingclass,
                 test_exec_spec_interpolation,
                 test_exec_read_only_path_suceed,
+                test_exec_unset_environment,
                 NULL,
         };
         static const test_function_t system_tests[] = {
index 5056a08117fb0bb1836a03e73726ea1da8e060a3..4d63b688096184573f678dd4fd449fd05083028b 100644 (file)
@@ -612,6 +612,36 @@ static void test_lock_personality(void) {
         assert_se(wait_for_terminate_and_warn("lockpersonalityseccomp", pid, true) == EXIT_SUCCESS);
 }
 
+static void test_filter_sets_ordered(void) {
+        size_t i;
+
+        /* Ensure "@default" always remains at the beginning of the list */
+        assert_se(SYSCALL_FILTER_SET_DEFAULT == 0);
+        assert_se(streq(syscall_filter_sets[0].name, "@default"));
+
+        for (i = 0; i < _SYSCALL_FILTER_SET_MAX; i++) {
+                const char *k, *p = NULL;
+
+                /* Make sure each group has a description */
+                assert_se(!isempty(syscall_filter_sets[0].help));
+
+                /* Make sure the groups are ordered alphabetically, except for the first entry */
+                assert_se(i < 2 || strcmp(syscall_filter_sets[i-1].name, syscall_filter_sets[i].name) < 0);
+
+                NULSTR_FOREACH(k, syscall_filter_sets[i].value) {
+
+                        /* Ensure each syscall list is in itself ordered, but groups before names */
+                        assert_se(!p ||
+                                  (*p == '@' && *k != '@') ||
+                                  (((*p == '@' && *k == '@') ||
+                                    (*p != '@' && *k != '@')) &&
+                                   strcmp(p, k) < 0));
+
+                        p = k;
+                }
+        }
+}
+
 int main(int argc, char *argv[]) {
 
         log_set_max_level(LOG_DEBUG);
@@ -629,6 +659,7 @@ int main(int argc, char *argv[]) {
         test_restrict_archs();
         test_load_syscall_filter_set_raw();
         test_lock_personality();
+        test_filter_sets_ordered();
 
         return 0;
 }
index b8979c0e95638cc3e32f2abab5593eb92d166ca5..dcccc9080cd326b160a5844d2e6e45524dbf4c81 100644 (file)
@@ -237,7 +237,8 @@ static int test_unit_printf(void) {
         /* general tests */
         expect(u, "%%", "%");
         expect(u, "%%s", "%s");
-        expect(u, "%", "");    // REALLY?
+        expect(u, "%,", "%,");
+        expect(u, "%", "%");
 
         /* normal unit */
         expect(u, "%n", "blah.service");
index 875a886bf3de9cbe92ca2bf060c09c3e4674e87b..3d3967f2719f3c62f5cc55fba8021633b9d25de1 100644 (file)
@@ -2300,7 +2300,7 @@ int main(int argc, char *argv[]) {
                 _cleanup_strv_free_ char **files = NULL;
                 char **f;
 
-                r = conf_files_list_nulstr(&files, ".conf", arg_root, conf_file_dirs);
+                r = conf_files_list_nulstr(&files, ".conf", arg_root, 0, conf_file_dirs);
                 if (r < 0) {
                         log_error_errno(r, "Failed to enumerate tmpfiles.d files: %m");
                         goto finish;
index 05a186357c5233fb8d31d09c944ddab9d29fb81f..6ece1250f25ce3092a7572e86c4f4decd1d9e1e2 100644 (file)
@@ -213,7 +213,7 @@ int link_config_load(link_config_ctx *ctx) {
         /* update timestamp */
         paths_check_timestamp(link_dirs, &ctx->link_dirs_ts_usec, true);
 
-        r = conf_files_list_strv(&files, ".link", NULL, link_dirs);
+        r = conf_files_list_strv(&files, ".link", NULL, 0, link_dirs);
         if (r < 0)
                 return log_error_errno(r, "failed to enumerate link files: %m");
 
index 294a3225472fa0ba1394d07bccc39c396038377b..76a1d35a19712a62a1181e106fb16c2846d6a96a 100644 (file)
@@ -1533,7 +1533,7 @@ struct udev_rules *udev_rules_new(struct udev *udev, int resolve_names) {
 
         udev_rules_check_timestamp(rules);
 
-        r = conf_files_list_strv(&files, ".rules", NULL, rules_dirs);
+        r = conf_files_list_strv(&files, ".rules", NULL, 0, rules_dirs);
         if (r < 0) {
                 log_error_errno(r, "failed to enumerate rules files: %m");
                 return udev_rules_unref(rules);
index 7688f8192b23ecdf644f0cd2ec967533fa15c588..4a23270dfb835de9da64c7fa5f18b9964b7a2824 100644 (file)
@@ -627,7 +627,7 @@ static int adm_hwdb(struct udev *udev, int argc, char *argv[]) {
                 }
                 trie->nodes_count++;
 
-                err = conf_files_list_strv(&files, ".hwdb", root, conf_file_dirs);
+                err = conf_files_list_strv(&files, ".hwdb", root, 0, conf_file_dirs);
                 if (err < 0) {
                         log_error_errno(err, "failed to enumerate hwdb files: %m");
                         rc = EXIT_FAILURE;
index c16ca92702491a7d008a792537de94a14028d8ca..bddeeb62b44ba929b13ca12b57c76d75dde2a384 100644 (file)
@@ -94,6 +94,7 @@ test_data_files = '''
         test-execute/exec-systemcallfilter-not-failing.service
         test-execute/exec-systemcallfilter-system-user.service
         test-execute/exec-systemcallfilter-system-user-nfsnobody.service
+        test-execute/exec-unset-environment.service
         test-execute/exec-user.service
         test-execute/exec-user-nfsnobody.service
         test-execute/exec-workingdirectory.service
diff --git a/test/test-execute/exec-unset-environment.service b/test/test-execute/exec-unset-environment.service
new file mode 100644 (file)
index 0000000..5b0123b
--- /dev/null
@@ -0,0 +1,8 @@
+[Unit]
+Description=Test for UnsetEnvironment
+
+[Service]
+ExecStart=/bin/sh -x -c 'test "$$FOO" = "bar" && test "$${QUUX-X}" = "X" && test "$$VAR3" = "value3" && test "$${VAR4-X}" = "X" && test "$$VAR5" = "value5" && test "$${X%b-X}" = "X"'
+Type=oneshot
+Environment=FOO=bar QUUX=waldo VAR3=value3 VAR4=value4 VAR5=value5 X%b=%U
+UnsetEnvironment=QUUX=waldo VAR3=somethingelse VAR4 X%b=%U
index e7938c8911db11070a7d8e5c086de11432269efa..e32a38855a85378854a9b15fcea912e6d6937716 100644 (file)
@@ -8,7 +8,7 @@
 # See tmpfiles.d(5) for details
 
 # Set the NOCOW attribute for directories of journal files. This flag
-# is inheredited by their new files and sub-directories. Matters only
+# is inherited by their new files and sub-directories. Matters only
 # for btrfs filesystems.
 #
 # WARNING: Enabling the NOCOW attribute improves journal performance
index 59f6e494b375d58e42fc73314867b475550ff6ed..f72e5ef6b637fb3ed100ff0c880476b5591a2c47 100644 (file)
@@ -28,7 +28,7 @@ KillSignal=SIGHUP
 
 # Unset locale for the console getty since the console has problems
 # displaying some internationalized messages.
-Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
 
 [Install]
 WantedBy=sysinit.target
index b62f1b9225bd3c0fdaedd29c4d7b27664328f270..ff1b3c3d87ac1a467fed523807feac7ef5f8fad4 100644 (file)
@@ -51,7 +51,7 @@ SendSIGHUP=yes
 
 # Unset locale for the console getty since the console has problems
 # displaying some internationalized messages.
-Environment=LANG= LANGUAGE= LC_CTYPE= LC_NUMERIC= LC_TIME= LC_COLLATE= LC_MONETARY= LC_MESSAGES= LC_PAPER= LC_NAME= LC_ADDRESS= LC_TELEPHONE= LC_MEASUREMENT= LC_IDENTIFICATION=
+UnsetEnvironment=LANG LANGUAGE LC_CTYPE LC_NUMERIC LC_TIME LC_COLLATE LC_MONETARY LC_MESSAGES LC_PAPER LC_NAME LC_ADDRESS LC_TELEPHONE LC_MEASUREMENT LC_IDENTIFICATION
 
 [Install]
 WantedBy=getty.target
index c699a80f3428297f78343762f4f40d8177c45364..d7eaf3398e7070bee39ddb7e173c7f71ef43fcf5 100644 (file)
@@ -33,4 +33,5 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 StateDirectory=systemd/coredump
index d29e9ff81be325c849bbebddecdb02b6d5dec99c..9bb5ad8cac002f6c72edf1ba2097c179cfcb6367 100644 (file)
@@ -29,4 +29,5 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 ReadWritePaths=/etc
index 58762055eb6a569c8e1187ac7fce9ed3c77fbdc8..695a5f21cb0066b13d23642e10ca5c996c5c3e03 100644 (file)
@@ -23,3 +23,4 @@ RestrictNamespaces=net
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
index fd7a9718f7391ebed8442ec565990ba3c9f3cb51..b24d698c8a373c94db6dc35d0838f76c28a6ad1b 100644 (file)
@@ -25,6 +25,7 @@ RestrictRealtime=yes
 RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
 SystemCallArchitectures=native
+LockPersonality=yes
 
 # If there are many split upjournal files we need a lot of fds to
 # access them all and combine
index c24e673d8251ddb20676e6b7f8d3fc8db4aa53b3..92cec21c2fbe8978b8f7e6726a090a4c953c5069 100644 (file)
@@ -27,6 +27,7 @@ RestrictRealtime=yes
 RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
 SystemCallArchitectures=native
+LockPersonality=yes
 LogsDirectory=journal/remote
 
 [Install]
index b0bee3925e3194987ff78897d5cdfbe1ebd971a8..98a4b2bb7af15e62c860d6dcad46366a66a59187 100644 (file)
@@ -28,6 +28,7 @@ RestrictRealtime=yes
 RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
 SystemCallArchitectures=native
+LockPersonality=yes
 StateDirectory=systemd/journal-upload
 
 # If there are many split up journal files we need a lot of fds to
index 1e86d636485618cdf74fe27fc885a3fbcac97b6b..07e03e736ef7cae33997a9334aec9bf6e537dfae 100644 (file)
@@ -29,6 +29,7 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 
 # Increase the default a bit in order to allow many simultaneous
 # services being run since we keep one fd open per service. Also, when
index 90a913881acdd5924e288760798398eeb6f7964f..1366fa791069cc4eff509bb2670391285b15c2f5 100644 (file)
@@ -29,4 +29,5 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 ReadWritePaths=/etc
index f851373658bad3658a383457030b07497629f656..f6daf7755cd1ccbc08692e528cb1922d774131a4 100644 (file)
@@ -30,6 +30,7 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 FileDescriptorStoreMax=512
 
 # Increase the default a bit in order to allow many simultaneous
index a4f86aa7c87de98b676c689ae711329963d2a150..fb4df3829310f3e1bde8a5cde7f9460c71e2633b 100644 (file)
@@ -23,6 +23,7 @@ RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 
 # Note that machined cannot be placed in a mount namespace, since it
 # needs access to the host's mount namespace in order to implement the
index 3f0ad77b7d2a9b0f1afcffbb1017ca08810ad237..932dd63964983f0441dffc963f0af36652d6a1d6 100644 (file)
@@ -34,6 +34,7 @@ RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6 AF_PACKET
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 RuntimeDirectory=systemd/netif
 RuntimeDirectoryPreserve=yes
 
index ba8d3f6bb1656e1760c09cb00626a09ca6ec9cf0..cda83ee9666ceb2a704700ea3cb4dce205248094 100644 (file)
@@ -36,6 +36,7 @@ RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallFilter=~@clock @cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 RuntimeDirectory=systemd/resolve
 RuntimeDirectoryPreserve=yes
 
index 2b5f0744c9bfa7e7752bbaa896c5cf8c53136b0e..9fca1d1905d039a5e1c7813fa953ee1acdb7f146 100644 (file)
@@ -27,4 +27,5 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX
 SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 ReadWritePaths=/etc
index a6e14d24d1384c1bb97f29040020eec9903c001d..8d3f46cf5e227942f24a1b7b8567648c9239f177 100644 (file)
@@ -38,6 +38,7 @@ RestrictNamespaces=yes
 RestrictAddressFamilies=AF_UNIX AF_INET AF_INET6
 SystemCallFilter=~@cpu-emulation @debug @keyring @module @mount @obsolete @raw-io @reboot @swap
 SystemCallArchitectures=native
+LockPersonality=yes
 StateDirectory=systemd/timesync
 
 [Install]
index 3b92c6a8662cb760d870bdf58c225b1cae59761a..d3d13ed7cf2ef3291267fb5b02d4e0a3f3277f58 100644 (file)
@@ -28,3 +28,4 @@ MemoryDenyWriteExecute=yes
 RestrictRealtime=yes
 RestrictAddressFamilies=AF_UNIX AF_NETLINK AF_INET AF_INET6
 SystemCallArchitectures=native
+LockPersonality=yes