From f6c4cb1b9f725d6c20ac21817df26b6861ded4ea Mon Sep 17 00:00:00 2001 From: Nicolas Trangez Date: Tue, 2 Apr 2024 23:11:48 +0200 Subject: [PATCH 1/3] landlock: properly zero-out structs after allocation When allocating a struct of a specific size, but only filling in some members, everything should be zeroed out first (before, e.g., passing the struct to the kernel). This was not an issue until now, since the relevant API structures are always fully filled, however, with an upcoming Landlock struct change, this is required: when not zeroing the memory, some random values would be passed to the kernel, resulting in an error (this could only be reproduced on GHC 8.10 and 9.0, though, it looks like more recent versions have `alloca` return zeroed memory). Where before `Foreign.Marshal.Utils.with` was used to get a pointer to a structure, `with0` is introduced which basically does the same (`alloca`, `poke`, run the callback), but uses `fillBytes` to zero out the `alloca`ted memory before `poke`ing the `Storable` in place. --- landlock/CHANGELOG.md | 2 ++ landlock/src/System/Landlock.hs | 20 +++++++++++++++----- 2 files changed, 17 insertions(+), 5 deletions(-) diff --git a/landlock/CHANGELOG.md b/landlock/CHANGELOG.md index 23c6c54..9866a5b 100644 --- a/landlock/CHANGELOG.md +++ b/landlock/CHANGELOG.md @@ -14,6 +14,8 @@ * Support `filepath ^>=1.5`. +* Properly zero-out structs after allocation. + ## 0.2.1.1 -- 2023-02-28 * Extend API documentation with links to man-pages. diff --git a/landlock/src/System/Landlock.hs b/landlock/src/System/Landlock.hs index e09e7cd..628735d 100644 --- a/landlock/src/System/Landlock.hs +++ b/landlock/src/System/Landlock.hs @@ -77,9 +77,10 @@ import Control.Exception.Base (handleJust) import Control.Monad (void) import Control.Monad.Catch (MonadMask, bracket) import Control.Monad.IO.Class (MonadIO, liftIO) -import Foreign.Marshal.Utils (with) -import Foreign.Ptr (nullPtr) -import Foreign.Storable (Storable, sizeOf) +import Foreign.Marshal.Alloc (alloca) +import Foreign.Marshal.Utils (fillBytes) +import Foreign.Ptr (Ptr, nullPtr) +import Foreign.Storable (Storable, poke, sizeOf) import GHC.IO.Exception (IOErrorType (UnsupportedOperation)) import System.IO.Error (ioeGetErrorType) import System.Landlock.Flags @@ -115,6 +116,15 @@ import System.Landlock.Version (Version (..), version1, version2, version3) import System.Posix.IO (closeFd) import System.Posix.Types (Fd) +-- Like @Foreign.Marshal.Utils.with@, but zeros out the memory first +with0 :: (Storable a) => a -> (Ptr a -> IO b) -> IO b +with0 val f = + alloca $ \ptr -> do + let len = sizeOf val + fillBytes ptr 0 len + poke ptr val + f ptr + -- | Retrieve the Landlock ABI version of the running system. -- -- This invokes @@ -166,7 +176,7 @@ newtype LandlockFd = LandlockFd {unLandlockFd :: Fd} deriving (Show, Eq) createRuleset :: RulesetAttr -> [CreateRulesetFlag] -> IO LandlockFd -createRuleset attr flags = with attr' $ \attrp -> +createRuleset attr flags = with0 attr' $ \attrp -> wrap <$> landlock_create_ruleset attrp (fromIntegral $ sizeOf attr') flags' where wrap = LandlockFd . fromIntegral @@ -244,7 +254,7 @@ addRule :: [AddRuleFlag] -> m () addRule fd rule flags = liftIO $ - with rule $ \ruleAttrp -> + with0 rule $ \ruleAttrp -> landlock_add_rule (fromIntegral $ unLandlockFd fd) (ruleType rule) From 16b9699031c870a969a0816d232d831b36e1f1ac Mon Sep 17 00:00:00 2001 From: Nicolas Trangez Date: Tue, 2 Apr 2024 22:03:50 +0200 Subject: [PATCH 2/3] landlock: update vendored `landlock.h` Copied from Linux 6.8, ref e8f897f4afef0031fe618a8e94127a0934896aba. See: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/plain/include/uapi/linux/landlock.h?id=e8f897f4afef0031fe618a8e94127a0934896aba --- landlock/cbits/linux/landlock.h | 101 +++++++++++++++++++++++++++----- 1 file changed, 86 insertions(+), 15 deletions(-) diff --git a/landlock/cbits/linux/landlock.h b/landlock/cbits/linux/landlock.h index f3223f9..25c8d76 100644 --- a/landlock/cbits/linux/landlock.h +++ b/landlock/cbits/linux/landlock.h @@ -31,6 +31,12 @@ struct landlock_ruleset_attr { * this access right. */ __u64 handled_access_fs; + /** + * @handled_access_net: Bitmask of actions (cf. `Network flags`_) + * that is handled by this ruleset and should then be forbidden if no + * rule explicitly allow them. + */ + __u64 handled_access_net; }; /* @@ -54,6 +60,11 @@ enum landlock_rule_type { * landlock_path_beneath_attr . */ LANDLOCK_RULE_PATH_BENEATH = 1, + /** + * @LANDLOCK_RULE_NET_PORT: Type of a &struct + * landlock_net_port_attr . + */ + LANDLOCK_RULE_NET_PORT, }; /** @@ -79,6 +90,31 @@ struct landlock_path_beneath_attr { */ } __attribute__((packed)); +/** + * struct landlock_net_port_attr - Network port definition + * + * Argument of sys_landlock_add_rule(). + */ +struct landlock_net_port_attr { + /** + * @allowed_access: Bitmask of allowed access network for a port + * (cf. `Network flags`_). + */ + __u64 allowed_access; + /** + * @port: Network port in host endianness. + * + * It should be noted that port 0 passed to :manpage:`bind(2)` will + * bind to an available port from a specific port range. This can be + * configured thanks to the ``/proc/sys/net/ipv4/ip_local_port_range`` + * sysctl (also used for IPv6). A Landlock rule with port 0 and the + * ``LANDLOCK_ACCESS_NET_BIND_TCP`` right means that requesting to bind + * on port 0 is allowed and it will automatically translate to binding + * on the related port range. + */ + __u64 port; +}; + /** * DOC: fs_access * @@ -130,21 +166,37 @@ struct landlock_path_beneath_attr { * - %LANDLOCK_ACCESS_FS_MAKE_BLOCK: Create (or rename or link) a block device. * - %LANDLOCK_ACCESS_FS_MAKE_SYM: Create (or rename or link) a symbolic link. * - %LANDLOCK_ACCESS_FS_REFER: Link or rename a file from or to a different - * directory (i.e. reparent a file hierarchy). This access right is - * available since the second version of the Landlock ABI. This is also the - * only access right which is always considered handled by any ruleset in - * such a way that reparenting a file hierarchy is always denied by default. - * To avoid privilege escalation, it is not enough to add a rule with this - * access right. When linking or renaming a file, the destination directory - * hierarchy must also always have the same or a superset of restrictions of - * the source hierarchy. If it is not the case, or if the domain doesn't - * handle this access right, such actions are denied by default with errno - * set to ``EXDEV``. Linking also requires a ``LANDLOCK_ACCESS_FS_MAKE_*`` - * access right on the destination directory, and renaming also requires a - * ``LANDLOCK_ACCESS_FS_REMOVE_*`` access right on the source's (file or - * directory) parent. Otherwise, such actions are denied with errno set to - * ``EACCES``. The ``EACCES`` errno prevails over ``EXDEV`` to let user space - * efficiently deal with an unrecoverable error. + * directory (i.e. reparent a file hierarchy). + * + * This access right is available since the second version of the Landlock + * ABI. + * + * This is the only access right which is denied by default by any ruleset, + * even if the right is not specified as handled at ruleset creation time. + * The only way to make a ruleset grant this right is to explicitly allow it + * for a specific directory by adding a matching rule to the ruleset. + * + * In particular, when using the first Landlock ABI version, Landlock will + * always deny attempts to reparent files between different directories. + * + * In addition to the source and destination directories having the + * %LANDLOCK_ACCESS_FS_REFER access right, the attempted link or rename + * operation must meet the following constraints: + * + * * The reparented file may not gain more access rights in the destination + * directory than it previously had in the source directory. If this is + * attempted, the operation results in an ``EXDEV`` error. + * + * * When linking or renaming, the ``LANDLOCK_ACCESS_FS_MAKE_*`` right for the + * respective file type must be granted for the destination directory. + * Otherwise, the operation results in an ``EACCES`` error. + * + * * When renaming, the ``LANDLOCK_ACCESS_FS_REMOVE_*`` right for the + * respective file type must be granted for the source directory. Otherwise, + * the operation results in an ``EACCES`` error. + * + * If multiple requirements are not met, the ``EACCES`` error code takes + * precedence over ``EXDEV``. * * .. warning:: * @@ -173,4 +225,23 @@ struct landlock_path_beneath_attr { #define LANDLOCK_ACCESS_FS_TRUNCATE (1ULL << 14) /* clang-format on */ +/** + * DOC: net_access + * + * Network flags + * ~~~~~~~~~~~~~~~~ + * + * These flags enable to restrict a sandboxed process to a set of network + * actions. This is supported since the Landlock ABI version 4. + * + * TCP sockets with allowed actions: + * + * - %LANDLOCK_ACCESS_NET_BIND_TCP: Bind a TCP socket to a local port. + * - %LANDLOCK_ACCESS_NET_CONNECT_TCP: Connect an active TCP socket to + * a remote port. + */ +/* clang-format off */ +#define LANDLOCK_ACCESS_NET_BIND_TCP (1ULL << 0) +#define LANDLOCK_ACCESS_NET_CONNECT_TCP (1ULL << 1) +/* clang-format on */ #endif /* _UAPI_LINUX_LANDLOCK_H */ From ef8eb846bb32be051318154a18cbbacc191aa2bf Mon Sep 17 00:00:00 2001 From: Nicolas Trangez Date: Tue, 2 Apr 2024 22:17:35 +0200 Subject: [PATCH 3/3] landlock: update Haddock comments according to new header --- landlock/CHANGELOG.md | 2 + landlock/internal/System/Landlock/Flags.hs | 53 +++++++++++++--------- 2 files changed, 34 insertions(+), 21 deletions(-) diff --git a/landlock/CHANGELOG.md b/landlock/CHANGELOG.md index 9866a5b..3126335 100644 --- a/landlock/CHANGELOG.md +++ b/landlock/CHANGELOG.md @@ -16,6 +16,8 @@ * Properly zero-out structs after allocation. +* Update `landlock.h` to Linux 6.8. + ## 0.2.1.1 -- 2023-02-28 * Extend API documentation with links to man-pages. diff --git a/landlock/internal/System/Landlock/Flags.hs b/landlock/internal/System/Landlock/Flags.hs index 584a266..c3134cf 100644 --- a/landlock/internal/System/Landlock/Flags.hs +++ b/landlock/internal/System/Landlock/Flags.hs @@ -142,27 +142,38 @@ data AccessFsFlag -- ([@LANDLOCK_ACCESS_FS_MAKE_SYM@](https://man.archlinux.org/man/landlock.7.en#LANDLOCK_ACCESS_FS_MAKE_SYM)). AccessFsMakeSym | -- | Link or rename a file from or to a different - -- directory (i.e. reparent a file hierarchy). This access right is - -- available since the second version of the Landlock ABI. This is also the - -- only access right which is always considered handled by any ruleset in - -- such a way that reparenting a file hierarchy is always denied by default. - -- To avoid privilege escalation, it is not enough to add a rule with this - -- access right. When linking or renaming a file, the destination directory - -- hierarchy must also always have the same or a superset of restrictions of - -- the source hierarchy. If it is not the case, or if the domain doesn't - -- handle this access right, such actions are denied by default with - -- [@errno@](https://man.archlinux.org/man/errno.3) - -- set to [@EXDEV@](https://man.archlinux.org/man/errno.3#EXDEV). Linking - -- also requires a @LANDLOCK_ACCESS_FS_MAKE_*@ access right on the - -- destination directory, and renaming also requires a - -- @LANDLOCK_ACCESS_FS_REMOVE_*@ access right on the source's (file or - -- directory) parent. Otherwise, such actions are denied with - -- [@errno@](https://man.archlinux.org/man/errno.3) set to - -- [@EACCES@](https://man.archlinux.org/man/errno.3#EACCES). - -- The [@EACCES@](https://man.archlinux.org/man/errno.3#EACCES) - -- [@errno@](https://man.archlinux.org/man/errno.3) prevails over - -- [@EXDEV@](https://man.archlinux.org/man/errno.3#EXDEV) to let user - -- space efficiently deal with an unrecoverable error. + -- directory (i.e. reparent a file hierarchy) + -- ([@LANDLOCK_ACCESS_FS_REFER@](https://man.archlinux.org/man/landlock.7.en#LANDLOCK_ACCESS_FS_REFER)). + -- + -- This access right is available since the second version of the Landlock + -- ABI. + -- + -- This is the only access right which is denied by default by any ruleset, + -- even if the right is not specified as handled at ruleset creation time. + -- The only way to make a ruleset grant this right is to explicitly allow it + -- for a specific directory by adding a matching rule to the ruleset. + -- + -- In particular, when using the first Landlock ABI version, Landlock will + -- always deny attempts to reparent files between different directories. + -- + -- In addition to the source and destination directories having the + -- @LANDLOCK_ACCESS_FS_REFER@ access right, the attempted link or rename + -- operation must meet the following constraints: + -- + -- * The reparented file may not gain more access rights in the destination + -- directory than it previously had in the source directory. If this is + -- attempted, the operation results in an [@EXDEV@](https://man.archlinux.org/man/errno.3#EXDEV) error. + -- + -- * When linking or renaming, the @LANDLOCK_ACCESS_FS_MAKE_*@ right for the + -- respective file type must be granted for the destination directory. + -- Otherwise, the operation results in an [@EACCES@](https://man.archlinux.org/man/errno.3#EACCES) error. + -- + -- * When renaming, the @LANDLOCK_ACCESS_FS_REMOVE_*@ right for the + -- respective file type must be granted for the source directory. Otherwise, + -- the operation results in an [@EACCES@](https://man.archlinux.org/man/errno.3#EACCES) error. + -- + -- If multiple requirements are not met, the [@EACCES@](https://man.archlinux.org/man/errno.3#EACCES) error code takes + -- precedence over [@EXDEV@](https://man.archlinux.org/man/errno.3#EXDEV). AccessFsRefer | -- | Truncate a file with -- [@truncate@](https://man.archlinux.org/man/truncate.2),