diff options
author | Miklos Szeredi <mszeredi@redhat.com> | 2019-06-18 16:06:16 +0300 |
---|---|---|
committer | Miklos Szeredi <mszeredi@redhat.com> | 2019-06-18 16:06:16 +0300 |
commit | 9179c21dc6ed1c993caa5fe4da876a6765c26af7 (patch) | |
tree | 56f958c3bc6ab1368f51e5c11f106a49efe33120 /fs/overlayfs | |
parent | 941d935ac7636911a3fd8fa80e758e52b0b11e20 (diff) | |
download | linux-9179c21dc6ed1c993caa5fe4da876a6765c26af7.tar.xz |
ovl: don't fail with disconnected lower NFS
NFS mounts can be disconnected from fs root. Don't fail the overlapping
layer check because of this.
The check is not authoritative anyway, since topology can change during or
after the check.
Reported-by: Antti Antinoja <antti@fennosys.fi>
Signed-off-by: Miklos Szeredi <mszeredi@redhat.com>
Fixes: 146d62e5a586 ("ovl: detect overlapping layers")
Diffstat (limited to 'fs/overlayfs')
-rw-r--r-- | fs/overlayfs/super.c | 26 |
1 files changed, 9 insertions, 17 deletions
diff --git a/fs/overlayfs/super.c b/fs/overlayfs/super.c index 746ea36f3171..9b18e0f9016a 100644 --- a/fs/overlayfs/super.c +++ b/fs/overlayfs/super.c @@ -1471,23 +1471,20 @@ out_err: * Check if this layer root is a descendant of: * - another layer of this overlayfs instance * - upper/work dir of any overlayfs instance - * - a disconnected dentry (detached root) */ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, const char *name) { - struct dentry *next, *parent; - bool is_root = false; + struct dentry *next = dentry, *parent; int err = 0; - if (!dentry || dentry == dentry->d_sb->s_root) + if (!dentry) return 0; - next = dget(dentry); - /* Walk back ancestors to fs root (inclusive) looking for traps */ - do { - parent = dget_parent(next); - is_root = (parent == next); + parent = dget_parent(next); + + /* Walk back ancestors to root (inclusive) looking for traps */ + while (!err && parent != next) { if (ovl_is_inuse(parent)) { err = -EBUSY; pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n", @@ -1496,17 +1493,12 @@ static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, err = -ELOOP; pr_err("overlayfs: overlapping %s path\n", name); } - dput(next); next = parent; - } while (!err && !is_root); - - /* Did we really walk to fs root or found a detached root? */ - if (!err && next != dentry->d_sb->s_root) { - err = -ESTALE; - pr_err("overlayfs: disconnected %s path\n", name); + parent = dget_parent(next); + dput(next); } - dput(next); + dput(parent); return err; } |