[PATCH Yakkety SRU] ovl: fix d_real() for stacked fs

Tim Gardner tim.gardner at canonical.com
Tue Dec 6 19:56:04 UTC 2016


From: Miklos Szeredi <mszeredi at redhat.com>

BugLink: http://bugs.launchpad.net/bugs/1647007

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+
(cherry picked from commit c4fcfc1619ea43a8a89ad2f83ff23905eee088bd)
Signed-off-by: Tim Gardner <tim.gardner at canonical.com>
---
 fs/overlayfs/super.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 73281e8d..78bc852 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -329,11 +329,11 @@ static struct dentry *ovl_d_real(struct dentry *dentry,
 	if (!real)
 		goto bug;
 
+	/* Handle recursion */
+	real = d_real(real, inode, open_flags);
+
 	if (!inode || inode == d_inode(real))
 		return real;
-
-	/* Handle recursion */
-	return d_real(real, inode, open_flags);
 bug:
 	WARN(1, "ovl_d_real(%pd4, %s:%lu): real dentry not found\n", dentry,
 	     inode ? inode->i_sb->s_id : "NULL", inode ? inode->i_ino : 0);
-- 
2.7.4





More information about the kernel-team mailing list