From 4a8a6eff0ee1633b28f0302e5bd356790110b28b Mon Sep 17 00:00:00 2001 From: netblue30 Date: Fri, 13 Nov 2015 07:50:40 -0500 Subject: support for kde and server programs --- src/firejail/sandbox.c | 193 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 128 insertions(+), 65 deletions(-) (limited to 'src') 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 @@ #include #include #include +#include +#include #include #ifndef CLONE_NEWUSER @@ -124,6 +126,119 @@ static void chk_chroot(void) { exit(1); } +static void monitor_application(pid_t app_pid) { + while (app_pid) { + sleep(1); + + int status; + unsigned rv = waitpid(app_pid, &status, 0); + if (arg_debug) + printf("Sandbox monitor: waitpid %u retval %d status %d\n", app_pid, rv, status); + + DIR *dir; + if (!(dir = opendir("/proc"))) { + // sleep 2 seconds and try again + sleep(2); + if (!(dir = opendir("/proc"))) { + fprintf(stderr, "Error: cannot open /proc directory\n"); + exit(1); + } + } + + struct dirent *entry; + app_pid = 0; + while ((entry = readdir(dir)) != NULL) { + char *end; + unsigned pid; + if (sscanf(entry->d_name, "%u", &pid) != 1) + continue; + if (pid == 1) + continue; + app_pid = pid; + break; + } + closedir(dir); + + if (app_pid != 0 && arg_debug) + printf("Sandbox monitor: monitoring %u\n", app_pid); + } +} + + +static void start_application(void) { + //**************************************** + // start the program without using a shell + //**************************************** + if (arg_shell_none) { + if (arg_debug) { + int i; + for (i = cfg.original_program_index; i < cfg.original_argc; i++) { + if (cfg.original_argv[i] == NULL) + break; + printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]); + } + } + + if (!arg_command && !arg_quiet) + printf("Child process initialized\n"); + execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); + } + //**************************************** + // start the program using a shell + //**************************************** + else { + // choose the shell requested by the user, or use bash as default + char *sh; + if (cfg.shell) + sh = cfg.shell; + else if (arg_zsh) + sh = "/usr/bin/zsh"; + else if (arg_csh) + sh = "/bin/csh"; + else + sh = "/bin/bash"; + + char *arg[5]; + int index = 0; + arg[index++] = sh; + arg[index++] = "-c"; + assert(cfg.command_line); + if (arg_debug) + printf("Starting %s\n", cfg.command_line); + if (arg_doubledash) + arg[index++] = "--"; + arg[index++] = cfg.command_line; + arg[index] = NULL; + assert(index < 5); + + if (arg_debug) { + char *msg; + if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) + errExit("asprintf"); + logmsg(msg); + free(msg); + } + + if (arg_debug) { + int i; + for (i = 0; i < 5; i++) { + if (arg[i] == NULL) + break; + printf("execvp argument %d: %s\n", i, arg[i]); + } + } + + if (!arg_command && !arg_quiet) + printf("Child process initialized\n"); + execvp(sh, arg); + } + + perror("execvp"); + exit(1); // it should never get here!!! +} + + + int sandbox(void* sandbox_arg) { // Get rid of unused parameter warning (void)sandbox_arg; @@ -379,7 +494,7 @@ int sandbox(void* sandbox_arg) { fs_delete_cp_command(); //**************************** - // start executable + // set application environment //**************************** prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died int cwd = 0; @@ -407,6 +522,9 @@ int sandbox(void* sandbox_arg) { // set user-supplied environment variables env_apply(); + //**************************** + // set security filters + //**************************** // set capabilities if (!arg_noroot) set_caps(); @@ -477,73 +595,18 @@ int sandbox(void* sandbox_arg) { //**************************************** - // start the program without using a shell - //**************************************** - if (arg_shell_none) { - if (arg_debug) { - int i; - for (i = cfg.original_program_index; i < cfg.original_argc; i++) { - if (cfg.original_argv[i] == NULL) - break; - printf("execvp argument %d: %s\n", i - cfg.original_program_index, cfg.original_argv[i]); - } - } - - if (!arg_command && !arg_quiet) - printf("Child process initialized\n"); - execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); - } - //**************************************** - // start the program using a shell + // fork the application and monitor it //**************************************** - else { - // choose the shell requested by the user, or use bash as default - char *sh; - if (cfg.shell) - sh = cfg.shell; - else if (arg_zsh) - sh = "/usr/bin/zsh"; - else if (arg_csh) - sh = "/bin/csh"; - else - sh = "/bin/bash"; - - char *arg[5]; - int index = 0; - arg[index++] = sh; - arg[index++] = "-c"; - assert(cfg.command_line); - if (arg_debug) - printf("Starting %s\n", cfg.command_line); - if (arg_doubledash) - arg[index++] = "--"; - arg[index++] = cfg.command_line; - arg[index] = NULL; - assert(index < 5); - - if (arg_debug) { - char *msg; - if (asprintf(&msg, "sandbox %d, execvp into %s", sandbox_pid, cfg.command_line) == -1) - errExit("asprintf"); - logmsg(msg); - free(msg); - } + pid_t app_pid = fork(); + if (app_pid == -1) + errExit("fork"); - if (arg_debug) { - int i; - for (i = 0; i < 5; i++) { - if (arg[i] == NULL) - break; - printf("execvp argument %d: %s\n", i, arg[i]); - } - } - - if (!arg_command && !arg_quiet) - printf("Child process initialized\n"); - execvp(sh, arg); + if (app_pid == 0) { + prctl(PR_SET_PDEATHSIG, SIGKILL, 0, 0, 0); // kill the child in case the parent died + start_application(); // start app } - - perror("execvp"); + monitor_application(app_pid); // monitor application + return 0; } -- cgit v1.2.3-70-g09d2