Re: [PATCH] configfs: fix a race in configfs_lookup()

From: Gong, Sishuai
Date: Tue Dec 28 2021 - 21:23:36 EST


Sorry, this email was delayed by several months due to some network
issues on my machine.

Please simply ignore it, since the bug mentioned is fixed already by
the commit c42dd069be8dfc9b2239a5c89e73bbd08ab35de0.

> On Dec 28, 2021, at 8:35 PM, Sishuai Gong <sishuai@xxxxxxxxxx> wrote:
>
> From: sishuaigong <sishuai@xxxxxxxxxx>
>
> When configfs_lookup() is executing list_for_each_entry(),
> it is possible that configfs_dir_lseek() is calling list_del().
> Some unfortunate interleavings of them can cause a kernel NULL
> pointer dereference error
>
> Thread 1 Thread 2
> //configfs_dir_lseek() //configfs_lookup()
> list_del(&cursor->s_sibling);
> list_for_each_entry(sd, ...)
>
> Fix this bug by using list_for_each_entry_safe() instead.
>
> Reported-by: Sishuai Gong <sishuai@xxxxxxxxxx>
> Signed-off-by: sishuaigong <sishuai@xxxxxxxxxx>
> ---
> fs/configfs/dir.c | 4 ++--
> 1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/fs/configfs/dir.c b/fs/configfs/dir.c
> index ac5e0c0e9181..8f5d0309fb4a 100644
> --- a/fs/configfs/dir.c
> +++ b/fs/configfs/dir.c
> @@ -452,7 +452,7 @@ static struct dentry * configfs_lookup(struct inode *dir,
> unsigned int flags)
> {
> struct configfs_dirent * parent_sd = dentry->d_parent->d_fsdata;
> - struct configfs_dirent * sd;
> + struct configfs_dirent *sd, *tmp;
> int found = 0;
> int err;
>
> @@ -468,7 +468,7 @@ static struct dentry * configfs_lookup(struct inode *dir,
> if (!configfs_dirent_is_ready(parent_sd))
> goto out;
>
> - list_for_each_entry(sd, &parent_sd->s_children, s_sibling) {
> + list_for_each_entry_safe(sd, tmp, &parent_sd->s_children, s_sibling) {
> if (sd->s_type & CONFIGFS_NOT_PINNED) {
> const unsigned char * name = configfs_get_name(sd);
>
> --
> 2.17.1
>