ovl: Fix opaque regression in ovl_lookup
Current multi-layer support overlayfs has a regression in .lookup(). If there is a directory in upperdir and a regular file has same name in lowerdir in a merged directory, lower file is hidden and upper directory is set to opaque in former case. But it is changed in present code. In lowerdir lookup path, if a found inode is not directory, the type checking of previous inode is missing. This inode will be copied to the lowerstack of ovl_entry directly. That will lead to several wrong conditions, for example, the reading of the directory in upperdir may return an error like: ls: reading directory .: Not a directory This patch makes the lowerdir lookup path check the opaque for non-directory file too. Signed-off-by: hujianyang <hujianyang@huawei.com> Signed-off-by: Miklos Szeredi <mszeredi@suse.cz>
This commit is contained in:
committed by
Miklos Szeredi
parent
2f83fd8c28
commit
a425c037f3
+13
-10
@@ -372,7 +372,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
bool opaque = false;
|
bool opaque = false;
|
||||||
struct path lowerpath = poe->lowerstack[i];
|
struct path lowerpath = poe->lowerstack[i];
|
||||||
|
|
||||||
opaque = false;
|
|
||||||
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
|
this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
|
||||||
err = PTR_ERR(this);
|
err = PTR_ERR(this);
|
||||||
if (IS_ERR(this)) {
|
if (IS_ERR(this)) {
|
||||||
@@ -395,20 +394,24 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
|
|||||||
*/
|
*/
|
||||||
if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
|
if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
|
||||||
opaque = true;
|
opaque = true;
|
||||||
/*
|
|
||||||
* If this is a non-directory then stop here.
|
if (prev && (!S_ISDIR(prev->d_inode->i_mode) ||
|
||||||
*
|
!S_ISDIR(this->d_inode->i_mode))) {
|
||||||
* FIXME: check for opaqueness maybe better done in remove code.
|
/*
|
||||||
*/
|
* FIXME: check for upper-opaqueness maybe better done
|
||||||
if (!S_ISDIR(this->d_inode->i_mode)) {
|
* in remove code.
|
||||||
opaque = true;
|
*/
|
||||||
} else if (prev && (!S_ISDIR(prev->d_inode->i_mode) ||
|
|
||||||
!S_ISDIR(this->d_inode->i_mode))) {
|
|
||||||
if (prev == upperdentry)
|
if (prev == upperdentry)
|
||||||
upperopaque = true;
|
upperopaque = true;
|
||||||
dput(this);
|
dput(this);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
/*
|
||||||
|
* If this is a non-directory then stop here.
|
||||||
|
*/
|
||||||
|
if (!S_ISDIR(this->d_inode->i_mode))
|
||||||
|
opaque = true;
|
||||||
|
|
||||||
stack[ctr].dentry = this;
|
stack[ctr].dentry = this;
|
||||||
stack[ctr].mnt = lowerpath.mnt;
|
stack[ctr].mnt = lowerpath.mnt;
|
||||||
ctr++;
|
ctr++;
|
||||||
|
|||||||
Reference in New Issue
Block a user