diff options
-rw-r--r-- | contrib/vim/syntax/firejail.vim | 6 | ||||
-rw-r--r-- | etc/profile-a-l/default.profile | 1 | ||||
-rw-r--r-- | etc/profile-m-z/server.profile | 1 | ||||
-rw-r--r-- | etc/templates/profile.template | 1 | ||||
-rw-r--r-- | src/firejail/firejail.h | 2 | ||||
-rw-r--r-- | src/firejail/main.c | 14 | ||||
-rw-r--r-- | src/firejail/preproc.c | 10 | ||||
-rw-r--r-- | src/firejail/profile.c | 27 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 10 | ||||
-rw-r--r-- | src/firejail/seccomp.c | 31 | ||||
-rw-r--r-- | src/firejail/usage.c | 3 | ||||
-rw-r--r-- | src/fseccomp/fseccomp.h | 4 | ||||
-rw-r--r-- | src/fseccomp/main.c | 6 | ||||
-rw-r--r-- | src/fseccomp/namespaces.c | 197 | ||||
-rw-r--r-- | src/fseccomp/protocol.c | 9 | ||||
-rw-r--r-- | src/include/rundefs.h | 2 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 6 | ||||
-rw-r--r-- | src/man/firejail.txt | 24 | ||||
-rw-r--r-- | src/zsh_completion/_firejail.in | 4 |
19 files changed, 350 insertions, 8 deletions
diff --git a/contrib/vim/syntax/firejail.vim b/contrib/vim/syntax/firejail.vim index 51e9cfdad..9099a0808 100644 --- a/contrib/vim/syntax/firejail.vim +++ b/contrib/vim/syntax/firejail.vim | |||
@@ -17,6 +17,9 @@ syn match fjComment "#.*$" contains=fjTodo | |||
17 | syn keyword fjCapability audit_control audit_read audit_write block_suspend chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mac_admin mac_override mknod net_admin net_bind_service net_broadcast net_raw setgid setfcap setpcap setuid sys_admin sys_boot sys_chroot sys_module sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config syslog wake_alarm nextgroup=fjCapabilityList contained | 17 | syn keyword fjCapability audit_control audit_read audit_write block_suspend chown dac_override dac_read_search fowner fsetid ipc_lock ipc_owner kill lease linux_immutable mac_admin mac_override mknod net_admin net_bind_service net_broadcast net_raw setgid setfcap setpcap setuid sys_admin sys_boot sys_chroot sys_module sys_nice sys_pacct sys_ptrace sys_rawio sys_resource sys_time sys_tty_config syslog wake_alarm nextgroup=fjCapabilityList contained |
18 | syn match fjCapabilityList /,/ nextgroup=fjCapability contained | 18 | syn match fjCapabilityList /,/ nextgroup=fjCapability contained |
19 | 19 | ||
20 | syn keyword fjNamespaces cgroup ipc net mnt pid time user uts nextgroup=fjNamespacesList contained | ||
21 | syn match fjNamespacesList /,/ nextgroup=fjNamespaces contained | ||
22 | |||
20 | syn keyword fjProtocol unix inet inet6 netlink packet nextgroup=fjProtocolList contained | 23 | syn keyword fjProtocol unix inet inet6 netlink packet nextgroup=fjProtocolList contained |
21 | syn match fjProtocolList /,/ nextgroup=fjProtocol contained | 24 | syn match fjProtocolList /,/ nextgroup=fjProtocol contained |
22 | 25 | ||
@@ -48,7 +51,7 @@ syn keyword fjFilter filter contained | |||
48 | syn match fjVar /\v\$\{(CFG|DESKTOP|DOCUMENTS|DOWNLOADS|HOME|MUSIC|PATH|PICTURES|RUNUSER|VIDEOS)}/ | 51 | syn match fjVar /\v\$\{(CFG|DESKTOP|DOCUMENTS|DOWNLOADS|HOME|MUSIC|PATH|PICTURES|RUNUSER|VIDEOS)}/ |
49 | 52 | ||
50 | " Commands grabbed from: src/firejail/profile.c | 53 | " Commands grabbed from: src/firejail/profile.c |
51 | " Generate list with: { rg -o 'strn?cmp\(ptr, "([^"]+) "' -r '$1' src/firejail/profile.c; echo private-lib; } | grep -vEx '(include|ignore|caps\.drop|caps\.keep|protocol|seccomp|seccomp\.drop|seccomp\.keep|env|rmenv|net|ip)' | sort -u | tr $'\n' '|' # private-lib is special-cased in the code and doesn't match the regex; grep-ed patterns are handled later with 'syn match nextgroup=' directives (except for include which is special-cased as a fjCommandNoCond keyword) | 54 | " Generate list with: { rg -o 'strn?cmp\(ptr, "([^"]+) "' -r '$1' src/firejail/profile.c; echo private-lib; } | grep -vEx '(include|ignore|caps\.drop|caps\.keep|protocol|restrict-namespaces|seccomp|seccomp\.drop|seccomp\.keep|env|rmenv|net|ip)' | sort -u | tr $'\n' '|' # private-lib is special-cased in the code and doesn't match the regex; grep-ed patterns are handled later with 'syn match nextgroup=' directives (except for include which is special-cased as a fjCommandNoCond keyword) |
52 | syn match fjCommand /\v(bind|blacklist|blacklist-nolog|cpu|defaultgw|dns|hostname|hosts-file|ip6|iprange|join-or-start|mac|mkdir|mkfile|mtu|name|netfilter|netfilter6|netmask|nice|noblacklist|noexec|nowhitelist|overlay-named|private|private-bin|private-cwd|private-etc|private-home|private-lib|private-opt|private-srv|read-only|read-write|rlimit-as|rlimit-cpu|rlimit-fsize|rlimit-nofile|rlimit-nproc|rlimit-sigpending|timeout|tmpfs|veth-name|whitelist|xephyr-screen) / skipwhite contained | 55 | syn match fjCommand /\v(bind|blacklist|blacklist-nolog|cpu|defaultgw|dns|hostname|hosts-file|ip6|iprange|join-or-start|mac|mkdir|mkfile|mtu|name|netfilter|netfilter6|netmask|nice|noblacklist|noexec|nowhitelist|overlay-named|private|private-bin|private-cwd|private-etc|private-home|private-lib|private-opt|private-srv|read-only|read-write|rlimit-as|rlimit-cpu|rlimit-fsize|rlimit-nofile|rlimit-nproc|rlimit-sigpending|timeout|tmpfs|veth-name|whitelist|xephyr-screen) / skipwhite contained |
53 | " Generate list with: rg -o 'strn?cmp\(ptr, "([^ "]*[^ ])"' -r '$1' src/firejail/profile.c | grep -vEx '(include|rlimit|quiet)' | sed -e 's/\./\\./' | sort -u | tr $'\n' '|' # include/rlimit are false positives, quiet is special-cased below | 56 | " Generate list with: rg -o 'strn?cmp\(ptr, "([^ "]*[^ ])"' -r '$1' src/firejail/profile.c | grep -vEx '(include|rlimit|quiet)' | sed -e 's/\./\\./' | sort -u | tr $'\n' '|' # include/rlimit are false positives, quiet is special-cased below |
54 | syn match fjCommand /\v(allow-debuggers|allusers|apparmor|caps|deterministic-exit-code|deterministic-shutdown|disable-mnt|ipc-namespace|keep-config-pulse|keep-dev-shm|keep-fd|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noprinters|noroot|nosound|notv|nou2f|novideo|overlay|overlay-tmpfs|private|private-cache|private-cwd|private-dev|private-lib|private-tmp|seccomp|seccomp\.32|seccomp\.block-secondary|tracelog|writable-etc|writable-run-user|writable-var|writable-var-log|x11)$/ contained | 57 | syn match fjCommand /\v(allow-debuggers|allusers|apparmor|caps|deterministic-exit-code|deterministic-shutdown|disable-mnt|ipc-namespace|keep-config-pulse|keep-dev-shm|keep-fd|keep-var-tmp|machine-id|memory-deny-write-execute|netfilter|no3d|noautopulse|nodbus|nodvd|nogroups|noinput|nonewprivs|noprinters|noroot|nosound|notv|nou2f|novideo|overlay|overlay-tmpfs|private|private-cache|private-cwd|private-dev|private-lib|private-tmp|seccomp|seccomp\.32|seccomp\.block-secondary|tracelog|writable-etc|writable-run-user|writable-var|writable-var-log|x11)$/ contained |
@@ -56,6 +59,7 @@ syn match fjCommand /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite cont | |||
56 | syn match fjCommand /caps\.drop / nextgroup=fjCapability,fjAll skipwhite contained | 59 | syn match fjCommand /caps\.drop / nextgroup=fjCapability,fjAll skipwhite contained |
57 | syn match fjCommand /caps\.keep / nextgroup=fjCapability skipwhite contained | 60 | syn match fjCommand /caps\.keep / nextgroup=fjCapability skipwhite contained |
58 | syn match fjCommand /protocol / nextgroup=fjProtocol skipwhite contained | 61 | syn match fjCommand /protocol / nextgroup=fjProtocol skipwhite contained |
62 | syn match fjCommand /restrict-namespaces / nextgroup=fjNamespaces skipwhite contained | ||
59 | syn match fjCommand /\vseccomp(\.32)?(\.drop|\.keep)? / nextgroup=fjSyscall skipwhite contained | 63 | syn match fjCommand /\vseccomp(\.32)?(\.drop|\.keep)? / nextgroup=fjSyscall skipwhite contained |
60 | syn match fjCommand /x11 / nextgroup=fjX11Sandbox skipwhite contained | 64 | syn match fjCommand /x11 / nextgroup=fjX11Sandbox skipwhite contained |
61 | syn match fjCommand /env / nextgroup=fjEnvVar skipwhite contained | 65 | syn match fjCommand /env / nextgroup=fjEnvVar skipwhite contained |
diff --git a/etc/profile-a-l/default.profile b/etc/profile-a-l/default.profile index dac842bb6..397a89bee 100644 --- a/etc/profile-a-l/default.profile +++ b/etc/profile-a-l/default.profile | |||
@@ -60,3 +60,4 @@ seccomp | |||
60 | # deterministic-shutdown | 60 | # deterministic-shutdown |
61 | # memory-deny-write-execute | 61 | # memory-deny-write-execute |
62 | # read-only ${HOME} | 62 | # read-only ${HOME} |
63 | # restrict-namespaces | ||
diff --git a/etc/profile-m-z/server.profile b/etc/profile-m-z/server.profile index fd7ffb38d..8d8a1dac6 100644 --- a/etc/profile-m-z/server.profile +++ b/etc/profile-m-z/server.profile | |||
@@ -90,6 +90,7 @@ dbus-user none | |||
90 | # deterministic-shutdown | 90 | # deterministic-shutdown |
91 | # memory-deny-write-execute | 91 | # memory-deny-write-execute |
92 | # read-only ${HOME} | 92 | # read-only ${HOME} |
93 | # restrict-namespaces | ||
93 | # writable-run-user | 94 | # writable-run-user |
94 | # writable-var | 95 | # writable-var |
95 | # writable-var-log | 96 | # writable-var-log |
diff --git a/etc/templates/profile.template b/etc/templates/profile.template index 28339765f..59083f660 100644 --- a/etc/templates/profile.template +++ b/etc/templates/profile.template | |||
@@ -228,3 +228,4 @@ include globals.local | |||
228 | ##noexec PATH | 228 | ##noexec PATH |
229 | ##read-only ${HOME} | 229 | ##read-only ${HOME} |
230 | ##read-write ${HOME} | 230 | ##read-write ${HOME} |
231 | #restrict-namespaces | ||
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 96e3f735e..167b6a843 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -198,6 +198,7 @@ typedef struct config_t { | |||
198 | char *seccomp_list_drop, *seccomp_list_drop32; // seccomp drop list | 198 | char *seccomp_list_drop, *seccomp_list_drop32; // seccomp drop list |
199 | char *seccomp_list_keep, *seccomp_list_keep32; // seccomp keep list | 199 | char *seccomp_list_keep, *seccomp_list_keep32; // seccomp keep list |
200 | char *protocol; // protocol list | 200 | char *protocol; // protocol list |
201 | char *restrict_namespaces; // namespaces list | ||
201 | char *seccomp_error_action; // error action: kill, log or errno | 202 | char *seccomp_error_action; // error action: kill, log or errno |
202 | 203 | ||
203 | // rlimits | 204 | // rlimits |
@@ -632,6 +633,7 @@ int seccomp_load(const char *fname); | |||
632 | int seccomp_filter_drop(bool native); | 633 | int seccomp_filter_drop(bool native); |
633 | int seccomp_filter_keep(bool native); | 634 | int seccomp_filter_keep(bool native); |
634 | int seccomp_filter_mdwx(bool native); | 635 | int seccomp_filter_mdwx(bool native); |
636 | int seccomp_filter_namespaces(bool native, const char *list); | ||
635 | void seccomp_print_filter(pid_t pid) __attribute__((noreturn)); | 637 | void seccomp_print_filter(pid_t pid) __attribute__((noreturn)); |
636 | 638 | ||
637 | // caps.c | 639 | // caps.c |
diff --git a/src/firejail/main.c b/src/firejail/main.c index e6c5b50b0..55f623138 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -1400,6 +1400,20 @@ int main(int argc, char **argv, char **envp) { | |||
1400 | else | 1400 | else |
1401 | exit_err_feature("seccomp"); | 1401 | exit_err_feature("seccomp"); |
1402 | } | 1402 | } |
1403 | else if (strcmp(argv[i], "--restrict-namespaces") == 0) { | ||
1404 | if (checkcfg(CFG_SECCOMP)) | ||
1405 | profile_list_augment(&cfg.restrict_namespaces, "cgroup,ipc,net,mnt,pid,time,user,uts"); | ||
1406 | else | ||
1407 | exit_err_feature("seccomp"); | ||
1408 | } | ||
1409 | else if (strncmp(argv[i], "--restrict-namespaces=", 22) == 0) { | ||
1410 | if (checkcfg(CFG_SECCOMP)) { | ||
1411 | const char *add = argv[i] + 22; | ||
1412 | profile_list_augment(&cfg.restrict_namespaces, add); | ||
1413 | } | ||
1414 | else | ||
1415 | exit_err_feature("seccomp"); | ||
1416 | } | ||
1403 | else if (strncmp(argv[i], "--seccomp-error-action=", 23) == 0) { | 1417 | else if (strncmp(argv[i], "--seccomp-error-action=", 23) == 0) { |
1404 | if (checkcfg(CFG_SECCOMP)) { | 1418 | if (checkcfg(CFG_SECCOMP)) { |
1405 | int config_seccomp_error_action = checkcfg(CFG_SECCOMP_ERROR_ACTION); | 1419 | int config_seccomp_error_action = checkcfg(CFG_SECCOMP_ERROR_ACTION); |
diff --git a/src/firejail/preproc.c b/src/firejail/preproc.c index b25b79a9e..44f82681a 100644 --- a/src/firejail/preproc.c +++ b/src/firejail/preproc.c | |||
@@ -91,10 +91,18 @@ void preproc_mount_mnt_dir(void) { | |||
91 | copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed | 91 | copy_file(PATH_SECCOMP_MDWX, RUN_SECCOMP_MDWX, getuid(), getgid(), 0644); // root needed |
92 | copy_file(PATH_SECCOMP_MDWX_32, RUN_SECCOMP_MDWX_32, getuid(), getgid(), 0644); // root needed | 92 | copy_file(PATH_SECCOMP_MDWX_32, RUN_SECCOMP_MDWX_32, getuid(), getgid(), 0644); // root needed |
93 | } | 93 | } |
94 | // as root, create empty RUN_SECCOMP_PROTOCOL and RUN_SECCOMP_POSTEXEC files | 94 | // as root, create empty RUN_SECCOMP_PROTOCOL, RUN_SECCOMP_NS and RUN_SECCOMP_POSTEXEC files |
95 | create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); | 95 | create_empty_file_as_root(RUN_SECCOMP_PROTOCOL, 0644); |
96 | if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) | 96 | if (set_perms(RUN_SECCOMP_PROTOCOL, getuid(), getgid(), 0644)) |
97 | errExit("set_perms"); | 97 | errExit("set_perms"); |
98 | if (cfg.restrict_namespaces) { | ||
99 | create_empty_file_as_root(RUN_SECCOMP_NS, 0644); | ||
100 | if (set_perms(RUN_SECCOMP_NS, getuid(), getgid(), 0644)) | ||
101 | errExit("set_perms"); | ||
102 | create_empty_file_as_root(RUN_SECCOMP_NS_32, 0644); | ||
103 | if (set_perms(RUN_SECCOMP_NS_32, getuid(), getgid(), 0644)) | ||
104 | errExit("set_perms"); | ||
105 | } | ||
98 | create_empty_file_as_root(RUN_SECCOMP_POSTEXEC, 0644); | 106 | create_empty_file_as_root(RUN_SECCOMP_POSTEXEC, 0644); |
99 | if (set_perms(RUN_SECCOMP_POSTEXEC, getuid(), getgid(), 0644)) | 107 | if (set_perms(RUN_SECCOMP_POSTEXEC, getuid(), getgid(), 0644)) |
100 | errExit("set_perms"); | 108 | errExit("set_perms"); |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 1a83a0628..dc1aff49a 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -26,7 +26,8 @@ | |||
26 | 26 | ||
27 | extern char *xephyr_screen; | 27 | extern char *xephyr_screen; |
28 | 28 | ||
29 | #define MAX_READ 8192 // line buffer for profile files | 29 | #define MAX_READ 8192 // line buffer for profile files |
30 | #define MAX_LIST 16384 // size limit for argument lists | ||
30 | 31 | ||
31 | // find and read the profile specified by name from dir directory | 32 | // find and read the profile specified by name from dir directory |
32 | // return 1 if a profile was found | 33 | // return 1 if a profile was found |
@@ -1042,6 +1043,24 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1042 | return 0; | 1043 | return 0; |
1043 | } | 1044 | } |
1044 | 1045 | ||
1046 | // restrict-namespaces | ||
1047 | if (strcmp(ptr, "restrict-namespaces") == 0) { | ||
1048 | if (checkcfg(CFG_SECCOMP)) | ||
1049 | profile_list_augment(&cfg.restrict_namespaces, "cgroup,ipc,net,mnt,pid,time,user,uts"); | ||
1050 | else | ||
1051 | warning_feature_disabled("seccomp"); | ||
1052 | return 0; | ||
1053 | } | ||
1054 | if (strncmp(ptr, "restrict-namespaces ", 20) == 0) { | ||
1055 | if (checkcfg(CFG_SECCOMP)) { | ||
1056 | const char *add = ptr + 20; | ||
1057 | profile_list_augment(&cfg.restrict_namespaces, add); | ||
1058 | } | ||
1059 | else | ||
1060 | warning_feature_disabled("seccomp"); | ||
1061 | return 0; | ||
1062 | } | ||
1063 | |||
1045 | // seccomp error action | 1064 | // seccomp error action |
1046 | if (strncmp(ptr, "seccomp-error-action ", 21) == 0) { | 1065 | if (strncmp(ptr, "seccomp-error-action ", 21) == 0) { |
1047 | if (checkcfg(CFG_SECCOMP)) { | 1066 | if (checkcfg(CFG_SECCOMP)) { |
@@ -1959,4 +1978,10 @@ void profile_list_augment(char **list, const char *items) | |||
1959 | errExit("asprintf"); | 1978 | errExit("asprintf"); |
1960 | free(*list); | 1979 | free(*list); |
1961 | *list = profile_list_compress(tmp); | 1980 | *list = profile_list_compress(tmp); |
1981 | |||
1982 | // lists should not grow indefinitely | ||
1983 | if (strlen(*list) > MAX_LIST) { | ||
1984 | fprintf(stderr, "Error: argument list is too long\n"); | ||
1985 | exit(1); | ||
1986 | } | ||
1962 | } | 1987 | } |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 864236824..b1b3407b4 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -1205,6 +1205,16 @@ int sandbox(void* sandbox_arg) { | |||
1205 | seccomp_load(RUN_SECCOMP_MDWX_32); | 1205 | seccomp_load(RUN_SECCOMP_MDWX_32); |
1206 | } | 1206 | } |
1207 | 1207 | ||
1208 | if (cfg.restrict_namespaces) { | ||
1209 | seccomp_filter_namespaces(true, cfg.restrict_namespaces); | ||
1210 | seccomp_filter_namespaces(false, cfg.restrict_namespaces); | ||
1211 | |||
1212 | if (arg_debug) | ||
1213 | printf("Install namespaces filter\n"); | ||
1214 | seccomp_load(RUN_SECCOMP_NS); // install filter | ||
1215 | seccomp_load(RUN_SECCOMP_NS_32); | ||
1216 | } | ||
1217 | |||
1208 | // make seccomp filters read-only | 1218 | // make seccomp filters read-only |
1209 | fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); | 1219 | fs_remount(RUN_SECCOMP_DIR, MOUNT_READONLY, 0); |
1210 | seccomp_debug(); | 1220 | seccomp_debug(); |
diff --git a/src/firejail/seccomp.c b/src/firejail/seccomp.c index b8b4ec0d6..84748da77 100644 --- a/src/firejail/seccomp.c +++ b/src/firejail/seccomp.c | |||
@@ -416,7 +416,7 @@ int seccomp_filter_mdwx(bool native) { | |||
416 | 416 | ||
417 | // build the seccomp filter as a regular user | 417 | // build the seccomp filter as a regular user |
418 | int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, | 418 | int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 3, |
419 | PATH_FSECCOMP, command, filter); | 419 | PATH_FSECCOMP, command, filter); |
420 | 420 | ||
421 | if (rv) { | 421 | if (rv) { |
422 | fprintf(stderr, "Error: cannot build memory-deny-write-execute filter\n"); | 422 | fprintf(stderr, "Error: cannot build memory-deny-write-execute filter\n"); |
@@ -429,6 +429,35 @@ int seccomp_filter_mdwx(bool native) { | |||
429 | return 0; | 429 | return 0; |
430 | } | 430 | } |
431 | 431 | ||
432 | // create namespaces filter | ||
433 | int seccomp_filter_namespaces(bool native, const char *list) { | ||
434 | if (arg_debug) | ||
435 | printf("Build restrict-namespaces filter\n"); | ||
436 | |||
437 | const char *command, *filter; | ||
438 | if (native) { | ||
439 | command = "restrict-namespaces"; | ||
440 | filter = RUN_SECCOMP_NS; | ||
441 | } else { | ||
442 | command = "restrict-namespaces.32"; | ||
443 | filter = RUN_SECCOMP_NS_32; | ||
444 | } | ||
445 | |||
446 | // build the seccomp filter as a regular user | ||
447 | int rv = sbox_run(SBOX_USER | SBOX_CAPS_NONE | SBOX_SECCOMP, 4, | ||
448 | PATH_FSECCOMP, command, filter, list); | ||
449 | |||
450 | if (rv) { | ||
451 | fprintf(stderr, "Error: cannot build restrict-namespaces filter\n"); | ||
452 | exit(rv); | ||
453 | } | ||
454 | |||
455 | if (arg_debug) | ||
456 | printf("restrict-namespaces filter configured\n"); | ||
457 | |||
458 | return 0; | ||
459 | } | ||
460 | |||
432 | void seccomp_print_filter(pid_t pid) { | 461 | void seccomp_print_filter(pid_t pid) { |
433 | EUID_ASSERT(); | 462 | EUID_ASSERT(); |
434 | 463 | ||
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 14cd1f3a4..c3c17393c 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -214,6 +214,9 @@ static char *usage_str = | |||
214 | " --quiet - turn off Firejail's output.\n" | 214 | " --quiet - turn off Firejail's output.\n" |
215 | " --read-only=filename - set directory or file read-only.\n" | 215 | " --read-only=filename - set directory or file read-only.\n" |
216 | " --read-write=filename - set directory or file read-write.\n" | 216 | " --read-write=filename - set directory or file read-write.\n" |
217 | " --restrict-namespaces - seccomp filter that blocks attempts to create new namespaces.\n" | ||
218 | " --restrict-namespaces=namespace,namespace - seccomp filter that blocks attempts\n" | ||
219 | "\tto create specified namespaces.\n" | ||
217 | " --rlimit-as=number - set the maximum size of the process's virtual memory.\n" | 220 | " --rlimit-as=number - set the maximum size of the process's virtual memory.\n" |
218 | "\t(address space) in bytes.\n" | 221 | "\t(address space) in bytes.\n" |
219 | " --rlimit-cpu=number - set the maximum CPU time in seconds.\n" | 222 | " --rlimit-cpu=number - set the maximum CPU time in seconds.\n" |
diff --git a/src/fseccomp/fseccomp.h b/src/fseccomp/fseccomp.h index 65337da2a..5911b5156 100644 --- a/src/fseccomp/fseccomp.h +++ b/src/fseccomp/fseccomp.h | |||
@@ -61,6 +61,10 @@ void seccomp_keep(const char *fname1, const char *fname2, char *list, bool nativ | |||
61 | void memory_deny_write_execute(const char *fname); | 61 | void memory_deny_write_execute(const char *fname); |
62 | void memory_deny_write_execute_32(const char *fname); | 62 | void memory_deny_write_execute_32(const char *fname); |
63 | 63 | ||
64 | // namespaces.c | ||
65 | void deny_ns(const char *fname, const char *list); | ||
66 | void deny_ns_32(const char *fname, const char *list); | ||
67 | |||
64 | // seccomp_print | 68 | // seccomp_print |
65 | void filter_print(const char *fname); | 69 | void filter_print(const char *fname); |
66 | 70 | ||
diff --git a/src/fseccomp/main.c b/src/fseccomp/main.c index 48665ab71..01d7dd8cf 100644 --- a/src/fseccomp/main.c +++ b/src/fseccomp/main.c | |||
@@ -48,6 +48,8 @@ static void usage(void) { | |||
48 | printf("\tfseccomp keep32 file1 file2 list\n"); | 48 | printf("\tfseccomp keep32 file1 file2 list\n"); |
49 | printf("\tfseccomp memory-deny-write-execute file\n"); | 49 | printf("\tfseccomp memory-deny-write-execute file\n"); |
50 | printf("\tfseccomp memory-deny-write-execute.32 file\n"); | 50 | printf("\tfseccomp memory-deny-write-execute.32 file\n"); |
51 | printf("\tfseccomp restrict-namespaces file list\n"); | ||
52 | printf("\tfseccomp restrict-namespaces.32 file list\n"); | ||
51 | } | 53 | } |
52 | 54 | ||
53 | int main(int argc, char **argv) { | 55 | int main(int argc, char **argv) { |
@@ -135,6 +137,10 @@ printf("\n"); | |||
135 | memory_deny_write_execute(argv[2]); | 137 | memory_deny_write_execute(argv[2]); |
136 | else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute.32") == 0) | 138 | else if (argc == 3 && strcmp(argv[1], "memory-deny-write-execute.32") == 0) |
137 | memory_deny_write_execute_32(argv[2]); | 139 | memory_deny_write_execute_32(argv[2]); |
140 | else if (argc == 4 && strcmp(argv[1], "restrict-namespaces") == 0) | ||
141 | deny_ns(argv[2], argv[3]); | ||
142 | else if (argc == 4 && strcmp(argv[1], "restrict-namespaces.32") == 0) | ||
143 | deny_ns_32(argv[2], argv[3]); | ||
138 | else { | 144 | else { |
139 | fprintf(stderr, "Error fseccomp: invalid arguments\n"); | 145 | fprintf(stderr, "Error fseccomp: invalid arguments\n"); |
140 | return 1; | 146 | return 1; |
diff --git a/src/fseccomp/namespaces.c b/src/fseccomp/namespaces.c new file mode 100644 index 000000000..3df23dcff --- /dev/null +++ b/src/fseccomp/namespaces.c | |||
@@ -0,0 +1,197 @@ | |||
1 | /* | ||
2 | * Copyright (C) 2014-2022 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 | #define _GNU_SOURCE | ||
21 | #include "fseccomp.h" | ||
22 | #include "../include/seccomp.h" | ||
23 | #include <sys/syscall.h> | ||
24 | |||
25 | #include <sched.h> | ||
26 | #ifndef CLONE_NEWCGROUP | ||
27 | #define CLONE_NEWCGROUP 0x02000000 | ||
28 | #endif | ||
29 | #ifndef CLONE_NEWTIME | ||
30 | #define CLONE_NEWTIME 0x00000080 | ||
31 | #endif | ||
32 | |||
33 | // 64-bit architectures | ||
34 | #if INTPTR_MAX == INT64_MAX | ||
35 | #if defined __x86_64__ | ||
36 | // i386 syscalls | ||
37 | #define clone_32 120 | ||
38 | #define clone3_32 435 | ||
39 | #define unshare_32 310 | ||
40 | #define setns_32 346 | ||
41 | #else | ||
42 | #warning 32 bit namespaces filter not implemented yet for your architecture | ||
43 | #endif | ||
44 | #endif | ||
45 | |||
46 | |||
47 | static int build_ns_mask(const char *list) { | ||
48 | int mask = 0; | ||
49 | |||
50 | char *dup = strdup(list); | ||
51 | if (!dup) | ||
52 | errExit("strdup"); | ||
53 | |||
54 | char *token = strtok(dup, ","); | ||
55 | while (token) { | ||
56 | if (strcmp(token, "cgroup") == 0) | ||
57 | mask |= CLONE_NEWCGROUP; | ||
58 | else if (strcmp(token, "ipc") == 0) | ||
59 | mask |= CLONE_NEWIPC; | ||
60 | else if (strcmp(token, "net") == 0) | ||
61 | mask |= CLONE_NEWNET; | ||
62 | else if (strcmp(token, "mnt") == 0) | ||
63 | mask |= CLONE_NEWNS; | ||
64 | else if (strcmp(token, "pid") == 0) | ||
65 | mask |= CLONE_NEWPID; | ||
66 | else if (strcmp(token, "time") == 0) | ||
67 | mask |= CLONE_NEWTIME; | ||
68 | else if (strcmp(token, "user") == 0) | ||
69 | mask |= CLONE_NEWUSER; | ||
70 | else if (strcmp(token, "uts") == 0) | ||
71 | mask |= CLONE_NEWUTS; | ||
72 | else { | ||
73 | fprintf(stderr, "Error fseccomp: %s is not a valid namespace\n", token); | ||
74 | exit(1); | ||
75 | } | ||
76 | |||
77 | token = strtok(NULL, ","); | ||
78 | } | ||
79 | |||
80 | free(dup); | ||
81 | return mask; | ||
82 | } | ||
83 | |||
84 | void deny_ns(const char *fname, const char *list) { | ||
85 | int mask = build_ns_mask(list); | ||
86 | // CLONE_NEWTIME means something different for clone | ||
87 | // create a second mask without it | ||
88 | int clone_mask = mask & ~CLONE_NEWTIME; | ||
89 | |||
90 | // open file | ||
91 | int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
92 | if (fd < 0) { | ||
93 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
94 | exit(1); | ||
95 | } | ||
96 | |||
97 | filter_init(fd, true); | ||
98 | |||
99 | // build filter | ||
100 | struct sock_filter filter[] = { | ||
101 | #ifdef SYS_clone | ||
102 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_clone, 0, 4), | ||
103 | // s390 has first and second argument flipped | ||
104 | #if defined __s390__ | ||
105 | EXAMINE_ARGUMENT(1), | ||
106 | #else | ||
107 | EXAMINE_ARGUMENT(0), | ||
108 | #endif | ||
109 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, clone_mask, 0, 1), | ||
110 | KILL_OR_RETURN_ERRNO, | ||
111 | RETURN_ALLOW, | ||
112 | #endif | ||
113 | #ifdef SYS_clone3 | ||
114 | // cannot inspect clone3 argument because | ||
115 | // seccomp does not dereference pointers | ||
116 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_clone3, 0, 1), | ||
117 | RETURN_ERRNO(ENOSYS), // hint to use clone instead | ||
118 | #endif | ||
119 | #ifdef SYS_unshare | ||
120 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_unshare, 0, 4), | ||
121 | EXAMINE_ARGUMENT(0), | ||
122 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, mask, 0, 1), | ||
123 | KILL_OR_RETURN_ERRNO, | ||
124 | RETURN_ALLOW, | ||
125 | #endif | ||
126 | #ifdef SYS_setns | ||
127 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, SYS_setns, 0, 4), | ||
128 | EXAMINE_ARGUMENT(1), | ||
129 | // always fail if argument is zero | ||
130 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 1, 0), | ||
131 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, mask, 0, 1), | ||
132 | KILL_OR_RETURN_ERRNO, | ||
133 | RETURN_ALLOW | ||
134 | #endif | ||
135 | }; | ||
136 | write_to_file(fd, filter, sizeof(filter)); | ||
137 | |||
138 | filter_end_blacklist(fd); | ||
139 | |||
140 | // close file | ||
141 | close(fd); | ||
142 | } | ||
143 | |||
144 | void deny_ns_32(const char *fname, const char *list) { | ||
145 | int mask = build_ns_mask(list); | ||
146 | // CLONE_NEWTIME means something different for clone | ||
147 | // create a second mask without it | ||
148 | int clone_mask = mask & ~CLONE_NEWTIME; | ||
149 | |||
150 | // open file | ||
151 | int fd = open(fname, O_CREAT|O_WRONLY|O_TRUNC, S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH); | ||
152 | if (fd < 0) { | ||
153 | fprintf(stderr, "Error fseccomp: cannot open %s file\n", fname); | ||
154 | exit(1); | ||
155 | } | ||
156 | |||
157 | filter_init(fd, false); | ||
158 | |||
159 | // build filter | ||
160 | struct sock_filter filter[] = { | ||
161 | #ifdef clone_32 | ||
162 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, clone_32, 0, 4), | ||
163 | EXAMINE_ARGUMENT(0), | ||
164 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, clone_mask, 0, 1), | ||
165 | KILL_OR_RETURN_ERRNO, | ||
166 | RETURN_ALLOW, | ||
167 | #endif | ||
168 | #ifdef clone3_32 | ||
169 | // cannot inspect clone3 argument because | ||
170 | // seccomp does not dereference pointers | ||
171 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, clone3_32, 0, 1), | ||
172 | RETURN_ERRNO(ENOSYS), // hint to use clone instead | ||
173 | #endif | ||
174 | #ifdef unshare_32 | ||
175 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, unshare_32, 0, 4), | ||
176 | EXAMINE_ARGUMENT(0), | ||
177 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, mask, 0, 1), | ||
178 | KILL_OR_RETURN_ERRNO, | ||
179 | RETURN_ALLOW, | ||
180 | #endif | ||
181 | #ifdef setns_32 | ||
182 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, setns_32, 0, 4), | ||
183 | EXAMINE_ARGUMENT(1), | ||
184 | // always fail if argument is zero | ||
185 | BPF_JUMP(BPF_JMP+BPF_JEQ+BPF_K, 0, 1, 0), | ||
186 | BPF_JUMP(BPF_JMP+BPF_JSET+BPF_K, mask, 0, 1), | ||
187 | KILL_OR_RETURN_ERRNO, | ||
188 | RETURN_ALLOW | ||
189 | #endif | ||
190 | }; | ||
191 | write_to_file(fd, filter, sizeof(filter)); | ||
192 | |||
193 | filter_end_blacklist(fd); | ||
194 | |||
195 | // close file | ||
196 | close(fd); | ||
197 | } | ||
diff --git a/src/fseccomp/protocol.c b/src/fseccomp/protocol.c index 25742c173..ea5cd5bd4 100644 --- a/src/fseccomp/protocol.c +++ b/src/fseccomp/protocol.c | |||
@@ -132,15 +132,18 @@ void protocol_build_filter(const char *prlist, const char *fname) { | |||
132 | EXAMINE_SYSCALL, // 1 | 132 | EXAMINE_SYSCALL, // 1 |
133 | // checking SYS_socket only: filtering SYS_socketcall not possible with seccomp | 133 | // checking SYS_socket only: filtering SYS_socketcall not possible with seccomp |
134 | ONLY(359), // 1 + 2 | 134 | ONLY(359), // 1 + 2 |
135 | BPF_JUMP(BPF_JMP+BPF_JA+BPF_K, (3 + 1 + 2), 0, 0), // 1 + 2 + 1 | 135 | BPF_JUMP(BPF_JMP+BPF_JA+BPF_K, (3 + 1 + 3 + 2), 0, 0), // 1 + 2 + 1 |
136 | #else | 136 | #else |
137 | #warning 32 bit protocol filter not implemented yet for your architecture | 137 | #warning 32 bit protocol filter not implemented yet for your architecture |
138 | #endif | 138 | #endif |
139 | VALIDATE_ARCHITECTURE, // 3 | 139 | VALIDATE_ARCHITECTURE, // 3 |
140 | EXAMINE_SYSCALL, // 3 + 1 | 140 | EXAMINE_SYSCALL, // 3 + 1 |
141 | ONLY(SYS_socket), // 3 + 1 + 2 | 141 | #if defined __x86_64__ |
142 | HANDLE_X32, // 3 + 1 + 3 | ||
143 | #endif | ||
144 | ONLY(SYS_socket), // 3 + 1 (+ 3) + 2 | ||
142 | 145 | ||
143 | EXAMINE_ARGUMENT(0) // 3 + 1 + 2 + 1 | 146 | EXAMINE_ARGUMENT(0) // 3 + 1 (+ 3) + 2 + 1 |
144 | }; | 147 | }; |
145 | memcpy(ptr, &filter_start[0], sizeof(filter_start)); | 148 | memcpy(ptr, &filter_start[0], sizeof(filter_start)); |
146 | ptr += sizeof(filter_start); | 149 | ptr += sizeof(filter_start); |
diff --git a/src/include/rundefs.h b/src/include/rundefs.h index 08042d2c4..079670f10 100644 --- a/src/include/rundefs.h +++ b/src/include/rundefs.h | |||
@@ -68,6 +68,8 @@ | |||
68 | #define RUN_SECCOMP_32 RUN_SECCOMP_DIR "/seccomp.32" // 32bit arch filter installed on 64bit architectures | 68 | #define RUN_SECCOMP_32 RUN_SECCOMP_DIR "/seccomp.32" // 32bit arch filter installed on 64bit architectures |
69 | #define RUN_SECCOMP_MDWX RUN_SECCOMP_DIR "/seccomp.mdwx" // filter for memory-deny-write-execute | 69 | #define RUN_SECCOMP_MDWX RUN_SECCOMP_DIR "/seccomp.mdwx" // filter for memory-deny-write-execute |
70 | #define RUN_SECCOMP_MDWX_32 RUN_SECCOMP_DIR "/seccomp.mdwx.32" | 70 | #define RUN_SECCOMP_MDWX_32 RUN_SECCOMP_DIR "/seccomp.mdwx.32" |
71 | #define RUN_SECCOMP_NS RUN_SECCOMP_DIR "/seccomp.namespaces" | ||
72 | #define RUN_SECCOMP_NS_32 RUN_SECCOMP_DIR "/seccomp.namespaces.32" | ||
71 | #define RUN_SECCOMP_BLOCK_SECONDARY RUN_SECCOMP_DIR "/seccomp.block_secondary" // secondary arch blocking filter | 73 | #define RUN_SECCOMP_BLOCK_SECONDARY RUN_SECCOMP_DIR "/seccomp.block_secondary" // secondary arch blocking filter |
72 | #define RUN_SECCOMP_POSTEXEC RUN_SECCOMP_DIR "/seccomp.postexec" // filter for post-exec library | 74 | #define RUN_SECCOMP_POSTEXEC RUN_SECCOMP_DIR "/seccomp.postexec" // filter for post-exec library |
73 | #define RUN_SECCOMP_POSTEXEC_32 RUN_SECCOMP_DIR "/seccomp.postexec32" // filter for post-exec library | 75 | #define RUN_SECCOMP_POSTEXEC_32 RUN_SECCOMP_DIR "/seccomp.postexec32" // filter for post-exec library |
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 5c8b6031d..be1f55f0f 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -520,6 +520,12 @@ first argument to socket system call. Recognized values: \fBunix\fR, | |||
520 | \fBinet\fR, \fBinet6\fR, \fBnetlink\fR, \fBpacket\fR, and \fBbluetooth\fR. | 520 | \fBinet\fR, \fBinet6\fR, \fBnetlink\fR, \fBpacket\fR, and \fBbluetooth\fR. |
521 | Multiple protocol commands are allowed and they accumulate. | 521 | Multiple protocol commands are allowed and they accumulate. |
522 | .TP | 522 | .TP |
523 | \fBrestrict-namespaces | ||
524 | Install a seccomp filter that blocks attempts to create new cgroup, ipc, net, mount, pid, time, user or uts namespaces. | ||
525 | .TP | ||
526 | \fBrestrict-namespaces cgroup,ipc,net,mnt,pid,time,user,uts | ||
527 | Install a seccomp filter that blocks attempts to create any of the specified namespaces. | ||
528 | .TP | ||
523 | \fBseccomp | 529 | \fBseccomp |
524 | Enable seccomp filter and blacklist the syscalls in the default list. See man 1 firejail for more details. | 530 | Enable seccomp filter and blacklist the syscalls in the default list. See man 1 firejail for more details. |
525 | .TP | 531 | .TP |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index c2c0bc297..087d1c85a 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -693,6 +693,7 @@ Example: | |||
693 | .br | 693 | .br |
694 | $ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox | 694 | $ firejail \-\-net=eth0 \-\-defaultgw=10.10.20.1 firefox |
695 | #endif | 695 | #endif |
696 | |||
696 | .TP | 697 | .TP |
697 | \fB\-\-deterministic-exit-code | 698 | \fB\-\-deterministic-exit-code |
698 | Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic. | 699 | Always exit firejail with the first child's exit status. The default behavior is to use the exit status of the final child to exit, which can be nondeterministic. |
@@ -2257,6 +2258,29 @@ $ firejail --read-only=~/test --read-write=~/test/a | |||
2257 | 2258 | ||
2258 | 2259 | ||
2259 | .TP | 2260 | .TP |
2261 | \fB\-\-restrict-namespaces | ||
2262 | Install a seccomp filter that blocks attempts to create new cgroup, ipc, net, mount, pid, time, user or uts namespaces. | ||
2263 | .br | ||
2264 | |||
2265 | .br | ||
2266 | Example: | ||
2267 | .br | ||
2268 | $ firejail \-\-restrict-namespaces | ||
2269 | |||
2270 | .TP | ||
2271 | \fB\-\-restrict-namespaces=cgroup,ipc,net,mnt,pid,time,user,uts | ||
2272 | Install a seccomp filter that blocks attempts to create any of the specified namespaces. The filter examines | ||
2273 | the arguments of clone, unshare and setns system calls and returns error EPERM to the process | ||
2274 | (or kills it or logs the attempt, see \-\-seccomp-error-action below) if necessary. Note that the filter is not | ||
2275 | able to examine the arguments of clone3 system calls, and always responds to these calls with error ENOSYS. | ||
2276 | .br | ||
2277 | |||
2278 | .br | ||
2279 | Example: | ||
2280 | .br | ||
2281 | $ firejail \-\-restrict-namespaces=user,net | ||
2282 | |||
2283 | .TP | ||
2260 | \fB\-\-rlimit-as=number | 2284 | \fB\-\-rlimit-as=number |
2261 | Set the maximum size of the process's virtual memory (address space) in bytes. | 2285 | Set the maximum size of the process's virtual memory (address space) in bytes. |
2262 | Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). | 2286 | Use k(ilobyte), m(egabyte) or g(igabyte) for size suffix (base 1024). |
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index 8383d83d3..605000e31 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in | |||
@@ -103,7 +103,7 @@ _firejail_args=( | |||
103 | '--join-or-start=-[join the sandbox or start a new one name|pid]: :_all_firejails' | 103 | '--join-or-start=-[join the sandbox or start a new one name|pid]: :_all_firejails' |
104 | '--keep-config-pulse[disable automatic ~/.config/pulse init]' | 104 | '--keep-config-pulse[disable automatic ~/.config/pulse init]' |
105 | '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]' | 105 | '--keep-dev-shm[/dev/shm directory is untouched (even with --private-dev)]' |
106 | '--keep-fd[inherit open file descriptors to sandbox]' | 106 | '--keep-fd[inherit open file descriptors to sandbox]: :' |
107 | '--keep-var-tmp[/var/tmp directory is untouched]' | 107 | '--keep-var-tmp[/var/tmp directory is untouched]' |
108 | '--machine-id[spoof /etc/machine-id with a random id]' | 108 | '--machine-id[spoof /etc/machine-id with a random id]' |
109 | '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' | 109 | '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' |
@@ -141,6 +141,8 @@ _firejail_args=( | |||
141 | "--quiet[turn off Firejail's output.]" | 141 | "--quiet[turn off Firejail's output.]" |
142 | '*--read-only=-[set directory or file read-only]: :_files' | 142 | '*--read-only=-[set directory or file read-only]: :_files' |
143 | '*--read-write=-[set directory or file read-write]: :_files' | 143 | '*--read-write=-[set directory or file read-write]: :_files' |
144 | '--restrict-namespaces[seccomp filter that blocks attempts to create new namespaces]' | ||
145 | '--restrict-namespaces=-[seccomp filter that blocks attempts to create specified namespaces]: :' | ||
144 | "--rlimit-as=-[set the maximum size of the process's virtual memory (address space) in bytes]: :" | 146 | "--rlimit-as=-[set the maximum size of the process's virtual memory (address space) in bytes]: :" |
145 | '--rlimit-cpu=-[set the maximum CPU time in seconds]: :' | 147 | '--rlimit-cpu=-[set the maximum CPU time in seconds]: :' |
146 | '--rlimit-fsize=-[set the maximum file size that can be created by a process]: :' | 148 | '--rlimit-fsize=-[set the maximum file size that can be created by a process]: :' |