ryantimwilson / rpms / systemd

Forked from rpms/systemd a month ago
Clone
c2dfb7
From 11f5677752f9b78239214b3064e5a2c3712d71b1 Mon Sep 17 00:00:00 2001
c2dfb7
From: Lennart Poettering <lennart@poettering.net>
c2dfb7
Date: Wed, 20 Mar 2019 20:19:38 +0100
c2dfb7
Subject: [PATCH] core: imply NNP and SUID/SGID restriction for DynamicUser=yes
c2dfb7
 service
c2dfb7
c2dfb7
Let's be safe, rather than sorry. This way DynamicUser=yes services can
c2dfb7
neither take benefit of, nor create SUID/SGID binaries.
c2dfb7
c2dfb7
Given that DynamicUser= is a recent addition only we should be able to
c2dfb7
get away with turning this on, even though this is strictly speaking a
c2dfb7
binary compatibility breakage.
c2dfb7
c2dfb7
(cherry picked from commit bf65b7e0c9fc215897b676ab9a7c9d1c688143ba)
c2dfb7
Resolves: #1687512
c2dfb7
---
c2dfb7
 man/systemd.exec.xml | 16 ++++++++++------
c2dfb7
 src/core/unit.c      | 10 ++++++++--
c2dfb7
 2 files changed, 18 insertions(+), 8 deletions(-)
c2dfb7
c2dfb7
diff --git a/man/systemd.exec.xml b/man/systemd.exec.xml
c2dfb7
index 45ed1864f8..bdaed68162 100644
c2dfb7
--- a/man/systemd.exec.xml
c2dfb7
+++ b/man/systemd.exec.xml
c2dfb7
@@ -229,7 +229,9 @@
c2dfb7
         created by the executed processes is bound to the runtime of the service, and hence the lifetime of the dynamic
c2dfb7
         user/group. Since <filename>/tmp</filename> and <filename>/var/tmp</filename> are usually the only
c2dfb7
         world-writable directories on a system this ensures that a unit making use of dynamic user/group allocation
c2dfb7
-        cannot leave files around after unit termination. Moreover <varname>ProtectSystem=strict</varname> and
c2dfb7
+        cannot leave files around after unit termination. Furthermore <varname>NoNewPrivileges=</varname> and
c2dfb7
+        <varname>RestrictSUIDSGID=</varname> are implicitly enabled to ensure that processes invoked cannot take benefit
c2dfb7
+        or create SUID/SGID files or directories. Moreover <varname>ProtectSystem=strict</varname> and
c2dfb7
         <varname>ProtectHome=read-only</varname> are implied, thus prohibiting the service to write to arbitrary file
c2dfb7
         system locations. In order to allow the service to write to certain directories, they have to be whitelisted
c2dfb7
         using <varname>ReadWritePaths=</varname>, but care must be taken so that UID/GID recycling doesn't create
c2dfb7
@@ -357,11 +359,12 @@ CapabilityBoundingSet=~CAP_B CAP_C</programlisting>
c2dfb7
         <varname>RestrictAddressFamilies=</varname>, <varname>RestrictNamespaces=</varname>,
c2dfb7
         <varname>PrivateDevices=</varname>, <varname>ProtectKernelTunables=</varname>,
c2dfb7
         <varname>ProtectKernelModules=</varname>, <varname>MemoryDenyWriteExecute=</varname>,
c2dfb7
-        <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname> or
c2dfb7
-        <varname>LockPersonality=</varname> are specified. Note that even if this setting is overridden by
c2dfb7
-        them, <command>systemctl show</command> shows the original value of this setting. Also see 
c2dfb7
+        <varname>RestrictRealtime=</varname>, <varname>RestrictSUIDSGID=</varname>,
c2dfb7
+        <varname>DynamicUser=</varname> or <varname>LockPersonality=</varname> are specified. Note that even
c2dfb7
+        if this setting is overridden by them, <command>systemctl show</command> shows the original value of
c2dfb7
+        this setting. Also see 
c2dfb7
         url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges
c2dfb7
-        Flag</ulink>.  </para></listitem>
c2dfb7
+        Flag</ulink>.</para></listitem>
c2dfb7
       </varlistentry>
c2dfb7
 
c2dfb7
       <varlistentry>
c2dfb7
@@ -1288,7 +1291,8 @@ RestrictNamespaces=~cgroup net</programlisting>
c2dfb7
         identity of other users, it is recommended to restrict creation of SUID/SGID files to the few
c2dfb7
         programs that actually require them. Note that this restricts marking of any type of file system
c2dfb7
         object with these bits, including both regular files and directories (where the SGID is a different
c2dfb7
-        meaning than for files, see documentation). Defaults to off.</para></listitem>
c2dfb7
+        meaning than for files, see documentation). This option is implied if <varname>DynamicUser=</varname>
c2dfb7
+        is enabled. Defaults to off.</para></listitem>
c2dfb7
       </varlistentry>
c2dfb7
 
c2dfb7
       <varlistentry>
c2dfb7
diff --git a/src/core/unit.c b/src/core/unit.c
c2dfb7
index 115739f4c6..e1f5e6f7bd 100644
c2dfb7
--- a/src/core/unit.c
c2dfb7
+++ b/src/core/unit.c
c2dfb7
@@ -4161,14 +4161,20 @@ int unit_patch_contexts(Unit *u) {
c2dfb7
                                         return -ENOMEM;
c2dfb7
                         }
c2dfb7
 
c2dfb7
-                        /* If the dynamic user option is on, let's make sure that the unit can't leave its UID/GID
c2dfb7
-                         * around in the file system or on IPC objects. Hence enforce a strict sandbox. */
c2dfb7
+                        /* If the dynamic user option is on, let's make sure that the unit can't leave its
c2dfb7
+                         * UID/GID around in the file system or on IPC objects. Hence enforce a strict
c2dfb7
+                         * sandbox. */
c2dfb7
 
c2dfb7
                         ec->private_tmp = true;
c2dfb7
                         ec->remove_ipc = true;
c2dfb7
                         ec->protect_system = PROTECT_SYSTEM_STRICT;
c2dfb7
                         if (ec->protect_home == PROTECT_HOME_NO)
c2dfb7
                                 ec->protect_home = PROTECT_HOME_READ_ONLY;
c2dfb7
+
c2dfb7
+                        /* Make sure this service can neither benefit from SUID/SGID binaries nor create
c2dfb7
+                         * them. */
c2dfb7
+                        ec->no_new_privileges = true;
c2dfb7
+                        ec->restrict_suid_sgid = true;
c2dfb7
                 }
c2dfb7
         }
c2dfb7