From 99a9f8d680ea5a613506d5f0a1804bf97a5d69f3 Mon Sep 17 00:00:00 2001 From: Austin Morton Date: Mon, 20 May 2019 19:44:40 -0400 Subject: Add private-cwd option to control working directory within jail --- src/firejail/firejail.h | 3 +++ src/firejail/fs_home.c | 15 +++++++++++++++ src/firejail/main.c | 15 +++++++++++++++ src/firejail/profile.c | 14 +++++++++++++- src/firejail/sandbox.c | 4 ++++ src/firejail/usage.c | 2 ++ src/man/firejail-profile.txt | 6 ++++++ src/man/firejail.txt | 42 ++++++++++++++++++++++++++++++++++++++++++ 8 files changed, 100 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index e0f3a6a16..bbdf279ce 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -283,6 +283,7 @@ extern int arg_private_srv; // private srv directory extern int arg_private_bin; // private bin directory extern int arg_private_tmp; // private tmp directory extern int arg_private_lib; // private lib directory +extern int arg_private_cwd; // private working directory extern int arg_scan; // arp-scan all interfaces extern int arg_whitelist; // whitelist command extern int arg_nosound; // disable sound @@ -521,6 +522,8 @@ void fs_private(void); void fs_private_homedir(void); // check new private home directory (--private= option) - exit if it fails void fs_check_private_dir(void); +// check new private working directory (--private-cwd= option) - exit if it fails +void fs_check_private_cwd(void); void fs_private_home_list(void); diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index b44d09acc..a1a16841a 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c @@ -370,6 +370,21 @@ void fs_check_private_dir(void) { } } +// check new private working directory (--private-cwd= option) - exit if it fails +void fs_check_private_cwd(void) { + EUID_ASSERT(); + invalid_filename(cfg.cwd, 0); // no globbing + + // Expand the working directory + cfg.cwd = expand_macros(cfg.cwd); + + // realpath/is_dir not used because path may not exist outside of jail + if (!cfg.cwd) { + fprintf(stderr, "Error: invalid private working directory\n"); + exit(1); + } +} + //*********************************************************************************** // --private-home //*********************************************************************************** diff --git a/src/firejail/main.c b/src/firejail/main.c index f3dc72944..2c7290854 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -92,6 +92,7 @@ int arg_private_srv = 0; // private srv directory int arg_private_bin = 0; // private bin directory int arg_private_tmp = 0; // private tmp directory int arg_private_lib = 0; // private lib directory +int arg_private_cwd = 0; // private working directory int arg_scan = 0; // arp-scan all interfaces int arg_whitelist = 0; // whitelist command int arg_nosound = 0; // disable sound @@ -1773,6 +1774,20 @@ int main(int argc, char **argv) { else exit_err_feature("private-cache"); } + else if (strcmp(argv[i], "--private-cwd") == 0) { + cfg.cwd = NULL; + arg_private_cwd = 1; + } + else if (strncmp(argv[i], "--private-cwd=", 14) == 0) { + cfg.cwd = argv[i] + 14; + if (*cfg.cwd == '\0') { + fprintf(stderr, "Error: invalid private-cwd option\n"); + exit(1); + } + + fs_check_private_cwd(); + arg_private_cwd = 1; + } //************************************* // hostname, etc diff --git a/src/firejail/profile.c b/src/firejail/profile.c index c8619f7e2..801c8ba4c 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -338,7 +338,7 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { arg_private = 1; return 0; } - if (strncmp(ptr, "private-home ", 13) == 0) { + else if (strncmp(ptr, "private-home ", 13) == 0) { #ifdef HAVE_PRIVATE_HOME if (checkcfg(CFG_PRIVATE_HOME)) { if (cfg.home_private_keep) { @@ -353,6 +353,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { #endif return 0; } + else if (strcmp(ptr, "private-cwd") == 0) { + cfg.cwd = NULL; + arg_private_cwd = 1; + return 0; + } + else if (strncmp(ptr, "private-cwd ", 12) == 0) { + cfg.cwd = strdup(ptr + 12); + + fs_check_private_cwd(); + arg_private_cwd = 1; + return 0; + } else if (strcmp(ptr, "allusers") == 0) { arg_allusers = 1; return 0; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 9f0a5f25c..250247f8a 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -1016,6 +1016,10 @@ int sandbox(void* sandbox_arg) { if (cfg.cwd) { if (chdir(cfg.cwd) == 0) cwd = 1; + else if (arg_private_cwd) { + fprintf(stderr, "Error: unabled to enter private working directory: %s: %s\n", cfg.cwd, strerror(errno)); + exit(1); + } } if (!cwd) { diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 7620bba82..a8d5bfdda 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -162,6 +162,8 @@ static char *usage_str = " --private-etc=file,directory - build a new /etc in a temporary\n" "\tfilesystem, and copy the files and directories in the list.\n" " --private-tmp - mount a tmpfs on top of /tmp directory.\n" + " --private-cwd - do not inherit working directory inside jail.\n" + " --private-cwd=directory - set working directory inside jail.\n" " --private-opt=file,directory - build a new /opt in a temporary filesystem.\n" " --private-srv=file,directory - build a new /srv in a temporary filesystem.\n" " --profile=filename|profile_name - use a custom profile.\n" diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 703fac30f..23007725a 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt @@ -288,6 +288,12 @@ All modifications are discarded when the sandbox is closed. \fBprivate-tmp Mount an empty temporary filesystem on top of /tmp directory whitelisting /tmp/.X11-unix. .TP +\fBprivate-cwd +Set working directory inside jail to the home directory, and failing that, the root directory. +.TP +\fBprivate-cwd directory +Set working directory inside the jail. +.TP \fBread-only file_or_directory Make directory or file read-only. .TP diff --git a/src/man/firejail.txt b/src/man/firejail.txt index e6826448b..1fa2a6546 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt @@ -1568,6 +1568,48 @@ drwx------ 2 nobody nogroup 4096 Apr 30 10:52 pulse-PKdhtXMmr18n drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix .br +.TP +\fB\-\-private-cwd +Set working directory inside jail to the home directory, and failing that, the root directory. +.br +Does not impact working directory of profile include paths. +.br + +.br +Example: +.br +$ pwd +.br +/tmp +.br +$ firejail \-\-private-cwd +.br +$ pwd +.br +/home/user +.br + +.TP +\fB\-\-private-cwd=directory +Set working directory inside the jail. +.br +Does not impact working directory of profile include paths. +.br + +.br +Example: +.br +$ pwd +.br +/tmp +.br +$ firejail \-\-private-cwd=/opt +.br +$ pwd +.br +/opt +.br + .TP \fB\-\-profile=filename_or_profilename -- cgit v1.2.3-70-g09d2