Skip to content

Commit 75c542d

Browse files
committed
landlock: Reduce the maximum number of layers to 16
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>
1 parent 5f2ff33 commit 75c542d

5 files changed

Lines changed: 15 additions & 14 deletions

File tree

Documentation/userspace-api/landlock.rst

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -267,8 +267,8 @@ restrict such paths with dedicated ruleset flags.
267267
Ruleset layers
268268
--------------
269269

270-
There is a limit of 64 layers of stacked rulesets. This can be an issue for a
271-
task willing to enforce a new ruleset in complement to its 64 inherited
270+
There is a limit of 16 layers of stacked rulesets. This can be an issue for a
271+
task willing to enforce a new ruleset in complement to its 16 inherited
272272
rulesets. Once this limit is reached, sys_landlock_restrict_self() returns
273273
E2BIG. It is then strongly suggested to carefully build rulesets once in the
274274
life of a thread, especially for applications able to launch other applications

security/landlock/fs.c

Lines changed: 7 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -183,10 +183,10 @@ int landlock_append_fs_rule(struct landlock_ruleset *const ruleset,
183183

184184
/* Access-control management */
185185

186-
static inline u64 unmask_layers(const struct landlock_ruleset *const domain,
187-
const struct path *const path,
188-
const access_mask_t access_request,
189-
u64 layer_mask)
186+
static inline layer_mask_t
187+
unmask_layers(const struct landlock_ruleset *const domain,
188+
const struct path *const path, const access_mask_t access_request,
189+
layer_mask_t layer_mask)
190190
{
191191
const struct landlock_rule *rule;
192192
const struct inode *inode;
@@ -212,11 +212,11 @@ static inline u64 unmask_layers(const struct landlock_ruleset *const domain,
212212
*/
213213
for (i = 0; i < rule->num_layers; i++) {
214214
const struct landlock_layer *const layer = &rule->layers[i];
215-
const u64 layer_level = BIT_ULL(layer->level - 1);
215+
const layer_mask_t layer_bit = BIT_ULL(layer->level - 1);
216216

217217
/* Checks that the layer grants access to the full request. */
218218
if ((layer->access & access_request) == access_request) {
219-
layer_mask &= ~layer_level;
219+
layer_mask &= ~layer_bit;
220220

221221
if (layer_mask == 0)
222222
return layer_mask;
@@ -231,12 +231,9 @@ static int check_access_path(const struct landlock_ruleset *const domain,
231231
{
232232
bool allowed = false;
233233
struct path walker_path;
234-
u64 layer_mask;
234+
layer_mask_t layer_mask;
235235
size_t i;
236236

237-
/* Make sure all layers can be checked. */
238-
BUILD_BUG_ON(BITS_PER_TYPE(layer_mask) < LANDLOCK_MAX_NUM_LAYERS);
239-
240237
if (!access_request)
241238
return 0;
242239
if (WARN_ON_ONCE(!domain || !path))

security/landlock/limits.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515

1616
/* clang-format off */
1717

18-
#define LANDLOCK_MAX_NUM_LAYERS 64
18+
#define LANDLOCK_MAX_NUM_LAYERS 16
1919
#define LANDLOCK_MAX_NUM_RULES U32_MAX
2020

2121
#define LANDLOCK_LAST_ACCESS_FS LANDLOCK_ACCESS_FS_MAKE_SYM

security/landlock/ruleset.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,10 @@ typedef u16 access_mask_t;
2323
/* Makes sure all filesystem access rights can be stored. */
2424
static_assert(BITS_PER_TYPE(access_mask_t) >= LANDLOCK_NUM_ACCESS_FS);
2525

26+
typedef u16 layer_mask_t;
27+
/* Makes sure all layers can be checked. */
28+
static_assert(BITS_PER_TYPE(layer_mask_t) >= LANDLOCK_MAX_NUM_LAYERS);
29+
2630
/**
2731
* struct landlock_layer - Access rights for a given layer
2832
*/

tools/testing/selftests/landlock/fs_test.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1159,7 +1159,7 @@ TEST_F_FORK(layout1, max_layers)
11591159
const int ruleset_fd = create_ruleset(_metadata, ACCESS_RW, rules);
11601160

11611161
ASSERT_LE(0, ruleset_fd);
1162-
for (i = 0; i < 64; i++)
1162+
for (i = 0; i < 16; i++)
11631163
enforce_ruleset(_metadata, ruleset_fd);
11641164

11651165
for (i = 0; i < 2; i++) {

0 commit comments

Comments
 (0)