summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMiklos Szeredi <mszeredi@redhat.com>2019-06-18 09:06:16 -0400
committerMiklos Szeredi <mszeredi@redhat.com>2019-06-18 09:06:16 -0400
commit9179c21dc6ed1c993caa5fe4da876a6765c26af7 (patch)
tree56f958c3bc6ab1368f51e5c11f106a49efe33120
parent941d935ac7636911a3fd8fa80e758e52b0b11e20 (diff)
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")
-rw-r--r--fs/overlayfs/super.c26
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:
1471 * Check if this layer root is a descendant of: 1471 * Check if this layer root is a descendant of:
1472 * - another layer of this overlayfs instance 1472 * - another layer of this overlayfs instance
1473 * - upper/work dir of any overlayfs instance 1473 * - upper/work dir of any overlayfs instance
1474 * - a disconnected dentry (detached root)
1475 */ 1474 */
1476static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, 1475static int ovl_check_layer(struct super_block *sb, struct dentry *dentry,
1477 const char *name) 1476 const char *name)
1478{ 1477{
1479 struct dentry *next, *parent; 1478 struct dentry *next = dentry, *parent;
1480 bool is_root = false;
1481 int err = 0; 1479 int err = 0;
1482 1480
1483 if (!dentry || dentry == dentry->d_sb->s_root) 1481 if (!dentry)
1484 return 0; 1482 return 0;
1485 1483
1486 next = dget(dentry); 1484 parent = dget_parent(next);
1487 /* Walk back ancestors to fs root (inclusive) looking for traps */ 1485
1488 do { 1486 /* Walk back ancestors to root (inclusive) looking for traps */
1489 parent = dget_parent(next); 1487 while (!err && parent != next) {
1490 is_root = (parent == next);
1491 if (ovl_is_inuse(parent)) { 1488 if (ovl_is_inuse(parent)) {
1492 err = -EBUSY; 1489 err = -EBUSY;
1493 pr_err("overlayfs: %s path overlapping in-use upperdir/workdir\n", 1490 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,
1496 err = -ELOOP; 1493 err = -ELOOP;
1497 pr_err("overlayfs: overlapping %s path\n", name); 1494 pr_err("overlayfs: overlapping %s path\n", name);
1498 } 1495 }
1499 dput(next);
1500 next = parent; 1496 next = parent;
1501 } while (!err && !is_root); 1497 parent = dget_parent(next);
1502 1498 dput(next);
1503 /* Did we really walk to fs root or found a detached root? */
1504 if (!err && next != dentry->d_sb->s_root) {
1505 err = -ESTALE;
1506 pr_err("overlayfs: disconnected %s path\n", name);
1507 } 1499 }
1508 1500
1509 dput(next); 1501 dput(parent);
1510 1502
1511 return err; 1503 return err;
1512} 1504}