diff options
author | netblue30 <netblue30@protonmail.com> | 2020-12-30 08:41:54 -0500 |
---|---|---|
committer | GitHub <noreply@github.com> | 2020-12-30 08:41:54 -0500 |
commit | 98a87e6b535526a2efc7a2cb6ca3fe5d32f2b3d8 (patch) | |
tree | ab217878b74413d5fa11bd3f977c718f06baf6b2 | |
parent | Merge pull request #3852 from rusty-snake/fix-3846 (diff) | |
parent | join: add fexecve fallback for shells (diff) | |
download | firejail-98a87e6b535526a2efc7a2cb6ca3fe5d32f2b3d8.tar.gz firejail-98a87e6b535526a2efc7a2cb6ca3fe5d32f2b3d8.tar.zst firejail-98a87e6b535526a2efc7a2cb6ca3fe5d32f2b3d8.zip |
Merge pull request #3850 from smitsohu/smitsohu-shell
join: add fexecve fallback for shells
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/join.c | 32 | ||||
-rw-r--r-- | src/firejail/main.c | 2 | ||||
-rw-r--r-- | src/firejail/no_sandbox.c | 4 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 41 |
5 files changed, 54 insertions, 27 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 6c0ebcd43..80987e494 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -372,7 +372,7 @@ char *guess_shell(void); | |||
372 | // sandbox.c | 372 | // sandbox.c |
373 | #define SANDBOX_DONE '1' | 373 | #define SANDBOX_DONE '1' |
374 | int sandbox(void* sandbox_arg); | 374 | int sandbox(void* sandbox_arg); |
375 | void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn)); | 375 | void start_application(int no_sandbox, int fd, char *set_sandbox_status) __attribute__((noreturn)); |
376 | void set_apparmor(void); | 376 | void set_apparmor(void); |
377 | 377 | ||
378 | // network_main.c | 378 | // network_main.c |
diff --git a/src/firejail/join.c b/src/firejail/join.c index ca8b8c4bf..d2f802add 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c | |||
@@ -20,10 +20,14 @@ | |||
20 | #include "firejail.h" | 20 | #include "firejail.h" |
21 | #include <sys/stat.h> | 21 | #include <sys/stat.h> |
22 | #include <sys/wait.h> | 22 | #include <sys/wait.h> |
23 | #include <fcntl.h> | ||
24 | #include <unistd.h> | 23 | #include <unistd.h> |
25 | #include <errno.h> | 24 | #include <errno.h> |
26 | 25 | ||
26 | #include <fcntl.h> | ||
27 | #ifndef O_PATH | ||
28 | #define O_PATH 010000000 | ||
29 | #endif | ||
30 | |||
27 | #include <sys/prctl.h> | 31 | #include <sys/prctl.h> |
28 | #ifndef PR_SET_NO_NEW_PRIVS | 32 | #ifndef PR_SET_NO_NEW_PRIVS |
29 | #define PR_SET_NO_NEW_PRIVS 38 | 33 | #define PR_SET_NO_NEW_PRIVS 38 |
@@ -299,6 +303,21 @@ static void extract_umask(pid_t pid) { | |||
299 | fclose(fp); | 303 | fclose(fp); |
300 | } | 304 | } |
301 | 305 | ||
306 | static int open_shell(void) { | ||
307 | EUID_ASSERT(); | ||
308 | assert(cfg.shell); | ||
309 | |||
310 | if (arg_debug) | ||
311 | printf("Opening shell %s\n", cfg.shell); | ||
312 | // file descriptor will leak if not opened with O_CLOEXEC !! | ||
313 | int fd = open(cfg.shell, O_PATH|O_CLOEXEC); | ||
314 | if (fd == -1) { | ||
315 | fprintf(stderr, "Error: cannot open shell %s\n", cfg.shell); | ||
316 | exit(1); | ||
317 | } | ||
318 | return fd; | ||
319 | } | ||
320 | |||
302 | // return false if the sandbox identified by pid is not fully set up yet or if | 321 | // return false if the sandbox identified by pid is not fully set up yet or if |
303 | // it is no firejail sandbox at all, return true if the sandbox is complete | 322 | // it is no firejail sandbox at all, return true if the sandbox is complete |
304 | bool is_ready_for_join(const pid_t pid) { | 323 | bool is_ready_for_join(const pid_t pid) { |
@@ -391,6 +410,10 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
391 | 410 | ||
392 | extract_x11_display(parent); | 411 | extract_x11_display(parent); |
393 | 412 | ||
413 | int shfd = -1; | ||
414 | if (!arg_shell_none) | ||
415 | shfd = open_shell(); | ||
416 | |||
394 | EUID_ROOT(); | 417 | EUID_ROOT(); |
395 | // in user mode set caps seccomp, cpu, cgroup, etc | 418 | // in user mode set caps seccomp, cpu, cgroup, etc |
396 | if (getuid() != 0) { | 419 | if (getuid() != 0) { |
@@ -522,10 +545,9 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
522 | extract_command(argc, argv, index); | 545 | extract_command(argc, argv, index); |
523 | if (cfg.command_line == NULL) { | 546 | if (cfg.command_line == NULL) { |
524 | assert(cfg.shell); | 547 | assert(cfg.shell); |
525 | cfg.command_line = cfg.shell; | ||
526 | cfg.window_title = cfg.shell; | 548 | cfg.window_title = cfg.shell; |
527 | } | 549 | } |
528 | if (arg_debug) | 550 | else if (arg_debug) |
529 | printf("Extracted command #%s#\n", cfg.command_line); | 551 | printf("Extracted command #%s#\n", cfg.command_line); |
530 | 552 | ||
531 | // set cpu affinity | 553 | // set cpu affinity |
@@ -554,11 +576,13 @@ void join(pid_t pid, int argc, char **argv, int index) { | |||
554 | dbus_set_system_bus_env(); | 576 | dbus_set_system_bus_env(); |
555 | #endif | 577 | #endif |
556 | 578 | ||
557 | start_application(0, NULL); | 579 | start_application(0, shfd, NULL); |
558 | 580 | ||
559 | __builtin_unreachable(); | 581 | __builtin_unreachable(); |
560 | } | 582 | } |
561 | EUID_USER(); | 583 | EUID_USER(); |
584 | if (shfd != -1) | ||
585 | close(shfd); | ||
562 | 586 | ||
563 | int status = 0; | 587 | int status = 0; |
564 | //***************************** | 588 | //***************************** |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 544bfe83a..e5d8a4720 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -2787,7 +2787,7 @@ int main(int argc, char **argv, char **envp) { | |||
2787 | 2787 | ||
2788 | // build the sandbox command | 2788 | // build the sandbox command |
2789 | if (prog_index == -1 && cfg.shell) { | 2789 | if (prog_index == -1 && cfg.shell) { |
2790 | cfg.command_line = cfg.shell; | 2790 | assert(cfg.command_line == NULL); // runs cfg.shell |
2791 | cfg.window_title = cfg.shell; | 2791 | cfg.window_title = cfg.shell; |
2792 | cfg.command_name = cfg.shell; | 2792 | cfg.command_name = cfg.shell; |
2793 | } | 2793 | } |
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c index d7426f6ae..6c7803602 100644 --- a/src/firejail/no_sandbox.c +++ b/src/firejail/no_sandbox.c | |||
@@ -212,7 +212,7 @@ void run_no_sandbox(int argc, char **argv) { | |||
212 | // } | 212 | // } |
213 | 213 | ||
214 | if (prog_index == 0) { | 214 | if (prog_index == 0) { |
215 | cfg.command_line = cfg.shell; | 215 | assert(cfg.command_line == NULL); // runs cfg.shell |
216 | cfg.window_title = cfg.shell; | 216 | cfg.window_title = cfg.shell; |
217 | } else { | 217 | } else { |
218 | build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); | 218 | build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); |
@@ -231,5 +231,5 @@ void run_no_sandbox(int argc, char **argv) { | |||
231 | 231 | ||
232 | arg_quiet = 1; | 232 | arg_quiet = 1; |
233 | 233 | ||
234 | start_application(1, NULL); | 234 | start_application(1, -1, NULL); |
235 | } | 235 | } |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 5115191ea..d811fe45a 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -461,7 +461,7 @@ static int ok_to_run(const char *program) { | |||
461 | return 0; | 461 | return 0; |
462 | } | 462 | } |
463 | 463 | ||
464 | void start_application(int no_sandbox, char *set_sandbox_status) { | 464 | void start_application(int no_sandbox, int fd, char *set_sandbox_status) { |
465 | // set environment | 465 | // set environment |
466 | if (no_sandbox == 0) { | 466 | if (no_sandbox == 0) { |
467 | env_defaults(); | 467 | env_defaults(); |
@@ -471,7 +471,7 @@ void start_application(int no_sandbox, char *set_sandbox_status) { | |||
471 | umask(orig_umask); | 471 | umask(orig_umask); |
472 | 472 | ||
473 | if (arg_debug) { | 473 | if (arg_debug) { |
474 | printf("starting application\n"); | 474 | printf("Starting application\n"); |
475 | printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); | 475 | printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); |
476 | } | 476 | } |
477 | 477 | ||
@@ -488,9 +488,6 @@ void start_application(int no_sandbox, char *set_sandbox_status) { | |||
488 | if (set_sandbox_status) | 488 | if (set_sandbox_status) |
489 | *set_sandbox_status = SANDBOX_DONE; | 489 | *set_sandbox_status = SANDBOX_DONE; |
490 | execl(arg_audit_prog, arg_audit_prog, NULL); | 490 | execl(arg_audit_prog, arg_audit_prog, NULL); |
491 | |||
492 | perror("execl"); | ||
493 | exit(1); | ||
494 | } | 491 | } |
495 | //**************************************** | 492 | //**************************************** |
496 | // start the program without using a shell | 493 | // start the program without using a shell |
@@ -532,35 +529,37 @@ void start_application(int no_sandbox, char *set_sandbox_status) { | |||
532 | //**************************************** | 529 | //**************************************** |
533 | else { | 530 | else { |
534 | assert(cfg.shell); | 531 | assert(cfg.shell); |
535 | assert(cfg.command_line); | ||
536 | 532 | ||
537 | char *arg[5]; | 533 | char *arg[5]; |
538 | int index = 0; | 534 | int index = 0; |
539 | arg[index++] = cfg.shell; | 535 | arg[index++] = cfg.shell; |
540 | if (login_shell) { | 536 | if (cfg.command_line) { |
541 | arg[index++] = "-l"; | ||
542 | if (arg_debug) | ||
543 | printf("Starting %s login shell\n", cfg.shell); | ||
544 | } else { | ||
545 | arg[index++] = "-c"; | ||
546 | if (arg_debug) | 537 | if (arg_debug) |
547 | printf("Running %s command through %s\n", cfg.command_line, cfg.shell); | 538 | printf("Running %s command through %s\n", cfg.command_line, cfg.shell); |
539 | arg[index++] = "-c"; | ||
548 | if (arg_doubledash) | 540 | if (arg_doubledash) |
549 | arg[index++] = "--"; | 541 | arg[index++] = "--"; |
550 | arg[index++] = cfg.command_line; | 542 | arg[index++] = cfg.command_line; |
551 | } | 543 | } |
552 | arg[index] = NULL; | 544 | else if (login_shell) { |
545 | if (arg_debug) | ||
546 | printf("Starting %s login shell\n", cfg.shell); | ||
547 | arg[index++] = "-l"; | ||
548 | } | ||
549 | else if (arg_debug) | ||
550 | printf("Starting %s shell\n", cfg.shell); | ||
551 | |||
553 | assert(index < 5); | 552 | assert(index < 5); |
553 | arg[index] = NULL; | ||
554 | 554 | ||
555 | if (arg_debug) { | 555 | if (arg_debug) { |
556 | char *msg; | 556 | char *msg; |
557 | if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) | 557 | if (asprintf(&msg, "sandbox %d, execvp into %s", |
558 | sandbox_pid, cfg.command_line ? cfg.command_line : cfg.shell) == -1) | ||
558 | errExit("asprintf"); | 559 | errExit("asprintf"); |
559 | logmsg(msg); | 560 | logmsg(msg); |
560 | free(msg); | 561 | free(msg); |
561 | } | ||
562 | 562 | ||
563 | if (arg_debug) { | ||
564 | int i; | 563 | int i; |
565 | for (i = 0; i < 5; i++) { | 564 | for (i = 0; i < 5; i++) { |
566 | if (arg[i] == NULL) | 565 | if (arg[i] == NULL) |
@@ -580,10 +579,14 @@ void start_application(int no_sandbox, char *set_sandbox_status) { | |||
580 | if (set_sandbox_status) | 579 | if (set_sandbox_status) |
581 | *set_sandbox_status = SANDBOX_DONE; | 580 | *set_sandbox_status = SANDBOX_DONE; |
582 | execvp(arg[0], arg); | 581 | execvp(arg[0], arg); |
582 | |||
583 | // join sandbox without shell in the mount namespace | ||
584 | if (fd > -1) | ||
585 | fexecve(fd, arg, environ); | ||
583 | } | 586 | } |
584 | 587 | ||
585 | perror("execvp"); | 588 | perror("Cannot start application"); |
586 | exit(1); // it should never get here!!! | 589 | exit(1); |
587 | } | 590 | } |
588 | 591 | ||
589 | static void enforce_filters(void) { | 592 | static void enforce_filters(void) { |
@@ -1223,7 +1226,7 @@ int sandbox(void* sandbox_arg) { | |||
1223 | set_nice(cfg.nice); | 1226 | set_nice(cfg.nice); |
1224 | set_rlimits(); | 1227 | set_rlimits(); |
1225 | 1228 | ||
1226 | start_application(0, set_sandbox_status); | 1229 | start_application(0, -1, set_sandbox_status); |
1227 | } | 1230 | } |
1228 | 1231 | ||
1229 | munmap(set_sandbox_status, 1); | 1232 | munmap(set_sandbox_status, 1); |