aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2020-12-28 21:06:52 +0100
committerLibravatar smitsohu <smitsohu@gmail.com>2020-12-29 23:47:05 +0100
commit4df931507606a0a1ee2d0e916d027d01c801d926 (patch)
tree73f0e2b5eefdc2471ec2c446970edfc1dc299f6d /src
parentNew profiles for alacarte,tootle,photoflare (#3816) (diff)
downloadfirejail-4df931507606a0a1ee2d0e916d027d01c801d926.tar.gz
firejail-4df931507606a0a1ee2d0e916d027d01c801d926.tar.zst
firejail-4df931507606a0a1ee2d0e916d027d01c801d926.zip
join: add fexecve fallback for shells
Allows users to join a sandbox and get a shell even if there is none in the sandbox mount namespace. There are few limitations: 1. This will fail with scripted shells (see man 3 fexecve for an explanation) 2. Shell process names are not user friendly
Diffstat (limited to 'src')
-rw-r--r--src/firejail/firejail.h2
-rw-r--r--src/firejail/join.c32
-rw-r--r--src/firejail/main.c2
-rw-r--r--src/firejail/no_sandbox.c4
-rw-r--r--src/firejail/sandbox.c41
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'
374int sandbox(void* sandbox_arg); 374int sandbox(void* sandbox_arg);
375void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn)); 375void start_application(int no_sandbox, int fd, char *set_sandbox_status) __attribute__((noreturn));
376void set_apparmor(void); 376void 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
306static 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
304bool is_ready_for_join(const pid_t pid) { 323bool 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 b8ed29ece..213d5c014 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -2786,7 +2786,7 @@ int main(int argc, char **argv, char **envp) {
2786 2786
2787 // build the sandbox command 2787 // build the sandbox command
2788 if (prog_index == -1 && cfg.shell) { 2788 if (prog_index == -1 && cfg.shell) {
2789 cfg.command_line = cfg.shell; 2789 assert(cfg.command_line == NULL); // runs cfg.shell
2790 cfg.window_title = cfg.shell; 2790 cfg.window_title = cfg.shell;
2791 cfg.command_name = cfg.shell; 2791 cfg.command_name = cfg.shell;
2792 } 2792 }
diff --git a/src/firejail/no_sandbox.c b/src/firejail/no_sandbox.c
index 01df77ee6..22f36ef07 100644
--- a/src/firejail/no_sandbox.c
+++ b/src/firejail/no_sandbox.c
@@ -211,7 +211,7 @@ void run_no_sandbox(int argc, char **argv) {
211 } 211 }
212 212
213 if (prog_index == 0) { 213 if (prog_index == 0) {
214 cfg.command_line = cfg.shell; 214 assert(cfg.command_line == NULL); // runs cfg.shell
215 cfg.window_title = cfg.shell; 215 cfg.window_title = cfg.shell;
216 } else { 216 } else {
217 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index); 217 build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
@@ -230,5 +230,5 @@ void run_no_sandbox(int argc, char **argv) {
230 230
231 arg_quiet = 1; 231 arg_quiet = 1;
232 232
233 start_application(1, NULL); 233 start_application(1, -1, NULL);
234} 234}
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 5c7b5e556..991e5b2f2 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
464void start_application(int no_sandbox, char *set_sandbox_status) { 464void 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
589static void enforce_filters(void) { 592static 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);