Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

join: add fexecve fallback for shells #3850

Merged
merged 1 commit into from
Dec 30, 2020
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/firejail/firejail.h
Original file line number Diff line number Diff line change
Expand Up @@ -372,7 +372,7 @@ char *guess_shell(void);
// sandbox.c
#define SANDBOX_DONE '1'
int sandbox(void* sandbox_arg);
void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn));
void start_application(int no_sandbox, int fd, char *set_sandbox_status) __attribute__((noreturn));
void set_apparmor(void);

// network_main.c
Expand Down
32 changes: 28 additions & 4 deletions src/firejail/join.c
Original file line number Diff line number Diff line change
Expand Up @@ -20,10 +20,14 @@
#include "firejail.h"
#include <sys/stat.h>
#include <sys/wait.h>
#include <fcntl.h>
#include <unistd.h>
#include <errno.h>

#include <fcntl.h>
#ifndef O_PATH
#define O_PATH 010000000
#endif

#include <sys/prctl.h>
#ifndef PR_SET_NO_NEW_PRIVS
#define PR_SET_NO_NEW_PRIVS 38
Expand Down Expand Up @@ -299,6 +303,21 @@ static void extract_umask(pid_t pid) {
fclose(fp);
}

static int open_shell(void) {
EUID_ASSERT();
assert(cfg.shell);

if (arg_debug)
printf("Opening shell %s\n", cfg.shell);
// file descriptor will leak if not opened with O_CLOEXEC !!
int fd = open(cfg.shell, O_PATH|O_CLOEXEC);
if (fd == -1) {
fprintf(stderr, "Error: cannot open shell %s\n", cfg.shell);
exit(1);
}
return fd;
}

// return false if the sandbox identified by pid is not fully set up yet or if
// it is no firejail sandbox at all, return true if the sandbox is complete
bool is_ready_for_join(const pid_t pid) {
Expand Down Expand Up @@ -391,6 +410,10 @@ void join(pid_t pid, int argc, char **argv, int index) {

extract_x11_display(parent);

int shfd = -1;
if (!arg_shell_none)
shfd = open_shell();

EUID_ROOT();
// in user mode set caps seccomp, cpu, cgroup, etc
if (getuid() != 0) {
Expand Down Expand Up @@ -522,10 +545,9 @@ void join(pid_t pid, int argc, char **argv, int index) {
extract_command(argc, argv, index);
if (cfg.command_line == NULL) {
assert(cfg.shell);
cfg.command_line = cfg.shell;
cfg.window_title = cfg.shell;
}
if (arg_debug)
else if (arg_debug)
printf("Extracted command #%s#\n", cfg.command_line);

// set cpu affinity
Expand Down Expand Up @@ -554,11 +576,13 @@ void join(pid_t pid, int argc, char **argv, int index) {
dbus_set_system_bus_env();
#endif

start_application(0, NULL);
start_application(0, shfd, NULL);

__builtin_unreachable();
}
EUID_USER();
if (shfd != -1)
close(shfd);

int status = 0;
//*****************************
Expand Down
2 changes: 1 addition & 1 deletion src/firejail/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -2786,7 +2786,7 @@ int main(int argc, char **argv, char **envp) {

// build the sandbox command
if (prog_index == -1 && cfg.shell) {
cfg.command_line = cfg.shell;
assert(cfg.command_line == NULL); // runs cfg.shell
cfg.window_title = cfg.shell;
cfg.command_name = cfg.shell;
}
Expand Down
4 changes: 2 additions & 2 deletions src/firejail/no_sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -211,7 +211,7 @@ void run_no_sandbox(int argc, char **argv) {
}

if (prog_index == 0) {
cfg.command_line = cfg.shell;
assert(cfg.command_line == NULL); // runs cfg.shell
cfg.window_title = cfg.shell;
} else {
build_cmdline(&cfg.command_line, &cfg.window_title, argc, argv, prog_index);
Expand All @@ -230,5 +230,5 @@ void run_no_sandbox(int argc, char **argv) {

arg_quiet = 1;

start_application(1, NULL);
start_application(1, -1, NULL);
}
41 changes: 22 additions & 19 deletions src/firejail/sandbox.c
Original file line number Diff line number Diff line change
Expand Up @@ -461,7 +461,7 @@ static int ok_to_run(const char *program) {
return 0;
}

void start_application(int no_sandbox, char *set_sandbox_status) {
void start_application(int no_sandbox, int fd, char *set_sandbox_status) {
// set environment
if (no_sandbox == 0) {
env_defaults();
Expand All @@ -471,7 +471,7 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
umask(orig_umask);

if (arg_debug) {
printf("starting application\n");
printf("Starting application\n");
printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD"));
}

Expand All @@ -488,9 +488,6 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
if (set_sandbox_status)
*set_sandbox_status = SANDBOX_DONE;
execl(arg_audit_prog, arg_audit_prog, NULL);

perror("execl");
exit(1);
}
//****************************************
// start the program without using a shell
Expand Down Expand Up @@ -532,35 +529,37 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
//****************************************
else {
assert(cfg.shell);
assert(cfg.command_line);

char *arg[5];
int index = 0;
arg[index++] = cfg.shell;
if (login_shell) {
arg[index++] = "-l";
if (arg_debug)
printf("Starting %s login shell\n", cfg.shell);
} else {
arg[index++] = "-c";
if (cfg.command_line) {
if (arg_debug)
printf("Running %s command through %s\n", cfg.command_line, cfg.shell);
arg[index++] = "-c";
if (arg_doubledash)
arg[index++] = "--";
arg[index++] = cfg.command_line;
}
arg[index] = NULL;
else if (login_shell) {
if (arg_debug)
printf("Starting %s login shell\n", cfg.shell);
arg[index++] = "-l";
}
else if (arg_debug)
printf("Starting %s shell\n", cfg.shell);

assert(index < 5);
arg[index] = NULL;

if (arg_debug) {
char *msg;
if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
if (asprintf(&msg, "sandbox %d, execvp into %s",
sandbox_pid, cfg.command_line ? cfg.command_line : cfg.shell) == -1)
errExit("asprintf");
logmsg(msg);
free(msg);
}

if (arg_debug) {
int i;
for (i = 0; i < 5; i++) {
if (arg[i] == NULL)
Expand All @@ -580,10 +579,14 @@ void start_application(int no_sandbox, char *set_sandbox_status) {
if (set_sandbox_status)
*set_sandbox_status = SANDBOX_DONE;
execvp(arg[0], arg);

// join sandbox without shell in the mount namespace
if (fd > -1)
fexecve(fd, arg, environ);
}

perror("execvp");
exit(1); // it should never get here!!!
perror("Cannot start application");
exit(1);
}

static void enforce_filters(void) {
Expand Down Expand Up @@ -1223,7 +1226,7 @@ int sandbox(void* sandbox_arg) {
set_nice(cfg.nice);
set_rlimits();

start_application(0, set_sandbox_status);
start_application(0, -1, set_sandbox_status);
}

munmap(set_sandbox_status, 1);
Expand Down