From 760f50f78ad13664d7a32b4577381c0341ab2d4a Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Fri, 17 Nov 2023 19:57:29 -0300 Subject: landlock: move commands into profile and add landlock.enforce Changes: * Move commands from --landlock and --landlock.proc= into etc/inc/landlock-common.inc * Remove --landlock and --landlock.proc= * Add --landlock.enforce Instead of hard-coding the default commands (and having a separate command just for /proc), move them into a dedicated profile to make it easier for users to interact with the entries (view, copy, add ignore entries, etc). Only enforce the Landlock commands if --landlock.enforce is supplied. This allows safely adding Landlock commands to (upstream) profiles while keeping their enforcement opt-in. It also makes it simpler to effectively disable all Landlock commands, by using `--ignore=landlock.enforce`. Relates to #6078. --- contrib/syntax/lists/profile_commands_arg0.list | 2 +- contrib/syntax/lists/profile_commands_arg1.list | 1 - etc/inc/landlock-common.inc | 39 +++++++++++++++++++ etc/profile-a-l/default.profile | 2 + etc/templates/profile.template | 7 ++++ src/bash_completion/firejail.bash_completion.in | 2 +- src/firejail/firejail.h | 4 +- src/firejail/landlock.c | 50 ------------------------- src/firejail/main.c | 20 ++-------- src/firejail/profile.c | 21 ++--------- src/firejail/sandbox.c | 15 ++------ src/firejail/usage.c | 3 +- src/man/firejail-profile.5.in | 15 ++------ src/man/firejail.1.in | 41 ++++++-------------- src/zsh_completion/_firejail.in | 3 +- 15 files changed, 79 insertions(+), 146 deletions(-) create mode 100644 etc/inc/landlock-common.inc diff --git a/contrib/syntax/lists/profile_commands_arg0.list b/contrib/syntax/lists/profile_commands_arg0.list index 4d49e96d9..0ac70e5cf 100644 --- a/contrib/syntax/lists/profile_commands_arg0.list +++ b/contrib/syntax/lists/profile_commands_arg0.list @@ -12,7 +12,7 @@ keep-config-pulse keep-dev-shm keep-shell-rc keep-var-tmp -landlock +landlock.enforce machine-id memory-deny-write-execute netfilter diff --git a/contrib/syntax/lists/profile_commands_arg1.list b/contrib/syntax/lists/profile_commands_arg1.list index cce37efa0..e76b6ef40 100644 --- a/contrib/syntax/lists/profile_commands_arg1.list +++ b/contrib/syntax/lists/profile_commands_arg1.list @@ -30,7 +30,6 @@ iprange join-or-start keep-fd landlock.execute -landlock.proc landlock.read landlock.special landlock.write diff --git a/etc/inc/landlock-common.inc b/etc/inc/landlock-common.inc new file mode 100644 index 000000000..ebe9f98dc --- /dev/null +++ b/etc/inc/landlock-common.inc @@ -0,0 +1,39 @@ +# This file is overwritten during software install. +# Persistent customizations should go in a .local file. +include landlock-common.local + +landlock.read / # whole system read +landlock.read /proc +landlock.special / # sockets etc. + +# write access +landlock.write ${HOME} +landlock.write ${RUNUSER} +landlock.write /dev +landlock.write /proc +landlock.write /run/shm +landlock.write /tmp + +# exec access +## misc +landlock.execute /opt +landlock.execute /run/firejail # appimage and various firejail features +## bin +landlock.execute /bin +landlock.execute /sbin +landlock.execute /usr/bin +landlock.execute /usr/sbin +landlock.execute /usr/games +landlock.execute /usr/local/bin +landlock.execute /usr/local/sbin +landlock.execute /usr/local/games +## lib +landlock.execute /lib +landlock.execute /lib32 +landlock.execute /libx32 +landlock.execute /lib64 +landlock.execute /usr/lib +landlock.execute /usr/lib32 +landlock.execute /usr/libx32 +landlock.execute /usr/lib64 +landlock.execute /usr/local/lib diff --git a/etc/profile-a-l/default.profile b/etc/profile-a-l/default.profile index c071da4b7..b0ae2d49f 100644 --- a/etc/profile-a-l/default.profile +++ b/etc/profile-a-l/default.profile @@ -22,6 +22,8 @@ include disable-programs.inc #include whitelist-usr-share-common.inc #include whitelist-var-common.inc +include landlock-common.inc + #apparmor caps.drop all #ipc-namespace diff --git a/etc/templates/profile.template b/etc/templates/profile.template index 6299d42cd..8882c9012 100644 --- a/etc/templates/profile.template +++ b/etc/templates/profile.template @@ -137,6 +137,13 @@ include globals.local #include whitelist-usr-share-common.inc #include whitelist-var-common.inc +# Landlock commands +##landlock.read PATH +##landlock.write PATH +##landlock.special PATH +##landlock.execute PATH +#include landlock-common.inc + ##allusers #apparmor #caps.drop all diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in index eab0f7df6..76667ca0c 100644 --- a/src/bash_completion/firejail.bash_completion.in +++ b/src/bash_completion/firejail.bash_completion.in @@ -42,7 +42,7 @@ _firejail() _filedir -d return 0 ;; - --landlock) + --landlock.enforce) return 0 ;; --landlock.read) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index d0b903fb4..95b25b658 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -293,8 +293,7 @@ extern int arg_overlay; // overlay option extern int arg_overlay_keep; // place overlay diff in a known directory extern int arg_overlay_reuse; // allow the reuse of overlays -extern int arg_landlock; // add basic Landlock rules -extern int arg_landlock_proc; // 0 - no access; 1 -read-only; 2 - read-write +extern int arg_landlock_enforce; // enforce the Landlock ruleset extern int arg_seccomp; // enable default seccomp filter extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch @@ -973,7 +972,6 @@ int ll_read(const char *allowed_path); int ll_write(const char *allowed_path); int ll_special(const char *allowed_path); int ll_exec(const char *allowed_path); -int ll_basic_system(void); int ll_restrict(uint32_t flags); void ll_add_profile(int type, const char *data); #endif /* HAVE_LANDLOCK */ diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index e93bde402..11de2e297 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -202,56 +202,6 @@ int ll_exec(const char *allowed_path) { return ll_fs(allowed_path, allowed_access, __func__); } -int ll_basic_system(void) { - if (!ll_is_supported()) - return 0; - - if (ll_ruleset_fd == -1) - ll_ruleset_fd = ll_create_full_ruleset(); - - int error = - ll_read("/") || // whole system read - ll_special("/") || // sockets etc. - - // write access - ll_write("${HOME}") || - ll_write("${RUNUSER}") || - ll_write("/dev") || - ll_write("/run/shm") || - ll_write("/tmp") || - - // exec access - /// misc - ll_exec("/opt") || - ll_exec("/run/firejail") || // appimage and various firejail features - /// bin - ll_exec("/bin") || - ll_exec("/sbin") || - ll_exec("/usr/bin") || - ll_exec("/usr/sbin") || - ll_exec("/usr/games") || - ll_exec("/usr/local/bin") || - ll_exec("/usr/local/sbin") || - ll_exec("/usr/local/games") || - /// lib - ll_exec("/lib") || - ll_exec("/lib32") || - ll_exec("/libx32") || - ll_exec("/lib64") || - ll_exec("/usr/lib") || - ll_exec("/usr/lib32") || - ll_exec("/usr/libx32") || - ll_exec("/usr/lib64") || - ll_exec("/usr/local/lib"); - - if (error) { - fprintf(stderr, "Error: %s: failed to set --landlock rules\n", - __func__); - } - - return error; -} - int ll_restrict(uint32_t flags) { if (!ll_is_supported()) return 0; diff --git a/src/firejail/main.c b/src/firejail/main.c index 5bcc3a0e5..aaa7c8a2f 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -75,8 +75,7 @@ int arg_overlay = 0; // overlay option int arg_overlay_keep = 0; // place overlay diff in a known directory int arg_overlay_reuse = 0; // allow the reuse of overlays -int arg_landlock = 0; // add basic Landlock rules -int arg_landlock_proc = 2; // 0 - no access; 1 -read-only; 2 - read-write +int arg_landlock_enforce = 0; // enforce the Landlock ruleset int arg_seccomp = 0; // enable default seccomp filter int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch @@ -1504,21 +1503,8 @@ int main(int argc, char **argv, char **envp) { exit_err_feature("seccomp"); } #ifdef HAVE_LANDLOCK - else if (strcmp(argv[i], "--landlock") == 0) - arg_landlock = 1; - else if (strncmp(argv[i], "--landlock.proc=", 16) == 0) { - if (strncmp(argv[i] + 16, "no", 2) == 0) - arg_landlock_proc = 0; - else if (strncmp(argv[i] + 16, "ro", 2) == 0) - arg_landlock_proc = 1; - else if (strncmp(argv[i] + 16, "rw", 2) == 0) - arg_landlock_proc = 2; - else { - fprintf(stderr, "Error: invalid landlock.proc value: %s\n", - argv[i] + 16); - exit(1); - } - } + else if (strncmp(argv[i], "--landlock.enforce", 18) == 0) + arg_landlock_enforce = 1; else if (strncmp(argv[i], "--landlock.read=", 16) == 0) ll_add_profile(LL_READ, argv[i] + 16); else if (strncmp(argv[i], "--landlock.write=", 17) == 0) diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 62d3c78e7..ddcaa5382 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1074,24 +1074,9 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { } #ifdef HAVE_LANDLOCK - // Landlock ruleset paths - if (strcmp(ptr, "landlock") == 0) { - arg_landlock = 1; - return 0; - } - if (strncmp(ptr, "landlock.proc ", 14) == 0) { - if (strncmp(ptr + 14, "no", 2) == 0) - arg_landlock_proc = 0; - else if (strncmp(ptr + 14, "ro", 2) == 0) - arg_landlock_proc = 1; - else if (strncmp(ptr + 14, "rw", 2) == 0) - arg_landlock_proc = 2; - else { - fprintf(stderr, "Error: invalid landlock.proc value: %s\n", - ptr + 14); - exit(1); - } - return 0; + if (strncmp(ptr, "landlock.enforce", 16) == 0) { + arg_landlock_enforce = 1; + return 0; } if (strncmp(ptr, "landlock.read ", 14) == 0) { ll_add_profile(LL_READ, ptr + 14); diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index dbc115137..516f1187e 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -520,21 +520,14 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { //**************************** // Configure Landlock //**************************** - if (arg_landlock) - ll_basic_system(); - - if (ll_get_fd() != -1) { - if (arg_landlock_proc >= 1) - ll_read("/proc/"); - if (arg_landlock_proc == 2) - ll_write("/proc/"); - } - - if (ll_restrict(0)) { + if (arg_landlock_enforce && ll_restrict(0)) { // It isn't safe to continue if Landlock self-restriction was // enabled and the "landlock_restrict_self" syscall has failed. fprintf(stderr, "Error: ll_restrict() failed, exiting...\n"); exit(1); + } else { + if (arg_debug) + fprintf(stderr, "Not enforcing Landlock\n"); } #endif diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 5f9185da9..f0f148900 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -134,8 +134,7 @@ static const char *const usage_str = " --keep-shell-rc - do not copy shell rc files from /etc/skel\n" " --keep-var-tmp - /var/tmp directory is untouched.\n" #ifdef HAVE_LANDLOCK - " --landlock - add basic rules to the Landlock ruleset.\n" - " --landlock.proc=no|ro|rw - add an access rule for /proc to the Landlock ruleset.\n" + " --landlock.enforce - enforce the Landlock ruleset.\n" " --landlock.read=path - add a read access rule for the path to the Landlock ruleset.\n" " --landlock.write=path - add a write access rule for the path to the Landlock ruleset.\n" " --landlock.special=path - add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets.\n" diff --git a/src/man/firejail-profile.5.in b/src/man/firejail-profile.5.in index 76f5e4d20..e1d7fde94 100644 --- a/src/man/firejail-profile.5.in +++ b/src/man/firejail-profile.5.in @@ -509,17 +509,10 @@ Blacklist all Linux capabilities. Whitelist given Linux capabilities. #ifdef HAVE_LANDLOCK .TP -\fBlandlock -Create a Landlock ruleset (if it doesn't already exist) and add basic access -rules to it. -.TP -\fBlandlock.proc no|ro|rw -Add an access rule for /proc directory (read-only if set to \fBro\fR and -read-write if set to \fBrw\fR). -The access rule for /proc is added after this directory is set up in the -sandbox. -Access rules for /proc set up with other Landlock-related profile options have -no effect. +\fBlandlock.enforce +Enforce the Landlock ruleset. +.PP +Without it, the other Landlock commands have no effect. .TP \fBlandlock.read path Create a Landlock ruleset (if it doesn't already exist) and add a read access diff --git a/src/man/firejail.1.in b/src/man/firejail.1.in index 39f12b005..c63cf350d 100644 --- a/src/man/firejail.1.in +++ b/src/man/firejail.1.in @@ -1245,31 +1245,15 @@ $ firejail --keep-var-tmp #ifdef HAVE_LANDLOCK .TP -\fB\-\-landlock -Create a Landlock ruleset (if it doesn't already exist) and add basic access -rules to it. -The basic set of rules applies the following access permissions: +\fB\-\-landlock.enforce +Enforce the Landlock ruleset. .PP -.RS -- read: /bin, /dev, /etc, /lib, /opt, /proc, /usr, /var -.br -- write: /dev, /proc -.br -- exec: /bin, /lib, /opt, /usr -.RE +Without it, the other Landlock commands have no effect. .PP .RS See the \fBLANDLOCK\fR section for more information. .RE .TP -\fB\-\-landlock.proc=no|ro|rw -Add an access rule for /proc directory (read-only if set to \fBro\fR and -read-write if set to \fBrw\fR). -The access rule for /proc is added after this directory is set up in the -sandbox. -Access rules for /proc set up with other Landlock-related command-line options -have no effect. -.TP \fB\-\-landlock.read=path Create a Landlock ruleset (if it doesn't already exist) and add a read access rule for path. @@ -1291,7 +1275,9 @@ permission rule for path. .br Example: .br -$ firejail \-\-landlock.read=/ \-\-landlock.write=/home \-\-landlock.execute=/usr +$ firejail \-\-landlock.read=/ \-\-landlock.write=/home +\-\-landlock.execute=/usr \-\-landlock.enforce +.PP #endif .TP \fB\-\-list @@ -3426,7 +3412,7 @@ Firejail supports Landlock as an additional sandboxing feature. It can be used to ensure that a sandboxed application can only access files and directories that it was explicitly allowed to access. Firejail supports populating the ruleset with both a basic set of rules (see -\fB\-\-landlock\fR) and with a custom set of rules. +landlock-common.inc) and with a custom set of rules. .TP Important notes: .PP @@ -3438,9 +3424,6 @@ Because of this, enabling the Landlock feature will also cause Firejail to enable the "No New Privileges" restriction, regardless of the profile or the \fB\-\-nonewprivs\fR command line option. .PP -- Access to the /proc directory is managed through the \fB\-\-landlock.proc\fR -command line option. -.PP - Access to the /etc directory is automatically allowed. To override this, use the \fB\-\-writable\-etc\fR command line option. You can also use the \fB\-\-private\-etc\fR option to restrict access to the @@ -3448,13 +3431,13 @@ You can also use the \fB\-\-private\-etc\fR option to restrict access to the .RE .PP To enable Landlock self-restriction on top of your current Firejail security -features, pass \fB\-\-landlock\fR flag to Firejail command line. -You can also use \fB\-\-landlock.read\fR, \fB\-\-landlock.write\fR, -\fB\-\-landlock.special\fR and \fB\-\-landlock.execute\fR options together with -\fB\-\-landlock\fR or instead of it. +features, pass \fB\-\-landlock.enforce\fR flag to Firejail command line. +Without it, the other Landlock commands have no effect. Example: .PP -$ firejail \-\-landlock \-\-landlock.read=/media \-\-landlock.proc=ro mc +$ firejail \-\-landlock.enforce \-\-landlock.read=/media mc +.PP +To disable Landlock self-restriction, use \fB\-\-ignore=landlock.enforce\fR. #endif .SH DESKTOP INTEGRATION A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index ac0554bc5..bea5df2be 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in @@ -107,8 +107,7 @@ _firejail_args=( '--keep-shell-rc[do not copy shell rc files from /etc/skel]' '--keep-var-tmp[/var/tmp directory is untouched]' #ifdef HAVE_LANDLOCK - '--landlock[add basic rules to the Landlock ruleset]' - '--landlock.proc=-[add an access rule for /proc to the Landlock ruleset]: :(no ro rw)' + '--landlock.enforce[enforce the Landlock ruleset]' '--landlock.read=-[add a read access rule for the path to the Landlock ruleset]: :_files' '--landlock.write=-[add a write access rule for the path to the Landlock ruleset]: :_files' '--landlock.special=-[add an access rule for the path to the Landlock ruleset for creating block/char devices, named pipes and sockets]: :_files' -- cgit v1.2.3-54-g00ecf