diff options
| -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: | |||
| 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 | */ |
| 1476 | static int ovl_check_layer(struct super_block *sb, struct dentry *dentry, | 1475 | static 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 | } |
