Skip to content

Commit 155b8a0

Browse files
amir73ilMiklos Szeredi
authored andcommitted
ovl: fix decode of dir file handle with multi lower layers
When decoding a lower file handle, we first call ovl_check_origin_fh() with connected=false to get any real lower dentry for overlay inode cache lookup. If the real dentry is a disconnected dir dentry, ovl_check_origin_fh() is called again with connected=true to get a connected real dentry and find the lower layer the real dentry belongs to. If the first call returned a connected real dentry, we use it to lookup an overlay connected dentry, but the first ovl_check_origin_fh() call with connected=false did not check that the found dentry is under the root of the layer (see ovl_acceptable()), it only checked that the found dentry super block matches the uuid of the lower file handle. In case there are multiple lower layers on the same fs and the found dentry is not from the top most lower layer, using the layer index returned from the first ovl_check_origin_fh() is wrong and we end up failing to decode the file handle. Fix this by always calling ovl_check_origin_fh() with connected=true if we got a directory dentry in the first call. Fixes: 8b58924 ("ovl: lookup in inode cache first when decoding...") Cc: <stable@vger.kernel.org> # v4.17 Signed-off-by: Amir Goldstein <amir73il@gmail.com> Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
1 parent 91ff20f commit 155b8a0

File tree

1 file changed

+3
-3
lines changed

1 file changed

+3
-3
lines changed

fs/overlayfs/export.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -754,9 +754,8 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
754754
goto out;
755755
}
756756

757-
/* Otherwise, get a connected non-upper dir or disconnected non-dir */
758-
if (d_is_dir(origin.dentry) &&
759-
(origin.dentry->d_flags & DCACHE_DISCONNECTED)) {
757+
/* Find origin.dentry again with ovl_acceptable() layer check */
758+
if (d_is_dir(origin.dentry)) {
760759
dput(origin.dentry);
761760
origin.dentry = NULL;
762761
err = ovl_check_origin_fh(ofs, fh, true, NULL, &stack);
@@ -769,6 +768,7 @@ static struct dentry *ovl_lower_fh_to_d(struct super_block *sb,
769768
goto out_err;
770769
}
771770

771+
/* Get a connected non-upper dir or disconnected non-dir */
772772
dentry = ovl_get_dentry(sb, NULL, &origin, index);
773773

774774
out:

0 commit comments

Comments
 (0)