aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Austin Morton <austinpmorton@gmail.com>2019-05-20 19:44:40 -0400
committerLibravatar Austin Morton <austinpmorton@gmail.com>2019-05-23 18:45:44 -0400
commit99a9f8d680ea5a613506d5f0a1804bf97a5d69f3 (patch)
treef4fb77e96f9e2a3f08776ae4471b5db3f059831d
parentCreate a profile for mp3splt-gtk (diff)
downloadfirejail-99a9f8d680ea5a613506d5f0a1804bf97a5d69f3.tar.gz
firejail-99a9f8d680ea5a613506d5f0a1804bf97a5d69f3.tar.zst
firejail-99a9f8d680ea5a613506d5f0a1804bf97a5d69f3.zip
Add private-cwd option to control working directory within jail
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/fs_home.c15
-rw-r--r--src/firejail/main.c15
-rw-r--r--src/firejail/profile.c14
-rw-r--r--src/firejail/sandbox.c4
-rw-r--r--src/firejail/usage.c2
-rw-r--r--src/man/firejail-profile.txt6
-rw-r--r--src/man/firejail.txt42
-rwxr-xr-xtest/fs/fs.sh3
-rwxr-xr-xtest/fs/private-cwd.exp52
10 files changed, 155 insertions, 1 deletions
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
283extern int arg_private_bin; // private bin directory 283extern int arg_private_bin; // private bin directory
284extern int arg_private_tmp; // private tmp directory 284extern int arg_private_tmp; // private tmp directory
285extern int arg_private_lib; // private lib directory 285extern int arg_private_lib; // private lib directory
286extern int arg_private_cwd; // private working directory
286extern int arg_scan; // arp-scan all interfaces 287extern int arg_scan; // arp-scan all interfaces
287extern int arg_whitelist; // whitelist command 288extern int arg_whitelist; // whitelist command
288extern int arg_nosound; // disable sound 289extern int arg_nosound; // disable sound
@@ -521,6 +522,8 @@ void fs_private(void);
521void fs_private_homedir(void); 522void fs_private_homedir(void);
522// check new private home directory (--private= option) - exit if it fails 523// check new private home directory (--private= option) - exit if it fails
523void fs_check_private_dir(void); 524void fs_check_private_dir(void);
525// check new private working directory (--private-cwd= option) - exit if it fails
526void fs_check_private_cwd(void);
524void fs_private_home_list(void); 527void fs_private_home_list(void);
525 528
526 529
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) {
370 } 370 }
371} 371}
372 372
373// check new private working directory (--private-cwd= option) - exit if it fails
374void fs_check_private_cwd(void) {
375 EUID_ASSERT();
376 invalid_filename(cfg.cwd, 0); // no globbing
377
378 // Expand the working directory
379 cfg.cwd = expand_macros(cfg.cwd);
380
381 // realpath/is_dir not used because path may not exist outside of jail
382 if (!cfg.cwd) {
383 fprintf(stderr, "Error: invalid private working directory\n");
384 exit(1);
385 }
386}
387
373//*********************************************************************************** 388//***********************************************************************************
374// --private-home 389// --private-home
375//*********************************************************************************** 390//***********************************************************************************
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
92int arg_private_bin = 0; // private bin directory 92int arg_private_bin = 0; // private bin directory
93int arg_private_tmp = 0; // private tmp directory 93int arg_private_tmp = 0; // private tmp directory
94int arg_private_lib = 0; // private lib directory 94int arg_private_lib = 0; // private lib directory
95int arg_private_cwd = 0; // private working directory
95int arg_scan = 0; // arp-scan all interfaces 96int arg_scan = 0; // arp-scan all interfaces
96int arg_whitelist = 0; // whitelist command 97int arg_whitelist = 0; // whitelist command
97int arg_nosound = 0; // disable sound 98int arg_nosound = 0; // disable sound
@@ -1773,6 +1774,20 @@ int main(int argc, char **argv) {
1773 else 1774 else
1774 exit_err_feature("private-cache"); 1775 exit_err_feature("private-cache");
1775 } 1776 }
1777 else if (strcmp(argv[i], "--private-cwd") == 0) {
1778 cfg.cwd = NULL;
1779 arg_private_cwd = 1;
1780 }
1781 else if (strncmp(argv[i], "--private-cwd=", 14) == 0) {
1782 cfg.cwd = argv[i] + 14;
1783 if (*cfg.cwd == '\0') {
1784 fprintf(stderr, "Error: invalid private-cwd option\n");
1785 exit(1);
1786 }
1787
1788 fs_check_private_cwd();
1789 arg_private_cwd = 1;
1790 }
1776 1791
1777 //************************************* 1792 //*************************************
1778 // hostname, etc 1793 // 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) {
338 arg_private = 1; 338 arg_private = 1;
339 return 0; 339 return 0;
340 } 340 }
341 if (strncmp(ptr, "private-home ", 13) == 0) { 341 else if (strncmp(ptr, "private-home ", 13) == 0) {
342#ifdef HAVE_PRIVATE_HOME 342#ifdef HAVE_PRIVATE_HOME
343 if (checkcfg(CFG_PRIVATE_HOME)) { 343 if (checkcfg(CFG_PRIVATE_HOME)) {
344 if (cfg.home_private_keep) { 344 if (cfg.home_private_keep) {
@@ -353,6 +353,18 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
353#endif 353#endif
354 return 0; 354 return 0;
355 } 355 }
356 else if (strcmp(ptr, "private-cwd") == 0) {
357 cfg.cwd = NULL;
358 arg_private_cwd = 1;
359 return 0;
360 }
361 else if (strncmp(ptr, "private-cwd ", 12) == 0) {
362 cfg.cwd = strdup(ptr + 12);
363
364 fs_check_private_cwd();
365 arg_private_cwd = 1;
366 return 0;
367 }
356 else if (strcmp(ptr, "allusers") == 0) { 368 else if (strcmp(ptr, "allusers") == 0) {
357 arg_allusers = 1; 369 arg_allusers = 1;
358 return 0; 370 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) {
1016 if (cfg.cwd) { 1016 if (cfg.cwd) {
1017 if (chdir(cfg.cwd) == 0) 1017 if (chdir(cfg.cwd) == 0)
1018 cwd = 1; 1018 cwd = 1;
1019 else if (arg_private_cwd) {
1020 fprintf(stderr, "Error: unabled to enter private working directory: %s: %s\n", cfg.cwd, strerror(errno));
1021 exit(1);
1022 }
1019 } 1023 }
1020 1024
1021 if (!cwd) { 1025 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 =
162 " --private-etc=file,directory - build a new /etc in a temporary\n" 162 " --private-etc=file,directory - build a new /etc in a temporary\n"
163 "\tfilesystem, and copy the files and directories in the list.\n" 163 "\tfilesystem, and copy the files and directories in the list.\n"
164 " --private-tmp - mount a tmpfs on top of /tmp directory.\n" 164 " --private-tmp - mount a tmpfs on top of /tmp directory.\n"
165 " --private-cwd - do not inherit working directory inside jail.\n"
166 " --private-cwd=directory - set working directory inside jail.\n"
165 " --private-opt=file,directory - build a new /opt in a temporary filesystem.\n" 167 " --private-opt=file,directory - build a new /opt in a temporary filesystem.\n"
166 " --private-srv=file,directory - build a new /srv in a temporary filesystem.\n" 168 " --private-srv=file,directory - build a new /srv in a temporary filesystem.\n"
167 " --profile=filename|profile_name - use a custom profile.\n" 169 " --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.
288\fBprivate-tmp 288\fBprivate-tmp
289Mount an empty temporary filesystem on top of /tmp directory whitelisting /tmp/.X11-unix. 289Mount an empty temporary filesystem on top of /tmp directory whitelisting /tmp/.X11-unix.
290.TP 290.TP
291\fBprivate-cwd
292Set working directory inside jail to the home directory, and failing that, the root directory.
293.TP
294\fBprivate-cwd directory
295Set working directory inside the jail.
296.TP
291\fBread-only file_or_directory 297\fBread-only file_or_directory
292Make directory or file read-only. 298Make directory or file read-only.
293.TP 299.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
1568drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix 1568drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix
1569.br 1569.br
1570 1570
1571.TP
1572\fB\-\-private-cwd
1573Set working directory inside jail to the home directory, and failing that, the root directory.
1574.br
1575Does not impact working directory of profile include paths.
1576.br
1577
1578.br
1579Example:
1580.br
1581$ pwd
1582.br
1583/tmp
1584.br
1585$ firejail \-\-private-cwd
1586.br
1587$ pwd
1588.br
1589/home/user
1590.br
1591
1592.TP
1593\fB\-\-private-cwd=directory
1594Set working directory inside the jail.
1595.br
1596Does not impact working directory of profile include paths.
1597.br
1598
1599.br
1600Example:
1601.br
1602$ pwd
1603.br
1604/tmp
1605.br
1606$ firejail \-\-private-cwd=/opt
1607.br
1608$ pwd
1609.br
1610/opt
1611.br
1612
1571 1613
1572.TP 1614.TP
1573\fB\-\-profile=filename_or_profilename 1615\fB\-\-profile=filename_or_profilename
diff --git a/test/fs/fs.sh b/test/fs/fs.sh
index 0fc216b20..7e1d46f0a 100755
--- a/test/fs/fs.sh
+++ b/test/fs/fs.sh
@@ -69,6 +69,9 @@ echo "TESTING: empty private-etc (test/fs/private-etc-empty.exp)"
69echo "TESTING: private-bin (test/fs/private-bin.exp)" 69echo "TESTING: private-bin (test/fs/private-bin.exp)"
70./private-bin.exp 70./private-bin.exp
71 71
72echo "TESTING: private-cwd (test/fs/private-cwd.exp)"
73./private-cwd.exp
74
72echo "TESTING: macros (test/fs/macro.exp)" 75echo "TESTING: macros (test/fs/macro.exp)"
73./macro.exp 76./macro.exp
74 77
diff --git a/test/fs/private-cwd.exp b/test/fs/private-cwd.exp
new file mode 100755
index 000000000..0fa87a92f
--- /dev/null
+++ b/test/fs/private-cwd.exp
@@ -0,0 +1,52 @@
1#!/usr/bin/expect -f
2# This file is part of Firejail project
3# Copyright (C) 2014-2019 Firejail Authors
4# License GPL v2
5
6set timeout 10
7spawn $env(SHELL)
8match_max 100000
9
10send -- "cd /tmp\r"
11after 100
12
13# testing profile and private
14send -- "firejail --private-cwd\r"
15expect {
16 timeout {puts "TESTING ERROR 0\n";exit}
17 "Child process initialized"
18}
19sleep 1
20
21send -- "pwd\r"
22expect {
23 timeout {puts "TESTING ERROR 1\n";exit}
24 "$env(HOME)"
25}
26after 100
27
28send -- "exit\r"
29sleep 1
30
31send -- "cd /\r"
32after 100
33
34# testing profile and private
35send -- "firejail --private-cwd=/tmp\r"
36expect {
37 timeout {puts "TESTING ERROR 3\n";exit}
38 "Child process initialized"
39}
40sleep 1
41
42send -- "pwd\r"
43expect {
44 timeout {puts "TESTING ERROR 4\n";exit}
45 "/tmp"
46}
47after 100
48
49send -- "exit\r"
50sleep 1
51
52puts "all done\n"