summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2019-05-24 21:28:10 +0200
committerLibravatar GitHub <noreply@github.com>2019-05-24 21:28:10 +0200
commit9314fff8cb801e3f2f7a2996764c12ca4e350bea (patch)
tree58416f0e3a01b43f8265ff785c255eaa97e73e65
parentadd header guard to firecfg.h (diff)
parentAdd private-cwd option to control working directory within jail (diff)
downloadfirejail-9314fff8cb801e3f2f7a2996764c12ca4e350bea.tar.gz
firejail-9314fff8cb801e3f2f7a2996764c12ca4e350bea.tar.zst
firejail-9314fff8cb801e3f2f7a2996764c12ca4e350bea.zip
Merge pull request #2712 from apmorton/features/private-cwd
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 b2083d6ad..f904d65d2 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
@@ -522,6 +523,8 @@ void fs_private(void);
522void fs_private_homedir(void); 523void fs_private_homedir(void);
523// check new private home directory (--private= option) - exit if it fails 524// check new private home directory (--private= option) - exit if it fails
524void fs_check_private_dir(void); 525void fs_check_private_dir(void);
526// check new private working directory (--private-cwd= option) - exit if it fails
527void fs_check_private_cwd(void);
525void fs_private_home_list(void); 528void fs_private_home_list(void);
526 529
527 530
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 3e2cc3a17..7ac88f5a5 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
@@ -1774,6 +1775,20 @@ int main(int argc, char **argv) {
1774 else 1775 else
1775 exit_err_feature("private-cache"); 1776 exit_err_feature("private-cache");
1776 } 1777 }
1778 else if (strcmp(argv[i], "--private-cwd") == 0) {
1779 cfg.cwd = NULL;
1780 arg_private_cwd = 1;
1781 }
1782 else if (strncmp(argv[i], "--private-cwd=", 14) == 0) {
1783 cfg.cwd = argv[i] + 14;
1784 if (*cfg.cwd == '\0') {
1785 fprintf(stderr, "Error: invalid private-cwd option\n");
1786 exit(1);
1787 }
1788
1789 fs_check_private_cwd();
1790 arg_private_cwd = 1;
1791 }
1777 1792
1778 //************************************* 1793 //*************************************
1779 // hostname, etc 1794 // hostname, etc
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 55d3cf5b0..8d228fae6 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 c09a1bc73..58245fa38 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -1019,6 +1019,10 @@ int sandbox(void* sandbox_arg) {
1019 if (cfg.cwd) { 1019 if (cfg.cwd) {
1020 if (chdir(cfg.cwd) == 0) 1020 if (chdir(cfg.cwd) == 0)
1021 cwd = 1; 1021 cwd = 1;
1022 else if (arg_private_cwd) {
1023 fprintf(stderr, "Error: unabled to enter private working directory: %s: %s\n", cfg.cwd, strerror(errno));
1024 exit(1);
1025 }
1022 } 1026 }
1023 1027
1024 if (!cwd) { 1028 if (!cwd) {
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index ab749413b..af3bac839 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -163,6 +163,8 @@ static char *usage_str =
163 " --private-etc=file,directory - build a new /etc in a temporary\n" 163 " --private-etc=file,directory - build a new /etc in a temporary\n"
164 "\tfilesystem, and copy the files and directories in the list.\n" 164 "\tfilesystem, and copy the files and directories in the list.\n"
165 " --private-tmp - mount a tmpfs on top of /tmp directory.\n" 165 " --private-tmp - mount a tmpfs on top of /tmp directory.\n"
166 " --private-cwd - do not inherit working directory inside jail.\n"
167 " --private-cwd=directory - set working directory inside jail.\n"
166 " --private-opt=file,directory - build a new /opt in a temporary filesystem.\n" 168 " --private-opt=file,directory - build a new /opt in a temporary filesystem.\n"
167 " --private-srv=file,directory - build a new /srv in a temporary filesystem.\n" 169 " --private-srv=file,directory - build a new /srv in a temporary filesystem.\n"
168 " --profile=filename|profile_name - use a custom profile.\n" 170 " --profile=filename|profile_name - use a custom profile.\n"
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index cbc745af7..d3a563abd 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 fcc7f66d7..c4e8b9175 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -1572,6 +1572,48 @@ drwx------ 2 nobody nogroup 4096 Apr 30 10:52 pulse-PKdhtXMmr18n
1572drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix 1572drwxrwxrwt 2 nobody nogroup 4096 Apr 30 10:52 .X11-unix
1573.br 1573.br
1574 1574
1575.TP
1576\fB\-\-private-cwd
1577Set working directory inside jail to the home directory, and failing that, the root directory.
1578.br
1579Does not impact working directory of profile include paths.
1580.br
1581
1582.br
1583Example:
1584.br
1585$ pwd
1586.br
1587/tmp
1588.br
1589$ firejail \-\-private-cwd
1590.br
1591$ pwd
1592.br
1593/home/user
1594.br
1595
1596.TP
1597\fB\-\-private-cwd=directory
1598Set working directory inside the jail.
1599.br
1600Does not impact working directory of profile include paths.
1601.br
1602
1603.br
1604Example:
1605.br
1606$ pwd
1607.br
1608/tmp
1609.br
1610$ firejail \-\-private-cwd=/opt
1611.br
1612$ pwd
1613.br
1614/opt
1615.br
1616
1575 1617
1576.TP 1618.TP
1577\fB\-\-profile=filename_or_profilename 1619\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"