5.10-stable review patch. If anyone has any objections, please let me know.
------------------
From: Sishuai Gong sishuai@purdue.edu
commit c42dd069be8dfc9b2239a5c89e73bbd08ab35de0 upstream.
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 by grabbing configfs_dirent_lock in configfs_lookup() while iterating ->s_children.
Signed-off-by: Sishuai Gong sishuai@purdue.edu Signed-off-by: Christoph Hellwig hch@lst.de Signed-off-by: Kyle Zeng zengyhkyle@gmail.com Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org --- fs/configfs/dir.c | 2 ++ 1 file changed, 2 insertions(+)
--- a/fs/configfs/dir.c +++ b/fs/configfs/dir.c @@ -479,6 +479,7 @@ static struct dentry * configfs_lookup(s if (!configfs_dirent_is_ready(parent_sd)) goto out;
+ spin_lock(&configfs_dirent_lock); list_for_each_entry(sd, &parent_sd->s_children, s_sibling) { if (sd->s_type & CONFIGFS_NOT_PINNED) { const unsigned char * name = configfs_get_name(sd); @@ -491,6 +492,7 @@ static struct dentry * configfs_lookup(s break; } } + spin_unlock(&configfs_dirent_lock);
if (!found) { /*