ovl: allow upperdir inside lowerdir
commit708fa01597upstream. Commit146d62e5a5("ovl: detect overlapping layers") made sure we don't have overlapping layers, but it also broke the arguably valid use case of mount -olowerdir=/,upperdir=/subdir,.. where upperdir overlaps lowerdir on the same filesystem. This has been causing regressions. Revert the check, but only for the specific case where upperdir and/or workdir are subdirectories of lowerdir. Any other overlap (e.g. lowerdir is subdirectory of upperdir, etc) case is crazy, so leave the check in place for those. Overlaps are detected at lookup time too, so reverting the mount time check should be safe. Fixes:146d62e5a5("ovl: detect overlapping layers") Cc: <stable@vger.kernel.org> # v5.2 Signed-off-by: Miklos Szeredi <mszeredi@redhat.com> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
This commit is contained in:
parent
71d58457a8
commit
27c1936af5
1 changed files with 7 additions and 5 deletions
|
|
@ -1759,7 +1759,8 @@ out_err:
|
||||||
* - upper/work dir of any overlayfs instance
|
* - upper/work dir of any overlayfs instance
|
||||||
*/
|
*/
|
||||||
static int ovl_check_layer(struct super_block *sb, struct ovl_fs *ofs,
|
static int ovl_check_layer(struct super_block *sb, struct ovl_fs *ofs,
|
||||||
struct dentry *dentry, const char *name)
|
struct dentry *dentry, const char *name,
|
||||||
|
bool is_lower)
|
||||||
{
|
{
|
||||||
struct dentry *next = dentry, *parent;
|
struct dentry *next = dentry, *parent;
|
||||||
int err = 0;
|
int err = 0;
|
||||||
|
|
@ -1771,7 +1772,7 @@ static int ovl_check_layer(struct super_block *sb, struct ovl_fs *ofs,
|
||||||
|
|
||||||
/* Walk back ancestors to root (inclusive) looking for traps */
|
/* Walk back ancestors to root (inclusive) looking for traps */
|
||||||
while (!err && parent != next) {
|
while (!err && parent != next) {
|
||||||
if (ovl_lookup_trap_inode(sb, parent)) {
|
if (is_lower && ovl_lookup_trap_inode(sb, parent)) {
|
||||||
err = -ELOOP;
|
err = -ELOOP;
|
||||||
pr_err("overlapping %s path\n", name);
|
pr_err("overlapping %s path\n", name);
|
||||||
} else if (ovl_is_inuse(parent)) {
|
} else if (ovl_is_inuse(parent)) {
|
||||||
|
|
@ -1797,7 +1798,7 @@ static int ovl_check_overlapping_layers(struct super_block *sb,
|
||||||
|
|
||||||
if (ovl_upper_mnt(ofs)) {
|
if (ovl_upper_mnt(ofs)) {
|
||||||
err = ovl_check_layer(sb, ofs, ovl_upper_mnt(ofs)->mnt_root,
|
err = ovl_check_layer(sb, ofs, ovl_upper_mnt(ofs)->mnt_root,
|
||||||
"upperdir");
|
"upperdir", false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
|
|
||||||
|
|
@ -1808,7 +1809,8 @@ static int ovl_check_overlapping_layers(struct super_block *sb,
|
||||||
* workbasedir. In that case, we already have their traps in
|
* workbasedir. In that case, we already have their traps in
|
||||||
* inode cache and we will catch that case on lookup.
|
* inode cache and we will catch that case on lookup.
|
||||||
*/
|
*/
|
||||||
err = ovl_check_layer(sb, ofs, ofs->workbasedir, "workdir");
|
err = ovl_check_layer(sb, ofs, ofs->workbasedir, "workdir",
|
||||||
|
false);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
@ -1816,7 +1818,7 @@ static int ovl_check_overlapping_layers(struct super_block *sb,
|
||||||
for (i = 1; i < ofs->numlayer; i++) {
|
for (i = 1; i < ofs->numlayer; i++) {
|
||||||
err = ovl_check_layer(sb, ofs,
|
err = ovl_check_layer(sb, ofs,
|
||||||
ofs->layers[i].mnt->mnt_root,
|
ofs->layers[i].mnt->mnt_root,
|
||||||
"lowerdir");
|
"lowerdir", true);
|
||||||
if (err)
|
if (err)
|
||||||
return err;
|
return err;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue