Re: [PATCH] usb: gadget: f_mass_storage: reject relative paths to fix sb_writers deadlock
From: Alan Stern
Date: Wed Jul 29 2026 - 10:33:51 EST
On Wed, Jul 29, 2026 at 06:32:45PM +0800, Xue Lei wrote:
> 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.
What happens if the user gives an absolute path that just happens to be
below the configfs mount point?
What happens if the user gives a relative path of the form
"../filename"?
Alan Stern
>
> Reported-by: syzbot+4c9318af45f0bf2af153@xxxxxxxxxxxxxxxxxxxxxxxxx
> Closes: https://syzkaller.appspot.com/bug?extid=4c9318af45f0bf2af153
> Fixes: ef0aa4b92cf1 ("usb: gadget: f_mass_storage: add configfs support")
> Signed-off-by: Xue Lei <Xue.Lei@xxxxxxxxxxxxx>
> ---
> 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
>
>