diff options
Diffstat (limited to 'src')
33 files changed, 234 insertions, 356 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config index 9ca3c5a3e..94e8b9194 100644 --- a/src/firecfg/firecfg.config +++ b/src/firecfg/firecfg.config | |||
@@ -11,6 +11,7 @@ Cryptocat | |||
11 | Cyberfox | 11 | Cyberfox |
12 | Discord | 12 | Discord |
13 | DiscordCanary | 13 | DiscordCanary |
14 | DiscordPTB | ||
14 | Documents | 15 | Documents |
15 | FossaMail | 16 | FossaMail |
16 | Fritzing | 17 | Fritzing |
@@ -24,6 +25,7 @@ Natron | |||
24 | PCSX2 | 25 | PCSX2 |
25 | PPSSPPQt | 26 | PPSSPPQt |
26 | PPSSPPSDL | 27 | PPSSPPSDL |
28 | Postman | ||
27 | QMediathekView | 29 | QMediathekView |
28 | QOwnNotes | 30 | QOwnNotes |
29 | Screenshot | 31 | Screenshot |
@@ -44,6 +46,7 @@ amarok | |||
44 | amule | 46 | amule |
45 | amuled | 47 | amuled |
46 | android-studio | 48 | android-studio |
49 | ani-cli | ||
47 | anydesk | 50 | anydesk |
48 | apktool | 51 | apktool |
49 | apostrophe | 52 | apostrophe |
@@ -196,6 +199,7 @@ dino | |||
196 | dino-im | 199 | dino-im |
197 | discord | 200 | discord |
198 | discord-canary | 201 | discord-canary |
202 | discord-ptb | ||
199 | display | 203 | display |
200 | display-im6.q16 | 204 | display-im6.q16 |
201 | dnox | 205 | dnox |
@@ -418,6 +422,7 @@ ipcalc | |||
418 | ipcalc-ng | 422 | ipcalc-ng |
419 | iridium | 423 | iridium |
420 | iridium-browser | 424 | iridium-browser |
425 | jami | ||
421 | jd-gui | 426 | jd-gui |
422 | jdownloader | 427 | jdownloader |
423 | jerry | 428 | jerry |
@@ -483,6 +488,7 @@ linphone | |||
483 | linuxqq | 488 | linuxqq |
484 | lmms | 489 | lmms |
485 | lobase | 490 | lobase |
491 | lobster | ||
486 | localc | 492 | localc |
487 | lodraw | 493 | lodraw |
488 | loffice | 494 | loffice |
@@ -533,6 +539,7 @@ meteo-qt | |||
533 | microsoft-edge | 539 | microsoft-edge |
534 | microsoft-edge-beta | 540 | microsoft-edge-beta |
535 | microsoft-edge-dev | 541 | microsoft-edge-dev |
542 | microsoft-edge-stable | ||
536 | midori | 543 | midori |
537 | min | 544 | min |
538 | mindless | 545 | mindless |
@@ -677,6 +684,8 @@ pluma | |||
677 | plv | 684 | plv |
678 | pngquant | 685 | pngquant |
679 | polari | 686 | polari |
687 | porn-cli | ||
688 | postman | ||
680 | ppsspp | 689 | ppsspp |
681 | pragha | 690 | pragha |
682 | presentations18 | 691 | presentations18 |
diff --git a/src/firejail/appimage.c b/src/firejail/appimage.c index f93891af2..a4f727c0a 100644 --- a/src/firejail/appimage.c +++ b/src/firejail/appimage.c | |||
@@ -33,12 +33,10 @@ static char *devloop = NULL; // device file | |||
33 | static long unsigned size = 0; // offset into appimage file | 33 | static long unsigned size = 0; // offset into appimage file |
34 | #define MAXBUF 4096 | 34 | #define MAXBUF 4096 |
35 | 35 | ||
36 | #ifdef LOOP_CTL_GET_FREE // test for older kernels; this definition is found in /usr/include/linux/loop.h | 36 | static void err_loop(char *msg) { |
37 | static void err_loop(void) { | 37 | fprintf(stderr, "%s\n", msg); |
38 | fprintf(stderr, "Error: cannot configure loopback device\n"); | ||
39 | exit(1); | 38 | exit(1); |
40 | } | 39 | } |
41 | #endif | ||
42 | 40 | ||
43 | // return 1 if found | 41 | // return 1 if found |
44 | int appimage_find_profile(const char *archive) { | 42 | int appimage_find_profile(const char *archive) { |
@@ -75,7 +73,6 @@ void appimage_set(const char *appimage) { | |||
75 | assert(devloop == NULL); // don't call this twice! | 73 | assert(devloop == NULL); // don't call this twice! |
76 | EUID_ASSERT(); | 74 | EUID_ASSERT(); |
77 | 75 | ||
78 | #ifdef LOOP_CTL_GET_FREE | ||
79 | // open appimage file | 76 | // open appimage file |
80 | invalid_filename(appimage, 0); // no globbing | 77 | invalid_filename(appimage, 0); // no globbing |
81 | int ffd = open(appimage, O_RDONLY|O_CLOEXEC); | 78 | int ffd = open(appimage, O_RDONLY|O_CLOEXEC); |
@@ -99,29 +96,46 @@ void appimage_set(const char *appimage) { | |||
99 | 96 | ||
100 | // find or allocate a free loop device to use | 97 | // find or allocate a free loop device to use |
101 | EUID_ROOT(); | 98 | EUID_ROOT(); |
102 | int cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC); | 99 | int cfd; // loop control fd |
103 | if (cfd == -1) | 100 | if ((cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC)) == -1) { |
104 | err_loop(); | 101 | sleep(1); // sleep 1 second and try again |
105 | int devnr = ioctl(cfd, LOOP_CTL_GET_FREE); | 102 | if ((cfd = open("/dev/loop-control", O_RDWR|O_CLOEXEC)) == -1) |
106 | if (devnr == -1) | 103 | err_loop("cannot open /dev/loop-control"); |
107 | err_loop(); | 104 | } |
105 | |||
106 | int devnr; // loop device number | ||
107 | if ((devnr = ioctl(cfd, LOOP_CTL_GET_FREE)) == -1) { | ||
108 | sleep(1); // sleep 1 second and try again | ||
109 | if ((devnr = ioctl(cfd, LOOP_CTL_GET_FREE)) == -1) | ||
110 | err_loop("cannot get a free loop device number"); | ||
111 | } | ||
108 | close(cfd); | 112 | close(cfd); |
109 | if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) | 113 | if (asprintf(&devloop, "/dev/loop%d", devnr) == -1) |
110 | errExit("asprintf"); | 114 | errExit("asprintf"); |
111 | 115 | ||
116 | int lfd; // loopback fd | ||
117 | if ((lfd = open(devloop, O_RDONLY|O_CLOEXEC)) == -1) { | ||
118 | sleep (1); // sleep 1 second and try again | ||
119 | if ((lfd = open(devloop, O_RDONLY|O_CLOEXEC)) == -1) | ||
120 | err_loop("cannot open loop device"); | ||
121 | } | ||
122 | |||
112 | // associate loop device with appimage | 123 | // associate loop device with appimage |
113 | int lfd = open(devloop, O_RDONLY|O_CLOEXEC); | 124 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) { |
114 | if (lfd == -1) | 125 | sleep(1); // sleep 1 second and try again |
115 | err_loop(); | 126 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) |
116 | if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) | 127 | err_loop("cannot associate loop device with appimage file"); |
117 | err_loop(); | 128 | } |
118 | 129 | ||
119 | if (size) { | 130 | if (size) { |
120 | struct loop_info64 info; | 131 | struct loop_info64 info; |
121 | memset(&info, 0, sizeof(struct loop_info64)); | 132 | memset(&info, 0, sizeof(struct loop_info64)); |
122 | info.lo_offset = size; | 133 | info.lo_offset = size; |
123 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) | 134 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) { |
124 | err_loop(); | 135 | sleep(1); // sleep 1 second and try again |
136 | if (ioctl(lfd, LOOP_SET_STATUS64, &info) == -1) | ||
137 | err_loop("cannot set loop status"); | ||
138 | } | ||
125 | } | 139 | } |
126 | close(lfd); | 140 | close(lfd); |
127 | close(ffd); | 141 | close(ffd); |
@@ -143,10 +157,6 @@ void appimage_set(const char *appimage) { | |||
143 | env_store_name_val("OWD", cfg.cwd, SETENV); | 157 | env_store_name_val("OWD", cfg.cwd, SETENV); |
144 | 158 | ||
145 | __gcov_flush(); | 159 | __gcov_flush(); |
146 | #else | ||
147 | fprintf(stderr, "Error: /dev/loop-control interface is not supported by your kernel\n"); | ||
148 | exit(1); | ||
149 | #endif | ||
150 | } | 160 | } |
151 | 161 | ||
152 | // mount appimage into sandbox file system | 162 | // mount appimage into sandbox file system |
diff --git a/src/firejail/arp.c b/src/firejail/arp.c index bfb522d38..d4288b29e 100644 --- a/src/firejail/arp.c +++ b/src/firejail/arp.c | |||
@@ -299,7 +299,7 @@ static uint32_t arp_random(const char *dev, Bridge *br) { | |||
299 | return 0; | 299 | return 0; |
300 | } | 300 | } |
301 | 301 | ||
302 | // go sequentially trough all IP addresses and assign the first one not in use | 302 | // go sequentially through all IP addresses and assign the first one not in use |
303 | static uint32_t arp_sequential(const char *dev, Bridge *br) { | 303 | static uint32_t arp_sequential(const char *dev, Bridge *br) { |
304 | assert(dev); | 304 | assert(dev); |
305 | assert(br); | 305 | assert(br); |
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index 56f983854..a39e8c667 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c | |||
@@ -409,6 +409,14 @@ void print_compiletime_support(void) { | |||
409 | #endif | 409 | #endif |
410 | ); | 410 | ); |
411 | 411 | ||
412 | printf("\t- private-lib support is %s\n", | ||
413 | #ifdef HAVE_PRIVATE_LIB | ||
414 | "enabled" | ||
415 | #else | ||
416 | "disabled" | ||
417 | #endif | ||
418 | ); | ||
419 | |||
412 | printf("\t- private-cache and tmpfs as user %s\n", | 420 | printf("\t- private-cache and tmpfs as user %s\n", |
413 | #ifdef HAVE_USERTMPFS | 421 | #ifdef HAVE_USERTMPFS |
414 | "enabled" | 422 | "enabled" |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 5295393f0..2cde75463 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -525,7 +525,6 @@ int macro_id(const char *name); | |||
525 | 525 | ||
526 | 526 | ||
527 | // util.c | 527 | // util.c |
528 | int invalid_name(const char *name); | ||
529 | void errLogExit(char* fmt, ...) __attribute__((noreturn)); | 528 | void errLogExit(char* fmt, ...) __attribute__((noreturn)); |
530 | void fwarning(char* fmt, ...); | 529 | void fwarning(char* fmt, ...); |
531 | void fmessage(char* fmt, ...); | 530 | void fmessage(char* fmt, ...); |
@@ -581,6 +580,13 @@ int has_handler(pid_t pid, int signal); | |||
581 | void enter_network_namespace(pid_t pid); | 580 | void enter_network_namespace(pid_t pid); |
582 | int read_pid(const char *name, pid_t *pid); | 581 | int read_pid(const char *name, pid_t *pid); |
583 | pid_t require_pid(const char *name); | 582 | pid_t require_pid(const char *name); |
583 | int ascii_isalnum(unsigned char c); | ||
584 | int ascii_isalpha(unsigned char c); | ||
585 | int ascii_isdigit(unsigned char c); | ||
586 | int ascii_islower(unsigned char c); | ||
587 | int ascii_isupper(unsigned char c); | ||
588 | int ascii_isxdigit(unsigned char c); | ||
589 | int invalid_name(const char *name); | ||
584 | void check_homedir(const char *dir); | 590 | void check_homedir(const char *dir); |
585 | 591 | ||
586 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo | 592 | // Get info regarding the last kernel mount operation from /proc/self/mountinfo |
@@ -606,7 +612,6 @@ void fs_var_run(void); | |||
606 | void fs_var_lock(void); | 612 | void fs_var_lock(void); |
607 | void fs_var_tmp(void); | 613 | void fs_var_tmp(void); |
608 | void fs_var_utmp(void); | 614 | void fs_var_utmp(void); |
609 | void dbg_test_dir(const char *dir); | ||
610 | 615 | ||
611 | // fs_dev.c | 616 | // fs_dev.c |
612 | void fs_dev_shm(void); | 617 | void fs_dev_shm(void); |
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c index 51a58013d..9ca73eb35 100644 --- a/src/firejail/fs_dev.c +++ b/src/firejail/fs_dev.c | |||
@@ -177,7 +177,6 @@ static void mount_dev_shm(void) { | |||
177 | int rv = mount(RUN_DEV_DIR "/shm", "/dev/shm", "none", MS_BIND, "mode=01777,gid=0"); | 177 | int rv = mount(RUN_DEV_DIR "/shm", "/dev/shm", "none", MS_BIND, "mode=01777,gid=0"); |
178 | if (rv == -1) { | 178 | if (rv == -1) { |
179 | fwarning("cannot mount the old /dev/shm in private-dev\n"); | 179 | fwarning("cannot mount the old /dev/shm in private-dev\n"); |
180 | dbg_test_dir(RUN_DEV_DIR "/shm"); | ||
181 | empty_dev_shm(); | 180 | empty_dev_shm(); |
182 | return; | 181 | return; |
183 | } | 182 | } |
diff --git a/src/firejail/fs_etc.c b/src/firejail/fs_etc.c index 3b7369ea8..dc4e5c228 100644 --- a/src/firejail/fs_etc.c +++ b/src/firejail/fs_etc.c | |||
@@ -111,6 +111,11 @@ char *fs_etc_build(char *str) { | |||
111 | } | 111 | } |
112 | 112 | ||
113 | void fs_resolvconf(void) { | 113 | void fs_resolvconf(void) { |
114 | if (arg_nonetwork) { | ||
115 | if (arg_debug) | ||
116 | printf("arg_nonetwork found (--net=none). Skip creating /etc/resolv.conf file\n"); | ||
117 | return; | ||
118 | } | ||
114 | if (arg_debug) | 119 | if (arg_debug) |
115 | printf("Creating a new /etc/resolv.conf file\n"); | 120 | printf("Creating a new /etc/resolv.conf file\n"); |
116 | FILE *fp = fopen(RUN_RESOLVCONF_FILE, "wxe"); | 121 | FILE *fp = fopen(RUN_RESOLVCONF_FILE, "wxe"); |
diff --git a/src/firejail/fs_home.c b/src/firejail/fs_home.c index 624e74fe4..fd2441832 100644 --- a/src/firejail/fs_home.c +++ b/src/firejail/fs_home.c | |||
@@ -185,20 +185,10 @@ static int store_asoundrc(void) { | |||
185 | errExit("asprintf"); | 185 | errExit("asprintf"); |
186 | 186 | ||
187 | struct stat s; | 187 | struct stat s; |
188 | if (lstat(src, &s) == 0) { | 188 | if (stat(src, &s) == 0) { |
189 | if (S_ISLNK(s.st_mode)) { | 189 | if (s.st_uid != getuid()) { |
190 | // make sure the real path of the file is inside the home directory | 190 | fwarning(".asoundrc is not owned by the current user, skipping...\n"); |
191 | /* coverity[toctou] */ | 191 | return 0; |
192 | char *rp = realpath(src, NULL); | ||
193 | if (!rp) { | ||
194 | fprintf(stderr, "Error: Cannot access %s\n", src); | ||
195 | exit(1); | ||
196 | } | ||
197 | if (strncmp(rp, cfg.homedir, strlen(cfg.homedir)) != 0 || rp[strlen(cfg.homedir)] != '/') { | ||
198 | fprintf(stderr, "Error: .asoundrc is a symbolic link pointing to a file outside home directory\n"); | ||
199 | exit(1); | ||
200 | } | ||
201 | free(rp); | ||
202 | } | 192 | } |
203 | 193 | ||
204 | // create an empty file as root, and change ownership to user | 194 | // create an empty file as root, and change ownership to user |
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c index e349941fa..ba7a291ee 100644 --- a/src/firejail/fs_lib.c +++ b/src/firejail/fs_lib.c | |||
@@ -32,35 +32,6 @@ extern void fslib_install_stdc(void); | |||
32 | extern void fslib_install_firejail(void); | 32 | extern void fslib_install_firejail(void); |
33 | extern void fslib_install_system(void); | 33 | extern void fslib_install_system(void); |
34 | 34 | ||
35 | static int lib_cnt = 0; | ||
36 | static int dir_cnt = 0; | ||
37 | |||
38 | static const char *masked_lib_dirs[] = { | ||
39 | "/usr/lib64", | ||
40 | "/lib64", | ||
41 | "/usr/lib", | ||
42 | "/lib", | ||
43 | "/usr/local/lib64", | ||
44 | "/usr/local/lib", | ||
45 | NULL, | ||
46 | }; | ||
47 | |||
48 | // return 1 if the file is in masked_lib_dirs[] | ||
49 | static int valid_full_path(const char *full_path) { | ||
50 | if (strstr(full_path, "..")) | ||
51 | return 0; | ||
52 | |||
53 | int i = 0; | ||
54 | while (masked_lib_dirs[i]) { | ||
55 | size_t len = strlen(masked_lib_dirs[i]); | ||
56 | if (strncmp(full_path, masked_lib_dirs[i], len) == 0 && | ||
57 | full_path[len] == '/') | ||
58 | return 1; | ||
59 | i++; | ||
60 | } | ||
61 | return 0; | ||
62 | } | ||
63 | |||
64 | // return 1 if symlink to firejail executable | 35 | // return 1 if symlink to firejail executable |
65 | int is_firejail_link(const char *fname) { | 36 | int is_firejail_link(const char *fname) { |
66 | EUID_ASSERT(); | 37 | EUID_ASSERT(); |
@@ -116,6 +87,36 @@ char *find_in_path(const char *program) { | |||
116 | return NULL; | 87 | return NULL; |
117 | } | 88 | } |
118 | 89 | ||
90 | #ifdef HAVE_PRIVATE_LIB | ||
91 | static int lib_cnt = 0; | ||
92 | static int dir_cnt = 0; | ||
93 | |||
94 | static const char *masked_lib_dirs[] = { | ||
95 | "/usr/lib64", | ||
96 | "/lib64", | ||
97 | "/usr/lib", | ||
98 | "/lib", | ||
99 | "/usr/local/lib64", | ||
100 | "/usr/local/lib", | ||
101 | NULL, | ||
102 | }; | ||
103 | |||
104 | // return 1 if the file is in masked_lib_dirs[] | ||
105 | static int valid_full_path(const char *full_path) { | ||
106 | if (strstr(full_path, "..")) | ||
107 | return 0; | ||
108 | |||
109 | int i = 0; | ||
110 | while (masked_lib_dirs[i]) { | ||
111 | size_t len = strlen(masked_lib_dirs[i]); | ||
112 | if (strncmp(full_path, masked_lib_dirs[i], len) == 0 && | ||
113 | full_path[len] == '/') | ||
114 | return 1; | ||
115 | i++; | ||
116 | } | ||
117 | return 0; | ||
118 | } | ||
119 | |||
119 | static char *build_dest_dir(const char *full_path) { | 120 | static char *build_dest_dir(const char *full_path) { |
120 | assert(full_path); | 121 | assert(full_path); |
121 | if (strstr(full_path, "/x86_64-linux-gnu/")) | 122 | if (strstr(full_path, "/x86_64-linux-gnu/")) |
@@ -465,3 +466,4 @@ void fs_private_lib(void) { | |||
465 | // mount lib filesystem | 466 | // mount lib filesystem |
466 | mount_directories(); | 467 | mount_directories(); |
467 | } | 468 | } |
469 | #endif \ No newline at end of file | ||
diff --git a/src/firejail/fs_lib2.c b/src/firejail/fs_lib2.c index 540c3286f..583888e0e 100644 --- a/src/firejail/fs_lib2.c +++ b/src/firejail/fs_lib2.c | |||
@@ -36,6 +36,7 @@ typedef struct liblist_t { | |||
36 | int len; | 36 | int len; |
37 | } LibList; | 37 | } LibList; |
38 | 38 | ||
39 | #ifdef HAVE_PRIVATE_LIB | ||
39 | static LibList libc_list[] = { | 40 | static LibList libc_list[] = { |
40 | { "libselinux.so.", 0 }, | 41 | { "libselinux.so.", 0 }, |
41 | { "libpcre2-8.so.", 0 }, | 42 | { "libpcre2-8.so.", 0 }, |
@@ -356,3 +357,4 @@ void fslib_install_system(void) { | |||
356 | ptr++; | 357 | ptr++; |
357 | } | 358 | } |
358 | } | 359 | } |
360 | #endif | ||
diff --git a/src/firejail/fs_var.c b/src/firejail/fs_var.c index 690780a0e..4787df21e 100644 --- a/src/firejail/fs_var.c +++ b/src/firejail/fs_var.c | |||
@@ -230,21 +230,6 @@ void fs_var_cache(void) { | |||
230 | } | 230 | } |
231 | } | 231 | } |
232 | 232 | ||
233 | void dbg_test_dir(const char *dir) { | ||
234 | if (arg_debug) { | ||
235 | if (is_dir(dir)) | ||
236 | printf("%s is a directory\n", dir); | ||
237 | if (is_link(dir)) { | ||
238 | char *lnk = realpath(dir, NULL); | ||
239 | if (lnk) { | ||
240 | printf("%s is a symbolic link to %s\n", dir, lnk); | ||
241 | free(lnk); | ||
242 | } | ||
243 | } | ||
244 | } | ||
245 | } | ||
246 | |||
247 | |||
248 | void fs_var_lock(void) { | 233 | void fs_var_lock(void) { |
249 | 234 | ||
250 | if (is_dir("/var/lock")) { | 235 | if (is_dir("/var/lock")) { |
@@ -254,10 +239,8 @@ void fs_var_lock(void) { | |||
254 | errExit("mounting /lock"); | 239 | errExit("mounting /lock"); |
255 | fs_logger("tmpfs /var/lock"); | 240 | fs_logger("tmpfs /var/lock"); |
256 | } | 241 | } |
257 | else { | 242 | else |
258 | fwarning("/var/lock not mounted\n"); | 243 | fwarning("/var/lock not mounted\n"); |
259 | dbg_test_dir("/var/lock"); | ||
260 | } | ||
261 | } | 244 | } |
262 | 245 | ||
263 | void fs_var_tmp(void) { | 246 | void fs_var_tmp(void) { |
@@ -271,10 +254,8 @@ void fs_var_tmp(void) { | |||
271 | fs_logger("tmpfs /var/tmp"); | 254 | fs_logger("tmpfs /var/tmp"); |
272 | } | 255 | } |
273 | } | 256 | } |
274 | else { | 257 | else |
275 | fwarning("/var/tmp not mounted\n"); | 258 | fwarning("/var/tmp not mounted\n"); |
276 | dbg_test_dir("/var/tmp"); | ||
277 | } | ||
278 | } | 259 | } |
279 | 260 | ||
280 | void fs_var_utmp(void) { | 261 | void fs_var_utmp(void) { |
diff --git a/src/firejail/ls.c b/src/firejail/ls.c index ea85fabfd..f2ab1c188 100644 --- a/src/firejail/ls.c +++ b/src/firejail/ls.c | |||
@@ -140,7 +140,7 @@ static void print_file_or_dir(const char *path, const char *fname) { | |||
140 | } | 140 | } |
141 | } | 141 | } |
142 | 142 | ||
143 | // print grup name, 8 chars maximum | 143 | // print group name, 8 chars maximum |
144 | len = strlen(groupname); | 144 | len = strlen(groupname); |
145 | if (len > 8) { | 145 | if (len > 8) { |
146 | groupname[8] = '\0'; | 146 | groupname[8] = '\0'; |
@@ -381,7 +381,7 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) { | |||
381 | errExit("ftruncate"); | 381 | errExit("ftruncate"); |
382 | 382 | ||
383 | if (copy_file_by_fd(src, dest) != 0) | 383 | if (copy_file_by_fd(src, dest) != 0) |
384 | fwarning("an error occured during copying\n"); | 384 | fwarning("an error occurred during copying\n"); |
385 | close(src); | 385 | close(src); |
386 | close(dest); | 386 | close(dest); |
387 | } | 387 | } |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 0e5363cb0..7e23cdc63 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1355,8 +1355,10 @@ int main(int argc, char **argv, char **envp) { | |||
1355 | arg_debug_blacklists = 1; | 1355 | arg_debug_blacklists = 1; |
1356 | else if (strcmp(argv[i], "--debug-whitelists") == 0) | 1356 | else if (strcmp(argv[i], "--debug-whitelists") == 0) |
1357 | arg_debug_whitelists = 1; | 1357 | arg_debug_whitelists = 1; |
1358 | #ifdef HAVE_PRIVATE_LIB | ||
1358 | else if (strcmp(argv[i], "--debug-private-lib") == 0) | 1359 | else if (strcmp(argv[i], "--debug-private-lib") == 0) |
1359 | arg_debug_private_lib = 1; | 1360 | arg_debug_private_lib = 1; |
1361 | #endif | ||
1360 | else if (strcmp(argv[i], "--quiet") == 0) { | 1362 | else if (strcmp(argv[i], "--quiet") == 0) { |
1361 | if (!arg_debug) | 1363 | if (!arg_debug) |
1362 | arg_quiet = 1; | 1364 | arg_quiet = 1; |
@@ -1575,7 +1577,7 @@ int main(int argc, char **argv, char **envp) { | |||
1575 | exit(1); | 1577 | exit(1); |
1576 | } | 1578 | } |
1577 | invalid_filename(arg_tracefile, 0); // no globbing | 1579 | invalid_filename(arg_tracefile, 0); // no globbing |
1578 | if (strstr(arg_tracefile, "..")) { | 1580 | if (strstr(arg_tracefile, "..") || has_cntrl_chars(arg_tracefile)) { |
1579 | fprintf(stderr, "Error: invalid file name %s\n", arg_tracefile); | 1581 | fprintf(stderr, "Error: invalid file name %s\n", arg_tracefile); |
1580 | exit(1); | 1582 | exit(1); |
1581 | } | 1583 | } |
@@ -2137,6 +2139,7 @@ int main(int argc, char **argv, char **envp) { | |||
2137 | else | 2139 | else |
2138 | exit_err_feature("private-bin"); | 2140 | exit_err_feature("private-bin"); |
2139 | } | 2141 | } |
2142 | #ifdef HAVE_PRIVATE_LIB | ||
2140 | else if (strncmp(argv[i], "--private-lib", 13) == 0) { | 2143 | else if (strncmp(argv[i], "--private-lib", 13) == 0) { |
2141 | if (checkcfg(CFG_PRIVATE_LIB)) { | 2144 | if (checkcfg(CFG_PRIVATE_LIB)) { |
2142 | // extract private lib list (if any) | 2145 | // extract private lib list (if any) |
@@ -2152,6 +2155,7 @@ int main(int argc, char **argv, char **envp) { | |||
2152 | else | 2155 | else |
2153 | exit_err_feature("private-lib"); | 2156 | exit_err_feature("private-lib"); |
2154 | } | 2157 | } |
2158 | #endif | ||
2155 | else if (strcmp(argv[i], "--private-tmp") == 0) { | 2159 | else if (strcmp(argv[i], "--private-tmp") == 0) { |
2156 | arg_private_tmp = 1; | 2160 | arg_private_tmp = 1; |
2157 | } | 2161 | } |
@@ -2186,18 +2190,31 @@ int main(int argc, char **argv, char **envp) { | |||
2186 | fprintf(stderr, "Error: please provide a name for sandbox\n"); | 2190 | fprintf(stderr, "Error: please provide a name for sandbox\n"); |
2187 | return 1; | 2191 | return 1; |
2188 | } | 2192 | } |
2189 | if (invalid_name(cfg.name)) { | 2193 | if (invalid_name(cfg.name) || has_cntrl_chars(cfg.name)) { |
2190 | fprintf(stderr, "Error: invalid sandbox name\n"); | 2194 | fprintf(stderr, "Error: invalid sandbox name\n"); |
2191 | return 1; | 2195 | return 1; |
2192 | } | 2196 | } |
2193 | } | 2197 | } |
2194 | else if (strncmp(argv[i], "--hostname=", 11) == 0) { | 2198 | else if (strncmp(argv[i], "--hostname=", 11) == 0) { |
2195 | cfg.hostname = argv[i] + 11; | 2199 | cfg.hostname = argv[i] + 11; |
2196 | if (strlen(cfg.hostname) == 0) { | 2200 | size_t len = strlen(cfg.hostname); |
2197 | fprintf(stderr, "Error: please provide a hostname for sandbox\n"); | 2201 | if (len == 0 || len > 253) { |
2202 | fprintf(stderr, "Error: please provide a valid hostname for sandbox, with maximum length of 253 ASCII characters\n"); | ||
2198 | return 1; | 2203 | return 1; |
2199 | } | 2204 | } |
2200 | if (invalid_name(cfg.hostname)) { | 2205 | int invalid = invalid_name(cfg.hostname); |
2206 | char* hostname = cfg.hostname; | ||
2207 | while (*hostname && !invalid) { | ||
2208 | invalid = invalid || !( | ||
2209 | (*hostname >= 'a' && *hostname <= 'z') || | ||
2210 | (*hostname >= 'A' && *hostname <= 'Z') || | ||
2211 | (*hostname >= '0' && *hostname <= '9') || | ||
2212 | (*hostname == '-' || *hostname == '.')); | ||
2213 | hostname++; | ||
2214 | } | ||
2215 | invalid = invalid || cfg.hostname[0] == '-'; // must not start with - | ||
2216 | invalid = invalid || cfg.hostname[len - 1] == '-'; // must not end with - | ||
2217 | if (invalid) { | ||
2201 | fprintf(stderr, "Error: invalid hostname\n"); | 2218 | fprintf(stderr, "Error: invalid hostname\n"); |
2202 | return 1; | 2219 | return 1; |
2203 | } | 2220 | } |
diff --git a/src/firejail/netfilter.c b/src/firejail/netfilter.c index b4deda562..32fdd6218 100644 --- a/src/firejail/netfilter.c +++ b/src/firejail/netfilter.c | |||
@@ -248,5 +248,5 @@ void netfilter_print(pid_t pid, int ipv6) { | |||
248 | exit(1); | 248 | exit(1); |
249 | } | 249 | } |
250 | 250 | ||
251 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-vL"); | 251 | sbox_run(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, 2, iptables, "-nvL"); |
252 | } | 252 | } |
diff --git a/src/firejail/network.c b/src/firejail/network.c index c1adf87cc..3da51e195 100644 --- a/src/firejail/network.c +++ b/src/firejail/network.c | |||
@@ -89,31 +89,7 @@ int net_get_mtu(const char *ifname) { | |||
89 | return mtu; | 89 | return mtu; |
90 | } | 90 | } |
91 | 91 | ||
92 | void net_set_mtu(const char *ifname, int mtu) { | 92 | // return -1 if the interface was not found; if the interface was found return 0 and fill in IP address and mask |
93 | if (strlen(ifname) > IFNAMSIZ) { | ||
94 | fprintf(stderr, "Error: invalid network device name %s\n", ifname); | ||
95 | exit(1); | ||
96 | } | ||
97 | |||
98 | if (arg_debug) | ||
99 | printf("set interface %s MTU %d.\n", ifname, mtu); | ||
100 | |||
101 | int s; | ||
102 | struct ifreq ifr; | ||
103 | |||
104 | if ((s = socket(AF_INET, SOCK_DGRAM, 0)) < 0) | ||
105 | errExit("socket"); | ||
106 | |||
107 | memset(&ifr, 0, sizeof(ifr)); | ||
108 | ifr.ifr_addr.sa_family = AF_INET; | ||
109 | strncpy(ifr.ifr_name, ifname, IFNAMSIZ - 1); | ||
110 | ifr.ifr_mtu = mtu; | ||
111 | if (ioctl(s, SIOCSIFMTU, (caddr_t)&ifr) != 0) | ||
112 | fwarning("cannot set mtu for interface %s\n", ifname); | ||
113 | close(s); | ||
114 | } | ||
115 | |||
116 | // return -1 if the interface was not found; if the interface was found retrn 0 and fill in IP address and mask | ||
117 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu) { | 93 | int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu) { |
118 | assert(bridge); | 94 | assert(bridge); |
119 | assert(ip); | 95 | assert(ip); |
diff --git a/src/firejail/output.c b/src/firejail/output.c index 57679901f..687aaba9c 100644 --- a/src/firejail/output.c +++ b/src/firejail/output.c | |||
@@ -66,8 +66,8 @@ void check_output(int argc, char **argv) { | |||
66 | } | 66 | } |
67 | 67 | ||
68 | // do not accept directories, links, and files with ".." | 68 | // do not accept directories, links, and files with ".." |
69 | if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile)) { | 69 | if (strstr(outfile, "..") || is_link(outfile) || is_dir(outfile) || has_cntrl_chars(outfile)) { |
70 | fprintf(stderr, "Error: invalid output file. Links, directories and files with \"..\" are not allowed.\n"); | 70 | fprintf(stderr, "Error: invalid output file. Links, directories, files with \"..\" and control characters in filenames are not allowed.\n"); |
71 | exit(1); | 71 | exit(1); |
72 | } | 72 | } |
73 | 73 | ||
diff --git a/src/firejail/restrict_users.c b/src/firejail/restrict_users.c index b95c9a96b..c5c66549d 100644 --- a/src/firejail/restrict_users.c +++ b/src/firejail/restrict_users.c | |||
@@ -234,7 +234,7 @@ static void sanitize_passwd(void) { | |||
234 | SET_PERMS_STREAM(fpout, 0, 0, 0644); | 234 | SET_PERMS_STREAM(fpout, 0, 0, 0644); |
235 | fclose(fpout); | 235 | fclose(fpout); |
236 | 236 | ||
237 | // mount-bind tne new password file | 237 | // mount-bind the new password file |
238 | if (mount(RUN_PASSWD_FILE, "/etc/passwd", "none", MS_BIND, "mode=400,gid=0") < 0) | 238 | if (mount(RUN_PASSWD_FILE, "/etc/passwd", "none", MS_BIND, "mode=400,gid=0") < 0) |
239 | errExit("mount"); | 239 | errExit("mount"); |
240 | 240 | ||
@@ -369,7 +369,7 @@ static void sanitize_group(void) { | |||
369 | SET_PERMS_STREAM(fpout, 0, 0, 0644); | 369 | SET_PERMS_STREAM(fpout, 0, 0, 0644); |
370 | fclose(fpout); | 370 | fclose(fpout); |
371 | 371 | ||
372 | // mount-bind tne new group file | 372 | // mount-bind the new group file |
373 | if (mount(RUN_GROUP_FILE, "/etc/group", "none", MS_BIND, "mode=400,gid=0") < 0) | 373 | if (mount(RUN_GROUP_FILE, "/etc/group", "none", MS_BIND, "mode=400,gid=0") < 0) |
374 | errExit("mount"); | 374 | errExit("mount"); |
375 | 375 | ||
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 648fc2248..19ac8d9ec 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -949,6 +949,7 @@ int sandbox(void* sandbox_arg) { | |||
949 | } | 949 | } |
950 | } | 950 | } |
951 | 951 | ||
952 | #ifdef HAVE_PRIVATE_LIB | ||
952 | // private-lib is disabled for appimages | 953 | // private-lib is disabled for appimages |
953 | if (arg_private_lib && !arg_appimage) { | 954 | if (arg_private_lib && !arg_appimage) { |
954 | if (cfg.chrootdir) | 955 | if (cfg.chrootdir) |
@@ -959,6 +960,7 @@ int sandbox(void* sandbox_arg) { | |||
959 | fs_private_lib(); | 960 | fs_private_lib(); |
960 | } | 961 | } |
961 | } | 962 | } |
963 | #endif | ||
962 | 964 | ||
963 | #ifdef HAVE_USERTMPFS | 965 | #ifdef HAVE_USERTMPFS |
964 | if (arg_private_cache) { | 966 | if (arg_private_cache) { |
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c index 11ea5b036..ce43b4832 100644 --- a/src/firejail/sbox.c +++ b/src/firejail/sbox.c | |||
@@ -26,6 +26,7 @@ | |||
26 | #include <sys/resource.h> | 26 | #include <sys/resource.h> |
27 | #include <sys/wait.h> | 27 | #include <sys/wait.h> |
28 | #include "../include/seccomp.h" | 28 | #include "../include/seccomp.h" |
29 | #include "../include/gcov_wrapper.h" | ||
29 | 30 | ||
30 | #include <fcntl.h> | 31 | #include <fcntl.h> |
31 | #ifndef O_PATH | 32 | #ifndef O_PATH |
@@ -238,6 +239,7 @@ static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char * | |||
238 | fprintf(stderr, "Error: %s is world writable, refusing to execute\n", arg[0]); | 239 | fprintf(stderr, "Error: %s is world writable, refusing to execute\n", arg[0]); |
239 | exit(1); | 240 | exit(1); |
240 | } | 241 | } |
242 | __gcov_dump(); | ||
241 | fexecve(fd, arg, new_environment); | 243 | fexecve(fd, arg, new_environment); |
242 | } else { | 244 | } else { |
243 | assert(0); | 245 | assert(0); |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 2e10fb959..b6b60d85c 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -81,7 +81,9 @@ static char *usage_str = | |||
81 | " --debug-blacklists - debug blacklisting.\n" | 81 | " --debug-blacklists - debug blacklisting.\n" |
82 | " --debug-caps - print all recognized capabilities.\n" | 82 | " --debug-caps - print all recognized capabilities.\n" |
83 | " --debug-errnos - print all recognized error numbers.\n" | 83 | " --debug-errnos - print all recognized error numbers.\n" |
84 | #ifdef HAVE_PRIVATE_LIB | ||
84 | " --debug-private-lib - debug for --private-lib option.\n" | 85 | " --debug-private-lib - debug for --private-lib option.\n" |
86 | #endif | ||
85 | " --debug-protocols - print all recognized protocols.\n" | 87 | " --debug-protocols - print all recognized protocols.\n" |
86 | " --debug-syscalls - print all recognized system calls.\n" | 88 | " --debug-syscalls - print all recognized system calls.\n" |
87 | " --debug-syscalls32 - print all recognized 32 bit system calls.\n" | 89 | " --debug-syscalls32 - print all recognized 32 bit system calls.\n" |
@@ -200,14 +202,17 @@ static char *usage_str = | |||
200 | " --private=directory - use directory as user home.\n" | 202 | " --private=directory - use directory as user home.\n" |
201 | " --private-cache - temporary ~/.cache directory.\n" | 203 | " --private-cache - temporary ~/.cache directory.\n" |
202 | " --private-home=file,directory - build a new user home in a temporary\n" | 204 | " --private-home=file,directory - build a new user home in a temporary\n" |
203 | "\tfilesystem, and copy the files and directories in the list in\n" | 205 | "\tfilesystem, and copy the files and directories in the list in the\n" |
204 | "\tthe new home.\n" | 206 | "\tnew home.\n" |
205 | " --private-bin=file,file - build a new /bin in a temporary filesystem,\n" | 207 | " --private-bin=file,file - build a new /bin in a temporary filesystem,\n" |
206 | "\tand copy the programs in the list.\n" | 208 | "\tand copy the programs in the list.\n" |
207 | " --private-dev - create a new /dev directory with a small number of\n" | 209 | " --private-dev - create a new /dev directory with a small number of\n" |
208 | "\tcommon device files.\n" | 210 | "\tcommon device files.\n" |
209 | " --private-etc=file,directory - build a new /etc in a temporary\n" | 211 | " --private-etc=file,directory - build a new /etc in a temporary\n" |
210 | "\tfilesystem, and copy the files and directories in the list.\n" | 212 | "\tfilesystem, and copy the files and directories in the list.\n" |
213 | #ifdef HAVE_PRIVATE_LIB | ||
214 | " --private-lib - create a private /lib directory\n" | ||
215 | #endif | ||
211 | " --private-tmp - mount a tmpfs on top of /tmp directory.\n" | 216 | " --private-tmp - mount a tmpfs on top of /tmp directory.\n" |
212 | " --private-cwd - do not inherit working directory inside jail.\n" | 217 | " --private-cwd - do not inherit working directory inside jail.\n" |
213 | " --private-cwd=directory - set working directory inside jail.\n" | 218 | " --private-cwd=directory - set working directory inside jail.\n" |
diff --git a/src/firejail/util.c b/src/firejail/util.c index bafcd69ec..b2a0c85f1 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c | |||
@@ -1323,7 +1323,7 @@ void close_all(int *keep_list, size_t sz) { | |||
1323 | if (fd == dirfd(dir)) | 1323 | if (fd == dirfd(dir)) |
1324 | continue; // just postponed | 1324 | continue; // just postponed |
1325 | 1325 | ||
1326 | // dont't close file descriptors in keep list | 1326 | // don't close file descriptors in keep list |
1327 | int keep = 0; | 1327 | int keep = 0; |
1328 | if (keep_list) { | 1328 | if (keep_list) { |
1329 | size_t i; | 1329 | size_t i; |
@@ -1448,15 +1448,42 @@ static int has_link(const char *dir) { | |||
1448 | return 0; | 1448 | return 0; |
1449 | } | 1449 | } |
1450 | 1450 | ||
1451 | int ascii_isalnum(unsigned char c) { | ||
1452 | return (ascii_isalpha(c) || ascii_isdigit(c)); | ||
1453 | } | ||
1454 | |||
1455 | int ascii_isalpha(unsigned char c) { | ||
1456 | return (ascii_islower(c) || ascii_isupper(c)); | ||
1457 | } | ||
1458 | |||
1459 | int ascii_isdigit(unsigned char c) { | ||
1460 | return (c >= '0' && c <= '9'); | ||
1461 | } | ||
1462 | |||
1463 | int ascii_islower(unsigned char c) { | ||
1464 | return (c >= 'a' && c <= 'z'); | ||
1465 | } | ||
1466 | |||
1467 | int ascii_isupper(unsigned char c) { | ||
1468 | return (c >= 'A' && c <= 'Z'); | ||
1469 | } | ||
1470 | |||
1471 | int ascii_isxdigit(unsigned char c) { | ||
1472 | int ret = (ascii_isdigit(c) || | ||
1473 | (c >= 'a' && c <= 'f') || | ||
1474 | (c >= 'A' && c <= 'F')); | ||
1475 | return ret; | ||
1476 | } | ||
1477 | |||
1451 | // allow strict ASCII letters and numbers; names with only numbers are rejected; spaces are rejected | 1478 | // allow strict ASCII letters and numbers; names with only numbers are rejected; spaces are rejected |
1452 | int invalid_name(const char *name) { | 1479 | int invalid_name(const char *name) { |
1453 | const char *c = name; | 1480 | const char *c = name; |
1454 | 1481 | ||
1455 | int only_numbers = 1; | 1482 | int only_numbers = 1; |
1456 | while (*c) { | 1483 | while (*c) { |
1457 | if (!isalnum(*c)) | 1484 | if (!ascii_isalnum(*c)) |
1458 | return 1; | 1485 | return 1; |
1459 | if (!isdigit(*c)) | 1486 | if (!ascii_isdigit(*c)) |
1460 | only_numbers = 0; | 1487 | only_numbers = 0; |
1461 | ++c; | 1488 | ++c; |
1462 | } | 1489 | } |
diff --git a/src/firemon/firemon.c b/src/firemon/firemon.c index 01167e555..d82f387ff 100644 --- a/src/firemon/firemon.c +++ b/src/firemon/firemon.c | |||
@@ -30,7 +30,6 @@ int arg_debug = 0; | |||
30 | static int arg_route = 0; | 30 | static int arg_route = 0; |
31 | static int arg_arp = 0; | 31 | static int arg_arp = 0; |
32 | static int arg_tree = 0; | 32 | static int arg_tree = 0; |
33 | static int arg_interface = 0; | ||
34 | static int arg_seccomp = 0; | 33 | static int arg_seccomp = 0; |
35 | static int arg_caps = 0; | 34 | static int arg_caps = 0; |
36 | static int arg_cpu = 0; | 35 | static int arg_cpu = 0; |
@@ -178,13 +177,6 @@ int main(int argc, char **argv) { | |||
178 | arg_seccomp = 1; | 177 | arg_seccomp = 1; |
179 | else if (strcmp(argv[i], "--caps") == 0) | 178 | else if (strcmp(argv[i], "--caps") == 0) |
180 | arg_caps = 1; | 179 | arg_caps = 1; |
181 | else if (strcmp(argv[i], "--interface") == 0) { | ||
182 | if (getuid() != 0) { | ||
183 | fprintf(stderr, "Error: you need to be root to run this command\n"); | ||
184 | exit(1); | ||
185 | } | ||
186 | arg_interface = 1; | ||
187 | } | ||
188 | #ifdef HAVE_NETWORK | 180 | #ifdef HAVE_NETWORK |
189 | else if (strcmp(argv[i], "--route") == 0) | 181 | else if (strcmp(argv[i], "--route") == 0) |
190 | arg_route = 1; | 182 | arg_route = 1; |
@@ -261,13 +253,12 @@ int main(int argc, char **argv) { | |||
261 | 253 | ||
262 | // if --name requested without other options, print all data | 254 | // if --name requested without other options, print all data |
263 | if (pid && !arg_cpu && !arg_seccomp && !arg_caps && !arg_apparmor && | 255 | if (pid && !arg_cpu && !arg_seccomp && !arg_caps && !arg_apparmor && |
264 | !arg_x11 && !arg_interface && !arg_route && !arg_arp) { | 256 | !arg_x11 && !arg_route && !arg_arp) { |
265 | arg_tree = 1; | 257 | arg_tree = 1; |
266 | arg_cpu = 1; | 258 | arg_cpu = 1; |
267 | arg_seccomp = 1; | 259 | arg_seccomp = 1; |
268 | arg_caps = 1; | 260 | arg_caps = 1; |
269 | arg_x11 = 1; | 261 | arg_x11 = 1; |
270 | arg_interface = 1; | ||
271 | arg_route = 1; | 262 | arg_route = 1; |
272 | arg_arp = 1; | 263 | arg_arp = 1; |
273 | arg_apparmor = 1; | 264 | arg_apparmor = 1; |
@@ -295,10 +286,6 @@ int main(int argc, char **argv) { | |||
295 | x11((pid_t) pid, print_procs); | 286 | x11((pid_t) pid, print_procs); |
296 | print_procs = 0; | 287 | print_procs = 0; |
297 | } | 288 | } |
298 | if (arg_interface && getuid() == 0) { | ||
299 | interface((pid_t) pid, print_procs); | ||
300 | print_procs = 0; | ||
301 | } | ||
302 | if (arg_route) { | 289 | if (arg_route) { |
303 | route((pid_t) pid, print_procs); | 290 | route((pid_t) pid, print_procs); |
304 | print_procs = 0; | 291 | print_procs = 0; |
diff --git a/src/firemon/firemon.h b/src/firemon/firemon.h index dae071e89..8b6e75fc3 100644 --- a/src/firemon/firemon.h +++ b/src/firemon/firemon.h | |||
@@ -57,9 +57,6 @@ void top(void) __attribute__((noreturn)); | |||
57 | // list.c | 57 | // list.c |
58 | void list(void); | 58 | void list(void); |
59 | 59 | ||
60 | // interface.c | ||
61 | void interface(pid_t pid, int print_procs); | ||
62 | |||
63 | // arp.c | 60 | // arp.c |
64 | void arp(pid_t pid, int print_procs); | 61 | void arp(pid_t pid, int print_procs); |
65 | 62 | ||
diff --git a/src/firemon/interface.c b/src/firemon/interface.c deleted file mode 100644 index a8e78133b..000000000 --- a/src/firemon/interface.c +++ /dev/null | |||
@@ -1,175 +0,0 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2023 Firejail Authors | ||
3 | * | ||
4 | * This file is part of firejail project | ||
5 | * | ||
6 | * This program is free software; you can redistribute it and/or modify | ||
7 | * it under the terms of the GNU General Public License as published by | ||
8 | * the Free Software Foundation; either version 2 of the License, or | ||
9 | * (at your option) any later version. | ||
10 | * | ||
11 | * This program is distributed in the hope that it will be useful, | ||
12 | * but WITHOUT ANY WARRANTY; without even the implied warranty of | ||
13 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | ||
14 | * GNU General Public License for more details. | ||
15 | * | ||
16 | * You should have received a copy of the GNU General Public License along | ||
17 | * with this program; if not, write to the Free Software Foundation, Inc., | ||
18 | * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. | ||
19 | */ | ||
20 | #include "firemon.h" | ||
21 | #include "../include/gcov_wrapper.h" | ||
22 | #include <sys/types.h> | ||
23 | #include <sys/wait.h> | ||
24 | #include <netdb.h> | ||
25 | #include <arpa/inet.h> | ||
26 | #include <ifaddrs.h> | ||
27 | #include <net/if.h> | ||
28 | #include <linux/connector.h> | ||
29 | #include <linux/netlink.h> | ||
30 | #include <linux/if_link.h> | ||
31 | #include <linux/sockios.h> | ||
32 | #include <sys/ioctl.h> | ||
33 | |||
34 | //#include <net/route.h> | ||
35 | //#include <linux/if_bridge.h> | ||
36 | |||
37 | // print IP addresses for all interfaces | ||
38 | static void net_ifprint(void) { | ||
39 | uint32_t ip; | ||
40 | uint32_t mask; | ||
41 | struct ifaddrs *ifaddr, *ifa; | ||
42 | |||
43 | int fd; | ||
44 | if ((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) { | ||
45 | fprintf(stderr, "Error: cannot open AF_INET socket\n"); | ||
46 | exit(1); | ||
47 | } | ||
48 | |||
49 | if (getifaddrs(&ifaddr) == -1) | ||
50 | errExit("getifaddrs"); | ||
51 | |||
52 | // walk through the linked list | ||
53 | printf(" Link status:\n"); | ||
54 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||
55 | if (ifa->ifa_addr == NULL) | ||
56 | continue; | ||
57 | |||
58 | if (ifa->ifa_addr->sa_family == AF_PACKET) { | ||
59 | if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) { | ||
60 | if (ifa->ifa_data != NULL) { | ||
61 | struct rtnl_link_stats *stats = ifa->ifa_data; | ||
62 | |||
63 | // extract mac address | ||
64 | struct ifreq ifr; | ||
65 | memset(&ifr, 0, sizeof(ifr)); | ||
66 | strncpy(ifr.ifr_name, ifa->ifa_name, IFNAMSIZ - 1); | ||
67 | int rv = ioctl (fd, SIOCGIFHWADDR, &ifr); | ||
68 | |||
69 | if (rv == 0) | ||
70 | printf(" %s UP, %02x:%02x:%02x:%02x:%02x:%02x\n", | ||
71 | ifa->ifa_name, PRINT_MAC((unsigned char *) &ifr.ifr_hwaddr.sa_data)); | ||
72 | else | ||
73 | printf(" %s UP\n", ifa->ifa_name); | ||
74 | |||
75 | printf(" tx/rx: %u/%u packets, %u/%u bytes\n", | ||
76 | stats->tx_packets, stats->rx_packets, | ||
77 | stats->tx_bytes, stats->rx_bytes); | ||
78 | } | ||
79 | } | ||
80 | else | ||
81 | printf(" %s DOWN\n", ifa->ifa_name); | ||
82 | } | ||
83 | } | ||
84 | |||
85 | |||
86 | // walk through the linked list | ||
87 | printf(" IPv4 status:\n"); | ||
88 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||
89 | if (ifa->ifa_addr == NULL) | ||
90 | continue; | ||
91 | |||
92 | if (ifa->ifa_addr->sa_family == AF_INET) { | ||
93 | struct sockaddr_in *si = (struct sockaddr_in *) ifa->ifa_netmask; | ||
94 | mask = ntohl(si->sin_addr.s_addr); | ||
95 | si = (struct sockaddr_in *) ifa->ifa_addr; | ||
96 | ip = ntohl(si->sin_addr.s_addr); | ||
97 | |||
98 | char *status; | ||
99 | if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) | ||
100 | status = "UP"; | ||
101 | else | ||
102 | status = "DOWN"; | ||
103 | |||
104 | printf(" %s %s, %d.%d.%d.%d/%u\n", | ||
105 | ifa->ifa_name, status, PRINT_IP(ip), mask2bits(mask)); | ||
106 | } | ||
107 | } | ||
108 | |||
109 | |||
110 | // walk through the linked list | ||
111 | printf(" IPv6 status:\n"); | ||
112 | for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next) { | ||
113 | if (ifa->ifa_addr == NULL) | ||
114 | continue; | ||
115 | |||
116 | if (ifa->ifa_addr->sa_family == AF_INET6) { | ||
117 | char host[NI_MAXHOST]; | ||
118 | int s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6), | ||
119 | host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST); | ||
120 | if (s == 0) { | ||
121 | char *ptr; | ||
122 | if ((ptr = strchr(host, '%')) != NULL) | ||
123 | *ptr = '\0'; | ||
124 | char *status; | ||
125 | if (ifa->ifa_flags & IFF_RUNNING && ifa->ifa_flags & IFF_UP) | ||
126 | status = "UP"; | ||
127 | else | ||
128 | status = "DOWN"; | ||
129 | |||
130 | printf(" %s %s, %s\n", ifa->ifa_name, status, host); | ||
131 | } | ||
132 | } | ||
133 | } | ||
134 | |||
135 | freeifaddrs(ifaddr); | ||
136 | close(fd); | ||
137 | } | ||
138 | |||
139 | static void print_sandbox(pid_t pid) { | ||
140 | pid_t child = fork(); | ||
141 | if (child == -1) | ||
142 | return; | ||
143 | |||
144 | if (child == 0) { | ||
145 | int rv = join_namespace(pid, "net"); | ||
146 | if (rv) | ||
147 | return; | ||
148 | net_ifprint(); | ||
149 | |||
150 | __gcov_flush(); | ||
151 | |||
152 | _exit(0); | ||
153 | } | ||
154 | |||
155 | // wait for the child to finish | ||
156 | waitpid(child, NULL, 0); | ||
157 | } | ||
158 | |||
159 | void interface(pid_t pid, int print_procs) { | ||
160 | pid_read(pid); // a pid of 0 will include all processes | ||
161 | |||
162 | // print processes | ||
163 | int i; | ||
164 | for (i = 0; i < max_pids; i++) { | ||
165 | if (pids[i].level == 1) { | ||
166 | if (print_procs || pid == 0) | ||
167 | pid_print_list(i, arg_wrap); | ||
168 | int child = find_child(i); | ||
169 | if (child != -1) { | ||
170 | print_sandbox(child); | ||
171 | } | ||
172 | } | ||
173 | } | ||
174 | printf("\n"); | ||
175 | } | ||
diff --git a/src/fldd/main.c b/src/fldd/main.c index 4b645b1b3..63398ce2e 100644 --- a/src/fldd/main.c +++ b/src/fldd/main.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include "../include/common.h" | 21 | #include "../include/common.h" |
22 | #include "../include/ldd_utils.h" | 22 | #include "../include/ldd_utils.h" |
23 | #ifdef HAVE_PRIVATE_LIB | ||
23 | 24 | ||
24 | #include <fcntl.h> | 25 | #include <fcntl.h> |
25 | #include <sys/mman.h> | 26 | #include <sys/mman.h> |
@@ -357,3 +358,9 @@ printf("\n"); | |||
357 | close(fd); | 358 | close(fd); |
358 | return 0; | 359 | return 0; |
359 | } | 360 | } |
361 | #else | ||
362 | int main(void) { | ||
363 | printf("Sorry, private lib is disabled in this build\n"); | ||
364 | return 0; | ||
365 | } | ||
366 | #endif \ No newline at end of file | ||
diff --git a/src/fnet/interface.c b/src/fnet/interface.c index ca7c744ed..50e1beaa0 100644 --- a/src/fnet/interface.c +++ b/src/fnet/interface.c | |||
@@ -213,6 +213,23 @@ void net_ifprint(int scan) { | |||
213 | fmessage("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", | 213 | fmessage("%-17.17s%-19.19s%-17.17s%-17.17s%-6.6s\n", |
214 | ifa->ifa_name, macstr, ipstr, maskstr, status); | 214 | ifa->ifa_name, macstr, ipstr, maskstr, status); |
215 | 215 | ||
216 | // print ipv6 address | ||
217 | if (!scan) { | ||
218 | struct ifaddrs *ptr = ifa->ifa_next; | ||
219 | while (ptr) { | ||
220 | if (ptr->ifa_addr->sa_family == AF_INET6 && strcmp(ifa->ifa_name, ptr->ifa_name) == 0) { | ||
221 | struct sockaddr_in6 *s6 = (struct sockaddr_in6 *)ptr->ifa_addr; | ||
222 | struct in6_addr *in_addr = &s6->sin6_addr; | ||
223 | char buf[64]; | ||
224 | if(inet_ntop(ptr->ifa_addr->sa_family, in_addr, buf, sizeof(buf))) { | ||
225 | fmessage("%-35.35s %s\n", " ", buf); | ||
226 | break; | ||
227 | } | ||
228 | } | ||
229 | ptr = ptr->ifa_next; | ||
230 | } | ||
231 | } | ||
232 | |||
216 | // network scanning | 233 | // network scanning |
217 | if (!scan) // scanning disabled | 234 | if (!scan) // scanning disabled |
218 | continue; | 235 | continue; |
diff --git a/src/fnet/main.c b/src/fnet/main.c index 96c4f1478..fc36ae977 100644 --- a/src/fnet/main.c +++ b/src/fnet/main.c | |||
@@ -87,7 +87,7 @@ printf("\n"); | |||
87 | else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) { | 87 | else if (argc == 7 && strcmp(argv[1], "create") == 0 && strcmp(argv[2], "veth") == 0) { |
88 | // create veth pair and move one end in the the namespace | 88 | // create veth pair and move one end in the the namespace |
89 | net_create_veth(argv[3], argv[4], atoi(argv[6])); | 89 | net_create_veth(argv[3], argv[4], atoi(argv[6])); |
90 | // connect the ohter veth end to the bridge ... | 90 | // connect the other veth end to the bridge ... |
91 | net_bridge_add_interface(argv[5], argv[3]); | 91 | net_bridge_add_interface(argv[5], argv[3]); |
92 | // ... and bring it up | 92 | // ... and bring it up |
93 | net_if_up(argv[3]); | 93 | net_if_up(argv[3]); |
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index 57a5a6d67..0b46daf65 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c | |||
@@ -23,33 +23,33 @@ int arg_quiet = 0; | |||
23 | int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill | 23 | int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill |
24 | 24 | ||
25 | static void usage(void) { | 25 | static void usage(void) { |
26 | printf("Usage:\n"); | 26 | printf("Usage:\n" |
27 | printf("\tfseccomp debug-syscalls\n"); | 27 | "\tfseccomp debug-syscalls\n" |
28 | printf("\tfseccomp debug-syscalls32\n"); | 28 | "\tfseccomp debug-syscalls32\n" |
29 | printf("\tfseccomp debug-errnos\n"); | 29 | "\tfseccomp debug-errnos\n" |
30 | printf("\tfseccomp debug-protocols\n"); | 30 | "\tfseccomp debug-protocols\n" |
31 | printf("\tfseccomp protocol build list file\n"); | 31 | "\tfseccomp protocol build list file\n" |
32 | printf("\tfseccomp secondary 64 file\n"); | 32 | "\tfseccomp secondary 64 file\n" |
33 | printf("\tfseccomp secondary 32 file\n"); | 33 | "\tfseccomp secondary 32 file\n" |
34 | printf("\tfseccomp secondary block file\n"); | 34 | "\tfseccomp secondary block file\n" |
35 | printf("\tfseccomp default file\n"); | 35 | "\tfseccomp default file\n" |
36 | printf("\tfseccomp default file allow-debuggers\n"); | 36 | "\tfseccomp default file allow-debuggers\n" |
37 | printf("\tfseccomp default32 file\n"); | 37 | "\tfseccomp default32 file\n" |
38 | printf("\tfseccomp default32 file allow-debuggers\n"); | 38 | "\tfseccomp default32 file allow-debuggers\n" |
39 | printf("\tfseccomp drop file1 file2 list\n"); | 39 | "\tfseccomp drop file1 file2 list\n" |
40 | printf("\tfseccomp drop file1 file2 list allow-debuggers\n"); | 40 | "\tfseccomp drop file1 file2 list allow-debuggers\n" |
41 | printf("\tfseccomp drop32 file1 file2 list\n"); | 41 | "\tfseccomp drop32 file1 file2 list\n" |
42 | printf("\tfseccomp drop32 file1 file2 list allow-debuggers\n"); | 42 | "\tfseccomp drop32 file1 file2 list allow-debuggers\n" |
43 | printf("\tfseccomp default drop file1 file2 list\n"); | 43 | "\tfseccomp default drop file1 file2 list\n" |
44 | printf("\tfseccomp default drop file1 file2 list allow-debuggers\n"); | 44 | "\tfseccomp default drop file1 file2 list allow-debuggers\n" |
45 | printf("\tfseccomp default32 drop file1 file2 list\n"); | 45 | "\tfseccomp default32 drop file1 file2 list\n" |
46 | printf("\tfseccomp default32 drop file1 file2 list allow-debuggers\n"); | 46 | "\tfseccomp default32 drop file1 file2 list allow-debuggers\n" |
47 | printf("\tfseccomp keep file1 file2 list\n"); | 47 | "\tfseccomp keep file1 file2 list\n" |
48 | printf("\tfseccomp keep32 file1 file2 list\n"); | 48 | "\tfseccomp keep32 file1 file2 list\n" |
49 | printf("\tfseccomp memory-deny-write-execute file\n"); | 49 | "\tfseccomp memory-deny-write-execute file\n" |
50 | printf("\tfseccomp memory-deny-write-execute.32 file\n"); | 50 | "\tfseccomp memory-deny-write-execute.32 file\n" |
51 | printf("\tfseccomp restrict-namespaces file list\n"); | 51 | "\tfseccomp restrict-namespaces file list\n" |
52 | printf("\tfseccomp restrict-namespaces.32 file list\n"); | 52 | "\tfseccomp restrict-namespaces.32 file list\n"); |
53 | } | 53 | } |
54 | 54 | ||
55 | int main(int argc, char **argv) { | 55 | int main(int argc, char **argv) { |
diff --git a/src/lib/firejail_user.c b/src/lib/firejail_user.c index dc6361422..a924f26cf 100644 --- a/src/lib/firejail_user.c +++ b/src/lib/firejail_user.c | |||
@@ -19,7 +19,7 @@ | |||
19 | */ | 19 | */ |
20 | 20 | ||
21 | // | 21 | // |
22 | // Firejail access database inplementation | 22 | // Firejail access database implementation |
23 | // | 23 | // |
24 | // The database is a simple list of users allowed to run firejail SUID executable | 24 | // The database is a simple list of users allowed to run firejail SUID executable |
25 | // It is usually stored in /etc/firejail/firejail.users | 25 | // It is usually stored in /etc/firejail/firejail.users |
diff --git a/src/lib/ldd_utils.c b/src/lib/ldd_utils.c index 39a548887..80e3b92d7 100644 --- a/src/lib/ldd_utils.c +++ b/src/lib/ldd_utils.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <sys/stat.h> | 23 | #include <sys/stat.h> |
24 | #include <fcntl.h> | 24 | #include <fcntl.h> |
25 | 25 | ||
26 | #ifdef HAVE_PRIVATE_LIB | ||
26 | // todo: resolve overlap with masked_lib_dirs[] array from fs_lib.c | 27 | // todo: resolve overlap with masked_lib_dirs[] array from fs_lib.c |
27 | const char * const default_lib_paths[] = { | 28 | const char * const default_lib_paths[] = { |
28 | "/usr/lib/x86_64-linux-gnu", // Debian & friends | 29 | "/usr/lib/x86_64-linux-gnu", // Debian & friends |
@@ -63,3 +64,4 @@ doexit: | |||
63 | close(fd); | 64 | close(fd); |
64 | return retval; | 65 | return retval; |
65 | } | 66 | } |
67 | #endif \ No newline at end of file | ||
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 3fa07d1ee..fa294d888 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -407,12 +407,14 @@ the current user's home directory. | |||
407 | All modifications are discarded when the sandbox is | 407 | All modifications are discarded when the sandbox is |
408 | closed. | 408 | closed. |
409 | #endif | 409 | #endif |
410 | #ifdef HAVE_PRIVATE_LIB | ||
410 | .TP | 411 | .TP |
411 | \fBprivate-lib file,directory | 412 | \fBprivate-lib file,directory |
412 | Build a new /lib directory and bring in the libraries required by the application to run. | 413 | Build a new /lib directory and bring in the libraries required by the application to run. |
413 | The files and directories in the list must be expressed as relative to | 414 | The files and directories in the list must be expressed as relative to |
414 | the /lib directory. | 415 | the /lib directory. |
415 | This feature is still under development, see \fBman 1 firejail\fR for some examples. | 416 | This feature is still under development, see \fBman 1 firejail\fR for some examples. |
417 | #endif | ||
416 | .TP | 418 | .TP |
417 | \fBprivate-opt file,directory | 419 | \fBprivate-opt file,directory |
418 | Build a new /opt in a temporary | 420 | Build a new /opt in a temporary |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 6068c9ff4..586ef9852 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -684,9 +684,11 @@ Print all recognized error numbers in the current Firejail software build and ex | |||
684 | Example: | 684 | Example: |
685 | .br | 685 | .br |
686 | $ firejail \-\-debug-errnos | 686 | $ firejail \-\-debug-errnos |
687 | #ifdef HAVE_PRIVATE_LIB | ||
687 | .TP | 688 | .TP |
688 | \fB\-\-debug-private-lib | 689 | \fB\-\-debug-private-lib |
689 | Debug messages for --private-lib option. | 690 | Debug messages for --private-lib option. |
691 | #endif | ||
690 | .TP | 692 | .TP |
691 | \fB\-\-debug-protocols | 693 | \fB\-\-debug-protocols |
692 | Print all recognized protocols in the current Firejail software build and exit. | 694 | Print all recognized protocols in the current Firejail software build and exit. |
@@ -2179,6 +2181,7 @@ Example: | |||
2179 | .br | 2181 | .br |
2180 | $ firejail \-\-private-home=.mozilla firefox | 2182 | $ firejail \-\-private-home=.mozilla firefox |
2181 | #endif | 2183 | #endif |
2184 | #ifdef HAVE_PRIVATE_LIB | ||
2182 | .TP | 2185 | .TP |
2183 | \fB\-\-private-lib=file,directory | 2186 | \fB\-\-private-lib=file,directory |
2184 | This feature is currently under heavy development. Only amd64 platforms are supported at this moment. | 2187 | This feature is currently under heavy development. Only amd64 platforms are supported at this moment. |
@@ -2234,6 +2237,7 @@ $ | |||
2234 | .br | 2237 | .br |
2235 | Note: Support for this command is controlled in firejail.config with the | 2238 | Note: Support for this command is controlled in firejail.config with the |
2236 | \fBprivate-lib\fR option. | 2239 | \fBprivate-lib\fR option. |
2240 | #endif | ||
2237 | .TP | 2241 | .TP |
2238 | \fB\-\-private-opt=file,directory | 2242 | \fB\-\-private-opt=file,directory |
2239 | Build a new /opt in a temporary | 2243 | Build a new /opt in a temporary |
diff --git a/src/man/firemon.txt b/src/man/firemon.txt index 9d0785a4a..fb0cf1175 100644 --- a/src/man/firemon.txt +++ b/src/man/firemon.txt | |||
@@ -30,9 +30,6 @@ Print debug messages | |||
30 | \fB\-?\fR, \fB\-\-help\fR | 30 | \fB\-?\fR, \fB\-\-help\fR |
31 | Print options end exit. | 31 | Print options end exit. |
32 | .TP | 32 | .TP |
33 | \fB\-\-interface | ||
34 | Print network interface information for each sandbox. | ||
35 | .TP | ||
36 | \fB\-\-list | 33 | \fB\-\-list |
37 | List all sandboxes. | 34 | List all sandboxes. |
38 | .TP | 35 | .TP |