From 5456ec647741ae4b3494f1db8fa40a617ffadcea Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 26 Oct 2023 08:38:24 -0400 Subject: cleanup --- src/firejail/profile.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 8cc5c1166..a250e5611 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1901,8 +1901,7 @@ void profile_read(const char *fname) { fclose(fp); } -char *profile_list_normalize(char *list) -{ +char *profile_list_normalize(char *list) { /* Remove redundant commas. * * As result is always shorter than original, -- cgit v1.2.3-70-g09d2 From 13b2c566df883269b55f77757bb50a5d2890ec20 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Tue, 24 Oct 2023 12:43:46 -0400 Subject: feature: add Landlock support MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Based on 5315 by ChrysoliteAzalea. It is based on the same underlying structure, but with a lot of refactoring/simplification and with bugfixes and improvements. Co-authored-by: Kelvin M. Klann Co-authored-by: Азалия Смарагдова --- README | 3 +- config.mk.in | 2 + configure | 86 +++++--- configure.ac | 12 ++ contrib/syntax/lists/profile_commands_arg0.list | 1 + contrib/syntax/lists/profile_commands_arg1.list | 5 + src/bash_completion/firejail.bash_completion.in | 19 ++ src/firejail/checkcfg.c | 7 + src/firejail/firejail.h | 22 ++ src/firejail/landlock.c | 263 ++++++++++++++++++++++++ src/firejail/main.c | 28 +++ src/firejail/profile.c | 38 ++++ src/firejail/sandbox.c | 22 ++ src/firejail/usage.c | 8 + src/firejail/util.c | 7 + src/man/firejail-profile.5.in | 31 +++ src/man/firejail.1.in | 87 ++++++++ src/zsh_completion/_firejail.in | 5 + 18 files changed, 616 insertions(+), 30 deletions(-) create mode 100644 src/firejail/landlock.c diff --git a/README b/README index 174530cc6..2514cdeeb 100644 --- a/README +++ b/README @@ -197,7 +197,8 @@ avoidr (https://github.com/avoidr) - fixed mpv profile - various other fixes Азалия Смарагдова/ChrysoliteAzalea (https://github.com/ChrysoliteAzalea) - - add support for custom AppArmor profiles (--apparmor=) + - add support for custom AppArmor profiles (--apparmor=) + - add Landlock support backspac (https://github.com/backspac) - firecfg fixes - add steam-runtime alias diff --git a/config.mk.in b/config.mk.in index c76ca1a98..d50c7d2f5 100644 --- a/config.mk.in +++ b/config.mk.in @@ -38,6 +38,7 @@ HAVE_FIRETUNNEL=@HAVE_FIRETUNNEL@ HAVE_FORCE_NONEWPRIVS=@HAVE_FORCE_NONEWPRIVS@ HAVE_GLOBALCFG=@HAVE_GLOBALCFG@ HAVE_IDS=@HAVE_IDS@ +HAVE_LANDLOCK=@HAVE_LANDLOCK@ HAVE_LTS=@HAVE_LTS@ HAVE_NETWORK=@HAVE_NETWORK@ HAVE_ONLY_SYSCFG_PROFILES=@HAVE_ONLY_SYSCFG_PROFILES@ @@ -60,6 +61,7 @@ MANFLAGS = \ $(HAVE_FORCE_NONEWPRIVS) \ $(HAVE_GLOBALCFG) \ $(HAVE_IDS) \ + $(HAVE_LANDLOCK) \ $(HAVE_LTS) \ $(HAVE_NETWORK) \ $(HAVE_ONLY_SYSCFG_PROFILES) \ diff --git a/configure b/configure index 54b9d4da3..8c2d3b894 100755 --- a/configure +++ b/configure @@ -675,6 +675,7 @@ HAVE_OVERLAYFS HAVE_DBUSPROXY EXTRA_LDFLAGS EXTRA_CFLAGS +HAVE_LANDLOCK HAVE_SELINUX AA_LIBS AA_CFLAGS @@ -737,6 +738,7 @@ enable_sanitizer enable_ids enable_apparmor enable_selinux +enable_landlock enable_dbusproxy enable_output enable_usertmpfs @@ -1396,6 +1398,7 @@ Optional Features: --enable-ids enable ids --enable-apparmor enable apparmor --enable-selinux SELinux labeling support + --enable-landlock Landlock self-restriction support --disable-dbusproxy disable dbus proxy --disable-output disable --output logging --disable-usertmpfs disable tmpfs as regular user @@ -3739,6 +3742,58 @@ then : fi +HAVE_LANDLOCK="" + +# Check whether --enable-landlock was given. +if test ${enable_landlock+y} +then : + enableval=$enable_landlock; +fi + +ac_header= ac_cache= +for ac_item in $ac_header_c_list +do + if test $ac_cache; then + ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" + if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then + printf "%s\n" "#define $ac_item 1" >> confdefs.h + fi + ac_header= ac_cache= + elif test $ac_header; then + ac_cache=$ac_item + else + ac_header=$ac_item + fi +done + + + + + + + + +if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes +then : + +printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h + +fi +if test "x$enable_landlock" != "xno" +then : + + ac_fn_c_check_header_compile "$LINENO" "linux/landlock.h" "ac_cv_header_linux_landlock_h" "$ac_includes_default" +if test "x$ac_cv_header_linux_landlock_h" = xyes +then : + HAVE_LANDLOCK="-DHAVE_LANDLOCK" +else $as_nop + { printf "%s\n" "$as_me:${as_lineno-$LINENO}: WARNING: header not found: linux/landlock.h, building without Landlock support" >&5 +printf "%s\n" "$as_me: WARNING: header not found: linux/landlock.h, building without Landlock support" >&2;} +fi + + +fi + @@ -4112,6 +4167,7 @@ if test "x$enable_lts" = "xyes" then : HAVE_LTS="-DHAVE_LTS" + HAVE_LANDLOCK="" HAVE_IDS="" HAVE_DBUSPROXY="" HAVE_OVERLAYFS="" @@ -4132,35 +4188,6 @@ then : fi -ac_header= ac_cache= -for ac_item in $ac_header_c_list -do - if test $ac_cache; then - ac_fn_c_check_header_compile "$LINENO" $ac_header ac_cv_header_$ac_cache "$ac_includes_default" - if eval test \"x\$ac_cv_header_$ac_cache\" = xyes; then - printf "%s\n" "#define $ac_item 1" >> confdefs.h - fi - ac_header= ac_cache= - elif test $ac_header; then - ac_cache=$ac_item - else - ac_header=$ac_item - fi -done - - - - - - - - -if test $ac_cv_header_stdlib_h = yes && test $ac_cv_header_string_h = yes -then : - -printf "%s\n" "#define STDC_HEADERS 1" >>confdefs.h - -fi ac_fn_c_check_header_compile "$LINENO" "linux/seccomp.h" "ac_cv_header_linux_seccomp_h" "$ac_includes_default" if test "x$ac_cv_header_linux_seccomp_h" = xyes then : @@ -5360,6 +5387,7 @@ Features: firetunnel support: $HAVE_FIRETUNNEL global config: $HAVE_GLOBALCFG IDS support: $HAVE_IDS + Landlock support: $HAVE_LANDLOCK LTS: $HAVE_LTS manpage support: $HAVE_MAN network: $HAVE_NETWORK diff --git a/configure.ac b/configure.ac index 93de61b95..bd80150ed 100644 --- a/configure.ac +++ b/configure.ac @@ -81,6 +81,16 @@ AS_IF([test "x$enable_selinux" = "xyes"], [ LIBS="$LIBS -lselinux" ]) +HAVE_LANDLOCK="" +AC_SUBST([HAVE_LANDLOCK]) +AC_ARG_ENABLE([landlock], + [AS_HELP_STRING([--enable-landlock], [Landlock self-restriction support])]) +AS_IF([test "x$enable_landlock" != "xno"], [ + AC_CHECK_HEADER([linux/landlock.h], + [HAVE_LANDLOCK="-DHAVE_LANDLOCK"], + [AC_MSG_WARN([header not found: linux/landlock.h, building without Landlock support])]) +]) + AC_SUBST([EXTRA_CFLAGS]) AC_SUBST([EXTRA_LDFLAGS]) @@ -264,6 +274,7 @@ AC_ARG_ENABLE([lts], [AS_HELP_STRING([--enable-lts], [enable long-term support software version (LTS)])]) AS_IF([test "x$enable_lts" = "xyes"], [ HAVE_LTS="-DHAVE_LTS" + HAVE_LANDLOCK="" HAVE_IDS="" HAVE_DBUSPROXY="" HAVE_OVERLAYFS="" @@ -324,6 +335,7 @@ Features: firetunnel support: $HAVE_FIRETUNNEL global config: $HAVE_GLOBALCFG IDS support: $HAVE_IDS + Landlock support: $HAVE_LANDLOCK LTS: $HAVE_LTS manpage support: $HAVE_MAN network: $HAVE_NETWORK diff --git a/contrib/syntax/lists/profile_commands_arg0.list b/contrib/syntax/lists/profile_commands_arg0.list index e7fecef4b..4d49e96d9 100644 --- a/contrib/syntax/lists/profile_commands_arg0.list +++ b/contrib/syntax/lists/profile_commands_arg0.list @@ -12,6 +12,7 @@ keep-config-pulse keep-dev-shm keep-shell-rc keep-var-tmp +landlock 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 5862f16ac..cce37efa0 100644 --- a/contrib/syntax/lists/profile_commands_arg1.list +++ b/contrib/syntax/lists/profile_commands_arg1.list @@ -29,6 +29,11 @@ ip6 iprange join-or-start keep-fd +landlock.execute +landlock.proc +landlock.read +landlock.special +landlock.write mac mkdir mkfile diff --git a/src/bash_completion/firejail.bash_completion.in b/src/bash_completion/firejail.bash_completion.in index 98e3a035e..eab0f7df6 100644 --- a/src/bash_completion/firejail.bash_completion.in +++ b/src/bash_completion/firejail.bash_completion.in @@ -42,6 +42,25 @@ _firejail() _filedir -d return 0 ;; + --landlock) + return 0 + ;; + --landlock.read) + _filedir + return 0 + ;; + --landlock.write) + _filedir + return 0 + ;; + --landlock.special) + _filedir + return 0 + ;; + --landlock.execute) + _filedir + return 0 + ;; --tmpfs) _filedir return 0 diff --git a/src/firejail/checkcfg.c b/src/firejail/checkcfg.c index d2289bb40..7792c6541 100644 --- a/src/firejail/checkcfg.c +++ b/src/firejail/checkcfg.c @@ -363,6 +363,13 @@ static const char *const compiletime_support = "disabled" #endif + "\n\t- Landlock support is " +#ifdef HAVE_LANDLOCK + "enabled" +#else + "disabled" +#endif + "\n\t- networking support is " #ifdef HAVE_NETWORK "enabled" diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index c791913ea..efeda7228 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -281,6 +281,9 @@ 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_seccomp; // enable default seccomp filter extern int arg_seccomp32; // enable default seccomp filter for 32 bit arch extern int arg_seccomp_postexec; // need postexec ld.preload library? @@ -950,4 +953,23 @@ void run_ids(int argc, char **argv); // oom.c void oom_set(const char *oom_string); +// landlock.c +#ifdef HAVE_LANDLOCK +int ll_get_fd(void); +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(__u32 flags); +#else +static inline int ll_get_fd(void) { return -1; } +static inline int ll_read(...) { return 0; } +static inline int ll_write(...) { return 0; } +static inline int ll_special(...) { return 0; } +static inline int ll_exec(...) { return 0; } +static inline int ll_basic_system(void) { return 0; } +static inline int ll_restrict(...) { return 0; } +#endif /* HAVE_LANDLOCK */ + #endif diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c new file mode 100644 index 000000000..b5f4140c5 --- /dev/null +++ b/src/firejail/landlock.c @@ -0,0 +1,263 @@ +/* + * Copyright (C) 2014-2023 Firejail Authors + * + * This file is part of firejail project + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation; either version 2 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License along + * with this program; if not, write to the Free Software Foundation, Inc., + * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA. +*/ + +#ifdef HAVE_LANDLOCK +#include "firejail.h" +#include +#include +#include +#include +#include +#include + +static int ll_ruleset_fd = -1; + +int ll_get_fd(void) { + return ll_ruleset_fd; +} + +#ifndef landlock_create_ruleset +static inline int +landlock_create_ruleset(const struct landlock_ruleset_attr *const attr, + const size_t size, const __u32 flags) { + return syscall(__NR_landlock_create_ruleset, attr, size, flags); +} +#endif + +#ifndef landlock_add_rule +static inline int +landlock_add_rule(const int ruleset_fd, + const enum landlock_rule_type rule_type, + const void *const rule_attr, + const __u32 flags) { + return syscall(__NR_landlock_add_rule, ruleset_fd, rule_type, + rule_attr, flags); +} +#endif + +#ifndef landlock_restrict_self +static inline int +landlock_restrict_self(const int ruleset_fd, const __u32 flags) { + return syscall(__NR_landlock_restrict_self, ruleset_fd, flags); +} +#endif + +static int ll_create_full_ruleset() { + struct landlock_ruleset_attr attr; + attr.handled_access_fs = + LANDLOCK_ACCESS_FS_EXECUTE | + LANDLOCK_ACCESS_FS_MAKE_BLOCK | + LANDLOCK_ACCESS_FS_MAKE_CHAR | + LANDLOCK_ACCESS_FS_MAKE_DIR | + LANDLOCK_ACCESS_FS_MAKE_FIFO | + LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_MAKE_SOCK | + LANDLOCK_ACCESS_FS_MAKE_SYM | + LANDLOCK_ACCESS_FS_READ_DIR | + LANDLOCK_ACCESS_FS_READ_FILE | + LANDLOCK_ACCESS_FS_REMOVE_DIR | + LANDLOCK_ACCESS_FS_REMOVE_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE; + + ll_ruleset_fd = landlock_create_ruleset(&attr, sizeof(attr), 0); + if (ll_ruleset_fd < 0) { + fprintf(stderr, "Error: failed to create a Landlock ruleset: %s\n", + strerror(errno)); + } + return ll_ruleset_fd; +} + +int ll_read(const char *allowed_path) { + if (ll_ruleset_fd == -1) + ll_ruleset_fd = ll_create_full_ruleset(); + + int error; + int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC); + if (allowed_fd < 0) { + if (arg_debug) { + fprintf(stderr, "%s: failed to open %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + return 0; + } + struct landlock_path_beneath_attr target; + target.parent_fd = allowed_fd; + target.allowed_access = + LANDLOCK_ACCESS_FS_READ_DIR | + LANDLOCK_ACCESS_FS_READ_FILE; + + error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, + &target, 0); + if (error) { + fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + close(allowed_fd); + return error; +} + +int ll_write(const char *allowed_path) { + if (ll_ruleset_fd == -1) + ll_ruleset_fd = ll_create_full_ruleset(); + + int error; + int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC); + if (allowed_fd < 0) { + if (arg_debug) { + fprintf(stderr, "%s: failed to open %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + return 0; + } + struct landlock_path_beneath_attr target; + target.parent_fd = allowed_fd; + target.allowed_access = + LANDLOCK_ACCESS_FS_MAKE_DIR | + LANDLOCK_ACCESS_FS_MAKE_REG | + LANDLOCK_ACCESS_FS_MAKE_SYM | + LANDLOCK_ACCESS_FS_REMOVE_DIR | + LANDLOCK_ACCESS_FS_REMOVE_FILE | + LANDLOCK_ACCESS_FS_WRITE_FILE; + + error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, + &target, 0); + if (error) { + fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + close(allowed_fd); + return error; +} + +int ll_special(const char *allowed_path) { + if (ll_ruleset_fd == -1) + ll_ruleset_fd = ll_create_full_ruleset(); + + int error; + int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC); + if (allowed_fd < 0) { + if (arg_debug) { + fprintf(stderr, "%s: failed to open %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + return 0; + } + struct landlock_path_beneath_attr target; + target.parent_fd = allowed_fd; + target.allowed_access = + LANDLOCK_ACCESS_FS_MAKE_BLOCK | + LANDLOCK_ACCESS_FS_MAKE_CHAR | + LANDLOCK_ACCESS_FS_MAKE_FIFO | + LANDLOCK_ACCESS_FS_MAKE_SOCK; + + error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, + &target, 0); + if (error) { + fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + close(allowed_fd); + return error; +} + +int ll_exec(const char *allowed_path) { + if (ll_ruleset_fd == -1) + ll_ruleset_fd = ll_create_full_ruleset(); + + int error; + int allowed_fd = open(allowed_path, O_PATH | O_CLOEXEC); + if (allowed_fd < 0) { + if (arg_debug) { + fprintf(stderr, "%s: failed to open %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + return 0; + } + struct landlock_path_beneath_attr target; + target.parent_fd = allowed_fd; + target.allowed_access = + LANDLOCK_ACCESS_FS_EXECUTE; + + error = landlock_add_rule(ll_ruleset_fd, LANDLOCK_RULE_PATH_BENEATH, + &target, 0); + if (error) { + fprintf(stderr, "Error: %s: failed to add Landlock rule for %s: %s\n", + __func__, allowed_path, strerror(errno)); + } + close(allowed_fd); + return error; +} + +int ll_basic_system(void) { + assert(cfg.homedir); + + if (ll_ruleset_fd == -1) + ll_ruleset_fd = ll_create_full_ruleset(); + + int error = + ll_read("/bin/") || + ll_read("/dev/") || + ll_read("/etc/") || + ll_read("/lib/") || + ll_read("/opt/") || + ll_read("/usr/") || + ll_read("/var/") || + ll_read(cfg.homedir) || + + ll_write("/dev/") || + ll_write(cfg.homedir) || + + ll_exec("/bin/") || + ll_exec("/lib/") || + ll_exec("/opt/") || + ll_exec("/usr/"); + + if (error) { + fprintf(stderr, "Error: %s: failed to set --landlock rules\n", + __func__); + } + return error; +} + +int ll_restrict(__u32 flags) { + if (ll_ruleset_fd == -1) + return 0; + + int error; + error = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0); + if (error) { + fprintf(stderr, "Error: %s: failed to restrict privileges: %s\n", + __func__, strerror(errno)); + goto out; + } + error = landlock_restrict_self(ll_ruleset_fd, flags); + if (error) { + fprintf(stderr, "Error: %s: failed to enforce Landlock: %s\n", + __func__, strerror(errno)); + goto out; + } + if (arg_debug) + printf("%s: Enforcing Landlock\n", __func__); +out: + close(ll_ruleset_fd); + return error; +} + +#endif /* HAVE_LANDLOCK */ diff --git a/src/firejail/main.c b/src/firejail/main.c index 0c9c80137..df31fe2ce 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -75,6 +75,9 @@ 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_seccomp = 0; // enable default seccomp filter int arg_seccomp32 = 0; // enable default seccomp filter for 32 bit arch int arg_seccomp_postexec = 0; // need postexec ld.preload library? @@ -1500,6 +1503,31 @@ int main(int argc, char **argv, char **envp) { else 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.read=", 16) == 0) + ll_read(argv[i] + 16); + else if (strncmp(argv[i], "--landlock.write=", 17) == 0) + ll_write(argv[i] + 17); + else if (strncmp(argv[i], "--landlock.special=", 19) == 0) + ll_special(argv[i] + 19); + else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) + ll_exec(argv[i] + 19); +#endif else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { if (checkcfg(CFG_SECCOMP)) arg_memory_deny_write_execute = 1; diff --git a/src/firejail/profile.c b/src/firejail/profile.c index a250e5611..08804c5f3 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1077,6 +1077,44 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } +#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.read ", 14) == 0) { + ll_read(ptr + 14); + return 0; + } + if (strncmp(ptr, "landlock.write ", 15) == 0) { + ll_write(ptr + 15); + return 0; + } + if (strncmp(ptr, "landlock.special ", 17) == 0) { + ll_special(ptr + 17); + return 0; + } + if (strncmp(ptr, "landlock.execute ", 17) == 0) { + ll_exec(ptr + 17); + return 0; + } +#endif + // memory deny write&execute if (strcmp(ptr, "memory-deny-write-execute") == 0) { if (checkcfg(CFG_SECCOMP)) diff --git a/src/firejail/sandbox.c b/src/firejail/sandbox.c index 827be5d85..dbc115137 100644 --- a/src/firejail/sandbox.c +++ b/src/firejail/sandbox.c @@ -516,6 +516,28 @@ void start_application(int no_sandbox, int fd, char *set_sandbox_status) { printf("LD_PRELOAD=%s\n", getenv("LD_PRELOAD")); } +#ifdef HAVE_LANDLOCK + //**************************** + // 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)) { + // 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); + } +#endif + if (just_run_the_shell) { char *arg[2]; arg[0] = cfg.usershell; diff --git a/src/firejail/usage.c b/src/firejail/usage.c index e8758c807..5f9185da9 100644 --- a/src/firejail/usage.c +++ b/src/firejail/usage.c @@ -133,6 +133,14 @@ static const char *const usage_str = " --keep-fd - inherit open file descriptors to sandbox.\n" " --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.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.execute=path - add an execute access rule for the path to the Landlock ruleset.\n" +#endif " --list - list all sandboxes.\n" #ifdef HAVE_FILE_TRANSFER " --ls=name|pid dir_or_filename - list files in sandbox container.\n" diff --git a/src/firejail/util.c b/src/firejail/util.c index bd32181b5..c0f30931c 100644 --- a/src/firejail/util.c +++ b/src/firejail/util.c @@ -1338,6 +1338,13 @@ void close_all(int *keep_list, size_t sz) { if (keep) continue; +#ifdef HAVE_LANDLOCK + // Don't close the file descriptor of the Landlock ruleset; it + // will be automatically closed by the "ll_restrict" wrapper + // function. + if (fd == ll_get_fd()) + continue; +#endif close(fd); } closedir(dir); diff --git a/src/man/firejail-profile.5.in b/src/man/firejail-profile.5.in index 3a678b14f..76f5e4d20 100644 --- a/src/man/firejail-profile.5.in +++ b/src/man/firejail-profile.5.in @@ -507,6 +507,37 @@ Blacklist all Linux capabilities. .TP \fBcaps.keep capability,capability,capability 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. +.TP +\fBlandlock.read path +Create a Landlock ruleset (if it doesn't already exist) and add a read access +rule for path. +.TP +\fBlandlock.write path +Create a Landlock ruleset (if it doesn't already exist) and add a write access +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. +.TP +\fBlandlock.execute path +Create a Landlock ruleset (if it doesn't already exist) and add an execution +permission rule for path. +#endif .TP \fBmemory-deny-write-execute Install a seccomp filter to block attempts to create memory mappings diff --git a/src/man/firejail.1.in b/src/man/firejail.1.in index 06969e851..d5a00c41b 100644 --- a/src/man/firejail.1.in +++ b/src/man/firejail.1.in @@ -1243,6 +1243,52 @@ Example: .br $ 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: +.PP +.RS +- read: /bin, /dev, /etc, /lib, /opt, /proc, /usr, /var +.br +- write: /dev, /proc +.br +- exec: /bin, /lib, /opt, /usr +.RE +.PP +See the \fBLANDLOCK\fR section for more information. +.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. +.TP +\fB\-\-landlock.write=path +Create a Landlock ruleset (if it doesn't already exist) and add a write access +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. +.TP +\fB\-\-landlock.execute=path +Create a Landlock ruleset (if it doesn't already exist) and add an execution +permission rule for path. +.PP +Example: +.PP +$ firejail \-\-landlock.read=/ \-\-landlock.write=/home \-\-landlock.execute=/usr +#endif .TP \fB\-\-list List all sandboxes, see \fBMONITORING\fR section for more details. @@ -3365,6 +3411,47 @@ To enable AppArmor confinement on top of your current Firejail security features $ firejail --apparmor firefox #endif +#ifdef HAVE_LANDLOCK +.SH LANDLOCK +Landlock is a Linux security module first introduced in version 5.13 of the +Linux kernel. +It allows unprivileged processes to restrict their access to the filesystem. +Once imposed, these restrictions can never be removed, and all child processes +created by a Landlock-restricted processes inherit these restrictions. +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. +.TP +Important notes: +.PP +.RS +- A process can install a Landlock ruleset only if it has either +\fBCAP_SYS_ADMIN\fR in its effective capability set, or the "No New +Privileges" restriction enabled. +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\-\-no\-new\-privs\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 +/etc directory. +.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. +Example: +.PP +$ firejail \-\-landlock \-\-landlock.read=/media \-\-landlock.proc=ro mc +#endif .SH DESKTOP INTEGRATION A symbolic link to /usr/bin/firejail under the name of a program, will start the program in Firejail sandbox. The symbolic link should be placed in the first $PATH position. On most systems, a good place diff --git a/src/zsh_completion/_firejail.in b/src/zsh_completion/_firejail.in index 7e87bb991..89cb1b84c 100644 --- a/src/zsh_completion/_firejail.in +++ b/src/zsh_completion/_firejail.in @@ -106,6 +106,11 @@ _firejail_args=( '--keep-fd[inherit open file descriptors to sandbox]: :' '--keep-shell-rc[do not copy shell rc files from /etc/skel]' '--keep-var-tmp[/var/tmp directory is untouched]' + '--landlock.proc=-[add an access rule for /proc to the Landlock ruleset]: :(no ro rw)' + '--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.execute=-[add an execute access rule for the path to the Landlock ruleset]: :_files' '--machine-id[spoof /etc/machine-id with a random id]' '--memory-deny-write-execute[seccomp filter to block attempts to create memory mappings that are both writable and executable]' '*--mkdir=-[create a directory]:' -- cgit v1.2.3-70-g09d2 From abc1edccb2c6a0041a05da3f5da71d9025e8ea56 Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 2 Nov 2023 08:34:59 -0400 Subject: landlock: new filesystem for --landlock command --- src/firejail/landlock.c | 46 ++++++++++++++++++++++++++++++++-------------- 1 file changed, 32 insertions(+), 14 deletions(-) diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index b5f4140c5..602190446 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -211,28 +211,46 @@ int ll_basic_system(void) { if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); - int error = - ll_read("/bin/") || - ll_read("/dev/") || - ll_read("/etc/") || - ll_read("/lib/") || - ll_read("/opt/") || - ll_read("/usr/") || - ll_read("/var/") || - ll_read(cfg.homedir) || + int error; + char *rundir; + if (asprintf(&rundir, "/run/user/%d", getuid()) == -1) + errExit("asprintf"); + + error = + ll_read("/") || // whole system read + ll_special("/") || // sockets etc. - ll_write("/dev/") || + ll_write("/tmp") || // write access + ll_write("/dev") || + ll_write("/run/shm") || ll_write(cfg.homedir) || + ll_write(rundir) || - ll_exec("/bin/") || - ll_exec("/lib/") || - ll_exec("/opt/") || - ll_exec("/usr/"); + ll_exec("/opt") || // exec access + ll_exec("/bin") || + ll_exec("/sbin") || + ll_exec("/lib") || + ll_exec("/lib32") || + ll_exec("/libx32") || + ll_exec("/lib64") || + ll_exec("/usr/bin") || + ll_exec("/usr/sbin") || + ll_exec("/usr/games") || + ll_exec("/usr/lib") || + ll_exec("/usr/lib32") || + ll_exec("/usr/libx32") || + ll_exec("/usr/lib64") || + ll_exec("/usr/local/bin") || + ll_exec("/usr/local/sbin") || + ll_exec("/usr/local/games") || + ll_exec("/usr/local/lib") || + ll_exec("/run/firejail"); // appimage and various firejail features if (error) { fprintf(stderr, "Error: %s: failed to set --landlock rules\n", __func__); } + free(rundir); return error; } -- cgit v1.2.3-70-g09d2 From b94cc754a0f88ac5b594c52b6a1a3c88b622772c Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 26 Oct 2023 10:21:40 -0400 Subject: landlock: apply rules in sandbox before app start Apply rules in the sandbox thread before the application is started. --- src/firejail/firejail.h | 8 ++++++++ src/firejail/landlock.c | 12 ++++++++++++ src/firejail/main.c | 8 ++++---- src/firejail/profile.c | 8 ++++---- 4 files changed, 28 insertions(+), 8 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index efeda7228..43325de62 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -150,6 +150,11 @@ typedef struct profile_entry_t { } ProfileEntry; +typedef struct landlock_entry_t { + struct landlock_entry_t *next; + char *data; +} LandlockEntry; + typedef struct config_t { // user data char *username; @@ -159,6 +164,7 @@ typedef struct config_t { // filesystem ProfileEntry *profile; ProfileEntry *profile_rebuild_etc; // blacklist files in /etc directory used by fs_rebuild_etc() + LandlockEntry *lprofile; #define MAX_PROFILE_IGNORE 32 char *profile_ignore[MAX_PROFILE_IGNORE]; @@ -962,6 +968,7 @@ int ll_special(const char *allowed_path); int ll_exec(const char *allowed_path); int ll_basic_system(void); int ll_restrict(__u32 flags); +void ll_add_profile(const char *data); #else static inline int ll_get_fd(void) { return -1; } static inline int ll_read(...) { return 0; } @@ -970,6 +977,7 @@ static inline int ll_special(...) { return 0; } static inline int ll_exec(...) { return 0; } static inline int ll_basic_system(void) { return 0; } static inline int ll_restrict(...) { return 0; } +static inline void ll_add_profile(...) { return; } #endif /* HAVE_LANDLOCK */ #endif diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index 602190446..b2a427047 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -278,4 +278,16 @@ out: return error; } +void ll_add_profile(const char *data) { + LandlockEntry *ptr = malloc(sizeof(LandlockEntry)); + if (!ptr) + errExit("malloc"); + memset(ptr, 0, sizeof(LandlockEntry)); + ptr->data = strdup(data); + if (!ptr->data) + errExit("strdup"); + ptr->next = cfg.lprofile; + cfg.lprofile = ptr; +} + #endif /* HAVE_LANDLOCK */ diff --git a/src/firejail/main.c b/src/firejail/main.c index df31fe2ce..8715d9486 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -1520,13 +1520,13 @@ int main(int argc, char **argv, char **envp) { } } else if (strncmp(argv[i], "--landlock.read=", 16) == 0) - ll_read(argv[i] + 16); + ll_add_profile(argv[i] + 2); else if (strncmp(argv[i], "--landlock.write=", 17) == 0) - ll_write(argv[i] + 17); + ll_add_profile(argv[i] + 2); else if (strncmp(argv[i], "--landlock.special=", 19) == 0) - ll_special(argv[i] + 19); + ll_add_profile(argv[i] + 2); else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) - ll_exec(argv[i] + 19); + ll_add_profile(argv[i] + 2); #endif else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { if (checkcfg(CFG_SECCOMP)) diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 08804c5f3..4e67ec2a3 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1098,19 +1098,19 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } if (strncmp(ptr, "landlock.read ", 14) == 0) { - ll_read(ptr + 14); + ll_add_profile(ptr); return 0; } if (strncmp(ptr, "landlock.write ", 15) == 0) { - ll_write(ptr + 15); + ll_add_profile(ptr); return 0; } if (strncmp(ptr, "landlock.special ", 17) == 0) { - ll_special(ptr + 17); + ll_add_profile(ptr); return 0; } if (strncmp(ptr, "landlock.execute ", 17) == 0) { - ll_exec(ptr + 17); + ll_add_profile(ptr); return 0; } #endif -- cgit v1.2.3-70-g09d2 From 520508d5be10e7579635193d24bc1ff004ed682b Mon Sep 17 00:00:00 2001 From: netblue30 Date: Thu, 2 Nov 2023 08:34:59 -0400 Subject: landlock: avoid parsing landlock commands twice --- src/firejail/firejail.h | 8 +++++++- src/firejail/landlock.c | 27 +++++++++++++++++++++++++-- src/firejail/main.c | 8 ++++---- src/firejail/profile.c | 8 ++++---- 4 files changed, 40 insertions(+), 11 deletions(-) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index 43325de62..f9f4cb473 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -152,6 +152,12 @@ typedef struct profile_entry_t { typedef struct landlock_entry_t { struct landlock_entry_t *next; +#define LL_READ 0 +#define LL_WRITE 1 +#define LL_SPECIAL 2 +#define LL_EXEC 3 +#define LL_MAX 4 + int type; char *data; } LandlockEntry; @@ -968,7 +974,7 @@ int ll_special(const char *allowed_path); int ll_exec(const char *allowed_path); int ll_basic_system(void); int ll_restrict(__u32 flags); -void ll_add_profile(const char *data); +void ll_add_profile(int type, const char *data); #else static inline int ll_get_fd(void) { return -1; } static inline int ll_read(...) { return 0; } diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index b2a427047..596e35aea 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -255,6 +255,20 @@ int ll_basic_system(void) { } int ll_restrict(__u32 flags) { + int (*fnc[])(const char *) = { + ll_read, + ll_write, + ll_special, + ll_exec, + NULL + }; + + LandlockEntry *ptr = cfg.lprofile; + while (ptr) { + fnc[ptr->type](ptr->data); + ptr = ptr->next; + } + if (ll_ruleset_fd == -1) return 0; @@ -278,12 +292,21 @@ out: return error; } -void ll_add_profile(const char *data) { +void ll_add_profile(int type, const char *data) { + assert(type >= 0); + assert(type < LL_MAX); + assert(data); + + const char *str = data; + while (*str == ' ' || *str == '\t') + str++; + LandlockEntry *ptr = malloc(sizeof(LandlockEntry)); if (!ptr) errExit("malloc"); memset(ptr, 0, sizeof(LandlockEntry)); - ptr->data = strdup(data); + ptr->type = type; + ptr->data = strdup(str); if (!ptr->data) errExit("strdup"); ptr->next = cfg.lprofile; diff --git a/src/firejail/main.c b/src/firejail/main.c index 8715d9486..b39693af7 100644 --- a/src/firejail/main.c +++ b/src/firejail/main.c @@ -1520,13 +1520,13 @@ int main(int argc, char **argv, char **envp) { } } else if (strncmp(argv[i], "--landlock.read=", 16) == 0) - ll_add_profile(argv[i] + 2); + ll_add_profile(LL_READ, argv[i] + 16); else if (strncmp(argv[i], "--landlock.write=", 17) == 0) - ll_add_profile(argv[i] + 2); + ll_add_profile(LL_WRITE, argv[i] + 17); else if (strncmp(argv[i], "--landlock.special=", 19) == 0) - ll_add_profile(argv[i] + 2); + ll_add_profile(LL_SPECIAL, argv[i] + 19); else if (strncmp(argv[i], "--landlock.execute=", 19) == 0) - ll_add_profile(argv[i] + 2); + ll_add_profile(LL_EXEC, argv[i] + 19); #endif else if (strcmp(argv[i], "--memory-deny-write-execute") == 0) { if (checkcfg(CFG_SECCOMP)) diff --git a/src/firejail/profile.c b/src/firejail/profile.c index 4e67ec2a3..e3554eb12 100644 --- a/src/firejail/profile.c +++ b/src/firejail/profile.c @@ -1098,19 +1098,19 @@ int profile_check_line(char *ptr, int lineno, const char *fname) { return 0; } if (strncmp(ptr, "landlock.read ", 14) == 0) { - ll_add_profile(ptr); + ll_add_profile(LL_READ, ptr + 14); return 0; } if (strncmp(ptr, "landlock.write ", 15) == 0) { - ll_add_profile(ptr); + ll_add_profile(LL_WRITE, ptr + 15); return 0; } if (strncmp(ptr, "landlock.special ", 17) == 0) { - ll_add_profile(ptr); + ll_add_profile(LL_SPECIAL, ptr + 17); return 0; } if (strncmp(ptr, "landlock.execute ", 17) == 0) { - ll_add_profile(ptr); + ll_add_profile(LL_EXEC, ptr + 17); return 0; } #endif -- cgit v1.2.3-70-g09d2 From d10bf154a9f0eab07e15f9d3b45b3642e3634f30 Mon Sep 17 00:00:00 2001 From: "Kelvin M. Klann" Date: Mon, 6 Nov 2023 04:29:02 -0300 Subject: landlock: detect support at runtime And ignore landlock-related commands if Landlock is unsupported at runtime. --- src/firejail/firejail.h | 1 + src/firejail/landlock.c | 45 +++++++++++++++++++++++++++++++++++++++++++++ 2 files changed, 46 insertions(+) diff --git a/src/firejail/firejail.h b/src/firejail/firejail.h index f9f4cb473..5a96fcbfd 100644 --- a/src/firejail/firejail.h +++ b/src/firejail/firejail.h @@ -968,6 +968,7 @@ void oom_set(const char *oom_string); // landlock.c #ifdef HAVE_LANDLOCK int ll_get_fd(void); +int ll_is_supported(void); int ll_read(const char *allowed_path); int ll_write(const char *allowed_path); int ll_special(const char *allowed_path); diff --git a/src/firejail/landlock.c b/src/firejail/landlock.c index 596e35aea..27fc1d748 100644 --- a/src/firejail/landlock.c +++ b/src/firejail/landlock.c @@ -28,6 +28,7 @@ #include static int ll_ruleset_fd = -1; +static int ll_abi = -1; int ll_get_fd(void) { return ll_ruleset_fd; @@ -59,7 +60,30 @@ landlock_restrict_self(const int ruleset_fd, const __u32 flags) { } #endif +int ll_is_supported(void) { + if (ll_abi != -1) + goto out; + + ll_abi = landlock_create_ruleset(NULL, 0, + LANDLOCK_CREATE_RULESET_VERSION); + if (ll_abi < 1) { + ll_abi = 0; + fprintf(stderr, "Warning: Landlock is disabled or not supported: %s, " + "ignoring landlock commands\n", + strerror(errno)); + goto out; + } + if (arg_debug) { + printf("Detected Landlock ABI version %d\n", ll_abi); + } +out: + return ll_abi; +} + static int ll_create_full_ruleset() { + if (!ll_is_supported()) + return -1; + struct landlock_ruleset_attr attr; attr.handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE | @@ -85,6 +109,9 @@ static int ll_create_full_ruleset() { } int ll_read(const char *allowed_path) { + if (!ll_is_supported()) + return 0; + if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); @@ -114,6 +141,9 @@ int ll_read(const char *allowed_path) { } int ll_write(const char *allowed_path) { + if (!ll_is_supported()) + return 0; + if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); @@ -147,6 +177,9 @@ int ll_write(const char *allowed_path) { } int ll_special(const char *allowed_path) { + if (!ll_is_supported()) + return 0; + if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); @@ -178,6 +211,9 @@ int ll_special(const char *allowed_path) { } int ll_exec(const char *allowed_path) { + if (!ll_is_supported()) + return 0; + if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); @@ -208,6 +244,9 @@ int ll_exec(const char *allowed_path) { int ll_basic_system(void) { assert(cfg.homedir); + if (!ll_is_supported()) + return 0; + if (ll_ruleset_fd == -1) ll_ruleset_fd = ll_create_full_ruleset(); @@ -255,6 +294,9 @@ int ll_basic_system(void) { } int ll_restrict(__u32 flags) { + if (!ll_is_supported()) + return 0; + int (*fnc[])(const char *) = { ll_read, ll_write, @@ -297,6 +339,9 @@ void ll_add_profile(int type, const char *data) { assert(type < LL_MAX); assert(data); + if (!ll_is_supported()) + return; + const char *str = data; while (*str == ' ' || *str == '\t') str++; -- cgit v1.2.3-70-g09d2