]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
binfmt_misc: switch to locked_recursive_removal()
authorAl Viro <viro@zeniv.linux.org.uk>
Sun, 9 Mar 2025 00:54:09 +0000 (19:54 -0500)
committerAl Viro <viro@zeniv.linux.org.uk>
Thu, 3 Jul 2025 02:36:51 +0000 (22:36 -0400)
... fixing a mount leak, strictly speaking.

Reviewed-by: Christian Brauner <brauner@kernel.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
fs/binfmt_misc.c

index 432fbf4fc33413877228d290999d71b820c1b296..a839f960cd4a00323bf34f733ca0faa4cbca9b8e 100644 (file)
@@ -674,44 +674,6 @@ static void bm_evict_inode(struct inode *inode)
        }
 }
 
-/**
- * unlink_binfmt_dentry - remove the dentry for the binary type handler
- * @dentry: dentry associated with the binary type handler
- *
- * Do the actual filesystem work to remove a dentry for a registered binary
- * type handler. Since binfmt_misc only allows simple files to be created
- * directly under the root dentry of the filesystem we ensure that we are
- * indeed passed a dentry directly beneath the root dentry, that the inode
- * associated with the root dentry is locked, and that it is a regular file we
- * are asked to remove.
- */
-static void unlink_binfmt_dentry(struct dentry *dentry)
-{
-       struct dentry *parent = dentry->d_parent;
-       struct inode *inode, *parent_inode;
-
-       /* All entries are immediate descendants of the root dentry. */
-       if (WARN_ON_ONCE(dentry->d_sb->s_root != parent))
-               return;
-
-       /* We only expect to be called on regular files. */
-       inode = d_inode(dentry);
-       if (WARN_ON_ONCE(!S_ISREG(inode->i_mode)))
-               return;
-
-       /* The parent inode must be locked. */
-       parent_inode = d_inode(parent);
-       if (WARN_ON_ONCE(!inode_is_locked(parent_inode)))
-               return;
-
-       if (simple_positive(dentry)) {
-               dget(dentry);
-               simple_unlink(parent_inode, dentry);
-               d_delete(dentry);
-               dput(dentry);
-       }
-}
-
 /**
  * remove_binfmt_handler - remove a binary type handler
  * @misc: handle to binfmt_misc instance
@@ -729,7 +691,7 @@ static void remove_binfmt_handler(struct binfmt_misc *misc, Node *e)
        write_lock(&misc->entries_lock);
        list_del_init(&e->list);
        write_unlock(&misc->entries_lock);
-       unlink_binfmt_dentry(e->dentry);
+       locked_recursive_removal(e->dentry, NULL);
 }
 
 /* /<entry> */
@@ -772,7 +734,7 @@ static ssize_t bm_entry_write(struct file *file, const char __user *buffer,
        case 3:
                /* Delete this handler. */
                inode = d_inode(inode->i_sb->s_root);
-               inode_lock(inode);
+               inode_lock_nested(inode, I_MUTEX_PARENT);
 
                /*
                 * In order to add new element or remove elements from the list
@@ -922,7 +884,7 @@ static ssize_t bm_status_write(struct file *file, const char __user *buffer,
        case 3:
                /* Delete all handlers. */
                inode = d_inode(file_inode(file)->i_sb->s_root);
-               inode_lock(inode);
+               inode_lock_nested(inode, I_MUTEX_PARENT);
 
                /*
                 * In order to add new element or remove elements from the list