[Devel] [PATCH RHEL7 COMMIT] ms/ovl: fix d_real() for stacked fs
Konstantin Khorenko
khorenko at virtuozzo.com
Mon Feb 20 05:30:09 PST 2017
The commit is pushed to "branch-rh7-3.10.0-514.6.1.vz7.28.x-ovz" and will appear at https://src.openvz.org/scm/ovz/vzkernel.git
after rh7-3.10.0-514.6.1.vz7.28.6
------>
commit ac92f4fd30a80bafb27cac001dba58b2e1f8c812
Author: Miklos Szeredi <mszeredi at redhat.com>
Date: Mon Feb 20 17:30:09 2017 +0400
ms/ovl: fix d_real() for stacked fs
Handling of recursion in d_real() is completely broken. Recursion is only
done in the 'inode != NULL' case. But when opening the file we have
'inode == NULL' hence d_real() will return an overlay dentry. This won't
work since overlayfs doesn't define its own file operations, so all file
ops will fail.
Fix by doing the recursion first and the check against the inode second.
Bash script to reproduce the issue written by Quentin:
- 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - -
tmpdir=$(mktemp -d)
pushd ${tmpdir}
mkdir -p {upper,lower,work}
echo -n 'rocks' > lower/ksplice
mount -t overlay level_zero upper -o lowerdir=lower,upperdir=upper,workdir=work
cat upper/ksplice
tmpdir2=$(mktemp -d)
pushd ${tmpdir2}
mkdir -p {upper,work}
mount -t overlay level_one upper -o lowerdir=${tmpdir}/upper,upperdir=upper,workdir=work
ls -l upper/ksplice
cat upper/ksplice
- 8< - - - - - 8< - - - - - 8< - - - - - 8< - - - -
Reported-by: Quentin Casasnovas <quentin.casasnovas at oracle.com>
Signed-off-by: Miklos Szeredi <mszeredi at redhat.com>
Fixes: 2d902671ce1c ("vfs: merge .d_select_inode() into .d_real()")
Cc: <stable at vger.kernel.org> # v4.8+
Found while investigating https://jira.sw.ru/browse/PSBM-58480
Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.com>
---
fs/overlayfs/super.c | 7 +++----
1 file changed, 3 insertions(+), 4 deletions(-)
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 21db028..ed7b2f3 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -330,12 +330,11 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
if (!real)
goto bug;
- if (!inode || inode == d_inode(real))
- return real;
-
/* Handle recursion */
- return d_real(real, inode, open_flags);
+ real = d_real(real, inode, open_flags);
+ if (!inode || inode == d_inode(real))
+ return real;
bug:
WARN(1, "ovl_d_real(%pd4, %s:%lu\n): real dentry not found\n", dentry,
inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
More information about the Devel
mailing list