let join wait if target sandbox is not ready yet

fixes #2139
This commit is contained in:
smitsohu 2019-12-23 02:07:33 +01:00
parent 0d2ec2682a
commit 34b39fd486
10 changed files with 68 additions and 141 deletions

View file

@ -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;

View file

@ -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);
}

View file

@ -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

View file

@ -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;
}
pid_t switch_to_child(pid_t pid) {
EUID_ROOT();
errno = 0;
char *comm = pid_proc_comm(pid);
if (!comm) {
if (errno == ENOENT) {
fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
exit(1);
}
else {
fprintf(stderr, "Error: cannot read /proc file\n");
exit(1);
}
}
EUID_USER();
if (strcmp(comm, "firejail") == 0) {
pid_t child;
if (find_child(pid, &child) == 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);
}
fmessage("Switching to pid %u, the first child process inside the sandbox\n", (unsigned) child);
pid = child;
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)
fprintf(stderr, "Error: cannot find process with pid %d\n", pid);
else
fprintf(stderr, "Error: cannot read /proc file\n");
exit(1);
}
EUID_USER();
if (strcmp(comm, "firejail") == 0) {
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) 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);

View file

@ -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);;

View file

@ -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"))

View file

@ -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();

View file

@ -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"));

View file

@ -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();

View file

@ -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;