aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--README1
-rw-r--r--RELNOTES1
-rw-r--r--src/firejail/main.c18
-rw-r--r--src/firejail/usage.c4
-rw-r--r--src/firejail/util.c71
-rw-r--r--src/firemon/procevent.c2
-rw-r--r--src/man/firejail.txt10
7 files changed, 82 insertions, 25 deletions
diff --git a/README b/README
index a690a9b65..6ea10c901 100644
--- a/README
+++ b/README
@@ -127,6 +127,7 @@ Vasya Novikov (https://github.com/vn971)
127 - Hedegewars profile 127 - Hedegewars profile
128 - manpage fixes 128 - manpage fixes
129 - fixed firecfg clean/clear issue 129 - fixed firecfg clean/clear issue
130 - found the ugliest bug so far
130curiosity-seeker (https://github.com/curiosity-seeker) 131curiosity-seeker (https://github.com/curiosity-seeker)
131 - tightening unbound and dnscrypt-proxy profiles 132 - tightening unbound and dnscrypt-proxy profiles
132 - dnsmasq profile 133 - dnsmasq profile
diff --git a/RELNOTES b/RELNOTES
index b0d93c141..0eb9db370 100644
--- a/RELNOTES
+++ b/RELNOTES
@@ -8,6 +8,7 @@ firejail (0.9.42~rc2) baseline; urgency=low
8 * Sandbox auditing support (--audit) 8 * Sandbox auditing support (--audit)
9 * remove environment variable (--rmenv) 9 * remove environment variable (--rmenv)
10 * noexec support (--noexec) 10 * noexec support (--noexec)
11 * --overlay-clean option
11 * Ubuntu snap support 12 * Ubuntu snap support
12 * include /dev/snd in --private-dev 13 * include /dev/snd in --private-dev
13 * added mkfile profile command 14 * added mkfile profile command
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
79int mkpath_as_root(const char* path) { 81int 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
117void logsignal(int s) { 118void 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
215int is_dir(const char *fname) { 217int 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
245int is_link(const char *fname) { 248int is_link(const char *fname) {
246 assert(fname); 249 assert(fname);
@@ -325,7 +328,7 @@ char *split_comma(char *str) {
325 328
326int not_unsigned(const char *str) { 329int 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
408void extract_command_name(int index, char **argv) { 410void 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) {
541char *expand_home(const char *path, const char* homedir) { 542char *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
571uid_t pid_get_uid(pid_t pid) { 574uid_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
617void invalid_filename(const char *fname) { 621void 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
640uid_t get_tty_gid(void) { 645uid_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
650uid_t get_audio_gid(void) { 656uid_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
667static 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
680int 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
1012Clean all overlays stored in $HOME/.firejail directory.
1013.br
1014
1015.br
1016Example:
1017.br
1018$ firejail \-\-overlay-clean
1019
1020.TP
1011\fB\-\-overlay-tmpfs 1021\fB\-\-overlay-tmpfs
1012Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay, 1022Mount a filesystem overlay on top of the current filesystem. All filesystem modifications go into the overlay,
1013and are discarded when the sandbox is closed. This option is not available on Grsecurity systems. 1023and are discarded when the sandbox is closed. This option is not available on Grsecurity systems.