main: add NoNewPrivileges config option (#8475)
authorjuergbi <j@bitron.ch>
Wed, 21 Mar 2018 22:41:19 +0000 (23:41 +0100)
committerLennart Poettering <lennart@poettering.net>
Wed, 21 Mar 2018 22:41:19 +0000 (23:41 +0100)
This makes it possible to disable new privileges for the whole system.

man/systemd-system.conf.xml
src/core/main.c
src/core/system.conf.in
test/fuzz-corpus/unit-file/directives.service

index fca9690..5a308f2 100644 (file)
       </varlistentry>
 
       <varlistentry>
+        <term><varname>NoNewPrivileges=</varname></term>
+
+        <listitem><para>Takes a boolean argument. If true, ensures that PID 1
+        and all its children can never gain new privileges through
+        <citerefentry project='man-pages'><refentrytitle>execve</refentrytitle><manvolnum>2</manvolnum></citerefentry>
+        (e.g. via setuid or setgid bits, or filesystem capabilities).
+        Defaults to false. General purpose distributions commonly rely
+        on executables with setuid or setgid bits and will thus not
+        function properly with this option enabled. Individual units
+        cannot disable this option.
+        Also see <ulink url="https://www.kernel.org/doc/html/latest/userspace-api/no_new_privs.html">No New Privileges Flag</ulink>.
+        </para></listitem>
+      </varlistentry>
+
+      <varlistentry>
         <term><varname>SystemCallArchitectures=</varname></term>
 
         <listitem><para>Takes a space-separated list of architecture
index a4d2cdf..7ee3faa 100644 (file)
@@ -127,6 +127,7 @@ static char *arg_watchdog_device = NULL;
 static char **arg_default_environment = NULL;
 static struct rlimit *arg_default_rlimit[_RLIMIT_MAX] = {};
 static uint64_t arg_capability_bounding_set = CAP_ALL;
+static bool arg_no_new_privs = false;
 static nsec_t arg_timer_slack_nsec = NSEC_INFINITY;
 static usec_t arg_default_timer_accuracy_usec = 1 * USEC_PER_MINUTE;
 static Set* arg_syscall_archs = NULL;
@@ -671,6 +672,7 @@ static int parse_config_file(void) {
                 { "Manager", "ShutdownWatchdogSec",       config_parse_sec,              0, &arg_shutdown_watchdog                 },
                 { "Manager", "WatchdogDevice",            config_parse_path,             0, &arg_watchdog_device                   },
                 { "Manager", "CapabilityBoundingSet",     config_parse_capability_set,   0, &arg_capability_bounding_set           },
+                { "Manager", "NoNewPrivileges",           config_parse_bool,             0, &arg_no_new_privs                      },
 #if HAVE_SECCOMP
                 { "Manager", "SystemCallArchitectures",   config_parse_syscall_archs,    0, &arg_syscall_archs                     },
 #endif
@@ -1865,6 +1867,13 @@ static int initialize_runtime(
                 }
         }
 
+        if (arg_system && arg_no_new_privs) {
+                if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) < 0) {
+                        *ret_error_message = "Failed to disable new privileges";
+                        return log_emergency_errno(errno, "Failed to disable new privileges: %m");
+                }
+        }
+
         if (arg_syscall_archs) {
                 r = enforce_syscall_archs(arg_syscall_archs);
                 if (r < 0) {
index 08cbe52..f0a59a7 100644 (file)
@@ -27,6 +27,7 @@
 #RuntimeWatchdogSec=0
 #ShutdownWatchdogSec=10min
 #CapabilityBoundingSet=
+#NoNewPrivileges=no
 #SystemCallArchitectures=
 #TimerSlackNSec=
 #DefaultTimerAccuracySec=1min
index 0077ae7..c2334d3 100644 (file)
@@ -809,6 +809,7 @@ MountFlags=
 NAME=
 NAutoVTs=
 Nice=
+NoNewPrivileges=
 NotifyReady=
 OOMScoreAdjust=
 Overlay=