diff options
Diffstat (limited to 'fs/overlayfs/namei.c')
| -rw-r--r-- | fs/overlayfs/namei.c | 18 |
1 files changed, 10 insertions, 8 deletions
diff --git a/fs/overlayfs/namei.c b/fs/overlayfs/namei.c index f010e7456668..d489e80feb6f 100644 --- a/fs/overlayfs/namei.c +++ b/fs/overlayfs/namei.c @@ -1066,6 +1066,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, unsigned int ctr = 0; struct inode *inode = NULL; bool upperopaque = false; + bool check_redirect = (ovl_redirect_follow(ofs) || ofs->numdatalayer); struct dentry *this; unsigned int i; int err; @@ -1078,7 +1079,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, .is_dir = false, .opaque = false, .stop = false, - .last = ovl_redirect_follow(ofs) ? false : !ovl_numlower(poe), + .last = check_redirect ? false : !ovl_numlower(poe), .redirect = NULL, .upperredirect = NULL, .metacopy = 0, @@ -1146,7 +1147,7 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, goto out_put; } - if (!ovl_redirect_follow(ofs)) + if (!check_redirect) d.last = i == ovl_numlower(poe) - 1; else if (d.is_dir || !ofs->numdatalayer) d.last = lower.layer->idx == ovl_numlower(roe); @@ -1221,15 +1222,16 @@ struct dentry *ovl_lookup(struct inode *dir, struct dentry *dentry, } } - if (!ovl_check_follow_redirect(&d)) { - err = -EPERM; - goto out_put; - } - - /* Defer lookup of lowerdata in data-only layers to first access */ + /* + * Defer lookup of lowerdata in data-only layers to first access. + * Don't require redirect=follow and metacopy=on in this case. + */ if (d.metacopy && ctr && ofs->numdatalayer && d.absolute_redirect) { d.metacopy = 0; ctr++; + } else if (!ovl_check_follow_redirect(&d)) { + err = -EPERM; + goto out_put; } /* |
