aboutsummaryrefslogtreecommitdiff
path: root/src/xz/file_io.c
diff options
context:
space:
mode:
authorLasse Collin <lasse.collin@tukaani.org>2023-10-09 22:07:52 +0300
committerLasse Collin <lasse.collin@tukaani.org>2023-10-22 19:03:52 +0300
commit8276c7f41c671eee4aa3239490658b23dcfd3021 (patch)
tree0ea5a10ee423725d55b888281678784da2bb5aac /src/xz/file_io.c
parentCMake: Edit threading related messages. (diff)
downloadxz-8276c7f41c671eee4aa3239490658b23dcfd3021.tar.xz
xz: Support basic sandboxing with Linux Landlock (ABI versions 1-3).
It is enabled only when decompressing one file to stdout, similar to how Capsicum is used. Landlock was added in Linux 5.13.
Diffstat (limited to 'src/xz/file_io.c')
-rw-r--r--src/xz/file_io.c58
1 files changed, 58 insertions, 0 deletions
diff --git a/src/xz/file_io.c b/src/xz/file_io.c
index 5a7d317f..70fb0772 100644
--- a/src/xz/file_io.c
+++ b/src/xz/file_io.c
@@ -33,6 +33,11 @@ static bool warn_fchown;
# include <sys/capsicum.h>
#endif
+#ifdef HAVE_LINUX_LANDLOCK_H
+# include <linux/landlock.h>
+# include <sys/syscall.h>
+#endif
+
#include "tuklib_open_stdxxx.h"
#ifdef _MSC_VER
@@ -253,6 +258,59 @@ io_sandbox_enter(int src_fd)
(void)src_fd;
+#elif defined(HAVE_LINUX_LANDLOCK_H)
+ int landlock_abi = syscall(SYS_landlock_create_ruleset,
+ (void *)NULL, 0, LANDLOCK_CREATE_RULESET_VERSION);
+
+ if (landlock_abi > 0) {
+ // We support ABI versions 1-3.
+ if (landlock_abi > 3)
+ landlock_abi = 3;
+
+ // We want to set all supported flags in handled_access_fs.
+ // This way the ruleset will initially forbid access to all
+ // actions that the available Landlock ABI version supports.
+ // Exceptions can be added using landlock_add_rule(2) to
+ // allow certain actions on certain files or directories.
+ //
+ // The same flag values are used on all archs. ABI v2 and v3
+ // both add one new flag.
+ //
+ // First in ABI v1: LANDLOCK_ACCESS_FS_EXECUTE = 1ULL << 0
+ // Last in ABI v1: LANDLOCK_ACCESS_FS_MAKE_SYM = 1ULL << 12
+ // Last in ABI v2: LANDLOCK_ACCESS_FS_REFER = 1ULL << 13
+ // Last in ABI v3: LANDLOCK_ACCESS_FS_TRUNCATE = 1ULL << 14
+ //
+ // This makes it simple to set the mask based on the ABI
+ // version and we don't need to care which flags are #defined
+ // in the installed <linux/landlock.h>.
+ const struct landlock_ruleset_attr attr = {
+ .handled_access_fs = (1ULL << (12 + landlock_abi)) - 1
+ };
+
+ const int ruleset_fd = syscall(SYS_landlock_create_ruleset,
+ &attr, sizeof(attr), 0U);
+ if (ruleset_fd < 0)
+ goto error;
+
+ // All files we need should have already been openend. Thus,
+ // we don't need to add any rules using landlock_add_rule(2)
+ // before activating the sandbox.
+ //
+ // NOTE: It's possible that the hack at the beginning of this
+ // function isn't be good enough. It tries to get translations
+ // and libc-specific files loaded but if it's not good enough
+ // then perhaps a Landlock rule to allow reading from /usr
+ // and/or the xz installation prefix would be needed.
+ //
+ // prctl(PR_SET_NO_NEW_PRIVS, ...) was already called in
+ // main() so we don't do it here again.
+ if (syscall(SYS_landlock_restrict_self, ruleset_fd, 0U) != 0)
+ goto error;
+ }
+
+ (void)src_fd;
+
#else
# error ENABLE_SANDBOX is defined but no sandboxing method was found.
#endif