aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorLibravatar Азалия Смарагдова <charming.flurry@yandex.ru>2022-08-15 12:19:11 +0500
committerLibravatar Азалия Смарагдова <charming.flurry@yandex.ru>2022-08-15 13:32:24 +0500
commit61b15442898eeb1db2d23b6b2eb72a705ceb368a (patch)
tree6d9cb22307941a81f4562dbfd0c00e7b2e96dbcd
parentmore merges (diff)
downloadfirejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.tar.gz
firejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.tar.zst
firejail-61b15442898eeb1db2d23b6b2eb72a705ceb368a.zip
Landlock support has been added.
-rw-r--r--config.mk.in3
-rwxr-xr-xconfigure16
-rw-r--r--configure.ac10
-rw-r--r--contrib/vim/syntax/firejail.vim2
-rw-r--r--src/bash_completion/firejail.bash_completion.in16
-rw-r--r--src/firejail/firejail.h3
-rw-r--r--src/firejail/main.c33
-rw-r--r--src/firejail/profile.c35
-rw-r--r--src/firejail/sandbox.c13
-rw-r--r--src/firejail/usage.c4
-rw-r--r--src/include/tinyLL.h23
-rw-r--r--src/lib/libtinyll.c108
-rw-r--r--src/man/firejail-profile.txt21
-rw-r--r--src/man/firejail.txt28
-rw-r--r--src/zsh_completion/_firejail.in4
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@
41HAVE_IDS=@HAVE_IDS@ 41HAVE_IDS=@HAVE_IDS@
42HAVE_GCOV=@HAVE_GCOV@ 42HAVE_GCOV=@HAVE_GCOV@
43HAVE_SELINUX=@HAVE_SELINUX@ 43HAVE_SELINUX=@HAVE_SELINUX@
44HAVE_LANDLOCK=@HAVE_LANDLOCK@
44HAVE_SUID=@HAVE_SUID@ 45HAVE_SUID=@HAVE_SUID@
45HAVE_DBUSPROXY=@HAVE_DBUSPROXY@ 46HAVE_DBUSPROXY=@HAVE_DBUSPROXY@
46HAVE_USERTMPFS=@HAVE_USERTMPFS@ 47HAVE_USERTMPFS=@HAVE_USERTMPFS@
@@ -49,7 +50,7 @@ HAVE_LTS=@HAVE_LTS@
49HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@ 50HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@
50HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@ 51HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@
51 52
52MANFLAGS = $(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) 53MANFLAGS = $(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
54CC=@CC@ 55CC=@CC@
55CFLAGS=@CFLAGS@ 56CFLAGS=@CFLAGS@
diff --git a/configure b/configure
index f3bd77169..7a40e47b4 100755
--- a/configure
+++ b/configure
@@ -652,6 +652,7 @@ HAVE_DBUSPROXY
652EXTRA_LDFLAGS 652EXTRA_LDFLAGS
653EXTRA_CFLAGS 653EXTRA_CFLAGS
654HAVE_SELINUX 654HAVE_SELINUX
655HAVE_LANDLOCK
655AA_LIBS 656AA_LIBS
656AA_CFLAGS 657AA_CFLAGS
657PKG_CONFIG_LIBDIR 658PKG_CONFIG_LIBDIR
@@ -713,6 +714,7 @@ enable_sanitizer
713enable_ids 714enable_ids
714enable_apparmor 715enable_apparmor
715enable_selinux 716enable_selinux
717enable_landlock
716enable_dbusproxy 718enable_dbusproxy
717enable_output 719enable_output
718enable_usertmpfs 720enable_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
3343fi 3346fi
3344 3347
3348HAVE_LANDLOCK=""
3345 3349
3350# Check whether --enable-landlock was given.
3351if test "${enable_landlock+set}" = set; then :
3352 enableval=$enable_landlock;
3353fi
3354
3355if test "x$enable_landlock" = "xyes"; then :
3356
3357 HAVE_LANDLOCK="-DHAVE_LANDLOCK"
3358 EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ltinyll"
3359
3360fi
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
84HAVE_LANDLOCK=""
85AC_SUBST([HAVE_LANDLOCK])
86AC_ARG_ENABLE([landlock])
87 [AS_HELP_STRING([--enable-landlock], [Landlock self-restriction support])]
88AS_IF([test "x$enable_landlock" = "xyes"], [
89 HAVE_LANDLOCK="-DHAVE_LANDLOCK"
90 EXTRA_LDFLAGS="$EXTRA_LDFLAGS -ltinyll"
91])
92
84AC_SUBST([EXTRA_CFLAGS]) 93AC_SUBST([EXTRA_CFLAGS])
85AC_SUBST([EXTRA_LDFLAGS]) 94AC_SUBST([EXTRA_LDFLAGS])
86 95
87
88HAVE_DBUSPROXY="" 96HAVE_DBUSPROXY=""
89AC_SUBST([HAVE_DBUSPROXY]) 97AC_SUBST([HAVE_DBUSPROXY])
90AC_ARG_ENABLE([dbusproxy], 98AC_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)
55syn 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 55syn 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
57syn 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 57syn 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
58syn match fjCommand /ignore / nextgroup=fjCommand,fjCommandNoCond skipwhite contained 58syn 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
286extern int arg_seccomp_postexec; // need postexec ld.preload library? 287extern int arg_seccomp_postexec; // need postexec ld.preload library?
287extern int arg_seccomp_block_secondary; // block any secondary architectures 288extern int arg_seccomp_block_secondary; // block any secondary architectures
288 289
290extern int arg_landlock; // Landlock ruleset file descriptor
291
289extern int arg_caps_default_filter; // enable default capabilities filter 292extern int arg_caps_default_filter; // enable default capabilities filter
290extern int arg_caps_drop; // drop list 293extern int arg_caps_drop; // drop list
291extern int arg_caps_drop_all; // drop all capabilities 294extern 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?
81int arg_seccomp_block_secondary = 0; // block any secondary architectures 84int arg_seccomp_block_secondary = 0; // block any secondary architectures
82int arg_seccomp_error_action = 0; 85int arg_seccomp_error_action = 0;
83 86
87#ifdef HAVE_LANDLOCK
88int arg_landlock = -1; // Landlock ruleset file descriptor (-1 if it doesn't exist)
89#endif
90
84int arg_caps_default_filter = 0; // enable default capabilities filter 91int arg_caps_default_filter = 0; // enable default capabilities filter
85int arg_caps_drop = 0; // drop list 92int arg_caps_drop = 0; // drop list
86int arg_caps_drop_all = 0; // drop all capabilities 93int 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 @@
1extern int landlock_create_ruleset(struct landlock_ruleset_attr *rsattr,size_t size,__u32 flags);
2
3extern int landlock_add_rule(int fd,enum landlock_rule_type t,void *attr,__u32 flags);
4
5extern int landlock_restrict_self(int fd,__u32 flags);
6
7extern int create_full_ruleset();
8
9extern int add_read_access_rule(int rset_fd,int allowed_fd);
10
11extern int add_read_access_rule_by_path(int rset_fd,char *allowed_path);
12
13extern int add_write_access_rule(int rset_fd,int allowed_fd,int restricted);
14
15extern int add_write_access_rule_by_path(int rset_fd,char *allowed_path,int restricted);
16
17extern int add_execute_rule(int rset_fd,int allowed_fd);
18
19extern int add_execute_rule_by_path(int rset_fd,char *allowed_path);
20
21extern int check_nnp();
22
23extern 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
13int 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
17int 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
21int 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
30int 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
36int 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
45int 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
56int 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
66int 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
82int 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
91int 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
102int check_nnp() {
103 return prctl(PR_GET_NO_NEW_PRIVS,0,0,0,0);
104}
105
106int 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
499Whitelist given Linux capabilities. 499Whitelist given Linux capabilities.
500#ifdef HAVE_LANDLOCK
501.TP
502\fBlandlock-read path
503Create 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
508Create 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
513Create 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
518Create 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
502Install a seccomp filter to block attempts to create memory mappings 523Install 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
1150Create 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
1155Create 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
1160Create 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
1165Create 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
1169Example:
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
1149List all sandboxes, see \fBMONITORING\fR section for more details. 1176List all sandboxes, see \fBMONITORING\fR section for more details.
@@ -1261,6 +1288,7 @@ $ firejail --list
1261.br 1288.br
12621312:netblue:browser-1312:firejail --name=browser --private firefox --no-remote 12891312: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]:'