aboutsummaryrefslogtreecommitdiffstats
path: root/fs/overlayfs
diff options
context:
space:
mode:
authorhujianyang <hujianyang@huawei.com>2015-01-06 03:10:01 -0500
committerMiklos Szeredi <mszeredi@suse.cz>2015-01-08 08:47:20 -0500
commita425c037f3dd8a56469158ab5f37beb46402d958 (patch)
treeb412f83087392ee4b96c6be8437c782ad53a775b /fs/overlayfs
parent2f83fd8c2849a388082f30d755a75c1e67c4643b (diff)
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>
Diffstat (limited to 'fs/overlayfs')
-rw-r--r--fs/overlayfs/super.c23
1 files changed, 13 insertions, 10 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c
index 6ca8ea8cb9b2..9e94f4acef1a 100644
--- a/fs/overlayfs/super.c
+++ b/fs/overlayfs/super.c
@@ -372,7 +372,6 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
372 bool opaque = false; 372 bool opaque = false;
373 struct path lowerpath = poe->lowerstack[i]; 373 struct path lowerpath = poe->lowerstack[i];
374 374
375 opaque = false;
376 this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name); 375 this = ovl_lookup_real(lowerpath.dentry, &dentry->d_name);
377 err = PTR_ERR(this); 376 err = PTR_ERR(this);
378 if (IS_ERR(this)) { 377 if (IS_ERR(this)) {
@@ -395,20 +394,24 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry,
395 */ 394 */
396 if (i < poe->numlower - 1 && ovl_is_opaquedir(this)) 395 if (i < poe->numlower - 1 && ovl_is_opaquedir(this))
397 opaque = true; 396 opaque = true;
398 /* 397
399 * If this is a non-directory then stop here. 398 if (prev && (!S_ISDIR(prev->d_inode->i_mode) ||
400 * 399 !S_ISDIR(this->d_inode->i_mode))) {
401 * FIXME: check for opaqueness maybe better done in remove code. 400 /*
402 */ 401 * FIXME: check for upper-opaqueness maybe better done
403 if (!S_ISDIR(this->d_inode->i_mode)) { 402 * in remove code.
404 opaque = true; 403 */
405 } else if (prev && (!S_ISDIR(prev->d_inode->i_mode) ||
406 !S_ISDIR(this->d_inode->i_mode))) {
407 if (prev == upperdentry) 404 if (prev == upperdentry)
408 upperopaque = true; 405 upperopaque = true;
409 dput(this); 406 dput(this);
410 break; 407 break;
411 } 408 }
409 /*
410 * If this is a non-directory then stop here.
411 */
412 if (!S_ISDIR(this->d_inode->i_mode))
413 opaque = true;
414
412 stack[ctr].dentry = this; 415 stack[ctr].dentry = this;
413 stack[ctr].mnt = lowerpath.mnt; 416 stack[ctr].mnt = lowerpath.mnt;
414 ctr++; 417 ctr++;