Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux
1
fork

Configure Feed

Select the types of activity you want to include in your feed.

scsi: target: Fix recursive locking in __configfs_open_file()

In flush_write_buffer, &p->frag_sem is acquired and then the loaded store
function is called, which, here, is target_core_item_dbroot_store(). This
function called filp_open(), following which these functions were called
(in reverse order), according to the call trace:

down_read
__configfs_open_file
do_dentry_open
vfs_open
do_open
path_openat
do_filp_open
file_open_name
filp_open
target_core_item_dbroot_store
flush_write_buffer
configfs_write_iter

target_core_item_dbroot_store() tries to validate the new file path by
trying to open the file path provided to it; however, in this case, the bug
report shows:

db_root: not a directory: /sys/kernel/config/target/dbroot

indicating that the same configfs file was tried to be opened, on which it
is currently working on. Thus, it is trying to acquire frag_sem semaphore
of the same file of which it already holds the semaphore obtained in
flush_write_buffer(), leading to acquiring the semaphore in a nested manner
and a possibility of recursive locking.

Fix this by modifying target_core_item_dbroot_store() to use kern_path()
instead of filp_open() to avoid opening the file using filesystem-specific
function __configfs_open_file(), and further modifying it to make this fix
compatible.

Reported-by: syzbot+f6e8174215573a84b797@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=f6e8174215573a84b797
Tested-by: syzbot+f6e8174215573a84b797@syzkaller.appspotmail.com
Cc: stable@vger.kernel.org
Signed-off-by: Prithvi Tambewagh <activprithvi@gmail.com>
Reviewed-by: Dmitry Bogdanov <d.bogdanov@yadro.com>
Link: https://patch.msgid.link/20260216062002.61937-1-activprithvi@gmail.com
Signed-off-by: Martin K. Petersen <martin.petersen@oracle.com>

authored by

Prithvi Tambewagh and committed by
Martin K. Petersen
14d4ac19 80bf3b28

+6 -9
+6 -9
drivers/target/target_core_configfs.c
··· 108 108 const char *page, size_t count) 109 109 { 110 110 ssize_t read_bytes; 111 - struct file *fp; 112 111 ssize_t r = -EINVAL; 112 + struct path path = {}; 113 113 114 114 mutex_lock(&target_devices_lock); 115 115 if (target_devices) { ··· 131 131 db_root_stage[read_bytes - 1] = '\0'; 132 132 133 133 /* validate new db root before accepting it */ 134 - fp = filp_open(db_root_stage, O_RDONLY, 0); 135 - if (IS_ERR(fp)) { 134 + r = kern_path(db_root_stage, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, &path); 135 + if (r) { 136 136 pr_err("db_root: cannot open: %s\n", db_root_stage); 137 + if (r == -ENOTDIR) 138 + pr_err("db_root: not a directory: %s\n", db_root_stage); 137 139 goto unlock; 138 140 } 139 - if (!S_ISDIR(file_inode(fp)->i_mode)) { 140 - filp_close(fp, NULL); 141 - pr_err("db_root: not a directory: %s\n", db_root_stage); 142 - goto unlock; 143 - } 144 - filp_close(fp, NULL); 141 + path_put(&path); 145 142 146 143 strscpy(db_root, db_root_stage); 147 144 pr_debug("Target_Core_ConfigFS: db_root set to %s\n", db_root);