diff options
Diffstat (limited to 'src/firejail/fs_whitelist.c')
-rw-r--r-- | src/firejail/fs_whitelist.c | 61 |
1 files changed, 59 insertions, 2 deletions
diff --git a/src/firejail/fs_whitelist.c b/src/firejail/fs_whitelist.c index 849861805..b1c2774e2 100644 --- a/src/firejail/fs_whitelist.c +++ b/src/firejail/fs_whitelist.c | |||
@@ -254,7 +254,16 @@ static void whitelist_path(ProfileEntry *entry) { | |||
254 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1) | 254 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_OPT_DIR, fname) == -1) |
255 | errExit("asprintf"); | 255 | errExit("asprintf"); |
256 | } | 256 | } |
257 | else if (entry->srv_dir) { | ||
258 | fname = path + 4; // strlen("/srv") | ||
259 | if (*fname == '\0') { | ||
260 | fprintf(stderr, "Error: file %s is not in /srv directory, exiting...\n", path); | ||
261 | exit(1); | ||
262 | } | ||
257 | 263 | ||
264 | if (asprintf(&wfile, "%s/%s", RUN_WHITELIST_SRV_DIR, fname) == -1) | ||
265 | errExit("asprintf"); | ||
266 | } | ||
258 | // check if the file exists | 267 | // check if the file exists |
259 | struct stat s; | 268 | struct stat s; |
260 | if (wfile && stat(wfile, &s) == 0) { | 269 | if (wfile && stat(wfile, &s) == 0) { |
@@ -317,7 +326,7 @@ void fs_whitelist(void) { | |||
317 | int var_dir = 0; // /var directory flag | 326 | int var_dir = 0; // /var directory flag |
318 | int dev_dir = 0; // /dev directory flag | 327 | int dev_dir = 0; // /dev directory flag |
319 | int opt_dir = 0; // /opt directory flag | 328 | int opt_dir = 0; // /opt directory flag |
320 | 329 | int srv_dir = 0; // /srv directory flag | |
321 | // verify whitelist files, extract symbolic links, etc. | 330 | // verify whitelist files, extract symbolic links, etc. |
322 | while (entry) { | 331 | while (entry) { |
323 | // handle only whitelist commands | 332 | // handle only whitelist commands |
@@ -387,7 +396,9 @@ void fs_whitelist(void) { | |||
387 | dev_dir = 1; | 396 | dev_dir = 1; |
388 | else if (strncmp(new_name, "/opt/", 5) == 0) | 397 | else if (strncmp(new_name, "/opt/", 5) == 0) |
389 | opt_dir = 1; | 398 | opt_dir = 1; |
390 | 399 | else if (strncmp(new_name, "/srv/", 5) == 0) | |
400 | opt_dir = 1; | ||
401 | |||
391 | continue; | 402 | continue; |
392 | } | 403 | } |
393 | 404 | ||
@@ -481,6 +492,16 @@ void fs_whitelist(void) { | |||
481 | goto errexit; | 492 | goto errexit; |
482 | } | 493 | } |
483 | } | 494 | } |
495 | else if (strncmp(new_name, "/srv/", 5) == 0) { | ||
496 | entry->srv_dir = 1; | ||
497 | srv_dir = 1; | ||
498 | // both path and absolute path are under /srv | ||
499 | if (strncmp(fname, "/srv/", 5) != 0) { | ||
500 | if (arg_debug) | ||
501 | fprintf(stderr, "Debug %d: fname #%s#\n", __LINE__, fname); | ||
502 | goto errexit; | ||
503 | } | ||
504 | } | ||
484 | else { | 505 | else { |
485 | if (arg_debug) | 506 | if (arg_debug) |
486 | fprintf(stderr, "Debug %d: \n", __LINE__); | 507 | fprintf(stderr, "Debug %d: \n", __LINE__); |
@@ -675,6 +696,36 @@ void fs_whitelist(void) { | |||
675 | fs_logger("tmpfs /opt"); | 696 | fs_logger("tmpfs /opt"); |
676 | } | 697 | } |
677 | 698 | ||
699 | // /srv mountpoint | ||
700 | if (srv_dir) { | ||
701 | // check if /srv directory exists | ||
702 | struct stat s; | ||
703 | if (stat("/srv", &s) == 0) { | ||
704 | // keep a copy of real /srv directory in RUN_WHITELIST_SRV_DIR | ||
705 | int rv = mkdir(RUN_WHITELIST_SRV_DIR, 0755); | ||
706 | if (rv == -1) | ||
707 | errExit("mkdir"); | ||
708 | if (chown(RUN_WHITELIST_SRV_DIR, 0, 0) < 0) | ||
709 | errExit("chown"); | ||
710 | if (chmod(RUN_WHITELIST_SRV_DIR, 0755) < 0) | ||
711 | errExit("chmod"); | ||
712 | |||
713 | if (mount("/srv", RUN_WHITELIST_SRV_DIR, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
714 | errExit("mount bind"); | ||
715 | |||
716 | // mount tmpfs on /srv | ||
717 | if (arg_debug || arg_debug_whitelists) | ||
718 | printf("Mounting tmpfs on /srv directory\n"); | ||
719 | if (mount("tmpfs", "/srv", "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
720 | errExit("mounting tmpfs on /srv"); | ||
721 | fs_logger("tmpfs /srv"); | ||
722 | } | ||
723 | else | ||
724 | srv_dir = 0; | ||
725 | } | ||
726 | |||
727 | |||
728 | |||
678 | // go through profile rules again, and interpret whitelist commands | 729 | // go through profile rules again, and interpret whitelist commands |
679 | entry = cfg.profile; | 730 | entry = cfg.profile; |
680 | while (entry) { | 731 | while (entry) { |
@@ -766,6 +817,12 @@ void fs_whitelist(void) { | |||
766 | fs_logger2("tmpfs", RUN_WHITELIST_MNT_DIR); | 817 | fs_logger2("tmpfs", RUN_WHITELIST_MNT_DIR); |
767 | } | 818 | } |
768 | 819 | ||
820 | // mask the real /srv directory, currently mounted on RUN_WHITELIST_SRV_DIR | ||
821 | if (srv_dir) { | ||
822 | if (mount("tmpfs", RUN_WHITELIST_SRV_DIR, "tmpfs", MS_NOSUID | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
823 | errExit("mount tmpfs"); | ||
824 | fs_logger2("tmpfs", RUN_WHITELIST_SRV_DIR); | ||
825 | |||
769 | if (new_name) | 826 | if (new_name) |
770 | free(new_name); | 827 | free(new_name); |
771 | 828 | ||