]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
5.18-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jun 2022 13:39:28 +0000 (15:39 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 6 Jun 2022 13:39:28 +0000 (15:39 +0200)
added patches:
landlock-add-clang-format-exceptions.patch
landlock-change-landlock_add_rule-2-argument-check-ordering.patch
landlock-change-landlock_restrict_self-2-check-ordering.patch
landlock-create-find_rule-from-unmask_layers.patch
landlock-define-access_mask_t-to-enforce-a-consistent-access-mask-size.patch
landlock-fix-landlock_add_rule-2-documentation.patch
landlock-fix-same-layer-rule-unions.patch
landlock-format-with-clang-format.patch
landlock-reduce-the-maximum-number-of-layers-to-16.patch
samples-landlock-add-clang-format-exceptions.patch
samples-landlock-format-with-clang-format.patch
selftests-landlock-add-clang-format-exceptions.patch
selftests-landlock-add-tests-for-o_path.patch
selftests-landlock-add-tests-for-unknown-access-rights.patch
selftests-landlock-extend-access-right-tests-to-directories.patch
selftests-landlock-extend-tests-for-minimal-valid-attribute-size.patch
selftests-landlock-format-with-clang-format.patch
selftests-landlock-fully-test-file-rename-with-remove-access.patch
selftests-landlock-make-tests-build-with-old-libc.patch
selftests-landlock-normalize-array-assignment.patch
selftests-landlock-test-landlock_create_ruleset-2-argument-check-ordering.patch

22 files changed:
queue-5.18/landlock-add-clang-format-exceptions.patch [new file with mode: 0644]
queue-5.18/landlock-change-landlock_add_rule-2-argument-check-ordering.patch [new file with mode: 0644]
queue-5.18/landlock-change-landlock_restrict_self-2-check-ordering.patch [new file with mode: 0644]
queue-5.18/landlock-create-find_rule-from-unmask_layers.patch [new file with mode: 0644]
queue-5.18/landlock-define-access_mask_t-to-enforce-a-consistent-access-mask-size.patch [new file with mode: 0644]
queue-5.18/landlock-fix-landlock_add_rule-2-documentation.patch [new file with mode: 0644]
queue-5.18/landlock-fix-same-layer-rule-unions.patch [new file with mode: 0644]
queue-5.18/landlock-format-with-clang-format.patch [new file with mode: 0644]
queue-5.18/landlock-reduce-the-maximum-number-of-layers-to-16.patch [new file with mode: 0644]
queue-5.18/samples-landlock-add-clang-format-exceptions.patch [new file with mode: 0644]
queue-5.18/samples-landlock-format-with-clang-format.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-add-clang-format-exceptions.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-add-tests-for-o_path.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-add-tests-for-unknown-access-rights.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-extend-access-right-tests-to-directories.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-extend-tests-for-minimal-valid-attribute-size.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-format-with-clang-format.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-fully-test-file-rename-with-remove-access.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-make-tests-build-with-old-libc.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-normalize-array-assignment.patch [new file with mode: 0644]
queue-5.18/selftests-landlock-test-landlock_create_ruleset-2-argument-check-ordering.patch [new file with mode: 0644]
queue-5.18/series

diff --git a/queue-5.18/landlock-add-clang-format-exceptions.patch b/queue-5.18/landlock-add-clang-format-exceptions.patch
new file mode 100644 (file)
index 0000000..99a44ac
--- /dev/null
@@ -0,0 +1,86 @@
+From 6cc2df8e3a3967e7c13a424f87f6efb1d4a62d80 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:07 +0200
+Subject: landlock: Add clang-format exceptions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 6cc2df8e3a3967e7c13a424f87f6efb1d4a62d80 upstream.
+
+In preparation to a following commit, add clang-format on and
+clang-format off stanzas around constant definitions.  This enables to
+keep aligned values, which is much more readable than packed
+definitions.
+
+Link: https://lore.kernel.org/r/20220506160513.523257-2-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/landlock.h |    4 ++++
+ security/landlock/fs.c        |    2 ++
+ security/landlock/limits.h    |    4 ++++
+ 3 files changed, 10 insertions(+)
+
+--- a/include/uapi/linux/landlock.h
++++ b/include/uapi/linux/landlock.h
+@@ -33,7 +33,9 @@ struct landlock_ruleset_attr {
+  * - %LANDLOCK_CREATE_RULESET_VERSION: Get the highest supported Landlock ABI
+  *   version.
+  */
++/* clang-format off */
+ #define LANDLOCK_CREATE_RULESET_VERSION                       (1U << 0)
++/* clang-format on */
+ /**
+  * enum landlock_rule_type - Landlock rule type
+@@ -120,6 +122,7 @@ struct landlock_path_beneath_attr {
+  *   :manpage:`access(2)`.
+  *   Future Landlock evolutions will enable to restrict them.
+  */
++/* clang-format off */
+ #define LANDLOCK_ACCESS_FS_EXECUTE                    (1ULL << 0)
+ #define LANDLOCK_ACCESS_FS_WRITE_FILE                 (1ULL << 1)
+ #define LANDLOCK_ACCESS_FS_READ_FILE                  (1ULL << 2)
+@@ -133,5 +136,6 @@ struct landlock_path_beneath_attr {
+ #define LANDLOCK_ACCESS_FS_MAKE_FIFO                  (1ULL << 10)
+ #define LANDLOCK_ACCESS_FS_MAKE_BLOCK                 (1ULL << 11)
+ #define LANDLOCK_ACCESS_FS_MAKE_SYM                   (1ULL << 12)
++/* clang-format on */
+ #endif /* _UAPI_LINUX_LANDLOCK_H */
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -141,10 +141,12 @@ retry:
+ }
+ /* All access rights that can be tied to files. */
++/* clang-format off */
+ #define ACCESS_FILE ( \
+       LANDLOCK_ACCESS_FS_EXECUTE | \
+       LANDLOCK_ACCESS_FS_WRITE_FILE | \
+       LANDLOCK_ACCESS_FS_READ_FILE)
++/* clang-format on */
+ /*
+  * @path: Should have been checked by get_path_from_fd().
+--- a/security/landlock/limits.h
++++ b/security/landlock/limits.h
+@@ -12,10 +12,14 @@
+ #include <linux/limits.h>
+ #include <uapi/linux/landlock.h>
++/* clang-format off */
++
+ #define LANDLOCK_MAX_NUM_LAYERS               64
+ #define LANDLOCK_MAX_NUM_RULES                U32_MAX
+ #define LANDLOCK_LAST_ACCESS_FS               LANDLOCK_ACCESS_FS_MAKE_SYM
+ #define LANDLOCK_MASK_ACCESS_FS               ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
++/* clang-format on */
++
+ #endif /* _SECURITY_LANDLOCK_LIMITS_H */
diff --git a/queue-5.18/landlock-change-landlock_add_rule-2-argument-check-ordering.patch b/queue-5.18/landlock-change-landlock_add_rule-2-argument-check-ordering.patch
new file mode 100644 (file)
index 0000000..0acca80
--- /dev/null
@@ -0,0 +1,118 @@
+From 589172e5636c4d16c40b90e87543d43defe2d968 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:18 +0200
+Subject: landlock: Change landlock_add_rule(2) argument check ordering
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 589172e5636c4d16c40b90e87543d43defe2d968 upstream.
+
+This makes more sense to first check the ruleset FD and then the rule
+attribute.  It will be useful to factor out code for other rule types.
+
+Add inval_add_rule_arguments tests, extension of empty_path_beneath_attr
+tests, to also check error ordering for landlock_add_rule(2).
+
+Link: https://lore.kernel.org/r/20220506160820.524344-9-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/syscalls.c                 |   22 ++++++++++-------
+ tools/testing/selftests/landlock/base_test.c |   34 +++++++++++++++++++++++++--
+ 2 files changed, 45 insertions(+), 11 deletions(-)
+
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -318,20 +318,24 @@ SYSCALL_DEFINE4(landlock_add_rule, const
+       if (flags)
+               return -EINVAL;
+-      if (rule_type != LANDLOCK_RULE_PATH_BENEATH)
+-              return -EINVAL;
+-
+-      /* Copies raw user space buffer, only one type for now. */
+-      res = copy_from_user(&path_beneath_attr, rule_attr,
+-                           sizeof(path_beneath_attr));
+-      if (res)
+-              return -EFAULT;
+-
+       /* Gets and checks the ruleset. */
+       ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_WRITE);
+       if (IS_ERR(ruleset))
+               return PTR_ERR(ruleset);
++      if (rule_type != LANDLOCK_RULE_PATH_BENEATH) {
++              err = -EINVAL;
++              goto out_put_ruleset;
++      }
++
++      /* Copies raw user space buffer, only one type for now. */
++      res = copy_from_user(&path_beneath_attr, rule_attr,
++                           sizeof(path_beneath_attr));
++      if (res) {
++              err = -EFAULT;
++              goto out_put_ruleset;
++      }
++
+       /*
+        * Informs about useless rule: empty allowed_access (i.e. deny rules)
+        * are ignored in path walks.
+--- a/tools/testing/selftests/landlock/base_test.c
++++ b/tools/testing/selftests/landlock/base_test.c
+@@ -121,20 +121,50 @@ TEST(inval_create_ruleset_flags)
+       ASSERT_EQ(EINVAL, errno);
+ }
+-TEST(empty_path_beneath_attr)
++/* Tests ordering of syscall argument checks. */
++TEST(add_rule_checks_ordering)
+ {
+       const struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
+       };
++      struct landlock_path_beneath_attr path_beneath_attr = {
++              .allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
++              .parent_fd = -1,
++      };
+       const int ruleset_fd =
+               landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+-      /* Similar to struct landlock_path_beneath_attr.parent_fd = 0 */
++      /* Checks invalid flags. */
++      ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 1));
++      ASSERT_EQ(EINVAL, errno);
++
++      /* Checks invalid ruleset FD. */
++      ASSERT_EQ(-1, landlock_add_rule(-1, 0, NULL, 0));
++      ASSERT_EQ(EBADF, errno);
++
++      /* Checks invalid rule type. */
++      ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, 0, NULL, 0));
++      ASSERT_EQ(EINVAL, errno);
++
++      /* Checks invalid rule attr. */
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+                                       NULL, 0));
+       ASSERT_EQ(EFAULT, errno);
++
++      /* Checks invalid path_beneath.parent_fd. */
++      ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
++                                      &path_beneath_attr, 0));
++      ASSERT_EQ(EBADF, errno);
++
++      /* Checks valid call. */
++      path_beneath_attr.parent_fd =
++              open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
++      ASSERT_LE(0, path_beneath_attr.parent_fd);
++      ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
++                                     &path_beneath_attr, 0));
++      ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
+       ASSERT_EQ(0, close(ruleset_fd));
+ }
diff --git a/queue-5.18/landlock-change-landlock_restrict_self-2-check-ordering.patch b/queue-5.18/landlock-change-landlock_restrict_self-2-check-ordering.patch
new file mode 100644 (file)
index 0000000..9879ab7
--- /dev/null
@@ -0,0 +1,115 @@
+From eba39ca4b155c54adf471a69e91799cc1727873f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:19 +0200
+Subject: landlock: Change landlock_restrict_self(2) check ordering
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit eba39ca4b155c54adf471a69e91799cc1727873f upstream.
+
+According to the Landlock goal to be a security feature available to
+unprivileges processes, it makes more sense to first check for
+no_new_privs before checking anything else (i.e. syscall arguments).
+
+Merge inval_fd_enforce and unpriv_enforce_without_no_new_privs tests
+into the new restrict_self_checks_ordering.  This is similar to the
+previous commit checking other syscalls.
+
+Link: https://lore.kernel.org/r/20220506160820.524344-10-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/syscalls.c                 |    8 ++--
+ tools/testing/selftests/landlock/base_test.c |   47 +++++++++++++++++++++------
+ 2 files changed, 41 insertions(+), 14 deletions(-)
+
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -405,10 +405,6 @@ SYSCALL_DEFINE2(landlock_restrict_self,
+       if (!landlock_initialized)
+               return -EOPNOTSUPP;
+-      /* No flag for now. */
+-      if (flags)
+-              return -EINVAL;
+-
+       /*
+        * Similar checks as for seccomp(2), except that an -EPERM may be
+        * returned.
+@@ -417,6 +413,10 @@ SYSCALL_DEFINE2(landlock_restrict_self,
+           !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
+               return -EPERM;
++      /* No flag for now. */
++      if (flags)
++              return -EINVAL;
++
+       /* Gets and checks the ruleset. */
+       ruleset = get_ruleset_from_fd(ruleset_fd, FMODE_CAN_READ);
+       if (IS_ERR(ruleset))
+--- a/tools/testing/selftests/landlock/base_test.c
++++ b/tools/testing/selftests/landlock/base_test.c
+@@ -168,22 +168,49 @@ TEST(add_rule_checks_ordering)
+       ASSERT_EQ(0, close(ruleset_fd));
+ }
+-TEST(inval_fd_enforce)
++/* Tests ordering of syscall argument and permission checks. */
++TEST(restrict_self_checks_ordering)
+ {
++      const struct landlock_ruleset_attr ruleset_attr = {
++              .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
++      };
++      struct landlock_path_beneath_attr path_beneath_attr = {
++              .allowed_access = LANDLOCK_ACCESS_FS_EXECUTE,
++              .parent_fd = -1,
++      };
++      const int ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
++
++      ASSERT_LE(0, ruleset_fd);
++      path_beneath_attr.parent_fd =
++              open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
++      ASSERT_LE(0, path_beneath_attr.parent_fd);
++      ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
++                                     &path_beneath_attr, 0));
++      ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
++
++      /* Checks unprivileged enforcement without no_new_privs. */
++      drop_caps(_metadata);
++      ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
++      ASSERT_EQ(EPERM, errno);
++      ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
++      ASSERT_EQ(EPERM, errno);
++      ASSERT_EQ(-1, landlock_restrict_self(ruleset_fd, 0));
++      ASSERT_EQ(EPERM, errno);
++
+       ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
++      /* Checks invalid flags. */
++      ASSERT_EQ(-1, landlock_restrict_self(-1, -1));
++      ASSERT_EQ(EINVAL, errno);
++
++      /* Checks invalid ruleset FD. */
+       ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
+       ASSERT_EQ(EBADF, errno);
+-}
+-
+-TEST(unpriv_enforce_without_no_new_privs)
+-{
+-      int err;
+-      drop_caps(_metadata);
+-      err = landlock_restrict_self(-1, 0);
+-      ASSERT_EQ(EPERM, errno);
+-      ASSERT_EQ(err, -1);
++      /* Checks valid call. */
++      ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
++      ASSERT_EQ(0, close(ruleset_fd));
+ }
+ TEST(ruleset_fd_io)
diff --git a/queue-5.18/landlock-create-find_rule-from-unmask_layers.patch b/queue-5.18/landlock-create-find_rule-from-unmask_layers.patch
new file mode 100644 (file)
index 0000000..367ee96
--- /dev/null
@@ -0,0 +1,95 @@
+From 2cd7cd6eed88b8383cfddce589afe9c0ae1d19b4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:10:53 +0200
+Subject: landlock: Create find_rule() from unmask_layers()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 2cd7cd6eed88b8383cfddce589afe9c0ae1d19b4 upstream.
+
+This refactoring will be useful in a following commit.
+
+Reviewed-by: Paul Moore <paul@paul-moore.com>
+Link: https://lore.kernel.org/r/20220506161102.525323-4-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/fs.c |   41 ++++++++++++++++++++++++++++-------------
+ 1 file changed, 28 insertions(+), 13 deletions(-)
+
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -183,23 +183,36 @@ int landlock_append_fs_rule(struct landl
+ /* Access-control management */
+-static inline layer_mask_t
+-unmask_layers(const struct landlock_ruleset *const domain,
+-            const struct path *const path, const access_mask_t access_request,
+-            layer_mask_t layer_mask)
++/*
++ * The lifetime of the returned rule is tied to @domain.
++ *
++ * Returns NULL if no rule is found or if @dentry is negative.
++ */
++static inline const struct landlock_rule *
++find_rule(const struct landlock_ruleset *const domain,
++        const struct dentry *const dentry)
+ {
+       const struct landlock_rule *rule;
+       const struct inode *inode;
+-      size_t i;
+-      if (d_is_negative(path->dentry))
+-              /* Ignore nonexistent leafs. */
+-              return layer_mask;
+-      inode = d_backing_inode(path->dentry);
++      /* Ignores nonexistent leafs. */
++      if (d_is_negative(dentry))
++              return NULL;
++
++      inode = d_backing_inode(dentry);
+       rcu_read_lock();
+       rule = landlock_find_rule(
+               domain, rcu_dereference(landlock_inode(inode)->object));
+       rcu_read_unlock();
++      return rule;
++}
++
++static inline layer_mask_t unmask_layers(const struct landlock_rule *const rule,
++                                       const access_mask_t access_request,
++                                       layer_mask_t layer_mask)
++{
++      size_t layer_level;
++
+       if (!rule)
+               return layer_mask;
+@@ -210,8 +223,9 @@ unmask_layers(const struct landlock_rule
+        * the remaining layers for each inode, from the first added layer to
+        * the last one.
+        */
+-      for (i = 0; i < rule->num_layers; i++) {
+-              const struct landlock_layer *const layer = &rule->layers[i];
++      for (layer_level = 0; layer_level < rule->num_layers; layer_level++) {
++              const struct landlock_layer *const layer =
++                      &rule->layers[layer_level];
+               const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
+               /* Checks that the layer grants access to the full request. */
+@@ -269,8 +283,9 @@ static int check_access_path(const struc
+       while (true) {
+               struct dentry *parent_dentry;
+-              layer_mask = unmask_layers(domain, &walker_path, access_request,
+-                                         layer_mask);
++              layer_mask =
++                      unmask_layers(find_rule(domain, walker_path.dentry),
++                                    access_request, layer_mask);
+               if (layer_mask == 0) {
+                       /* Stops when a rule from each layer grants access. */
+                       allowed = true;
diff --git a/queue-5.18/landlock-define-access_mask_t-to-enforce-a-consistent-access-mask-size.patch b/queue-5.18/landlock-define-access_mask_t-to-enforce-a-consistent-access-mask-size.patch
new file mode 100644 (file)
index 0000000..cfd061b
--- /dev/null
@@ -0,0 +1,209 @@
+From 5f2ff33e10843ef51275c8611bdb7b49537aba5d Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:10:51 +0200
+Subject: landlock: Define access_mask_t to enforce a consistent access mask size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 5f2ff33e10843ef51275c8611bdb7b49537aba5d upstream.
+
+Create and use the access_mask_t typedef to enforce a consistent access
+mask size and uniformly use a 16-bits type.  This will helps transition
+to a 32-bits value one day.
+
+Add a build check to make sure all (filesystem) access rights fit in.
+This will be extended with a following commit.
+
+Reviewed-by: Paul Moore <paul@paul-moore.com>
+Link: https://lore.kernel.org/r/20220506161102.525323-2-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/fs.c      |   19 +++++++++++--------
+ security/landlock/fs.h      |    2 +-
+ security/landlock/limits.h  |    2 ++
+ security/landlock/ruleset.c |    6 ++++--
+ security/landlock/ruleset.h |   16 ++++++++++++----
+ 5 files changed, 30 insertions(+), 15 deletions(-)
+
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -152,7 +152,8 @@ retry:
+  * @path: Should have been checked by get_path_from_fd().
+  */
+ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
+-                          const struct path *const path, u32 access_rights)
++                          const struct path *const path,
++                          access_mask_t access_rights)
+ {
+       int err;
+       struct landlock_object *object;
+@@ -184,7 +185,8 @@ int landlock_append_fs_rule(struct landl
+ static inline u64 unmask_layers(const struct landlock_ruleset *const domain,
+                               const struct path *const path,
+-                              const u32 access_request, u64 layer_mask)
++                              const access_mask_t access_request,
++                              u64 layer_mask)
+ {
+       const struct landlock_rule *rule;
+       const struct inode *inode;
+@@ -224,7 +226,8 @@ static inline u64 unmask_layers(const st
+ }
+ static int check_access_path(const struct landlock_ruleset *const domain,
+-                           const struct path *const path, u32 access_request)
++                           const struct path *const path,
++                           const access_mask_t access_request)
+ {
+       bool allowed = false;
+       struct path walker_path;
+@@ -309,7 +312,7 @@ jump_up:
+ }
+ static inline int current_check_access_path(const struct path *const path,
+-                                          const u32 access_request)
++                                          const access_mask_t access_request)
+ {
+       const struct landlock_ruleset *const dom =
+               landlock_get_current_domain();
+@@ -512,7 +515,7 @@ static int hook_sb_pivotroot(const struc
+ /* Path hooks */
+-static inline u32 get_mode_access(const umode_t mode)
++static inline access_mask_t get_mode_access(const umode_t mode)
+ {
+       switch (mode & S_IFMT) {
+       case S_IFLNK:
+@@ -565,7 +568,7 @@ static int hook_path_link(struct dentry
+               get_mode_access(d_backing_inode(old_dentry)->i_mode));
+ }
+-static inline u32 maybe_remove(const struct dentry *const dentry)
++static inline access_mask_t maybe_remove(const struct dentry *const dentry)
+ {
+       if (d_is_negative(dentry))
+               return 0;
+@@ -635,9 +638,9 @@ static int hook_path_rmdir(const struct
+ /* File hooks */
+-static inline u32 get_file_access(const struct file *const file)
++static inline access_mask_t get_file_access(const struct file *const file)
+ {
+-      u32 access = 0;
++      access_mask_t access = 0;
+       if (file->f_mode & FMODE_READ) {
+               /* A directory can only be opened in read mode. */
+--- a/security/landlock/fs.h
++++ b/security/landlock/fs.h
+@@ -66,6 +66,6 @@ __init void landlock_add_fs_hooks(void);
+ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
+                           const struct path *const path,
+-                          u32 access_hierarchy);
++                          access_mask_t access_hierarchy);
+ #endif /* _SECURITY_LANDLOCK_FS_H */
+--- a/security/landlock/limits.h
++++ b/security/landlock/limits.h
+@@ -9,6 +9,7 @@
+ #ifndef _SECURITY_LANDLOCK_LIMITS_H
+ #define _SECURITY_LANDLOCK_LIMITS_H
++#include <linux/bitops.h>
+ #include <linux/limits.h>
+ #include <uapi/linux/landlock.h>
+@@ -19,6 +20,7 @@
+ #define LANDLOCK_LAST_ACCESS_FS               LANDLOCK_ACCESS_FS_MAKE_SYM
+ #define LANDLOCK_MASK_ACCESS_FS               ((LANDLOCK_LAST_ACCESS_FS << 1) - 1)
++#define LANDLOCK_NUM_ACCESS_FS                __const_hweight64(LANDLOCK_MASK_ACCESS_FS)
+ /* clang-format on */
+--- a/security/landlock/ruleset.c
++++ b/security/landlock/ruleset.c
+@@ -45,7 +45,8 @@ static struct landlock_ruleset *create_r
+       return new_ruleset;
+ }
+-struct landlock_ruleset *landlock_create_ruleset(const u32 fs_access_mask)
++struct landlock_ruleset *
++landlock_create_ruleset(const access_mask_t fs_access_mask)
+ {
+       struct landlock_ruleset *new_ruleset;
+@@ -228,7 +229,8 @@ static void build_check_layer(void)
+ /* @ruleset must be locked by the caller. */
+ int landlock_insert_rule(struct landlock_ruleset *const ruleset,
+-                       struct landlock_object *const object, const u32 access)
++                       struct landlock_object *const object,
++                       const access_mask_t access)
+ {
+       struct landlock_layer layers[] = { {
+               .access = access,
+--- a/security/landlock/ruleset.h
++++ b/security/landlock/ruleset.h
+@@ -9,13 +9,20 @@
+ #ifndef _SECURITY_LANDLOCK_RULESET_H
+ #define _SECURITY_LANDLOCK_RULESET_H
++#include <linux/bitops.h>
++#include <linux/build_bug.h>
+ #include <linux/mutex.h>
+ #include <linux/rbtree.h>
+ #include <linux/refcount.h>
+ #include <linux/workqueue.h>
++#include "limits.h"
+ #include "object.h"
++typedef u16 access_mask_t;
++/* Makes sure all filesystem access rights can be stored. */
++static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
++
+ /**
+  * struct landlock_layer - Access rights for a given layer
+  */
+@@ -28,7 +35,7 @@ struct landlock_layer {
+        * @access: Bitfield of allowed actions on the kernel object.  They are
+        * relative to the object type (e.g. %LANDLOCK_ACTION_FS_READ).
+        */
+-      u16 access;
++      access_mask_t access;
+ };
+ /**
+@@ -135,19 +142,20 @@ struct landlock_ruleset {
+                        * layers are set once and never changed for the
+                        * lifetime of the ruleset.
+                        */
+-                      u16 fs_access_masks[];
++                      access_mask_t fs_access_masks[];
+               };
+       };
+ };
+-struct landlock_ruleset *landlock_create_ruleset(const u32 fs_access_mask);
++struct landlock_ruleset *
++landlock_create_ruleset(const access_mask_t fs_access_mask);
+ void landlock_put_ruleset(struct landlock_ruleset *const ruleset);
+ void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset);
+ int landlock_insert_rule(struct landlock_ruleset *const ruleset,
+                        struct landlock_object *const object,
+-                       const u32 access);
++                       const access_mask_t access);
+ struct landlock_ruleset *
+ landlock_merge_ruleset(struct landlock_ruleset *const parent,
diff --git a/queue-5.18/landlock-fix-landlock_add_rule-2-documentation.patch b/queue-5.18/landlock-fix-landlock_add_rule-2-documentation.patch
new file mode 100644 (file)
index 0000000..ecad48c
--- /dev/null
@@ -0,0 +1,58 @@
+From a13e248ff90e81e9322406c0e618cf2168702f4e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:11 +0200
+Subject: landlock: Fix landlock_add_rule(2) documentation
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit a13e248ff90e81e9322406c0e618cf2168702f4e upstream.
+
+It is not mandatory to pass a file descriptor obtained with the O_PATH
+flag.  Also, replace rule's accesses with ruleset's accesses.
+
+Link: https://lore.kernel.org/r/20220506160820.524344-2-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ include/uapi/linux/landlock.h |    5 +++--
+ security/landlock/syscalls.c  |    7 +++----
+ 2 files changed, 6 insertions(+), 6 deletions(-)
+
+--- a/include/uapi/linux/landlock.h
++++ b/include/uapi/linux/landlock.h
+@@ -62,8 +62,9 @@ struct landlock_path_beneath_attr {
+        */
+       __u64 allowed_access;
+       /**
+-       * @parent_fd: File descriptor, open with ``O_PATH``, which identifies
+-       * the parent directory of a file hierarchy, or just a file.
++       * @parent_fd: File descriptor, preferably opened with ``O_PATH``,
++       * which identifies the parent directory of a file hierarchy, or just a
++       * file.
+        */
+       __s32 parent_fd;
+       /*
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -292,14 +292,13 @@ out_fdput:
+  *
+  * - EOPNOTSUPP: Landlock is supported by the kernel but disabled at boot time;
+  * - EINVAL: @flags is not 0, or inconsistent access in the rule (i.e.
+- *   &landlock_path_beneath_attr.allowed_access is not a subset of the rule's
+- *   accesses);
++ *   &landlock_path_beneath_attr.allowed_access is not a subset of the
++ *   ruleset handled accesses);
+  * - ENOMSG: Empty accesses (e.g. &landlock_path_beneath_attr.allowed_access);
+  * - EBADF: @ruleset_fd is not a file descriptor for the current thread, or a
+  *   member of @rule_attr is not a file descriptor as expected;
+  * - EBADFD: @ruleset_fd is not a ruleset file descriptor, or a member of
+- *   @rule_attr is not the expected file descriptor type (e.g. file open
+- *   without O_PATH);
++ *   @rule_attr is not the expected file descriptor type;
+  * - EPERM: @ruleset_fd has no write access to the underlying ruleset;
+  * - EFAULT: @rule_attr inconsistency.
+  */
diff --git a/queue-5.18/landlock-fix-same-layer-rule-unions.patch b/queue-5.18/landlock-fix-same-layer-rule-unions.patch
new file mode 100644 (file)
index 0000000..0c93138
--- /dev/null
@@ -0,0 +1,311 @@
+From 8ba0005ff418ec356e176b26eaa04a6ac755d05b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:10:54 +0200
+Subject: landlock: Fix same-layer rule unions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 8ba0005ff418ec356e176b26eaa04a6ac755d05b upstream.
+
+The original behavior was to check if the full set of requested accesses
+was allowed by at least a rule of every relevant layer.  This didn't
+take into account requests for multiple accesses and same-layer rules
+allowing the union of these accesses in a complementary way.  As a
+result, multiple accesses requested on a file hierarchy matching rules
+that, together, allowed these accesses, but without a unique rule
+allowing all of them, was illegitimately denied.  This case should be
+rare in practice and it can only be triggered by the path_rename or
+file_open hook implementations.
+
+For instance, if, for the same layer, a rule allows execution
+beneath /a/b and another rule allows read beneath /a, requesting access
+to read and execute at the same time for /a/b should be allowed for this
+layer.
+
+This was an inconsistency because the union of same-layer rule accesses
+was already allowed if requested once at a time anyway.
+
+This fix changes the way allowed accesses are gathered over a path walk.
+To take into account all these rule accesses, we store in a matrix all
+layer granting the set of requested accesses, according to the handled
+accesses.  To avoid heap allocation, we use an array on the stack which
+is 2*13 bytes.  A following commit bringing the LANDLOCK_ACCESS_FS_REFER
+access right will increase this size to reach 112 bytes (2*14*4) in case
+of link or rename actions.
+
+Add a new layout1.layer_rule_unions test to check that accesses from
+different rules pertaining to the same layer are ORed in a file
+hierarchy.  Also test that it is not the case for rules from different
+layers.
+
+Reviewed-by: Paul Moore <paul@paul-moore.com>
+Link: https://lore.kernel.org/r/20220506161102.525323-5-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/fs.c                     |   80 ++++++++++++++-------
+ security/landlock/ruleset.h                |    2 
+ tools/testing/selftests/landlock/fs_test.c |  107 +++++++++++++++++++++++++++++
+ 3 files changed, 162 insertions(+), 27 deletions(-)
+
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -207,45 +207,67 @@ find_rule(const struct landlock_ruleset
+       return rule;
+ }
+-static inline layer_mask_t unmask_layers(const struct landlock_rule *const rule,
+-                                       const access_mask_t access_request,
+-                                       layer_mask_t layer_mask)
++/*
++ * @layer_masks is read and may be updated according to the access request and
++ * the matching rule.
++ *
++ * Returns true if the request is allowed (i.e. relevant layer masks for the
++ * request are empty).
++ */
++static inline bool
++unmask_layers(const struct landlock_rule *const rule,
++            const access_mask_t access_request,
++            layer_mask_t (*const layer_masks)[LANDLOCK_NUM_ACCESS_FS])
+ {
+       size_t layer_level;
++      if (!access_request || !layer_masks)
++              return true;
+       if (!rule)
+-              return layer_mask;
++              return false;
+       /*
+        * An access is granted if, for each policy layer, at least one rule
+-       * encountered on the pathwalk grants the requested accesses,
+-       * regardless of their position in the layer stack.  We must then check
++       * encountered on the pathwalk grants the requested access,
++       * regardless of its position in the layer stack.  We must then check
+        * the remaining layers for each inode, from the first added layer to
+-       * the last one.
++       * the last one.  When there is multiple requested accesses, for each
++       * policy layer, the full set of requested accesses may not be granted
++       * by only one rule, but by the union (binary OR) of multiple rules.
++       * E.g. /a/b <execute> + /a <read> => /a/b <execute + read>
+        */
+       for (layer_level = 0; layer_level < rule->num_layers; layer_level++) {
+               const struct landlock_layer *const layer =
+                       &rule->layers[layer_level];
+               const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
+-
+-              /* Checks that the layer grants access to the full request. */
+-              if ((layer->access & access_request) == access_request) {
+-                      layer_mask &= ~layer_bit;
+-
+-                      if (layer_mask == 0)
+-                              return layer_mask;
++              const unsigned long access_req = access_request;
++              unsigned long access_bit;
++              bool is_empty;
++
++              /*
++               * Records in @layer_masks which layer grants access to each
++               * requested access.
++               */
++              is_empty = true;
++              for_each_set_bit(access_bit, &access_req,
++                               ARRAY_SIZE(*layer_masks)) {
++                      if (layer->access & BIT_ULL(access_bit))
++                              (*layer_masks)[access_bit] &= ~layer_bit;
++                      is_empty = is_empty && !(*layer_masks)[access_bit];
+               }
++              if (is_empty)
++                      return true;
+       }
+-      return layer_mask;
++      return false;
+ }
+ static int check_access_path(const struct landlock_ruleset *const domain,
+                            const struct path *const path,
+                            const access_mask_t access_request)
+ {
+-      bool allowed = false;
++      layer_mask_t layer_masks[LANDLOCK_NUM_ACCESS_FS] = {};
++      bool allowed = false, has_access = false;
+       struct path walker_path;
+-      layer_mask_t layer_mask;
+       size_t i;
+       if (!access_request)
+@@ -265,13 +287,20 @@ static int check_access_path(const struc
+               return -EACCES;
+       /* Saves all layers handling a subset of requested accesses. */
+-      layer_mask = 0;
+       for (i = 0; i < domain->num_layers; i++) {
+-              if (domain->fs_access_masks[i] & access_request)
+-                      layer_mask |= BIT_ULL(i);
++              const unsigned long access_req = access_request;
++              unsigned long access_bit;
++
++              for_each_set_bit(access_bit, &access_req,
++                               ARRAY_SIZE(layer_masks)) {
++                      if (domain->fs_access_masks[i] & BIT_ULL(access_bit)) {
++                              layer_masks[access_bit] |= BIT_ULL(i);
++                              has_access = true;
++                      }
++              }
+       }
+       /* An access request not handled by the domain is allowed. */
+-      if (layer_mask == 0)
++      if (!has_access)
+               return 0;
+       walker_path = *path;
+@@ -283,14 +312,11 @@ static int check_access_path(const struc
+       while (true) {
+               struct dentry *parent_dentry;
+-              layer_mask =
+-                      unmask_layers(find_rule(domain, walker_path.dentry),
+-                                    access_request, layer_mask);
+-              if (layer_mask == 0) {
++              allowed = unmask_layers(find_rule(domain, walker_path.dentry),
++                                      access_request, &layer_masks);
++              if (allowed)
+                       /* Stops when a rule from each layer grants access. */
+-                      allowed = true;
+                       break;
+-              }
+ jump_up:
+               if (walker_path.dentry == walker_path.mnt->mnt_root) {
+--- a/security/landlock/ruleset.h
++++ b/security/landlock/ruleset.h
+@@ -22,6 +22,8 @@
+ typedef u16 access_mask_t;
+ /* Makes sure all filesystem access rights can be stored. */
+ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
++/* Makes sure for_each_set_bit() and for_each_clear_bit() calls are OK. */
++static_assert(sizeof(unsigned long) >= sizeof(access_mask_t));
+ typedef u16 layer_mask_t;
+ /* Makes sure all layers can be checked. */
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -758,6 +758,113 @@ TEST_F_FORK(layout1, ruleset_overlap)
+       ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY | O_DIRECTORY));
+ }
++TEST_F_FORK(layout1, layer_rule_unions)
++{
++      const struct rule layer1[] = {
++              {
++                      .path = dir_s1d2,
++                      .access = LANDLOCK_ACCESS_FS_READ_FILE,
++              },
++              /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
++              {
++                      .path = dir_s1d3,
++                      .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
++              },
++              {},
++      };
++      const struct rule layer2[] = {
++              /* Doesn't change anything from layer1. */
++              {
++                      .path = dir_s1d2,
++                      .access = LANDLOCK_ACCESS_FS_READ_FILE |
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
++              },
++              {},
++      };
++      const struct rule layer3[] = {
++              /* Only allows write (but not read) to dir_s1d3. */
++              {
++                      .path = dir_s1d2,
++                      .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
++              },
++              {},
++      };
++      int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer1);
++
++      ASSERT_LE(0, ruleset_fd);
++      enforce_ruleset(_metadata, ruleset_fd);
++      ASSERT_EQ(0, close(ruleset_fd));
++
++      /* Checks s1d1 hierarchy with layer1. */
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d2 hierarchy with layer1. */
++      ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d3 hierarchy with layer1. */
++      ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
++      ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
++      /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
++      ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Doesn't change anything from layer1. */
++      ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer2);
++      ASSERT_LE(0, ruleset_fd);
++      enforce_ruleset(_metadata, ruleset_fd);
++      ASSERT_EQ(0, close(ruleset_fd));
++
++      /* Checks s1d1 hierarchy with layer2. */
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d2 hierarchy with layer2. */
++      ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d3 hierarchy with layer2. */
++      ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
++      ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
++      /* dir_s1d3 should allow READ_FILE and WRITE_FILE (O_RDWR). */
++      ASSERT_EQ(0, test_open(file1_s1d3, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Only allows write (but not read) to dir_s1d3. */
++      ruleset_fd = create_ruleset(_metadata, ACCESS_RW, layer3);
++      ASSERT_LE(0, ruleset_fd);
++      enforce_ruleset(_metadata, ruleset_fd);
++      ASSERT_EQ(0, close(ruleset_fd));
++
++      /* Checks s1d1 hierarchy with layer3. */
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d2 hierarchy with layer3. */
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_WRONLY));
++      ASSERT_EQ(EACCES, test_open(file1_s1d2, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++
++      /* Checks s1d3 hierarchy with layer3. */
++      ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDONLY));
++      ASSERT_EQ(0, test_open(file1_s1d3, O_WRONLY));
++      /* dir_s1d3 should now deny READ_FILE and WRITE_FILE (O_RDWR). */
++      ASSERT_EQ(EACCES, test_open(file1_s1d3, O_RDWR));
++      ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY | O_DIRECTORY));
++}
++
+ TEST_F_FORK(layout1, non_overlapping_accesses)
+ {
+       const struct rule layer1[] = {
diff --git a/queue-5.18/landlock-format-with-clang-format.patch b/queue-5.18/landlock-format-with-clang-format.patch
new file mode 100644 (file)
index 0000000..5324b3c
--- /dev/null
@@ -0,0 +1,840 @@
+From 06a1c40a09a8dded4bf0e7e3ccbda6bddcccd7c8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:08 +0200
+Subject: landlock: Format with clang-format
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 06a1c40a09a8dded4bf0e7e3ccbda6bddcccd7c8 upstream.
+
+Let's follow a consistent and documented coding style.  Everything may
+not be to our liking but it is better than tacit knowledge.  Moreover,
+this will help maintain style consistency between different developers.
+
+This contains only whitespace changes.
+
+Automatically formatted with:
+clang-format-14 -i security/landlock/*.[ch] include/uapi/linux/landlock.h
+
+Link: https://lore.kernel.org/r/20220506160513.523257-3-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ security/landlock/cred.c     |    4 +-
+ security/landlock/cred.h     |    8 ++--
+ security/landlock/fs.c       |   78 +++++++++++++++++++++--------------------
+ security/landlock/fs.h       |   11 +++--
+ security/landlock/object.c   |    6 +--
+ security/landlock/object.h   |    6 +--
+ security/landlock/ptrace.c   |   10 ++---
+ security/landlock/ruleset.c  |   80 +++++++++++++++++++++----------------------
+ security/landlock/ruleset.h  |   15 ++++----
+ security/landlock/syscalls.c |   60 ++++++++++++++++----------------
+ 10 files changed, 142 insertions(+), 136 deletions(-)
+
+--- a/security/landlock/cred.c
++++ b/security/landlock/cred.c
+@@ -15,7 +15,7 @@
+ #include "setup.h"
+ static int hook_cred_prepare(struct cred *const new,
+-              const struct cred *const old, const gfp_t gfp)
++                           const struct cred *const old, const gfp_t gfp)
+ {
+       struct landlock_ruleset *const old_dom = landlock_cred(old)->domain;
+@@ -42,5 +42,5 @@ static struct security_hook_list landloc
+ __init void landlock_add_cred_hooks(void)
+ {
+       security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-                      LANDLOCK_NAME);
++                         LANDLOCK_NAME);
+ }
+--- a/security/landlock/cred.h
++++ b/security/landlock/cred.h
+@@ -20,8 +20,8 @@ struct landlock_cred_security {
+       struct landlock_ruleset *domain;
+ };
+-static inline struct landlock_cred_security *landlock_cred(
+-              const struct cred *cred)
++static inline struct landlock_cred_security *
++landlock_cred(const struct cred *cred)
+ {
+       return cred->security + landlock_blob_sizes.lbs_cred;
+ }
+@@ -34,8 +34,8 @@ static inline const struct landlock_rule
+ /*
+  * The call needs to come from an RCU read-side critical section.
+  */
+-static inline const struct landlock_ruleset *landlock_get_task_domain(
+-              const struct task_struct *const task)
++static inline const struct landlock_ruleset *
++landlock_get_task_domain(const struct task_struct *const task)
+ {
+       return landlock_cred(__task_cred(task))->domain;
+ }
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -152,14 +152,14 @@ retry:
+  * @path: Should have been checked by get_path_from_fd().
+  */
+ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
+-              const struct path *const path, u32 access_rights)
++                          const struct path *const path, u32 access_rights)
+ {
+       int err;
+       struct landlock_object *object;
+       /* Files only get access rights that make sense. */
+-      if (!d_is_dir(path->dentry) && (access_rights | ACCESS_FILE) !=
+-                      ACCESS_FILE)
++      if (!d_is_dir(path->dentry) &&
++          (access_rights | ACCESS_FILE) != ACCESS_FILE)
+               return -EINVAL;
+       if (WARN_ON_ONCE(ruleset->num_layers != 1))
+               return -EINVAL;
+@@ -182,10 +182,9 @@ int landlock_append_fs_rule(struct landl
+ /* Access-control management */
+-static inline u64 unmask_layers(
+-              const struct landlock_ruleset *const domain,
+-              const struct path *const path, const u32 access_request,
+-              u64 layer_mask)
++static inline u64 unmask_layers(const struct landlock_ruleset *const domain,
++                              const struct path *const path,
++                              const u32 access_request, u64 layer_mask)
+ {
+       const struct landlock_rule *rule;
+       const struct inode *inode;
+@@ -196,8 +195,8 @@ static inline u64 unmask_layers(
+               return layer_mask;
+       inode = d_backing_inode(path->dentry);
+       rcu_read_lock();
+-      rule = landlock_find_rule(domain,
+-                      rcu_dereference(landlock_inode(inode)->object));
++      rule = landlock_find_rule(
++              domain, rcu_dereference(landlock_inode(inode)->object));
+       rcu_read_unlock();
+       if (!rule)
+               return layer_mask;
+@@ -225,7 +224,7 @@ static inline u64 unmask_layers(
+ }
+ static int check_access_path(const struct landlock_ruleset *const domain,
+-              const struct path *const path, u32 access_request)
++                           const struct path *const path, u32 access_request)
+ {
+       bool allowed = false;
+       struct path walker_path;
+@@ -245,8 +244,8 @@ static int check_access_path(const struc
+        * /proc/<pid>/fd/<file-descriptor> .
+        */
+       if ((path->dentry->d_sb->s_flags & SB_NOUSER) ||
+-                      (d_is_positive(path->dentry) &&
+-                       unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))))
++          (d_is_positive(path->dentry) &&
++           unlikely(IS_PRIVATE(d_backing_inode(path->dentry)))))
+               return 0;
+       if (WARN_ON_ONCE(domain->num_layers < 1))
+               return -EACCES;
+@@ -270,8 +269,8 @@ static int check_access_path(const struc
+       while (true) {
+               struct dentry *parent_dentry;
+-              layer_mask = unmask_layers(domain, &walker_path,
+-                              access_request, layer_mask);
++              layer_mask = unmask_layers(domain, &walker_path, access_request,
++                                         layer_mask);
+               if (layer_mask == 0) {
+                       /* Stops when a rule from each layer grants access. */
+                       allowed = true;
+@@ -310,7 +309,7 @@ jump_up:
+ }
+ static inline int current_check_access_path(const struct path *const path,
+-              const u32 access_request)
++                                          const u32 access_request)
+ {
+       const struct landlock_ruleset *const dom =
+               landlock_get_current_domain();
+@@ -438,8 +437,8 @@ static void hook_sb_delete(struct super_
+       if (prev_inode)
+               iput(prev_inode);
+       /* Waits for pending iput() in release_inode(). */
+-      wait_var_event(&landlock_superblock(sb)->inode_refs, !atomic_long_read(
+-                              &landlock_superblock(sb)->inode_refs));
++      wait_var_event(&landlock_superblock(sb)->inode_refs,
++                     !atomic_long_read(&landlock_superblock(sb)->inode_refs));
+ }
+ /*
+@@ -461,8 +460,8 @@ static void hook_sb_delete(struct super_
+  * a dedicated user space option would be required (e.g. as a ruleset flag).
+  */
+ static int hook_sb_mount(const char *const dev_name,
+-              const struct path *const path, const char *const type,
+-              const unsigned long flags, void *const data)
++                       const struct path *const path, const char *const type,
++                       const unsigned long flags, void *const data)
+ {
+       if (!landlock_get_current_domain())
+               return 0;
+@@ -470,7 +469,7 @@ static int hook_sb_mount(const char *con
+ }
+ static int hook_move_mount(const struct path *const from_path,
+-              const struct path *const to_path)
++                         const struct path *const to_path)
+ {
+       if (!landlock_get_current_domain())
+               return 0;
+@@ -504,7 +503,7 @@ static int hook_sb_remount(struct super_
+  * view of the filesystem.
+  */
+ static int hook_sb_pivotroot(const struct path *const old_path,
+-              const struct path *const new_path)
++                           const struct path *const new_path)
+ {
+       if (!landlock_get_current_domain())
+               return 0;
+@@ -547,8 +546,8 @@ static inline u32 get_mode_access(const
+  * deal with that.
+  */
+ static int hook_path_link(struct dentry *const old_dentry,
+-              const struct path *const new_dir,
+-              struct dentry *const new_dentry)
++                        const struct path *const new_dir,
++                        struct dentry *const new_dentry)
+ {
+       const struct landlock_ruleset *const dom =
+               landlock_get_current_domain();
+@@ -561,8 +560,9 @@ static int hook_path_link(struct dentry
+               return -EXDEV;
+       if (unlikely(d_is_negative(old_dentry)))
+               return -ENOENT;
+-      return check_access_path(dom, new_dir,
+-                      get_mode_access(d_backing_inode(old_dentry)->i_mode));
++      return check_access_path(
++              dom, new_dir,
++              get_mode_access(d_backing_inode(old_dentry)->i_mode));
+ }
+ static inline u32 maybe_remove(const struct dentry *const dentry)
+@@ -570,13 +570,13 @@ static inline u32 maybe_remove(const str
+       if (d_is_negative(dentry))
+               return 0;
+       return d_is_dir(dentry) ? LANDLOCK_ACCESS_FS_REMOVE_DIR :
+-              LANDLOCK_ACCESS_FS_REMOVE_FILE;
++                                LANDLOCK_ACCESS_FS_REMOVE_FILE;
+ }
+ static int hook_path_rename(const struct path *const old_dir,
+-              struct dentry *const old_dentry,
+-              const struct path *const new_dir,
+-              struct dentry *const new_dentry)
++                          struct dentry *const old_dentry,
++                          const struct path *const new_dir,
++                          struct dentry *const new_dentry)
+ {
+       const struct landlock_ruleset *const dom =
+               landlock_get_current_domain();
+@@ -590,20 +590,21 @@ static int hook_path_rename(const struct
+       if (unlikely(d_is_negative(old_dentry)))
+               return -ENOENT;
+       /* RENAME_EXCHANGE is handled because directories are the same. */
+-      return check_access_path(dom, old_dir, maybe_remove(old_dentry) |
+-                      maybe_remove(new_dentry) |
++      return check_access_path(
++              dom, old_dir,
++              maybe_remove(old_dentry) | maybe_remove(new_dentry) |
+                       get_mode_access(d_backing_inode(old_dentry)->i_mode));
+ }
+ static int hook_path_mkdir(const struct path *const dir,
+-              struct dentry *const dentry, const umode_t mode)
++                         struct dentry *const dentry, const umode_t mode)
+ {
+       return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_DIR);
+ }
+ static int hook_path_mknod(const struct path *const dir,
+-              struct dentry *const dentry, const umode_t mode,
+-              const unsigned int dev)
++                         struct dentry *const dentry, const umode_t mode,
++                         const unsigned int dev)
+ {
+       const struct landlock_ruleset *const dom =
+               landlock_get_current_domain();
+@@ -614,19 +615,20 @@ static int hook_path_mknod(const struct
+ }
+ static int hook_path_symlink(const struct path *const dir,
+-              struct dentry *const dentry, const char *const old_name)
++                           struct dentry *const dentry,
++                           const char *const old_name)
+ {
+       return current_check_access_path(dir, LANDLOCK_ACCESS_FS_MAKE_SYM);
+ }
+ static int hook_path_unlink(const struct path *const dir,
+-              struct dentry *const dentry)
++                          struct dentry *const dentry)
+ {
+       return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_FILE);
+ }
+ static int hook_path_rmdir(const struct path *const dir,
+-              struct dentry *const dentry)
++                         struct dentry *const dentry)
+ {
+       return current_check_access_path(dir, LANDLOCK_ACCESS_FS_REMOVE_DIR);
+ }
+@@ -690,5 +692,5 @@ static struct security_hook_list landloc
+ __init void landlock_add_fs_hooks(void)
+ {
+       security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-                      LANDLOCK_NAME);
++                         LANDLOCK_NAME);
+ }
+--- a/security/landlock/fs.h
++++ b/security/landlock/fs.h
+@@ -50,14 +50,14 @@ struct landlock_superblock_security {
+       atomic_long_t inode_refs;
+ };
+-static inline struct landlock_inode_security *landlock_inode(
+-              const struct inode *const inode)
++static inline struct landlock_inode_security *
++landlock_inode(const struct inode *const inode)
+ {
+       return inode->i_security + landlock_blob_sizes.lbs_inode;
+ }
+-static inline struct landlock_superblock_security *landlock_superblock(
+-              const struct super_block *const superblock)
++static inline struct landlock_superblock_security *
++landlock_superblock(const struct super_block *const superblock)
+ {
+       return superblock->s_security + landlock_blob_sizes.lbs_superblock;
+ }
+@@ -65,6 +65,7 @@ static inline struct landlock_superblock
+ __init void landlock_add_fs_hooks(void);
+ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
+-              const struct path *const path, u32 access_hierarchy);
++                          const struct path *const path,
++                          u32 access_hierarchy);
+ #endif /* _SECURITY_LANDLOCK_FS_H */
+--- a/security/landlock/object.c
++++ b/security/landlock/object.c
+@@ -17,9 +17,9 @@
+ #include "object.h"
+-struct landlock_object *landlock_create_object(
+-              const struct landlock_object_underops *const underops,
+-              void *const underobj)
++struct landlock_object *
++landlock_create_object(const struct landlock_object_underops *const underops,
++                     void *const underobj)
+ {
+       struct landlock_object *new_object;
+--- a/security/landlock/object.h
++++ b/security/landlock/object.h
+@@ -76,9 +76,9 @@ struct landlock_object {
+       };
+ };
+-struct landlock_object *landlock_create_object(
+-              const struct landlock_object_underops *const underops,
+-              void *const underobj);
++struct landlock_object *
++landlock_create_object(const struct landlock_object_underops *const underops,
++                     void *const underobj);
+ void landlock_put_object(struct landlock_object *const object);
+--- a/security/landlock/ptrace.c
++++ b/security/landlock/ptrace.c
+@@ -30,7 +30,7 @@
+  * means a subset of) the @child domain.
+  */
+ static bool domain_scope_le(const struct landlock_ruleset *const parent,
+-              const struct landlock_ruleset *const child)
++                          const struct landlock_ruleset *const child)
+ {
+       const struct landlock_hierarchy *walker;
+@@ -48,7 +48,7 @@ static bool domain_scope_le(const struct
+ }
+ static bool task_is_scoped(const struct task_struct *const parent,
+-              const struct task_struct *const child)
++                         const struct task_struct *const child)
+ {
+       bool is_scoped;
+       const struct landlock_ruleset *dom_parent, *dom_child;
+@@ -62,7 +62,7 @@ static bool task_is_scoped(const struct
+ }
+ static int task_ptrace(const struct task_struct *const parent,
+-              const struct task_struct *const child)
++                     const struct task_struct *const child)
+ {
+       /* Quick return for non-landlocked tasks. */
+       if (!landlocked(parent))
+@@ -86,7 +86,7 @@ static int task_ptrace(const struct task
+  * granted, -errno if denied.
+  */
+ static int hook_ptrace_access_check(struct task_struct *const child,
+-              const unsigned int mode)
++                                  const unsigned int mode)
+ {
+       return task_ptrace(current, child);
+ }
+@@ -116,5 +116,5 @@ static struct security_hook_list landloc
+ __init void landlock_add_ptrace_hooks(void)
+ {
+       security_add_hooks(landlock_hooks, ARRAY_SIZE(landlock_hooks),
+-                      LANDLOCK_NAME);
++                         LANDLOCK_NAME);
+ }
+--- a/security/landlock/ruleset.c
++++ b/security/landlock/ruleset.c
+@@ -28,8 +28,9 @@ static struct landlock_ruleset *create_r
+ {
+       struct landlock_ruleset *new_ruleset;
+-      new_ruleset = kzalloc(struct_size(new_ruleset, fs_access_masks,
+-                              num_layers), GFP_KERNEL_ACCOUNT);
++      new_ruleset =
++              kzalloc(struct_size(new_ruleset, fs_access_masks, num_layers),
++                      GFP_KERNEL_ACCOUNT);
+       if (!new_ruleset)
+               return ERR_PTR(-ENOMEM);
+       refcount_set(&new_ruleset->usage, 1);
+@@ -66,11 +67,10 @@ static void build_check_rule(void)
+       BUILD_BUG_ON(rule.num_layers < LANDLOCK_MAX_NUM_LAYERS);
+ }
+-static struct landlock_rule *create_rule(
+-              struct landlock_object *const object,
+-              const struct landlock_layer (*const layers)[],
+-              const u32 num_layers,
+-              const struct landlock_layer *const new_layer)
++static struct landlock_rule *
++create_rule(struct landlock_object *const object,
++          const struct landlock_layer (*const layers)[], const u32 num_layers,
++          const struct landlock_layer *const new_layer)
+ {
+       struct landlock_rule *new_rule;
+       u32 new_num_layers;
+@@ -85,7 +85,7 @@ static struct landlock_rule *create_rule
+               new_num_layers = num_layers;
+       }
+       new_rule = kzalloc(struct_size(new_rule, layers, new_num_layers),
+-                      GFP_KERNEL_ACCOUNT);
++                         GFP_KERNEL_ACCOUNT);
+       if (!new_rule)
+               return ERR_PTR(-ENOMEM);
+       RB_CLEAR_NODE(&new_rule->node);
+@@ -94,7 +94,7 @@ static struct landlock_rule *create_rule
+       new_rule->num_layers = new_num_layers;
+       /* Copies the original layer stack. */
+       memcpy(new_rule->layers, layers,
+-                      flex_array_size(new_rule, layers, num_layers));
++             flex_array_size(new_rule, layers, num_layers));
+       if (new_layer)
+               /* Adds a copy of @new_layer on the layer stack. */
+               new_rule->layers[new_rule->num_layers - 1] = *new_layer;
+@@ -142,9 +142,9 @@ static void build_check_ruleset(void)
+  * access rights.
+  */
+ static int insert_rule(struct landlock_ruleset *const ruleset,
+-              struct landlock_object *const object,
+-              const struct landlock_layer (*const layers)[],
+-              size_t num_layers)
++                     struct landlock_object *const object,
++                     const struct landlock_layer (*const layers)[],
++                     size_t num_layers)
+ {
+       struct rb_node **walker_node;
+       struct rb_node *parent_node = NULL;
+@@ -156,8 +156,8 @@ static int insert_rule(struct landlock_r
+               return -ENOENT;
+       walker_node = &(ruleset->root.rb_node);
+       while (*walker_node) {
+-              struct landlock_rule *const this = rb_entry(*walker_node,
+-                              struct landlock_rule, node);
++              struct landlock_rule *const this =
++                      rb_entry(*walker_node, struct landlock_rule, node);
+               if (this->object != object) {
+                       parent_node = *walker_node;
+@@ -194,7 +194,7 @@ static int insert_rule(struct landlock_r
+                * ruleset and a domain.
+                */
+               new_rule = create_rule(object, &this->layers, this->num_layers,
+-                              &(*layers)[0]);
++                                     &(*layers)[0]);
+               if (IS_ERR(new_rule))
+                       return PTR_ERR(new_rule);
+               rb_replace_node(&this->node, &new_rule->node, &ruleset->root);
+@@ -228,13 +228,13 @@ static void build_check_layer(void)
+ /* @ruleset must be locked by the caller. */
+ int landlock_insert_rule(struct landlock_ruleset *const ruleset,
+-              struct landlock_object *const object, const u32 access)
++                       struct landlock_object *const object, const u32 access)
+ {
+-      struct landlock_layer layers[] = {{
++      struct landlock_layer layers[] = { {
+               .access = access,
+               /* When @level is zero, insert_rule() extends @ruleset. */
+               .level = 0,
+-      }};
++      } };
+       build_check_layer();
+       return insert_rule(ruleset, object, &layers, ARRAY_SIZE(layers));
+@@ -257,7 +257,7 @@ static void put_hierarchy(struct landloc
+ }
+ static int merge_ruleset(struct landlock_ruleset *const dst,
+-              struct landlock_ruleset *const src)
++                       struct landlock_ruleset *const src)
+ {
+       struct landlock_rule *walker_rule, *next_rule;
+       int err = 0;
+@@ -282,11 +282,11 @@ static int merge_ruleset(struct landlock
+       dst->fs_access_masks[dst->num_layers - 1] = src->fs_access_masks[0];
+       /* Merges the @src tree. */
+-      rbtree_postorder_for_each_entry_safe(walker_rule, next_rule,
+-                      &src->root, node) {
+-              struct landlock_layer layers[] = {{
++      rbtree_postorder_for_each_entry_safe(walker_rule, next_rule, &src->root,
++                                           node) {
++              struct landlock_layer layers[] = { {
+                       .level = dst->num_layers,
+-              }};
++              } };
+               if (WARN_ON_ONCE(walker_rule->num_layers != 1)) {
+                       err = -EINVAL;
+@@ -298,7 +298,7 @@ static int merge_ruleset(struct landlock
+               }
+               layers[0].access = walker_rule->layers[0].access;
+               err = insert_rule(dst, walker_rule->object, &layers,
+-                              ARRAY_SIZE(layers));
++                                ARRAY_SIZE(layers));
+               if (err)
+                       goto out_unlock;
+       }
+@@ -310,7 +310,7 @@ out_unlock:
+ }
+ static int inherit_ruleset(struct landlock_ruleset *const parent,
+-              struct landlock_ruleset *const child)
++                         struct landlock_ruleset *const child)
+ {
+       struct landlock_rule *walker_rule, *next_rule;
+       int err = 0;
+@@ -325,9 +325,10 @@ static int inherit_ruleset(struct landlo
+       /* Copies the @parent tree. */
+       rbtree_postorder_for_each_entry_safe(walker_rule, next_rule,
+-                      &parent->root, node) {
++                                           &parent->root, node) {
+               err = insert_rule(child, walker_rule->object,
+-                              &walker_rule->layers, walker_rule->num_layers);
++                                &walker_rule->layers,
++                                walker_rule->num_layers);
+               if (err)
+                       goto out_unlock;
+       }
+@@ -338,7 +339,7 @@ static int inherit_ruleset(struct landlo
+       }
+       /* Copies the parent layer stack and leaves a space for the new layer. */
+       memcpy(child->fs_access_masks, parent->fs_access_masks,
+-                      flex_array_size(parent, fs_access_masks, parent->num_layers));
++             flex_array_size(parent, fs_access_masks, parent->num_layers));
+       if (WARN_ON_ONCE(!parent->hierarchy)) {
+               err = -EINVAL;
+@@ -358,8 +359,7 @@ static void free_ruleset(struct landlock
+       struct landlock_rule *freeme, *next;
+       might_sleep();
+-      rbtree_postorder_for_each_entry_safe(freeme, next, &ruleset->root,
+-                      node)
++      rbtree_postorder_for_each_entry_safe(freeme, next, &ruleset->root, node)
+               free_rule(freeme);
+       put_hierarchy(ruleset->hierarchy);
+       kfree(ruleset);
+@@ -397,9 +397,9 @@ void landlock_put_ruleset_deferred(struc
+  * Returns the intersection of @parent and @ruleset, or returns @parent if
+  * @ruleset is empty, or returns a duplicate of @ruleset if @parent is empty.
+  */
+-struct landlock_ruleset *landlock_merge_ruleset(
+-              struct landlock_ruleset *const parent,
+-              struct landlock_ruleset *const ruleset)
++struct landlock_ruleset *
++landlock_merge_ruleset(struct landlock_ruleset *const parent,
++                     struct landlock_ruleset *const ruleset)
+ {
+       struct landlock_ruleset *new_dom;
+       u32 num_layers;
+@@ -421,8 +421,8 @@ struct landlock_ruleset *landlock_merge_
+       new_dom = create_ruleset(num_layers);
+       if (IS_ERR(new_dom))
+               return new_dom;
+-      new_dom->hierarchy = kzalloc(sizeof(*new_dom->hierarchy),
+-                      GFP_KERNEL_ACCOUNT);
++      new_dom->hierarchy =
++              kzalloc(sizeof(*new_dom->hierarchy), GFP_KERNEL_ACCOUNT);
+       if (!new_dom->hierarchy) {
+               err = -ENOMEM;
+               goto out_put_dom;
+@@ -449,9 +449,9 @@ out_put_dom:
+ /*
+  * The returned access has the same lifetime as @ruleset.
+  */
+-const struct landlock_rule *landlock_find_rule(
+-              const struct landlock_ruleset *const ruleset,
+-              const struct landlock_object *const object)
++const struct landlock_rule *
++landlock_find_rule(const struct landlock_ruleset *const ruleset,
++                 const struct landlock_object *const object)
+ {
+       const struct rb_node *node;
+@@ -459,8 +459,8 @@ const struct landlock_rule *landlock_fin
+               return NULL;
+       node = ruleset->root.rb_node;
+       while (node) {
+-              struct landlock_rule *this = rb_entry(node,
+-                              struct landlock_rule, node);
++              struct landlock_rule *this =
++                      rb_entry(node, struct landlock_rule, node);
+               if (this->object == object)
+                       return this;
+--- a/security/landlock/ruleset.h
++++ b/security/landlock/ruleset.h
+@@ -146,15 +146,16 @@ void landlock_put_ruleset(struct landloc
+ void landlock_put_ruleset_deferred(struct landlock_ruleset *const ruleset);
+ int landlock_insert_rule(struct landlock_ruleset *const ruleset,
+-              struct landlock_object *const object, const u32 access);
++                       struct landlock_object *const object,
++                       const u32 access);
+-struct landlock_ruleset *landlock_merge_ruleset(
+-              struct landlock_ruleset *const parent,
+-              struct landlock_ruleset *const ruleset);
++struct landlock_ruleset *
++landlock_merge_ruleset(struct landlock_ruleset *const parent,
++                     struct landlock_ruleset *const ruleset);
+-const struct landlock_rule *landlock_find_rule(
+-              const struct landlock_ruleset *const ruleset,
+-              const struct landlock_object *const object);
++const struct landlock_rule *
++landlock_find_rule(const struct landlock_ruleset *const ruleset,
++                 const struct landlock_object *const object);
+ static inline void landlock_get_ruleset(struct landlock_ruleset *const ruleset)
+ {
+--- a/security/landlock/syscalls.c
++++ b/security/landlock/syscalls.c
+@@ -43,9 +43,10 @@
+  * @src: User space pointer or NULL.
+  * @usize: (Alleged) size of the data pointed to by @src.
+  */
+-static __always_inline int copy_min_struct_from_user(void *const dst,
+-              const size_t ksize, const size_t ksize_min,
+-              const void __user *const src, const size_t usize)
++static __always_inline int
++copy_min_struct_from_user(void *const dst, const size_t ksize,
++                        const size_t ksize_min, const void __user *const src,
++                        const size_t usize)
+ {
+       /* Checks buffer inconsistencies. */
+       BUILD_BUG_ON(!dst);
+@@ -93,7 +94,7 @@ static void build_check_abi(void)
+ /* Ruleset handling */
+ static int fop_ruleset_release(struct inode *const inode,
+-              struct file *const filp)
++                             struct file *const filp)
+ {
+       struct landlock_ruleset *ruleset = filp->private_data;
+@@ -102,15 +103,15 @@ static int fop_ruleset_release(struct in
+ }
+ static ssize_t fop_dummy_read(struct file *const filp, char __user *const buf,
+-              const size_t size, loff_t *const ppos)
++                            const size_t size, loff_t *const ppos)
+ {
+       /* Dummy handler to enable FMODE_CAN_READ. */
+       return -EINVAL;
+ }
+ static ssize_t fop_dummy_write(struct file *const filp,
+-              const char __user *const buf, const size_t size,
+-              loff_t *const ppos)
++                             const char __user *const buf, const size_t size,
++                             loff_t *const ppos)
+ {
+       /* Dummy handler to enable FMODE_CAN_WRITE. */
+       return -EINVAL;
+@@ -128,7 +129,7 @@ static const struct file_operations rule
+       .write = fop_dummy_write,
+ };
+-#define LANDLOCK_ABI_VERSION  1
++#define LANDLOCK_ABI_VERSION 1
+ /**
+  * sys_landlock_create_ruleset - Create a new ruleset
+@@ -168,22 +169,23 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
+               return -EOPNOTSUPP;
+       if (flags) {
+-              if ((flags == LANDLOCK_CREATE_RULESET_VERSION)
+-                              && !attr && !size)
++              if ((flags == LANDLOCK_CREATE_RULESET_VERSION) && !attr &&
++                  !size)
+                       return LANDLOCK_ABI_VERSION;
+               return -EINVAL;
+       }
+       /* Copies raw user space buffer. */
+       err = copy_min_struct_from_user(&ruleset_attr, sizeof(ruleset_attr),
+-                      offsetofend(typeof(ruleset_attr), handled_access_fs),
+-                      attr, size);
++                                      offsetofend(typeof(ruleset_attr),
++                                                  handled_access_fs),
++                                      attr, size);
+       if (err)
+               return err;
+       /* Checks content (and 32-bits cast). */
+       if ((ruleset_attr.handled_access_fs | LANDLOCK_MASK_ACCESS_FS) !=
+-                      LANDLOCK_MASK_ACCESS_FS)
++          LANDLOCK_MASK_ACCESS_FS)
+               return -EINVAL;
+       /* Checks arguments and transforms to kernel struct. */
+@@ -193,7 +195,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
+       /* Creates anonymous FD referring to the ruleset. */
+       ruleset_fd = anon_inode_getfd("[landlock-ruleset]", &ruleset_fops,
+-                      ruleset, O_RDWR | O_CLOEXEC);
++                                    ruleset, O_RDWR | O_CLOEXEC);
+       if (ruleset_fd < 0)
+               landlock_put_ruleset(ruleset);
+       return ruleset_fd;
+@@ -204,7 +206,7 @@ SYSCALL_DEFINE3(landlock_create_ruleset,
+  * landlock_put_ruleset() on the return value.
+  */
+ static struct landlock_ruleset *get_ruleset_from_fd(const int fd,
+-              const fmode_t mode)
++                                                  const fmode_t mode)
+ {
+       struct fd ruleset_f;
+       struct landlock_ruleset *ruleset;
+@@ -244,8 +246,8 @@ static int get_path_from_fd(const s32 fd
+       struct fd f;
+       int err = 0;
+-      BUILD_BUG_ON(!__same_type(fd,
+-              ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
++      BUILD_BUG_ON(!__same_type(
++              fd, ((struct landlock_path_beneath_attr *)NULL)->parent_fd));
+       /* Handles O_PATH. */
+       f = fdget_raw(fd);
+@@ -257,10 +259,10 @@ static int get_path_from_fd(const s32 fd
+        * pipefs).
+        */
+       if ((f.file->f_op == &ruleset_fops) ||
+-                      (f.file->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
+-                      (f.file->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
+-                      d_is_negative(f.file->f_path.dentry) ||
+-                      IS_PRIVATE(d_backing_inode(f.file->f_path.dentry))) {
++          (f.file->f_path.mnt->mnt_flags & MNT_INTERNAL) ||
++          (f.file->f_path.dentry->d_sb->s_flags & SB_NOUSER) ||
++          d_is_negative(f.file->f_path.dentry) ||
++          IS_PRIVATE(d_backing_inode(f.file->f_path.dentry))) {
+               err = -EBADFD;
+               goto out_fdput;
+       }
+@@ -301,8 +303,8 @@ out_fdput:
+  * - EPERM: @ruleset_fd has no write access to the underlying ruleset;
+  * - EFAULT: @rule_attr inconsistency.
+  */
+-SYSCALL_DEFINE4(landlock_add_rule,
+-              const int, ruleset_fd, const enum landlock_rule_type, rule_type,
++SYSCALL_DEFINE4(landlock_add_rule, const int, ruleset_fd,
++              const enum landlock_rule_type, rule_type,
+               const void __user *const, rule_attr, const __u32, flags)
+ {
+       struct landlock_path_beneath_attr path_beneath_attr;
+@@ -322,7 +324,7 @@ SYSCALL_DEFINE4(landlock_add_rule,
+       /* Copies raw user space buffer, only one type for now. */
+       res = copy_from_user(&path_beneath_attr, rule_attr,
+-                      sizeof(path_beneath_attr));
++                           sizeof(path_beneath_attr));
+       if (res)
+               return -EFAULT;
+@@ -344,7 +346,7 @@ SYSCALL_DEFINE4(landlock_add_rule,
+        * (ruleset->fs_access_masks[0] is automatically upgraded to 64-bits).
+        */
+       if ((path_beneath_attr.allowed_access | ruleset->fs_access_masks[0]) !=
+-                      ruleset->fs_access_masks[0]) {
++          ruleset->fs_access_masks[0]) {
+               err = -EINVAL;
+               goto out_put_ruleset;
+       }
+@@ -356,7 +358,7 @@ SYSCALL_DEFINE4(landlock_add_rule,
+       /* Imports the new rule. */
+       err = landlock_append_fs_rule(ruleset, &path,
+-                      path_beneath_attr.allowed_access);
++                                    path_beneath_attr.allowed_access);
+       path_put(&path);
+ out_put_ruleset:
+@@ -389,8 +391,8 @@ out_put_ruleset:
+  * - E2BIG: The maximum number of stacked rulesets is reached for the current
+  *   thread.
+  */
+-SYSCALL_DEFINE2(landlock_restrict_self,
+-              const int, ruleset_fd, const __u32, flags)
++SYSCALL_DEFINE2(landlock_restrict_self, const int, ruleset_fd, const __u32,
++              flags)
+ {
+       struct landlock_ruleset *new_dom, *ruleset;
+       struct cred *new_cred;
+@@ -409,7 +411,7 @@ SYSCALL_DEFINE2(landlock_restrict_self,
+        * returned.
+        */
+       if (!task_no_new_privs(current) &&
+-                      !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
++          !ns_capable_noaudit(current_user_ns(), CAP_SYS_ADMIN))
+               return -EPERM;
+       /* Gets and checks the ruleset. */
diff --git a/queue-5.18/landlock-reduce-the-maximum-number-of-layers-to-16.patch b/queue-5.18/landlock-reduce-the-maximum-number-of-layers-to-16.patch
new file mode 100644 (file)
index 0000000..28238c9
--- /dev/null
@@ -0,0 +1,129 @@
+From 75c542d6c6cc48720376862d5496d51509160dfd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:10:52 +0200
+Subject: landlock: Reduce the maximum number of layers to 16
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 75c542d6c6cc48720376862d5496d51509160dfd upstream.
+
+The maximum number of nested Landlock domains is currently 64.  Because
+of the following fix and to help reduce the stack size, let's reduce it
+to 16.  This seems large enough for a lot of use cases (e.g. sandboxed
+init service, spawning a sandboxed SSH service, in nested sandboxed
+containers).  Reducing the number of nested domains may also help to
+discover misuse of Landlock (e.g. creating a domain per rule).
+
+Add and use a dedicated layer_mask_t typedef to fit with the number of
+layers.  This might be useful when changing it and to keep it consistent
+with the maximum number of layers.
+
+Reviewed-by: Paul Moore <paul@paul-moore.com>
+Link: https://lore.kernel.org/r/20220506161102.525323-3-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ Documentation/userspace-api/landlock.rst   |    4 ++--
+ security/landlock/fs.c                     |   17 +++++++----------
+ security/landlock/limits.h                 |    2 +-
+ security/landlock/ruleset.h                |    4 ++++
+ tools/testing/selftests/landlock/fs_test.c |    2 +-
+ 5 files changed, 15 insertions(+), 14 deletions(-)
+
+--- a/Documentation/userspace-api/landlock.rst
++++ b/Documentation/userspace-api/landlock.rst
+@@ -267,8 +267,8 @@ restrict such paths with dedicated rules
+ Ruleset layers
+ --------------
+-There is a limit of 64 layers of stacked rulesets.  This can be an issue for a
+-task willing to enforce a new ruleset in complement to its 64 inherited
++There is a limit of 16 layers of stacked rulesets.  This can be an issue for a
++task willing to enforce a new ruleset in complement to its 16 inherited
+ rulesets.  Once this limit is reached, sys_landlock_restrict_self() returns
+ E2BIG.  It is then strongly suggested to carefully build rulesets once in the
+ life of a thread, especially for applications able to launch other applications
+--- a/security/landlock/fs.c
++++ b/security/landlock/fs.c
+@@ -183,10 +183,10 @@ int landlock_append_fs_rule(struct landl
+ /* Access-control management */
+-static inline u64 unmask_layers(const struct landlock_ruleset *const domain,
+-                              const struct path *const path,
+-                              const access_mask_t access_request,
+-                              u64 layer_mask)
++static inline layer_mask_t
++unmask_layers(const struct landlock_ruleset *const domain,
++            const struct path *const path, const access_mask_t access_request,
++            layer_mask_t layer_mask)
+ {
+       const struct landlock_rule *rule;
+       const struct inode *inode;
+@@ -212,11 +212,11 @@ static inline u64 unmask_layers(const st
+        */
+       for (i = 0; i < rule->num_layers; i++) {
+               const struct landlock_layer *const layer = &rule->layers[i];
+-              const u64 layer_level = BIT_ULL(layer->level - 1);
++              const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
+               /* Checks that the layer grants access to the full request. */
+               if ((layer->access & access_request) == access_request) {
+-                      layer_mask &= ~layer_level;
++                      layer_mask &= ~layer_bit;
+                       if (layer_mask == 0)
+                               return layer_mask;
+@@ -231,12 +231,9 @@ static int check_access_path(const struc
+ {
+       bool allowed = false;
+       struct path walker_path;
+-      u64 layer_mask;
++      layer_mask_t layer_mask;
+       size_t i;
+-      /* Make sure all layers can be checked. */
+-      BUILD_BUG_ON(BITS_PER_TYPE(layer_mask) < LANDLOCK_MAX_NUM_LAYERS);
+-
+       if (!access_request)
+               return 0;
+       if (WARN_ON_ONCE(!domain || !path))
+--- a/security/landlock/limits.h
++++ b/security/landlock/limits.h
+@@ -15,7 +15,7 @@
+ /* clang-format off */
+-#define LANDLOCK_MAX_NUM_LAYERS               64
++#define LANDLOCK_MAX_NUM_LAYERS               16
+ #define LANDLOCK_MAX_NUM_RULES                U32_MAX
+ #define LANDLOCK_LAST_ACCESS_FS               LANDLOCK_ACCESS_FS_MAKE_SYM
+--- a/security/landlock/ruleset.h
++++ b/security/landlock/ruleset.h
+@@ -23,6 +23,10 @@ typedef u16 access_mask_t;
+ /* Makes sure all filesystem access rights can be stored. */
+ static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
++typedef u16 layer_mask_t;
++/* Makes sure all layers can be checked. */
++static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS);
++
+ /**
+  * struct landlock_layer - Access rights for a given layer
+  */
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -1159,7 +1159,7 @@ TEST_F_FORK(layout1, max_layers)
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+       ASSERT_LE(0, ruleset_fd);
+-      for (i = 0; i < 64; i++)
++      for (i = 0; i < 16; i++)
+               enforce_ruleset(_metadata, ruleset_fd);
+       for (i = 0; i < 2; i++) {
diff --git a/queue-5.18/samples-landlock-add-clang-format-exceptions.patch b/queue-5.18/samples-landlock-add-clang-format-exceptions.patch
new file mode 100644 (file)
index 0000000..d8b99b9
--- /dev/null
@@ -0,0 +1,61 @@
+From 9805a722db071e1772b80e6e0ff33f35355639ac Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:12 +0200
+Subject: samples/landlock: Add clang-format exceptions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 9805a722db071e1772b80e6e0ff33f35355639ac upstream.
+
+In preparation to a following commit, add clang-format on and
+clang-format off stanzas around constant definitions.  This enables to
+keep aligned values, which is much more readable than packed
+definitions.
+
+Link: https://lore.kernel.org/r/20220506160513.523257-7-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ samples/landlock/sandboxer.c |    8 ++++++++
+ 1 file changed, 8 insertions(+)
+
+--- a/samples/landlock/sandboxer.c
++++ b/samples/landlock/sandboxer.c
+@@ -70,11 +70,15 @@ static int parse_path(char *env_path, co
+       return num_paths;
+ }
++/* clang-format off */
++
+ #define ACCESS_FILE ( \
+       LANDLOCK_ACCESS_FS_EXECUTE | \
+       LANDLOCK_ACCESS_FS_WRITE_FILE | \
+       LANDLOCK_ACCESS_FS_READ_FILE)
++/* clang-format on */
++
+ static int populate_ruleset(
+               const char *const env_var, const int ruleset_fd,
+               const __u64 allowed_access)
+@@ -139,6 +143,8 @@ out_free_name:
+       return ret;
+ }
++/* clang-format off */
++
+ #define ACCESS_FS_ROUGHLY_READ ( \
+       LANDLOCK_ACCESS_FS_EXECUTE | \
+       LANDLOCK_ACCESS_FS_READ_FILE | \
+@@ -156,6 +162,8 @@ out_free_name:
+       LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
+       LANDLOCK_ACCESS_FS_MAKE_SYM)
++/* clang-format on */
++
+ int main(const int argc, char *const argv[], char *const *const envp)
+ {
+       const char *cmd_path;
diff --git a/queue-5.18/samples-landlock-format-with-clang-format.patch b/queue-5.18/samples-landlock-format-with-clang-format.patch
new file mode 100644 (file)
index 0000000..2133d87
--- /dev/null
@@ -0,0 +1,208 @@
+From 81709f3dccacf4104a4bc2daa80bdd767a9c4c54 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:13 +0200
+Subject: samples/landlock: Format with clang-format
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 81709f3dccacf4104a4bc2daa80bdd767a9c4c54 upstream.
+
+Let's follow a consistent and documented coding style.  Everything may
+not be to our liking but it is better than tacit knowledge.  Moreover,
+this will help maintain style consistency between different developers.
+
+This contains only whitespace changes.
+
+Automatically formatted with:
+clang-format-14 -i samples/landlock/*.[ch]
+
+Link: https://lore.kernel.org/r/20220506160513.523257-8-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ samples/landlock/sandboxer.c |   96 +++++++++++++++++++++++--------------------
+ 1 file changed, 52 insertions(+), 44 deletions(-)
+
+--- a/samples/landlock/sandboxer.c
++++ b/samples/landlock/sandboxer.c
+@@ -22,9 +22,9 @@
+ #include <unistd.h>
+ #ifndef landlock_create_ruleset
+-static inline int landlock_create_ruleset(
+-              const struct landlock_ruleset_attr *const attr,
+-              const size_t size, const __u32 flags)
++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);
+ }
+@@ -32,17 +32,18 @@ static inline int landlock_create_rulese
+ #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)
++                                  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);
++      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)
++                                       const __u32 flags)
+ {
+       return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
+ }
+@@ -79,9 +80,8 @@ static int parse_path(char *env_path, co
+ /* clang-format on */
+-static int populate_ruleset(
+-              const char *const env_var, const int ruleset_fd,
+-              const __u64 allowed_access)
++static int populate_ruleset(const char *const env_var, const int ruleset_fd,
++                          const __u64 allowed_access)
+ {
+       int num_paths, i, ret = 1;
+       char *env_path_name;
+@@ -111,12 +111,10 @@ static int populate_ruleset(
+       for (i = 0; i < num_paths; i++) {
+               struct stat statbuf;
+-              path_beneath.parent_fd = open(path_list[i], O_PATH |
+-                              O_CLOEXEC);
++              path_beneath.parent_fd = open(path_list[i], O_PATH | O_CLOEXEC);
+               if (path_beneath.parent_fd < 0) {
+                       fprintf(stderr, "Failed to open \"%s\": %s\n",
+-                                      path_list[i],
+-                                      strerror(errno));
++                              path_list[i], strerror(errno));
+                       goto out_free_name;
+               }
+               if (fstat(path_beneath.parent_fd, &statbuf)) {
+@@ -127,9 +125,10 @@ static int populate_ruleset(
+               if (!S_ISDIR(statbuf.st_mode))
+                       path_beneath.allowed_access &= ACCESS_FILE;
+               if (landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                                      &path_beneath, 0)) {
+-                      fprintf(stderr, "Failed to update the ruleset with \"%s\": %s\n",
+-                                      path_list[i], strerror(errno));
++                                    &path_beneath, 0)) {
++                      fprintf(stderr,
++                              "Failed to update the ruleset with \"%s\": %s\n",
++                              path_list[i], strerror(errno));
+                       close(path_beneath.parent_fd);
+                       goto out_free_name;
+               }
+@@ -171,55 +170,64 @@ int main(const int argc, char *const arg
+       int ruleset_fd;
+       struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = ACCESS_FS_ROUGHLY_READ |
+-                      ACCESS_FS_ROUGHLY_WRITE,
++                                   ACCESS_FS_ROUGHLY_WRITE,
+       };
+       if (argc < 2) {
+-              fprintf(stderr, "usage: %s=\"...\" %s=\"...\" %s <cmd> [args]...\n\n",
+-                              ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]);
+-              fprintf(stderr, "Launch a command in a restricted environment.\n\n");
++              fprintf(stderr,
++                      "usage: %s=\"...\" %s=\"...\" %s <cmd> [args]...\n\n",
++                      ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]);
++              fprintf(stderr,
++                      "Launch a command in a restricted environment.\n\n");
+               fprintf(stderr, "Environment variables containing paths, "
+                               "each separated by a colon:\n");
+-              fprintf(stderr, "* %s: list of paths allowed to be used in a read-only way.\n",
+-                              ENV_FS_RO_NAME);
+-              fprintf(stderr, "* %s: list of paths allowed to be used in a read-write way.\n",
+-                              ENV_FS_RW_NAME);
+-              fprintf(stderr, "\nexample:\n"
+-                              "%s=\"/bin:/lib:/usr:/proc:/etc:/dev/urandom\" "
+-                              "%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" "
+-                              "%s bash -i\n",
+-                              ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]);
++              fprintf(stderr,
++                      "* %s: list of paths allowed to be used in a read-only way.\n",
++                      ENV_FS_RO_NAME);
++              fprintf(stderr,
++                      "* %s: list of paths allowed to be used in a read-write way.\n",
++                      ENV_FS_RW_NAME);
++              fprintf(stderr,
++                      "\nexample:\n"
++                      "%s=\"/bin:/lib:/usr:/proc:/etc:/dev/urandom\" "
++                      "%s=\"/dev/null:/dev/full:/dev/zero:/dev/pts:/tmp\" "
++                      "%s bash -i\n",
++                      ENV_FS_RO_NAME, ENV_FS_RW_NAME, argv[0]);
+               return 1;
+       }
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       if (ruleset_fd < 0) {
+               const int err = errno;
+               perror("Failed to create a ruleset");
+               switch (err) {
+               case ENOSYS:
+-                      fprintf(stderr, "Hint: Landlock is not supported by the current kernel. "
+-                                      "To support it, build the kernel with "
+-                                      "CONFIG_SECURITY_LANDLOCK=y and prepend "
+-                                      "\"landlock,\" to the content of CONFIG_LSM.\n");
++                      fprintf(stderr,
++                              "Hint: Landlock is not supported by the current kernel. "
++                              "To support it, build the kernel with "
++                              "CONFIG_SECURITY_LANDLOCK=y and prepend "
++                              "\"landlock,\" to the content of CONFIG_LSM.\n");
+                       break;
+               case EOPNOTSUPP:
+-                      fprintf(stderr, "Hint: Landlock is currently disabled. "
+-                                      "It can be enabled in the kernel configuration by "
+-                                      "prepending \"landlock,\" to the content of CONFIG_LSM, "
+-                                      "or at boot time by setting the same content to the "
+-                                      "\"lsm\" kernel parameter.\n");
++                      fprintf(stderr,
++                              "Hint: Landlock is currently disabled. "
++                              "It can be enabled in the kernel configuration by "
++                              "prepending \"landlock,\" to the content of CONFIG_LSM, "
++                              "or at boot time by setting the same content to the "
++                              "\"lsm\" kernel parameter.\n");
+                       break;
+               }
+               return 1;
+       }
+       if (populate_ruleset(ENV_FS_RO_NAME, ruleset_fd,
+-                              ACCESS_FS_ROUGHLY_READ)) {
++                           ACCESS_FS_ROUGHLY_READ)) {
+               goto err_close_ruleset;
+       }
+       if (populate_ruleset(ENV_FS_RW_NAME, ruleset_fd,
+-                              ACCESS_FS_ROUGHLY_READ | ACCESS_FS_ROUGHLY_WRITE)) {
++                           ACCESS_FS_ROUGHLY_READ |
++                                   ACCESS_FS_ROUGHLY_WRITE)) {
+               goto err_close_ruleset;
+       }
+       if (prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0)) {
+@@ -236,7 +244,7 @@ int main(const int argc, char *const arg
+       cmd_argv = argv + 1;
+       execvpe(cmd_path, cmd_argv, envp);
+       fprintf(stderr, "Failed to execute \"%s\": %s\n", cmd_path,
+-                      strerror(errno));
++              strerror(errno));
+       fprintf(stderr, "Hint: access to the binary, the interpreter or "
+                       "shared libraries may be denied.\n");
+       return 1;
diff --git a/queue-5.18/selftests-landlock-add-clang-format-exceptions.patch b/queue-5.18/selftests-landlock-add-clang-format-exceptions.patch
new file mode 100644 (file)
index 0000000..96f5d6e
--- /dev/null
@@ -0,0 +1,216 @@
+From 4598d9abf4215e1e371a35683350d50122793c80 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:09 +0200
+Subject: selftests/landlock: Add clang-format exceptions
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 4598d9abf4215e1e371a35683350d50122793c80 upstream.
+
+In preparation to a following commit, add clang-format on and
+clang-format off stanzas around constant definitions and the TEST_F_FORK
+macro.  This enables to keep aligned values, which is much more readable
+than packed definitions.
+
+Add other clang-format exceptions for FIXTURE() and
+FIXTURE_VARIANT_ADD() declarations to force space before open brace,
+which is reported by checkpatch.pl .
+
+Link: https://lore.kernel.org/r/20220506160513.523257-4-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/common.h      |    2 ++
+ tools/testing/selftests/landlock/fs_test.c     |   23 +++++++++++++++++------
+ tools/testing/selftests/landlock/ptrace_test.c |   20 +++++++++++++++++++-
+ 3 files changed, 38 insertions(+), 7 deletions(-)
+
+--- a/tools/testing/selftests/landlock/common.h
++++ b/tools/testing/selftests/landlock/common.h
+@@ -25,6 +25,7 @@
+  * this to be possible, we must not call abort() but instead exit smoothly
+  * (hence the step print).
+  */
++/* clang-format off */
+ #define TEST_F_FORK(fixture_name, test_name) \
+       static void fixture_name##_##test_name##_child( \
+               struct __test_metadata *_metadata, \
+@@ -71,6 +72,7 @@
+               FIXTURE_DATA(fixture_name) __attribute__((unused)) *self, \
+               const FIXTURE_VARIANT(fixture_name) \
+                       __attribute__((unused)) *variant)
++/* clang-format on */
+ #ifndef landlock_create_ruleset
+ static inline int landlock_create_ruleset(
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -221,8 +221,9 @@ static void remove_layout1(struct __test
+       EXPECT_EQ(0, remove_path(dir_s3d2));
+ }
+-FIXTURE(layout1) {
+-};
++/* clang-format off */
++FIXTURE(layout1) {};
++/* clang-format on */
+ FIXTURE_SETUP(layout1)
+ {
+@@ -376,6 +377,8 @@ TEST_F_FORK(layout1, inval)
+       ASSERT_EQ(0, close(ruleset_fd));
+ }
++/* clang-format off */
++
+ #define ACCESS_FILE ( \
+       LANDLOCK_ACCESS_FS_EXECUTE | \
+       LANDLOCK_ACCESS_FS_WRITE_FILE | \
+@@ -396,6 +399,8 @@ TEST_F_FORK(layout1, inval)
+       LANDLOCK_ACCESS_FS_MAKE_BLOCK | \
+       ACCESS_LAST)
++/* clang-format on */
++
+ TEST_F_FORK(layout1, file_access_rights)
+ {
+       __u64 access;
+@@ -452,6 +457,8 @@ struct rule {
+       __u64 access;
+ };
++/* clang-format off */
++
+ #define ACCESS_RO ( \
+       LANDLOCK_ACCESS_FS_READ_FILE | \
+       LANDLOCK_ACCESS_FS_READ_DIR)
+@@ -460,6 +467,8 @@ struct rule {
+       ACCESS_RO | \
+       LANDLOCK_ACCESS_FS_WRITE_FILE)
++/* clang-format on */
++
+ static int create_ruleset(struct __test_metadata *const _metadata,
+               const __u64 handled_access_fs, const struct rule rules[])
+ {
+@@ -2070,8 +2079,9 @@ TEST_F_FORK(layout1, proc_pipe)
+       ASSERT_EQ(0, close(pipe_fds[1]));
+ }
+-FIXTURE(layout1_bind) {
+-};
++/* clang-format off */
++FIXTURE(layout1_bind) {};
++/* clang-format on */
+ FIXTURE_SETUP(layout1_bind)
+ {
+@@ -2411,8 +2421,9 @@ static const char (*merge_sub_files[])[]
+  *         └── work
+  */
+-FIXTURE(layout2_overlay) {
+-};
++/* clang-format off */
++FIXTURE(layout2_overlay) {};
++/* clang-format on */
+ FIXTURE_SETUP(layout2_overlay)
+ {
+--- a/tools/testing/selftests/landlock/ptrace_test.c
++++ b/tools/testing/selftests/landlock/ptrace_test.c
+@@ -59,7 +59,9 @@ static int test_ptrace_read(const pid_t
+       return 0;
+ }
+-FIXTURE(hierarchy) { };
++/* clang-format off */
++FIXTURE(hierarchy) {};
++/* clang-format on */
+ FIXTURE_VARIANT(hierarchy) {
+       const bool domain_both;
+@@ -83,7 +85,9 @@ FIXTURE_VARIANT(hierarchy) {
+  *       \              P2 -> P1 : allow
+  *        'P2
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, allow_without_domain) {
++      /* clang-format on */
+       .domain_both = false,
+       .domain_parent = false,
+       .domain_child = false,
+@@ -98,7 +102,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_wit
+  *        |  P2  |
+  *        '------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, allow_with_one_domain) {
++      /* clang-format on */
+       .domain_both = false,
+       .domain_parent = false,
+       .domain_child = true,
+@@ -112,7 +118,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_wit
+  *            '
+  *            P2
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, deny_with_parent_domain) {
++      /* clang-format on */
+       .domain_both = false,
+       .domain_parent = true,
+       .domain_child = false,
+@@ -127,7 +135,9 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with
+  *         |  P2  |
+  *         '------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, deny_with_sibling_domain) {
++      /* clang-format on */
+       .domain_both = false,
+       .domain_parent = true,
+       .domain_child = true,
+@@ -142,7 +152,9 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with
+  * |         P2  |
+  * '-------------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, allow_sibling_domain) {
++      /* clang-format on */
+       .domain_both = true,
+       .domain_parent = false,
+       .domain_child = false,
+@@ -158,7 +170,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_sib
+  * |        '------' |
+  * '-----------------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, allow_with_nested_domain) {
++      /* clang-format on */
+       .domain_both = true,
+       .domain_parent = false,
+       .domain_child = true,
+@@ -174,7 +188,9 @@ FIXTURE_VARIANT_ADD(hierarchy, allow_wit
+  * |             P2  |
+  * '-----------------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, deny_with_nested_and_parent_domain) {
++      /* clang-format on */
+       .domain_both = true,
+       .domain_parent = true,
+       .domain_child = false,
+@@ -192,7 +208,9 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with
+  * |        '------' |
+  * '-----------------'
+  */
++/* clang-format off */
+ FIXTURE_VARIANT_ADD(hierarchy, deny_with_forked_domain) {
++      /* clang-format on */
+       .domain_both = true,
+       .domain_parent = true,
+       .domain_child = true,
diff --git a/queue-5.18/selftests-landlock-add-tests-for-o_path.patch b/queue-5.18/selftests-landlock-add-tests-for-o_path.patch
new file mode 100644 (file)
index 0000000..b6fc6fc
--- /dev/null
@@ -0,0 +1,52 @@
+From d1788ad990874734341b05ab8ccb6448c09c6422 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:17 +0200
+Subject: selftests/landlock: Add tests for O_PATH
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit d1788ad990874734341b05ab8ccb6448c09c6422 upstream.
+
+The O_PATH flag is currently not handled by Landlock.  Let's make sure
+this behavior will remain consistent with the same ruleset over time.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-8-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |   10 ++++++++--
+ 1 file changed, 8 insertions(+), 2 deletions(-)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -654,17 +654,23 @@ TEST_F_FORK(layout1, effective_access)
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+-      /* Tests on a directory. */
++      /* Tests on a directory (with or without O_PATH). */
+       ASSERT_EQ(EACCES, test_open("/", O_RDONLY));
++      ASSERT_EQ(0, test_open("/", O_RDONLY | O_PATH));
+       ASSERT_EQ(EACCES, test_open(dir_s1d1, O_RDONLY));
++      ASSERT_EQ(0, test_open(dir_s1d1, O_RDONLY | O_PATH));
+       ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
++      ASSERT_EQ(0, test_open(file1_s1d1, O_RDONLY | O_PATH));
++
+       ASSERT_EQ(0, test_open(dir_s1d2, O_RDONLY));
+       ASSERT_EQ(0, test_open(file1_s1d2, O_RDONLY));
+       ASSERT_EQ(0, test_open(dir_s1d3, O_RDONLY));
+       ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
+-      /* Tests on a file. */
++      /* Tests on a file (with or without O_PATH). */
+       ASSERT_EQ(EACCES, test_open(dir_s2d2, O_RDONLY));
++      ASSERT_EQ(0, test_open(dir_s2d2, O_RDONLY | O_PATH));
++
+       ASSERT_EQ(0, test_open(file1_s2d2, O_RDONLY));
+       /* Checks effective read and write actions. */
diff --git a/queue-5.18/selftests-landlock-add-tests-for-unknown-access-rights.patch b/queue-5.18/selftests-landlock-add-tests-for-unknown-access-rights.patch
new file mode 100644 (file)
index 0000000..da44243
--- /dev/null
@@ -0,0 +1,48 @@
+From c56b3bf566da5a0dd3b58ad97a614b0928b06ebf Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:14 +0200
+Subject: selftests/landlock: Add tests for unknown access rights
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit c56b3bf566da5a0dd3b58ad97a614b0928b06ebf upstream.
+
+Make sure that trying to use unknown access rights returns an error.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-5-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |   16 ++++++++++++++++
+ 1 file changed, 16 insertions(+)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -448,6 +448,22 @@ TEST_F_FORK(layout1, file_access_rights)
+       ASSERT_EQ(0, close(path_beneath.parent_fd));
+ }
++TEST_F_FORK(layout1, unknown_access_rights)
++{
++      __u64 access_mask;
++
++      for (access_mask = 1ULL << 63; access_mask != ACCESS_LAST;
++           access_mask >>= 1) {
++              struct landlock_ruleset_attr ruleset_attr = {
++                      .handled_access_fs = access_mask,
++              };
++
++              ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
++                                                    sizeof(ruleset_attr), 0));
++              ASSERT_EQ(EINVAL, errno);
++      }
++}
++
+ static void add_path_beneath(struct __test_metadata *const _metadata,
+                            const int ruleset_fd, const __u64 allowed_access,
+                            const char *const path)
diff --git a/queue-5.18/selftests-landlock-extend-access-right-tests-to-directories.patch b/queue-5.18/selftests-landlock-extend-access-right-tests-to-directories.patch
new file mode 100644 (file)
index 0000000..54a1cb8
--- /dev/null
@@ -0,0 +1,83 @@
+From d18955d094d09a220cf8f533f5e896a2fe31575a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:15 +0200
+Subject: selftests/landlock: Extend access right tests to directories
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit d18955d094d09a220cf8f533f5e896a2fe31575a upstream.
+
+Make sure that all filesystem access rights can be tied to directories.
+
+Rename layout1.file_access_rights to layout1.file_and_dir_access_rights
+to reflect this change.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-6-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |   30 +++++++++++++++++++++--------
+ 1 file changed, 22 insertions(+), 8 deletions(-)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -418,11 +418,12 @@ TEST_F_FORK(layout1, inval)
+ /* clang-format on */
+-TEST_F_FORK(layout1, file_access_rights)
++TEST_F_FORK(layout1, file_and_dir_access_rights)
+ {
+       __u64 access;
+       int err;
+-      struct landlock_path_beneath_attr path_beneath = {};
++      struct landlock_path_beneath_attr path_beneath_file = {},
++                                        path_beneath_dir = {};
+       struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = ACCESS_ALL,
+       };
+@@ -432,20 +433,33 @@ TEST_F_FORK(layout1, file_access_rights)
+       ASSERT_LE(0, ruleset_fd);
+       /* Tests access rights for files. */
+-      path_beneath.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
+-      ASSERT_LE(0, path_beneath.parent_fd);
++      path_beneath_file.parent_fd = open(file1_s1d2, O_PATH | O_CLOEXEC);
++      ASSERT_LE(0, path_beneath_file.parent_fd);
++
++      /* Tests access rights for directories. */
++      path_beneath_dir.parent_fd =
++              open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
++      ASSERT_LE(0, path_beneath_dir.parent_fd);
++
+       for (access = 1; access <= ACCESS_LAST; access <<= 1) {
+-              path_beneath.allowed_access = access;
++              path_beneath_dir.allowed_access = access;
++              ASSERT_EQ(0, landlock_add_rule(ruleset_fd,
++                                             LANDLOCK_RULE_PATH_BENEATH,
++                                             &path_beneath_dir, 0));
++
++              path_beneath_file.allowed_access = access;
+               err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                                      &path_beneath, 0);
+-              if ((access | ACCESS_FILE) == ACCESS_FILE) {
++                                      &path_beneath_file, 0);
++              if (access & ACCESS_FILE) {
+                       ASSERT_EQ(0, err);
+               } else {
+                       ASSERT_EQ(-1, err);
+                       ASSERT_EQ(EINVAL, errno);
+               }
+       }
+-      ASSERT_EQ(0, close(path_beneath.parent_fd));
++      ASSERT_EQ(0, close(path_beneath_file.parent_fd));
++      ASSERT_EQ(0, close(path_beneath_dir.parent_fd));
++      ASSERT_EQ(0, close(ruleset_fd));
+ }
+ TEST_F_FORK(layout1, unknown_access_rights)
diff --git a/queue-5.18/selftests-landlock-extend-tests-for-minimal-valid-attribute-size.patch b/queue-5.18/selftests-landlock-extend-tests-for-minimal-valid-attribute-size.patch
new file mode 100644 (file)
index 0000000..5d78c5f
--- /dev/null
@@ -0,0 +1,45 @@
+From 291865bd7e8bb4b4033d341fa02dafa728e6378c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:13 +0200
+Subject: selftests/landlock: Extend tests for minimal valid attribute size
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 291865bd7e8bb4b4033d341fa02dafa728e6378c upstream.
+
+This might be useful when the struct landlock_ruleset_attr will get more
+fields.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-4-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/base_test.c |    5 +++++
+ 1 file changed, 5 insertions(+)
+
+--- a/tools/testing/selftests/landlock/base_test.c
++++ b/tools/testing/selftests/landlock/base_test.c
+@@ -35,6 +35,8 @@ TEST(inconsistent_attr)
+       ASSERT_EQ(EINVAL, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 1, 0));
+       ASSERT_EQ(EINVAL, errno);
++      ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 7, 0));
++      ASSERT_EQ(EINVAL, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(NULL, 1, 0));
+       /* The size if less than sizeof(struct landlock_attr_enforce). */
+@@ -47,6 +49,9 @@ TEST(inconsistent_attr)
+       ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size + 1, 0));
+       ASSERT_EQ(E2BIG, errno);
++      /* Checks minimal valid attribute size. */
++      ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, 8, 0));
++      ASSERT_EQ(ENOMSG, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(
+                             ruleset_attr,
+                             sizeof(struct landlock_ruleset_attr), 0));
diff --git a/queue-5.18/selftests-landlock-format-with-clang-format.patch b/queue-5.18/selftests-landlock-format-with-clang-format.patch
new file mode 100644 (file)
index 0000000..ccba585
--- /dev/null
@@ -0,0 +1,1513 @@
+From 371183fa578a4cf56b3ae12e54b7f01a4249add1 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:11 +0200
+Subject: selftests/landlock: Format with clang-format
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 371183fa578a4cf56b3ae12e54b7f01a4249add1 upstream.
+
+Let's follow a consistent and documented coding style.  Everything may
+not be to our liking but it is better than tacit knowledge.  Moreover,
+this will help maintain style consistency between different developers.
+
+This contains only whitespace changes.
+
+Automatically formatted with:
+clang-format-14 -i tools/testing/selftests/landlock/*.[ch]
+
+Link: https://lore.kernel.org/r/20220506160513.523257-6-mic@digikod.net
+Cc: stable@vger.kernel.org
+[mic: Update style according to
+https://lore.kernel.org/r/02494cb8-2aa5-1769-f28d-d7206f284e5a@digikod.net]
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/base_test.c   |   80 ++---
+ tools/testing/selftests/landlock/common.h      |   64 ++--
+ tools/testing/selftests/landlock/fs_test.c     |  399 +++++++++++++------------
+ tools/testing/selftests/landlock/ptrace_test.c |   20 -
+ 4 files changed, 312 insertions(+), 251 deletions(-)
+
+--- a/tools/testing/selftests/landlock/base_test.c
++++ b/tools/testing/selftests/landlock/base_test.c
+@@ -18,10 +18,11 @@
+ #include "common.h"
+ #ifndef O_PATH
+-#define O_PATH                010000000
++#define O_PATH 010000000
+ #endif
+-TEST(inconsistent_attr) {
++TEST(inconsistent_attr)
++{
+       const long page_size = sysconf(_SC_PAGESIZE);
+       char *const buf = malloc(page_size + 1);
+       struct landlock_ruleset_attr *const ruleset_attr = (void *)buf;
+@@ -39,15 +40,16 @@ TEST(inconsistent_attr) {
+       /* The size if less than sizeof(struct landlock_attr_enforce). */
+       ASSERT_EQ(EFAULT, errno);
+-      ASSERT_EQ(-1, landlock_create_ruleset(NULL,
+-                              sizeof(struct landlock_ruleset_attr), 0));
++      ASSERT_EQ(-1, landlock_create_ruleset(
++                            NULL, sizeof(struct landlock_ruleset_attr), 0));
+       ASSERT_EQ(EFAULT, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size + 1, 0));
+       ASSERT_EQ(E2BIG, errno);
+-      ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr,
+-                              sizeof(struct landlock_ruleset_attr), 0));
++      ASSERT_EQ(-1, landlock_create_ruleset(
++                            ruleset_attr,
++                            sizeof(struct landlock_ruleset_attr), 0));
+       ASSERT_EQ(ENOMSG, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(ruleset_attr, page_size, 0));
+       ASSERT_EQ(ENOMSG, errno);
+@@ -63,32 +65,35 @@ TEST(inconsistent_attr) {
+       free(buf);
+ }
+-TEST(abi_version) {
++TEST(abi_version)
++{
+       const struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
+       };
+       ASSERT_EQ(1, landlock_create_ruleset(NULL, 0,
+-                              LANDLOCK_CREATE_RULESET_VERSION));
++                                           LANDLOCK_CREATE_RULESET_VERSION));
+       ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0,
+-                              LANDLOCK_CREATE_RULESET_VERSION));
++                                            LANDLOCK_CREATE_RULESET_VERSION));
+       ASSERT_EQ(EINVAL, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
+-                              LANDLOCK_CREATE_RULESET_VERSION));
++                                            LANDLOCK_CREATE_RULESET_VERSION));
+       ASSERT_EQ(EINVAL, errno);
+-      ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
+-                              sizeof(ruleset_attr),
+-                              LANDLOCK_CREATE_RULESET_VERSION));
++      ASSERT_EQ(-1,
++                landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
++                                        LANDLOCK_CREATE_RULESET_VERSION));
+       ASSERT_EQ(EINVAL, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0,
+-                              LANDLOCK_CREATE_RULESET_VERSION | 1 << 31));
++                                            LANDLOCK_CREATE_RULESET_VERSION |
++                                                    1 << 31));
+       ASSERT_EQ(EINVAL, errno);
+ }
+-TEST(inval_create_ruleset_flags) {
++TEST(inval_create_ruleset_flags)
++{
+       const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
+       const int invalid_flag = last_flag << 1;
+       const struct landlock_ruleset_attr ruleset_attr = {
+@@ -102,38 +107,42 @@ TEST(inval_create_ruleset_flags) {
+       ASSERT_EQ(EINVAL, errno);
+       ASSERT_EQ(-1, landlock_create_ruleset(NULL, sizeof(ruleset_attr),
+-                              invalid_flag));
++                                            invalid_flag));
+       ASSERT_EQ(EINVAL, errno);
+-      ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr,
+-                              sizeof(ruleset_attr), invalid_flag));
++      ASSERT_EQ(-1,
++                landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
++                                        invalid_flag));
+       ASSERT_EQ(EINVAL, errno);
+ }
+-TEST(empty_path_beneath_attr) {
++TEST(empty_path_beneath_attr)
++{
+       const struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = LANDLOCK_ACCESS_FS_EXECUTE,
+       };
+-      const int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      const int ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+       /* Similar to struct landlock_path_beneath_attr.parent_fd = 0 */
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              NULL, 0));
++                                      NULL, 0));
+       ASSERT_EQ(EFAULT, errno);
+       ASSERT_EQ(0, close(ruleset_fd));
+ }
+-TEST(inval_fd_enforce) {
++TEST(inval_fd_enforce)
++{
+       ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
+       ASSERT_EQ(-1, landlock_restrict_self(-1, 0));
+       ASSERT_EQ(EBADF, errno);
+ }
+-TEST(unpriv_enforce_without_no_new_privs) {
++TEST(unpriv_enforce_without_no_new_privs)
++{
+       int err;
+       drop_caps(_metadata);
+@@ -151,8 +160,8 @@ TEST(ruleset_fd_io)
+       char buf;
+       drop_caps(_metadata);
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+       ASSERT_EQ(-1, write(ruleset_fd, ".", 1));
+@@ -197,14 +206,15 @@ TEST(ruleset_fd_transfer)
+       drop_caps(_metadata);
+       /* Creates a test ruleset with a simple rule. */
+-      ruleset_fd_tx = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd_tx =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd_tx);
+-      path_beneath_attr.parent_fd = open("/tmp", O_PATH | O_NOFOLLOW |
+-                      O_DIRECTORY | O_CLOEXEC);
++      path_beneath_attr.parent_fd =
++              open("/tmp", O_PATH | O_NOFOLLOW | O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, path_beneath_attr.parent_fd);
+-      ASSERT_EQ(0, landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath_attr, 0));
++      ASSERT_EQ(0,
++                landlock_add_rule(ruleset_fd_tx, LANDLOCK_RULE_PATH_BENEATH,
++                                  &path_beneath_attr, 0));
+       ASSERT_EQ(0, close(path_beneath_attr.parent_fd));
+       cmsg = CMSG_FIRSTHDR(&msg);
+@@ -215,7 +225,8 @@ TEST(ruleset_fd_transfer)
+       memcpy(CMSG_DATA(cmsg), &ruleset_fd_tx, sizeof(ruleset_fd_tx));
+       /* Sends the ruleset FD over a socketpair and then close it. */
+-      ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0, socket_fds));
++      ASSERT_EQ(0, socketpair(AF_UNIX, SOCK_STREAM | SOCK_CLOEXEC, 0,
++                              socket_fds));
+       ASSERT_EQ(sizeof(data_tx), sendmsg(socket_fds[0], &msg, 0));
+       ASSERT_EQ(0, close(socket_fds[0]));
+       ASSERT_EQ(0, close(ruleset_fd_tx));
+@@ -226,7 +237,8 @@ TEST(ruleset_fd_transfer)
+               int ruleset_fd_rx;
+               *(char *)msg.msg_iov->iov_base = '\0';
+-              ASSERT_EQ(sizeof(data_tx), recvmsg(socket_fds[1], &msg, MSG_CMSG_CLOEXEC));
++              ASSERT_EQ(sizeof(data_tx),
++                        recvmsg(socket_fds[1], &msg, MSG_CMSG_CLOEXEC));
+               ASSERT_EQ('.', *(char *)msg.msg_iov->iov_base);
+               ASSERT_EQ(0, close(socket_fds[1]));
+               cmsg = CMSG_FIRSTHDR(&msg);
+--- a/tools/testing/selftests/landlock/common.h
++++ b/tools/testing/selftests/landlock/common.h
+@@ -75,9 +75,9 @@
+ /* clang-format on */
+ #ifndef landlock_create_ruleset
+-static inline int landlock_create_ruleset(
+-              const struct landlock_ruleset_attr *const attr,
+-              const size_t size, const __u32 flags)
++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);
+ }
+@@ -85,17 +85,18 @@ static inline int landlock_create_rulese
+ #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)
++                                  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);
++      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)
++                                       const __u32 flags)
+ {
+       return syscall(__NR_landlock_restrict_self, ruleset_fd, flags);
+ }
+@@ -113,69 +114,76 @@ static void _init_caps(struct __test_met
+       };
+       cap_p = cap_get_proc();
+-      EXPECT_NE(NULL, cap_p) {
++      EXPECT_NE(NULL, cap_p)
++      {
+               TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
+       }
+-      EXPECT_NE(-1, cap_clear(cap_p)) {
++      EXPECT_NE(-1, cap_clear(cap_p))
++      {
+               TH_LOG("Failed to cap_clear: %s", strerror(errno));
+       }
+       if (!drop_all) {
+               EXPECT_NE(-1, cap_set_flag(cap_p, CAP_PERMITTED,
+-                                      ARRAY_SIZE(caps), caps, CAP_SET)) {
++                                         ARRAY_SIZE(caps), caps, CAP_SET))
++              {
+                       TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
+               }
+       }
+-      EXPECT_NE(-1, cap_set_proc(cap_p)) {
++      EXPECT_NE(-1, cap_set_proc(cap_p))
++      {
+               TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
+       }
+-      EXPECT_NE(-1, cap_free(cap_p)) {
++      EXPECT_NE(-1, cap_free(cap_p))
++      {
+               TH_LOG("Failed to cap_free: %s", strerror(errno));
+       }
+ }
+ /* We cannot put such helpers in a library because of kselftest_harness.h . */
+-__attribute__((__unused__))
+-static void disable_caps(struct __test_metadata *const _metadata)
++__attribute__((__unused__)) static void
++disable_caps(struct __test_metadata *const _metadata)
+ {
+       _init_caps(_metadata, false);
+ }
+-__attribute__((__unused__))
+-static void drop_caps(struct __test_metadata *const _metadata)
++__attribute__((__unused__)) static void
++drop_caps(struct __test_metadata *const _metadata)
+ {
+       _init_caps(_metadata, true);
+ }
+ static void _effective_cap(struct __test_metadata *const _metadata,
+-              const cap_value_t caps, const cap_flag_value_t value)
++                         const cap_value_t caps, const cap_flag_value_t value)
+ {
+       cap_t cap_p;
+       cap_p = cap_get_proc();
+-      EXPECT_NE(NULL, cap_p) {
++      EXPECT_NE(NULL, cap_p)
++      {
+               TH_LOG("Failed to cap_get_proc: %s", strerror(errno));
+       }
+-      EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value)) {
++      EXPECT_NE(-1, cap_set_flag(cap_p, CAP_EFFECTIVE, 1, &caps, value))
++      {
+               TH_LOG("Failed to cap_set_flag: %s", strerror(errno));
+       }
+-      EXPECT_NE(-1, cap_set_proc(cap_p)) {
++      EXPECT_NE(-1, cap_set_proc(cap_p))
++      {
+               TH_LOG("Failed to cap_set_proc: %s", strerror(errno));
+       }
+-      EXPECT_NE(-1, cap_free(cap_p)) {
++      EXPECT_NE(-1, cap_free(cap_p))
++      {
+               TH_LOG("Failed to cap_free: %s", strerror(errno));
+       }
+ }
+-__attribute__((__unused__))
+-static void set_cap(struct __test_metadata *const _metadata,
+-              const cap_value_t caps)
++__attribute__((__unused__)) static void
++set_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
+ {
+       _effective_cap(_metadata, caps, CAP_SET);
+ }
+-__attribute__((__unused__))
+-static void clear_cap(struct __test_metadata *const _metadata,
+-              const cap_value_t caps)
++__attribute__((__unused__)) static void
++clear_cap(struct __test_metadata *const _metadata, const cap_value_t caps)
+ {
+       _effective_cap(_metadata, caps, CAP_CLEAR);
+ }
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -22,8 +22,8 @@
+ #include "common.h"
+-#define TMP_DIR               "tmp"
+-#define BINARY_PATH   "./true"
++#define TMP_DIR "tmp"
++#define BINARY_PATH "./true"
+ /* Paths (sibling number and depth) */
+ static const char dir_s1d1[] = TMP_DIR "/s1d1";
+@@ -75,7 +75,7 @@ static const char dir_s3d3[] = TMP_DIR "
+  */
+ static void mkdir_parents(struct __test_metadata *const _metadata,
+-              const char *const path)
++                        const char *const path)
+ {
+       char *walker;
+       const char *parent;
+@@ -90,9 +90,10 @@ static void mkdir_parents(struct __test_
+                       continue;
+               walker[i] = '\0';
+               err = mkdir(parent, 0700);
+-              ASSERT_FALSE(err && errno != EEXIST) {
+-                      TH_LOG("Failed to create directory \"%s\": %s",
+-                                      parent, strerror(errno));
++              ASSERT_FALSE(err && errno != EEXIST)
++              {
++                      TH_LOG("Failed to create directory \"%s\": %s", parent,
++                             strerror(errno));
+               }
+               walker[i] = '/';
+       }
+@@ -100,22 +101,24 @@ static void mkdir_parents(struct __test_
+ }
+ static void create_directory(struct __test_metadata *const _metadata,
+-              const char *const path)
++                           const char *const path)
+ {
+       mkdir_parents(_metadata, path);
+-      ASSERT_EQ(0, mkdir(path, 0700)) {
++      ASSERT_EQ(0, mkdir(path, 0700))
++      {
+               TH_LOG("Failed to create directory \"%s\": %s", path,
+-                              strerror(errno));
++                     strerror(errno));
+       }
+ }
+ static void create_file(struct __test_metadata *const _metadata,
+-              const char *const path)
++                      const char *const path)
+ {
+       mkdir_parents(_metadata, path);
+-      ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0)) {
++      ASSERT_EQ(0, mknod(path, S_IFREG | 0700, 0))
++      {
+               TH_LOG("Failed to create file \"%s\": %s", path,
+-                              strerror(errno));
++                     strerror(errno));
+       }
+ }
+@@ -243,7 +246,8 @@ FIXTURE_TEARDOWN(layout1)
+  * This helper enables to use the ASSERT_* macros and print the line number
+  * pointing to the test caller.
+  */
+-static int test_open_rel(const int dirfd, const char *const path, const int flags)
++static int test_open_rel(const int dirfd, const char *const path,
++                       const int flags)
+ {
+       int fd;
+@@ -292,23 +296,23 @@ TEST_F_FORK(layout1, inval)
+ {
+       struct landlock_path_beneath_attr path_beneath = {
+               .allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               .parent_fd = -1,
+       };
+       struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                   LANDLOCK_ACCESS_FS_WRITE_FILE,
+       };
+       int ruleset_fd;
+-      path_beneath.parent_fd = open(dir_s1d2, O_PATH | O_DIRECTORY |
+-                      O_CLOEXEC);
++      path_beneath.parent_fd =
++              open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, path_beneath.parent_fd);
+       ruleset_fd = open(dir_s1d1, O_PATH | O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, ruleset_fd);
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       /* Returns EBADF because ruleset_fd is not a landlock-ruleset FD. */
+       ASSERT_EQ(EBADF, errno);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -316,55 +320,55 @@ TEST_F_FORK(layout1, inval)
+       ruleset_fd = open(dir_s1d1, O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, ruleset_fd);
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       /* Returns EBADFD because ruleset_fd is not a valid ruleset. */
+       ASSERT_EQ(EBADFD, errno);
+       ASSERT_EQ(0, close(ruleset_fd));
+       /* Gets a real ruleset. */
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+       ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                     &path_beneath, 0));
+       ASSERT_EQ(0, close(path_beneath.parent_fd));
+       /* Tests without O_PATH. */
+       path_beneath.parent_fd = open(dir_s1d2, O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, path_beneath.parent_fd);
+       ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                     &path_beneath, 0));
+       ASSERT_EQ(0, close(path_beneath.parent_fd));
+       /* Tests with a ruleset FD. */
+       path_beneath.parent_fd = ruleset_fd;
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       ASSERT_EQ(EBADFD, errno);
+       /* Checks unhandled allowed_access. */
+-      path_beneath.parent_fd = open(dir_s1d2, O_PATH | O_DIRECTORY |
+-                      O_CLOEXEC);
++      path_beneath.parent_fd =
++              open(dir_s1d2, O_PATH | O_DIRECTORY | O_CLOEXEC);
+       ASSERT_LE(0, path_beneath.parent_fd);
+       /* Test with legitimate values. */
+       path_beneath.allowed_access |= LANDLOCK_ACCESS_FS_EXECUTE;
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       ASSERT_EQ(EINVAL, errno);
+       path_beneath.allowed_access &= ~LANDLOCK_ACCESS_FS_EXECUTE;
+       /* Test with unknown (64-bits) value. */
+       path_beneath.allowed_access |= (1ULL << 60);
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       ASSERT_EQ(EINVAL, errno);
+       path_beneath.allowed_access &= ~(1ULL << 60);
+       /* Test with no access. */
+       path_beneath.allowed_access = 0;
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       ASSERT_EQ(ENOMSG, errno);
+       path_beneath.allowed_access &= ~(1ULL << 60);
+@@ -409,8 +413,8 @@ TEST_F_FORK(layout1, file_access_rights)
+       struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = ACCESS_ALL,
+       };
+-      const int ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      const int ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+@@ -420,7 +424,7 @@ TEST_F_FORK(layout1, file_access_rights)
+       for (access = 1; access <= ACCESS_LAST; access <<= 1) {
+               path_beneath.allowed_access = access;
+               err = landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0);
++                                      &path_beneath, 0);
+               if ((access | ACCESS_FILE) == ACCESS_FILE) {
+                       ASSERT_EQ(0, err);
+               } else {
+@@ -432,22 +436,24 @@ TEST_F_FORK(layout1, file_access_rights)
+ }
+ static void add_path_beneath(struct __test_metadata *const _metadata,
+-              const int ruleset_fd, const __u64 allowed_access,
+-              const char *const path)
++                           const int ruleset_fd, const __u64 allowed_access,
++                           const char *const path)
+ {
+       struct landlock_path_beneath_attr path_beneath = {
+               .allowed_access = allowed_access,
+       };
+       path_beneath.parent_fd = open(path, O_PATH | O_CLOEXEC);
+-      ASSERT_LE(0, path_beneath.parent_fd) {
++      ASSERT_LE(0, path_beneath.parent_fd)
++      {
+               TH_LOG("Failed to open directory \"%s\": %s", path,
+-                              strerror(errno));
++                     strerror(errno));
+       }
+       ASSERT_EQ(0, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0)) {
++                                     &path_beneath, 0))
++      {
+               TH_LOG("Failed to update the ruleset with \"%s\": %s", path,
+-                              strerror(errno));
++                     strerror(errno));
+       }
+       ASSERT_EQ(0, close(path_beneath.parent_fd));
+ }
+@@ -470,38 +476,43 @@ struct rule {
+ /* clang-format on */
+ static int create_ruleset(struct __test_metadata *const _metadata,
+-              const __u64 handled_access_fs, const struct rule rules[])
++                        const __u64 handled_access_fs,
++                        const struct rule rules[])
+ {
+       int ruleset_fd, i;
+       struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = handled_access_fs,
+       };
+-      ASSERT_NE(NULL, rules) {
++      ASSERT_NE(NULL, rules)
++      {
+               TH_LOG("No rule list");
+       }
+-      ASSERT_NE(NULL, rules[0].path) {
++      ASSERT_NE(NULL, rules[0].path)
++      {
+               TH_LOG("Empty rule list");
+       }
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
+-      ASSERT_LE(0, ruleset_fd) {
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
++      ASSERT_LE(0, ruleset_fd)
++      {
+               TH_LOG("Failed to create a ruleset: %s", strerror(errno));
+       }
+       for (i = 0; rules[i].path; i++) {
+               add_path_beneath(_metadata, ruleset_fd, rules[i].access,
+-                              rules[i].path);
++                               rules[i].path);
+       }
+       return ruleset_fd;
+ }
+ static void enforce_ruleset(struct __test_metadata *const _metadata,
+-              const int ruleset_fd)
++                          const int ruleset_fd)
+ {
+       ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
+-      ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0)) {
++      ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0))
++      {
+               TH_LOG("Failed to enforce ruleset: %s", strerror(errno));
+       }
+ }
+@@ -512,13 +523,14 @@ TEST_F_FORK(layout1, proc_nsfs)
+               {
+                       .path = "/dev/null",
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {},
+       };
+       struct landlock_path_beneath_attr path_beneath;
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access |
+-                      LANDLOCK_ACCESS_FS_READ_DIR, rules);
++      const int ruleset_fd = create_ruleset(
++              _metadata, rules[0].access | LANDLOCK_ACCESS_FS_READ_DIR,
++              rules);
+       ASSERT_LE(0, ruleset_fd);
+       ASSERT_EQ(0, test_open("/proc/self/ns/mnt", O_RDONLY));
+@@ -545,16 +557,17 @@ TEST_F_FORK(layout1, proc_nsfs)
+        * references to a ruleset.
+        */
+       path_beneath.allowed_access = LANDLOCK_ACCESS_FS_READ_FILE |
+-              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                    LANDLOCK_ACCESS_FS_WRITE_FILE,
+       path_beneath.parent_fd = open("/proc/self/ns/mnt", O_PATH | O_CLOEXEC);
+       ASSERT_LE(0, path_beneath.parent_fd);
+       ASSERT_EQ(-1, landlock_add_rule(ruleset_fd, LANDLOCK_RULE_PATH_BENEATH,
+-                              &path_beneath, 0));
++                                      &path_beneath, 0));
+       ASSERT_EQ(EBADFD, errno);
+       ASSERT_EQ(0, close(path_beneath.parent_fd));
+ }
+-TEST_F_FORK(layout1, unpriv) {
++TEST_F_FORK(layout1, unpriv)
++{
+       const struct rule rules[] = {
+               {
+                       .path = dir_s1d2,
+@@ -586,7 +599,7 @@ TEST_F_FORK(layout1, effective_access)
+               {
+                       .path = file1_s2d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {},
+       };
+@@ -662,12 +675,12 @@ TEST_F_FORK(layout1, ruleset_overlap)
+               {
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_READ_DIR,
++                                LANDLOCK_ACCESS_FS_READ_DIR,
+               },
+               {},
+       };
+@@ -717,8 +730,8 @@ TEST_F_FORK(layout1, non_overlapping_acc
+       ASSERT_EQ(0, unlink(file1_s1d1));
+       ASSERT_EQ(0, unlink(file1_s1d2));
+-      ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG,
+-                      layer1);
++      ruleset_fd =
++              create_ruleset(_metadata, LANDLOCK_ACCESS_FS_MAKE_REG, layer1);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -729,7 +742,7 @@ TEST_F_FORK(layout1, non_overlapping_acc
+       ASSERT_EQ(0, unlink(file1_s1d2));
+       ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_REMOVE_FILE,
+-                      layer2);
++                                  layer2);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -775,7 +788,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+               {
+                       .path = dir_s1d3,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               /* ...but also denies read access via its grandparent directory. */
+               {
+@@ -839,7 +852,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+       int ruleset_fd;
+       ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
+-                      layer1_read);
++                                  layer1_read);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -849,8 +862,10 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
+       ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
+-      ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE, layer2_read_write);
++      ruleset_fd = create_ruleset(_metadata,
++                                  LANDLOCK_ACCESS_FS_READ_FILE |
++                                          LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                  layer2_read_write);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -861,7 +876,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
+       ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
+-                      layer3_read);
++                                  layer3_read);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -872,8 +887,10 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(0, test_open(file2_s1d3, O_WRONLY));
+       /* This time, denies write access for the file hierarchy. */
+-      ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE, layer4_read_write);
++      ruleset_fd = create_ruleset(_metadata,
++                                  LANDLOCK_ACCESS_FS_READ_FILE |
++                                          LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                  layer4_read_write);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -888,7 +905,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
+       ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE,
+-                      layer5_read);
++                                  layer5_read);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -900,7 +917,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
+       ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_EXECUTE,
+-                      layer6_execute);
++                                  layer6_execute);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -911,8 +928,10 @@ TEST_F_FORK(layout1, interleaved_masked_
+       ASSERT_EQ(EACCES, test_open(file2_s1d3, O_WRONLY));
+       ASSERT_EQ(EACCES, test_open(file2_s1d3, O_RDONLY));
+-      ruleset_fd = create_ruleset(_metadata, LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE, layer7_read_write);
++      ruleset_fd = create_ruleset(_metadata,
++                                  LANDLOCK_ACCESS_FS_READ_FILE |
++                                          LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                  layer7_read_write);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -930,7 +949,7 @@ TEST_F_FORK(layout1, inherit_subset)
+               {
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_READ_DIR,
++                                LANDLOCK_ACCESS_FS_READ_DIR,
+               },
+               {},
+       };
+@@ -958,7 +977,7 @@ TEST_F_FORK(layout1, inherit_subset)
+        * ANDed with the previous ones.
+        */
+       add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
+-                      dir_s1d2);
++                       dir_s1d2);
+       /*
+        * According to ruleset_fd, dir_s1d2 should now have the
+        * LANDLOCK_ACCESS_FS_READ_FILE and LANDLOCK_ACCESS_FS_WRITE_FILE
+@@ -1013,7 +1032,7 @@ TEST_F_FORK(layout1, inherit_subset)
+        * that there was no rule tied to it before.
+        */
+       add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_WRITE_FILE,
+-                      dir_s1d3);
++                       dir_s1d3);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -1063,8 +1082,10 @@ TEST_F_FORK(layout1, inherit_superset)
+       ASSERT_EQ(0, test_open(file1_s1d3, O_RDONLY));
+       /* Now dir_s1d2, parent of dir_s1d3, gets a new rule tied to it. */
+-      add_path_beneath(_metadata, ruleset_fd, LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_READ_DIR, dir_s1d2);
++      add_path_beneath(_metadata, ruleset_fd,
++                       LANDLOCK_ACCESS_FS_READ_FILE |
++                               LANDLOCK_ACCESS_FS_READ_DIR,
++                       dir_s1d2);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(0, close(ruleset_fd));
+@@ -1106,15 +1127,15 @@ TEST_F_FORK(layout1, empty_or_same_rules
+       int ruleset_fd;
+       /* Tests empty handled_access_fs. */
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(-1, ruleset_fd);
+       ASSERT_EQ(ENOMSG, errno);
+       /* Enforces policy which deny read access to all files. */
+       ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE;
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
+@@ -1122,8 +1143,8 @@ TEST_F_FORK(layout1, empty_or_same_rules
+       /* Nests a policy which deny read access to all directories. */
+       ruleset_attr.handled_access_fs = LANDLOCK_ACCESS_FS_READ_DIR;
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+       ASSERT_EQ(EACCES, test_open(file1_s1d1, O_RDONLY));
+@@ -1258,7 +1279,8 @@ TEST_F_FORK(layout1, rule_inside_mount_n
+       int ruleset_fd;
+       set_cap(_metadata, CAP_SYS_ADMIN);
+-      ASSERT_EQ(0, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3)) {
++      ASSERT_EQ(0, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3))
++      {
+               TH_LOG("Failed to pivot root: %s", strerror(errno));
+       };
+       ASSERT_EQ(0, chdir("/"));
+@@ -1311,12 +1333,13 @@ TEST_F_FORK(layout1, move_mount)
+       set_cap(_metadata, CAP_SYS_ADMIN);
+       ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
+-                              dir_s1d2, 0)) {
++                           dir_s1d2, 0))
++      {
+               TH_LOG("Failed to move mount: %s", strerror(errno));
+       }
+       ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
+-                              dir_s3d2, 0));
++                           dir_s3d2, 0));
+       clear_cap(_metadata, CAP_SYS_ADMIN);
+       enforce_ruleset(_metadata, ruleset_fd);
+@@ -1324,7 +1347,7 @@ TEST_F_FORK(layout1, move_mount)
+       set_cap(_metadata, CAP_SYS_ADMIN);
+       ASSERT_EQ(-1, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
+-                              dir_s1d2, 0));
++                            dir_s1d2, 0));
+       ASSERT_EQ(EPERM, errno);
+       clear_cap(_metadata, CAP_SYS_ADMIN);
+ }
+@@ -1371,7 +1394,7 @@ enum relative_access {
+ };
+ static void test_relative_path(struct __test_metadata *const _metadata,
+-              const enum relative_access rel)
++                             const enum relative_access rel)
+ {
+       /*
+        * Common layer to check that chroot doesn't ignore it (i.e. a chroot
+@@ -1434,14 +1457,16 @@ static void test_relative_path(struct __
+               break;
+       case REL_CHROOT_ONLY:
+               /* Do chroot into dir_s1d2 (relative to dir_s2d2). */
+-              ASSERT_EQ(0, chroot("../../s1d1/s1d2")) {
++              ASSERT_EQ(0, chroot("../../s1d1/s1d2"))
++              {
+                       TH_LOG("Failed to chroot: %s", strerror(errno));
+               }
+               dirfd = AT_FDCWD;
+               break;
+       case REL_CHROOT_CHDIR:
+               /* Do chroot into dir_s1d2. */
+-              ASSERT_EQ(0, chroot(".")) {
++              ASSERT_EQ(0, chroot("."))
++              {
+                       TH_LOG("Failed to chroot: %s", strerror(errno));
+               }
+               dirfd = AT_FDCWD;
+@@ -1449,7 +1474,7 @@ static void test_relative_path(struct __
+       }
+       ASSERT_EQ((rel == REL_CHROOT_CHDIR) ? 0 : EACCES,
+-                      test_open_rel(dirfd, "..", O_RDONLY));
++                test_open_rel(dirfd, "..", O_RDONLY));
+       ASSERT_EQ(0, test_open_rel(dirfd, ".", O_RDONLY));
+       if (rel == REL_CHROOT_ONLY) {
+@@ -1471,11 +1496,13 @@ static void test_relative_path(struct __
+       if (rel != REL_CHROOT_CHDIR) {
+               ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s1d1", O_RDONLY));
+               ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2", O_RDONLY));
+-              ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3", O_RDONLY));
++              ASSERT_EQ(0, test_open_rel(dirfd, "../../s1d1/s1d2/s1d3",
++                                         O_RDONLY));
+               ASSERT_EQ(EACCES, test_open_rel(dirfd, "../../s2d1", O_RDONLY));
+               ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2", O_RDONLY));
+-              ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3", O_RDONLY));
++              ASSERT_EQ(0, test_open_rel(dirfd, "../../s2d1/s2d2/s2d3",
++                                         O_RDONLY));
+       }
+       if (rel == REL_OPEN)
+@@ -1504,40 +1531,42 @@ TEST_F_FORK(layout1, relative_chroot_chd
+ }
+ static void copy_binary(struct __test_metadata *const _metadata,
+-              const char *const dst_path)
++                      const char *const dst_path)
+ {
+       int dst_fd, src_fd;
+       struct stat statbuf;
+       dst_fd = open(dst_path, O_WRONLY | O_TRUNC | O_CLOEXEC);
+-      ASSERT_LE(0, dst_fd) {
+-              TH_LOG("Failed to open \"%s\": %s", dst_path,
+-                              strerror(errno));
++      ASSERT_LE(0, dst_fd)
++      {
++              TH_LOG("Failed to open \"%s\": %s", dst_path, strerror(errno));
+       }
+       src_fd = open(BINARY_PATH, O_RDONLY | O_CLOEXEC);
+-      ASSERT_LE(0, src_fd) {
++      ASSERT_LE(0, src_fd)
++      {
+               TH_LOG("Failed to open \"" BINARY_PATH "\": %s",
+-                              strerror(errno));
++                     strerror(errno));
+       }
+       ASSERT_EQ(0, fstat(src_fd, &statbuf));
+-      ASSERT_EQ(statbuf.st_size, sendfile(dst_fd, src_fd, 0,
+-                              statbuf.st_size));
++      ASSERT_EQ(statbuf.st_size,
++                sendfile(dst_fd, src_fd, 0, statbuf.st_size));
+       ASSERT_EQ(0, close(src_fd));
+       ASSERT_EQ(0, close(dst_fd));
+ }
+-static void test_execute(struct __test_metadata *const _metadata,
+-              const int err, const char *const path)
++static void test_execute(struct __test_metadata *const _metadata, const int err,
++                       const char *const path)
+ {
+       int status;
+-      char *const argv[] = {(char *)path, NULL};
++      char *const argv[] = { (char *)path, NULL };
+       const pid_t child = fork();
+       ASSERT_LE(0, child);
+       if (child == 0) {
+-              ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL)) {
++              ASSERT_EQ(err ? -1 : 0, execve(path, argv, NULL))
++              {
+                       TH_LOG("Failed to execute \"%s\": %s", path,
+-                                      strerror(errno));
++                             strerror(errno));
+               };
+               ASSERT_EQ(err, errno);
+               _exit(_metadata->passed ? 2 : 1);
+@@ -1545,9 +1574,10 @@ static void test_execute(struct __test_m
+       }
+       ASSERT_EQ(child, waitpid(child, &status, 0));
+       ASSERT_EQ(1, WIFEXITED(status));
+-      ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status)) {
++      ASSERT_EQ(err ? 2 : 0, WEXITSTATUS(status))
++      {
+               TH_LOG("Unexpected return code for \"%s\": %s", path,
+-                              strerror(errno));
++                     strerror(errno));
+       };
+ }
+@@ -1560,8 +1590,8 @@ TEST_F_FORK(layout1, execute)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+       copy_binary(_metadata, file1_s1d1);
+@@ -1593,8 +1623,8 @@ TEST_F_FORK(layout1, link)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1630,8 +1660,8 @@ TEST_F_FORK(layout1, rename_file)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1684,14 +1714,14 @@ TEST_F_FORK(layout1, rename_file)
+       /* Exchanges and renames files with same parent. */
+       ASSERT_EQ(0, renameat2(AT_FDCWD, file2_s2d3, AT_FDCWD, file1_s2d3,
+-                              RENAME_EXCHANGE));
++                             RENAME_EXCHANGE));
+       ASSERT_EQ(0, rename(file2_s2d3, file1_s2d3));
+       /* Exchanges files and directories with same parent, twice. */
+       ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
+-                              RENAME_EXCHANGE));
++                             RENAME_EXCHANGE));
+       ASSERT_EQ(0, renameat2(AT_FDCWD, file1_s2d2, AT_FDCWD, dir_s2d3,
+-                              RENAME_EXCHANGE));
++                             RENAME_EXCHANGE));
+ }
+ TEST_F_FORK(layout1, rename_dir)
+@@ -1707,8 +1737,8 @@ TEST_F_FORK(layout1, rename_dir)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1745,7 +1775,7 @@ TEST_F_FORK(layout1, rename_dir)
+        * directory removal.
+        */
+       ASSERT_EQ(0, renameat2(AT_FDCWD, dir_s1d3, AT_FDCWD, file1_s1d2,
+-                              RENAME_EXCHANGE));
++                             RENAME_EXCHANGE));
+       ASSERT_EQ(0, unlink(dir_s1d3));
+       ASSERT_EQ(0, mkdir(dir_s1d3, 0700));
+       ASSERT_EQ(0, rename(file1_s1d2, dir_s1d3));
+@@ -1761,8 +1791,8 @@ TEST_F_FORK(layout1, remove_dir)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1798,8 +1828,8 @@ TEST_F_FORK(layout1, remove_file)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+@@ -1814,7 +1844,8 @@ TEST_F_FORK(layout1, remove_file)
+ }
+ static void test_make_file(struct __test_metadata *const _metadata,
+-              const __u64 access, const mode_t mode, const dev_t dev)
++                         const __u64 access, const mode_t mode,
++                         const dev_t dev)
+ {
+       const struct rule rules[] = {
+               {
+@@ -1829,9 +1860,10 @@ static void test_make_file(struct __test
+       ASSERT_EQ(0, unlink(file1_s1d1));
+       ASSERT_EQ(0, unlink(file2_s1d1));
+-      ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev)) {
+-              TH_LOG("Failed to make file \"%s\": %s",
+-                              file2_s1d1, strerror(errno));
++      ASSERT_EQ(0, mknod(file2_s1d1, mode | 0400, dev))
++      {
++              TH_LOG("Failed to make file \"%s\": %s", file2_s1d1,
++                     strerror(errno));
+       };
+       ASSERT_EQ(0, unlink(file1_s1d2));
+@@ -1850,9 +1882,10 @@ static void test_make_file(struct __test
+       ASSERT_EQ(-1, rename(file2_s1d1, file1_s1d1));
+       ASSERT_EQ(EACCES, errno);
+-      ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev)) {
+-              TH_LOG("Failed to make file \"%s\": %s",
+-                              file1_s1d2, strerror(errno));
++      ASSERT_EQ(0, mknod(file1_s1d2, mode | 0400, dev))
++      {
++              TH_LOG("Failed to make file \"%s\": %s", file1_s1d2,
++                     strerror(errno));
+       };
+       ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
+       ASSERT_EQ(0, unlink(file2_s1d2));
+@@ -1869,7 +1902,7 @@ TEST_F_FORK(layout1, make_char)
+       /* Creates a /dev/null device. */
+       set_cap(_metadata, CAP_MKNOD);
+       test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_CHAR, S_IFCHR,
+-                      makedev(1, 3));
++                     makedev(1, 3));
+ }
+ TEST_F_FORK(layout1, make_block)
+@@ -1877,7 +1910,7 @@ TEST_F_FORK(layout1, make_block)
+       /* Creates a /dev/loop0 device. */
+       set_cap(_metadata, CAP_MKNOD);
+       test_make_file(_metadata, LANDLOCK_ACCESS_FS_MAKE_BLOCK, S_IFBLK,
+-                      makedev(7, 0));
++                     makedev(7, 0));
+ }
+ TEST_F_FORK(layout1, make_reg_1)
+@@ -1909,8 +1942,8 @@ TEST_F_FORK(layout1, make_sym)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1954,8 +1987,8 @@ TEST_F_FORK(layout1, make_dir)
+               },
+               {},
+       };
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1974,12 +2007,12 @@ TEST_F_FORK(layout1, make_dir)
+ }
+ static int open_proc_fd(struct __test_metadata *const _metadata, const int fd,
+-              const int open_flags)
++                      const int open_flags)
+ {
+       static const char path_template[] = "/proc/self/fd/%d";
+       char procfd_path[sizeof(path_template) + 10];
+-      const int procfd_path_size = snprintf(procfd_path, sizeof(procfd_path),
+-                      path_template, fd);
++      const int procfd_path_size =
++              snprintf(procfd_path, sizeof(procfd_path), path_template, fd);
+       ASSERT_LT(procfd_path_size, sizeof(procfd_path));
+       return open(procfd_path, open_flags);
+@@ -1995,9 +2028,10 @@ TEST_F_FORK(layout1, proc_unlinked_file)
+               {},
+       };
+       int reg_fd, proc_fd;
+-      const int ruleset_fd = create_ruleset(_metadata,
+-                      LANDLOCK_ACCESS_FS_READ_FILE |
+-                      LANDLOCK_ACCESS_FS_WRITE_FILE, rules);
++      const int ruleset_fd = create_ruleset(
++              _metadata,
++              LANDLOCK_ACCESS_FS_READ_FILE | LANDLOCK_ACCESS_FS_WRITE_FILE,
++              rules);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+@@ -2014,9 +2048,10 @@ TEST_F_FORK(layout1, proc_unlinked_file)
+       ASSERT_EQ(0, close(proc_fd));
+       proc_fd = open_proc_fd(_metadata, reg_fd, O_RDWR | O_CLOEXEC);
+-      ASSERT_EQ(-1, proc_fd) {
+-              TH_LOG("Successfully opened /proc/self/fd/%d: %s",
+-                              reg_fd, strerror(errno));
++      ASSERT_EQ(-1, proc_fd)
++      {
++              TH_LOG("Successfully opened /proc/self/fd/%d: %s", reg_fd,
++                     strerror(errno));
+       }
+       ASSERT_EQ(EACCES, errno);
+@@ -2032,13 +2067,13 @@ TEST_F_FORK(layout1, proc_pipe)
+               {
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {},
+       };
+       /* Limits read and write access to files tied to the filesystem. */
+-      const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+-                      rules);
++      const int ruleset_fd =
++              create_ruleset(_metadata, rules[0].access, rules);
+       ASSERT_LE(0, ruleset_fd);
+       enforce_ruleset(_metadata, ruleset_fd);
+@@ -2050,7 +2085,8 @@ TEST_F_FORK(layout1, proc_pipe)
+       /* Checks access to pipes through FD. */
+       ASSERT_EQ(0, pipe2(pipe_fds, O_CLOEXEC));
+-      ASSERT_EQ(1, write(pipe_fds[1], ".", 1)) {
++      ASSERT_EQ(1, write(pipe_fds[1], ".", 1))
++      {
+               TH_LOG("Failed to write in pipe: %s", strerror(errno));
+       }
+       ASSERT_EQ(1, read(pipe_fds[0], &buf, 1));
+@@ -2059,9 +2095,10 @@ TEST_F_FORK(layout1, proc_pipe)
+       /* Checks write access to pipe through /proc/self/fd . */
+       proc_fd = open_proc_fd(_metadata, pipe_fds[1], O_WRONLY | O_CLOEXEC);
+       ASSERT_LE(0, proc_fd);
+-      ASSERT_EQ(1, write(proc_fd, ".", 1)) {
++      ASSERT_EQ(1, write(proc_fd, ".", 1))
++      {
+               TH_LOG("Failed to write through /proc/self/fd/%d: %s",
+-                              pipe_fds[1], strerror(errno));
++                     pipe_fds[1], strerror(errno));
+       }
+       ASSERT_EQ(0, close(proc_fd));
+@@ -2069,9 +2106,10 @@ TEST_F_FORK(layout1, proc_pipe)
+       proc_fd = open_proc_fd(_metadata, pipe_fds[0], O_RDONLY | O_CLOEXEC);
+       ASSERT_LE(0, proc_fd);
+       buf = '\0';
+-      ASSERT_EQ(1, read(proc_fd, &buf, 1)) {
++      ASSERT_EQ(1, read(proc_fd, &buf, 1))
++      {
+               TH_LOG("Failed to read through /proc/self/fd/%d: %s",
+-                              pipe_fds[1], strerror(errno));
++                     pipe_fds[1], strerror(errno));
+       }
+       ASSERT_EQ(0, close(proc_fd));
+@@ -2292,8 +2330,8 @@ TEST_F_FORK(layout1_bind, same_content_s
+       ASSERT_EQ(EACCES, test_open(bind_file1_s1d3, O_WRONLY));
+ }
+-#define LOWER_BASE    TMP_DIR "/lower"
+-#define LOWER_DATA    LOWER_BASE "/data"
++#define LOWER_BASE TMP_DIR "/lower"
++#define LOWER_DATA LOWER_BASE "/data"
+ static const char lower_fl1[] = LOWER_DATA "/fl1";
+ static const char lower_dl1[] = LOWER_DATA "/dl1";
+ static const char lower_dl1_fl2[] = LOWER_DATA "/dl1/fl2";
+@@ -2319,9 +2357,9 @@ static const char (*lower_sub_files[])[]
+       NULL,
+ };
+-#define UPPER_BASE    TMP_DIR "/upper"
+-#define UPPER_DATA    UPPER_BASE "/data"
+-#define UPPER_WORK    UPPER_BASE "/work"
++#define UPPER_BASE TMP_DIR "/upper"
++#define UPPER_DATA UPPER_BASE "/data"
++#define UPPER_WORK UPPER_BASE "/work"
+ static const char upper_fu1[] = UPPER_DATA "/fu1";
+ static const char upper_du1[] = UPPER_DATA "/du1";
+ static const char upper_du1_fu2[] = UPPER_DATA "/du1/fu2";
+@@ -2347,8 +2385,8 @@ static const char (*upper_sub_files[])[]
+       NULL,
+ };
+-#define MERGE_BASE    TMP_DIR "/merge"
+-#define MERGE_DATA    MERGE_BASE "/data"
++#define MERGE_BASE TMP_DIR "/merge"
++#define MERGE_DATA MERGE_BASE "/data"
+ static const char merge_fl1[] = MERGE_DATA "/fl1";
+ static const char merge_dl1[] = MERGE_DATA "/dl1";
+ static const char merge_dl1_fl2[] = MERGE_DATA "/dl1/fl2";
+@@ -2374,12 +2412,8 @@ static const char (*merge_base_directori
+       NULL,
+ };
+ static const char (*merge_sub_files[])[] = {
+-      &merge_dl1_fl2,
+-      &merge_du1_fu2,
+-      &merge_do1_fo2,
+-      &merge_do1_fl3,
+-      &merge_do1_fu3,
+-      NULL,
++      &merge_dl1_fl2, &merge_du1_fu2, &merge_do1_fo2,
++      &merge_do1_fl3, &merge_do1_fu3, NULL,
+ };
+ /*
+@@ -2455,9 +2489,8 @@ FIXTURE_SETUP(layout2_overlay)
+       set_cap(_metadata, CAP_SYS_ADMIN);
+       set_cap(_metadata, CAP_DAC_OVERRIDE);
+       ASSERT_EQ(0, mount("overlay", MERGE_DATA, "overlay", 0,
+-                              "lowerdir=" LOWER_DATA
+-                              ",upperdir=" UPPER_DATA
+-                              ",workdir=" UPPER_WORK));
++                         "lowerdir=" LOWER_DATA ",upperdir=" UPPER_DATA
++                         ",workdir=" UPPER_WORK));
+       clear_cap(_metadata, CAP_DAC_OVERRIDE);
+       clear_cap(_metadata, CAP_SYS_ADMIN);
+ }
+@@ -2524,9 +2557,9 @@ TEST_F_FORK(layout2_overlay, no_restrict
+       ASSERT_EQ(0, test_open(merge_do1_fu3, O_RDONLY));
+ }
+-#define for_each_path(path_list, path_entry, i)                       \
+-      for (i = 0, path_entry = *path_list[i]; path_list[i];   \
+-                      path_entry = *path_list[++i])
++#define for_each_path(path_list, path_entry, i)               \
++      for (i = 0, path_entry = *path_list[i]; path_list[i]; \
++           path_entry = *path_list[++i])
+ TEST_F_FORK(layout2_overlay, same_content_different_file)
+ {
+@@ -2622,27 +2655,27 @@ TEST_F_FORK(layout2_overlay, same_conten
+               {
+                       .path = merge_dl1_fl2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {
+                       .path = merge_du1_fu2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {
+                       .path = merge_do1_fo2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {
+                       .path = merge_do1_fl3,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {
+                       .path = merge_do1_fu3,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {},
+       };
+@@ -2650,7 +2683,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+               {
+                       .path = MERGE_DATA,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+-                              LANDLOCK_ACCESS_FS_WRITE_FILE,
++                                LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+               {},
+       };
+@@ -2670,7 +2703,8 @@ TEST_F_FORK(layout2_overlay, same_conten
+               ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
+       }
+       for_each_path(lower_base_directories, path_entry, i) {
+-              ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
++              ASSERT_EQ(EACCES,
++                        test_open(path_entry, O_RDONLY | O_DIRECTORY));
+       }
+       for_each_path(lower_sub_files, path_entry, i) {
+               ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
+@@ -2682,7 +2716,8 @@ TEST_F_FORK(layout2_overlay, same_conten
+               ASSERT_EQ(EACCES, test_open(path_entry, O_WRONLY));
+       }
+       for_each_path(upper_base_directories, path_entry, i) {
+-              ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
++              ASSERT_EQ(EACCES,
++                        test_open(path_entry, O_RDONLY | O_DIRECTORY));
+       }
+       for_each_path(upper_sub_files, path_entry, i) {
+               ASSERT_EQ(0, test_open(path_entry, O_RDONLY));
+@@ -2767,7 +2802,8 @@ TEST_F_FORK(layout2_overlay, same_conten
+               ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
+       }
+       for_each_path(merge_base_directories, path_entry, i) {
+-              ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
++              ASSERT_EQ(EACCES,
++                        test_open(path_entry, O_RDONLY | O_DIRECTORY));
+       }
+       for_each_path(merge_sub_files, path_entry, i) {
+               ASSERT_EQ(0, test_open(path_entry, O_RDWR));
+@@ -2792,7 +2828,8 @@ TEST_F_FORK(layout2_overlay, same_conten
+               ASSERT_EQ(EACCES, test_open(path_entry, O_RDWR));
+       }
+       for_each_path(merge_base_directories, path_entry, i) {
+-              ASSERT_EQ(EACCES, test_open(path_entry, O_RDONLY | O_DIRECTORY));
++              ASSERT_EQ(EACCES,
++                        test_open(path_entry, O_RDONLY | O_DIRECTORY));
+       }
+       for_each_path(merge_sub_files, path_entry, i) {
+               ASSERT_EQ(0, test_open(path_entry, O_RDWR));
+--- a/tools/testing/selftests/landlock/ptrace_test.c
++++ b/tools/testing/selftests/landlock/ptrace_test.c
+@@ -26,9 +26,10 @@ static void create_domain(struct __test_
+               .handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_BLOCK,
+       };
+-      ruleset_fd = landlock_create_ruleset(&ruleset_attr,
+-                      sizeof(ruleset_attr), 0);
+-      EXPECT_LE(0, ruleset_fd) {
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
++      EXPECT_LE(0, ruleset_fd)
++      {
+               TH_LOG("Failed to create a ruleset: %s", strerror(errno));
+       }
+       EXPECT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
+@@ -43,7 +44,7 @@ static int test_ptrace_read(const pid_t
+       int procenv_path_size, fd;
+       procenv_path_size = snprintf(procenv_path, sizeof(procenv_path),
+-                      path_template, pid);
++                                   path_template, pid);
+       if (procenv_path_size >= sizeof(procenv_path))
+               return E2BIG;
+@@ -63,7 +64,8 @@ static int test_ptrace_read(const pid_t
+ FIXTURE(hierarchy) {};
+ /* clang-format on */
+-FIXTURE_VARIANT(hierarchy) {
++FIXTURE_VARIANT(hierarchy)
++{
+       const bool domain_both;
+       const bool domain_parent;
+       const bool domain_child;
+@@ -217,10 +219,12 @@ FIXTURE_VARIANT_ADD(hierarchy, deny_with
+ };
+ FIXTURE_SETUP(hierarchy)
+-{ }
++{
++}
+ FIXTURE_TEARDOWN(hierarchy)
+-{ }
++{
++}
+ /* Test PTRACE_TRACEME and PTRACE_ATTACH for parent and child. */
+ TEST_F(hierarchy, trace)
+@@ -348,7 +352,7 @@ TEST_F(hierarchy, trace)
+       ASSERT_EQ(1, write(pipe_parent[1], ".", 1));
+       ASSERT_EQ(child, waitpid(child, &status, 0));
+       if (WIFSIGNALED(status) || !WIFEXITED(status) ||
+-                      WEXITSTATUS(status) != EXIT_SUCCESS)
++          WEXITSTATUS(status) != EXIT_SUCCESS)
+               _metadata->passed = 0;
+ }
diff --git a/queue-5.18/selftests-landlock-fully-test-file-rename-with-remove-access.patch b/queue-5.18/selftests-landlock-fully-test-file-rename-with-remove-access.patch
new file mode 100644 (file)
index 0000000..c510335
--- /dev/null
@@ -0,0 +1,125 @@
+From 6a1bdd4a0bfc30fa4fa2b3a979e6525f28996db9 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:16 +0200
+Subject: selftests/landlock: Fully test file rename with "remove" access
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 6a1bdd4a0bfc30fa4fa2b3a979e6525f28996db9 upstream.
+
+These tests were missing to check the check_access_path() call with all
+combinations of maybe_remove(old_dentry) and maybe_remove(new_dentry).
+
+Extend layout1.link with a new complementary test and check that
+REMOVE_FILE is not required to link a file.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-7-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |   41 ++++++++++++++++++++++++++---
+ 1 file changed, 37 insertions(+), 4 deletions(-)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -1659,15 +1659,21 @@ TEST_F_FORK(layout1, execute)
+ TEST_F_FORK(layout1, link)
+ {
+-      const struct rule rules[] = {
++      const struct rule layer1[] = {
+               {
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_MAKE_REG,
+               },
+               {},
+       };
+-      const int ruleset_fd =
+-              create_ruleset(_metadata, rules[0].access, rules);
++      const struct rule layer2[] = {
++              {
++                      .path = dir_s1d3,
++                      .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
++              },
++              {},
++      };
++      int ruleset_fd = create_ruleset(_metadata, layer1[0].access, layer1);
+       ASSERT_LE(0, ruleset_fd);
+@@ -1680,14 +1686,30 @@ TEST_F_FORK(layout1, link)
+       ASSERT_EQ(-1, link(file2_s1d1, file1_s1d1));
+       ASSERT_EQ(EACCES, errno);
++
+       /* Denies linking because of reparenting. */
+       ASSERT_EQ(-1, link(file1_s2d1, file1_s1d2));
+       ASSERT_EQ(EXDEV, errno);
+       ASSERT_EQ(-1, link(file2_s1d2, file1_s1d3));
+       ASSERT_EQ(EXDEV, errno);
++      ASSERT_EQ(-1, link(file2_s1d3, file1_s1d2));
++      ASSERT_EQ(EXDEV, errno);
+       ASSERT_EQ(0, link(file2_s1d2, file1_s1d2));
+       ASSERT_EQ(0, link(file2_s1d3, file1_s1d3));
++
++      /* Prepares for next unlinks. */
++      ASSERT_EQ(0, unlink(file2_s1d2));
++      ASSERT_EQ(0, unlink(file2_s1d3));
++
++      ruleset_fd = create_ruleset(_metadata, layer2[0].access, layer2);
++      ASSERT_LE(0, ruleset_fd);
++      enforce_ruleset(_metadata, ruleset_fd);
++      ASSERT_EQ(0, close(ruleset_fd));
++
++      /* Checks that linkind doesn't require the ability to delete a file. */
++      ASSERT_EQ(0, link(file1_s1d2, file2_s1d2));
++      ASSERT_EQ(0, link(file1_s1d3, file2_s1d3));
+ }
+ TEST_F_FORK(layout1, rename_file)
+@@ -1708,7 +1730,6 @@ TEST_F_FORK(layout1, rename_file)
+       ASSERT_LE(0, ruleset_fd);
+-      ASSERT_EQ(0, unlink(file1_s1d1));
+       ASSERT_EQ(0, unlink(file1_s1d2));
+       enforce_ruleset(_metadata, ruleset_fd);
+@@ -1744,9 +1765,15 @@ TEST_F_FORK(layout1, rename_file)
+       ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s2d2, AT_FDCWD, file1_s2d1,
+                               RENAME_EXCHANGE));
+       ASSERT_EQ(EACCES, errno);
++      /* Checks that file1_s2d1 cannot be removed (instead of ENOTDIR). */
++      ASSERT_EQ(-1, rename(dir_s2d2, file1_s2d1));
++      ASSERT_EQ(EACCES, errno);
+       ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s2d1, AT_FDCWD, dir_s2d2,
+                               RENAME_EXCHANGE));
+       ASSERT_EQ(EACCES, errno);
++      /* Checks that file1_s1d1 cannot be removed (instead of EISDIR). */
++      ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
++      ASSERT_EQ(EACCES, errno);
+       /* Renames files with different parents. */
+       ASSERT_EQ(-1, rename(file1_s2d2, file1_s1d2));
+@@ -1809,9 +1836,15 @@ TEST_F_FORK(layout1, rename_dir)
+       ASSERT_EQ(-1, renameat2(AT_FDCWD, dir_s1d1, AT_FDCWD, dir_s2d1,
+                               RENAME_EXCHANGE));
+       ASSERT_EQ(EACCES, errno);
++      /* Checks that dir_s1d2 cannot be removed (instead of ENOTDIR). */
++      ASSERT_EQ(-1, rename(dir_s1d2, file1_s1d1));
++      ASSERT_EQ(EACCES, errno);
+       ASSERT_EQ(-1, renameat2(AT_FDCWD, file1_s1d1, AT_FDCWD, dir_s1d2,
+                               RENAME_EXCHANGE));
+       ASSERT_EQ(EACCES, errno);
++      /* Checks that dir_s1d2 cannot be removed (instead of EISDIR). */
++      ASSERT_EQ(-1, rename(file1_s1d1, dir_s1d2));
++      ASSERT_EQ(EACCES, errno);
+       /*
+        * Exchanges and renames directory to the same parent, which allows
diff --git a/queue-5.18/selftests-landlock-make-tests-build-with-old-libc.patch b/queue-5.18/selftests-landlock-make-tests-build-with-old-libc.patch
new file mode 100644 (file)
index 0000000..55bfc59
--- /dev/null
@@ -0,0 +1,96 @@
+From 87129ef13603ae46c82bcd09eed948acf0506dbb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:12 +0200
+Subject: selftests/landlock: Make tests build with old libc
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 87129ef13603ae46c82bcd09eed948acf0506dbb upstream.
+
+Replace SYS_<syscall> with __NR_<syscall>.  Using the __NR_<syscall>
+notation, provided by UAPI, is useful to build tests on systems without
+the SYS_<syscall> definitions.
+
+Replace SYS_pivot_root with __NR_pivot_root, and SYS_move_mount with
+__NR_move_mount.
+
+Define renameat2() and RENAME_EXCHANGE if they are unknown to old build
+systems.
+
+Cc: Shuah Khan <shuah@kernel.org>
+Link: https://lore.kernel.org/r/20220506160820.524344-3-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |   23 ++++++++++++++++++-----
+ 1 file changed, 18 insertions(+), 5 deletions(-)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -22,6 +22,19 @@
+ #include "common.h"
++#ifndef renameat2
++int renameat2(int olddirfd, const char *oldpath, int newdirfd,
++            const char *newpath, unsigned int flags)
++{
++      return syscall(__NR_renameat2, olddirfd, oldpath, newdirfd, newpath,
++                     flags);
++}
++#endif
++
++#ifndef RENAME_EXCHANGE
++#define RENAME_EXCHANGE (1 << 1)
++#endif
++
+ #define TMP_DIR "tmp"
+ #define BINARY_PATH "./true"
+@@ -1279,7 +1292,7 @@ TEST_F_FORK(layout1, rule_inside_mount_n
+       int ruleset_fd;
+       set_cap(_metadata, CAP_SYS_ADMIN);
+-      ASSERT_EQ(0, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3))
++      ASSERT_EQ(0, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3))
+       {
+               TH_LOG("Failed to pivot root: %s", strerror(errno));
+       };
+@@ -1313,7 +1326,7 @@ TEST_F_FORK(layout1, mount_and_pivot)
+       set_cap(_metadata, CAP_SYS_ADMIN);
+       ASSERT_EQ(-1, mount(NULL, dir_s3d2, NULL, MS_RDONLY, NULL));
+       ASSERT_EQ(EPERM, errno);
+-      ASSERT_EQ(-1, syscall(SYS_pivot_root, dir_s3d2, dir_s3d3));
++      ASSERT_EQ(-1, syscall(__NR_pivot_root, dir_s3d2, dir_s3d3));
+       ASSERT_EQ(EPERM, errno);
+       clear_cap(_metadata, CAP_SYS_ADMIN);
+ }
+@@ -1332,13 +1345,13 @@ TEST_F_FORK(layout1, move_mount)
+       ASSERT_LE(0, ruleset_fd);
+       set_cap(_metadata, CAP_SYS_ADMIN);
+-      ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
++      ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
+                            dir_s1d2, 0))
+       {
+               TH_LOG("Failed to move mount: %s", strerror(errno));
+       }
+-      ASSERT_EQ(0, syscall(SYS_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
++      ASSERT_EQ(0, syscall(__NR_move_mount, AT_FDCWD, dir_s1d2, AT_FDCWD,
+                            dir_s3d2, 0));
+       clear_cap(_metadata, CAP_SYS_ADMIN);
+@@ -1346,7 +1359,7 @@ TEST_F_FORK(layout1, move_mount)
+       ASSERT_EQ(0, close(ruleset_fd));
+       set_cap(_metadata, CAP_SYS_ADMIN);
+-      ASSERT_EQ(-1, syscall(SYS_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
++      ASSERT_EQ(-1, syscall(__NR_move_mount, AT_FDCWD, dir_s3d2, AT_FDCWD,
+                             dir_s1d2, 0));
+       ASSERT_EQ(EPERM, errno);
+       clear_cap(_metadata, CAP_SYS_ADMIN);
diff --git a/queue-5.18/selftests-landlock-normalize-array-assignment.patch b/queue-5.18/selftests-landlock-normalize-array-assignment.patch
new file mode 100644 (file)
index 0000000..73699af
--- /dev/null
@@ -0,0 +1,519 @@
+From 135464f9d29c5b306d7201220f1d00dab30fea89 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:05:10 +0200
+Subject: selftests/landlock: Normalize array assignment
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 135464f9d29c5b306d7201220f1d00dab30fea89 upstream.
+
+Add a comma after each array value to make clang-format keep the
+current array formatting.  See the following commit.
+
+Automatically modified with:
+sed -i 's/\t\({}\|NULL\)$/\0,/' tools/testing/selftests/landlock/fs_test.c
+
+Link: https://lore.kernel.org/r/20220506160513.523257-5-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/fs_test.c |  112 ++++++++++++++---------------
+ 1 file changed, 56 insertions(+), 56 deletions(-)
+
+--- a/tools/testing/selftests/landlock/fs_test.c
++++ b/tools/testing/selftests/landlock/fs_test.c
+@@ -514,7 +514,7 @@ TEST_F_FORK(layout1, proc_nsfs)
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       struct landlock_path_beneath_attr path_beneath;
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access |
+@@ -560,7 +560,7 @@ TEST_F_FORK(layout1, unpriv) {
+                       .path = dir_s1d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+@@ -588,7 +588,7 @@ TEST_F_FORK(layout1, effective_access)
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+       char buf;
+@@ -635,7 +635,7 @@ TEST_F_FORK(layout1, unhandled_access)
+                       .path = dir_s1d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       /* Here, we only handle read accesses, not write accesses. */
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RO, rules);
+@@ -669,7 +669,7 @@ TEST_F_FORK(layout1, ruleset_overlap)
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_READ_DIR,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -703,14 +703,14 @@ TEST_F_FORK(layout1, non_overlapping_acc
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_MAKE_REG,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer2[] = {
+               {
+                       .path = dir_s1d3,
+                       .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+@@ -767,7 +767,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = file1_s1d3,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       /* First rule with write restrictions. */
+       const struct rule layer2_read_write[] = {
+@@ -782,7 +782,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer3_read[] = {
+               /* Allows read access via its great-grandparent directory. */
+@@ -790,7 +790,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s1d1,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer4_read_write[] = {
+               /*
+@@ -801,7 +801,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer5_read[] = {
+               /*
+@@ -812,7 +812,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer6_execute[] = {
+               /*
+@@ -823,7 +823,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s2d1,
+                       .access = LANDLOCK_ACCESS_FS_EXECUTE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer7_read_write[] = {
+               /*
+@@ -834,7 +834,7 @@ TEST_F_FORK(layout1, interleaved_masked_
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+@@ -932,7 +932,7 @@ TEST_F_FORK(layout1, inherit_subset)
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_READ_DIR,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1048,7 +1048,7 @@ TEST_F_FORK(layout1, inherit_superset)
+                       .path = dir_s1d3,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1084,7 +1084,7 @@ TEST_F_FORK(layout1, max_layers)
+                       .path = dir_s1d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1146,7 +1146,7 @@ TEST_F_FORK(layout1, rule_on_mountpoint)
+                       .path = dir_s3d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1175,7 +1175,7 @@ TEST_F_FORK(layout1, rule_over_mountpoin
+                       .path = dir_s3d1,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1203,7 +1203,7 @@ TEST_F_FORK(layout1, rule_over_root_allo
+                       .path = "/",
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1233,7 +1233,7 @@ TEST_F_FORK(layout1, rule_over_root_deny
+                       .path = "/",
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1253,7 +1253,7 @@ TEST_F_FORK(layout1, rule_inside_mount_n
+                       .path = "s3d3",
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+@@ -1280,7 +1280,7 @@ TEST_F_FORK(layout1, mount_and_pivot)
+                       .path = dir_s3d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1303,7 +1303,7 @@ TEST_F_FORK(layout1, move_mount)
+                       .path = dir_s3d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1344,7 +1344,7 @@ TEST_F_FORK(layout1, release_inodes)
+                       .path = dir_s3d3,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
+@@ -1382,7 +1382,7 @@ static void test_relative_path(struct __
+                       .path = TMP_DIR,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer2_subs[] = {
+               {
+@@ -1393,7 +1393,7 @@ static void test_relative_path(struct __
+                       .path = dir_s2d2,
+                       .access = ACCESS_RO,
+               },
+-              {}
++              {},
+       };
+       int dirfd, ruleset_fd;
+@@ -1558,7 +1558,7 @@ TEST_F_FORK(layout1, execute)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_EXECUTE,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1591,7 +1591,7 @@ TEST_F_FORK(layout1, link)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_MAKE_REG,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1628,7 +1628,7 @@ TEST_F_FORK(layout1, rename_file)
+                       .path = dir_s2d2,
+                       .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1705,7 +1705,7 @@ TEST_F_FORK(layout1, rename_dir)
+                       .path = dir_s2d1,
+                       .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1759,7 +1759,7 @@ TEST_F_FORK(layout1, remove_dir)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_REMOVE_DIR,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1796,7 +1796,7 @@ TEST_F_FORK(layout1, remove_file)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_REMOVE_FILE,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1821,7 +1821,7 @@ static void test_make_file(struct __test
+                       .path = dir_s1d2,
+                       .access = access,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, access, rules);
+@@ -1907,7 +1907,7 @@ TEST_F_FORK(layout1, make_sym)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_MAKE_SYM,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1952,7 +1952,7 @@ TEST_F_FORK(layout1, make_dir)
+                       .path = dir_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_MAKE_DIR,
+               },
+-              {}
++              {},
+       };
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+                       rules);
+@@ -1992,7 +1992,7 @@ TEST_F_FORK(layout1, proc_unlinked_file)
+                       .path = file1_s1d2,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       int reg_fd, proc_fd;
+       const int ruleset_fd = create_ruleset(_metadata,
+@@ -2034,7 +2034,7 @@ TEST_F_FORK(layout1, proc_pipe)
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       /* Limits read and write access to files tied to the filesystem. */
+       const int ruleset_fd = create_ruleset(_metadata, rules[0].access,
+@@ -2171,7 +2171,7 @@ TEST_F_FORK(layout1_bind, same_content_s
+                       .path = dir_s2d1,
+                       .access = ACCESS_RW,
+               },
+-              {}
++              {},
+       };
+       /*
+        * Sets access rights on the same bind-mounted directories.  The result
+@@ -2187,7 +2187,7 @@ TEST_F_FORK(layout1_bind, same_content_s
+                       .path = dir_s2d2,
+                       .access = ACCESS_RW,
+               },
+-              {}
++              {},
+       };
+       /* Only allow read-access to the s1d3 hierarchies. */
+       const struct rule layer3_source[] = {
+@@ -2195,7 +2195,7 @@ TEST_F_FORK(layout1_bind, same_content_s
+                       .path = dir_s1d3,
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE,
+               },
+-              {}
++              {},
+       };
+       /* Removes all access rights. */
+       const struct rule layer4_destination[] = {
+@@ -2203,7 +2203,7 @@ TEST_F_FORK(layout1_bind, same_content_s
+                       .path = bind_file1_s1d3,
+                       .access = LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+@@ -2305,18 +2305,18 @@ static const char lower_do1_fl3[] = LOWE
+ static const char (*lower_base_files[])[] = {
+       &lower_fl1,
+       &lower_fo1,
+-      NULL
++      NULL,
+ };
+ static const char (*lower_base_directories[])[] = {
+       &lower_dl1,
+       &lower_do1,
+-      NULL
++      NULL,
+ };
+ static const char (*lower_sub_files[])[] = {
+       &lower_dl1_fl2,
+       &lower_do1_fo2,
+       &lower_do1_fl3,
+-      NULL
++      NULL,
+ };
+ #define UPPER_BASE    TMP_DIR "/upper"
+@@ -2333,18 +2333,18 @@ static const char upper_do1_fu3[] = UPPE
+ static const char (*upper_base_files[])[] = {
+       &upper_fu1,
+       &upper_fo1,
+-      NULL
++      NULL,
+ };
+ static const char (*upper_base_directories[])[] = {
+       &upper_du1,
+       &upper_do1,
+-      NULL
++      NULL,
+ };
+ static const char (*upper_sub_files[])[] = {
+       &upper_du1_fu2,
+       &upper_do1_fo2,
+       &upper_do1_fu3,
+-      NULL
++      NULL,
+ };
+ #define MERGE_BASE    TMP_DIR "/merge"
+@@ -2365,13 +2365,13 @@ static const char (*merge_base_files[])[
+       &merge_fl1,
+       &merge_fu1,
+       &merge_fo1,
+-      NULL
++      NULL,
+ };
+ static const char (*merge_base_directories[])[] = {
+       &merge_dl1,
+       &merge_du1,
+       &merge_do1,
+-      NULL
++      NULL,
+ };
+ static const char (*merge_sub_files[])[] = {
+       &merge_dl1_fl2,
+@@ -2379,7 +2379,7 @@ static const char (*merge_sub_files[])[]
+       &merge_do1_fo2,
+       &merge_do1_fl3,
+       &merge_do1_fu3,
+-      NULL
++      NULL,
+ };
+ /*
+@@ -2544,7 +2544,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+                       .path = MERGE_BASE,
+                       .access = ACCESS_RW,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer2_data[] = {
+               {
+@@ -2559,7 +2559,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+                       .path = MERGE_DATA,
+                       .access = ACCESS_RW,
+               },
+-              {}
++              {},
+       };
+       /* Sets access right on directories inside both layers. */
+       const struct rule layer3_subdirs[] = {
+@@ -2591,7 +2591,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+                       .path = merge_do1,
+                       .access = ACCESS_RW,
+               },
+-              {}
++              {},
+       };
+       /* Tighten access rights to the files. */
+       const struct rule layer4_files[] = {
+@@ -2644,7 +2644,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       const struct rule layer5_merge_only[] = {
+               {
+@@ -2652,7 +2652,7 @@ TEST_F_FORK(layout2_overlay, same_conten
+                       .access = LANDLOCK_ACCESS_FS_READ_FILE |
+                               LANDLOCK_ACCESS_FS_WRITE_FILE,
+               },
+-              {}
++              {},
+       };
+       int ruleset_fd;
+       size_t i;
diff --git a/queue-5.18/selftests-landlock-test-landlock_create_ruleset-2-argument-check-ordering.patch b/queue-5.18/selftests-landlock-test-landlock_create_ruleset-2-argument-check-ordering.patch
new file mode 100644 (file)
index 0000000..30a97fe
--- /dev/null
@@ -0,0 +1,73 @@
+From 6533d0c3a86ee1cc74ff37ac92ca597deb87015c Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Micka=C3=ABl=20Sala=C3=BCn?= <mic@digikod.net>
+Date: Fri, 6 May 2022 18:08:20 +0200
+Subject: selftests/landlock: Test landlock_create_ruleset(2) argument check ordering
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+From: Mickaël Salaün <mic@digikod.net>
+
+commit 6533d0c3a86ee1cc74ff37ac92ca597deb87015c upstream.
+
+Add inval_create_ruleset_arguments, extension of
+inval_create_ruleset_flags, to also check error ordering for
+landlock_create_ruleset(2).
+
+This is similar to the previous commit checking landlock_add_rule(2).
+
+Test coverage for security/landlock is 94.4% of 504 lines accorging to
+gcc/gcov-11.
+
+Link: https://lore.kernel.org/r/20220506160820.524344-11-mic@digikod.net
+Cc: stable@vger.kernel.org
+Signed-off-by: Mickaël Salaün <mic@digikod.net>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ tools/testing/selftests/landlock/base_test.c |   21 ++++++++++++++++++++-
+ 1 file changed, 20 insertions(+), 1 deletion(-)
+
+--- a/tools/testing/selftests/landlock/base_test.c
++++ b/tools/testing/selftests/landlock/base_test.c
+@@ -97,14 +97,17 @@ TEST(abi_version)
+       ASSERT_EQ(EINVAL, errno);
+ }
+-TEST(inval_create_ruleset_flags)
++/* Tests ordering of syscall argument checks. */
++TEST(create_ruleset_checks_ordering)
+ {
+       const int last_flag = LANDLOCK_CREATE_RULESET_VERSION;
+       const int invalid_flag = last_flag << 1;
++      int ruleset_fd;
+       const struct landlock_ruleset_attr ruleset_attr = {
+               .handled_access_fs = LANDLOCK_ACCESS_FS_READ_FILE,
+       };
++      /* Checks priority for invalid flags. */
+       ASSERT_EQ(-1, landlock_create_ruleset(NULL, 0, invalid_flag));
+       ASSERT_EQ(EINVAL, errno);
+@@ -119,6 +122,22 @@ TEST(inval_create_ruleset_flags)
+                 landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr),
+                                         invalid_flag));
+       ASSERT_EQ(EINVAL, errno);
++
++      /* Checks too big ruleset_attr size. */
++      ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, -1, 0));
++      ASSERT_EQ(E2BIG, errno);
++
++      /* Checks too small ruleset_attr size. */
++      ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 0, 0));
++      ASSERT_EQ(EINVAL, errno);
++      ASSERT_EQ(-1, landlock_create_ruleset(&ruleset_attr, 1, 0));
++      ASSERT_EQ(EINVAL, errno);
++
++      /* Checks valid call. */
++      ruleset_fd =
++              landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
++      ASSERT_LE(0, ruleset_fd);
++      ASSERT_EQ(0, close(ruleset_fd));
+ }
+ /* Tests ordering of syscall argument checks. */
index 92e4dfd21eb88c793549b0e50ebc1987339fef88..598572966466e44b3ffd9d7f3b4a3459be8a548d 100644 (file)
@@ -768,3 +768,24 @@ dlm-fix-missing-lkb-refcount-handling.patch
 ocfs2-dlmfs-fix-error-handling-of-user_dlm_destroy_lock.patch
 scsi-dc395x-fix-a-missing-check-on-list-iterator.patch
 scsi-ufs-qcom-add-a-readl-to-make-sure-ref_clk-gets-enabled.patch
+landlock-add-clang-format-exceptions.patch
+landlock-format-with-clang-format.patch
+selftests-landlock-add-clang-format-exceptions.patch
+selftests-landlock-normalize-array-assignment.patch
+selftests-landlock-format-with-clang-format.patch
+samples-landlock-add-clang-format-exceptions.patch
+samples-landlock-format-with-clang-format.patch
+landlock-fix-landlock_add_rule-2-documentation.patch
+selftests-landlock-make-tests-build-with-old-libc.patch
+selftests-landlock-extend-tests-for-minimal-valid-attribute-size.patch
+selftests-landlock-add-tests-for-unknown-access-rights.patch
+selftests-landlock-extend-access-right-tests-to-directories.patch
+selftests-landlock-fully-test-file-rename-with-remove-access.patch
+selftests-landlock-add-tests-for-o_path.patch
+landlock-change-landlock_add_rule-2-argument-check-ordering.patch
+landlock-change-landlock_restrict_self-2-check-ordering.patch
+selftests-landlock-test-landlock_create_ruleset-2-argument-check-ordering.patch
+landlock-define-access_mask_t-to-enforce-a-consistent-access-mask-size.patch
+landlock-reduce-the-maximum-number-of-layers-to-16.patch
+landlock-create-find_rule-from-unmask_layers.patch
+landlock-fix-same-layer-rule-unions.patch