[Devel] [PATCH RH7] ms/ovl: fix d_real() for stacked fs

Pavel Tikhomirov ptikhomirov at virtuozzo.com
Mon Feb 13 05:22:58 PST 2017


Maxim, please review.

On 02/09/2017 07:13 PM, Pavel Tikhomirov wrote:
> From: Miklos Szeredi <mszeredi at redhat.com>
>
> 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< - - - -
>
> found while investigating https://jira.sw.ru/browse/PSBM-58480
>
> 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+
> Signed-off-by: Pavel Tikhomirov <ptikhomirov at virtuozzo.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 edd46a0..0e10085 100644
> --- a/fs/overlayfs/super.c
> +++ b/fs/overlayfs/super.c
> @@ -328,11 +328,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);
>

-- 
Best regards, Tikhomirov Pavel
Software Developer, Virtuozzo.


More information about the Devel mailing list