landlock: Reduce the maximum number of layers to 16
authorMickaël Salaün <mic@digikod.net>
Fri, 6 May 2022 16:10:52 +0000 (18:10 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Thu, 9 Jun 2022 08:23:24 +0000 (10:23 +0200)
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
security/landlock/fs.c
security/landlock/limits.h
security/landlock/ruleset.h
tools/testing/selftests/landlock/fs_test.c

index f35552f..b68e7a5 100644 (file)
@@ -267,8 +267,8 @@ restrict such paths with dedicated ruleset flags.
 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
index d4006ad..f48c0a3 100644 (file)
@@ -183,10 +183,10 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
 
 /* 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 struct landlock_ruleset *const domain,
         */
        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 struct landlock_ruleset *const domain,
 {
        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))
index 41372f2..17c2a2e 100644 (file)
@@ -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
index 8d57175..521af28 100644 (file)
@@ -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
  */
index a8f54c4..e13f046 100644 (file)
@@ -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++) {