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 --- src/firejail/main.c | 4 +++- src/firejail/sandbox.c | 50 ++++++++++++++++++++++++++++++++++--------- src/firejail/shutdown.c | 56 +++++++++++++++++++++++++++++++++---------------- 3 files changed, 81 insertions(+), 29 deletions(-) (limited to 'src') 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); -- cgit v1.2.3-54-g00ecf