Skip to content
This repository was archived by the owner on Nov 8, 2023. It is now read-only.

Commit d9aab0b

Browse files
committed
Merge tag 'landlock-6.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux
Pull landlock fix from Mickaël Salaün: "This fixes a wrong path walk triggered by syzkaller" * tag 'landlock-6.10-rc2' of git://git.kernel.org/pub/scm/linux/kernel/git/mic/linux: selftests/landlock: Add layout1.refer_mount_root landlock: Fix d_parent walk
2 parents cc8ed4d + 0055f53 commit d9aab0b

File tree

2 files changed

+56
-2
lines changed

2 files changed

+56
-2
lines changed

security/landlock/fs.c

Lines changed: 11 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,7 @@ static int current_check_refer_path(struct dentry *const old_dentry,
11101110
bool allow_parent1, allow_parent2;
11111111
access_mask_t access_request_parent1, access_request_parent2;
11121112
struct path mnt_dir;
1113+
struct dentry *old_parent;
11131114
layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS] = {},
11141115
layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS] = {};
11151116

@@ -1157,9 +1158,17 @@ static int current_check_refer_path(struct dentry *const old_dentry,
11571158
mnt_dir.mnt = new_dir->mnt;
11581159
mnt_dir.dentry = new_dir->mnt->mnt_root;
11591160

1161+
/*
1162+
* old_dentry may be the root of the common mount point and
1163+
* !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and
1164+
* OPEN_TREE_CLONE). We do not need to call dget(old_parent) because
1165+
* we keep a reference to old_dentry.
1166+
*/
1167+
old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry :
1168+
old_dentry->d_parent;
1169+
11601170
/* new_dir->dentry is equal to new_dentry->d_parent */
1161-
allow_parent1 = collect_domain_accesses(dom, mnt_dir.dentry,
1162-
old_dentry->d_parent,
1171+
allow_parent1 = collect_domain_accesses(dom, mnt_dir.dentry, old_parent,
11631172
&layer_masks_parent1);
11641173
allow_parent2 = collect_domain_accesses(
11651174
dom, mnt_dir.dentry, new_dir->dentry, &layer_masks_parent2);

tools/testing/selftests/landlock/fs_test.c

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -35,6 +35,7 @@
3535
* See https://sourceware.org/glibc/wiki/Synchronizing_Headers.
3636
*/
3737
#include <linux/fs.h>
38+
#include <linux/mount.h>
3839

3940
#include "common.h"
4041

@@ -47,6 +48,13 @@ int renameat2(int olddirfd, const char *oldpath, int newdirfd,
4748
}
4849
#endif
4950

51+
#ifndef open_tree
52+
int open_tree(int dfd, const char *filename, unsigned int flags)
53+
{
54+
return syscall(__NR_open_tree, dfd, filename, flags);
55+
}
56+
#endif
57+
5058
#ifndef RENAME_EXCHANGE
5159
#define RENAME_EXCHANGE (1 << 1)
5260
#endif
@@ -2400,6 +2408,43 @@ TEST_F_FORK(layout1, refer_denied_by_default4)
24002408
layer_dir_s1d1_refer);
24012409
}
24022410

2411+
/*
2412+
* Tests walking through a denied root mount.
2413+
*/
2414+
TEST_F_FORK(layout1, refer_mount_root_deny)
2415+
{
2416+
const struct landlock_ruleset_attr ruleset_attr = {
2417+
.handled_access_fs = LANDLOCK_ACCESS_FS_MAKE_DIR,
2418+
};
2419+
int root_fd, ruleset_fd;
2420+
2421+
/* Creates a mount object from a non-mount point. */
2422+
set_cap(_metadata, CAP_SYS_ADMIN);
2423+
root_fd =
2424+
open_tree(AT_FDCWD, dir_s1d1,
2425+
AT_EMPTY_PATH | OPEN_TREE_CLONE | OPEN_TREE_CLOEXEC);
2426+
clear_cap(_metadata, CAP_SYS_ADMIN);
2427+
ASSERT_LE(0, root_fd);
2428+
2429+
ruleset_fd =
2430+
landlock_create_ruleset(&ruleset_attr, sizeof(ruleset_attr), 0);
2431+
ASSERT_LE(0, ruleset_fd);
2432+
2433+
ASSERT_EQ(0, prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0));
2434+
ASSERT_EQ(0, landlock_restrict_self(ruleset_fd, 0));
2435+
EXPECT_EQ(0, close(ruleset_fd));
2436+
2437+
/* Link denied by Landlock: EACCES. */
2438+
EXPECT_EQ(-1, linkat(root_fd, ".", root_fd, "does_not_exist", 0));
2439+
EXPECT_EQ(EACCES, errno);
2440+
2441+
/* renameat2() always returns EBUSY. */
2442+
EXPECT_EQ(-1, renameat2(root_fd, ".", root_fd, "does_not_exist", 0));
2443+
EXPECT_EQ(EBUSY, errno);
2444+
2445+
EXPECT_EQ(0, close(root_fd));
2446+
}
2447+
24032448
TEST_F_FORK(layout1, reparent_link)
24042449
{
24052450
const struct rule layer1[] = {

0 commit comments

Comments
 (0)