From 0485cbed05c024c36020c8405bc0b0eb4e59f460 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Thu, 1 Feb 2024 23:21:26 -0300 Subject: [PATCH] landlock: move char/block devices into landlock.dev As discussed with @topimiettinen[1], it is unlikely that an unprivileged process would need to directly create block or character devices. So move the permission to create them from `landlock.special` into a new `landlock.dev` command. Misc: The name is based on `nodev` from mount(8), which makes it not interpret block and character devices. Relates to #6078. [1] https://github.com/netblue30/firejail/pull/6078#pullrequestreview-1740569786 --- contrib/syntax/lists/profile_commands_arg1.list | 1 + etc/templates/profile.template | 1 + src/bash_completion/firejail.bash_completion.in | 4 ++++ src/firejail/firejail.h | 5 +++-- src/firejail/landlock.c | 11 +++++++++-- src/firejail/main.c | 2 ++ src/firejail/profile.c | 4 ++++ src/firejail/usage.c | 3 ++- src/man/firejail-profile.5.in | 9 +++++++-- src/man/firejail.1.in | 9 +++++++-- src/zsh_completion/_firejail.in | 3 ++- 11 files changed, 42 insertions(+), 10 deletions(-) diff --git a/contrib/syntax/lists/profile_commands_arg1.list b/contrib/syntax/lists/profile_commands_arg1.list index e76b6ef40b9..f1b8e74a8ad 100644 --- a/contrib/syntax/lists/profile_commands_arg1.list +++ b/contrib/syntax/lists/profile_commands_arg1.list @@ -29,6 +29,7 @@ ip6 iprange join-or-start keep-fd +landlock.dev landlock.execute landlock.read landlock.special diff --git a/etc/templates/profile.template b/etc/templates/profile.template index 8882c9012bb..9bb83310641 100644 --- a/etc/templates/profile.template +++ b/etc/templates/profile.template @@ -141,6 +141,7 @@ include globals.local ##landlock.read PATH ##landlock.write PATH ##landlock.special PATH +##landlock.dev PATH ##landlock.execute PATH #include landlock-common.inc diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in index 76667ca0cab..c94afaddb81 100644 --- a/src/bash_completion/firejail.bash_completion.in +++ b/src/bash_completion/firejail.bash_completion.in @@ -57,6 +57,10 @@ _firejail() _filedir return 0 ;; + --landlock.dev) + _filedir + return 0 + ;; --landlock.execute) _filedir return 0 diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index eb9287f2ef9..10ce8e16bd9 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -155,8 +155,9 @@ typedef struct landlock_entry_t { #define LL_READ 0 #define LL_WRITE 1 #define LL_SPECIAL 2 -#define LL_EXEC 3 -#define LL_MAX 4 +#define LL_DEV 3 +#define LL_EXEC 4 +#define LL_MAX 5 int type; char *data; } LandlockEntry; diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index 77149a13426..de16a70b601 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -196,14 +196,20 @@ static void ll_write(const char *allowed_path) { static void ll_special(const char *allowed_path) { __u64 allowed_access = - LANDLOCK_ACCESS_FS_MAKE_BLOCK | - LANDLOCK_ACCESS_FS_MAKE_CHAR | LANDLOCK_ACCESS_FS_MAKE_FIFO | LANDLOCK_ACCESS_FS_MAKE_SOCK; ll_fs(allowed_path, allowed_access, __func__); } +static void ll_dev(const char *allowed_path) { + __u64 allowed_access = + LANDLOCK_ACCESS_FS_MAKE_BLOCK | + LANDLOCK_ACCESS_FS_MAKE_CHAR; + + ll_fs(allowed_path, allowed_access, __func__); +} + static void ll_exec(const char *allowed_path) { __u64 allowed_access = LANDLOCK_ACCESS_FS_EXECUTE; @@ -224,6 +230,7 @@ int ll_restrict(uint32_t flags) { ll_read, ll_write, ll_special, + ll_dev, ll_exec, NULL }; diff --git a/src/firejail/main.c b/src/firejail/main.c index 341bac058b0..1cad3a3682e 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -1511,6 +1511,8 @@ int main(int argc, char **argv, char **envp) { ll_add_profile(LL_WRITE, argv[i] + 17); else if (strncmp(argv[i], "--landlock.special=", 19) == 0) ll_add_profile(LL_SPECIAL, argv[i] + 19); + else if (strncmp(argv[i], "--landlock.dev=", 15) == 0) + ll_add_profile(LL_DEV, argv[i] + 15); else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) ll_add_profile(LL_EXEC, argv[i] + 19); #endif diff --git a/src/firejail/profile.c b/src/firejail/profile.c index c0abc339815..2e9f5017983 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1090,6 +1090,10 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { ll_add_profile(LL_SPECIAL, ptr + 17); return 0; } + if (strncmp(ptr, "landlock.dev ", 13) == 0) { + ll_add_profile(LL_DEV, ptr + 13); + return 0; + } if (strncmp(ptr, "landlock.execute ", 17) == 0) { ll_add_profile(LL_EXEC, ptr + 17); return 0; diff --git a/src/firejail/usage.c b/src/firejail/usage.c index 8598abd9d24..e6f765f4d76 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -137,7 +137,8 @@ static const char *const usage_str = " --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" + " --landlock.special=path - add an access rule for the path to the Landlock ruleset for creating named pipes and sockets.\n" + " --landlock.dev=path - add an access rule for the path to the Landlock ruleset for creating block/char devices.\n" " --landlock.execute=path - add an execute access rule for the path to the Landlock ruleset.\n" #endif " --list - list all sandboxes.\n" diff --git a/src/man/firejail-profile.5.in b/src/man/firejail-profile.5.in index e1d7fde9432..f25912b0d3e 100644 --- a/src/man/firejail-profile.5.in +++ b/src/man/firejail-profile.5.in @@ -524,8 +524,13 @@ rule for path. .TP \fBlandlock.special path Create a Landlock ruleset (if it doesn't already exist) and add a rule that -allows the creation of block devices, character devices, named pipes (FIFOs) -and Unix domain sockets beneath given path. +allows the creation of named pipes (FIFOs) and Unix domain sockets beneath +the given path. +.TP +\fBlandlock.dev path +Create a Landlock ruleset (if it doesn't already exist) and add a rule that +allows the creation of block devices and character devices beneath the given +path. .TP \fBlandlock.execute path Create a Landlock ruleset (if it doesn't already exist) and add an execution diff --git a/src/man/firejail.1.in b/src/man/firejail.1.in index ccc9a50a561..bb08844e948 100644 --- a/src/man/firejail.1.in +++ b/src/man/firejail.1.in @@ -1251,8 +1251,13 @@ rule for path. .TP \fB\-\-landlock.special=path Create a Landlock ruleset (if it doesn't already exist) and add a rule that -allows the creation of block devices, character devices, named pipes (FIFOs) -and Unix domain sockets beneath given path. +allows the creation of named pipes (FIFOs) and Unix domain sockets beneath +the given path. +.TP +\fB\-\-landlock.dev=path +Create a Landlock ruleset (if it doesn't already exist) and add a rule that +allows the creation of block devices and character devices beneath the given +path. .TP \fB\-\-landlock.execute=path Create a Landlock ruleset (if it doesn't already exist) and add an execution diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index c4056b902e9..02eecff2734 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in @@ -110,7 +110,8 @@ _firejail_args=( '--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' + '--landlock.special=-[add an access rule for the path to the Landlock ruleset for creating named pipes and sockets]: :_files' + '--landlock.dev=-[add an access rule for the path to the Landlock ruleset for creating block/char devices]: :_files' '--landlock.execute=-[add an execute access rule for the path to the Landlock ruleset]: :_files' #endif '--machine-id[spoof /etc/machine-id with a random id]'