diff options
author | Азалия Смарагдова <charming.flurry@yandex.ru> | 2022-08-15 12:19:11 +0500 |
---|---|---|
committer | Азалия Смарагдова <charming.flurry@yandex.ru> | 2022-08-15 13:32:24 +0500 |
commit | 61b15442898eeb1db2d23b6b2eb72a705ceb368a (patch) | |
tree | 6d9cb22307941a81f4562dbfd0c00e7b2e96dbcd | |
parent | more merges (diff) | |
download | firejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.tar.gz firejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.tar.zst firejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.zip |
Landlock support has been added.
-rw-r--r-- | config.mk.in | 3 | ||||
-rwxr-xr-x | configure | 16 | ||||
-rw-r--r-- | configure.ac | 10 | ||||
-rw-r--r-- | contrib/vim/syntax/firejail.vim | 2 | ||||
-rw-r--r-- | src/bash_completion/firejail.bash_completion.in | 16 | ||||
-rw-r--r-- | src/firejail/firejail.h | 3 | ||||
-rw-r--r-- | src/firejail/main.c | 33 | ||||
-rw-r--r-- | src/firejail/profile.c | 35 | ||||
-rw-r--r-- | src/firejail/sandbox.c | 13 | ||||
-rw-r--r-- | src/firejail/usage.c | 4 | ||||
-rw-r--r-- | src/include/tinyLL.h | 23 | ||||
-rw-r--r-- | src/lib/libtinyll.c | 108 | ||||
-rw-r--r-- | src/man/firejail-profile.txt | 21 | ||||
-rw-r--r-- | src/man/firejail.txt | 28 | ||||
-rw-r--r-- | src/zsh_completion/_firejail.in | 4 |
15 files changed, 316 insertions, 3 deletions
diff --git a/config.mk.in b/config.mk.in index 9973b7eaa..150ac8e15 100644 --- a/config.mk.in +++ b/config.mk.in | |||
@@ -41,6 +41,7 @@ HAVE_PRIVATE_HOME=@HAVE_PRIVATE_HOME@ | |||
41 | HAVE_IDS=@HAVE_IDS@ | 41 | HAVE_IDS=@HAVE_IDS@ |
42 | HAVE_GCOV=@HAVE_GCOV@ | 42 | HAVE_GCOV=@HAVE_GCOV@ |
43 | HAVE_SELINUX=@HAVE_SELINUX@ | 43 | HAVE_SELINUX=@HAVE_SELINUX@ |
44 | HAVE_LANDLOCK=@HAVE_LANDLOCK@ | ||
44 | HAVE_SUID=@HAVE_SUID@ | 45 | HAVE_SUID=@HAVE_SUID@ |
45 | HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ | 46 | HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ |
46 | HAVE_USERTMPFS=@HAVE_USERTMPFS@ | 47 | HAVE_USERTMPFS=@HAVE_USERTMPFS@ |
@@ -49,7 +50,7 @@ HAVE_LTS=@HAVE_LTS@ | |||
49 | HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@ | 50 | HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@ |
50 | HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@ | 51 | HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@ |
51 | 52 | ||
52 | MANFLAGS = $(HAVE_LTS) $(HAVE_OUTPUT) $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_IDS) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_SELINUX) $(HAVE_SUID) $(HAVE_FORCE_NONEWPRIVS) $(HAVE_ONLY_SYSCFG_PROFILES) | 53 | MANFLAGS = $(HAVE_LTS) $(HAVE_OUTPUT) $(HAVE_X11) $(HAVE_PRIVATE_HOME) $(HAVE_APPARMOR) $(HAVE_IDS) $(HAVE_OVERLAYFS) $(HAVE_USERTMPFS) $(HAVE_DBUSPROXY) $(HAVE_FIRETUNNEL) $(HAVE_GLOBALCFG) $(HAVE_CHROOT) $(HAVE_NETWORK) $(HAVE_USERNS) $(HAVE_FILE_TRANSFER) $(HAVE_SELINUX) $(HAVE_SUID) $(HAVE_LANDLOCK) $(HAVE_FORCE_NONEWPRIVS) $(HAVE_ONLY_SYSCFG_PROFILES) |
53 | 54 | ||
54 | CC=@CC@ | 55 | CC=@CC@ |
55 | CFLAGS=@CFLAGS@ | 56 | CFLAGS=@CFLAGS@ |
@@ -652,6 +652,7 @@ HAVE_DBUSPROXY | |||
652 | EXTRA_LDFLAGS | 652 | EXTRA_LDFLAGS |
653 | EXTRA_CFLAGS | 653 | EXTRA_CFLAGS |
654 | HAVE_SELINUX | 654 | HAVE_SELINUX |
655 | HAVE_LANDLOCK | ||
655 | AA_LIBS | 656 | AA_LIBS |
656 | AA_CFLAGS | 657 | AA_CFLAGS |
657 | PKG_CONFIG_LIBDIR | 658 | PKG_CONFIG_LIBDIR |
@@ -713,6 +714,7 @@ enable_sanitizer | |||
713 | enable_ids | 714 | enable_ids |
714 | enable_apparmor | 715 | enable_apparmor |
715 | enable_selinux | 716 | enable_selinux |
717 | enable_landlock | ||
716 | enable_dbusproxy | 718 | enable_dbusproxy |
717 | enable_output | 719 | enable_output |
718 | enable_usertmpfs | 720 | enable_usertmpfs |
@@ -1374,6 +1376,7 @@ Optional Features: | |||
1374 | --enable-ids enable ids | 1376 | --enable-ids enable ids |
1375 | --enable-apparmor enable apparmor | 1377 | --enable-apparmor enable apparmor |
1376 | --enable-selinux SELinux labeling support | 1378 | --enable-selinux SELinux labeling support |
1379 | --enable-landlock Landlock self-restriction support | ||
1377 | --disable-dbusproxy disable dbus proxy | 1380 | --disable-dbusproxy disable dbus proxy |
1378 | --disable-output disable --output logging | 1381 | --disable-output disable --output logging |
1379 | --disable-usertmpfs disable tmpfs as regular user | 1382 | --disable-usertmpfs disable tmpfs as regular user |
@@ -3342,7 +3345,19 @@ if test "x$enable_selinux" = "xyes"; then : | |||
3342 | 3345 | ||
3343 | fi | 3346 | fi |
3344 | 3347 | ||
3348 | HAVE_LANDLOCK="" | ||
3345 | 3349 | ||
3350 | # Check whether --enable-landlock was given. | ||
3351 | if test "${enable_landlock+set}" = set; then : | ||
3352 | enableval=$enable_landlock; | ||
3353 | fi | ||
3354 | |||
3355 | if test "x$enable_landlock" = "xyes"; then : | ||
3356 | |||
3357 | HAVE_LANDLOCK="-DHAVE_LANDLOCK" | ||
3358 | EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ltinyll" | ||
3359 | |||
3360 | fi | ||
3346 | 3361 | ||
3347 | 3362 | ||
3348 | 3363 | ||
@@ -5277,6 +5292,7 @@ Features: | |||
5277 | overlayfs support: $HAVE_OVERLAYFS | 5292 | overlayfs support: $HAVE_OVERLAYFS |
5278 | private home support: $HAVE_PRIVATE_HOME | 5293 | private home support: $HAVE_PRIVATE_HOME |
5279 | SELinux labeling support: $HAVE_SELINUX | 5294 | SELinux labeling support: $HAVE_SELINUX |
5295 | Landlock self-restriction support: $HAVE_LANDLOCK | ||
5280 | user namespace: $HAVE_USERNS | 5296 | user namespace: $HAVE_USERNS |
5281 | X11 sandboxing support: $HAVE_X11 | 5297 | X11 sandboxing support: $HAVE_X11 |
5282 | 5298 | ||
diff --git a/configure.ac b/configure.ac index 8a488ff43..580ca69f1 100644 --- a/configure.ac +++ b/configure.ac | |||
@@ -81,10 +81,18 @@ AS_IF([test "x$enable_selinux" = "xyes"], [ | |||
81 | EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lselinux" | 81 | EXTRA_LDFLAGS="$EXTRA_LDFLAGS -lselinux" |
82 | ]) | 82 | ]) |
83 | 83 | ||
84 | HAVE_LANDLOCK="" | ||
85 | AC_SUBST([HAVE_LANDLOCK]) | ||
86 | AC_ARG_ENABLE([landlock]) | ||
87 | [AS_HELP_STRING([--enable-landlock], [Landlock self-restriction support])] | ||
88 | AS_IF([test "x$enable_landlock" = "xyes"], [ | ||
89 | HAVE_LANDLOCK="-DHAVE_LANDLOCK" | ||
90 | EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ltinyll" | ||
91 | ]) | ||
92 | |||
84 | AC_SUBST([EXTRA_CFLAGS]) | 93 | AC_SUBST([EXTRA_CFLAGS]) |
85 | AC_SUBST([EXTRA_LDFLAGS]) | 94 | AC_SUBST([EXTRA_LDFLAGS]) |
86 | 95 | ||
87 | |||
88 | HAVE_DBUSPROXY="" | 96 | HAVE_DBUSPROXY="" |
89 | AC_SUBST([HAVE_DBUSPROXY]) | 97 | AC_SUBST([HAVE_DBUSPROXY]) |
90 | AC_ARG_ENABLE([dbusproxy], | 98 | AC_ARG_ENABLE([dbusproxy], |
diff --git a/contrib/vim/syntax/firejail.vim b/contrib/vim/syntax/firejail.vim index 0c8ebdbd8..d3631b5df 100644 --- a/contrib/vim/syntax/firejail.vim +++ b/contrib/vim/syntax/firejail.vim | |||
@@ -52,7 +52,7 @@ syn match fjVar /\v\$\{(CFG|DESKTOP|DOCUMENTS|DOWNLOADS|HOME|MUSIC|PATH|PICTURES | |||
52 | 52 | ||
53 | " Commands grabbed from: src/firejail/profile.c | 53 | " Commands grabbed from: src/firejail/profile.c |
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) | 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) |
55 | syn match fjCommand /\v(apparmor|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(apparmor|bind|blacklist|blacklist-nolog|cpu|defaultgw|dns|hostname|hosts-file|ip6|iprange|join-or-start|landlock-read|landlock-write|landlock-restricted-write|landlock-execute|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 |
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 | 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 |
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 | 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 |
58 | syn match fjCommand /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite contained | 58 | syn match fjCommand /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite contained |
diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in index 8e047ce90..83d11d766 100644 --- a/src/bash_completion/firejail.bash_completion.in +++ b/src/bash_completion/firejail.bash_completion.in | |||
@@ -42,6 +42,22 @@ _firejail() | |||
42 | _filedir -d | 42 | _filedir -d |
43 | return 0 | 43 | return 0 |
44 | ;; | 44 | ;; |
45 | --landlock-read) | ||
46 | _filedir | ||
47 | return 0 | ||
48 | ;; | ||
49 | --landlock-write) | ||
50 | _filedir | ||
51 | return 0 | ||
52 | ;; | ||
53 | --landlock-restricted-write) | ||
54 | _filedir | ||
55 | return 0 | ||
56 | ;; | ||
57 | --landlock-execute) | ||
58 | _filedir | ||
59 | return 0 | ||
60 | ;; | ||
45 | --tmpfs) | 61 | --tmpfs) |
46 | _filedir | 62 | _filedir |
47 | return 0 | 63 | return 0 |
diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 0a4dffb75..6a679f849 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h | |||
@@ -23,6 +23,7 @@ | |||
23 | #include "../include/euid_common.h" | 23 | #include "../include/euid_common.h" |
24 | #include "../include/rundefs.h" | 24 | #include "../include/rundefs.h" |
25 | #include <linux/limits.h> // Note: Plain limits.h may break ARG_MAX (see #4583) | 25 | #include <linux/limits.h> // Note: Plain limits.h may break ARG_MAX (see #4583) |
26 | #include <linux/landlock.h> | ||
26 | #include <stdarg.h> | 27 | #include <stdarg.h> |
27 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
28 | 29 | ||
@@ -286,6 +287,8 @@ extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch | |||
286 | extern int arg_seccomp_postexec; // need postexec ld.preload library? | 287 | extern int arg_seccomp_postexec; // need postexec ld.preload library? |
287 | extern int arg_seccomp_block_secondary; // block any secondary architectures | 288 | extern int arg_seccomp_block_secondary; // block any secondary architectures |
288 | 289 | ||
290 | extern int arg_landlock; // Landlock ruleset file descriptor | ||
291 | |||
289 | extern int arg_caps_default_filter; // enable default capabilities filter | 292 | extern int arg_caps_default_filter; // enable default capabilities filter |
290 | extern int arg_caps_drop; // drop list | 293 | extern int arg_caps_drop; // drop list |
291 | extern int arg_caps_drop_all; // drop all capabilities | 294 | extern int arg_caps_drop_all; // drop all capabilities |
diff --git a/src/firejail/main.c b/src/firejail/main.c index 29c25dfc5..cff6eba5f 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c | |||
@@ -23,6 +23,9 @@ | |||
23 | #include "../include/gcov_wrapper.h" | 23 | #include "../include/gcov_wrapper.h" |
24 | #include "../include/syscall.h" | 24 | #include "../include/syscall.h" |
25 | #include "../include/seccomp.h" | 25 | #include "../include/seccomp.h" |
26 | #ifdef HAVE_LANDLOCK | ||
27 | #include "../include/tinyLL.h" | ||
28 | #endif | ||
26 | #define _GNU_SOURCE | 29 | #define _GNU_SOURCE |
27 | #include <sys/utsname.h> | 30 | #include <sys/utsname.h> |
28 | #include <sched.h> | 31 | #include <sched.h> |
@@ -81,6 +84,10 @@ int arg_seccomp_postexec = 0; // need postexec ld.preload library? | |||
81 | int arg_seccomp_block_secondary = 0; // block any secondary architectures | 84 | int arg_seccomp_block_secondary = 0; // block any secondary architectures |
82 | int arg_seccomp_error_action = 0; | 85 | int arg_seccomp_error_action = 0; |
83 | 86 | ||
87 | #ifdef HAVE_LANDLOCK | ||
88 | int arg_landlock = -1; // Landlock ruleset file descriptor (-1 if it doesn't exist) | ||
89 | #endif | ||
90 | |||
84 | int arg_caps_default_filter = 0; // enable default capabilities filter | 91 | int arg_caps_default_filter = 0; // enable default capabilities filter |
85 | int arg_caps_drop = 0; // drop list | 92 | int arg_caps_drop = 0; // drop list |
86 | int arg_caps_drop_all = 0; // drop all capabilities | 93 | int arg_caps_drop_all = 0; // drop all capabilities |
@@ -1401,6 +1408,32 @@ int main(int argc, char **argv, char **envp) { | |||
1401 | else | 1408 | else |
1402 | exit_err_feature("seccomp"); | 1409 | exit_err_feature("seccomp"); |
1403 | } | 1410 | } |
1411 | #ifdef HAVE_LANDLOCK | ||
1412 | else if (strncmp(argv[i], "--landlock-read=", 16) == 0) { | ||
1413 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1414 | if (add_read_access_rule_by_path(arg_landlock, argv[i]+16)) { | ||
1415 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1416 | } | ||
1417 | } | ||
1418 | else if (strncmp(argv[i], "--landlock-write=", 17) == 0) { | ||
1419 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1420 | if (add_write_access_rule_by_path(arg_landlock, argv[i]+17,0)) { | ||
1421 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1422 | } | ||
1423 | } | ||
1424 | else if (strncmp(argv[i], "--landlock-restricted-write=", 28) == 0) { | ||
1425 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1426 | if (add_write_access_rule_by_path(arg_landlock, argv[i]+28,1)) { | ||
1427 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1428 | } | ||
1429 | } | ||
1430 | else if (strncmp(argv[i], "--landlock-execute=", 19) == 0) { | ||
1431 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1432 | if (add_execute_rule_by_path(arg_landlock, argv[i]+19)) { | ||
1433 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1434 | } | ||
1435 | } | ||
1436 | #endif | ||
1404 | else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { | 1437 | else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { |
1405 | if (checkcfg(CFG_SECCOMP)) | 1438 | if (checkcfg(CFG_SECCOMP)) |
1406 | arg_memory_deny_write_execute = 1; | 1439 | arg_memory_deny_write_execute = 1; |
diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 82f8a393b..9d154adee 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include "../include/gcov_wrapper.h" | 21 | #include "../include/gcov_wrapper.h" |
22 | #include "../include/seccomp.h" | 22 | #include "../include/seccomp.h" |
23 | #include "../include/syscall.h" | 23 | #include "../include/syscall.h" |
24 | #ifdef HAVE_LANDLOCK | ||
25 | #include "../include/tinyLL.h" | ||
26 | #endif | ||
24 | #include <dirent.h> | 27 | #include <dirent.h> |
25 | #include <sys/stat.h> | 28 | #include <sys/stat.h> |
26 | 29 | ||
@@ -1045,6 +1048,38 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { | |||
1045 | return 0; | 1048 | return 0; |
1046 | } | 1049 | } |
1047 | 1050 | ||
1051 | #ifdef HAVE_LANDLOCK | ||
1052 | // Landlock ruleset paths | ||
1053 | if (strncmp(ptr, "landlock-read ", 14) == 0) { | ||
1054 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1055 | if (add_read_access_rule_by_path(arg_landlock, ptr+14)) { | ||
1056 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1057 | } | ||
1058 | return 0; | ||
1059 | } | ||
1060 | else if (strncmp(ptr, "landlock-write ", 15) == 0) { | ||
1061 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1062 | if (add_write_access_rule_by_path(arg_landlock, ptr+15,0)) { | ||
1063 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1064 | } | ||
1065 | return 0; | ||
1066 | } | ||
1067 | else if (strncmp(ptr, "landlock-restricted-write ", 26) == 0) { | ||
1068 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1069 | if (add_write_access_rule_by_path(arg_landlock, ptr+26,1)) { | ||
1070 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1071 | } | ||
1072 | return 0; | ||
1073 | } | ||
1074 | else if (strncmp(ptr, "landlock-execute ", 17) == 0) { | ||
1075 | if (arg_landlock == -1) arg_landlock = create_full_ruleset(); | ||
1076 | if (add_execute_rule_by_path(arg_landlock, ptr+17)) { | ||
1077 | fprintf(stderr,"An error has occured while adding a rule to the Landlock ruleset.\n"); | ||
1078 | } | ||
1079 | return 0; | ||
1080 | } | ||
1081 | #endif | ||
1082 | |||
1048 | // memory deny write&execute | 1083 | // memory deny write&execute |
1049 | if (strcmp(ptr, "memory-deny-write-execute") == 0) { | 1084 | if (strcmp(ptr, "memory-deny-write-execute") == 0) { |
1050 | if (checkcfg(CFG_SECCOMP)) | 1085 | if (checkcfg(CFG_SECCOMP)) |
diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 9299268a3..73f2aa211 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c | |||
@@ -21,6 +21,9 @@ | |||
21 | #include "firejail.h" | 21 | #include "firejail.h" |
22 | #include "../include/gcov_wrapper.h" | 22 | #include "../include/gcov_wrapper.h" |
23 | #include "../include/seccomp.h" | 23 | #include "../include/seccomp.h" |
24 | #ifdef HAVE_LANDLOCK | ||
25 | #include "../include/tinyLL.h" | ||
26 | #endif | ||
24 | #include <sys/mman.h> | 27 | #include <sys/mman.h> |
25 | #include <sys/mount.h> | 28 | #include <sys/mount.h> |
26 | #include <sys/wait.h> | 29 | #include <sys/wait.h> |
@@ -488,6 +491,16 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { | |||
488 | #ifdef HAVE_APPARMOR | 491 | #ifdef HAVE_APPARMOR |
489 | set_apparmor(); | 492 | set_apparmor(); |
490 | #endif | 493 | #endif |
494 | #ifdef HAVE_LANDLOCK | ||
495 | // set Landlock | ||
496 | if (arg_landlock >= 0) { | ||
497 | if (landlock_restrict_self(arg_landlock,0)) { | ||
498 | fprintf(stderr,"An error has occured while enabling Landlock self-restriction. Exiting...\n"); | ||
499 | exit(1); // it isn't safe to continue if Landlock self-restriction was enabled and the "landlock_restrict_self" syscall has failed | ||
500 | } | ||
501 | } | ||
502 | #endif | ||
503 | |||
491 | close_file_descriptors(); | 504 | close_file_descriptors(); |
492 | 505 | ||
493 | // set nice and rlimits | 506 | // set nice and rlimits |
diff --git a/src/firejail/usage.c b/src/firejail/usage.c index e11081eed..485d08ab0 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c | |||
@@ -122,6 +122,10 @@ static char *usage_str = | |||
122 | " --keep-dev-shm - /dev/shm directory is untouched (even with --private-dev).\n" | 122 | " --keep-dev-shm - /dev/shm directory is untouched (even with --private-dev).\n" |
123 | " --keep-fd - inherit open file descriptors to sandbox.\n" | 123 | " --keep-fd - inherit open file descriptors to sandbox.\n" |
124 | " --keep-var-tmp - /var/tmp directory is untouched.\n" | 124 | " --keep-var-tmp - /var/tmp directory is untouched.\n" |
125 | " --landlock-read=path - add a read access rule for the path to the Landlock ruleset.\n" | ||
126 | " --landlock-write=path - add a write access rule for the path to the Landlock ruleset.\n" | ||
127 | " --landlock-restricted-write=path - add a write access rule that doesn't include creating FIFO pipes, Unix domain sockets and block devices for the path to the Landlock ruleset.\n" | ||
128 | " --landlock-execute=path - add an execution-permitting rule for the path to the Landlock ruleset.\n" | ||
125 | " --list - list all sandboxes.\n" | 129 | " --list - list all sandboxes.\n" |
126 | #ifdef HAVE_FILE_TRANSFER | 130 | #ifdef HAVE_FILE_TRANSFER |
127 | " --ls=name|pid dir_or_filename - list files in sandbox container.\n" | 131 | " --ls=name|pid dir_or_filename - list files in sandbox container.\n" |
diff --git a/src/include/tinyLL.h b/src/include/tinyLL.h new file mode 100644 index 000000000..f5cd20876 --- /dev/null +++ b/src/include/tinyLL.h | |||
@@ -0,0 +1,23 @@ | |||
1 | extern int landlock_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags); | ||
2 | |||
3 | extern int landlock_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags); | ||
4 | |||
5 | extern int landlock_restrict_self(int fd,__u32 flags); | ||
6 | |||
7 | extern int create_full_ruleset(); | ||
8 | |||
9 | extern int add_read_access_rule(int rset_fd,int allowed_fd); | ||
10 | |||
11 | extern int add_read_access_rule_by_path(int rset_fd,char *allowed_path); | ||
12 | |||
13 | extern int add_write_access_rule(int rset_fd,int allowed_fd,int restricted); | ||
14 | |||
15 | extern int add_write_access_rule_by_path(int rset_fd,char *allowed_path,int restricted); | ||
16 | |||
17 | extern int add_execute_rule(int rset_fd,int allowed_fd); | ||
18 | |||
19 | extern int add_execute_rule_by_path(int rset_fd,char *allowed_path); | ||
20 | |||
21 | extern int check_nnp(); | ||
22 | |||
23 | extern int enable_nnp(); | ||
diff --git a/src/lib/libtinyll.c b/src/lib/libtinyll.c new file mode 100644 index 000000000..9db6f75d7 --- /dev/null +++ b/src/lib/libtinyll.c | |||
@@ -0,0 +1,108 @@ | |||
1 | #define _GNU_SOURCE | ||
2 | #include <stdio.h> | ||
3 | #include <stddef.h> | ||
4 | #include <stdlib.h> | ||
5 | #include <unistd.h> | ||
6 | #include <fcntl.h> | ||
7 | #include <sys/syscall.h> | ||
8 | #include <sys/types.h> | ||
9 | #include <sys/prctl.h> | ||
10 | #include <linux/prctl.h> | ||
11 | #include <linux/landlock.h> | ||
12 | |||
13 | int landlock_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags) { | ||
14 | return syscall(__NR_landlock_create_ruleset,rsattr,size,flags); | ||
15 | } | ||
16 | |||
17 | int landlock_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags) { | ||
18 | return syscall(__NR_landlock_add_rule,fd,t,attr,flags); | ||
19 | } | ||
20 | |||
21 | int landlock_restrict_self(int fd,__u32 flags) { | ||
22 | int result = syscall(__NR_landlock_restrict_self,fd,flags); | ||
23 | if (result!=0) return result; | ||
24 | else { | ||
25 | close(fd); | ||
26 | return 0; | ||
27 | } | ||
28 | } | ||
29 | |||
30 | int create_full_ruleset() { | ||
31 | struct landlock_ruleset_attr attr; | ||
32 | attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR | LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM | LANDLOCK_ACCESS_FS_EXECUTE; | ||
33 | return landlock_create_ruleset(&attr,sizeof(attr),0); | ||
34 | } | ||
35 | |||
36 | int add_read_access_rule(int rset_fd,int allowed_fd) { | ||
37 | int result; | ||
38 | struct landlock_path_beneath_attr target; | ||
39 | target.parent_fd = allowed_fd; | ||
40 | target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR; | ||
41 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
42 | return result; | ||
43 | } | ||
44 | |||
45 | int add_read_access_rule_by_path(int rset_fd,char *allowed_path) { | ||
46 | int result; | ||
47 | int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); | ||
48 | struct landlock_path_beneath_attr target; | ||
49 | target.parent_fd = allowed_fd; | ||
50 | target.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_READ_DIR; | ||
51 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
52 | close(allowed_fd); | ||
53 | return result; | ||
54 | } | ||
55 | |||
56 | int add_write_access_rule(int rset_fd,int allowed_fd,int restricted) { | ||
57 | int result; | ||
58 | struct landlock_path_beneath_attr target; | ||
59 | target.parent_fd = allowed_fd; | ||
60 | if (restricted==0) target.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM; | ||
61 | else if (restricted==1) target.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SYM; | ||
62 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
63 | return result; | ||
64 | } | ||
65 | |||
66 | int add_write_access_rule_by_path(int rset_fd,char *allowed_path,int restricted) { | ||
67 | int result; | ||
68 | int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); | ||
69 | struct landlock_path_beneath_attr target; | ||
70 | target.parent_fd = allowed_fd; | ||
71 | if (restricted==0) target.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SOCK | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_BLOCK | LANDLOCK_ACCESS_FS_MAKE_SYM; | ||
72 | else if (restricted==1) target.allowed_access = LANDLOCK_ACCESS_FS_WRITE_FILE | LANDLOCK_ACCESS_FS_REMOVE_FILE | LANDLOCK_ACCESS_FS_REMOVE_DIR | LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_DIR | LANDLOCK_ACCESS_FS_MAKE_REG | LANDLOCK_ACCESS_FS_MAKE_SYM; | ||
73 | else { | ||
74 | close(allowed_fd); | ||
75 | return -1; | ||
76 | } | ||
77 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
78 | close(allowed_fd); | ||
79 | return result; | ||
80 | } | ||
81 | |||
82 | int add_execute_rule(int rset_fd,int allowed_fd) { | ||
83 | int result; | ||
84 | struct landlock_path_beneath_attr target; | ||
85 | target.parent_fd = allowed_fd; | ||
86 | target.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE; | ||
87 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
88 | return result; | ||
89 | } | ||
90 | |||
91 | int add_execute_rule_by_path(int rset_fd,char *allowed_path) { | ||
92 | int result; | ||
93 | int allowed_fd = open(allowed_path,O_PATH | O_CLOEXEC); | ||
94 | struct landlock_path_beneath_attr target; | ||
95 | target.parent_fd = allowed_fd; | ||
96 | target.allowed_access = LANDLOCK_ACCESS_FS_EXECUTE; | ||
97 | result = landlock_add_rule(rset_fd,LANDLOCK_RULE_PATH_BENEATH,&target,0); | ||
98 | close(allowed_fd); | ||
99 | return result; | ||
100 | } | ||
101 | |||
102 | int check_nnp() { | ||
103 | return prctl(PR_GET_NO_NEW_PRIVS,0,0,0,0); | ||
104 | } | ||
105 | |||
106 | int enable_nnp() { | ||
107 | return prctl(PR_SET_NO_NEW_PRIVS,1,0,0,0); | ||
108 | } | ||
diff --git a/src/man/firejail-profile.txt b/src/man/firejail-profile.txt index 138aae8af..6e75aceed 100644 --- a/src/man/firejail-profile.txt +++ b/src/man/firejail-profile.txt | |||
@@ -497,6 +497,27 @@ Blacklist all Linux capabilities. | |||
497 | .TP | 497 | .TP |
498 | \fBcaps.keep capability,capability,capability | 498 | \fBcaps.keep capability,capability,capability |
499 | Whitelist given Linux capabilities. | 499 | Whitelist given Linux capabilities. |
500 | #ifdef HAVE_LANDLOCK | ||
501 | .TP | ||
502 | \fBlandlock-read path | ||
503 | Create a Landlock ruleset (if it doesn't already exist) and add a read access rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
504 | .br | ||
505 | |||
506 | .TP | ||
507 | \fBlandlock-write path | ||
508 | Create a Landlock ruleset (if it doesn't already exist) and add a write access rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
509 | .br | ||
510 | |||
511 | .TP | ||
512 | \fBlandlock-restricted-write path | ||
513 | Create a Landlock ruleset (if it doesn't already exist) and add a write access rule for path. This type of write access doesn't include the permission to create Unix domain sockets, FIFO pipes and block devices. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
514 | .br | ||
515 | |||
516 | .TP | ||
517 | \fBlandlock-execute path | ||
518 | Create a Landlock ruleset (if it doesn't already exist) and add an execution permission rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
519 | .br | ||
520 | #endif | ||
500 | .TP | 521 | .TP |
501 | \fBmemory-deny-write-execute | 522 | \fBmemory-deny-write-execute |
502 | Install a seccomp filter to block attempts to create memory mappings | 523 | Install a seccomp filter to block attempts to create memory mappings |
diff --git a/src/man/firejail.txt b/src/man/firejail.txt index 2d8adb0b7..7082fe0ab 100644 --- a/src/man/firejail.txt +++ b/src/man/firejail.txt | |||
@@ -1144,6 +1144,33 @@ Example: | |||
1144 | .br | 1144 | .br |
1145 | $ firejail --keep-var-tmp | 1145 | $ firejail --keep-var-tmp |
1146 | 1146 | ||
1147 | #ifdef HAVE_LANDLOCK | ||
1148 | .TP | ||
1149 | \fB\-\-landlock-read=path | ||
1150 | Create a Landlock ruleset (if it doesn't already exist) and add a read access rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
1151 | .br | ||
1152 | |||
1153 | .TP | ||
1154 | \fB\-\-landlock-write=path | ||
1155 | Create a Landlock ruleset (if it doesn't already exist) and add a write access rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
1156 | .br | ||
1157 | |||
1158 | .TP | ||
1159 | \fB\-\-landlock-restricted-write=path | ||
1160 | Create a Landlock ruleset (if it doesn't already exist) and add a write access rule for path. This type of write access doesn't include the permission to create Unix domain sockets, FIFO pipes and block devices. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
1161 | .br | ||
1162 | |||
1163 | .TP | ||
1164 | \fB\-\-landlock-execute=path | ||
1165 | Create a Landlock ruleset (if it doesn't already exist) and add an execution permission rule for path. Note: if a process doesn't have CAP_SYS_ADMIN and the "No New Privileges" restriction is not enabled, the Landlock self-restriction will fail and Firejail will exit with an error. | ||
1166 | .br | ||
1167 | |||
1168 | .br | ||
1169 | Example: | ||
1170 | .br | ||
1171 | $ firejail \-\-landlock-read=/ \-\-landlock-restricted-write=/home \-\-landlock-execute=/usr | ||
1172 | #endif | ||
1173 | |||
1147 | .TP | 1174 | .TP |
1148 | \fB\-\-list | 1175 | \fB\-\-list |
1149 | List all sandboxes, see \fBMONITORING\fR section for more details. | 1176 | List all sandboxes, see \fBMONITORING\fR section for more details. |
@@ -1261,6 +1288,7 @@ $ firejail --list | |||
1261 | .br | 1288 | .br |
1262 | 1312:netblue:browser-1312:firejail --name=browser --private firefox --no-remote | 1289 | 1312:netblue:browser-1312:firejail --name=browser --private firefox --no-remote |
1263 | .br | 1290 | .br |
1291 | |||
1264 | #ifdef HAVE_NETWORK | 1292 | #ifdef HAVE_NETWORK |
1265 | .TP | 1293 | .TP |
1266 | \fB\-\-net=bridge_interface | 1294 | \fB\-\-net=bridge_interface |
diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index 2b67c2a00..661929db9 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in | |||
@@ -105,6 +105,10 @@ _firejail_args=( | |||
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 | '--landlock-read=-[Landlock read access rule]: :_files' | ||
109 | '--landlock-write=-[Landlock write access rule]: :_files' | ||
110 | '--landlock-restricted-write=-[Landlock write access rule that doesn't include creation of FIFO pipes, sockets and block devices]: :_files' | ||
111 | '--landlock-execute=-[Landlock execution-permitting rule]: :_files' | ||
108 | '--machine-id[spoof /etc/machine-id with a random id]' | 112 | '--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]' | 113 | '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' |
110 | '*--mkdir=-[create a directory]:' | 114 | '*--mkdir=-[create a directory]:' |