[Devel,RHEL7,COMMIT] ms/ovl: fix d_real() for stacked fs

Submitted by Konstantin Khorenko on Feb. 20, 2017, 1:30 p.m.

Details

Message ID 201702201330.v1KDU9jr009317@finist_cl7.x64_64.work.ct
State New
Series "ms/ovl: fix d_real() for stacked fs"
Headers show

Commit Message

Konstantin Khorenko Feb. 20, 2017, 1:30 p.m.
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@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@oracle.com>
    Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
    Fixes: 2d902671ce1c ("vfs: merge .d_select_inode() into .d_real()")
    Cc: <stable@vger.kernel.org> # v4.8+
    
    Found while investigating https://jira.sw.ru/browse/PSBM-58480
    
    Signed-off-by: Pavel Tikhomirov <ptikhomirov@virtuozzo.com>
---
 fs/overlayfs/super.c | 7 +++----
 1 file changed, 3 insertions(+), 4 deletions(-)

Patch hide | download patch | download mbox

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);