diff --git a/man/systemd-system.conf.xml b/man/systemd-system.conf.xml
index fca9690092..5a308f275e 100644
--- a/man/systemd-system.conf.xml
+++ b/man/systemd-system.conf.xml
@@ -215,6 +215,21 @@
good.
+
+ NoNewPrivileges=
+
+ Takes a boolean argument. If true, ensures that PID 1
+ and all its children can never gain new privileges through
+ execve2
+ (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 No New Privileges Flag.
+
+
+
SystemCallArchitectures=
diff --git a/src/core/main.c b/src/core/main.c
index a4d2cdf759..7ee3faabf4 100644
--- a/src/core/main.c
+++ b/src/core/main.c
@@ -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) {
diff --git a/src/core/system.conf.in b/src/core/system.conf.in
index 08cbe529ba..f0a59a79a5 100644
--- a/src/core/system.conf.in
+++ b/src/core/system.conf.in
@@ -27,6 +27,7 @@
#RuntimeWatchdogSec=0
#ShutdownWatchdogSec=10min
#CapabilityBoundingSet=
+#NoNewPrivileges=no
#SystemCallArchitectures=
#TimerSlackNSec=
#DefaultTimerAccuracySec=1min
diff --git a/test/fuzz-corpus/unit-file/directives.service b/test/fuzz-corpus/unit-file/directives.service
index 0077ae739b..c2334d3b19 100644
--- a/test/fuzz-corpus/unit-file/directives.service
+++ b/test/fuzz-corpus/unit-file/directives.service
@@ -809,6 +809,7 @@ MountFlags=
NAME=
NAutoVTs=
Nice=
+NoNewPrivileges=
NotifyReady=
OOMScoreAdjust=
Overlay=