From c85acb7ba71b153806632256b511b915b872c5bc Mon Sep 17 00:00:00 2001 From: netblue30 Date: Wed, 13 Apr 2016 20:47:18 -0400 Subject: wait up to 10 seconds for sandbox shutdown --- etc/deluge.profile | 3 ++- src/firejail/main.c | 4 ++- src/firejail/sandbox.c | 50 ++++++++++++++++++++++++++++------- src/firejail/shutdown.c | 56 ++++++++++++++++++++++++++------------- test/catchsignal-master.sh | 4 +++ test/catchsignal.sh | 27 +++++++++++++++++++ test/catchsignal2.sh | 49 ++++++++++++++++++++++++++++++++++ test/option-shutdown2.exp | 42 +++++++++++++++++++++++++++++ test/option-shutdown3.exp | 62 +++++++++++++++++++++++++++++++++++++++++++ test/option-shutdown4.exp | 66 ++++++++++++++++++++++++++++++++++++++++++++++ test/pid.exp | 2 +- test/test.sh | 9 +++++++ 12 files changed, 343 insertions(+), 31 deletions(-) create mode 100755 test/catchsignal-master.sh create mode 100755 test/catchsignal.sh create mode 100755 test/catchsignal2.sh create mode 100755 test/option-shutdown2.exp create mode 100755 test/option-shutdown3.exp create mode 100755 test/option-shutdown4.exp diff --git a/etc/deluge.profile b/etc/deluge.profile index d8ffc8ec5..4043f58f5 100644 --- a/etc/deluge.profile +++ b/etc/deluge.profile @@ -1,7 +1,8 @@ # deluge bittorernt client profile include /etc/firejail/disable-common.inc include /etc/firejail/disable-programs.inc -include /etc/firejail/disable-devel.inc +# deluge is using python on Debian +#include /etc/firejail/disable-devel.inc include /etc/firejail/disable-passwdmgr.inc caps.drop all diff --git a/src/firejail/main.c b/src/firejail/main.c index c183a7675..bdf960b96 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -132,8 +132,10 @@ static void myexit(int rv) { static void my_handler(int s){ EUID_ROOT(); - if (!arg_quiet) + if (!arg_quiet) { printf("\nParent received signal %d, shutting down the child process...\n", s); + fflush(0); + } logsignal(s); kill(child, SIGTERM); myexit(1); diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 4a4956687..3f3564295 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -34,17 +34,45 @@ #define CLONE_NEWUSER 0x10000000 #endif -static monitored_pid = 0; -static void sandbox_handler(int s){ - if (!arg_quiet) - printf("\nChild received signal %d, shutting down the sandbox...\n", s); +static int monitored_pid = 0; +static void sandbox_handler(int sig){ + if (!arg_quiet) { + printf("\nChild received signal %d, shutting down the sandbox...\n", sig); + fflush(0); + } + + // broadcast sigterm to all processes in the group + kill(-1, SIGTERM); + sleep(1); + if (monitored_pid) { - kill(monitored_pid, SIGTERM); - sleep(1); - kill(monitored_pid, SIGKILL); + int monsec = 9; + char *monfile; + if (asprintf(&monfile, "/proc/%d/cmdline", monitored_pid) == -1) + errExit("asprintf"); + while (monsec) { + FILE *fp = fopen(monfile, "r"); + if (!fp) + break; + + char c; + size_t count = fread(&c, 1, 1, fp); + fclose(fp); + if (count == 0) + break; + + if (arg_debug) + printf("Waiting on PID %d to finish\n", monitored_pid); + sleep(1); + monsec--; + } + free(monfile); + } - - exit(s); + + // broadcast a SIGKILL + kill(-1, SIGKILL); + exit(sig); } @@ -149,13 +177,15 @@ static int monitor_application(pid_t app_pid) { signal (SIGTERM, sandbox_handler); EUID_USER(); - int status; + int status = 0; while (monitored_pid) { usleep(20000); char *msg; if (asprintf(&msg, "monitoring pid %d\n", monitored_pid) == -1) errExit("asprintf"); logmsg(msg); + if (arg_debug) + printf("%s\n", msg); free(msg); pid_t rv; diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c index 94ca0a816..8d8035bfb 100644 --- a/src/firejail/shutdown.c +++ b/src/firejail/shutdown.c @@ -77,26 +77,46 @@ void shut(pid_t pid) { EUID_ROOT(); printf("Sending SIGTERM to %u\n", pid); kill(pid, SIGTERM); - sleep(2); - // if the process is still running, terminate it using SIGKILL - // try to open stat file - char *file; - if (asprintf(&file, "/proc/%u/status", pid) == -1) { - perror("asprintf"); - exit(1); + // wait for not more than 10 seconds + sleep(2); + int monsec = 8; + char *monfile; + if (asprintf(&monfile, "/proc/%d/cmdline", pid) == -1) + errExit("asprintf"); + int killdone = 0; + + while (monsec) { + FILE *fp = fopen(monfile, "r"); + if (!fp) { + killdone = 1; + break; + } + + char c; + size_t count = fread(&c, 1, 1, fp); + fclose(fp); + if (count == 0) { + // all done + killdone = 1; + break; + } + + sleep(1); + monsec--; } - FILE *fp = fopen(file, "r"); - if (!fp) - return; - fclose(fp); - - // kill the process and also the parent - printf("Sending SIGKILL to %u\n", pid); - kill(pid, SIGKILL); - if (parent != pid) { - printf("Sending SIGKILL to %u\n", parent); - kill(parent, SIGKILL); + free(monfile); + + + // force SIGKILL + if (!killdone) { + // kill the process and also the parent + printf("Sending SIGKILL to %u\n", pid); + kill(pid, SIGKILL); + if (parent != pid) { + printf("Sending SIGKILL to %u\n", parent); + kill(parent, SIGKILL); + } } clear_run_files(parent); diff --git a/test/catchsignal-master.sh b/test/catchsignal-master.sh new file mode 100755 index 000000000..62a1801cc --- /dev/null +++ b/test/catchsignal-master.sh @@ -0,0 +1,4 @@ +#!/bin/bash + +./catchsignal.sh & +./catchsignal.sh & diff --git a/test/catchsignal.sh b/test/catchsignal.sh new file mode 100755 index 000000000..87a1d0adf --- /dev/null +++ b/test/catchsignal.sh @@ -0,0 +1,27 @@ +#!/bin/bash + +_term() { + echo "Caught Signal" + echo 1 + sleep 1 + echo 2 + sleep 1 + echo 3 + sleep 1 + echo 4 + sleep 1 + echo 5 + sleep 1 + + kill $pid + exit +} + +trap _term SIGTERM +trap _term SIGINT + +echo "Sleeping..." + +sleep inf & +pid=$! +wait $pid diff --git a/test/catchsignal2.sh b/test/catchsignal2.sh new file mode 100755 index 000000000..424350397 --- /dev/null +++ b/test/catchsignal2.sh @@ -0,0 +1,49 @@ +#!/bin/bash + +_term() { + echo "Caught Signal" + echo 1 + sleep 1 + echo 2 + sleep 1 + echo 3 + sleep 1 + echo 4 + sleep 1 + echo 5 + sleep 1 + + echo 10 + sleep 1 + echo 20 + sleep 1 + echo 30 + sleep 1 + echo 40 + sleep 1 + echo 50 + sleep 1 + + echo 100 + sleep 1 + echo 200 + sleep 1 + echo 300 + sleep 1 + echo 400 + sleep 1 + echo 500 + sleep 1 + + kill $pid + exit +} + +trap _term SIGTERM +trap _term SIGINT + +echo "Sleeping..." + +sleep inf & +pid=$! +wait $pid diff --git a/test/option-shutdown2.exp b/test/option-shutdown2.exp new file mode 100755 index 000000000..403bc30be --- /dev/null +++ b/test/option-shutdown2.exp @@ -0,0 +1,42 @@ +#!/usr/bin/expect -f + +set timeout 10 +spawn $env(SHELL) +match_max 100000 + +set firstspawn $spawn_id + +send -- "firejail --name=shutdowntesting ./catchsignal.sh\r" +expect { + timeout {puts "TESTING ERROR 0\n";exit} + "Child process initialized" +} +sleep 2 + +spawn $env(SHELL) +send -- "firejail --shutdown=shutdowntesting\r" + +set spawn_id $firstspawn +expect { + timeout {puts "TESTING ERROR 1\n";exit} + "1" +} +expect { + timeout {puts "TESTING ERROR 2\n";exit} + "2" +} +expect { + timeout {puts "TESTING ERROR 3\n";exit} + "3" +} +expect { + timeout {puts "TESTING ERROR 4\n";exit} + "4" +} +expect { + timeout {puts "TESTING ERROR 5\n";exit} + "5" +} +sleep 1 + +puts "\nalldone\n" diff --git a/test/option-shutdown3.exp b/test/option-shutdown3.exp new file mode 100755 index 000000000..0ef371cd8 --- /dev/null +++ b/test/option-shutdown3.exp @@ -0,0 +1,62 @@ +#!/usr/bin/expect -f + +set timeout 10 +spawn $env(SHELL) +match_max 100000 + +set firstspawn $spawn_id + +send -- "firejail --name=shutdowntesting ./catchsignal-master.sh\r" +expect { + timeout {puts "TESTING ERROR 0\n";exit} + "Child process initialized" +} +sleep 2 + +spawn $env(SHELL) +send -- "firejail --shutdown=shutdowntesting\r" + +set spawn_id $firstspawn +expect { + timeout {puts "TESTING ERROR 1\n";exit} + "1" +} +expect { + timeout {puts "TESTING ERROR 2\n";exit} + "1" +} +expect { + timeout {puts "TESTING ERROR 3\n";exit} + "2" +} +expect { + timeout {puts "TESTING ERROR 4\n";exit} + "2" +} +expect { + timeout {puts "TESTING ERROR 5\n";exit} + "3" +} +expect { + timeout {puts "TESTING ERROR 6\n";exit} + "3" +} +expect { + timeout {puts "TESTING ERROR 7\n";exit} + "4" +} +expect { + timeout {puts "TESTING ERROR 8\n";exit} + "4" +} +expect { + timeout {puts "TESTING ERROR 9\n";exit} + "5" +} +expect { + timeout {puts "TESTING ERROR 10\n";exit} + "5" +} +sleep 1 + +puts "\nalldone\n" diff --git a/test/option-shutdown4.exp b/test/option-shutdown4.exp new file mode 100755 index 000000000..f188ec66d --- /dev/null +++ b/test/option-shutdown4.exp @@ -0,0 +1,66 @@ +#!/usr/bin/expect -f + +set timeout 10 +spawn $env(SHELL) +match_max 100000 + +set firstspawn $spawn_id + +send -- "firejail --name=shutdowntesting ./catchsignal2.sh\r" +expect { + timeout {puts "TESTING ERROR 0\n";exit} + "Child process initialized" +} +sleep 2 + +spawn $env(SHELL) +send -- "firejail --shutdown=shutdowntesting\r" + +set spawn_id $firstspawn +expect { + timeout {puts "TESTING ERROR 1\n";exit} + "1" +} +expect { + timeout {puts "TESTING ERROR 2\n";exit} + "2" +} +expect { + timeout {puts "TESTING ERROR 3\n";exit} + "3" +} +expect { + timeout {puts "TESTING ERROR 4\n";exit} + "4" +} +expect { + timeout {puts "TESTING ERROR 5\n";exit} + "5" +} +expect { + timeout {puts "TESTING ERROR 10\n";exit} + "10" +} +expect { + timeout {puts "TESTING ERROR 20\n";exit} + "20" +} +expect { + timeout {puts "TESTING ERROR 30\n";exit} + "30" +} +expect { + timeout {puts "TESTING ERROR 40\n";exit} + "40" +} +expect { + timeout {puts "TESTING ERROR 50\n";exit} + "50" +} +expect { + timeout {puts "TESTING ERROR 60\n";exit} + "Killed" +} +sleep 1 + +puts "\nalldone\n" diff --git a/test/pid.exp b/test/pid.exp index fb5b90f04..cdeb9d5fb 100755 --- a/test/pid.exp +++ b/test/pid.exp @@ -37,7 +37,7 @@ sleep 1 send -- "ps aux |wc -l; pwd\r" expect { timeout {puts "TESTING ERROR 5\n";exit} - "6" {puts "normal system\n'} + "6" {puts "normal system\n"} "5" {puts "grsecurity\n"} } expect { diff --git a/test/test.sh b/test/test.sh index 96ef8f423..c6fe4f299 100755 --- a/test/test.sh +++ b/test/test.sh @@ -133,6 +133,15 @@ echo "TESTING: rlimit (option_rlimit.exp)" echo "TESTING: shutdown (option_shutdown.exp)" ./option-shutdown.exp +echo "TESTING: shutdown2 (option_shutdown2.exp)" +./option-shutdown2.exp + +echo "TESTING: shutdown3 (option_shutdown3.exp)" +./option-shutdown3.exp + +echo "TESTING: shutdown4 (option_shutdown4.exp)" +./option-shutdown4.exp + echo "TESTING: join (option-join.exp)" ./option-join.exp -- cgit v1.2.3-70-g09d2