diff options
-rw-r--r-- | src/firejail/firejail.h | 5 | ||||
-rw-r--r-- | src/firejail/fs_home.c | 208 | ||||
-rw-r--r-- | src/firejail/main.c | 20 | ||||
-rw-r--r-- | src/firejail/profile.c | 8 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 2 | ||||
-rw-r--r-- | src/firejail/usage.c | 5 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 6 | ||||
-rw-r--r-- | src/man/firejail.txt | 12 |
8 files changed, 0 insertions, 266 deletions
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 2a7ff4104..39bc2beeb 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -123,7 +123,6 @@ typedef struct config_t { | |||
123 | char *profile_ignore[MAX_PROFILE_IGNORE]; | 123 | char *profile_ignore[MAX_PROFILE_IGNORE]; |
124 | char *chrootdir; // chroot directory | 124 | char *chrootdir; // chroot directory |
125 | char *home_private; // private home directory | 125 | char *home_private; // private home directory |
126 | char *home_private_keep; // keep list for private home directory | ||
127 | char *etc_private_keep; // keep list for private etc directory | 126 | char *etc_private_keep; // keep list for private etc directory |
128 | char *bin_private_keep; // keep list for private bin directory | 127 | char *bin_private_keep; // keep list for private bin directory |
129 | char *cwd; // current working directory | 128 | char *cwd; // current working directory |
@@ -378,10 +377,6 @@ void fs_private_dev(void); | |||
378 | void fs_private(void); | 377 | void fs_private(void); |
379 | // private mode (--private=homedir) | 378 | // private mode (--private=homedir) |
380 | void fs_private_homedir(void); | 379 | void fs_private_homedir(void); |
381 | // private mode (--private-home=list) | ||
382 | void fs_private_home_list(void); | ||
383 | // check directory list specified by user (--private-home option) - exit if it fails | ||
384 | void fs_check_home_list(void); | ||
385 | // check new private home directory (--private= option) - exit if it fails | 380 | // check new private home directory (--private= option) - exit if it fails |
386 | void fs_check_private_dir(void); | 381 | void fs_check_private_dir(void); |
387 | 382 | ||
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index ad849da3f..2bfabbe89 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -335,74 +335,6 @@ void fs_private(void) { | |||
335 | copy_asoundrc(); | 335 | copy_asoundrc(); |
336 | } | 336 | } |
337 | 337 | ||
338 | static void check_dir_or_file(const char *name) { | ||
339 | assert(name); | ||
340 | struct stat s; | ||
341 | |||
342 | invalid_filename(name); | ||
343 | |||
344 | |||
345 | char *fname = expand_home(name, cfg.homedir); | ||
346 | if (!fname) { | ||
347 | fprintf(stderr, "Error: file %s not found.\n", name); | ||
348 | exit(1); | ||
349 | } | ||
350 | if (fname[0] != '/') { | ||
351 | // If it doesn't start with '/', it must be relative to homedir | ||
352 | char* tmp; | ||
353 | if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1) | ||
354 | errExit("asprintf"); | ||
355 | free(fname); | ||
356 | fname = tmp; | ||
357 | } | ||
358 | if (arg_debug) | ||
359 | printf("Checking %s\n", fname); | ||
360 | if (stat(fname, &s) == -1) { | ||
361 | fprintf(stderr, "Error: file %s not found.\n", fname); | ||
362 | exit(1); | ||
363 | } | ||
364 | |||
365 | // check uid | ||
366 | uid_t uid = getuid(); | ||
367 | gid_t gid = getgid(); | ||
368 | if (s.st_uid != uid || s.st_gid != gid) { | ||
369 | fprintf(stderr, "Error: only files or directories created by the current user are allowed.\n"); | ||
370 | exit(1); | ||
371 | } | ||
372 | |||
373 | // dir or regular file | ||
374 | if (S_ISDIR(s.st_mode) || S_ISREG(s.st_mode)) { | ||
375 | free(fname); | ||
376 | return; | ||
377 | } | ||
378 | |||
379 | if (!is_link(fname)) { | ||
380 | free(fname); | ||
381 | return; | ||
382 | } | ||
383 | |||
384 | fprintf(stderr, "Error: invalid file type, %s.\n", fname); | ||
385 | exit(1); | ||
386 | } | ||
387 | |||
388 | // check directory list specified by user (--private-home option) - exit if it fails | ||
389 | void fs_check_home_list(void) { | ||
390 | if (strstr(cfg.home_private_keep, "..")) { | ||
391 | fprintf(stderr, "Error: invalid private-home list\n"); | ||
392 | exit(1); | ||
393 | } | ||
394 | |||
395 | char *dlist = strdup(cfg.home_private_keep); | ||
396 | if (!dlist) | ||
397 | errExit("strdup"); | ||
398 | |||
399 | char *ptr = strtok(dlist, ","); | ||
400 | check_dir_or_file(ptr); | ||
401 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
402 | check_dir_or_file(ptr); | ||
403 | |||
404 | free(dlist); | ||
405 | } | ||
406 | 338 | ||
407 | // check new private home directory (--private= option) - exit if it fails | 339 | // check new private home directory (--private= option) - exit if it fails |
408 | void fs_check_private_dir(void) { | 340 | void fs_check_private_dir(void) { |
@@ -441,143 +373,3 @@ void fs_check_private_dir(void) { | |||
441 | } | 373 | } |
442 | } | 374 | } |
443 | 375 | ||
444 | |||
445 | static void duplicate(char *name) { | ||
446 | char *cmd; | ||
447 | |||
448 | char *fname = expand_home(name, cfg.homedir); | ||
449 | if (!fname) { | ||
450 | fprintf(stderr, "Error: file %s not found.\n", name); | ||
451 | exit(1); | ||
452 | } | ||
453 | if (fname[0] != '/') { | ||
454 | // If it doesn't start with '/', it must be relative to homedir | ||
455 | char* tmp; | ||
456 | if (asprintf(&tmp, "%s/%s", cfg.homedir, fname) == -1) | ||
457 | errExit("asprintf"); | ||
458 | free(fname); | ||
459 | fname = tmp; | ||
460 | } | ||
461 | |||
462 | // copy the file | ||
463 | if (asprintf(&cmd, "%s -a --parents \"%s\" %s", RUN_CP_COMMAND, fname, RUN_HOME_DIR) == -1) | ||
464 | errExit("asprintf"); | ||
465 | if (arg_debug) | ||
466 | printf("%s\n", cmd); | ||
467 | if (system(cmd)) | ||
468 | errExit("system cp -a --parents"); | ||
469 | fs_logger2("clone", fname); | ||
470 | free(cmd); | ||
471 | free(fname); | ||
472 | } | ||
473 | |||
474 | |||
475 | // private mode (--private-home=list): | ||
476 | // mount homedir on top of /home/user, | ||
477 | // tmpfs on top of /root in nonroot mode, | ||
478 | // tmpfs on top of /tmp in root mode, | ||
479 | // set skel files, | ||
480 | // restore .Xauthority | ||
481 | void fs_private_home_list(void) { | ||
482 | char *homedir = cfg.homedir; | ||
483 | char *private_list = cfg.home_private_keep; | ||
484 | assert(homedir); | ||
485 | assert(private_list); | ||
486 | |||
487 | int xflag = store_xauthority(); | ||
488 | int aflag = store_asoundrc(); | ||
489 | |||
490 | uid_t u = getuid(); | ||
491 | gid_t g = getgid(); | ||
492 | struct stat s; | ||
493 | if (stat(homedir, &s) == -1) { | ||
494 | fprintf(stderr, "Error: cannot find user home directory\n"); | ||
495 | exit(1); | ||
496 | } | ||
497 | |||
498 | // create /tmp/firejail/mnt/home directory | ||
499 | fs_build_mnt_dir(); | ||
500 | int rv = mkdir(RUN_HOME_DIR, 0755); | ||
501 | if (rv == -1) | ||
502 | errExit("mkdir"); | ||
503 | if (chown(RUN_HOME_DIR, u, g) < 0) | ||
504 | errExit("chown"); | ||
505 | if (chmod(RUN_HOME_DIR, 0755) < 0) | ||
506 | errExit("chmod"); | ||
507 | |||
508 | |||
509 | // copy the list of files in the new home directory | ||
510 | // using a new child process without root privileges | ||
511 | fs_logger_print(); // save the current log | ||
512 | pid_t child = fork(); | ||
513 | if (child < 0) | ||
514 | errExit("fork"); | ||
515 | if (child == 0) { | ||
516 | if (arg_debug) | ||
517 | printf("Copying files in the new home:\n"); | ||
518 | |||
519 | // drop privileges | ||
520 | if (setgroups(0, NULL) < 0) | ||
521 | errExit("setgroups"); | ||
522 | if (setgid(getgid()) < 0) | ||
523 | errExit("setgid/getgid"); | ||
524 | if (setuid(getuid()) < 0) | ||
525 | errExit("setuid/getuid"); | ||
526 | |||
527 | // copy the list of files in the new home directory | ||
528 | char *dlist = strdup(cfg.home_private_keep); | ||
529 | if (!dlist) | ||
530 | errExit("strdup"); | ||
531 | |||
532 | char *ptr = strtok(dlist, ","); | ||
533 | duplicate(ptr); | ||
534 | |||
535 | while ((ptr = strtok(NULL, ",")) != NULL) | ||
536 | duplicate(ptr); | ||
537 | free(dlist); | ||
538 | fs_logger_print(); | ||
539 | exit(0); | ||
540 | } | ||
541 | // wait for the child to finish | ||
542 | waitpid(child, NULL, 0); | ||
543 | |||
544 | // mount bind private_homedir on top of homedir | ||
545 | char *newhome; | ||
546 | if (asprintf(&newhome, "%s%s", RUN_HOME_DIR, cfg.homedir) == -1) | ||
547 | errExit("asprintf"); | ||
548 | |||
549 | if (arg_debug) | ||
550 | printf("Mount-bind %s on top of %s\n", newhome, homedir); | ||
551 | if (mount(newhome, homedir, NULL, MS_BIND|MS_REC, NULL) < 0) | ||
552 | errExit("mount bind"); | ||
553 | fs_logger2("mount", homedir); | ||
554 | // preserve mode and ownership | ||
555 | // if (chown(homedir, s.st_uid, s.st_gid) == -1) | ||
556 | // errExit("mount-bind chown"); | ||
557 | // if (chmod(homedir, s.st_mode) == -1) | ||
558 | // errExit("mount-bind chmod"); | ||
559 | |||
560 | if (u != 0) { | ||
561 | // mask /root | ||
562 | if (arg_debug) | ||
563 | printf("Mounting a new /root directory\n"); | ||
564 | if (mount("tmpfs", "/root", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=700,gid=0") < 0) | ||
565 | errExit("mounting home directory"); | ||
566 | fs_logger("mount tmpfs on /root"); | ||
567 | } | ||
568 | else { | ||
569 | // mask /home | ||
570 | if (arg_debug) | ||
571 | printf("Mounting a new /home directory\n"); | ||
572 | if (mount("tmpfs", "/home", "tmpfs", MS_NOSUID | MS_NODEV | MS_STRICTATIME | MS_REC, "mode=755,gid=0") < 0) | ||
573 | errExit("mounting home directory"); | ||
574 | fs_logger("mount tmpfs on /home"); | ||
575 | } | ||
576 | |||
577 | skel(homedir, u, g); | ||
578 | if (xflag) | ||
579 | copy_xauthority(); | ||
580 | if (aflag) | ||
581 | copy_asoundrc(); | ||
582 | } | ||
583 | |||
diff --git a/src/firejail/main.c b/src/firejail/main.c index 2c63bf7b0..1597a7efc 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -891,11 +891,6 @@ int main(int argc, char **argv) { | |||
891 | else if (strcmp(argv[i], "--private") == 0) | 891 | else if (strcmp(argv[i], "--private") == 0) |
892 | arg_private = 1; | 892 | arg_private = 1; |
893 | else if (strncmp(argv[i], "--private=", 10) == 0) { | 893 | else if (strncmp(argv[i], "--private=", 10) == 0) { |
894 | if (cfg.home_private_keep) { | ||
895 | fprintf(stderr, "Error: a private list of files was already defined with --private-home option.\n"); | ||
896 | exit(1); | ||
897 | } | ||
898 | |||
899 | // extract private home dirname | 894 | // extract private home dirname |
900 | cfg.home_private = argv[i] + 10; | 895 | cfg.home_private = argv[i] + 10; |
901 | if (*cfg.home_private == '\0') { | 896 | if (*cfg.home_private == '\0') { |
@@ -905,21 +900,6 @@ int main(int argc, char **argv) { | |||
905 | fs_check_private_dir(); | 900 | fs_check_private_dir(); |
906 | arg_private = 1; | 901 | arg_private = 1; |
907 | } | 902 | } |
908 | else if (strncmp(argv[i], "--private-home=", 15) == 0) { | ||
909 | if (cfg.home_private) { | ||
910 | fprintf(stderr, "Error: a private home directory was already defined with --private option.\n"); | ||
911 | exit(1); | ||
912 | } | ||
913 | |||
914 | // extract private home dirname | ||
915 | cfg.home_private_keep = argv[i] + 15; | ||
916 | if (*cfg.home_private_keep == '\0') { | ||
917 | fprintf(stderr, "Error: invalid private-home option\n"); | ||
918 | exit(1); | ||
919 | } | ||
920 | fs_check_home_list(); | ||
921 | arg_private = 1; | ||
922 | } | ||
923 | else if (strcmp(argv[i], "--private-dev") == 0) { | 903 | else if (strcmp(argv[i], "--private-dev") == 0) { |
924 | arg_private_dev = 1; | 904 | arg_private_dev = 1; |
925 | } | 905 | } |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index bbdeafd60..bbec17447 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -304,14 +304,6 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
304 | return 0; | 304 | return 0; |
305 | } | 305 | } |
306 | 306 | ||
307 | // private home list of files and directories | ||
308 | if (strncmp(ptr, "private-home ", 13) == 0) { | ||
309 | cfg.home_private_keep = ptr + 13; | ||
310 | fs_check_home_list(); | ||
311 | arg_private = 1; | ||
312 | return 0; | ||
313 | } | ||
314 | |||
315 | // private /etc list of files and directories | 307 | // private /etc list of files and directories |
316 | if (strncmp(ptr, "private-etc ", 12) == 0) { | 308 | if (strncmp(ptr, "private-etc ", 12) == 0) { |
317 | cfg.etc_private_keep = ptr + 12; | 309 | cfg.etc_private_keep = ptr + 12; |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index a876f6b5f..0ad8e2f65 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -412,8 +412,6 @@ int sandbox(void* sandbox_arg) { | |||
412 | if (arg_private) { | 412 | if (arg_private) { |
413 | if (cfg.home_private) // --private= | 413 | if (cfg.home_private) // --private= |
414 | fs_private_homedir(); | 414 | fs_private_homedir(); |
415 | else if (cfg.home_private_keep) // --private-home= | ||
416 | fs_private_home_list(); | ||
417 | else // --private | 415 | else // --private |
418 | fs_private(); | 416 | fs_private(); |
419 | } | 417 | } |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index dcd6a388e..b773cc146 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -221,11 +221,6 @@ void usage(void) { | |||
221 | printf("\t\tand copy the programs in the list. The same directory is\n"); | 221 | printf("\t\tand copy the programs in the list. The same directory is\n"); |
222 | printf("\t\talso bind-mounted over /sbin, /usr/bin and /usr/sbin.\n\n"); | 222 | printf("\t\talso bind-mounted over /sbin, /usr/bin and /usr/sbin.\n\n"); |
223 | 223 | ||
224 | printf("\t--private-home=file,directory - build a new user home in a temporary\n"); | ||
225 | printf("\t\tfilesystem, and copy the files and directories in the list in\n"); | ||
226 | printf("\t\tthe new home. All modifications are discarded when the sandbox\n"); | ||
227 | printf("\t\tis closed.\n\n"); | ||
228 | |||
229 | printf("\t--private-dev - create a new /dev directory. Only dri, null, full, zero,\n"); | 224 | printf("\t--private-dev - create a new /dev directory. Only dri, null, full, zero,\n"); |
230 | printf("\t\tty, pst, ptms, random, urandom, log and shm devices are\n"); | 225 | printf("\t\tty, pst, ptms, random, urandom, log and shm devices are\n"); |
231 | printf("\t\tavailable.\n\n"); | 226 | printf("\t\tavailable.\n\n"); |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 90c59d753..1e8555d9c 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -146,12 +146,6 @@ Use directory as user home. | |||
146 | Build a new /bin in a temporary filesystem, and copy the programs in the list. | 146 | Build a new /bin in a temporary filesystem, and copy the programs in the list. |
147 | The same directory is also bind-mounted over /sbin, /usr/bin and /usr/sbin. | 147 | The same directory is also bind-mounted over /sbin, /usr/bin and /usr/sbin. |
148 | .TP | 148 | .TP |
149 | \fBprivate-home file,directory | ||
150 | Build a new user home in a temporary | ||
151 | filesystem, and copy the files and directories in the list in the | ||
152 | new home. All modifications are discarded when the sandbox is | ||
153 | closed. | ||
154 | .TP | ||
155 | \fBprivate-dev | 149 | \fBprivate-dev |
156 | Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, urandom, log and shm devices are available. | 150 | Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, urandom, log and shm devices are available. |
157 | .TP | 151 | .TP |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index e60ecadaa..ee019a24f 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -961,18 +961,6 @@ $ ls /bin | |||
961 | bash cat ls sed | 961 | bash cat ls sed |
962 | 962 | ||
963 | .TP | 963 | .TP |
964 | \fB\-\-private-home=file,directory | ||
965 | Build a new user home in a temporary | ||
966 | filesystem, and copy the files and directories in the list in the | ||
967 | new home. All modifications are discarded when the sandbox is | ||
968 | closed. | ||
969 | .br | ||
970 | |||
971 | .br | ||
972 | Example: | ||
973 | .br | ||
974 | $ firejail \-\-private-home=.mozilla firefox | ||
975 | .TP | ||
976 | \fB\-\-private-dev | 964 | \fB\-\-private-dev |
977 | Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, urandom, log and shm devices are available. | 965 | Create a new /dev directory. Only dri, null, full, zero, tty, pts, ptmx, random, urandom, log and shm devices are available. |
978 | .br | 966 | .br |