aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config4
-rw-r--r--src/firejail/arp.c4
-rw-r--r--src/firejail/bandwidth.c24
-rw-r--r--src/firejail/checkcfg.c2
-rw-r--r--src/firejail/chroot.c3
-rw-r--r--src/firejail/firejail.h40
-rw-r--r--src/firejail/fs_dev.c3
-rw-r--r--src/firejail/join.c2
-rw-r--r--src/firejail/ls.c169
-rw-r--r--src/firejail/main.c36
-rw-r--r--src/firejail/output.c3
-rw-r--r--src/firejail/profile.c2
-rw-r--r--src/firejail/protocol.c2
-rw-r--r--src/firejail/sandbox.c43
-rw-r--r--src/firejail/sbox.c2
-rw-r--r--src/firejail/shutdown.c2
-rw-r--r--src/firejail/usage.c6
-rw-r--r--src/firejail/x11.c4
-rw-r--r--src/firemon/firemon.h6
-rw-r--r--src/firemon/procevent.c13
-rw-r--r--src/fseccomp/main.c4
-rw-r--r--src/include/seccomp.h2
-rw-r--r--src/include/syscall.h2
-rw-r--r--src/lib/errno.c2
-rw-r--r--src/man/firejail-profile.txt6
-rw-r--r--src/man/firejail.txt32
26 files changed, 258 insertions, 160 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index 05c5681d5..0574daae6 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -327,6 +327,9 @@ gradio
327gramps 327gramps
328gravity-beams-and-evaporating-stars 328gravity-beams-and-evaporating-stars
329gthumb 329gthumb
330gtk-youtube-viewer
331gtk2-youtube-viewer
332gtk3-youtube-viewer
330guayadeque 333guayadeque
331gucharmap 334gucharmap
332gummi 335gummi
@@ -816,6 +819,7 @@ xviewer
816yandex-browser 819yandex-browser
817yelp 820yelp
818youtube-dl 821youtube-dl
822youtube-viewer
819zaproxy 823zaproxy
820zart 824zart
821zathura 825zathura
diff --git a/src/firejail/arp.c b/src/firejail/arp.c
index 3714af9a3..f88d0a1dd 100644
--- a/src/firejail/arp.c
+++ b/src/firejail/arp.c
@@ -239,9 +239,7 @@ int arp_check(const char *dev, uint32_t destaddr) {
239 } 239 }
240 } 240 }
241 241
242 // it will never get here! 242 __builtin_unreachable();
243 close(sock);
244 return -1;
245} 243}
246 244
247// assign a random IP address and check it 245// assign a random IP address and check it
diff --git a/src/firejail/bandwidth.c b/src/firejail/bandwidth.c
index edef823fd..6fd0b53ef 100644
--- a/src/firejail/bandwidth.c
+++ b/src/firejail/bandwidth.c
@@ -327,6 +327,15 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
327 devname = strdup(buf + len + 1); 327 devname = strdup(buf + len + 1);
328 if (!devname) 328 if (!devname)
329 errExit("strdup"); 329 errExit("strdup");
330 // double-check device name
331 size_t i;
332 for (i = 0; devname[i]; i++) {
333 if (isalnum((unsigned char) devname[i]) == 0 &&
334 devname[i] != '-') {
335 fprintf(stderr, "Error: name of network device is invalid\n");
336 exit(1);
337 }
338 }
330 // check device in namespace 339 // check device in namespace
331 if (if_nametoindex(devname) == 0) { 340 if (if_nametoindex(devname) == 0) {
332 fprintf(stderr, "Error: cannot find network device %s\n", devname); 341 fprintf(stderr, "Error: cannot find network device %s\n", devname);
@@ -354,6 +363,7 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
354 } 363 }
355 bandwidth_remove(pid, devname); 364 bandwidth_remove(pid, devname);
356 } 365 }
366 else assert(strcmp(command, "status") == 0);
357 367
358 // build fshaper.sh command 368 // build fshaper.sh command
359 char *cmd = NULL; 369 char *cmd = NULL;
@@ -375,26 +385,16 @@ void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, in
375 } 385 }
376 assert(cmd); 386 assert(cmd);
377 387
378 // wipe out environment variables
379 environ = NULL;
380
381 //************************ 388 //************************
382 // build command 389 // build command
383 //************************ 390 //************************
384 // elevate privileges
385 if (setreuid(0, 0))
386 errExit("setreuid");
387 if (setregid(0, 0))
388 errExit("setregid");
389
390 char *arg[4]; 391 char *arg[4];
391 arg[0] = "/bin/sh"; 392 arg[0] = "/bin/sh";
392 arg[1] = "-c"; 393 arg[1] = "-c";
393 arg[2] = cmd; 394 arg[2] = cmd;
394 arg[3] = NULL; 395 arg[3] = NULL;
395 clearenv(); 396 clearenv();
396 execvp(arg[0], arg); 397 sbox_exec_v(SBOX_ROOT | SBOX_CAPS_NETWORK | SBOX_SECCOMP, arg);
397 398
398 // it will never get here 399 // it will never get here!!
399 errExit("execvp");
400} 400}
diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c
index 5d6b4af66..f6b3b3252 100644
--- a/src/firejail/checkcfg.c
+++ b/src/firejail/checkcfg.c
@@ -229,6 +229,8 @@ int checkcfg(int val) {
229#ifdef HAVE_SECCOMP 229#ifdef HAVE_SECCOMP
230 if (strcmp(ptr + 21, "kill") == 0) 230 if (strcmp(ptr + 21, "kill") == 0)
231 cfg_val[CFG_SECCOMP_ERROR_ACTION] = SECCOMP_RET_KILL; 231 cfg_val[CFG_SECCOMP_ERROR_ACTION] = SECCOMP_RET_KILL;
232 else if (strcmp(ptr + 21, "log") == 0)
233 cfg_val[CFG_SECCOMP_ERROR_ACTION] = SECCOMP_RET_LOG;
232 else { 234 else {
233 cfg_val[CFG_SECCOMP_ERROR_ACTION] = errno_find_name(ptr + 21); 235 cfg_val[CFG_SECCOMP_ERROR_ACTION] = errno_find_name(ptr + 21);
234 if (cfg_val[CFG_SECCOMP_ERROR_ACTION] == -1) 236 if (cfg_val[CFG_SECCOMP_ERROR_ACTION] == -1)
diff --git a/src/firejail/chroot.c b/src/firejail/chroot.c
index cae52e20b..5fc6c8298 100644
--- a/src/firejail/chroot.c
+++ b/src/firejail/chroot.c
@@ -165,7 +165,8 @@ void fs_chroot(const char *rootdir) {
165 close(fd); 165 close(fd);
166 166
167 // x11 167 // x11
168 if (getenv("FIREJAIL_X11")) { 168 // if users want this mount, they should set FIREJAIL_CHROOT_X11
169 if (getenv("FIREJAIL_X11") || getenv("FIREJAIL_CHROOT_X11")) {
169 if (arg_debug) 170 if (arg_debug)
170 printf("Mounting /tmp/.X11-unix on chroot /tmp/.X11-unix\n"); 171 printf("Mounting /tmp/.X11-unix on chroot /tmp/.X11-unix\n");
171 check_subdir(parentfd, "tmp/.X11-unix", 0); 172 check_subdir(parentfd, "tmp/.X11-unix", 0);
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h
index 54a1023ab..49d19e33d 100644
--- a/src/firejail/firejail.h
+++ b/src/firejail/firejail.h
@@ -186,7 +186,7 @@ typedef struct config_t {
186 char *seccomp_list_drop, *seccomp_list_drop32; // seccomp drop list 186 char *seccomp_list_drop, *seccomp_list_drop32; // seccomp drop list
187 char *seccomp_list_keep, *seccomp_list_keep32; // seccomp keep list 187 char *seccomp_list_keep, *seccomp_list_keep32; // seccomp keep list
188 char *protocol; // protocol list 188 char *protocol; // protocol list
189 char *seccomp_error_action; // error action: kill or errno 189 char *seccomp_error_action; // error action: kill, log or errno
190 190
191 // rlimits 191 // rlimits
192 long long unsigned rlimit_cpu; 192 long long unsigned rlimit_cpu;
@@ -371,14 +371,14 @@ char *guess_shell(void);
371 371
372// sandbox.c 372// sandbox.c
373int sandbox(void* sandbox_arg); 373int sandbox(void* sandbox_arg);
374void start_application(int no_sandbox, FILE *fp); 374void start_application(int no_sandbox, FILE *fp) __attribute__((noreturn));
375void set_apparmor(void); 375void set_apparmor(void);
376 376
377// network_main.c 377// network_main.c
378void net_configure_sandbox_ip(Bridge *br); 378void net_configure_sandbox_ip(Bridge *br);
379void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child); 379void net_configure_veth_pair(Bridge *br, const char *ifname, pid_t child);
380void net_check_cfg(void); 380void net_check_cfg(void);
381void net_dns_print(pid_t pid); 381void net_dns_print(pid_t pid) __attribute__((noreturn));
382void network_main(pid_t child); 382void network_main(pid_t child);
383void net_print(pid_t pid); 383void net_print(pid_t pid);
384 384
@@ -453,13 +453,12 @@ void profile_add_ignore(const char *str);
453void list(void); 453void list(void);
454void tree(void); 454void tree(void);
455void top(void); 455void top(void);
456void netstats(void);
457 456
458// usage.c 457// usage.c
459void usage(void); 458void usage(void);
460 459
461// join.c 460// join.c
462void join(pid_t pid, int argc, char **argv, int index); 461void join(pid_t pid, int argc, char **argv, int index) __attribute__((noreturn));
463bool is_ready_for_join(const pid_t pid); 462bool is_ready_for_join(const pid_t pid);
464void check_join_permission(pid_t pid); 463void check_join_permission(pid_t pid);
465pid_t switch_to_child(pid_t pid); 464pid_t switch_to_child(pid_t pid);
@@ -486,7 +485,7 @@ int macro_id(const char *name);
486 485
487 486
488// util.c 487// util.c
489void errLogExit(char* fmt, ...); 488void errLogExit(char* fmt, ...) __attribute__((noreturn));
490void fwarning(char* fmt, ...); 489void fwarning(char* fmt, ...);
491void fmessage(char* fmt, ...); 490void fmessage(char* fmt, ...);
492void drop_privs(int nogroups); 491void drop_privs(int nogroups);
@@ -584,7 +583,7 @@ int seccomp_load(const char *fname);
584int seccomp_filter_drop(bool native); 583int seccomp_filter_drop(bool native);
585int seccomp_filter_keep(bool native); 584int seccomp_filter_keep(bool native);
586int seccomp_filter_mdwx(bool native); 585int seccomp_filter_mdwx(bool native);
587void seccomp_print_filter(pid_t pid); 586void seccomp_print_filter(pid_t pid) __attribute__((noreturn));
588 587
589// caps.c 588// caps.c
590void seccomp_load_file_list(void); 589void seccomp_load_file_list(void);
@@ -595,7 +594,7 @@ void caps_set(uint64_t caps);
595void caps_check_list(const char *clist, void (*callback)(int)); 594void caps_check_list(const char *clist, void (*callback)(int));
596void caps_drop_list(const char *clist); 595void caps_drop_list(const char *clist);
597void caps_keep_list(const char *clist); 596void caps_keep_list(const char *clist);
598void caps_print_filter(pid_t pid); 597void caps_print_filter(pid_t pid) __attribute__((noreturn));
599void caps_drop_dac_override(void); 598void caps_drop_dac_override(void);
600 599
601// fs_trace.c 600// fs_trace.c
@@ -618,7 +617,7 @@ void read_cpu_list(const char *str);
618void set_cpu_affinity(void); 617void set_cpu_affinity(void);
619void load_cpu(const char *fname); 618void load_cpu(const char *fname);
620void save_cpu(void); 619void save_cpu(void);
621void cpu_print_filter(pid_t pid); 620void cpu_print_filter(pid_t pid) __attribute__((noreturn));
622 621
623// cgroup.c 622// cgroup.c
624void save_cgroup(void); 623void save_cgroup(void);
@@ -640,7 +639,7 @@ void netns(const char *nsname);
640void netns_mounts(const char *nsname); 639void netns_mounts(const char *nsname);
641 640
642// bandwidth.c 641// bandwidth.c
643void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up); 642void bandwidth_pid(pid_t pid, const char *command, const char *dev, int down, int up) __attribute__((noreturn));
644void network_set_run_file(pid_t pid); 643void network_set_run_file(pid_t pid);
645 644
646// fs_etc.c 645// fs_etc.c
@@ -650,7 +649,7 @@ void fs_private_dir_list(const char *private_dir, const char *private_run_dir, c
650// no_sandbox.c 649// no_sandbox.c
651int check_namespace_virt(void); 650int check_namespace_virt(void);
652int check_kernel_procs(void); 651int check_kernel_procs(void);
653void run_no_sandbox(int argc, char **argv); 652void run_no_sandbox(int argc, char **argv) __attribute__((noreturn));
654 653
655#define MAX_ENVS 256 // some sane maximum number of environment variables 654#define MAX_ENVS 256 // some sane maximum number of environment variables
656#define MAX_ENV_LEN (PATH_MAX + 32) // FOOBAR=SOME_PATH 655#define MAX_ENV_LEN (PATH_MAX + 32) // FOOBAR=SOME_PATH
@@ -681,7 +680,7 @@ void fs_private_lib(void);
681// protocol.c 680// protocol.c
682void protocol_filter_save(void); 681void protocol_filter_save(void);
683void protocol_filter_load(const char *fname); 682void protocol_filter_load(const char *fname);
684void protocol_print_filter(pid_t pid); 683void protocol_print_filter(pid_t pid) __attribute__((noreturn));
685 684
686// restrict_users.c 685// restrict_users.c
687void restrict_users(void); 686void restrict_users(void);
@@ -693,7 +692,7 @@ void fs_logger2int(const char *msg1, int d);
693void fs_logger3(const char *msg1, const char *msg2, const char *msg3); 692void fs_logger3(const char *msg1, const char *msg2, const char *msg3);
694void fs_logger_print(void); 693void fs_logger_print(void);
695void fs_logger_change_owner(void); 694void fs_logger_change_owner(void);
696void fs_logger_print_log(pid_t pid); 695void fs_logger_print_log(pid_t pid) __attribute__((noreturn));
697 696
698// run_symlink.c 697// run_symlink.c
699void run_symlink(int argc, char **argv, int run_as_is); 698void run_symlink(int argc, char **argv, int run_as_is);
@@ -719,21 +718,24 @@ void fs_mkfile(const char *name);
719 718
720void fs_x11(void); 719void fs_x11(void);
721int x11_display(void); 720int x11_display(void);
722void x11_start(int argc, char **argv); 721void x11_start(int argc, char **argv) __attribute__((noreturn));
723void x11_start_xpra(int argc, char **argv); 722void x11_start_xpra(int argc, char **argv) __attribute__((noreturn));
724void x11_start_xephyr(int argc, char **argv); 723void x11_start_xephyr(int argc, char **argv) __attribute__((noreturn));
725void x11_block(void); 724void x11_block(void);
726void x11_start_xvfb(int argc, char **argv); 725void x11_start_xvfb(int argc, char **argv) __attribute__((noreturn));
727void x11_xorg(void); 726void x11_xorg(void);
728 727
729// ls.c 728// ls.c
730enum { 729enum {
731 SANDBOX_FS_LS = 0, 730 SANDBOX_FS_LS = 0,
731 SANDBOX_FS_CAT,
732 SANDBOX_FS_GET, 732 SANDBOX_FS_GET,
733 SANDBOX_FS_PUT, 733 SANDBOX_FS_PUT,
734 SANDBOX_FS_MAX // this should always be the last entry 734 SANDBOX_FS_MAX // this should always be the last entry
735}; 735};
736void sandboxfs(int op, pid_t pid, const char *path1, const char *path2); 736void ls(const char *path);
737void cat(const char *path);
738void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) __attribute__((noreturn));
737 739
738// checkcfg.c 740// checkcfg.c
739#define DEFAULT_ARP_PROBES 2 741#define DEFAULT_ARP_PROBES 2
@@ -839,7 +841,7 @@ void build_appimage_cmdline(char **command_line, char **window_title, int argc,
839// run sbox 841// run sbox
840int sbox_run(unsigned filter, int num, ...); 842int sbox_run(unsigned filter, int num, ...);
841int sbox_run_v(unsigned filter, char * const arg[]); 843int sbox_run_v(unsigned filter, char * const arg[]);
842void sbox_exec_v(unsigned filter, char * const arg[]); 844void sbox_exec_v(unsigned filter, char * const arg[]) __attribute__((noreturn));
843 845
844// run_files.c 846// run_files.c
845void delete_run_files(pid_t pid); 847void delete_run_files(pid_t pid);
diff --git a/src/firejail/fs_dev.c b/src/firejail/fs_dev.c
index fbce72429..00edc5f88 100644
--- a/src/firejail/fs_dev.c
+++ b/src/firejail/fs_dev.c
@@ -25,6 +25,7 @@
25#include <dirent.h> 25#include <dirent.h>
26#include <fcntl.h> 26#include <fcntl.h>
27#include <pwd.h> 27#include <pwd.h>
28#include <errno.h>
28#ifndef _BSD_SOURCE 29#ifndef _BSD_SOURCE
29#define _BSD_SOURCE 30#define _BSD_SOURCE
30#endif 31#endif
@@ -148,7 +149,7 @@ static void create_char_dev(const char *path, mode_t mode, int major, int minor)
148 return; 149 return;
149 150
150errexit: 151errexit:
151 fprintf(stderr, "Error: cannot create %s device\n", path); 152 fprintf(stderr, "Error: cannot create %s device: %s\n", path, strerror(errno));
152 exit(1); 153 exit(1);
153} 154}
154 155
diff --git a/src/firejail/join.c b/src/firejail/join.c
index 4c8555f29..f202d1a9c 100644
--- a/src/firejail/join.c
+++ b/src/firejail/join.c
@@ -588,7 +588,7 @@ void join(pid_t pid, int argc, char **argv, int index) {
588 588
589 start_application(0, NULL); 589 start_application(0, NULL);
590 590
591 // it will never get here!!! 591 __builtin_unreachable();
592 } 592 }
593 EUID_USER(); 593 EUID_USER();
594 594
diff --git a/src/firejail/ls.c b/src/firejail/ls.c
index aa33d838b..4d0a001b6 100644
--- a/src/firejail/ls.c
+++ b/src/firejail/ls.c
@@ -34,18 +34,12 @@
34static uid_t c_uid = 0; 34static uid_t c_uid = 0;
35static char *c_uid_name = NULL; 35static char *c_uid_name = NULL;
36 36
37static void print_file_or_dir(const char *path, const char *fname, int separator) { 37static void print_file_or_dir(const char *path, const char *fname) {
38 assert(fname); 38 assert(fname);
39 39
40 char *name; 40 char *name;
41 if (separator) { 41 if (asprintf(&name, "%s/%s", path, fname) == -1)
42 if (asprintf(&name, "%s/%s", path, fname) == -1) 42 errExit("asprintf");
43 errExit("asprintf");
44 }
45 else {
46 if (asprintf(&name, "%s%s", path, fname) == -1)
47 errExit("asprintf");
48 }
49 43
50 struct stat s; 44 struct stat s;
51 if (stat(name, &s) == -1) { 45 if (stat(name, &s) == -1) {
@@ -178,13 +172,81 @@ static void print_directory(const char *path) {
178 errExit("scandir"); 172 errExit("scandir");
179 else { 173 else {
180 for (i = 0; i < n; i++) { 174 for (i = 0; i < n; i++) {
181 print_file_or_dir(path, namelist[i]->d_name, 0); 175 print_file_or_dir(path, namelist[i]->d_name);
182 free(namelist[i]); 176 free(namelist[i]);
183 } 177 }
184 } 178 }
185 free(namelist); 179 free(namelist);
186} 180}
187 181
182void ls(const char *path) {
183 EUID_ASSERT();
184 assert(path);
185
186 char *rp = realpath(path, NULL);
187 if (!rp || access(rp, R_OK) == -1) {
188 fprintf(stderr, "Error: cannot access %s\n", path);
189 exit(1);
190 }
191 if (arg_debug)
192 printf("ls %s\n", rp);
193
194 // list directory contents
195 struct stat s;
196 if (stat(rp, &s) == -1) {
197 fprintf(stderr, "Error: cannot access %s\n", rp);
198 exit(1);
199 }
200 if (S_ISDIR(s.st_mode))
201 print_directory(rp);
202 else {
203 char *split = strrchr(rp, '/');
204 if (split) {
205 *split = '\0';
206 char *rp2 = split + 1;
207 if (arg_debug)
208 printf("path %s, file %s\n", rp, rp2);
209 print_file_or_dir(rp, rp2);
210 }
211 }
212 free(rp);
213}
214
215void cat(const char *path) {
216 EUID_ASSERT();
217 assert(path);
218
219 if (arg_debug)
220 printf("cat %s\n", path);
221 FILE *fp = fopen(path, "r");
222 if (!fp) {
223 fprintf(stderr, "Error: cannot read %s\n", path);
224 exit(1);
225 }
226 int fd = fileno(fp);
227 if (fd == -1)
228 errExit("fileno");
229 struct stat s;
230 if (fstat(fd, &s) == -1)
231 errExit("fstat");
232 if (!S_ISREG(s.st_mode)) {
233 fprintf(stderr, "Error: %s is not a regular file\n", path);
234 exit(1);
235 }
236 bool tty = isatty(STDOUT_FILENO);
237
238 int c;
239 while ((c = fgetc(fp)) != EOF) {
240 // file is untrusted
241 // replace control characters when printing to a terminal
242 if (tty && c != '\t' && c != '\n' && iscntrl((unsigned char) c))
243 c = '?';
244 fputc(c, stdout);
245 }
246 fflush(stdout);
247 fclose(fp);
248}
249
188char *expand_path(const char *path) { 250char *expand_path(const char *path) {
189 char *fname = NULL; 251 char *fname = NULL;
190 if (*path == '/') { 252 if (*path == '/') {
@@ -219,14 +281,14 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
219 check_join_permission(pid); 281 check_join_permission(pid);
220 282
221 // expand paths 283 // expand paths
222 char *fname1 = expand_path(path1);; 284 char *fname1 = expand_path(path1);
223 char *fname2 = NULL; 285 char *fname2 = NULL;
224 if (path2 != NULL) { 286 if (path2 != NULL) {
225 fname2 = expand_path(path2); 287 fname2 = expand_path(path2);
226 } 288 }
227 if (arg_debug) { 289 if (arg_debug) {
228 printf("file1 %s\n", fname1); 290 printf("file1 %s\n", fname1);
229 printf("file2 %s\n", fname2); 291 printf("file2 %s\n", fname2 ? fname2 : "(null)");
230 } 292 }
231 293
232 // sandbox root directory 294 // sandbox root directory
@@ -234,57 +296,36 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
234 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1) 296 if (asprintf(&rootdir, "/proc/%d/root", pid) == -1)
235 errExit("asprintf"); 297 errExit("asprintf");
236 298
237 if (op == SANDBOX_FS_LS) { 299 if (op == SANDBOX_FS_LS || op == SANDBOX_FS_CAT) {
238 EUID_ROOT(); 300 pid_t child = fork();
239 // chroot 301 if (child < 0)
240 if (chroot(rootdir) < 0) 302 errExit("fork");
241 errExit("chroot"); 303 if (child == 0) {
242 if (chdir("/") < 0) 304 EUID_ROOT();
243 errExit("chdir"); 305 // chroot
244 306 if (chroot(rootdir) < 0)
245 // drop privileges 307 errExit("chroot");
246 drop_privs(0); 308 if (chdir("/") < 0)
247 309 errExit("chdir");
248 // check access
249 if (access(fname1, R_OK) == -1) {
250 fprintf(stderr, "Error: Cannot access %s\n", fname1);
251 exit(1);
252 }
253 /* coverity[toctou] */
254 char *rp = realpath(fname1, NULL);
255 if (!rp) {
256 fprintf(stderr, "Error: Cannot access %s\n", fname1);
257 exit(1);
258 }
259 if (arg_debug)
260 printf("realpath %s\n", rp);
261
262 310
263 // list directory contents 311 // drop privileges
264 struct stat s; 312 drop_privs(0);
265 if (stat(rp, &s) == -1) {
266 fprintf(stderr, "Error: Cannot access %s\n", rp);
267 exit(1);
268 }
269 if (S_ISDIR(s.st_mode)) {
270 char *dir;
271 if (asprintf(&dir, "%s/", rp) == -1)
272 errExit("asprintf");
273 313
274 print_directory(dir); 314 if (op == SANDBOX_FS_LS)
275 free(dir); 315 ls(fname1);
276 } 316 else
277 else { 317 cat(fname1);
278 char *split = strrchr(rp, '/'); 318#ifdef HAVE_GCOV
279 if (split) { 319 __gcov_flush();
280 *split = '\0'; 320#endif
281 char *rp2 = split + 1; 321 _exit(0);
282 if (arg_debug)
283 printf("path %s, file %s\n", rp, rp2);
284 print_file_or_dir(rp, rp2, 1);
285 }
286 } 322 }
287 free(rp); 323 // wait for the child to finish
324 int status = 0;
325 waitpid(child, &status, 0);
326 if (WIFEXITED(status) && WEXITSTATUS(status) == 0);
327 else
328 exit(1);
288 } 329 }
289 330
290 // get file from sandbox and store it in the current directory 331 // get file from sandbox and store it in the current directory
@@ -303,10 +344,12 @@ void sandboxfs(int op, pid_t pid, const char *path1, const char *path2) {
303 // create a user-owned temporary file in /run/firejail directory 344 // create a user-owned temporary file in /run/firejail directory
304 char tmp_fname[] = "/run/firejail/tmpget-XXXXXX"; 345 char tmp_fname[] = "/run/firejail/tmpget-XXXXXX";
305 int fd = mkstemp(tmp_fname); 346 int fd = mkstemp(tmp_fname);
306 if (fd != -1) { 347 if (fd == -1) {
307 SET_PERMS_FD(fd, getuid(), getgid(), 0600); 348 fprintf(stderr, "Error: cannot create temporary file %s\n", tmp_fname);
308 close(fd); 349 exit(1);
309 } 350 }
351 SET_PERMS_FD(fd, getuid(), getgid(), 0600);
352 close(fd);
310 353
311 // copy the source file into the temporary file - we need to chroot 354 // copy the source file into the temporary file - we need to chroot
312 pid_t child = fork(); 355 pid_t child = fork();
diff --git a/src/firejail/main.c b/src/firejail/main.c
index 4aa5311a2..1ffa6158c 100644
--- a/src/firejail/main.c
+++ b/src/firejail/main.c
@@ -811,6 +811,8 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
811 } 811 }
812 812
813 // list directory contents 813 // list directory contents
814 if (!arg_debug)
815 arg_quiet = 1;
814 pid_t pid = require_pid(argv[i] + 5); 816 pid_t pid = require_pid(argv[i] + 5);
815 sandboxfs(SANDBOX_FS_LS, pid, path, NULL); 817 sandboxfs(SANDBOX_FS_LS, pid, path, NULL);
816 exit(0); 818 exit(0);
@@ -818,6 +820,35 @@ static void run_cmd_and_exit(int i, int argc, char **argv) {
818 else 820 else
819 exit_err_feature("file transfer"); 821 exit_err_feature("file transfer");
820 } 822 }
823 else if (strncmp(argv[i], "--cat=", 6) == 0) {
824 if (checkcfg(CFG_FILE_TRANSFER)) {
825 logargs(argc, argv);
826 if (arg_private_cwd) {
827 fprintf(stderr, "Error: --cat and --private-cwd options are mutually exclusive\n");
828 exit(1);
829 }
830
831 if ((i + 2) != argc) {
832 fprintf(stderr, "Error: invalid --cat option, path expected\n");
833 exit(1);
834 }
835 char *path = argv[i + 1];
836 invalid_filename(path, 0); // no globbing
837 if (strstr(path, "..")) {
838 fprintf(stderr, "Error: invalid file name %s\n", path);
839 exit(1);
840 }
841
842 // write file contents to stdout
843 if (!arg_debug)
844 arg_quiet = 1;
845 pid_t pid = require_pid(argv[i] + 6);
846 sandboxfs(SANDBOX_FS_CAT, pid, path, NULL);
847 exit(0);
848 }
849 else
850 exit_err_feature("file transfer");
851 }
821#endif 852#endif
822 else if (strncmp(argv[i], "--join=", 7) == 0) { 853 else if (strncmp(argv[i], "--join=", 7) == 0) {
823 if (checkcfg(CFG_JOIN) || getuid() == 0) { 854 if (checkcfg(CFG_JOIN) || getuid() == 0) {
@@ -1159,8 +1190,7 @@ int main(int argc, char **argv, char **envp) {
1159 1190
1160 // start the program directly without sandboxing 1191 // start the program directly without sandboxing
1161 run_no_sandbox(argc, argv); 1192 run_no_sandbox(argc, argv);
1162 // it will never get here! 1193 __builtin_unreachable();
1163 assert(0);
1164 } 1194 }
1165 } 1195 }
1166 EUID_ASSERT(); 1196 EUID_ASSERT();
@@ -1446,6 +1476,8 @@ int main(int argc, char **argv, char **envp) {
1446 if (config_seccomp_error_action == -1) { 1476 if (config_seccomp_error_action == -1) {
1447 if (strcmp(argv[i] + 23, "kill") == 0) 1477 if (strcmp(argv[i] + 23, "kill") == 0)
1448 arg_seccomp_error_action = SECCOMP_RET_KILL; 1478 arg_seccomp_error_action = SECCOMP_RET_KILL;
1479 else if (strcmp(argv[i] + 23, "log") == 0)
1480 arg_seccomp_error_action = SECCOMP_RET_LOG;
1449 else { 1481 else {
1450 arg_seccomp_error_action = errno_find_name(argv[i] + 23); 1482 arg_seccomp_error_action = errno_find_name(argv[i] + 23);
1451 if (arg_seccomp_error_action == -1) 1483 if (arg_seccomp_error_action == -1)
diff --git a/src/firejail/output.c b/src/firejail/output.c
index 0e961bb61..36cb905cb 100644
--- a/src/firejail/output.c
+++ b/src/firejail/output.c
@@ -122,7 +122,8 @@ void check_output(int argc, char **argv) {
122 } 122 }
123 bool found_separator = false; 123 bool found_separator = false;
124 /* copy argv into args, but drop --output(-stderr) arguments */ 124 /* copy argv into args, but drop --output(-stderr) arguments */
125 for (int i = 0, j = 0; i < argc; i++) { 125 int j;
126 for (i = 0, j = 0; i < argc; i++) {
126 if (!found_separator && i > 0) { 127 if (!found_separator && i > 0) {
127 if (strncmp(argv[i], "--output=", 9) == 0) { 128 if (strncmp(argv[i], "--output=", 9) == 0) {
128 continue; 129 continue;
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index 70acd8a2a..970033899 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -991,6 +991,8 @@ int profile_check_line(char *ptr, int lineno, const char *fname) {
991 if (config_seccomp_error_action == -1) { 991 if (config_seccomp_error_action == -1) {
992 if (strcmp(ptr + 21, "kill") == 0) 992 if (strcmp(ptr + 21, "kill") == 0)
993 arg_seccomp_error_action = SECCOMP_RET_KILL; 993 arg_seccomp_error_action = SECCOMP_RET_KILL;
994 else if (strcmp(ptr + 21, "log") == 0)
995 arg_seccomp_error_action = SECCOMP_RET_LOG;
994 else { 996 else {
995 arg_seccomp_error_action = errno_find_name(ptr + 21); 997 arg_seccomp_error_action = errno_find_name(ptr + 21);
996 if (arg_seccomp_error_action == -1) 998 if (arg_seccomp_error_action == -1)
diff --git a/src/firejail/protocol.c b/src/firejail/protocol.c
index 6402afbc6..a1594d6b9 100644
--- a/src/firejail/protocol.c
+++ b/src/firejail/protocol.c
@@ -90,7 +90,7 @@ void protocol_print_filter(pid_t pid) {
90 exit(0); 90 exit(0);
91#else 91#else
92 fwarning("--protocol not supported on this platform\n"); 92 fwarning("--protocol not supported on this platform\n");
93 return; 93 exit(1);
94#endif 94#endif
95} 95}
96 96
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index 2314d5744..81d535762 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -140,6 +140,20 @@ void set_apparmor(void) {
140} 140}
141#endif 141#endif
142 142
143#ifdef HAVE_SECCOMP
144void seccomp_debug(void) {
145 if (arg_debug == 0)
146 return;
147
148 EUID_USER();
149 printf("Seccomp directory:\n");
150 ls(RUN_SECCOMP_DIR);
151 printf("Active seccomp files:\n");
152 cat(RUN_SECCOMP_LIST);
153 EUID_ROOT();
154}
155#endif
156
143static void save_nogroups(void) { 157static void save_nogroups(void) {
144 if (arg_nogroups == 0) 158 if (arg_nogroups == 0)
145 return; 159 return;
@@ -197,32 +211,6 @@ static FILE *create_ready_for_join_file(void) {
197 } 211 }
198} 212}
199 213
200#ifdef HAVE_SECCOMP
201static void seccomp_debug(void) {
202 if (arg_debug == 0)
203 return;
204
205 pid_t child = fork();
206 if (child < 0)
207 errExit("fork");
208 if (child == 0) {
209 // dropping privs before calling system(3)
210 drop_privs(1);
211 printf("Seccomp directory:\n");
212 int rv = system("ls -l " RUN_SECCOMP_DIR);
213 (void) rv;
214 printf("Active seccomp files:\n");
215 rv = system("cat " RUN_SECCOMP_LIST);
216 (void) rv;
217#ifdef HAVE_GCOV
218 __gcov_flush();
219#endif
220 _exit(0);
221 }
222 waitpid(child, NULL, 0);
223}
224#endif
225
226static void sandbox_if_up(Bridge *br) { 214static void sandbox_if_up(Bridge *br) {
227 assert(br); 215 assert(br);
228 if (!br->configured) 216 if (!br->configured)
@@ -666,7 +654,8 @@ int sandbox(void* sandbox_arg) {
666 // ... and mount a tmpfs on top of /run/firejail/mnt directory 654 // ... and mount a tmpfs on top of /run/firejail/mnt directory
667 preproc_mount_mnt_dir(); 655 preproc_mount_mnt_dir();
668 // bind-mount firejail binaries and helper programs 656 // bind-mount firejail binaries and helper programs
669 if (mount(LIBDIR "/firejail", RUN_FIREJAIL_LIB_DIR, "none", MS_BIND, NULL) < 0) 657 if (mount(LIBDIR "/firejail", RUN_FIREJAIL_LIB_DIR, NULL, MS_BIND, NULL) < 0 ||
658 mount(NULL, RUN_FIREJAIL_LIB_DIR, NULL, MS_RDONLY|MS_NOSUID|MS_NODEV|MS_BIND|MS_REMOUNT, NULL) < 0)
670 errExit("mounting " RUN_FIREJAIL_LIB_DIR); 659 errExit("mounting " RUN_FIREJAIL_LIB_DIR);
671 660
672 //**************************** 661 //****************************
diff --git a/src/firejail/sbox.c b/src/firejail/sbox.c
index cf3d3aeed..a92d62940 100644
--- a/src/firejail/sbox.c
+++ b/src/firejail/sbox.c
@@ -31,7 +31,7 @@
31#define O_PATH 010000000 31#define O_PATH 010000000
32#endif 32#endif
33 33
34static int sbox_do_exec_v(unsigned filtermask, char * const arg[]) { 34static int __attribute__((noreturn)) sbox_do_exec_v(unsigned filtermask, char * const arg[]) {
35 // build a new, clean environment 35 // build a new, clean environment
36 int env_index = 0; 36 int env_index = 0;
37 char *new_environment[256] = { NULL }; 37 char *new_environment[256] = { NULL };
diff --git a/src/firejail/shutdown.c b/src/firejail/shutdown.c
index a7d0b2fbe..7e9628007 100644
--- a/src/firejail/shutdown.c
+++ b/src/firejail/shutdown.c
@@ -63,7 +63,9 @@ void shut(pid_t pid) {
63 sleep(1); 63 sleep(1);
64 monsec--; 64 monsec--;
65 65
66 EUID_ROOT();
66 FILE *fp = fopen(monfile, "r"); 67 FILE *fp = fopen(monfile, "r");
68 EUID_USER();
67 if (!fp) { 69 if (!fp) {
68 killdone = 1; 70 killdone = 1;
69 break; 71 break;
diff --git a/src/firejail/usage.c b/src/firejail/usage.c
index 4ab464289..2390706f2 100644
--- a/src/firejail/usage.c
+++ b/src/firejail/usage.c
@@ -47,6 +47,9 @@ static char *usage_str =
47 " --caps.drop=capability,capability - blacklist capabilities filter.\n" 47 " --caps.drop=capability,capability - blacklist capabilities filter.\n"
48 " --caps.keep=capability,capability - whitelist capabilities filter.\n" 48 " --caps.keep=capability,capability - whitelist capabilities filter.\n"
49 " --caps.print=name|pid - print the caps filter.\n" 49 " --caps.print=name|pid - print the caps filter.\n"
50#ifdef HAVE_FILE_TRANSFER
51 " --cat=name|pid filename - print content of file from sandbox container.\n"
52#endif
50 " --cgroup=tasks-file - place the sandbox in the specified control group.\n" 53 " --cgroup=tasks-file - place the sandbox in the specified control group.\n"
51#ifdef HAVE_CHROOT 54#ifdef HAVE_CHROOT
52 " --chroot=dirname - chroot into directory.\n" 55 " --chroot=dirname - chroot into directory.\n"
@@ -224,7 +227,8 @@ static char *usage_str =
224 " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n" 227 " --seccomp.print=name|pid - print the seccomp filter for the sandbox\n"
225 "\tidentified by name or PID.\n" 228 "\tidentified by name or PID.\n"
226 " --seccomp.32[.drop,.keep][=syscall] - like above but for 32 bit architecture.\n" 229 " --seccomp.32[.drop,.keep][=syscall] - like above but for 32 bit architecture.\n"
227 " --seccomp-error-action=errno|kill - change error code or kill process.\n" 230 " --seccomp-error-action=errno|kill|log - change error code, kill process\n"
231 "\tor log the attempt.\n"
228#endif 232#endif
229 " --shell=none - run the program directly without a user shell.\n" 233 " --shell=none - run the program directly without a user shell.\n"
230 " --shell=program - set default user shell.\n" 234 " --shell=program - set default user shell.\n"
diff --git a/src/firejail/x11.c b/src/firejail/x11.c
index 1ecb688af..e10abad4e 100644
--- a/src/firejail/x11.c
+++ b/src/firejail/x11.c
@@ -682,7 +682,7 @@ static char * get_title_arg_str() {
682} 682}
683 683
684 684
685void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) { 685static void __attribute__((noreturn)) x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {
686 EUID_ASSERT(); 686 EUID_ASSERT();
687 int i; 687 int i;
688 struct stat s; 688 struct stat s;
@@ -921,7 +921,7 @@ void x11_start_xpra_old(int argc, char **argv, int display, char *display_str) {
921} 921}
922 922
923 923
924void x11_start_xpra_new(int argc, char **argv, char *display_str) { 924static void __attribute__((noreturn)) x11_start_xpra_new(int argc, char **argv, char *display_str) {
925 EUID_ASSERT(); 925 EUID_ASSERT();
926 int i; 926 int i;
927 pid_t server = 0; 927 pid_t server = 0;
diff --git a/src/firemon/firemon.h b/src/firemon/firemon.h
index 7a55a64fb..3fba486eb 100644
--- a/src/firemon/firemon.h
+++ b/src/firemon/firemon.h
@@ -46,13 +46,13 @@ void firemon_sleep(int st);
46 46
47 47
48// procevent.c 48// procevent.c
49void procevent(pid_t pid); 49void procevent(pid_t pid) __attribute__((noreturn));
50 50
51// usage.c 51// usage.c
52void usage(void); 52void usage(void);
53 53
54// top.c 54// top.c
55void top(void); 55void top(void) __attribute__((noreturn));
56 56
57// list.c 57// list.c
58void list(void); 58void list(void);
@@ -82,7 +82,7 @@ void cgroup(pid_t pid, int print_procs);
82void tree(pid_t pid); 82void tree(pid_t pid);
83 83
84// netstats.c 84// netstats.c
85void netstats(void); 85void netstats(void) __attribute__((noreturn));
86 86
87// x11.c 87// x11.c
88void x11(pid_t pid, int print_procs); 88void x11(pid_t pid, int print_procs);
diff --git a/src/firemon/procevent.c b/src/firemon/procevent.c
index 7dd08444e..45964d3a2 100644
--- a/src/firemon/procevent.c
+++ b/src/firemon/procevent.c
@@ -220,7 +220,7 @@ errexit:
220} 220}
221 221
222 222
223static int procevent_monitor(const int sock, pid_t mypid) { 223static void __attribute__((noreturn)) procevent_monitor(const int sock, pid_t mypid) {
224 ssize_t len; 224 ssize_t len;
225 struct nlmsghdr *nlmsghdr; 225 struct nlmsghdr *nlmsghdr;
226 226
@@ -246,8 +246,7 @@ static int procevent_monitor(const int sock, pid_t mypid) {
246 246
247 int rv = select(max, &readfds, NULL, NULL, &tv); 247 int rv = select(max, &readfds, NULL, NULL, &tv);
248 if (rv == -1) { 248 if (rv == -1) {
249 fprintf(stderr, "recv: %s\n", strerror(errno)); 249 errExit("recv");
250 return -1;
251 } 250 }
252 251
253 // timeout 252 // timeout
@@ -259,7 +258,7 @@ static int procevent_monitor(const int sock, pid_t mypid) {
259 258
260 259
261 if ((len = recv(sock, buf, sizeof(buf), 0)) == 0) 260 if ((len = recv(sock, buf, sizeof(buf), 0)) == 0)
262 return 0; 261 exit(0);
263 if (len == -1) { 262 if (len == -1) {
264 if (errno == EINTR) 263 if (errno == EINTR)
265 continue; 264 continue;
@@ -271,7 +270,7 @@ static int procevent_monitor(const int sock, pid_t mypid) {
271 } 270 }
272 else { 271 else {
273 fprintf(stderr,"Error: rx socket recv call, errno %d, %s\n", errno, strerror(errno)); 272 fprintf(stderr,"Error: rx socket recv call, errno %d, %s\n", errno, strerror(errno));
274 return -1; 273 exit(1);
275 } 274 }
276 } 275 }
277 276
@@ -497,7 +496,7 @@ static int procevent_monitor(const int sock, pid_t mypid) {
497 exit(0); 496 exit(0);
498 } 497 }
499 } 498 }
500 return 0; 499 __builtin_unreachable();
501} 500}
502 501
503void procevent(pid_t pid) { 502void procevent(pid_t pid) {
@@ -515,6 +514,4 @@ void procevent(pid_t pid) {
515 } 514 }
516 515
517 procevent_monitor(sock, pid); // it will never return from here 516 procevent_monitor(sock, pid); // it will never return from here
518 assert(0);
519 close(sock); // quiet static analyzers
520} 517}
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c
index 13eb3dfe7..f505ca0f3 100644
--- a/src/fseccomp/main.c
+++ b/src/fseccomp/main.c
@@ -20,7 +20,7 @@
20#include "fseccomp.h" 20#include "fseccomp.h"
21#include "../include/seccomp.h" 21#include "../include/seccomp.h"
22int arg_quiet = 0; 22int arg_quiet = 0;
23int arg_seccomp_error_action = EPERM; // error action: errno or kill 23int arg_seccomp_error_action = 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");
@@ -83,6 +83,8 @@ printf("\n");
83 if (error_action) { 83 if (error_action) {
84 if (strcmp(error_action, "kill") == 0) 84 if (strcmp(error_action, "kill") == 0)
85 arg_seccomp_error_action = SECCOMP_RET_KILL; 85 arg_seccomp_error_action = SECCOMP_RET_KILL;
86 else if (strcmp(error_action, "log") == 0)
87 arg_seccomp_error_action = SECCOMP_RET_LOG;
86 else { 88 else {
87 arg_seccomp_error_action = errno_find_name(error_action); 89 arg_seccomp_error_action = errno_find_name(error_action);
88 if (arg_seccomp_error_action == -1) 90 if (arg_seccomp_error_action == -1)
diff --git a/src/include/seccomp.h b/src/include/seccomp.h
index 50920ce3a..29b858c70 100644
--- a/src/include/seccomp.h
+++ b/src/include/seccomp.h
@@ -274,7 +274,7 @@ struct seccomp_data {
274#define RETURN_ERRNO(nr) \ 274#define RETURN_ERRNO(nr) \
275 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr) 275 BPF_STMT(BPF_RET+BPF_K, SECCOMP_RET_ERRNO | nr)
276 276
277extern int arg_seccomp_error_action; // error action: errno or kill 277extern int arg_seccomp_error_action; // error action: errno, log or kill
278#define KILL_OR_RETURN_ERRNO \ 278#define KILL_OR_RETURN_ERRNO \
279 BPF_STMT(BPF_RET+BPF_K, arg_seccomp_error_action) 279 BPF_STMT(BPF_RET+BPF_K, arg_seccomp_error_action)
280 280
diff --git a/src/include/syscall.h b/src/include/syscall.h
index 89b54170e..489da0600 100644
--- a/src/include/syscall.h
+++ b/src/include/syscall.h
@@ -32,7 +32,7 @@ void filter_add_blacklist_override(int fd, int syscall, int arg, void *ptrarg, b
32// errno.c 32// errno.c
33void errno_print(void); 33void errno_print(void);
34int errno_find_name(const char *name); 34int errno_find_name(const char *name);
35char *errno_find_nr(int nr); 35const char *errno_find_nr(int nr);
36 36
37// syscall.c 37// syscall.c
38void syscall_print(void); 38void syscall_print(void);
diff --git a/src/lib/errno.c b/src/lib/errno.c
index d38c197ad..881c3b27e 100644
--- a/src/lib/errno.c
+++ b/src/lib/errno.c
@@ -183,7 +183,7 @@ int errno_find_name(const char *name) {
183 return -1; 183 return -1;
184} 184}
185 185
186char *errno_find_nr(int nr) { 186const char *errno_find_nr(int nr) {
187 int i; 187 int i;
188 int elems = sizeof(errnolist) / sizeof(errnolist[0]); 188 int elems = sizeof(errnolist) / sizeof(errnolist[0]);
189 for (i = 0; i < elems; i++) { 189 for (i = 0; i < elems; i++) {
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index 7b5653942..0784e7fd7 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -433,8 +433,10 @@ Enable seccomp filter and whitelist the system calls in the list.
433\fBseccomp.32.keep syscall,syscall,syscall 433\fBseccomp.32.keep syscall,syscall,syscall
434Enable seccomp filter and whitelist the system calls in the list for 32 bit system calls on a 64 bit architecture system. 434Enable seccomp filter and whitelist the system calls in the list for 32 bit system calls on a 64 bit architecture system.
435.TP 435.TP
436\fBseccomp-error-action kill | ERRNO 436\fBseccomp-error-action kill | log | ERRNO
437Return a different error instead of EPERM to the process or kill it when an attempt is made to call a blocked system call. 437Return a different error instead of EPERM to the process, kill it when
438an attempt is made to call a blocked system call, or allow but log the
439attempt.
438.TP 440.TP
439\fBx11 441\fBx11
440Enable X11 sandboxing. 442Enable X11 sandboxing.
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 69cd4a7bc..3b7ba4e3d 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -273,6 +273,10 @@ $ firejail \-\-list
273$ firejail \-\-caps.print=3272 273$ firejail \-\-caps.print=3272
274 274
275.TP 275.TP
276\fB\-\-cat=name|pid filename
277Print content of file from sandbox container, see FILE TRANSFER section for more details.
278
279.TP
276\fB\-\-cgroup=tasks-file 280\fB\-\-cgroup=tasks-file
277Place the sandbox in the specified control group. tasks-file is the full path of cgroup tasks file. 281Place the sandbox in the specified control group. tasks-file is the full path of cgroup tasks file.
278.br 282.br
@@ -344,7 +348,7 @@ $ firejail --dbus-system=filter --dbus-system.log --dbus-log=dbus.txt
344 348
345.TP 349.TP
346\fB\-\-dbus-system=filter|none 350\fB\-\-dbus-system=filter|none
347Set system DBus sandboxing policy. 351Set system DBus sandboxing policy.
348.br 352.br
349 353
350.br 354.br
@@ -1059,7 +1063,7 @@ that are both writable and executable, to change mappings to be
1059executable, or to create executable shared memory. The filter examines 1063executable, or to create executable shared memory. The filter examines
1060the arguments of mmap, mmap2, mprotect, pkey_mprotect, memfd_create 1064the arguments of mmap, mmap2, mprotect, pkey_mprotect, memfd_create
1061and shmat system calls and returns error EPERM to the process (or 1065and shmat system calls and returns error EPERM to the process (or
1062kills it, see \-\-seccomp-error-action below) if necessary. 1066kills it or log the attempt, see \-\-seccomp-error-action below) if necessary.
1063.br 1067.br
1064 1068
1065.br 1069.br
@@ -2122,8 +2126,8 @@ Instead of dropping the syscall by returning EPERM, another error
2122number can be returned using \fBsyscall:errno\fR syntax. This can be 2126number can be returned using \fBsyscall:errno\fR syntax. This can be
2123also changed globally with \-\-seccomp-error-action or 2127also changed globally with \-\-seccomp-error-action or
2124in /etc/firejail/firejail.config file. The process can also be killed 2128in /etc/firejail/firejail.config file. The process can also be killed
2125by using \fBsyscall:kill\fR syntax. 2129by using \fBsyscall:kill\fR syntax, or the attempt may be logged with
2126 2130\fBsyscall:log\fR.
2127.br 2131.br
2128 2132
2129.br 2133.br
@@ -2193,7 +2197,8 @@ Instead of dropping the syscall by returning EPERM, another error
2193number can be returned using \fBsyscall:errno\fR syntax. This can be 2197number can be returned using \fBsyscall:errno\fR syntax. This can be
2194also changed globally with \-\-seccomp-error-action or 2198also changed globally with \-\-seccomp-error-action or
2195in /etc/firejail/firejail.config file. The process can also be killed 2199in /etc/firejail/firejail.config file. The process can also be killed
2196by using \fBsyscall:kill\fR syntax. 2200by using \fBsyscall:kill\fR syntax, or the attempt may be logged with
2201\fBsyscall:log\fR.
2197.br 2202.br
2198 2203
2199.br 2204.br
@@ -2402,7 +2407,8 @@ By default, if a seccomp filter blocks a system call, the process gets
2402EPERM as the error. With \-\-seccomp-error-action=error, another error 2407EPERM as the error. With \-\-seccomp-error-action=error, another error
2403number can be returned, for example ENOSYS or EACCES. The process can 2408number can be returned, for example ENOSYS or EACCES. The process can
2404also be killed (like in versions <0.9.63 of Firejail) by using 2409also be killed (like in versions <0.9.63 of Firejail) by using
2405\-\-seccomp-error-action=kill syntax. Not killing the process weakens 2410\-\-seccomp-error-action=kill syntax, or the attempt may be logged
2411with \-\-seccomp-error-action=log. Not killing the process weakens
2406Firejail slightly when trying to contain intrusion, but it may also 2412Firejail slightly when trying to contain intrusion, but it may also
2407allow tighter filters if the only alternative is to allow a system 2413allow tighter filters if the only alternative is to allow a system
2408call. 2414call.
@@ -3029,6 +3035,12 @@ These features allow the user to inspect the filesystem container of an existing
3029and transfer files between the container and the host filesystem. 3035and transfer files between the container and the host filesystem.
3030 3036
3031.TP 3037.TP
3038\fB\-\-cat=name|pid filename
3039Write content of a container file to standard out. The container is specified by name or PID.
3040If standard out is a terminal, all ASCII control characters except new line and horizontal tab
3041are replaced.
3042
3043.TP
3032\fB\-\-get=name|pid filename 3044\fB\-\-get=name|pid filename
3033Retrieve the container file and store it on the host in the current working directory. 3045Retrieve the container file and store it on the host in the current working directory.
3034The container is specified by name or PID. 3046The container is specified by name or PID.
@@ -3072,6 +3084,10 @@ $ firejail \-\-get=mybrowser ~/Downloads/xpra-clipboard.png
3072$ firejail \-\-put=mybrowser xpra-clipboard.png ~/Downloads/xpra-clipboard.png 3084$ firejail \-\-put=mybrowser xpra-clipboard.png ~/Downloads/xpra-clipboard.png
3073.br 3085.br
3074 3086
3087.br
3088$ firejail \-\-cat=mybrowser ~/.bashrc
3089.br
3090
3075.SH MONITORING 3091.SH MONITORING
3076Option \-\-list prints a list of all sandboxes. The format 3092Option \-\-list prints a list of all sandboxes. The format
3077for each process entry is as follows: 3093for each process entry is as follows:
@@ -3259,7 +3275,7 @@ Homepage: https://firejail.wordpress.com
3259\&\flfirejail-profile\fR\|(5), 3275\&\flfirejail-profile\fR\|(5),
3260\&\flfirejail-login\fR\|(5), 3276\&\flfirejail-login\fR\|(5),
3261\&\flfirejail-users\fR\|(5), 3277\&\flfirejail-users\fR\|(5),
3262.UR https://github.com/netblue30/firejail/wiki 3278.UR https://github.com/netblue30/firejail/wiki
3263.UE , 3279.UE ,
3264.UR https://github.com/netblue30/firejail 3280.UR https://github.com/netblue30/firejail
3265.UE 3281.UE