From 34b39fd486af4e2f586d20fcea275940a5df41e9 Mon Sep 17 00:00:00 2001 From: smitsohu Date: Mon, 23 Dec 2019 02:07:33 +0100 Subject: let join wait if target sandbox is not ready yet fixes #2139 --- src/firejail/caps.c | 17 ++-------- src/firejail/cpu.c | 4 +-- src/firejail/firejail.h | 3 +- src/firejail/join.c | 78 ++++++++++++++++++++++++--------------------- src/firejail/ls.c | 17 ++-------- src/firejail/network_main.c | 17 ++-------- src/firejail/protocol.c | 17 ++-------- src/firejail/sandbox.c | 2 +- src/firejail/seccomp.c | 17 ++-------- src/firejail/util.c | 17 ++-------- 10 files changed, 58 insertions(+), 131 deletions(-) (limited to 'src') diff --git a/src/firejail/caps.c b/src/firejail/caps.c index 71dd9430b..738675766 100644 --- a/src/firejail/caps.c +++ b/src/firejail/caps.c @@ -404,21 +404,8 @@ void caps_print_filter(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); uint64_t caps = extract_caps(pid); int i; diff --git a/src/firejail/cpu.c b/src/firejail/cpu.c index 7a0807257..f3392d1e0 100644 --- a/src/firejail/cpu.c +++ b/src/firejail/cpu.c @@ -170,13 +170,11 @@ void cpu_print_filter(pid_t pid) { pid = switch_to_child(pid); // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { + if (is_ready_for_join(pid) == 0) { fprintf(stderr, "Error: no valid sandbox\n"); exit(1); } - - print_cpu(pid); exit(0); } diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 464e8c07c..a8c580aa1 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -426,7 +426,8 @@ void usage(void); // join.c void join(pid_t pid, int argc, char **argv, int index); -int invalid_sandbox(const pid_t pid); +int is_ready_for_join(const pid_t pid); +void check_join_permission(pid_t pid); pid_t switch_to_child(pid_t pid); // shutdown.c diff --git a/src/firejail/join.c b/src/firejail/join.c index a8dc56b3a..864d4069d 100644 --- a/src/firejail/join.c +++ b/src/firejail/join.c @@ -255,9 +255,10 @@ static void extract_umask(pid_t pid) { fclose(fp); } -// return 1 if the sandbox identified by pid is not fully set up yet or if -// it is no firejail sandbox at all, return 0 if the sandbox is complete -int invalid_sandbox(const pid_t pid) { +// return 0 if the sandbox identified by pid is not fully set up yet or if +// it is no firejail sandbox at all, return 1 if the sandbox is complete +int is_ready_for_join(const pid_t pid) { + EUID_ASSERT(); // check if a file "ready-for-join" exists char *fname; if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) @@ -267,7 +268,7 @@ int invalid_sandbox(const pid_t pid) { EUID_USER(); free(fname); if (!fp) - return 1; + return 0; // regular file owned by root int fd = fileno(fp); if (fd == -1) @@ -277,18 +278,18 @@ int invalid_sandbox(const pid_t pid) { errExit("fstat"); if (!S_ISREG(s.st_mode) || s.st_uid != 0) { fclose(fp); - return 1; + return 0; } // check if it is non-empty char buf[BUFLEN]; if (fgets(buf, BUFLEN, fp) == NULL) { fclose(fp); - return 1; + return 0; } fclose(fp); // confirm "ready" string was written - if (strncmp(buf, "ready\n", 6) != 0) - return 1; + if (strcmp(buf, "ready\n") != 0) + return 0; // walk down the process tree a few nodes, there should be no firejail leaf #define MAXNODES 5 @@ -306,7 +307,7 @@ int invalid_sandbox(const pid_t pid) { } if (strcmp(comm, "firejail") == 0) { free(comm); - return 1; + return 0; } free(comm); break; @@ -314,35 +315,53 @@ int invalid_sandbox(const pid_t pid) { current = next; } - return 0; + return 1; +} + +void check_join_permission(pid_t pid) { + // check if pid belongs to a fully set up firejail sandbox + unsigned i; + for (i = 0; is_ready_for_join(pid) == 0; i++) { // give sandbox some time to start up + if (i >= 50) { + fprintf(stderr, "Error: no valid sandbox\n"); + exit(1); + } + usleep(100000); // 0.1 sec + } + // check privileges for non-root users + uid_t uid = getuid(); + if (uid != 0) { + uid_t sandbox_uid = pid_get_uid(pid); + if (uid != sandbox_uid) { + fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); + exit(1); + } + } } pid_t switch_to_child(pid_t pid) { + EUID_ASSERT(); EUID_ROOT(); + pid_t rv = pid; errno = 0; char *comm = pid_proc_comm(pid); if (!comm) { - if (errno == ENOENT) { + if (errno == ENOENT) fprintf(stderr, "Error: cannot find process with pid %d\n", pid); - exit(1); - } - else { + else fprintf(stderr, "Error: cannot read /proc file\n"); - exit(1); - } + exit(1); } EUID_USER(); if (strcmp(comm, "firejail") == 0) { - pid_t child; - if (find_child(pid, &child) == 1) { + if (find_child(pid, &rv) == 1) { fprintf(stderr, "Error: no valid sandbox\n"); exit(1); } - fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child); - pid = child; + fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) rv); } free(comm); - return pid; + return rv; } @@ -354,21 +373,8 @@ void join(pid_t pid, int argc, char **argv, int index) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); extract_x11_display(parent); diff --git a/src/firejail/ls.c b/src/firejail/ls.c index 08cf5f16a..75333fdc2 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c @@ -215,21 +215,8 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); // expand paths char *fname1 = expand_path(path1);; diff --git a/src/firejail/network_main.c b/src/firejail/network_main.c index 6a199469a..6800bde8d 100644 --- a/src/firejail/network_main.c +++ b/src/firejail/network_main.c @@ -272,21 +272,8 @@ void net_dns_print(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); EUID_ROOT(); if (join_namespace(pid, "mnt")) diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c index 72d29c671..d3a9e0153 100644 --- a/src/firejail/protocol.c +++ b/src/firejail/protocol.c @@ -67,21 +67,8 @@ void protocol_print_filter(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); // find the seccomp filter EUID_ROOT(); diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 995e98f9f..6356f89a6 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -444,7 +444,7 @@ void start_application(int no_sandbox, FILE *fp) { } // restore original umask umask(orig_umask); - + //sleep(10); if (arg_debug) { printf("starting application\n"); printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index 609ebb7be..648ce1612 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c @@ -332,21 +332,8 @@ void seccomp_print_filter(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(pid)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission denied.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(pid); // find the seccomp list file EUID_ROOT(); diff --git a/src/firejail/util.c b/src/firejail/util.c index 032b9a003..2a4353d8d 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1234,21 +1234,8 @@ void enter_network_namespace(pid_t pid) { // in case the pid is that of a firejail process, use the pid of the first child process pid_t child = switch_to_child(pid); - // now check if the pid belongs to a firejail sandbox - if (invalid_sandbox(child)) { - fprintf(stderr, "Error: no valid sandbox\n"); - exit(1); - } - - // check privileges for non-root users - uid_t uid = getuid(); - if (uid != 0) { - uid_t sandbox_uid = pid_get_uid(pid); - if (uid != sandbox_uid) { - fprintf(stderr, "Error: permission is denied to join a sandbox created by a different user.\n"); - exit(1); - } - } + // exit if no permission to join the sandbox + check_join_permission(child); // check network namespace char *name; -- cgit v1.2.3-70-g09d2