aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/firejail/sandbox.c193
-rwxr-xr-xtest/fs_chroot.exp2
-rwxr-xr-xtest/ignore.exp2
-rwxr-xr-xtest/option-trace.exp10
-rwxr-xr-xtest/pid.exp2
-rwxr-xr-xtest/trace.exp29
6 files changed, 150 insertions, 88 deletions
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 81d09ed34..582a4f520 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -25,6 +25,8 @@
25#include <sys/prctl.h> 25#include <sys/prctl.h>
26#include <sys/time.h> 26#include <sys/time.h>
27#include <sys/resource.h> 27#include <sys/resource.h>
28#include <sys/types.h>
29#include <dirent.h>
28 30
29#include <sched.h> 31#include <sched.h>
30#ifndef CLONE_NEWUSER 32#ifndef CLONE_NEWUSER
@@ -124,6 +126,119 @@ static void chk_chroot(void) {
124 exit(1); 126 exit(1);
125} 127}
126 128
129static void monitor_application(pid_t app_pid) {
130 while (app_pid) {
131 sleep(1);
132
133 int status;
134 unsigned rv = waitpid(app_pid, &status, 0);
135 if (arg_debug)
136 printf("Sandbox monitor: waitpid %u retval %d status %d\n", app_pid, rv, status);
137
138 DIR *dir;
139 if (!(dir = opendir("/proc"))) {
140 // sleep 2 seconds and try again
141 sleep(2);
142 if (!(dir = opendir("/proc"))) {
143 fprintf(stderr, "Error: cannot open /proc directory\n");
144 exit(1);
145 }
146 }
147
148 struct dirent *entry;
149 app_pid = 0;
150 while ((entry = readdir(dir)) != NULL) {
151 char *end;
152 unsigned pid;
153 if (sscanf(entry->d_name, "%u", &pid) != 1)
154 continue;
155 if (pid == 1)
156 continue;
157 app_pid = pid;
158 break;
159 }
160 closedir(dir);
161
162 if (app_pid != 0 && arg_debug)
163 printf("Sandbox monitor: monitoring %u\n", app_pid);
164 }
165}
166
167
168static void start_application(void) {
169 //****************************************
170 // start the program without using a shell
171 //****************************************
172 if (arg_shell_none) {
173 if (arg_debug) {
174 int i;
175 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
176 if (cfg.original_argv[i] == NULL)
177 break;
178 printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]);
179 }
180 }
181
182 if (!arg_command && !arg_quiet)
183 printf("Child process initialized\n");
184 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
185 }
186 //****************************************
187 // start the program using a shell
188 //****************************************
189 else {
190 // choose the shell requested by the user, or use bash as default
191 char *sh;
192 if (cfg.shell)
193 sh = cfg.shell;
194 else if (arg_zsh)
195 sh = "/usr/bin/zsh";
196 else if (arg_csh)
197 sh = "/bin/csh";
198 else
199 sh = "/bin/bash";
200
201 char *arg[5];
202 int index = 0;
203 arg[index++] = sh;
204 arg[index++] = "-c";
205 assert(cfg.command_line);
206 if (arg_debug)
207 printf("Starting %s\n", cfg.command_line);
208 if (arg_doubledash)
209 arg[index++] = "--";
210 arg[index++] = cfg.command_line;
211 arg[index] = NULL;
212 assert(index < 5);
213
214 if (arg_debug) {
215 char *msg;
216 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
217 errExit("asprintf");
218 logmsg(msg);
219 free(msg);
220 }
221
222 if (arg_debug) {
223 int i;
224 for (i = 0; i < 5; i++) {
225 if (arg[i] == NULL)
226 break;
227 printf("execvp argument %d: %s\n", i, arg[i]);
228 }
229 }
230
231 if (!arg_command && !arg_quiet)
232 printf("Child process initialized\n");
233 execvp(sh, arg);
234 }
235
236 perror("execvp");
237 exit(1); // it should never get here!!!
238}
239
240
241
127int sandbox(void* sandbox_arg) { 242int sandbox(void* sandbox_arg) {
128 // Get rid of unused parameter warning 243 // Get rid of unused parameter warning
129 (void)sandbox_arg; 244 (void)sandbox_arg;
@@ -379,7 +494,7 @@ int sandbox(void* sandbox_arg) {
379 fs_delete_cp_command(); 494 fs_delete_cp_command();
380 495
381 //**************************** 496 //****************************
382 // start executable 497 // set application environment
383 //**************************** 498 //****************************
384 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died 499 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
385 int cwd = 0; 500 int cwd = 0;
@@ -407,6 +522,9 @@ int sandbox(void* sandbox_arg) {
407 // set user-supplied environment variables 522 // set user-supplied environment variables
408 env_apply(); 523 env_apply();
409 524
525 //****************************
526 // set security filters
527 //****************************
410 // set capabilities 528 // set capabilities
411 if (!arg_noroot) 529 if (!arg_noroot)
412 set_caps(); 530 set_caps();
@@ -477,73 +595,18 @@ int sandbox(void* sandbox_arg) {
477 595
478 596
479 //**************************************** 597 //****************************************
480 // start the program without using a shell 598 // fork the application and monitor it
481 //****************************************
482 if (arg_shell_none) {
483 if (arg_debug) {
484 int i;
485 for (i = cfg.original_program_index; i < cfg.original_argc; i++) {
486 if (cfg.original_argv[i] == NULL)
487 break;
488 printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]);
489 }
490 }
491
492 if (!arg_command && !arg_quiet)
493 printf("Child process initialized\n");
494 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
495 }
496 //****************************************
497 // start the program using a shell
498 //**************************************** 599 //****************************************
499 else { 600 pid_t app_pid = fork();
500 // choose the shell requested by the user, or use bash as default 601 if (app_pid == -1)
501 char *sh; 602 errExit("fork");
502 if (cfg.shell)
503 sh = cfg.shell;
504 else if (arg_zsh)
505 sh = "/usr/bin/zsh";
506 else if (arg_csh)
507 sh = "/bin/csh";
508 else
509 sh = "/bin/bash";
510
511 char *arg[5];
512 int index = 0;
513 arg[index++] = sh;
514 arg[index++] = "-c";
515 assert(cfg.command_line);
516 if (arg_debug)
517 printf("Starting %s\n", cfg.command_line);
518 if (arg_doubledash)
519 arg[index++] = "--";
520 arg[index++] = cfg.command_line;
521 arg[index] = NULL;
522 assert(index < 5);
523
524 if (arg_debug) {
525 char *msg;
526 if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1)
527 errExit("asprintf");
528 logmsg(msg);
529 free(msg);
530 }
531 603
532 if (arg_debug) { 604 if (app_pid == 0) {
533 int i; 605 prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died
534 for (i = 0; i < 5; i++) { 606 start_application(); // start app
535 if (arg[i] == NULL)
536 break;
537 printf("execvp argument %d: %s\n", i, arg[i]);
538 }
539 }
540
541 if (!arg_command && !arg_quiet)
542 printf("Child process initialized\n");
543 execvp(sh, arg);
544 } 607 }
545
546 608
547 perror("execvp"); 609 monitor_application(app_pid); // monitor application
610
548 return 0; 611 return 0;
549} 612}
diff --git a/test/fs_chroot.exp b/test/fs_chroot.exp
index 4ddf8d32a..cc0d82179 100755
--- a/test/fs_chroot.exp
+++ b/test/fs_chroot.exp
@@ -54,7 +54,7 @@ sleep 1
54send -- "ps aux |wc -l; pwd\r" 54send -- "ps aux |wc -l; pwd\r"
55expect { 55expect {
56 timeout {puts "TESTING ERROR 5\n";exit} 56 timeout {puts "TESTING ERROR 5\n";exit}
57 "5" 57 "6"
58} 58}
59expect { 59expect {
60 timeout {puts "TESTING ERROR 6\n";exit} 60 timeout {puts "TESTING ERROR 6\n";exit}
diff --git a/test/ignore.exp b/test/ignore.exp
index ab7f0655f..8f8076fb3 100755
--- a/test/ignore.exp
+++ b/test/ignore.exp
@@ -30,7 +30,7 @@ sleep 1
30send -- "ps aux | wc -l\r" 30send -- "ps aux | wc -l\r"
31expect { 31expect {
32 timeout {puts "TESTING ERROR 4\n";exit} 32 timeout {puts "TESTING ERROR 4\n";exit}
33 "4" 33 "5"
34} 34}
35sleep 1 35sleep 1
36send -- "exit\r" 36send -- "exit\r"
diff --git a/test/option-trace.exp b/test/option-trace.exp
index b20ef9ef9..6fd113e2b 100755
--- a/test/option-trace.exp
+++ b/test/option-trace.exp
@@ -11,17 +11,17 @@ expect {
11} 11}
12expect { 12expect {
13 timeout {puts "TESTING ERROR 1\n";exit} 13 timeout {puts "TESTING ERROR 1\n";exit}
14 "1:bash:open /dev/tty" {puts "64bit\n"} 14 "bash:open /dev/tty" {puts "64bit\n"}
15 "1:bash:open64 /dev/tty" {puts "32bit\n"} 15 "bash:open64 /dev/tty" {puts "32bit\n"}
16} 16}
17expect { 17expect {
18 timeout {puts "TESTING ERROR 2\n";exit} 18 timeout {puts "TESTING ERROR 2\n";exit}
19 "1:bash:fopen /etc/passwd" 19 "bash:fopen /etc/passwd"
20} 20}
21expect { 21expect {
22 timeout {puts "TESTING ERROR 3\n";exit} 22 timeout {puts "TESTING ERROR 3\n";exit}
23 "1:bash:access /etc/terminfo/x/xterm" {puts "debian\n"} 23 "bash:access /etc/terminfo/x/xterm" {puts "debian\n"}
24 "1:bash:access /usr/share/terminfo/x/xterm" {puts "arch\n"} 24 "bash:access /usr/share/terminfo/x/xterm" {puts "arch\n"}
25} 25}
26 26
27sleep 1 27sleep 1
diff --git a/test/pid.exp b/test/pid.exp
index 0baf3af0e..d382feb96 100755
--- a/test/pid.exp
+++ b/test/pid.exp
@@ -37,7 +37,7 @@ sleep 1
37send -- "ps aux |wc -l; pwd\r" 37send -- "ps aux |wc -l; pwd\r"
38expect { 38expect {
39 timeout {puts "TESTING ERROR 5\n";exit} 39 timeout {puts "TESTING ERROR 5\n";exit}
40 "5" 40 "6"
41} 41}
42expect { 42expect {
43 timeout {puts "TESTING ERROR 6\n";exit} 43 timeout {puts "TESTING ERROR 6\n";exit}
diff --git a/test/trace.exp b/test/trace.exp
index 2b5003d83..21dd6a559 100755
--- a/test/trace.exp
+++ b/test/trace.exp
@@ -11,7 +11,7 @@ expect {
11} 11}
12expect { 12expect {
13 timeout {puts "TESTING ERROR 1\n";exit} 13 timeout {puts "TESTING ERROR 1\n";exit}
14 "1:mkdir:mkdir ttt" 14 "mkdir:mkdir ttt"
15} 15}
16sleep 1 16sleep 1
17 17
@@ -22,7 +22,7 @@ expect {
22} 22}
23expect { 23expect {
24 timeout {puts "TESTING ERROR 3\n";exit} 24 timeout {puts "TESTING ERROR 3\n";exit}
25 "1:rmdir:rmdir ttt" 25 "rmdir:rmdir ttt"
26} 26}
27sleep 1 27sleep 1
28 28
@@ -33,8 +33,8 @@ expect {
33} 33}
34expect { 34expect {
35 timeout {puts "TESTING ERROR 5\n";exit} 35 timeout {puts "TESTING ERROR 5\n";exit}
36 "1:touch:open ttt" {puts "OK\n";} 36 "touch:open ttt" {puts "OK\n";}
37 "1:touch:open64 ttt" {puts "OK\n";} 37 "touch:open64 ttt" {puts "OK\n";}
38} 38}
39sleep 1 39sleep 1
40 40
@@ -45,7 +45,7 @@ expect {
45} 45}
46expect { 46expect {
47 timeout {puts "TESTING ERROR 7\n";exit} 47 timeout {puts "TESTING ERROR 7\n";exit}
48 "1:rm:unlinkat ttt" 48 "rm:unlinkat ttt"
49} 49}
50sleep 1 50sleep 1
51 51
@@ -56,26 +56,26 @@ expect {
56} 56}
57expect { 57expect {
58 timeout {puts "TESTING ERROR 8.2\n";exit} 58 timeout {puts "TESTING ERROR 8.2\n";exit}
59 "1:bash:open /dev/tty" {puts "OK\n";} 59 "bash:open /dev/tty" {puts "OK\n";}
60 "1:bash:open64 /dev/tty" {puts "OK\n";} 60 "bash:open64 /dev/tty" {puts "OK\n";}
61} 61}
62expect { 62expect {
63 timeout {puts "TESTING ERROR 8.3\n";exit} 63 timeout {puts "TESTING ERROR 8.3\n";exit}
64 "1:wget:fopen64 /etc/wgetrc" {puts "OK\n";} 64 "wget:fopen64 /etc/wgetrc" {puts "OK\n";}
65 "1:wget:fopen /etc/wgetrc" {puts "OK\n";} 65 "wget:fopen /etc/wgetrc" {puts "OK\n";}
66} 66}
67expect { 67expect {
68 timeout {puts "TESTING ERROR 8.4\n";exit} 68 timeout {puts "TESTING ERROR 8.4\n";exit}
69 "1:wget:fopen /etc/hosts" 69 "wget:fopen /etc/hosts"
70} 70}
71expect { 71expect {
72 timeout {puts "TESTING ERROR 8.5\n";exit} 72 timeout {puts "TESTING ERROR 8.5\n";exit}
73 "1:wget:connect" 73 "wget:connect"
74} 74}
75expect { 75expect {
76 timeout {puts "TESTING ERROR 8.6\n";exit} 76 timeout {puts "TESTING ERROR 8.6\n";exit}
77 "1:wget:fopen64 index.html" {puts "OK\n";} 77 "wget:fopen64 index.html" {puts "OK\n";}
78 "1:wget:fopen index.html" {puts "OK\n";} 78 "wget:fopen index.html" {puts "OK\n";}
79} 79}
80sleep 1 80sleep 1
81 81
@@ -86,10 +86,9 @@ expect {
86} 86}
87expect { 87expect {
88 timeout {puts "TESTING ERROR 10\n";exit} 88 timeout {puts "TESTING ERROR 10\n";exit}
89 "1:rm:unlinkat index.html" 89 "rm:unlinkat index.html"
90} 90}
91sleep 1 91sleep 1
92 92
93 93
94puts "\nall done\n" 94puts "\nall done\n"
95