From 8115f3274eab06743603aec502ae311e3bf0724b Mon Sep 17 00:00:00 2001 From: LinkTed Date: Mon, 3 Jan 2022 20:30:46 +0200 Subject: [PATCH] linux: Add support for No New Privs flag This add No New Privs flag for start-stop-daemon and supervise-daemon by adding --no-new-privs flag. As a result, the user set the No New Privs flag for the program should run with. see PR_SET_NO_NEW_PRIVS prctl(2) --- man/start-stop-daemon.8 | 2 ++ man/supervise-daemon.8 | 2 ++ sh/start-stop-daemon.sh | 1 + sh/supervise-daemon.sh | 1 + src/rc/start-stop-daemon.c | 21 +++++++++++++++++++++ src/rc/supervise-daemon.c | 21 +++++++++++++++++++++ 6 files changed, 48 insertions(+) diff --git a/man/start-stop-daemon.8 b/man/start-stop-daemon.8 index aedbd0cb..257cad70 100644 --- a/man/start-stop-daemon.8 +++ b/man/start-stop-daemon.8 @@ -168,6 +168,8 @@ The format is the same as in cap_iab(3). Set the security-bits for the program. The numeric value of the security-bits can be found in header file. The format is the same as in strtoul(3). +.It Fl -no-new-privs +Set the No New Privs flag for the program. See PR_SET_NO_NEW_PRIVS prctl(2). .It Fl w , -wait Ar milliseconds Wait .Ar milliseconds diff --git a/man/supervise-daemon.8 b/man/supervise-daemon.8 index 799a791a..dcefe2ee 100644 --- a/man/supervise-daemon.8 +++ b/man/supervise-daemon.8 @@ -165,6 +165,8 @@ The format is the same as in cap_iab(3). Set the security-bits for the program. The numeric value of the security-bits can be found in header file. The format is the same as in strtoul(3). +.It Fl -no-new-privs +Set the No New Privs flag for the program. See PR_SET_NO_NEW_PRIVS prctl(2). .El .Sh ENVIRONMENT .Va SSD_IONICELEVEL diff --git a/sh/start-stop-daemon.sh b/sh/start-stop-daemon.sh index bbb4da37..3c2fd32f 100644 --- a/sh/start-stop-daemon.sh +++ b/sh/start-stop-daemon.sh @@ -55,6 +55,7 @@ ssd_start() ${error_logger_arg} \ ${capabilities+--capabilities} "$capabilities" \ ${secbits:+--secbits} "$secbits" \ + ${no_new_privs:+--no-new-privs} \ ${procname:+--name} $procname \ ${pidfile:+--pidfile} $pidfile \ ${command_user+--user} $command_user \ diff --git a/sh/supervise-daemon.sh b/sh/supervise-daemon.sh index 39fe5727..8d2d6faf 100644 --- a/sh/supervise-daemon.sh +++ b/sh/supervise-daemon.sh @@ -38,6 +38,7 @@ supervise_start() ${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \ ${capabilities+--capabilities} "$capabilities" \ ${secbits:+--secbits} "$secbits" \ + ${no_new_privs:+--no_new_privs} \ ${command_user+--user} $command_user \ ${umask+--umask} $umask \ ${supervise_daemon_args:-${start_stop_daemon_args}} \ diff --git a/src/rc/start-stop-daemon.c b/src/rc/start-stop-daemon.c index e1a520f5..007a9309 100644 --- a/src/rc/start-stop-daemon.c +++ b/src/rc/start-stop-daemon.c @@ -31,6 +31,7 @@ #ifdef __linux__ #include /* For io priority */ +#include /* For prctl */ #endif #include @@ -75,6 +76,7 @@ const char getoptstring[] = "I:KN:PR:Sa:bc:d:e:g:ik:mn:op:s:tu:r:w:x:1:2:3:4:" \ const struct option longopts[] = { { "capabilities", 1, NULL, 0x100}, { "secbits", 1, NULL, 0x101}, + { "no-new-privs", 0, NULL, 0x102}, { "ionice", 1, NULL, 'I'}, { "stop", 0, NULL, 'K'}, { "nicelevel", 1, NULL, 'N'}, @@ -109,6 +111,7 @@ const struct option longopts[] = { const char * const longopts_help[] = { "Set the inheritable, ambient and bounding capabilities", "Set the security-bits for the program", + "Set the No New Privs flag for the program", "Set an ionice class:data when starting", "Stop daemon", "Set a nicelevel when starting", @@ -319,6 +322,9 @@ int main(int argc, char **argv) cap_iab_t cap_iab = NULL; unsigned secbits = 0; #endif +#ifdef PR_SET_NO_NEW_PRIVS + bool no_new_privs = false; +#endif applet = basename_c(argv[0]); atexit(cleanup); @@ -389,6 +395,13 @@ int main(int argc, char **argv) #endif break; + case 0x102: +#ifdef PR_SET_NO_NEW_PRIVS + no_new_privs = true; +#else + eerrorx("The No New Privs flag is only supported by Linux (since 3.5)"); +#endif + break; case 'I': /* --ionice */ if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0) @@ -915,6 +928,14 @@ int main(int argc, char **argv) } #endif +#ifdef PR_SET_NO_NEW_PRIVS + if (no_new_privs) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) + eerrorx("Could not set No New Privs flag: %s", strerror(errno)); + } +#endif + + #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); close(tty_fd); diff --git a/src/rc/supervise-daemon.c b/src/rc/supervise-daemon.c index 5c5c01fc..85d5efbb 100644 --- a/src/rc/supervise-daemon.c +++ b/src/rc/supervise-daemon.c @@ -32,6 +32,7 @@ #ifdef __linux__ #include /* For io priority */ +#include /* For prctl */ #endif #include @@ -79,6 +80,7 @@ const struct option longopts[] = { { "healthcheck-delay", 1, NULL, 'A'}, { "capabilities", 1, NULL, 0x100}, { "secbits", 1, NULL, 0x101}, + { "no-new-privs", 0, NULL, 0x102}, { "respawn-delay", 1, NULL, 'D'}, { "chdir", 1, NULL, 'd'}, { "env", 1, NULL, 'e'}, @@ -106,6 +108,7 @@ const char * const longopts_help[] = { "set a health check timer", "Set the inheritable, ambient and bounding capabilities", "Set the security-bits for the program", + "Set the No New Privs flag for the program", "Set a respawn delay", "Change the PWD", "Set an environment string", @@ -164,6 +167,9 @@ static bool verbose = false; static cap_iab_t cap_iab = NULL; static unsigned secbits = 0; #endif +#ifdef PR_SET_NO_NEW_PRIVS +static bool no_new_privs = false; +#endif extern char **environ; @@ -437,6 +443,13 @@ static void child_process(char *exec, char **argv) } #endif +#ifdef PR_SET_NO_NEW_PRIVS + if (no_new_privs) { + if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) == -1) + eerrorx("Could not set No New Privs flag: %s", strerror(errno)); + } +#endif + /* remove the controlling tty */ #ifdef TIOCNOTTY ioctl(tty_fd, TIOCNOTTY, 0); @@ -854,6 +867,14 @@ int main(int argc, char **argv) #endif break; + case 0x102: +#ifdef PR_SET_NO_NEW_PRIVS + no_new_privs = true; +#else + eerrorx("The No New Privs flag is only supported by Linux (since 3.5)"); +#endif + break; + case 'D': /* --respawn-delay time */ n = sscanf(optarg, "%d", &respawn_delay); if (n != 1 || respawn_delay < 1)