]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
ovl: fix possible double unlink
authorAmir Goldstein <amir73il@gmail.com>
Mon, 18 Aug 2025 09:23:55 +0000 (11:23 +0200)
committerAmir Goldstein <amir73il@gmail.com>
Mon, 18 Aug 2025 11:16:49 +0000 (13:16 +0200)
commit 9d23967b18c6 ("ovl: simplify an error path in
ovl_copy_up_workdir()") introduced the helper ovl_cleanup_unlocked(),
which is later used in several following patches to re-acquire the parent
inode lock and unlink a dentry that was earlier found using lookup.
This helper was eventually renamed to ovl_cleanup().

The helper ovl_parent_lock() is used to re-acquire the parent inode lock.
After acquiring the parent inode lock, the helper verifies that the
dentry has not since been moved to another parent, but it failed to
verify that the dentry wasn't unlinked from the parent.

This means that now every call to ovl_cleanup() could potentially
race with another thread, unlinking the dentry to be cleaned up
underneath overlayfs and trigger a vfs assertion.

Reported-by: syzbot+ec9fab8b7f0386b98a17@syzkaller.appspotmail.com
Tested-by: syzbot+ec9fab8b7f0386b98a17@syzkaller.appspotmail.com
Fixes: 9d23967b18c6 ("ovl: simplify an error path in ovl_copy_up_workdir()")
Suggested-by: NeilBrown <neil@brown.name>
Signed-off-by: Amir Goldstein <amir73il@gmail.com>
fs/overlayfs/util.c

index a33115e7384c129c543746326642813add63f060..41033bac96cbbb711103178e599876263c96d66a 100644 (file)
@@ -1552,7 +1552,8 @@ void ovl_copyattr(struct inode *inode)
 int ovl_parent_lock(struct dentry *parent, struct dentry *child)
 {
        inode_lock_nested(parent->d_inode, I_MUTEX_PARENT);
-       if (!child || child->d_parent == parent)
+       if (!child ||
+           (!d_unhashed(child) && child->d_parent == parent))
                return 0;
 
        inode_unlock(parent->d_inode);