Skip to content

Commit

Permalink
landlock: Fix d_parent walk
Browse files Browse the repository at this point in the history
The WARN_ON_ONCE() in collect_domain_accesses() can be triggered when
trying to link a root mount point.  This cannot work in practice because
this directory is mounted, but the VFS check is done after the call to
security_path_link().

Do not use source directory's d_parent when the source directory is the
mount point.

Cc: Günther Noack <[email protected]>
Cc: Paul Moore <[email protected]>
Cc: [email protected]
Reported-by: [email protected]
Fixes: b91c3e4 ("landlock: Add support for file reparenting with LANDLOCK_ACCESS_FS_REFER")
Closes: https://lore.kernel.org/r/[email protected]
Link: https://lore.kernel.org/r/[email protected]
[mic: Fix commit message]
Signed-off-by: Mickaël Salaün <[email protected]>
  • Loading branch information
l0kod committed May 31, 2024
1 parent 1613e60 commit 88da52c
Showing 1 changed file with 11 additions and 2 deletions.
13 changes: 11 additions & 2 deletions security/landlock/fs.c
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,7 @@ static int current_check_refer_path(struct dentry *const old_dentry,
bool allow_parent1, allow_parent2;
access_mask_t access_request_parent1, access_request_parent2;
struct path mnt_dir;
struct dentry *old_parent;
layer_mask_t layer_masks_parent1[LANDLOCK_NUM_ACCESS_FS] = {},
layer_masks_parent2[LANDLOCK_NUM_ACCESS_FS] = {};

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

/*
* old_dentry may be the root of the common mount point and
* !IS_ROOT(old_dentry) at the same time (e.g. with open_tree() and
* OPEN_TREE_CLONE). We do not need to call dget(old_parent) because
* we keep a reference to old_dentry.
*/
old_parent = (old_dentry == mnt_dir.dentry) ? old_dentry :
old_dentry->d_parent;

/* new_dir->dentry is equal to new_dentry->d_parent */
allow_parent1 = collect_domain_accesses(dom, mnt_dir.dentry,
old_dentry->d_parent,
allow_parent1 = collect_domain_accesses(dom, mnt_dir.dentry, old_parent,
&layer_masks_parent1);
allow_parent2 = collect_domain_accesses(
dom, mnt_dir.dentry, new_dir->dentry, &layer_masks_parent2);
Expand Down

0 comments on commit 88da52c

Please sign in to comment.