diff options
author | 2022-07-23 13:58:33 +0200 | |
---|---|---|
committer | 2022-07-24 20:39:23 +0200 | |
commit | 2cfd4dafc55117795970dc0c1f5655dbbd4588bd (patch) | |
tree | ca49a3cdd835ae3734a47ff41daa58988b3a48be | |
parent | build(deps): bump github/codeql-action from 2.1.15 to 2.1.16 (diff) | |
download | firejail-2cfd4dafc55117795970dc0c1f5655dbbd4588bd.tar.gz firejail-2cfd4dafc55117795970dc0c1f5655dbbd4588bd.tar.zst firejail-2cfd4dafc55117795970dc0c1f5655dbbd4588bd.zip |
improve force-nonewprivs security guarantees
-rw-r--r-- | src/firejail/join.c | 22 | ||||
-rw-r--r-- | src/firejail/main.c | 3 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 27 |
3 files changed, 26 insertions, 26 deletions
diff --git a/src/firejail/join.c b/src/firejail/join.c index 4e636ca27..96d891a49 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -133,6 +133,8 @@ static void extract_nogroups(ProcessHandle sandbox) { | |||
133 | 133 | ||
134 | if (process_rootfs_stat(sandbox, RUN_GROUPS_CFG, &s) == 0) | 134 | if (process_rootfs_stat(sandbox, RUN_GROUPS_CFG, &s) == 0) |
135 | arg_nogroups = 1; | 135 | arg_nogroups = 1; |
136 | else if (errno != ENOENT) | ||
137 | errExit("stat"); | ||
136 | } | 138 | } |
137 | 139 | ||
138 | static void extract_nonewprivs(ProcessHandle sandbox) { | 140 | static void extract_nonewprivs(ProcessHandle sandbox) { |
@@ -140,6 +142,8 @@ static void extract_nonewprivs(ProcessHandle sandbox) { | |||
140 | 142 | ||
141 | if (process_rootfs_stat(sandbox, RUN_NONEWPRIVS_CFG, &s) == 0) | 143 | if (process_rootfs_stat(sandbox, RUN_NONEWPRIVS_CFG, &s) == 0) |
142 | arg_nonewprivs = 1; | 144 | arg_nonewprivs = 1; |
145 | else if (errno != ENOENT) | ||
146 | errExit("stat"); | ||
143 | } | 147 | } |
144 | 148 | ||
145 | static void extract_caps(ProcessHandle sandbox) { | 149 | static void extract_caps(ProcessHandle sandbox) { |
@@ -477,13 +481,6 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
477 | EUID_USER(); | 481 | EUID_USER(); |
478 | unpin_process(sandbox); | 482 | unpin_process(sandbox); |
479 | 483 | ||
480 | // set nonewprivs | ||
481 | if (arg_nonewprivs == 1) { // not available for uid 0 | ||
482 | int rv = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | ||
483 | if (arg_debug && rv == 0) | ||
484 | printf("NO_NEW_PRIVS set\n"); | ||
485 | } | ||
486 | |||
487 | int cwd = 0; | 484 | int cwd = 0; |
488 | if (cfg.cwd) { | 485 | if (cfg.cwd) { |
489 | if (chdir(cfg.cwd) == 0) | 486 | if (chdir(cfg.cwd) == 0) |
@@ -503,6 +500,17 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
503 | } | 500 | } |
504 | } | 501 | } |
505 | 502 | ||
503 | // set nonewprivs | ||
504 | #ifndef HAVE_FORCE_NONEWPRIVS | ||
505 | if (arg_nonewprivs == 1) // not available for uid 0 | ||
506 | #endif | ||
507 | { | ||
508 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) | ||
509 | errExit("prctl"); | ||
510 | if (arg_debug) | ||
511 | printf("NO_NEW_PRIVS set\n"); | ||
512 | } | ||
513 | |||
506 | // drop privileges | 514 | // drop privileges |
507 | drop_privs(arg_nogroups); | 515 | drop_privs(arg_nogroups); |
508 | 516 | ||
diff --git a/src/firejail/main.c b/src/firejail/main.c index ff88b9f6e..e6c5b50b0 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1239,7 +1239,8 @@ int main(int argc, char **argv, char **envp) { | |||
1239 | if (check_arg(argc, argv, "--appimage", 1)) | 1239 | if (check_arg(argc, argv, "--appimage", 1)) |
1240 | arg_appimage = 1; | 1240 | arg_appimage = 1; |
1241 | 1241 | ||
1242 | // check for force-nonewprivs in /etc/firejail/firejail.config file | 1242 | // load configuration file /etc/firejail/firejail.config |
1243 | // and check for force-nonewprivs | ||
1243 | if (checkcfg(CFG_FORCE_NONEWPRIVS)) | 1244 | if (checkcfg(CFG_FORCE_NONEWPRIVS)) |
1244 | arg_nonewprivs = 1; | 1245 | arg_nonewprivs = 1; |
1245 | 1246 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index e72b03e15..864236824 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -50,7 +50,6 @@ | |||
50 | #include <sys/apparmor.h> | 50 | #include <sys/apparmor.h> |
51 | #endif | 51 | #endif |
52 | 52 | ||
53 | static int force_nonewprivs = 0; | ||
54 | extern int just_run_the_shell; | 53 | extern int just_run_the_shell; |
55 | 54 | ||
56 | static int monitored_pid = 0; | 55 | static int monitored_pid = 0; |
@@ -629,7 +628,6 @@ static void enforce_filters(void) { | |||
629 | fmessage("\n** Warning: dropping all Linux capabilities and setting NO_NEW_PRIVS prctl **\n\n"); | 628 | fmessage("\n** Warning: dropping all Linux capabilities and setting NO_NEW_PRIVS prctl **\n\n"); |
630 | // enforce NO_NEW_PRIVS | 629 | // enforce NO_NEW_PRIVS |
631 | arg_nonewprivs = 1; | 630 | arg_nonewprivs = 1; |
632 | force_nonewprivs = 1; | ||
633 | 631 | ||
634 | // disable all capabilities | 632 | // disable all capabilities |
635 | arg_caps_drop_all = 1; | 633 | arg_caps_drop_all = 1; |
@@ -832,14 +830,9 @@ int sandbox(void* sandbox_arg) { | |||
832 | exit(rv); | 830 | exit(rv); |
833 | } | 831 | } |
834 | 832 | ||
835 | #ifdef HAVE_FORCE_NONEWPRIVS | ||
836 | bool always_enforce_filters = true; | ||
837 | #else | ||
838 | bool always_enforce_filters = false; | ||
839 | #endif | ||
840 | // for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS | 833 | // for --appimage, --chroot and --overlay* we force NO_NEW_PRIVS |
841 | // and drop all capabilities | 834 | // and drop all capabilities |
842 | if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay || always_enforce_filters)) | 835 | if (getuid() != 0 && (arg_appimage || cfg.chrootdir || arg_overlay)) |
843 | enforce_filters(); | 836 | enforce_filters(); |
844 | 837 | ||
845 | // need ld.so.preload if tracing or seccomp with any non-default lists | 838 | // need ld.so.preload if tracing or seccomp with any non-default lists |
@@ -1266,17 +1259,15 @@ int sandbox(void* sandbox_arg) { | |||
1266 | //**************************************** | 1259 | //**************************************** |
1267 | // Set NO_NEW_PRIVS if desired | 1260 | // Set NO_NEW_PRIVS if desired |
1268 | //**************************************** | 1261 | //**************************************** |
1269 | if (arg_nonewprivs) { | 1262 | #ifndef HAVE_FORCE_NONEWPRIVS |
1270 | prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); | 1263 | if (arg_nonewprivs) |
1271 | 1264 | #endif | |
1272 | if (prctl(PR_GET_NO_NEW_PRIVS, 0, 0, 0, 0) != 1) { | 1265 | { |
1273 | fwarning("cannot set NO_NEW_PRIVS, it requires a Linux kernel version 3.5 or newer.\n"); | 1266 | if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) != 0) { |
1274 | if (force_nonewprivs) { | 1267 | fprintf(stderr, "Error: cannot set NO_NEW_PRIVS, it requires a Linux kernel version 3.5 or newer.\n"); |
1275 | fprintf(stderr, "Error: NO_NEW_PRIVS required for this sandbox, exiting ...\n"); | 1268 | exit(1); |
1276 | exit(1); | ||
1277 | } | ||
1278 | } | 1269 | } |
1279 | else if (arg_debug) | 1270 | if (arg_debug) |
1280 | printf("NO_NEW_PRIVS set\n"); | 1271 | printf("NO_NEW_PRIVS set\n"); |
1281 | } | 1272 | } |
1282 | 1273 | ||