From 4d43efd07b27929c9dcc308a76aaefb466bb1245 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Mon, 31 Aug 2020 19:32:51 +0200 Subject: join: move to mmapped sandbox status indicator 1) close #3612 2) remove an implicit limitation on rlimit-fsize option (could not set limit to smaller than 6 bytes without affecting the ability to join a sandbox) 3) rename 'join-or-start' file to just 'join' 4) when waiting for a sandbox that is not fully configured yet, increase polling frequency from 10 per second to 100 per second --- src/firejail/firejail.h | 3 ++- src/firejail/join.c | 59 +++++++++++-------------------------------------- src/firejail/sandbox.c | 51 +++++++++++++++++++----------------------- src/include/rundefs.h | 2 +- 4 files changed, 39 insertions(+), 76 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 85139d75f..2bb8dd351 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -370,8 +370,9 @@ void check_user_namespace(void); char *guess_shell(void); // sandbox.c +#define SANDBOX_DONE '1' int sandbox(void* sandbox_arg); -void start_application(int no_sandbox, FILE *fp) __attribute__((noreturn)); +void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn)); void set_apparmor(void); // network_main.c diff --git a/src/firejail/join.c b/src/firejail/join.c index 14eea4612..c7619ef3b 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -292,7 +292,7 @@ static void extract_umask(pid_t pid) { fprintf(stderr, "Error: cannot open umask file\n"); exit(1); } - if (fscanf(fp, "%3o", &orig_umask) < 1) { + if (fscanf(fp, "%o", &orig_umask) != 1) { fprintf(stderr, "Error: cannot read umask\n"); exit(1); } @@ -303,66 +303,33 @@ static void extract_umask(pid_t pid) { // it is no firejail sandbox at all, return true if the sandbox is complete bool is_ready_for_join(const pid_t pid) { EUID_ASSERT(); - // check if a file "ready-for-join" exists + // check if a file /run/firejail/mnt/join exists char *fname; - if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) + if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_JOIN_FILE) == -1) errExit("asprintf"); EUID_ROOT(); - FILE *fp = fopen(fname, "re"); + int fd = open(fname, O_RDONLY|O_CLOEXEC); EUID_USER(); free(fname); - if (!fp) - return false; - // regular file owned by root - int fd = fileno(fp); if (fd == -1) - errExit("fileno"); + return false; struct stat s; if (fstat(fd, &s) == -1) errExit("fstat"); if (!S_ISREG(s.st_mode) || s.st_uid != 0) { - fclose(fp); + close(fd); return false; } - // check if it is non-empty - char buf[BUFLEN]; - if (fgets(buf, BUFLEN, fp) == NULL) { - fclose(fp); - return false; + char status; + if (read(fd, &status, 1) == 1 && status == SANDBOX_DONE) { + close(fd); + return true; } - fclose(fp); - // confirm "ready" string was written - if (strcmp(buf, "ready\n") != 0) - return false; - - // walk down the process tree a few nodes, there should be no firejail leaf -#define MAXNODES 5 - pid_t current = pid, next; - int i; - for (i = 0; i < MAXNODES; i++) { - if (find_child(current, &next) == 1) { - // found a leaf - EUID_ROOT(); - char *comm = pid_proc_comm(current); - EUID_USER(); - if (!comm) { - fprintf(stderr, "Error: cannot read /proc file\n"); - exit(1); - } - if (strcmp(comm, "firejail") == 0) { - free(comm); - return false; - } - free(comm); - break; - } - current = next; - } - - return true; + close(fd); + return false; } -#define SNOOZE 100000 // sleep interval in microseconds +#define SNOOZE 10000 // sleep interval in microseconds void check_join_permission(pid_t pid) { // check if pid belongs to a fully set up firejail sandbox unsigned long i; diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 0965b1017..ef09a790c 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -20,6 +20,7 @@ #include "firejail.h" #include "../include/seccomp.h" +#include #include #include #include @@ -204,16 +205,17 @@ static void save_umask(void) { } } -static FILE *create_ready_for_join_file(void) { - FILE *fp = fopen(RUN_READY_FOR_JOIN, "wxe"); - if (fp) { - ASSERT_PERMS_STREAM(fp, 0, 0, 0644); - return fp; - } - else { - fprintf(stderr, "Error: cannot create %s\n", RUN_READY_FOR_JOIN); - exit(1); - } +static char *create_join_file(void) { + int fd = open(RUN_JOIN_FILE, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH); + if (fd == -1) + errExit("open"); + if (ftruncate(fd, 1) == -1) + errExit("ftruncate"); + char *rv = mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0); + if (rv == MAP_FAILED) + errExit("mmap"); + close(fd); + return rv; } static void sandbox_if_up(Bridge *br) { @@ -472,7 +474,7 @@ static int ok_to_run(const char *program) { return 0; } -void start_application(int no_sandbox, FILE *fp) { +void start_application(int no_sandbox, char *set_sandbox_status) { // set environment if (no_sandbox == 0) { env_defaults(); @@ -492,16 +494,14 @@ void start_application(int no_sandbox, FILE *fp) { if (arg_audit) { assert(arg_audit_prog); - if (fp) { - fprintf(fp, "ready\n"); - fclose(fp); - } #ifdef HAVE_GCOV __gcov_dump(); #endif #ifdef HAVE_SECCOMP seccomp_install_filters(); #endif + if (set_sandbox_status) + *set_sandbox_status = SANDBOX_DONE; execl(arg_audit_prog, arg_audit_prog, NULL); perror("execl"); @@ -530,16 +530,14 @@ void start_application(int no_sandbox, FILE *fp) { int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]); - if (fp) { - fprintf(fp, "ready\n"); - fclose(fp); - } #ifdef HAVE_GCOV __gcov_dump(); #endif #ifdef HAVE_SECCOMP seccomp_install_filters(); #endif + if (set_sandbox_status) + *set_sandbox_status = SANDBOX_DONE; if (rv) execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); else @@ -591,16 +589,14 @@ void start_application(int no_sandbox, FILE *fp) { if (!arg_command && !arg_quiet) print_time(); - if (fp) { - fprintf(fp, "ready\n"); - fclose(fp); - } #ifdef HAVE_GCOV __gcov_dump(); #endif #ifdef HAVE_SECCOMP seccomp_install_filters(); #endif + if (set_sandbox_status) + *set_sandbox_status = SANDBOX_DONE; execvp(arg[0], arg); } @@ -1162,11 +1158,10 @@ int sandbox(void* sandbox_arg) { set_caps(); //**************************************** - // communicate progress of sandbox set up - // to --join + // relay status information to join option //**************************************** - FILE *rj = create_ready_for_join_file(); + char *set_sandbox_status = create_join_file(); //**************************************** // create a new user namespace @@ -1248,10 +1243,10 @@ int sandbox(void* sandbox_arg) { set_nice(cfg.nice); set_rlimits(); - start_application(0, rj); + start_application(0, set_sandbox_status); } - fclose(rj); + munmap(set_sandbox_status, 1); int status = monitor_application(app_pid); // monitor application flush_stdin(); diff --git a/src/include/rundefs.h b/src/include/rundefs.h index d56623907..4da2db748 100644 --- a/src/include/rundefs.h +++ b/src/include/rundefs.h @@ -113,7 +113,7 @@ #define RUN_FSLOGGER_FILE RUN_MNT_DIR "/fslogger" #define RUN_TRACE_FILE RUN_MNT_DIR "/trace" #define RUN_UMASK_FILE RUN_MNT_DIR "/umask" +#define RUN_JOIN_FILE RUN_MNT_DIR "/join" #define RUN_OVERLAY_ROOT RUN_MNT_DIR "/oroot" -#define RUN_READY_FOR_JOIN RUN_MNT_DIR "/ready-for-join" #endif -- cgit v1.2.3-54-g00ecf