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)
This commit is contained in:
LinkTed 2022-01-03 20:30:46 +02:00 committed by Mike Frysinger
parent 79e5edc1a3
commit 8115f3274e
6 changed files with 48 additions and 0 deletions

View File

@ -168,6 +168,8 @@ The format is the same as in cap_iab(3).
Set the security-bits for the program. Set the security-bits for the program.
The numeric value of the security-bits can be found in <sys/secbits.h> header file. The numeric value of the security-bits can be found in <sys/secbits.h> header file.
The format is the same as in strtoul(3). 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 .It Fl w , -wait Ar milliseconds
Wait Wait
.Ar milliseconds .Ar milliseconds

View File

@ -165,6 +165,8 @@ The format is the same as in cap_iab(3).
Set the security-bits for the program. Set the security-bits for the program.
The numeric value of the security-bits can be found in <sys/secbits.h> header file. The numeric value of the security-bits can be found in <sys/secbits.h> header file.
The format is the same as in strtoul(3). 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 .El
.Sh ENVIRONMENT .Sh ENVIRONMENT
.Va SSD_IONICELEVEL .Va SSD_IONICELEVEL

View File

@ -55,6 +55,7 @@ ssd_start()
${error_logger_arg} \ ${error_logger_arg} \
${capabilities+--capabilities} "$capabilities" \ ${capabilities+--capabilities} "$capabilities" \
${secbits:+--secbits} "$secbits" \ ${secbits:+--secbits} "$secbits" \
${no_new_privs:+--no-new-privs} \
${procname:+--name} $procname \ ${procname:+--name} $procname \
${pidfile:+--pidfile} $pidfile \ ${pidfile:+--pidfile} $pidfile \
${command_user+--user} $command_user \ ${command_user+--user} $command_user \

View File

@ -38,6 +38,7 @@ supervise_start()
${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \ ${healthcheck_timer:+--healthcheck-timer} $healthcheck_timer \
${capabilities+--capabilities} "$capabilities" \ ${capabilities+--capabilities} "$capabilities" \
${secbits:+--secbits} "$secbits" \ ${secbits:+--secbits} "$secbits" \
${no_new_privs:+--no_new_privs} \
${command_user+--user} $command_user \ ${command_user+--user} $command_user \
${umask+--umask} $umask \ ${umask+--umask} $umask \
${supervise_daemon_args:-${start_stop_daemon_args}} \ ${supervise_daemon_args:-${start_stop_daemon_args}} \

View File

@ -31,6 +31,7 @@
#ifdef __linux__ #ifdef __linux__
#include <sys/syscall.h> /* For io priority */ #include <sys/syscall.h> /* For io priority */
#include <sys/prctl.h> /* For prctl */
#endif #endif
#include <ctype.h> #include <ctype.h>
@ -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[] = { const struct option longopts[] = {
{ "capabilities", 1, NULL, 0x100}, { "capabilities", 1, NULL, 0x100},
{ "secbits", 1, NULL, 0x101}, { "secbits", 1, NULL, 0x101},
{ "no-new-privs", 0, NULL, 0x102},
{ "ionice", 1, NULL, 'I'}, { "ionice", 1, NULL, 'I'},
{ "stop", 0, NULL, 'K'}, { "stop", 0, NULL, 'K'},
{ "nicelevel", 1, NULL, 'N'}, { "nicelevel", 1, NULL, 'N'},
@ -109,6 +111,7 @@ const struct option longopts[] = {
const char * const longopts_help[] = { const char * const longopts_help[] = {
"Set the inheritable, ambient and bounding capabilities", "Set the inheritable, ambient and bounding capabilities",
"Set the security-bits for the program", "Set the security-bits for the program",
"Set the No New Privs flag for the program",
"Set an ionice class:data when starting", "Set an ionice class:data when starting",
"Stop daemon", "Stop daemon",
"Set a nicelevel when starting", "Set a nicelevel when starting",
@ -319,6 +322,9 @@ int main(int argc, char **argv)
cap_iab_t cap_iab = NULL; cap_iab_t cap_iab = NULL;
unsigned secbits = 0; unsigned secbits = 0;
#endif #endif
#ifdef PR_SET_NO_NEW_PRIVS
bool no_new_privs = false;
#endif
applet = basename_c(argv[0]); applet = basename_c(argv[0]);
atexit(cleanup); atexit(cleanup);
@ -389,6 +395,13 @@ int main(int argc, char **argv)
#endif #endif
break; 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 */ case 'I': /* --ionice */
if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0) if (sscanf(optarg, "%d:%d", &ionicec, &ioniced) == 0)
@ -915,6 +928,14 @@ int main(int argc, char **argv)
} }
#endif #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 #ifdef TIOCNOTTY
ioctl(tty_fd, TIOCNOTTY, 0); ioctl(tty_fd, TIOCNOTTY, 0);
close(tty_fd); close(tty_fd);

View File

@ -32,6 +32,7 @@
#ifdef __linux__ #ifdef __linux__
#include <sys/syscall.h> /* For io priority */ #include <sys/syscall.h> /* For io priority */
#include <sys/prctl.h> /* For prctl */
#endif #endif
#include <ctype.h> #include <ctype.h>
@ -79,6 +80,7 @@ const struct option longopts[] = {
{ "healthcheck-delay", 1, NULL, 'A'}, { "healthcheck-delay", 1, NULL, 'A'},
{ "capabilities", 1, NULL, 0x100}, { "capabilities", 1, NULL, 0x100},
{ "secbits", 1, NULL, 0x101}, { "secbits", 1, NULL, 0x101},
{ "no-new-privs", 0, NULL, 0x102},
{ "respawn-delay", 1, NULL, 'D'}, { "respawn-delay", 1, NULL, 'D'},
{ "chdir", 1, NULL, 'd'}, { "chdir", 1, NULL, 'd'},
{ "env", 1, NULL, 'e'}, { "env", 1, NULL, 'e'},
@ -106,6 +108,7 @@ const char * const longopts_help[] = {
"set a health check timer", "set a health check timer",
"Set the inheritable, ambient and bounding capabilities", "Set the inheritable, ambient and bounding capabilities",
"Set the security-bits for the program", "Set the security-bits for the program",
"Set the No New Privs flag for the program",
"Set a respawn delay", "Set a respawn delay",
"Change the PWD", "Change the PWD",
"Set an environment string", "Set an environment string",
@ -164,6 +167,9 @@ static bool verbose = false;
static cap_iab_t cap_iab = NULL; static cap_iab_t cap_iab = NULL;
static unsigned secbits = 0; static unsigned secbits = 0;
#endif #endif
#ifdef PR_SET_NO_NEW_PRIVS
static bool no_new_privs = false;
#endif
extern char **environ; extern char **environ;
@ -437,6 +443,13 @@ static void child_process(char *exec, char **argv)
} }
#endif #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 */ /* remove the controlling tty */
#ifdef TIOCNOTTY #ifdef TIOCNOTTY
ioctl(tty_fd, TIOCNOTTY, 0); ioctl(tty_fd, TIOCNOTTY, 0);
@ -854,6 +867,14 @@ int main(int argc, char **argv)
#endif #endif
break; 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 */ case 'D': /* --respawn-delay time */
n = sscanf(optarg, "%d", &respawn_delay); n = sscanf(optarg, "%d", &respawn_delay);
if (n != 1 || respawn_delay < 1) if (n != 1 || respawn_delay < 1)