[PATCH] usb: gadget: f_mass_storage: reject relative paths to fix sb_writers deadlock

Xue Lei <[email protected]>
Newsgroups org.kernel.vger.linux-usb,org.kernel.vger.linux-kernel
Message-ID <[email protected]>
A deadlock can occur when writing a relative path to the mass_storage
lun file attribute while the process's CWD is on the same configfs
mount:

  write(configfs_fd, "relative_path", ...)
    -> vfs_write()
      -> file_start_write()          -- acquires sb_writers (configfs sb)
        -> configfs_write_iter()
          -> fsg_store_file()
            -> fsg_lun_open()
              -> filp_open("relative_path", O_RDWR, ...)
                -> path_openat()
                  -> open_last_lookups()
                    -> mnt_want_write() -- tries to acquire same sb_writers
                       *** DEADLOCK ***

This happens because filp_open() resolves relative paths against the
task's CWD. If the CWD is on the same configfs superblock, path_openat()
calls mnt_want_write() which calls sb_start_write() on the same
superblock, causing a recursive lock acquisition that can deadlock
during filesystem freeze.

Backing file paths for mass_storage LUNs should always be absolute
paths pointing to block devices or regular files. Reject relative
paths early in fsg_store_file() to prevent this deadlock.

Reported-by: [email protected]
Closes: https://syzkaller.appspot.com/bug?extid=4c9318af45f0bf2af153
Fixes: ef0aa4b92cf1 ("usb: gadget: f_mass_storage: add configfs support")
Signed-off-by: Xue Lei <[email protected]>
---
 drivers/usb/gadget/function/storage_common.c | 6 ++++++
 1 file changed, 6 insertions(+)

diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c
index 75831f2c7abe..d45c7a34df99 100644
--- a/drivers/usb/gadget/function/storage_common.c
+++ b/drivers/usb/gadget/function/storage_common.c
@@ -448,6 +448,12 @@ ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
 	if (count > 0 && buf[count-1] == '\n')
 		((char *) buf)[count-1] = 0;		/* Ugh! */
 
+	/* Reject relative paths to prevent sb_writers deadlock when
+	 * CWD is on the same filesystem (e.g., configfs).
+	 */
+	if (count > 0 && buf[0] && buf[0] != '/')
+		return -EINVAL;
+
 	/* Load new medium */
 	down_write(filesem);
 	if (count > 0 && buf[0]) {
-- 
2.49.1
lmpx.com only provides a reader for public news (NNTP) servers. It is not affiliated with the servers or forums shown here and is not responsible for the content of articles, which is written by their respective authors.