[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