aboutsummaryrefslogtreecommitdiffstats
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/firecfg/firecfg.config2
-rw-r--r--src/firejail/fs_lib.c71
-rw-r--r--src/firejail/profile.c5
-rw-r--r--src/firejail/sandbox.c28
-rw-r--r--src/lib/ldd_utils.c1
-rw-r--r--src/man/firejail-profile.txt2
-rw-r--r--src/man/firejail.txt10
-rw-r--r--src/zsh_completion/_firejail.in359
8 files changed, 275 insertions, 203 deletions
diff --git a/src/firecfg/firecfg.config b/src/firecfg/firecfg.config
index b44a1bc85..16cd59aa5 100644
--- a/src/firecfg/firecfg.config
+++ b/src/firecfg/firecfg.config
@@ -553,6 +553,8 @@ neverputt
553newsbeuter 553newsbeuter
554newsboat 554newsboat
555newsflash 555newsflash
556nextcloud
557nextcloud-desktop
556nheko 558nheko
557nicotine 559nicotine
558nitroshare 560nitroshare
diff --git a/src/firejail/fs_lib.c b/src/firejail/fs_lib.c
index 7e9666fc0..99d57fbbb 100644
--- a/src/firejail/fs_lib.c
+++ b/src/firejail/fs_lib.c
@@ -34,6 +34,31 @@ extern void fslib_install_system(void);
34static int lib_cnt = 0; 34static int lib_cnt = 0;
35static int dir_cnt = 0; 35static int dir_cnt = 0;
36 36
37static const char *lib_dirs[] = {
38 "/usr/lib64",
39 "/lib64",
40 "/usr/lib",
41 "/lib",
42 "/usr/local/lib64",
43 "/usr/local/lib",
44 NULL,
45};
46
47// return 1 if the file is in lib_dirs[]
48static int valid_full_path(const char *full_path) {
49 if (strstr(full_path, ".."))
50 return 0;
51
52 int i = 0;
53 while (lib_dirs[i]) {
54 if (strncmp(full_path, lib_dirs[i], strlen(lib_dirs[i])) == 0 &&
55 full_path[strlen(lib_dirs[i])] == '/')
56 return 1;
57 i++;
58 }
59 return 0;
60}
61
37char *find_in_path(const char *program) { 62char *find_in_path(const char *program) {
38 EUID_ASSERT(); 63 EUID_ASSERT();
39 if (arg_debug) 64 if (arg_debug)
@@ -108,7 +133,8 @@ void fslib_duplicate(const char *full_path) {
108 assert(full_path); 133 assert(full_path);
109 134
110 struct stat s; 135 struct stat s;
111 if (stat(full_path, &s) != 0 || s.st_uid != 0 || access(full_path, R_OK)) 136 if (stat(full_path, &s) != 0 || s.st_uid != 0 || access(full_path, R_OK)
137 || !valid_full_path(full_path))
112 return; 138 return;
113 139
114 char *dest_dir = build_dest_dir(full_path); 140 char *dest_dir = build_dest_dir(full_path);
@@ -208,7 +234,8 @@ void fslib_copy_dir(const char *full_path) {
208 234
209 // do nothing if the directory does not exist or is not owned by root 235 // do nothing if the directory does not exist or is not owned by root
210 struct stat s; 236 struct stat s;
211 if (stat(full_path, &s) != 0 || s.st_uid != 0 || !S_ISDIR(s.st_mode) || access(full_path, R_OK)) 237 if (stat(full_path, &s) != 0 || s.st_uid != 0 || !S_ISDIR(s.st_mode) || access(full_path, R_OK)
238 || !valid_full_path(full_path))
212 return; 239 return;
213 240
214 char *dir_name = strrchr(full_path, '/'); 241 char *dir_name = strrchr(full_path, '/');
@@ -334,34 +361,20 @@ void fslib_install_list(const char *lib_list) {
334 fs_logger_print(); 361 fs_logger_print();
335} 362}
336 363
337
338
339static void mount_directories(void) { 364static void mount_directories(void) {
340 if (arg_debug || arg_debug_private_lib) 365 fs_remount(RUN_LIB_DIR, MOUNT_READONLY, 1); // should be redundant except for RUN_LIB_DIR itself
341 printf("Mount-bind %s on top of /lib /lib64 /usr/lib\n", RUN_LIB_DIR); 366
342 367 int i = 0;
343 if (is_dir("/lib")) { 368 while (lib_dirs[i]) {
344 if (mount(RUN_LIB_DIR, "/lib", NULL, MS_BIND|MS_REC, NULL) < 0 || 369 if (is_dir(lib_dirs[i])) {
345 mount(NULL, "/lib", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0) 370 if (arg_debug || arg_debug_private_lib)
346 errExit("mount bind"); 371 printf("Mount-bind %s on top of %s\n", RUN_LIB_DIR, lib_dirs[i]);
347 fs_logger2("tmpfs", "/lib"); 372 if (mount(RUN_LIB_DIR, lib_dirs[i], NULL, MS_BIND|MS_REC, NULL) < 0)
348 fs_logger("mount /lib"); 373 errExit("mount bind");
349 } 374 fs_logger2("tmpfs", lib_dirs[i]);
350 375 fs_logger2("mount", lib_dirs[i]);
351 if (is_dir("/lib64")) { 376 }
352 if (mount(RUN_LIB_DIR, "/lib64", NULL, MS_BIND|MS_REC, NULL) < 0 || 377 i++;
353 mount(NULL, "/lib64", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
354 errExit("mount bind");
355 fs_logger2("tmpfs", "/lib64");
356 fs_logger("mount /lib64");
357 }
358
359 if (is_dir("/usr/lib")) {
360 if (mount(RUN_LIB_DIR, "/usr/lib", NULL, MS_BIND|MS_REC, NULL) < 0 ||
361 mount(NULL, "/usr/lib", NULL, MS_BIND|MS_REMOUNT|MS_NOSUID|MS_NODEV|MS_REC, NULL) < 0)
362 errExit("mount bind");
363 fs_logger2("tmpfs", "/usr/lib");
364 fs_logger("mount /usr/lib");
365 } 378 }
366 379
367 // for amd64 only - we'll deal with i386 later 380 // for amd64 only - we'll deal with i386 later
diff --git a/src/firejail/profile.c b/src/firejail/profile.c
index f3266c23e..351b760df 100644
--- a/src/firejail/profile.c
+++ b/src/firejail/profile.c
@@ -157,6 +157,10 @@ static int check_nosound(void) {
157 return arg_nosound != 0; 157 return arg_nosound != 0;
158} 158}
159 159
160static int check_private(void) {
161 return arg_private;
162}
163
160static int check_x11(void) { 164static int check_x11(void) {
161 return (arg_x11_block || arg_x11_xorg || env_get("FIREJAIL_X11")); 165 return (arg_x11_block || arg_x11_xorg || env_get("FIREJAIL_X11"));
162} 166}
@@ -174,6 +178,7 @@ Cond conditionals[] = {
174 {"HAS_NET", check_netoptions}, 178 {"HAS_NET", check_netoptions},
175 {"HAS_NODBUS", check_nodbus}, 179 {"HAS_NODBUS", check_nodbus},
176 {"HAS_NOSOUND", check_nosound}, 180 {"HAS_NOSOUND", check_nosound},
181 {"HAS_PRIVATE", check_private},
177 {"HAS_X11", check_x11}, 182 {"HAS_X11", check_x11},
178 {"BROWSER_DISABLE_U2F", check_disable_u2f}, 183 {"BROWSER_DISABLE_U2F", check_disable_u2f},
179 {"BROWSER_ALLOW_DRM", check_allow_drm}, 184 {"BROWSER_ALLOW_DRM", check_allow_drm},
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c
index b6e0468c6..36a54d6fe 100644
--- a/src/firejail/sandbox.c
+++ b/src/firejail/sandbox.c
@@ -1029,23 +1029,11 @@ int sandbox(void* sandbox_arg) {
1029 fs_dev_disable_video(); 1029 fs_dev_disable_video();
1030 1030
1031 //**************************** 1031 //****************************
1032 // install trace
1033 //****************************
1034 if (need_preload)
1035 fs_trace();
1036
1037 //****************************
1038 // set dns 1032 // set dns
1039 //**************************** 1033 //****************************
1040 fs_resolvconf(); 1034 fs_resolvconf();
1041 1035
1042 //**************************** 1036 //****************************
1043 // fs post-processing
1044 //****************************
1045 fs_logger_print();
1046 fs_logger_change_owner();
1047
1048 //****************************
1049 // start dhcp client 1037 // start dhcp client
1050 //**************************** 1038 //****************************
1051 dhcp_start(); 1039 dhcp_start();
@@ -1094,6 +1082,12 @@ int sandbox(void* sandbox_arg) {
1094 save_umask(); 1082 save_umask();
1095 1083
1096 //**************************** 1084 //****************************
1085 // fs post-processing
1086 //****************************
1087 fs_logger_print();
1088 fs_logger_change_owner();
1089
1090 //****************************
1097 // set security filters 1091 // set security filters
1098 //**************************** 1092 //****************************
1099 // save state of nonewprivs 1093 // save state of nonewprivs
@@ -1150,6 +1144,16 @@ int sandbox(void* sandbox_arg) {
1150 fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); 1144 fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0);
1151 seccomp_debug(); 1145 seccomp_debug();
1152 1146
1147 //****************************
1148 // install trace - still need capabilities
1149 //****************************
1150 if (need_preload)
1151 fs_trace();
1152
1153 //****************************
1154 // continue security filters
1155 //****************************
1156
1153 // set capabilities 1157 // set capabilities
1154 set_caps(); 1158 set_caps();
1155 1159
diff --git a/src/lib/ldd_utils.c b/src/lib/ldd_utils.c
index adde4a9b9..43fee4f21 100644
--- a/src/lib/ldd_utils.c
+++ b/src/lib/ldd_utils.c
@@ -30,6 +30,7 @@ const char * const default_lib_paths[] = {
30 "/lib", 30 "/lib",
31 "/lib64", 31 "/lib64",
32 LIBDIR, 32 LIBDIR,
33 "/usr/local/lib64",
33 "/usr/local/lib", 34 "/usr/local/lib",
34 "/usr/lib/x86_64-linux-gnu/mesa", // libGL.so is sometimes a symlink into this directory 35 "/usr/lib/x86_64-linux-gnu/mesa", // libGL.so is sometimes a symlink into this directory
35 "/usr/lib/x86_64-linux-gnu/mesa-egl", // libGL.so is sometimes a symlink into this directory 36 "/usr/lib/x86_64-linux-gnu/mesa-egl", // libGL.so is sometimes a symlink into this directory
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt
index b25fc9181..b0b390507 100644
--- a/src/man/firejail-profile.txt
+++ b/src/man/firejail-profile.txt
@@ -103,7 +103,7 @@ Example: "?HAS_APPIMAGE: whitelist ${HOME}/special/appimage/dir"
103 103
104This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line. 104This example will load the whitelist profile line only if the \-\-appimage option has been specified on the command line.
105 105
106Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM 106Currently the only conditionals supported this way are HAS_APPIMAGE, HAS_NET, HAS_NODBUS, HAS_NOSOUND, HAS_PRIVATE and HAS_X11. The conditionals BROWSER_DISABLE_U2F and BROWSER_ALLOW_DRM
107can be enabled or disabled globally in Firejail's configuration file. 107can be enabled or disabled globally in Firejail's configuration file.
108 108
109The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines. 109The profile line may be any profile line that you would normally use in a profile \fBexcept\fR for "quiet" and "include" lines.
diff --git a/src/man/firejail.txt b/src/man/firejail.txt
index 68deb85ec..ad11843ce 100644
--- a/src/man/firejail.txt
+++ b/src/man/firejail.txt
@@ -821,6 +821,16 @@ $ firejail \-\-ignore=shell --ignore=seccomp firefox
821$ firejail \-\-ignore="net eth0" firefox 821$ firejail \-\-ignore="net eth0" firefox
822#endif 822#endif
823 823
824.TP
825\fB\-\-\include=file.profile
826Include a profile file before the regular profiles are used.
827.br
828
829.br
830Example:
831.br
832$ firejail --include=/etc/firejail/disable-devel.inc gedit
833
824#ifdef HAVE_NETWORK 834#ifdef HAVE_NETWORK
825.TP 835.TP
826\fB\-\-interface=interface 836\fB\-\-interface=interface
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in
index f58f0d4b9..fd27bb35f 100644
--- a/src/zsh_completion/_firejail.in
+++ b/src/zsh_completion/_firejail.in
@@ -1,5 +1,8 @@
1#compdef firejail 1#compdef firejail
2 2
3# Documentation: man 1 zshcompsys
4# HowTo: https://github.com/zsh-users/zsh-completions/blob/master/zsh-completions-howto.org
5
3_all_firejails() { 6_all_firejails() {
4 local -a _all_firejails_list 7 local -a _all_firejails_list
5 for jail in ${(f)"$(_call_program modules_tag "firejail --list 2> /dev/null | cut -d: -f1")"}; do 8 for jail in ${(f)"$(_call_program modules_tag "firejail --list 2> /dev/null | cut -d: -f1")"}; do
@@ -16,7 +19,7 @@ _all_cpus() {
16} 19}
17 20
18_profiles() { 21_profiles() {
19 print $1/*.profile | sed -E "s;^$1/;;g;s;\.profile$;;g;" 22 print $1/*.profile | sed -E "s;$1/;;g;s;\.profile;;g;"
20} 23}
21_profiles_with_ext() { 24_profiles_with_ext() {
22 print $1/*.profile 25 print $1/*.profile
@@ -26,15 +29,40 @@ _all_profiles() {
26 _values 'profiles' $(_profiles _SYSCONFDIR_/firejail) $(_profiles $HOME/.config/firejail) $(_profiles_with_ext .) 29 _values 'profiles' $(_profiles _SYSCONFDIR_/firejail) $(_profiles $HOME/.config/firejail) $(_profiles_with_ext .)
27} 30}
28 31
32_session_bus_names() {
33 _values names $(busctl --user list --no-legend --activatable | cut -d" " -f1)
34 # Alternatives to hack on for non-systemd systems:
35 # dbus-send --session --dest=org.freedesktop.DBus --type=method_call --print-reply=literal /org/freedesktop/DBus org.freedesktop.DBus.ListNames
36 # ls /usr/share/dbus-1/services | xargs -I FILENAME basename FILENAME .service
37}
38
39_system_bus_names() {
40 _values names $(busctl --system list --no-legend --activatable | cut -d" " -f1)
41}
42
43_caps() {
44 _values -s "," caps $(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}')
45}
46
29_firejail_args=( 47_firejail_args=(
30 '*::arguments:_normal' 48 '*::arguments:_normal'
31 '(--profile)'{--profile=,--profile=}'[use a custom profile]: :_all_profiles' 49
32 '--caps[enable default Linux capabilities filter]' 50 '--appimage[sandbox an AppImage application]'
33 '(--caps.drop)'{--caps.drop=,--caps.drop=}'[drop capabilities: all|cap1,cap2,...]: :->caps_drop' 51 '--build[build a whitelisted profile for the application and print it on stdout]'
34 '(--caps.keep)'{--caps.keep=,--caps.keep=}'[keep capabilities: cap1,cap2,...]: :->caps_keep' 52 '--build=-[build a whitelisted profile for the application and save it]: :_files'
35 '(--caps.print)'{--caps.print=,--caps.print=}'[print the caps filter name|pid]:firejail:_all_firejails' 53 # Ignore that you can do -? too as it's the only short option
36 '--allow-debuggers[allow tools such as strace and gdb inside the sandbox]' 54 '--help[this help screen]'
37 '(--debug)'{--debug,--debug}'[print sandbox debug messages]' 55 '--join=-[join the sandbox name|pid]: :_all_firejails'
56 '--join-filesystem=-[join the mount namespace name|pid]: :_all_firejails'
57 '--list[list all sandboxes]'
58 '(--profile)--noprofile[do not use a security profile]'
59 '(--noprofile)--profile=-[use a custom profile]: :_all_profiles'
60 '--shutdown=-[shutdown the sandbox identified by name|pid]: :_all_firejails'
61 '--top[monitor the most CPU-intensive sandboxes]'
62 '--tree[print a tree of all sandboxed processes]'
63 '--version[print program version and exit]'
64
65 '--debug[print sandbox debug messages]'
38 '--debug-blacklists[debug blacklisting]' 66 '--debug-blacklists[debug blacklisting]'
39 '--debug-caps[print all recognized capabilities]' 67 '--debug-caps[print all recognized capabilities]'
40 '--debug-errnos[print all recognized error numbers]' 68 '--debug-errnos[print all recognized error numbers]'
@@ -43,197 +71,200 @@ _firejail_args=(
43 '--debug-syscalls[print all recognized system calls]' 71 '--debug-syscalls[print all recognized system calls]'
44 '--debug-syscalls32[print all recognized 32 bit system calls]' 72 '--debug-syscalls32[print all recognized 32 bit system calls]'
45 '--debug-whitelists[debug whitelisting]' 73 '--debug-whitelists[debug whitelisting]'
46 # Ignore that you can do -? too as it's the only short option 74
47 '(--help)'{--help,--help}'[this help screen]' 75 '--caps.print=-[print the caps filter name|pid]:firejail:_all_firejails'
76 '--cpu.print=-[print the cpus in use name|pid]: :_all_firejails'
77 '--fs.print=-[print the filesystem log name|pid]: :_all_firejails'
78 '--profile.print=-[print the name of profile file name|pid]: :_all_firejails'
79 '--protocol.print=-[print the protocol filter name|pid]: :_all_firejails'
80 '--seccomp.print=-[print the seccomp filter for the sandbox identified by name|pid]: :_all_firejails'
81
82 '--allow-debuggers[allow tools such as strace and gdb inside the sandbox]'
48 '--allusers[all user home directories are visible inside the sandbox]' 83 '--allusers[all user home directories are visible inside the sandbox]'
49 '--appimage[sandbox an AppImage application]' 84 # Should be _files, a comma and files or files -/
50 '--private[temporary home directory]' 85 '*--bind=-[mount-bind dirname1/filename1 on top of dirname2/filename2]: :(file1,file2 dir1,dir2)'
51 '(--private)'{--private=,--private=}'[use directory as user home]: : _files -/' 86 '*--blacklist=-[blacklist directory or file]: :_files'
52 '--seccomp[enable seccomp filter and apply the default blacklist]' 87 '--caps[enable default Linux capabilities filter]'
53 '(--seccomp=)'{--seccomp=,--seccomp=}'[enable seccomp filter, blacklist the default syscall list and the syscalls specified by the command]:' 88 '--caps.drop=all[drop all capabilities]'
54 '(--seccomp.print)'{--seccomp.print=,--seccomp.print=}'[print the seccomp filter for the sandbox identified by name|pid]: : _all_firejails' 89 '*--caps.drop=-[drop capabilities: all|cap1,cap2,...]: :_caps'
55 '--seccomp.block-secondary[build only the native architecture filters]' 90 '*--caps.keep=-[keep capabilities: cap1,cap2,...]: :_caps'
56 '(--seccomp.drop)'{--seccomp.drop=,--seccomp.drop=}'[enable seccomp filter, and blacklist the syscalls specified by the command]: :' 91 '--cgroup=-[place the sandbox in the specified control group]: :'
57 '(--seccomp.keep)'{--seccomp.keep=,--seccomp.keep=}'[enable seccomp filter, and whitelist the syscalls specified by the command]: :' 92 '--cpu=-[set cpu affinity]: :->cpus'
58 '(--seccomp.32.drop)'{--seccomp.32.drop=,--seccomp.32.drop=}'[enable seccomp filter, and blacklist the 32 bit syscalls specified by the command]: :' 93 "--deterministic-exit-code[always exit with first child's status code]"
59 '(--seccomp.32.keep)'{--seccomp.32.keep=,--seccomp.32.keep=}'[enable seccomp filter, and whitelist the 32 bit syscalls specified by the command]: :' 94 '*--dns=-[set DNS server]: :'
60 '(--seccomp-error-action)'{--seccomp-error-action=,--seccomp-error-action=}'[change error code, kill process or log the attempt]: :(ERRNO kill log)' 95 '*--env=-[set environment variable]: :'
96 '--hostname=-[set sandbox hostname]: :'
97 '--hosts-file=-[use file as /etc/hosts]: :_files'
98 '*--ignore=-[ignore command in profile files]: :'
99 '--ipc-namespace[enable a new IPC namespace]'
100 '--join-or-start=-[join the sandbox or start a new one name|pid]: :_all_firejails'
101 '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]'
102 '--keep-var-tmp[/var/tmp directory is untouched]'
103 '--machine-id[preserve /etc/machine-id]'
61 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' 104 '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]'
62 '*'{--blacklist=,--blacklist=}'[blacklist directory or file]: : _files'
63 '--writable-etc[/etc directory is mounted read-write]'
64 '--writable-run-user[allow access to /run/user/$UID/systemd and /run/user/$UID/gnupg]'
65 '--writable-var[/var directory is mounted read-write]'
66 '--writable-var-log[use the real /var/log directory, not a clone]'
67 '--build[build a whitelisted profile for the application and print it on stdout]'
68 '(--build)'{--build=,--build=}'[build a whitelisted profile for the application and save it]: : _files'
69 '(--fs.print)'{--fs.print=,--fs.print=}'[print the filesystem log name|pid]: : _all_firejails'
70 '(--join)'{--join=,--join=}'[join the sandbox name|pid]: : _all_firejails'
71 '(--join-filesystem)'{--join-filesystem=,--join-filesystem=}'[join the mount namespace name|pid]: : _all_firejails'
72 '(--profile.print)'{--profile.print=,--profile.print=}'[print the name of profile file name|pid]: : _all_firejails'
73 '(--protocol.print)'{--protocol.print=,--protocol.print=}'[print the protocol filter name|pid]: : _all_firejails'
74 '(--shutdown)'{--shutdown=,--shutdown=}'[shutdown the sandbox identified by name|pid]: : _all_firejails'
75 '(--cat)'{--cat=,--cat=}'[print content of file from sandbox container name|pid]: : _all_firejails'
76 '(--cpu.print)'{--cpu.print=,--cpu.print=}'[print the cpus in use name|pid]: : _all_firejails'
77 '--list[list all sandboxes]'
78 '(--dns)'{--dns=,--dns=}'[set DNS server]: :'
79 '*--mkdir=-[create a directory]:' 105 '*--mkdir=-[create a directory]:'
80 '*--mkfile=-[create a file]:' 106 '*--mkfile=-[create a file]:'
81 '(--protocol)'{--protocol=,--protocol=}'[enable protocol filter]: :' 107 '--name=-[set sandbox name]: :'
82 '(--join-or-start)'{--join-or-start=,--join-or-start=}'[join the sandbox or start a new one name|pid]: : _all_firejails' 108 '--net=none[enable a new, unconnected network namespace]'
83 '(--hosts-file)'{--hosts-file=,--hosts-file=}'[use file as /etc/hosts]: : _files' 109 # Sample values as I don't think
84 '--shell=none[run the program directly without a user shell]' 110 # many would enjoy getting a list from -20..20
85 '(--shell)'{--shell=,--shell=}'[set default user shell]: : _files -g "*(*)"' 111 '--nice=-[set nice value]: :(1 10 15 20)'
86 '(--output)'{--output=,--output=}'[stdout logging and log rotation]: : _files'
87 '(--output-stderr)'{--output-stderr=,--output-stderr=}'[stdout and stderr logging and log rotation]: : _files'
88 '--no3d[disable 3D hardware acceleration]' 112 '--no3d[disable 3D hardware acceleration]'
113 '--noautopulse[disable automatic ~/.config/pulse init]'
114 '--noblacklist=-[disable blacklist for file or directory]: :_files'
115 '--nodbus[disable D-Bus access]'
89 '--nodvd[disable DVD and audio CD devices]' 116 '--nodvd[disable DVD and audio CD devices]'
117 '*--noexec=-[remount the file or directory noexec nosuid and nodev]: :_files'
90 '--nogroups[disable supplementary groups]' 118 '--nogroups[disable supplementary groups]'
91 '--nonewprivs[sets the NO_NEW_PRIVS prctl]' 119 '--nonewprivs[sets the NO_NEW_PRIVS prctl]'
92 '--noprofile[do not use a security profile]' 120 '--nosound[disable sound system]'
93 '(--noexec)'{--noexec=,--noexec=}'[remount the file or directory noexec nosuid and nodev]: : _files' 121 '--nou2f[disable U2F devices]'
94 '--ipc-namespace[enable a new IPC namespace]' 122 '--novideo[disable video devices]'
95 '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]' 123 '--private[temporary home directory]'
96 '--keep-var-tmp[/var/tmp directory is untouched]' 124 '--private=-[use directory as user home]: :_files -/'
97 '--top[monitor the most CPU-intensive sandboxes]' 125 '--private-bin=-[build a new /bin in a temporary filesystem, and copy the programs in the list]: :_files -W /usr/bin'
98 '--trace[trace open, access and connect system calls]' 126 '--private-cwd[do not inherit working directory inside jail]'
99 '--tracelog[add a syslog message for every access to files or directories blacklisted by the security profile]' 127 '--private-cwd=-[set working directory inside jail]: :_files -/'
100 '--tree[print a tree of all sandboxed processes]'
101 '(--cpu)'{--cpu=,--cpu=}'[set cpu affinity]: :->cpus'
102 '--private-dev[create a new /dev directory with a small number of common device files]' 128 '--private-dev[create a new /dev directory with a small number of common device files]'
129 '(--writable-etc)--private-etc=-[build a new /etc in a temporary filesystem, and copy the files and directories in the list]: :_files -W /etc'
130 '--private-opt=-[build a new /opt in a temporary filesystem]: :_files -W /opt'
131 '--private-srv=-[build a new /srv in a temporary filesystem]: :_files -W /srv'
103 '--private-tmp[mount a tmpfs on top of /tmp directory]' 132 '--private-tmp[mount a tmpfs on top of /tmp directory]'
104 '--private-cwd[do not inherit working directory inside jail]' 133 '*--protocol=-[enable protocol filter]: :_values -s , protocols unix inet inet6 netlink packet bluetooth'
105 '(--private-cwd)'{--private-cwd=,--private-cwd=}'[set working directory inside jail]: : _files -/'
106 '*'{--read-only=,--read-only=}'[set directory or file read-only]: : _files'
107 '*'{--read-write=,--read-write=}'[set directory or file read-write]: : _files'
108 '(--tmpfs)'{--tmpfs=,--tmpfs=}'[mount a tmpfs filesystem on directory dirname]: : _files -/'
109 '(--private-etc)'{--private-etc=,--private-etc=}'[build a new /etc in a temporary filesystem, and copy the files and directories in the list]: : _files'
110 "--deterministic-exit-code[always exit with first child's status code]"
111 '--machine-id[preserve /etc/machine-id]'
112 # Sample values as I don't think
113 # many would enjoy getting a list from -20..20
114 '(--nice)'{--nice=,--nice=}'[set nice value]: :(1 10 15 20)'
115 # Should be _files, a comma and files or files -/
116 '*'{--bind=,--bind=}'[mount-bind dirname1/filename1 on top of dirname2/filename2]: :(file1,file2 dir1,dir2)'
117 '(--cgroup)'{--cgroup=,--cgroup=}'[place the sandbox in the specified control group]: :'
118 '*'{--env=,--env=}'[set environment variable]: :'
119 '(--hostname)'{--hostname=,--hostname=}'[set sandbox hostname]: :'
120 '(--ignore)'{--ignore=,--ignore=}'[ignore command in profile files]: :'
121 '(--name)'{--name=,--name=}'[set sandbox name]: :'
122 '(--rlimit-as)'{--rlimit-as=,--rlimit-as=}"[set the maximum size of the process's virtual memory (address space) in bytes]: :"
123 '(--rlimit-cpu)'{--rlimit-cpu=,--rlimit-cpu=}'[set the maximum CPU time in seconds]: :'
124 '(--rlimit-fsize)'{--rlimit-fsize=,--rlimit-fsize=}'[set the maximum file size that can be created by a process]: :'
125 '(--rlimit-nofile)'{--rlimit-nofile=,--rlimit-nofile=}'[set the maximum number of files that can be opened by a process]: :'
126 '(--rlimit-nproc)'{--rlimit-nproc=,--rlimit-nproc=}'[set the maximum number of processes that can be created for the real user ID of the calling process]: :'
127 '(--rlimit-sigpending)'{--rlimit-sigpending=,--rlimit-sigpending=}'[set the maximum number of pending signals for a process]: :'
128 '*'{--rmenv=,--rmenv=}'[remove environment variable in the new sandbox]: :'
129 '(--timeout)'{--timeout=,--timeout=}'[kill the sandbox automatically after the time has elapsed]: :(hh\:mm\:ss)'
130 "--quiet[turn off Firejail's output.]" 134 "--quiet[turn off Firejail's output.]"
131 '--version[print program version and exit]' 135 '*--read-only=-[set directory or file read-only]: :_files'
136 '*--read-write=-[set directory or file read-write]: :_files'
137 "--rlimit-as=-[set the maximum size of the process's virtual memory (address space) in bytes]: :"
138 '--rlimit-cpu=-[set the maximum CPU time in seconds]: :'
139 '--rlimit-fsize=-[set the maximum file size that can be created by a process]: :'
140 '--rlimit-nofile=-[set the maximum number of files that can be opened by a process]: :'
141 '--rlimit-nproc=-[set the maximum number of processes that can be created for the real user ID of the calling process]: :'
142 '--rlimit-sigpending=-[set the maximum number of pending signals for a process]: :'
143 '*--rmenv=-[remove environment variable in the new sandbox]: :_values environment-variables $(env | cut -d= -f1)'
144 '--seccomp[enable seccomp filter and apply the default blacklist]: :'
145 '--seccomp=-[enable seccomp filter, blacklist the default syscall list and the syscalls specified by the command]: :->seccomp'
146 '--seccomp.block-secondary[build only the native architecture filters]'
147 '*--seccomp.drop=-[enable seccomp filter, and blacklist the syscalls specified by the command]: :->seccomp'
148 '*--seccomp.keep=-[enable seccomp filter, and whitelist the syscalls specified by the command]: :->seccomp'
149 '*--seccomp.32.drop=-[enable seccomp filter, and blacklist the 32 bit syscalls specified by the command]: :'
150 '*--seccomp.32.keep=-[enable seccomp filter, and whitelist the 32 bit syscalls specified by the command]: :'
151 # FIXME: Add errnos
152 '--seccomp-error-action=-[change error code, kill process or log the attempt]: :(kill log)'
153 '--shell=none[run the program directly without a user shell]'
154 '--shell=-[set default user shell]: :_values $(cat /etc/shells)'
155 '--timeout=-[kill the sandbox automatically after the time has elapsed]: :'
156 #'(--tracelog)--trace[trace open, access and connect system calls]'
157 '(--tracelog)--trace=-[trace open, access and connect system calls]: :_files'
158 '(--trace)--tracelog[add a syslog message for every access to files or directories blacklisted by the security profile]'
159 '(--private-etc)--writable-etc[/etc directory is mounted read-write]'
160 '--writable-run-user[allow access to /run/user/$UID/systemd and /run/user/$UID/gnupg]'
161 '--writable-var[/var directory is mounted read-write]'
162 '--writable-var-log[use the real /var/log directory, not a clone]'
163
132#ifdef HAVE_APPARMOR 164#ifdef HAVE_APPARMOR
133 '--apparmor[enable AppArmor confinement]' 165 '--apparmor[enable AppArmor confinement]'
134 '(--apparmor.print=)'{--apparmor.print=,--apparmor.print=}'[print apparmor status name|pid]:firejail:_all_firejails' 166 '--apparmor.print=-[print apparmor status name|pid]:firejail:_all_firejails'
135#endif 167#endif
168
136#ifdef HAVE_CHROOT 169#ifdef HAVE_CHROOT
137 '(--chroot)'{--chroot=,--chroot=}'[chroot into directory]: : _files -/' 170 '(--noroot --overlay --overlay-named --overlay-tmpfs)--chroot=-[chroot into directory]: :_files -/'
138#endif 171#endif
172
173#ifdef HAVE_DBUSPROXY
174 # FIXME: _xx_bus_names is actually wrong for --dbus-*.{broadcast,call}.
175 # We can steal some function from https://github.com/systemd/systemd/blob/main/shell-completion/zsh/_busctl
176 '--dbus-log=-[set DBus log file location]: :_files'
177 '--dbus-system=-[set system DBus access policy]: :(filter none)'
178 '--dbus-system.broadcast=-[allow signals on the system DBus according to rule]: :_system_bus_names'
179 '--dbus-system.call=-[allow calls on the system DBus according to rule]: :_system_bus_names'
180 '--dbus-system.own=-[allow ownership of name on the system DBus]: :_system_bus_names'
181 '--dbus-system.see=-[allow seeing name on the system DBus]: :_system_bus_names'
182 '--dbus-system.talk=-[allow talking to name on the system DBus]: :_system_bus_names'
183 '--dbus-user=-[set session DBus access policy or none]: :(filter none)'
184 '--dbus-user.broadcast=-[allow signals on the session DBus according to rule]: :_session_bus_names'
185 '--dbus-user.call=-[allow calls on the session DBus according to rule]: :_session_bus_names'
186 '--dbus-user.own=-[allow ownership of name on the session DBus]: :_session_bus_names'
187 '--dbus-user.see=-[allow seeing name on the session DBus]: :_session_bus_names'
188 '--dbus-user.talk=-[allow talking to name on the session DBus]: :_session_bus_names'
189#endif
190
139#ifdef HAVE_FILE_TRANSFER 191#ifdef HAVE_FILE_TRANSFER
140 '(--get)'{--get=,--get=}'[get a file from sandbox container name|pid]: : _all_firejails' 192 '--cat=-[print content of file from sandbox container name|pid]: :_all_firejails'
193 '--get=-[get a file from sandbox container name|pid]: :_all_firejails'
141 # --put=name|pid src-filename dest-filename - put a file in sandbox container. 194 # --put=name|pid src-filename dest-filename - put a file in sandbox container.
142 '(--put)'{--put=,--put=}'[put a file in sandbox container]: :' 195 '--put=-[put a file in sandbox container]: :'
143 '(--ls)'{--ls=,--ls=}'[list files in sandbox container name|pid]: : _all_firejails' 196 '--ls=-[list files in sandbox container name|pid]: :_all_firejails'
197#endif
198
199#ifdef HAVE_FIRETUNNEL
200 '--tunnel=-[connect the sandbox to a tunnel created by firetunnel utility]: :'
144#endif 201#endif
202
145#ifdef HAVE_NETWORK 203#ifdef HAVE_NETWORK
146 # '--net=none[enable a new, unconnected network namespace]' 204 '--bandwidth=-[set bandwidth limits name|pid]: :_all_firejails'
147 '(--net)'{--net=,--net=}'[enable network namespaces and connect to this bridge or Ethernet interface (or none to disable)]: :->net_or_none' 205 '--defaultgw=[configure default gateway]: :'
148 '(--net.print)'{--net.print=,--net.print=}'[print network interface configuration name|pid]: : _all_firejails' 206 '--dns.print=-[print DNS configuration name|pid]: :_all_firejails'
149 '(--netfilter.print)'{--netfilter.print=,--netfilter.print=}'[print the firewall name|pid]: : _all_firejails' 207 '--join-network=-[join the network namespace name|pid]: :_all_firejails'
150 '(--netfilter6.print)'{--netfilter6.print=,--netfilter6.print=}'[print the IPv6 firewall name|pid]: : _all_firejails' 208 '--mac=-[set interface MAC address]: :(xx\:xx\:xx\:xx\:xx\:xx)'
209 '--mtu=-[set interface MTU]: :'
210 '--net=-[enable network namespaces and connect to this bridge or Ethernet interface (or none to disable)]: :->net_or_none'
211 '--net.print=-[print network interface configuration name|pid]: :_all_firejails'
212 '--netfilter=-[enable firewall]: :'
213 '--netfilter.print=-[print the firewall name|pid]: :_all_firejails'
214 '--netfilter6=-[enable IPv6 firewall]: :'
215 '--netfilter6.print=-[print the IPv6 firewall name|pid]: :_all_firejails'
216 '--netmask=-[define a network mask when dealing with unconfigured parrent interfaces]: :'
217 '--netns=-[Run the program in a named, persistent network namespace]: :'
151 '--netstats[monitor network statistics]' 218 '--netstats[monitor network statistics]'
152 '(--netmask)'{--netmask=,--netmask=}'[define a network mask when dealing with unconfigured parrent interfaces]: :' 219 '--interface=-[move interface in sandbox]: :'
153 '(--netns)'{--netns=,--netns=}'[Run the program in a named, persistent network namespace]: :' 220 '--ip=-[set interface IP address none|dhcp|ADDRESS]: :(none dhcp)'
154 '(--netfilter)'{--netfilter=,--netfilter=}'[enable firewall]: :' 221 '--ip6=-[set interface IPv6 address or use dhcp via dhclient]: :(dhcp)'
155 '(--netfilter6)'{--netfilter6=,--netfilter6=}'[enable IPv6 firewall]: :' 222 '--iprange=-[configure an IP address in this range]: :'
156 '(--veth-name)'{--veth-name=,--veth-name=}'[use this name for the interface connected to the bridge]: :'
157 '(--join-network)'{--join-network=,--join-network=}'[join the network namespace name|pid]: : _all_firejails'
158 '(--defaultgw)'{--defaultgw=,--defaultgw=}'[configure default gateway]: :'
159 '(--ip)'{--ip=,--ip=}'[set interface IP address none|dhcp|ADDRESS]: :(none dhcp)'
160 '(--dns.print)'{--dns.print=,--dns.print=}'[print DNS configuration name|pid]: : _all_firejails'
161 '(--interface)'{--interface=,--interface=}'[move interface in sandbox]: :'
162 '(--ip6)'{--ip6=,--ip6=}'[set interface IPv6 address or use dhcp via dhclient]: :(dhcp)'
163 '(--iprange)'{--iprange=,--iprange=}'[configure an IP address in this range]: :'
164 '(--mac)'{--mac=,--mac=}'[set interface MAC address]: :(xx\:xx\:xx\:xx\:xx\:xx)'
165 '(--mtu)'{--mtu=,--mtu=}'[set interface MTU]: :'
166 '--scan[ARP-scan all the networks from inside a network namespace]' 223 '--scan[ARP-scan all the networks from inside a network namespace]'
167 '(--bandwidth)'{--bandwidth=,--bandwidth=}'[set bandwidth limits name|pid]: : _all_firejails' 224 '--veth-name=-[use this name for the interface connected to the bridge]: :'
168#endif
169#ifdef HAVE_X11
170 '--x11[enable X11 sandboxing. The software checks first if Xpra is installed, then it checks if Xephyr is installed. If all fails, it will attempt to use X11 security extension]'
171 '(--x11)'{--x11=,--x11=}'[disable or enable specific X11 server]: :(none xephyr xorg xpra xvfb)'
172 '(--xephyr-screen)'{--xephyr-screen=,--xephyr-screen=}'[set screen size for --x11=xephyr]: :(WIDTHxHEIGHT)'
173#endif 225#endif
174#ifdef HAVE_USERNS 226
175 '--noroot[install a user namespace with only the current user]' 227#ifdef HAVE_OUTPUT
228 '--output=-[stdout logging and log rotation]: :_files'
229 '--output-stderr=-[stdout and stderr logging and log rotation]: :_files'
176#endif 230#endif
177 '--nosound[disable sound system]' 231
178 '--noautopulse[disable automatic ~/.config/pulse init]'
179 '--novideo[disable video devices]'
180 '--nou2f[disable U2F devices]'
181#ifdef HAVE_OVERLAYFS 232#ifdef HAVE_OVERLAYFS
182 '--overlay[mount a filesystem overlay on top of the current filesystem]' 233 '(--chroot --noroot)--overlay[mount a filesystem overlay on top of the current filesystem]'
183 '(--overlay-named)'{--overlay-named=,--overlay-named=}'[mount a filesystem overlay on top of the current filesystem, and store it in name directory]: : _files -/'
184 '--overlay-tmpfs[mount a temporary filesystem overlay on top of the current filesystem]'
185 '--overlay-clean[clean all overlays stored in $HOME/.firejail directory]' 234 '--overlay-clean[clean all overlays stored in $HOME/.firejail directory]'
235 '(--chroot --noroot)--overlay-named=-[mount a filesystem overlay on top of the current filesystem, and store it in name directory]: :_files -/'
236 '(--chroot --noroot)--overlay-tmpfs[mount a temporary filesystem overlay on top of the current filesystem]'
186#endif 237#endif
187#ifdef HAVE_WHITELIST 238
188 '(--nowhitelist)'{--nowhitelist=,--nowhitelist=}'[disable whitelist for file or directory]: : _files'
189 '*'{--whitelist=,--whitelist=}'[whitelist directory or file]: : _files'
190#endif
191 '(--noblacklist)'{--noblacklist=,--noblacklist=}'[disable blacklist for file or directory]: : _files'
192#ifdef HAVE_DBUSPROXY
193 '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy or none]: :'
194 '(--dbus-system.broadcast)'{--dbus-system.broadcast=,--dbus-system.broadcast=}'[allow signals on the system DBus according to rule]: :'
195 '(--dbus-system.call)'{--dbus-system.call=,--dbus-system.call=}'[allow calls on the system DBus according to rule]: :'
196 '(--dbus-system.own)'{--dbus-system.own=,--dbus-system.own=}'[allow ownership of name on the system DBus]: :'
197 '(--dbus-system.see)'{--dbus-system.see=,--dbus-system.see=}'[allow seeing name on the system DBus]: :'
198 '(--dbus-system.talk)'{--dbus-system.talk=,--dbus-system.talk=}'[allow talking to name on the system DBus]: :'
199 '(--dbus-user)'{--dbus-user=,--dbus-user=}'[set session DBus access policy or none]: :'
200 '(--dbus-user.broadcast)'{--dbus-user.broadcast=,--dbus-user.broadcast=}'[allow signals on the session DBus according to rule]: :'
201 '(--dbus-user.call)'{--dbus-user.call=,--dbus-user.call=}'[allow calls on the session DBus according to rule]: :'
202 '(--dbus-user.see)'{--dbus-user.see=,--dbus-user.see=}'[allow seeing name on the session DBus]: :'
203 '(--dbus-user.talk)'{--dbus-user.talk=,--dbus-user.talk=}'[allow talking to name on the session DBus]: :'
204 '(--dbus-log)'{--dbus-log=,--dbus-log=}'[set DBus log file location]: : _files'
205 '(--dbus-system)'{--dbus-system=,--dbus-system=}'[set system DBus access policy]: :(filter none)'
206 '--dbus-user.log[turn on logging for the user DBus]'
207 '(--dbus-user.own)'{--dbus-user.own=,--dbus-user.own=}'[allow ownership of name on the session DBus]: :'
208 '--dbus-system.log[turn on logging for the system DBus]'
209 '--nodbus[disable D-Bus access]'
210#endif
211#ifdef HAVE_PRIVATE_HOME 239#ifdef HAVE_PRIVATE_HOME
212 '(--private-home)'{--private-home=,--private-home=}'[build a new user home in a temporary filesystem, and copy the files and directories in the list in the new home]: :' 240 '--private-home=-[build a new user home in a temporary filesystem, and copy the files and directories in the list in the new home]: :_files'
241#endif
242
243#ifdef HAVE_USERNS
244 '(--chroot --overlay --overlay-named --overlay-tmpfs)--noroot[install a user namespace with only the current user]'
213#endif 245#endif
214 '(--private-bin)'{--private-bin=,--private-bin=}'[build a new /bin in a temporary filesystem, and copy the programs in the list]: :' 246
215 '(--private-opt)'{--private-opt=,--private-opt=}'[build a new /opt in a temporary filesystem]: :'
216 '(--private-srv)'{--private-srv=,--private-srv=}'[build a new /srv in a temporary filesystem]: :'
217#ifdef HAVE_USERTMPFS 247#ifdef HAVE_USERTMPFS
218 '--private-cache[temporary ~/.cache directory]' 248 '--private-cache[temporary ~/.cache directory]'
249 '*--tmpfs=-[mount a tmpfs filesystem on directory dirname]: :_files -/'
219#endif 250#endif
220#ifdef HAVE_FIRETUNNEL 251
221 '(--tunnel)'{--tunnel=,--tunnel=}'[connect the sandbox to a tunnel created by firetunnel utility]: :' 252#ifdef HAVE_WHITELIST
253 '*--nowhitelist=-[disable whitelist for file or directory]: :_files'
254 '*--whitelist=-[whitelist directory or file]: :_files'
222#endif 255#endif
223 ) 256
257#ifdef HAVE_X11
258 '--x11[enable X11 sandboxing. The software checks first if Xpra is installed, then it checks if Xephyr is installed. If all fails, it will attempt to use X11 security extension]'
259 '--x11=-[disable or enable specific X11 server]: :(none xephyr xorg xpra xvfb)'
260 '--xephyr-screen=-[set screen size for --x11=xephyr]: :(WIDTHxHEIGHT)'
261#endif
262)
224 263
225 264
226_firejail() { 265_firejail() {
227 _arguments -S $_firejail_args 266 _arguments -S $_firejail_args
228 case "$state" in 267 case "$state" in
229 caps_drop)
230 local caps_and_all=(all $(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}'))
231 _values -s "," 'caps_drop' $caps_and_all
232 ;;
233 caps_keep)
234 local caps=($(firejail --debug-caps | awk '/[0-9]+\s*- /{print $3}'))
235 _values -s "," 'caps_keep' $caps
236 ;;
237 cpus) 268 cpus)
238 _values -s "," 'cpus' $(_all_cpus) 269 _values -s "," 'cpus' $(_all_cpus)
239 ;; 270 ;;
@@ -242,5 +273,11 @@ _firejail() {
242 local net_and_none=(none $netdevs) 273 local net_and_none=(none $netdevs)
243 _values 'net' $net_and_none 274 _values 'net' $net_and_none
244 ;; 275 ;;
276 seccomp)
277 # TODO: syscall groups
278 _values -s "," 'syscalls' $(firejail --debug-syscalls | cut -d" " -f2)
279 ;;
245 esac 280 esac
246} 281}
282
283# vim: ft=zsh sw=4 ts=4 et sts=4 ai