From 38cb8ec9fd70d25fca6b473de44cf61586238552 Mon Sep 17 00:00:00 2001 From: Lasse Collin Date: Thu, 2 Jan 2025 15:32:10 +0200 Subject: [PATCH] Add my_landlock.h with helper functions to use Linux Landlock This supports up to Landlock ABI version 6. The current code in xz and xzdec only support up to ABI version 4. --- src/Makefile.am | 1 + src/common/my_landlock.h | 141 +++++++++++++++++++++++++++++++++++++++ 2 files changed, 142 insertions(+) create mode 100644 src/common/my_landlock.h diff --git a/src/Makefile.am b/src/Makefile.am index 15eee834..52885299 100644 --- a/src/Makefile.am +++ b/src/Makefile.am @@ -17,6 +17,7 @@ endif EXTRA_DIST = \ common/common_w32res.rc \ + common/my_landlock.h \ common/mythread.h \ common/sysdefs.h \ common/tuklib_common.h \ diff --git a/src/common/my_landlock.h b/src/common/my_landlock.h new file mode 100644 index 00000000..e135d08c --- /dev/null +++ b/src/common/my_landlock.h @@ -0,0 +1,141 @@ +// SPDX-License-Identifier: 0BSD + +/////////////////////////////////////////////////////////////////////////////// +// +/// \file my_landlock.h +/// \brief Linux Landlock sandbox helper functions +// +// Author: Lasse Collin +// +/////////////////////////////////////////////////////////////////////////////// + +#ifndef MY_LANDLOCK_H +#define MY_LANDLOCK_H + +#include "sysdefs.h" + +#include +#include +#include + + +/// \brief Initialize Landlock ruleset attributes to forbid everything +/// +/// The supported Landlock ABI is checked at runtime and only the supported +/// actions are forbidden in the attributes. Thus, if the attributes are +/// used with my_landlock_create_ruleset(), it shouldn't fail. +/// +/// \return On success, the Landlock ABI version is returned (a positive +/// integer). If Landlock isn't supported, -1 is returned. +static int +my_landlock_ruleset_attr_forbid_all(struct landlock_ruleset_attr *attr) +{ + memzero(attr, sizeof(*attr)); + + const int abi_version = syscall(SYS_landlock_create_ruleset, + (void *)NULL, 0, LANDLOCK_CREATE_RULESET_VERSION); + if (abi_version <= 0) + return -1; + + // ABI 1 except the few at the end + attr->handled_access_fs + = LANDLOCK_ACCESS_FS_EXECUTE + | LANDLOCK_ACCESS_FS_WRITE_FILE + | LANDLOCK_ACCESS_FS_READ_FILE + | LANDLOCK_ACCESS_FS_READ_DIR + | LANDLOCK_ACCESS_FS_REMOVE_DIR + | LANDLOCK_ACCESS_FS_REMOVE_FILE + | 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 +#ifdef LANDLOCK_ACCESS_FS_REFER + | LANDLOCK_ACCESS_FS_REFER // ABI 2 +#endif +#ifdef LANDLOCK_ACCESS_FS_TRUNCATE + | LANDLOCK_ACCESS_FS_TRUNCATE // ABI 3 +#endif +#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV + | LANDLOCK_ACCESS_FS_IOCTL_DEV // ABI 5 +#endif + ; + +#ifdef LANDLOCK_ACCESS_NET_BIND_TCP + // ABI 4 + attr->handled_access_net + = LANDLOCK_ACCESS_NET_BIND_TCP + | LANDLOCK_ACCESS_NET_CONNECT_TCP; +#endif + +#ifdef LANDLOCK_SCOPE_SIGNAL + // ABI 6 + attr->scoped + = LANDLOCK_SCOPE_ABSTRACT_UNIX_SOCKET + | LANDLOCK_SCOPE_SIGNAL; +#endif + + // Disable flags that require a new ABI version. + switch (abi_version) { + case 1: +#ifdef LANDLOCK_ACCESS_FS_REFER + attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_REFER; +#endif + FALLTHROUGH; + + case 2: +#ifdef LANDLOCK_ACCESS_FS_TRUNCATE + attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_TRUNCATE; +#endif + FALLTHROUGH; + + case 3: +#ifdef LANDLOCK_ACCESS_NET_BIND_TCP + attr->handled_access_net = 0; +#endif + FALLTHROUGH; + + case 4: +#ifdef LANDLOCK_ACCESS_FS_IOCTL_DEV + attr->handled_access_fs &= ~LANDLOCK_ACCESS_FS_IOCTL_DEV; +#endif + FALLTHROUGH; + + case 5: +#ifdef LANDLOCK_SCOPE_SIGNAL + attr->scoped = 0; +#endif + FALLTHROUGH; + + default: + // We only know about the features of the ABIs 1-6. + break; + } + + return abi_version; +} + + +/// \brief Wrapper for the landlock_create_ruleset(2) syscall +/// +/// Syscall wrappers provide argument type checking. +/// +/// \note Remember to call `prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)` too! +static inline int +my_landlock_create_ruleset(const struct landlock_ruleset_attr *attr, + size_t size, uint32_t flags) +{ + return syscall(SYS_landlock_create_ruleset, attr, size, flags); +} + + +/// \brief Wrapper for the landlock_restrict_self(2) syscall +static inline int +my_landlock_restrict_self(int ruleset_fd, uint32_t flags) +{ + return syscall(SYS_landlock_restrict_self, ruleset_fd, flags); +} + +#endif