From: Yu Zhang <yuz08559@gmail.com>
To: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org,
Yu Zhang <yuz08559@gmail.com>,
stable@vger.kernel.org
Subject: [PATCH] usb: gadget: f_mass_storage: take filesem in nofua store to fix backing-file UAF
Date: Sun, 18 Oct 2026 23:05:19 +1000 [thread overview]
Message-ID: <20261018130519.65850-1-yuz08559@gmail.com> (raw)
fsg_store_nofua() syncs the LUN's backing file when switching from async
to sync mode:
if (!nofua && curlun->nofua)
fsg_lun_fsync_sub(curlun);
fsg_lun_fsync_sub() dereferences curlun->filp (vfs_fsync(filp)). Unlike
every other store that touches the backing file -- fsg_store_ro() and
fsg_store_cdrom() (down_read), fsg_store_file() (down_write) --
fsg_store_nofua() holds no filesem while doing so.
A concurrent close of the backing file runs under down_write(filesem) and
does fput(curlun->filp) in fsg_lun_close() (fsg_store_file() with an empty
path, the SCSI START_STOP eject in do_start_stop(), or forced_eject), so
it can free the file while fsg_store_nofua() is dereferencing it:
BUG: KASAN: slab-use-after-free in vfs_fsync+0x20/0xe0
vfs_fsync+0x20/0xe0
fsg_lun_fsync_sub+0xa0/0xd0
fsg_store_nofua+0x138/0x160
configfs_write_iter+0x1a7/0x250
vfs_write+0x5df/0x940
Allocated by task 3459:
fsg_store_file+0x150/0x1f0
configfs_write_iter+0x1a7/0x250
Freed by task 3459:
__fput+0x456/0x6c0
__fput_deferred+0x10d/0x330
fsg_store_file+0x9e/0x1f0
configfs_write_iter+0x1a7/0x250
Take filesem for read around the fsync in fsg_store_nofua(), as the sibling
stores do, so the backing file cannot be closed underneath it.
Reproduced on a mass_storage gadget over dummy_hcd by writing lun.N/nofua
(1 then 0) from one task while another task rewrites and clears lun.N/file.
Cc: stable@vger.kernel.org
Signed-off-by: Yu Zhang <yuz08559@gmail.com>
---
drivers/usb/gadget/function/f_mass_storage.c | 6 ++++--
drivers/usb/gadget/function/storage_common.c | 5 ++++-
drivers/usb/gadget/function/storage_common.h | 3 ++-
3 files changed, 12 insertions(+), 4 deletions(-)
diff --git a/drivers/usb/gadget/function/f_mass_storage.c b/drivers/usb/gadget/function/f_mass_storage.c
index 0000001..0000002 100644
--- a/drivers/usb/gadget/function/f_mass_storage.c
+++ b/drivers/usb/gadget/function/f_mass_storage.c
@@ -2663,8 +2663,9 @@
const char *buf, size_t count)
{
struct fsg_lun *curlun = fsg_lun_from_dev(dev);
+ struct rw_semaphore *filesem = dev_get_drvdata(dev);
- return fsg_store_nofua(curlun, buf, count);
+ return fsg_store_nofua(curlun, filesem, buf, count);
}
static ssize_t file_store(struct device *dev, struct device_attribute *attr,
@@ -3239,7 +3240,10 @@
static ssize_t fsg_lun_opts_nofua_store(struct config_item *item,
const char *page, size_t len)
{
- return fsg_store_nofua(to_fsg_lun_opts(item)->lun, page, len);
+ struct fsg_lun_opts *opts = to_fsg_lun_opts(item);
+ struct fsg_opts *fsg_opts = to_fsg_opts(opts->group.cg_item.ci_parent);
+
+ return fsg_store_nofua(opts->lun, &fsg_opts->common->filesem, page, len);
}
CONFIGFS_ATTR(fsg_lun_opts_, nofua);
diff --git a/drivers/usb/gadget/function/storage_common.c b/drivers/usb/gadget/function/storage_common.c
index 0000003..0000004 100644
--- a/drivers/usb/gadget/function/storage_common.c
+++ b/drivers/usb/gadget/function/storage_common.c
@@ -415,7 +415,8 @@
}
EXPORT_SYMBOL_GPL(fsg_store_ro);
-ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count)
+ssize_t fsg_store_nofua(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+ const char *buf, size_t count)
{
bool nofua;
int ret;
@@ -424,11 +425,13 @@
if (ret)
return ret;
+ down_read(filesem);
/* Sync data when switching from async mode to sync */
if (!nofua && curlun->nofua)
fsg_lun_fsync_sub(curlun);
curlun->nofua = nofua;
+ up_read(filesem);
return count;
}
diff --git a/drivers/usb/gadget/function/storage_common.h b/drivers/usb/gadget/function/storage_common.h
index 0000005..0000006 100644
--- a/drivers/usb/gadget/function/storage_common.h
+++ b/drivers/usb/gadget/function/storage_common.h
@@ -210,7 +210,8 @@
ssize_t fsg_show_removable(struct fsg_lun *curlun, char *buf);
ssize_t fsg_store_ro(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count);
-ssize_t fsg_store_nofua(struct fsg_lun *curlun, const char *buf, size_t count);
+ssize_t fsg_store_nofua(struct fsg_lun *curlun, struct rw_semaphore *filesem,
+ const char *buf, size_t count);
ssize_t fsg_store_file(struct fsg_lun *curlun, struct rw_semaphore *filesem,
const char *buf, size_t count);
ssize_t fsg_store_cdrom(struct fsg_lun *curlun, struct rw_semaphore *filesem,
next reply other threads:[~2026-10-18 13:05 UTC|newest]
Thread overview: 7+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-18 13:05 Yu Zhang [this message]
2026-10-18 13:08 ` [PATCH] usb: gadget: f_mass_storage: take filesem in nofua store to fix backing-file UAF sashiko-bot
2026-10-18 13:34 ` Greg Kroah-Hartman
2026-10-18 15:50 ` Alan Stern
2026-10-20 2:30 ` [PATCH v2] " Yu Zhang
2026-10-20 8:03 ` sashiko-bot
2026-10-20 14:11 ` Alan Stern
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261018130519.65850-1-yuz08559@gmail.com \
--to=yuz08559@gmail.com \
--cc=gregkh@linuxfoundation.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-usb@vger.kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.