ovl: fix false positive ESTALE on lookup

Commit b9ac5c274b ("ovl: hash overlay non-dir inodes by copy up origin")
verifies that the origin lower inode stored in the overlayfs inode matched
the inode of a copy up origin dentry found by lookup.

There is a false positive result in that check when lower fs does not
support file handles and copy up origin cannot be followed by file handle
at lookup time.

The false negative happens when finding an overlay inode in cache on a
copied up overlay dentry lookup. The overlay inode still 'remembers' the
copy up origin inode, but the copy up origin dentry is not available for
verification.

Relax the check in case copy up origin dentry is not available.

Fixes: b9ac5c274b ("ovl: hash overlay non-dir inodes by copy up...")
Cc: <stable@vger.kernel.org> # v4.13
Reported-by: Jordi Pujol <jordipujolp@gmail.com>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
This commit is contained in:
Amir Goldstein 2017-09-11 16:30:15 +03:00 committed by Miklos Szeredi
parent 7c6893e3c9
commit 939ae4efd5

View File

@ -579,10 +579,13 @@ static int ovl_inode_set(struct inode *inode, void *data)
static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry, static bool ovl_verify_inode(struct inode *inode, struct dentry *lowerdentry,
struct dentry *upperdentry) struct dentry *upperdentry)
{ {
struct inode *lowerinode = lowerdentry ? d_inode(lowerdentry) : NULL; /*
* Allow non-NULL lower inode in ovl_inode even if lowerdentry is NULL.
/* Lower (origin) inode must match, even if NULL */ * This happens when finding a copied up overlay inode for a renamed
if (ovl_inode_lower(inode) != lowerinode) * or hardlinked overlay dentry and lower dentry cannot be followed
* by origin because lower fs does not support file handles.
*/
if (lowerdentry && ovl_inode_lower(inode) != d_inode(lowerdentry))
return false; return false;
/* /*