Commit eacb58fd authored by Al Viro's avatar Al Viro
Browse files

binfmt_misc: switch to locked_recursive_removal()



... fixing a mount leak, strictly speaking.

Reviewed-by: default avatarChristian Brauner <brauner@kernel.org>
Signed-off-by: default avatarAl Viro <viro@zeniv.linux.org.uk>
parent 8c0e092e
Loading
Loading
Loading
Loading
+3 −41
Original line number Diff line number Diff line
@@ -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