aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config9
-rw-r--r--src/firejail/appimage.c54
-rw-r--r--src/firejail/arp.c2
-rw-r--r--src/firejail/checkcfg.c8
-rw-r--r--src/firejail/firejail.h9
-rw-r--r--src/firejail/fs_dev.c1
-rw-r--r--src/firejail/fs_etc.c5
-rw-r--r--src/firejail/fs_home.c18
-rw-r--r--src/firejail/fs_lib.c60
-rw-r--r--src/firejail/fs_lib2.c2
-rw-r--r--src/firejail/fs_var.c23
-rw-r--r--src/firejail/ls.c4
-rw-r--r--src/firejail/main.c27
-rw-r--r--src/firejail/netfilter.c2
-rw-r--r--src/firejail/network.c26
-rw-r--r--src/firejail/output.c4
-rw-r--r--src/firejail/restrict_users.c4
-rw-r--r--src/firejail/sandbox.c2
-rw-r--r--src/firejail/sbox.c2
-rw-r--r--src/firejail/usage.c9
-rw-r--r--src/firejail/util.c33
-rw-r--r--src/firemon/firemon.c15
-rw-r--r--src/firemon/firemon.h3
-rw-r--r--src/firemon/interface.c175
-rw-r--r--src/fldd/main.c7
-rw-r--r--src/fnet/interface.c17
-rw-r--r--src/fnet/main.c2
-rw-r--r--src/fseccomp/main.c54
-rw-r--r--src/lib/firejail_user.c2
-rw-r--r--src/lib/ldd_utils.c2
-rw-r--r--src/man/firejail-profile.txt2
-rw-r--r--src/man/firejail.txt4
-rw-r--r--src/man/firemon.txt3
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
11Cyberfox 11Cyberfox
12Discord 12Discord
13DiscordCanary 13DiscordCanary
14DiscordPTB
14Documents 15Documents
15FossaMail 16FossaMail
16Fritzing 17Fritzing
@@ -24,6 +25,7 @@ Natron
24PCSX2 25PCSX2
25PPSSPPQt 26PPSSPPQt
26PPSSPPSDL 27PPSSPPSDL
28Postman
27QMediathekView 29QMediathekView
28QOwnNotes 30QOwnNotes
29Screenshot 31Screenshot
@@ -44,6 +46,7 @@ amarok
44amule 46amule
45amuled 47amuled
46android-studio 48android-studio
49ani-cli
47anydesk 50anydesk
48apktool 51apktool
49apostrophe 52apostrophe
@@ -196,6 +199,7 @@ dino
196dino-im 199dino-im
197discord 200discord
198discord-canary 201discord-canary
202discord-ptb
199display 203display
200display-im6.q16 204display-im6.q16
201dnox 205dnox
@@ -418,6 +422,7 @@ ipcalc
418ipcalc-ng 422ipcalc-ng
419iridium 423iridium
420iridium-browser 424iridium-browser
425jami
421jd-gui 426jd-gui
422jdownloader 427jdownloader
423jerry 428jerry
@@ -483,6 +488,7 @@ linphone
483linuxqq 488linuxqq
484lmms 489lmms
485lobase 490lobase
491lobster
486localc 492localc
487lodraw 493lodraw
488loffice 494loffice
@@ -533,6 +539,7 @@ meteo-qt
533microsoft-edge 539microsoft-edge
534microsoft-edge-beta 540microsoft-edge-beta
535microsoft-edge-dev 541microsoft-edge-dev
542microsoft-edge-stable
536midori 543midori
537min 544min
538mindless 545mindless
@@ -677,6 +684,8 @@ pluma
677plv 684plv
678pngquant 685pngquant
679polari 686polari
687porn-cli
688postman
680ppsspp 689ppsspp
681pragha 690pragha
682presentations18 691presentations18
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
33static long unsigned size = 0; // offset into appimage file 33static 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 36static void err_loop(char *msg) {
37static 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
44int appimage_find_profile(const char *archive) { 42int 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
303static uint32_t arp_sequential(const char *dev, Bridge *br) { 303static 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
528int invalid_name(const char *name);
529void errLogExit(char* fmt, ...) __attribute__((noreturn)); 528void errLogExit(char* fmt, ...) __attribute__((noreturn));
530void fwarning(char* fmt, ...); 529void fwarning(char* fmt, ...);
531void fmessage(char* fmt, ...); 530void fmessage(char* fmt, ...);
@@ -581,6 +580,13 @@ int has_handler(pid_t pid, int signal);
581void enter_network_namespace(pid_t pid); 580void enter_network_namespace(pid_t pid);
582int read_pid(const char *name, pid_t *pid); 581int read_pid(const char *name, pid_t *pid);
583pid_t require_pid(const char *name); 582pid_t require_pid(const char *name);
583int ascii_isalnum(unsigned char c);
584int ascii_isalpha(unsigned char c);
585int ascii_isdigit(unsigned char c);
586int ascii_islower(unsigned char c);
587int ascii_isupper(unsigned char c);
588int ascii_isxdigit(unsigned char c);
589int invalid_name(const char *name);
584void check_homedir(const char *dir); 590void 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);
606void fs_var_lock(void); 612void fs_var_lock(void);
607void fs_var_tmp(void); 613void fs_var_tmp(void);
608void fs_var_utmp(void); 614void fs_var_utmp(void);
609void dbg_test_dir(const char *dir);
610 615
611// fs_dev.c 616// fs_dev.c
612void fs_dev_shm(void); 617void 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
113void fs_resolvconf(void) { 113void 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);
32extern void fslib_install_firejail(void); 32extern void fslib_install_firejail(void);
33extern void fslib_install_system(void); 33extern void fslib_install_system(void);
34 34
35static int lib_cnt = 0;
36static int dir_cnt = 0;
37
38static 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[]
49static 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
65int is_firejail_link(const char *fname) { 36int 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
91static int lib_cnt = 0;
92static int dir_cnt = 0;
93
94static 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[]
105static 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
119static char *build_dest_dir(const char *full_path) { 120static 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
39static LibList libc_list[] = { 40static 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
233void 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
248void fs_var_lock(void) { 233void 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
263void fs_var_tmp(void) { 246void 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
280void fs_var_utmp(void) { 261void 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
92void 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
117int net_get_if_addr(const char *bridge, uint32_t *ip, uint32_t *mask, uint8_t mac[6], int *mtu) { 93int 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
1451int ascii_isalnum(unsigned char c) {
1452 return (ascii_isalpha(c) || ascii_isdigit(c));
1453}
1454
1455int ascii_isalpha(unsigned char c) {
1456 return (ascii_islower(c) || ascii_isupper(c));
1457}
1458
1459int ascii_isdigit(unsigned char c) {
1460 return (c >= '0' && c <= '9');
1461}
1462
1463int ascii_islower(unsigned char c) {
1464 return (c >= 'a' && c <= 'z');
1465}
1466
1467int ascii_isupper(unsigned char c) {
1468 return (c >= 'A' && c <= 'Z');
1469}
1470
1471int 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
1452int invalid_name(const char *name) { 1479int 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;
30static int arg_route = 0; 30static int arg_route = 0;
31static int arg_arp = 0; 31static int arg_arp = 0;
32static int arg_tree = 0; 32static int arg_tree = 0;
33static int arg_interface = 0;
34static int arg_seccomp = 0; 33static int arg_seccomp = 0;
35static int arg_caps = 0; 34static int arg_caps = 0;
36static int arg_cpu = 0; 35static 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
58void list(void); 58void list(void);
59 59
60// interface.c
61void interface(pid_t pid, int print_procs);
62
63// arp.c 60// arp.c
64void arp(pid_t pid, int print_procs); 61void 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
38static 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
139static 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
159void 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
362int 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;
23int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill 23int arg_seccomp_error_action = SECCOMP_RET_ERRNO | EPERM; // error action: errno, log or kill
24 24
25static void usage(void) { 25static 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
55int main(int argc, char **argv) { 55int 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
27const char * const default_lib_paths[] = { 28const 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.
407All modifications are discarded when the sandbox is 407All modifications are discarded when the sandbox is
408closed. 408closed.
409#endif 409#endif
410#ifdef HAVE_PRIVATE_LIB
410.TP 411.TP
411\fBprivate-lib file,directory 412\fBprivate-lib file,directory
412Build a new /lib directory and bring in the libraries required by the application to run. 413Build a new /lib directory and bring in the libraries required by the application to run.
413The files and directories in the list must be expressed as relative to 414The files and directories in the list must be expressed as relative to
414the /lib directory. 415the /lib directory.
415This feature is still under development, see \fBman 1 firejail\fR for some examples. 416This 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
418Build a new /opt in a temporary 420Build 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
684Example: 684Example:
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
689Debug messages for --private-lib option. 690Debug messages for --private-lib option.
691#endif
690.TP 692.TP
691\fB\-\-debug-protocols 693\fB\-\-debug-protocols
692Print all recognized protocols in the current Firejail software build and exit. 694Print 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
2184This feature is currently under heavy development. Only amd64 platforms are supported at this moment. 2187This feature is currently under heavy development. Only amd64 platforms are supported at this moment.
@@ -2234,6 +2237,7 @@ $
2234.br 2237.br
2235Note: Support for this command is controlled in firejail.config with the 2238Note: 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
2239Build a new /opt in a temporary 2243Build 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
31Print options end exit. 31Print options end exit.
32.TP 32.TP
33\fB\-\-interface
34Print network interface information for each sandbox.
35.TP
36\fB\-\-list 33\fB\-\-list
37List all sandboxes. 34List all sandboxes.
38.TP 35.TP