aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar smitsohu <smitsohu@gmail.com>2020-08-31 19:32:51 +0200
committerLibravatar smitsohu <smitsohu@gmail.com>2020-08-31 19:32:51 +0200
commit4d43efd07b27929c9dcc308a76aaefb466bb1245 (patch)
tree2a22cf83753c87c0d305d98f221c7ced37309e36
parentchroot: unify path name handling (diff)
downloadfirejail-4d43efd07b27929c9dcc308a76aaefb466bb1245.tar.gz
firejail-4d43efd07b27929c9dcc308a76aaefb466bb1245.tar.zst
firejail-4d43efd07b27929c9dcc308a76aaefb466bb1245.zip
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
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/join.c59
-rw-r--r--src/firejail/sandbox.c51
-rw-r--r--src/include/rundefs.h2
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);
370char *guess_shell(void); 370char *guess_shell(void);
371 371
372// sandbox.c 372// sandbox.c
373#define SANDBOX_DONE '1'
373int sandbox(void* sandbox_arg); 374int sandbox(void* sandbox_arg);
374void start_application(int no_sandbox, FILE *fp) __attribute__((noreturn)); 375void start_application(int no_sandbox, char *set_sandbox_status) __attribute__((noreturn));
375void set_apparmor(void); 376void set_apparmor(void);
376 377
377// network_main.c 378// 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) {
292 fprintf(stderr, "Error: cannot open umask file\n"); 292 fprintf(stderr, "Error: cannot open umask file\n");
293 exit(1); 293 exit(1);
294 } 294 }
295 if (fscanf(fp, "%3o", &orig_umask) < 1) { 295 if (fscanf(fp, "%o", &orig_umask) != 1) {
296 fprintf(stderr, "Error: cannot read umask\n"); 296 fprintf(stderr, "Error: cannot read umask\n");
297 exit(1); 297 exit(1);
298 } 298 }
@@ -303,66 +303,33 @@ static void extract_umask(pid_t pid) {
303// it is no firejail sandbox at all, return true if the sandbox is complete 303// it is no firejail sandbox at all, return true if the sandbox is complete
304bool is_ready_for_join(const pid_t pid) { 304bool is_ready_for_join(const pid_t pid) {
305 EUID_ASSERT(); 305 EUID_ASSERT();
306 // check if a file "ready-for-join" exists 306 // check if a file /run/firejail/mnt/join exists
307 char *fname; 307 char *fname;
308 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_READY_FOR_JOIN) == -1) 308 if (asprintf(&fname, "/proc/%d/root%s", pid, RUN_JOIN_FILE) == -1)
309 errExit("asprintf"); 309 errExit("asprintf");
310 EUID_ROOT(); 310 EUID_ROOT();
311 FILE *fp = fopen(fname, "re"); 311 int fd = open(fname, O_RDONLY|O_CLOEXEC);
312 EUID_USER(); 312 EUID_USER();
313 free(fname); 313 free(fname);
314 if (!fp)
315 return false;
316 // regular file owned by root
317 int fd = fileno(fp);
318 if (fd == -1) 314 if (fd == -1)
319 errExit("fileno"); 315 return false;
320 struct stat s; 316 struct stat s;
321 if (fstat(fd, &s) == -1) 317 if (fstat(fd, &s) == -1)
322 errExit("fstat"); 318 errExit("fstat");
323 if (!S_ISREG(s.st_mode) || s.st_uid != 0) { 319 if (!S_ISREG(s.st_mode) || s.st_uid != 0) {
324 fclose(fp); 320 close(fd);
325 return false; 321 return false;
326 } 322 }
327 // check if it is non-empty 323 char status;
328 char buf[BUFLEN]; 324 if (read(fd, &status, 1) == 1 && status == SANDBOX_DONE) {
329 if (fgets(buf, BUFLEN, fp) == NULL) { 325 close(fd);
330 fclose(fp); 326 return true;
331 return false;
332 } 327 }
333 fclose(fp); 328 close(fd);
334 // confirm "ready" string was written 329 return false;
335 if (strcmp(buf, "ready\n") != 0)
336 return false;
337
338 // walk down the process tree a few nodes, there should be no firejail leaf
339#define MAXNODES 5
340 pid_t current = pid, next;
341 int i;
342 for (i = 0; i < MAXNODES; i++) {
343 if (find_child(current, &next) == 1) {
344 // found a leaf
345 EUID_ROOT();
346 char *comm = pid_proc_comm(current);
347 EUID_USER();
348 if (!comm) {
349 fprintf(stderr, "Error: cannot read /proc file\n");
350 exit(1);
351 }
352 if (strcmp(comm, "firejail") == 0) {
353 free(comm);
354 return false;
355 }
356 free(comm);
357 break;
358 }
359 current = next;
360 }
361
362 return true;
363} 330}
364 331
365#define SNOOZE 100000 // sleep interval in microseconds 332#define SNOOZE 10000 // sleep interval in microseconds
366void check_join_permission(pid_t pid) { 333void check_join_permission(pid_t pid) {
367 // check if pid belongs to a fully set up firejail sandbox 334 // check if pid belongs to a fully set up firejail sandbox
368 unsigned long i; 335 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 @@
20 20
21#include "firejail.h" 21#include "firejail.h"
22#include "../include/seccomp.h" 22#include "../include/seccomp.h"
23#include <sys/mman.h>
23#include <sys/mount.h> 24#include <sys/mount.h>
24#include <sys/wait.h> 25#include <sys/wait.h>
25#include <sys/stat.h> 26#include <sys/stat.h>
@@ -204,16 +205,17 @@ static void save_umask(void) {
204 } 205 }
205} 206}
206 207
207static FILE *create_ready_for_join_file(void) { 208static char *create_join_file(void) {
208 FILE *fp = fopen(RUN_READY_FOR_JOIN, "wxe"); 209 int fd = open(RUN_JOIN_FILE, O_RDWR|O_CREAT|O_EXCL|O_CLOEXEC, S_IRUSR | S_IWRITE | S_IRGRP | S_IROTH);
209 if (fp) { 210 if (fd == -1)
210 ASSERT_PERMS_STREAM(fp, 0, 0, 0644); 211 errExit("open");
211 return fp; 212 if (ftruncate(fd, 1) == -1)
212 } 213 errExit("ftruncate");
213 else { 214 char *rv = mmap(NULL, 1, PROT_WRITE, MAP_SHARED, fd, 0);
214 fprintf(stderr, "Error: cannot create %s\n", RUN_READY_FOR_JOIN); 215 if (rv == MAP_FAILED)
215 exit(1); 216 errExit("mmap");
216 } 217 close(fd);
218 return rv;
217} 219}
218 220
219static void sandbox_if_up(Bridge *br) { 221static void sandbox_if_up(Bridge *br) {
@@ -472,7 +474,7 @@ static int ok_to_run(const char *program) {
472 return 0; 474 return 0;
473} 475}
474 476
475void start_application(int no_sandbox, FILE *fp) { 477void start_application(int no_sandbox, char *set_sandbox_status) {
476 // set environment 478 // set environment
477 if (no_sandbox == 0) { 479 if (no_sandbox == 0) {
478 env_defaults(); 480 env_defaults();
@@ -492,16 +494,14 @@ void start_application(int no_sandbox, FILE *fp) {
492 if (arg_audit) { 494 if (arg_audit) {
493 assert(arg_audit_prog); 495 assert(arg_audit_prog);
494 496
495 if (fp) {
496 fprintf(fp, "ready\n");
497 fclose(fp);
498 }
499#ifdef HAVE_GCOV 497#ifdef HAVE_GCOV
500 __gcov_dump(); 498 __gcov_dump();
501#endif 499#endif
502#ifdef HAVE_SECCOMP 500#ifdef HAVE_SECCOMP
503 seccomp_install_filters(); 501 seccomp_install_filters();
504#endif 502#endif
503 if (set_sandbox_status)
504 *set_sandbox_status = SANDBOX_DONE;
505 execl(arg_audit_prog, arg_audit_prog, NULL); 505 execl(arg_audit_prog, arg_audit_prog, NULL);
506 506
507 perror("execl"); 507 perror("execl");
@@ -530,16 +530,14 @@ void start_application(int no_sandbox, FILE *fp) {
530 530
531 int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]); 531 int rv = ok_to_run(cfg.original_argv[cfg.original_program_index]);
532 532
533 if (fp) {
534 fprintf(fp, "ready\n");
535 fclose(fp);
536 }
537#ifdef HAVE_GCOV 533#ifdef HAVE_GCOV
538 __gcov_dump(); 534 __gcov_dump();
539#endif 535#endif
540#ifdef HAVE_SECCOMP 536#ifdef HAVE_SECCOMP
541 seccomp_install_filters(); 537 seccomp_install_filters();
542#endif 538#endif
539 if (set_sandbox_status)
540 *set_sandbox_status = SANDBOX_DONE;
543 if (rv) 541 if (rv)
544 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]); 542 execvp(cfg.original_argv[cfg.original_program_index], &cfg.original_argv[cfg.original_program_index]);
545 else 543 else
@@ -591,16 +589,14 @@ void start_application(int no_sandbox, FILE *fp) {
591 if (!arg_command && !arg_quiet) 589 if (!arg_command && !arg_quiet)
592 print_time(); 590 print_time();
593 591
594 if (fp) {
595 fprintf(fp, "ready\n");
596 fclose(fp);
597 }
598#ifdef HAVE_GCOV 592#ifdef HAVE_GCOV
599 __gcov_dump(); 593 __gcov_dump();
600#endif 594#endif
601#ifdef HAVE_SECCOMP 595#ifdef HAVE_SECCOMP
602 seccomp_install_filters(); 596 seccomp_install_filters();
603#endif 597#endif
598 if (set_sandbox_status)
599 *set_sandbox_status = SANDBOX_DONE;
604 execvp(arg[0], arg); 600 execvp(arg[0], arg);
605 } 601 }
606 602
@@ -1162,11 +1158,10 @@ int sandbox(void* sandbox_arg) {
1162 set_caps(); 1158 set_caps();
1163 1159
1164 //**************************************** 1160 //****************************************
1165 // communicate progress of sandbox set up 1161 // relay status information to join option
1166 // to --join
1167 //**************************************** 1162 //****************************************
1168 1163
1169 FILE *rj = create_ready_for_join_file(); 1164 char *set_sandbox_status = create_join_file();
1170 1165
1171 //**************************************** 1166 //****************************************
1172 // create a new user namespace 1167 // create a new user namespace
@@ -1248,10 +1243,10 @@ int sandbox(void* sandbox_arg) {
1248 set_nice(cfg.nice); 1243 set_nice(cfg.nice);
1249 set_rlimits(); 1244 set_rlimits();
1250 1245
1251 start_application(0, rj); 1246 start_application(0, set_sandbox_status);
1252 } 1247 }
1253 1248
1254 fclose(rj); 1249 munmap(set_sandbox_status, 1);
1255 1250
1256 int status = monitor_application(app_pid); // monitor application 1251 int status = monitor_application(app_pid); // monitor application
1257 flush_stdin(); 1252 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 @@
113#define RUN_FSLOGGER_FILE RUN_MNT_DIR "/fslogger" 113#define RUN_FSLOGGER_FILE RUN_MNT_DIR "/fslogger"
114#define RUN_TRACE_FILE RUN_MNT_DIR "/trace" 114#define RUN_TRACE_FILE RUN_MNT_DIR "/trace"
115#define RUN_UMASK_FILE RUN_MNT_DIR "/umask" 115#define RUN_UMASK_FILE RUN_MNT_DIR "/umask"
116#define RUN_JOIN_FILE RUN_MNT_DIR "/join"
116#define RUN_OVERLAY_ROOT RUN_MNT_DIR "/oroot" 117#define RUN_OVERLAY_ROOT RUN_MNT_DIR "/oroot"
117#define RUN_READY_FOR_JOIN RUN_MNT_DIR "/ready-for-join"
118 118
119#endif 119#endif