diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/firejail/main.c | 18 | ||||
-rw-r--r-- | src/firejail/usage.c | 4 | ||||
-rw-r--r-- | src/firejail/util.c | 71 | ||||
-rw-r--r-- | src/firemon/procevent.c | 2 | ||||
-rw-r--r-- | src/man/firejail.txt | 10 |
5 files changed, 80 insertions, 25 deletions
diff --git a/src/firejail/main.c b/src/firejail/main.c index 9f6fa5142..acae7c3dd 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -263,6 +263,23 @@ static void run_cmd_and_exit(int i, int argc, char **argv) { | |||
263 | printf("\n"); | 263 | printf("\n"); |
264 | exit(0); | 264 | exit(0); |
265 | } | 265 | } |
266 | else if (strcmp(argv[i], "--overlay-clean") == 0) { | ||
267 | char *path; | ||
268 | if (asprintf(&path, "%s/.firejail", cfg.homedir) == -1) | ||
269 | errExit("asprintf"); | ||
270 | EUID_ROOT(); | ||
271 | if (setreuid(0, 0) < 0) | ||
272 | errExit("setreuid"); | ||
273 | if (setregid(0, 0) < 0) | ||
274 | errExit("setregid"); | ||
275 | errno = 0; | ||
276 | int rv = remove_directory(path); | ||
277 | if (rv) { | ||
278 | fprintf(stderr, "Error: cannot removed overlays stored in ~/.firejail directory, errno %d\n", errno); | ||
279 | exit(1); | ||
280 | } | ||
281 | exit(0); | ||
282 | } | ||
266 | #ifdef HAVE_X11 | 283 | #ifdef HAVE_X11 |
267 | else if (strcmp(argv[i], "--x11") == 0) { | 284 | else if (strcmp(argv[i], "--x11") == 0) { |
268 | if (checkcfg(CFG_X11)) { | 285 | if (checkcfg(CFG_X11)) { |
@@ -744,6 +761,7 @@ int main(int argc, char **argv) { | |||
744 | strcmp(argv[i], "--debug-protocols") == 0 || | 761 | strcmp(argv[i], "--debug-protocols") == 0 || |
745 | strcmp(argv[i], "--help") == 0 || | 762 | strcmp(argv[i], "--help") == 0 || |
746 | strcmp(argv[i], "--version") == 0 || | 763 | strcmp(argv[i], "--version") == 0 || |
764 | strcmp(argv[i], "--overlay-clean") == 0 || | ||
747 | strncmp(argv[i], "--dns.print=", 12) == 0 || | 765 | strncmp(argv[i], "--dns.print=", 12) == 0 || |
748 | strncmp(argv[i], "--bandwidth=", 12) == 0 || | 766 | strncmp(argv[i], "--bandwidth=", 12) == 0 || |
749 | strncmp(argv[i], "--caps.print=", 13) == 0 || | 767 | strncmp(argv[i], "--caps.print=", 13) == 0 || |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index baba93791..03558cca7 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -179,11 +179,13 @@ void usage(void) { | |||
179 | printf("\t$HOME/.firejail directory. (OverlayFS support is required in\n"); | 179 | printf("\t$HOME/.firejail directory. (OverlayFS support is required in\n"); |
180 | printf("\tLinux kernel for this option to work). \n\n"); | 180 | printf("\tLinux kernel for this option to work). \n\n"); |
181 | 181 | ||
182 | printf(" --overlay-clean - clean all overlays stored in $HOME/.firejail directory.\n\n"); | ||
183 | |||
182 | printf(" --overlay-tmpfs - mount a filesystem overlay on top of the current\n"); | 184 | printf(" --overlay-tmpfs - mount a filesystem overlay on top of the current\n"); |
183 | printf("\tfilesystem. The upper layer is stored in a tmpfs filesystem,\n"); | 185 | printf("\tfilesystem. The upper layer is stored in a tmpfs filesystem,\n"); |
184 | printf("\tand it is discarded when the sandbox is closed. (OverlayFS\n"); | 186 | printf("\tand it is discarded when the sandbox is closed. (OverlayFS\n"); |
185 | printf("\tsupport is required in Linux kernel for this option to work).\n\n"); | 187 | printf("\tsupport is required in Linux kernel for this option to work).\n\n"); |
186 | 188 | ||
187 | printf(" --private - mount new /root and /home/user directories in temporary\n"); | 189 | printf(" --private - mount new /root and /home/user directories in temporary\n"); |
188 | printf("\tfilesystems. All modifications are discarded when the sandbox is\n"); | 190 | printf("\tfilesystems. All modifications are discarded when the sandbox is\n"); |
189 | printf("\tclosed.\n\n"); | 191 | printf("\tclosed.\n\n"); |
diff --git a/src/firejail/util.c b/src/firejail/util.c index dc906532f..24bb71e4c 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -17,7 +17,9 @@ | |||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | 17 | * with this program; if not, write to the Free Software Foundation, Inc., |
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | 18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. |
19 | */ | 19 | */ |
20 | #define _XOPEN_SOURCE 500 | ||
20 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include <ftw.h> | ||
21 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
22 | #include <fcntl.h> | 24 | #include <fcntl.h> |
23 | #include <syslog.h> | 25 | #include <syslog.h> |
@@ -78,7 +80,7 @@ void drop_privs(int nogroups) { | |||
78 | 80 | ||
79 | int mkpath_as_root(const char* path) { | 81 | int mkpath_as_root(const char* path) { |
80 | assert(path && *path); | 82 | assert(path && *path); |
81 | 83 | ||
82 | // work on a copy of the path | 84 | // work on a copy of the path |
83 | char *file_path = strdup(path); | 85 | char *file_path = strdup(path); |
84 | if (!file_path) | 86 | if (!file_path) |
@@ -101,19 +103,18 @@ int mkpath_as_root(const char* path) { | |||
101 | if (chown(file_path, 0, 0) == -1) | 103 | if (chown(file_path, 0, 0) == -1) |
102 | errExit("chown"); | 104 | errExit("chown"); |
103 | done = 1; | 105 | done = 1; |
104 | } | 106 | } |
105 | 107 | ||
106 | *p='/'; | 108 | *p='/'; |
107 | } | 109 | } |
108 | if (done) | 110 | if (done) |
109 | fs_logger2("mkpath", path); | 111 | fs_logger2("mkpath", path); |
110 | 112 | ||
111 | free(file_path); | 113 | free(file_path); |
112 | return 0; | 114 | return 0; |
113 | } | 115 | } |
114 | 116 | ||
115 | 117 | ||
116 | |||
117 | void logsignal(int s) { | 118 | void logsignal(int s) { |
118 | if (!arg_debug) | 119 | if (!arg_debug) |
119 | return; | 120 | return; |
@@ -211,12 +212,13 @@ int copy_file(const char *srcname, const char *destname) { | |||
211 | return 0; | 212 | return 0; |
212 | } | 213 | } |
213 | 214 | ||
215 | |||
214 | // return 1 if the file is a directory | 216 | // return 1 if the file is a directory |
215 | int is_dir(const char *fname) { | 217 | int is_dir(const char *fname) { |
216 | assert(fname); | 218 | assert(fname); |
217 | if (*fname == '\0') | 219 | if (*fname == '\0') |
218 | return 0; | 220 | return 0; |
219 | 221 | ||
220 | // if fname doesn't end in '/', add one | 222 | // if fname doesn't end in '/', add one |
221 | int rv; | 223 | int rv; |
222 | struct stat s; | 224 | struct stat s; |
@@ -227,20 +229,21 @@ int is_dir(const char *fname) { | |||
227 | if (asprintf(&tmp, "%s/", fname) == -1) { | 229 | if (asprintf(&tmp, "%s/", fname) == -1) { |
228 | fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); | 230 | fprintf(stderr, "Error: cannot allocate memory, %s:%d\n", __FILE__, __LINE__); |
229 | errExit("asprintf"); | 231 | errExit("asprintf"); |
230 | } | 232 | } |
231 | rv = stat(tmp, &s); | 233 | rv = stat(tmp, &s); |
232 | free(tmp); | 234 | free(tmp); |
233 | } | 235 | } |
234 | 236 | ||
235 | if (rv == -1) | 237 | if (rv == -1) |
236 | return 0; | 238 | return 0; |
237 | 239 | ||
238 | if (S_ISDIR(s.st_mode)) | 240 | if (S_ISDIR(s.st_mode)) |
239 | return 1; | 241 | return 1; |
240 | 242 | ||
241 | return 0; | 243 | return 0; |
242 | } | 244 | } |
243 | 245 | ||
246 | |||
244 | // return 1 if the file is a link | 247 | // return 1 if the file is a link |
245 | int is_link(const char *fname) { | 248 | int is_link(const char *fname) { |
246 | assert(fname); | 249 | assert(fname); |
@@ -325,7 +328,7 @@ char *split_comma(char *str) { | |||
325 | 328 | ||
326 | int not_unsigned(const char *str) { | 329 | int not_unsigned(const char *str) { |
327 | EUID_ASSERT(); | 330 | EUID_ASSERT(); |
328 | 331 | ||
329 | int rv = 0; | 332 | int rv = 0; |
330 | const char *ptr = str; | 333 | const char *ptr = str; |
331 | while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { | 334 | while (*ptr != ' ' && *ptr != '\t' && *ptr != '\0') { |
@@ -347,7 +350,7 @@ int find_child(pid_t parent, pid_t *child) { | |||
347 | *child = 0; // use it to flag a found child | 350 | *child = 0; // use it to flag a found child |
348 | 351 | ||
349 | DIR *dir; | 352 | DIR *dir; |
350 | EUID_ROOT(); // grsecurity fix | 353 | EUID_ROOT(); // grsecurity fix |
351 | if (!(dir = opendir("/proc"))) { | 354 | if (!(dir = opendir("/proc"))) { |
352 | // sleep 2 seconds and try again | 355 | // sleep 2 seconds and try again |
353 | sleep(2); | 356 | sleep(2); |
@@ -404,13 +407,11 @@ int find_child(pid_t parent, pid_t *child) { | |||
404 | } | 407 | } |
405 | 408 | ||
406 | 409 | ||
407 | |||
408 | void extract_command_name(int index, char **argv) { | 410 | void extract_command_name(int index, char **argv) { |
409 | EUID_ASSERT(); | 411 | EUID_ASSERT(); |
410 | assert(argv); | 412 | assert(argv); |
411 | assert(argv[index]); | 413 | assert(argv[index]); |
412 | 414 | ||
413 | |||
414 | // configure command index | 415 | // configure command index |
415 | cfg.original_program_index = index; | 416 | cfg.original_program_index = index; |
416 | 417 | ||
@@ -447,7 +448,6 @@ void extract_command_name(int index, char **argv) { | |||
447 | exit(1); | 448 | exit(1); |
448 | } | 449 | } |
449 | 450 | ||
450 | |||
451 | char *tmp = strdup(ptr); | 451 | char *tmp = strdup(ptr); |
452 | if (!tmp) | 452 | if (!tmp) |
453 | errExit("strdup"); | 453 | errExit("strdup"); |
@@ -533,6 +533,7 @@ void notify_other(int fd) { | |||
533 | fclose(stream); | 533 | fclose(stream); |
534 | } | 534 | } |
535 | 535 | ||
536 | |||
536 | // This function takes a pathname supplied by the user and expands '~' and | 537 | // This function takes a pathname supplied by the user and expands '~' and |
537 | // '${HOME}' at the start, to refer to a path relative to the user's home | 538 | // '${HOME}' at the start, to refer to a path relative to the user's home |
538 | // directory (supplied). | 539 | // directory (supplied). |
@@ -541,7 +542,7 @@ void notify_other(int fd) { | |||
541 | char *expand_home(const char *path, const char* homedir) { | 542 | char *expand_home(const char *path, const char* homedir) { |
542 | assert(path); | 543 | assert(path); |
543 | assert(homedir); | 544 | assert(homedir); |
544 | 545 | ||
545 | // Replace home macro | 546 | // Replace home macro |
546 | char *new_name = NULL; | 547 | char *new_name = NULL; |
547 | if (strncmp(path, "${HOME}", 7) == 0) { | 548 | if (strncmp(path, "${HOME}", 7) == 0) { |
@@ -554,10 +555,11 @@ char *expand_home(const char *path, const char* homedir) { | |||
554 | errExit("asprintf"); | 555 | errExit("asprintf"); |
555 | return new_name; | 556 | return new_name; |
556 | } | 557 | } |
557 | 558 | ||
558 | return strdup(path); | 559 | return strdup(path); |
559 | } | 560 | } |
560 | 561 | ||
562 | |||
561 | // Equivalent to the GNU version of basename, which is incompatible with | 563 | // Equivalent to the GNU version of basename, which is incompatible with |
562 | // the POSIX basename. A few lines of code saves any portability pain. | 564 | // the POSIX basename. A few lines of code saves any portability pain. |
563 | // https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename | 565 | // https://www.gnu.org/software/libc/manual/html_node/Finding-Tokens-in-a-String.html#index-basename |
@@ -568,17 +570,18 @@ const char *gnu_basename(const char *path) { | |||
568 | return last_slash+1; | 570 | return last_slash+1; |
569 | } | 571 | } |
570 | 572 | ||
573 | |||
571 | uid_t pid_get_uid(pid_t pid) { | 574 | uid_t pid_get_uid(pid_t pid) { |
572 | EUID_ASSERT(); | 575 | EUID_ASSERT(); |
573 | uid_t rv = 0; | 576 | uid_t rv = 0; |
574 | 577 | ||
575 | // open status file | 578 | // open status file |
576 | char *file; | 579 | char *file; |
577 | if (asprintf(&file, "/proc/%u/status", pid) == -1) { | 580 | if (asprintf(&file, "/proc/%u/status", pid) == -1) { |
578 | perror("asprintf"); | 581 | perror("asprintf"); |
579 | exit(1); | 582 | exit(1); |
580 | } | 583 | } |
581 | EUID_ROOT(); // grsecurity fix | 584 | EUID_ROOT(); // grsecurity fix |
582 | FILE *fp = fopen(file, "r"); | 585 | FILE *fp = fopen(file, "r"); |
583 | if (!fp) { | 586 | if (!fp) { |
584 | free(file); | 587 | free(file); |
@@ -597,16 +600,16 @@ uid_t pid_get_uid(pid_t pid) { | |||
597 | } | 600 | } |
598 | if (*ptr == '\0') | 601 | if (*ptr == '\0') |
599 | break; | 602 | break; |
600 | 603 | ||
601 | rv = atoi(ptr); | 604 | rv = atoi(ptr); |
602 | break; // break regardless! | 605 | break; // break regardless! |
603 | } | 606 | } |
604 | } | 607 | } |
605 | 608 | ||
606 | fclose(fp); | 609 | fclose(fp); |
607 | free(file); | 610 | free(file); |
608 | EUID_USER(); // grsecurity fix | 611 | EUID_USER(); // grsecurity fix |
609 | 612 | ||
610 | if (rv == 0) { | 613 | if (rv == 0) { |
611 | fprintf(stderr, "Error: cannot read /proc file\n"); | 614 | fprintf(stderr, "Error: cannot read /proc file\n"); |
612 | exit(1); | 615 | exit(1); |
@@ -614,14 +617,15 @@ uid_t pid_get_uid(pid_t pid) { | |||
614 | return rv; | 617 | return rv; |
615 | } | 618 | } |
616 | 619 | ||
620 | |||
617 | void invalid_filename(const char *fname) { | 621 | void invalid_filename(const char *fname) { |
618 | EUID_ASSERT(); | 622 | EUID_ASSERT(); |
619 | assert(fname); | 623 | assert(fname); |
620 | const char *ptr = fname; | 624 | const char *ptr = fname; |
621 | 625 | ||
622 | if (arg_debug_check_filename) | 626 | if (arg_debug_check_filename) |
623 | printf("Checking filename %s\n", fname); | 627 | printf("Checking filename %s\n", fname); |
624 | 628 | ||
625 | if (strncmp(ptr, "${HOME}", 7) == 0) | 629 | if (strncmp(ptr, "${HOME}", 7) == 0) |
626 | ptr = fname + 7; | 630 | ptr = fname + 7; |
627 | else if (strncmp(ptr, "${PATH}", 7) == 0) | 631 | else if (strncmp(ptr, "${PATH}", 7) == 0) |
@@ -637,6 +641,7 @@ void invalid_filename(const char *fname) { | |||
637 | } | 641 | } |
638 | } | 642 | } |
639 | 643 | ||
644 | |||
640 | uid_t get_tty_gid(void) { | 645 | uid_t get_tty_gid(void) { |
641 | // find tty group id | 646 | // find tty group id |
642 | gid_t ttygid = 0; | 647 | gid_t ttygid = 0; |
@@ -647,6 +652,7 @@ uid_t get_tty_gid(void) { | |||
647 | return ttygid; | 652 | return ttygid; |
648 | } | 653 | } |
649 | 654 | ||
655 | |||
650 | uid_t get_audio_gid(void) { | 656 | uid_t get_audio_gid(void) { |
651 | // find tty group id | 657 | // find tty group id |
652 | gid_t audiogid = 0; | 658 | gid_t audiogid = 0; |
@@ -656,3 +662,22 @@ uid_t get_audio_gid(void) { | |||
656 | 662 | ||
657 | return audiogid; | 663 | return audiogid; |
658 | } | 664 | } |
665 | |||
666 | |||
667 | static int remove_callback(const char *fpath, const struct stat *sb, int typeflag, struct FTW *ftwbuf) { | ||
668 | (void) sb; | ||
669 | (void) typeflag; | ||
670 | (void) ftwbuf; | ||
671 | |||
672 | int rv = remove(fpath); | ||
673 | if (rv) | ||
674 | perror(fpath); | ||
675 | |||
676 | return rv; | ||
677 | } | ||
678 | |||
679 | |||
680 | int remove_directory(const char *path) { | ||
681 | // FTW_PHYS - do not follow symbolic links | ||
682 | return nftw(path, remove_callback, 64, FTW_DEPTH | FTW_PHYS); | ||
683 | } | ||
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c index 7c961adde..188c10183 100644 --- a/src/firemon/procevent.c +++ b/src/firemon/procevent.c | |||
@@ -90,7 +90,7 @@ static int pid_is_firejail(pid_t pid) { | |||
90 | // list of firejail arguments that don't trigger sandbox creation | 90 | // list of firejail arguments that don't trigger sandbox creation |
91 | // the initial -- is not included | 91 | // the initial -- is not included |
92 | char *firejail_args = "ls list tree x11 help version top netstats debug-syscalls debug-errnos debug-protocols " | 92 | char *firejail_args = "ls list tree x11 help version top netstats debug-syscalls debug-errnos debug-protocols " |
93 | "protocol.print debug.caps shutdown bandwidth caps.print cpu.print debug-caps fs.print get "; | 93 | "protocol.print debug.caps shutdown bandwidth caps.print cpu.print debug-caps fs.print get overlay-clean "; |
94 | 94 | ||
95 | int i; | 95 | int i; |
96 | char *start; | 96 | char *start; |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index c6b73f428..fb8cb630b 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -1008,6 +1008,16 @@ Example: | |||
1008 | $ firejail \-\-overlay firefox | 1008 | $ firejail \-\-overlay firefox |
1009 | 1009 | ||
1010 | .TP | 1010 | .TP |
1011 | \fB\-\-overlay-clean | ||
1012 | Clean all overlays stored in $HOME/.firejail directory. | ||
1013 | .br | ||
1014 | |||
1015 | .br | ||
1016 | Example: | ||
1017 | .br | ||
1018 | $ firejail \-\-overlay-clean | ||
1019 | |||
1020 | .TP | ||
1011 | \fB\-\-overlay-tmpfs | 1021 | \fB\-\-overlay-tmpfs |
1012 | Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay, | 1022 | Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay, |
1013 | and are discarded when the sandbox is closed. This option is not available on Grsecurity systems. | 1023 | and are discarded when the sandbox is closed. This option is not available on Grsecurity systems. |