* FAILED: patch "[PATCH] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile" failed to apply to 6.18-stable tree
@ 2026-07-14 16:50 gregkh
2026-07-20 10:54 ` [PATCH 6.18.y 1/3] new helper: simple_remove_by_name() Sasha Levin
0 siblings, 1 reply; 4+ messages in thread
From: gregkh @ 2026-07-14 16:50 UTC (permalink / raw)
To: nkapron, gregkh, stable; +Cc: stable
The patch below does not apply to the 6.18-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.18.y
git checkout FETCH_HEAD
git cherry-pick -x 8bdcf96eb135aebacac319667f87db034fb38406
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026071425-shield-overhung-4ba9@gregkh' --subject-prefix 'PATCH 6.18.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From 8bdcf96eb135aebacac319667f87db034fb38406 Mon Sep 17 00:00:00 2001
From: Neill Kapron <nkapron@google.com>
Date: Fri, 19 Jun 2026 04:06:04 +0000
Subject: [PATCH] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
Currently, ffs_epfile_release unconditionally frees the endpoint's
read_buffer when a file descriptor is closed. If userspace explicitly
opens the endpoint multiple times and closes one, the read_buffer is
destroyed. This can lead to silent data loss if other file descriptors
are still actively reading from the endpoint.
By tying the lifetime of the read_buffer to the ffs_epfile structure itself
(which is destroyed when the functionfs instance is torn down in
ffs_epfiles_destroy), we eliminate the brittle dependency on open/release
calls while correctly matching the conceptual lifetime of unread data on
the hardware endpoint.
Fixes: 9353afbbfa7b ("usb: gadget: f_fs: buffer data from ‘oversized’ OUT requests")
Cc: stable <stable@kernel.org>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Neill Kapron <nkapron@google.com>
Link: https://patch.msgid.link/20260619040609.4010746-3-nkapron@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index d9b95fb830df..44218be1e676 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1375,7 +1375,6 @@ ffs_epfile_release(struct inode *inode, struct file *file)
mutex_unlock(&epfile->dmabufs_mutex);
- __ffs_epfile_read_buffer_free(epfile);
ffs_data_closed(epfile->ffs);
return 0;
@@ -2393,6 +2392,7 @@ static void ffs_epfiles_destroy(struct super_block *sb,
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex));
+ __ffs_epfile_read_buffer_free(epfile);
simple_remove_by_name(root, epfile->name, clear_one);
}
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.18.y 1/3] new helper: simple_remove_by_name()
2026-07-14 16:50 FAILED: patch "[PATCH] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile" failed to apply to 6.18-stable tree gregkh
@ 2026-07-20 10:54 ` Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 2/3] functionfs: switch to simple_remove_by_name() Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 3/3] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile Sasha Levin
0 siblings, 2 replies; 4+ messages in thread
From: Sasha Levin @ 2026-07-20 10:54 UTC (permalink / raw)
To: stable; +Cc: Al Viro, Miklos Szeredi, Sasha Levin
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit 4051a9115ad24bb9a691774730ca9c1dd56de665 ]
simple_recursive_removal(), but instead of victim dentry it takes
parent + name.
Used to be open-coded in fs/fuse/control.c, but there's no need to expose
the guts of that thing there and there are other potential users, so
let's lift it into libfs...
Acked-by: Miklos Szeredi <mszeredi@redhat.com>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Stable-dep-of: 8bdcf96eb135 ("usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
fs/fuse/control.c | 7 +------
fs/libfs.c | 13 +++++++++++++
include/linux/fs.h | 2 ++
3 files changed, 16 insertions(+), 6 deletions(-)
diff --git a/fs/fuse/control.c b/fs/fuse/control.c
index ce11f4b427c281..2e300f6d646c31 100644
--- a/fs/fuse/control.c
+++ b/fs/fuse/control.c
@@ -290,18 +290,13 @@ static void remove_one(struct dentry *dentry)
*/
void fuse_ctl_remove_conn(struct fuse_conn *fc)
{
- struct dentry *dentry;
char name[32];
if (!fuse_control_sb || fc->no_control)
return;
sprintf(name, "%u", fc->dev);
- dentry = lookup_noperm_positive_unlocked(&QSTR(name), fuse_control_sb->s_root);
- if (!IS_ERR(dentry)) {
- simple_recursive_removal(dentry, remove_one);
- dput(dentry); // paired with lookup_noperm_positive_unlocked()
- }
+ simple_remove_by_name(fuse_control_sb->s_root, name, remove_one);
}
static int fuse_ctl_fill_super(struct super_block *sb, struct fs_context *fsc)
diff --git a/fs/libfs.c b/fs/libfs.c
index 96551deff8e501..52f00bfc8f7baa 100644
--- a/fs/libfs.c
+++ b/fs/libfs.c
@@ -647,6 +647,19 @@ void simple_recursive_removal(struct dentry *dentry,
}
EXPORT_SYMBOL(simple_recursive_removal);
+void simple_remove_by_name(struct dentry *parent, const char *name,
+ void (*callback)(struct dentry *))
+{
+ struct dentry *dentry;
+
+ dentry = lookup_noperm_positive_unlocked(&QSTR(name), parent);
+ if (!IS_ERR(dentry)) {
+ simple_recursive_removal(dentry, callback);
+ dput(dentry); // paired with lookup_noperm_positive_unlocked()
+ }
+}
+EXPORT_SYMBOL(simple_remove_by_name);
+
/* caller holds parent directory with I_MUTEX_PARENT */
void locked_recursive_removal(struct dentry *dentry,
void (*callback)(struct dentry *))
diff --git a/include/linux/fs.h b/include/linux/fs.h
index 39269c7d167e6d..95986609923592 100644
--- a/include/linux/fs.h
+++ b/include/linux/fs.h
@@ -3654,6 +3654,8 @@ extern int simple_rename(struct mnt_idmap *, struct inode *,
unsigned int);
extern void simple_recursive_removal(struct dentry *,
void (*callback)(struct dentry *));
+extern void simple_remove_by_name(struct dentry *, const char *,
+ void (*callback)(struct dentry *));
extern void locked_recursive_removal(struct dentry *,
void (*callback)(struct dentry *));
extern int noop_fsync(struct file *, loff_t, loff_t, int);
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.18.y 2/3] functionfs: switch to simple_remove_by_name()
2026-07-20 10:54 ` [PATCH 6.18.y 1/3] new helper: simple_remove_by_name() Sasha Levin
@ 2026-07-20 10:54 ` Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 3/3] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-07-20 10:54 UTC (permalink / raw)
To: stable; +Cc: Al Viro, Greg Kroah-Hartman, Sasha Levin
From: Al Viro <viro@zeniv.linux.org.uk>
[ Upstream commit c7747fafaba0dcdad3d7da240e961927b4865f98 ]
No need to return dentry from ffs_sb_create_file() or keep it around
afterwards.
To avoid subtle issues with getting to ffs from epfiles in
ffs_epfiles_destroy(), pass the superblock as explicit argument.
Callers have it anyway.
Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Al Viro <viro@zeniv.linux.org.uk>
Stable-dep-of: 8bdcf96eb135 ("usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile")
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/gadget/function/f_fs.c | 51 +++++++++++++-----------------
1 file changed, 22 insertions(+), 29 deletions(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index 5ef9a7a7f3bc30..bd82db001c7250 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -162,8 +162,6 @@ struct ffs_epfile {
struct ffs_data *ffs;
struct ffs_ep *ep; /* P: ffs->eps_lock */
- struct dentry *dentry;
-
/*
* Buffer for holding data from partial reads which may happen since
* we’re rounding user read requests to a multiple of a max packet size.
@@ -273,11 +271,11 @@ struct ffs_desc_helper {
};
static int __must_check ffs_epfiles_create(struct ffs_data *ffs);
-static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count);
+static void ffs_epfiles_destroy(struct super_block *sb,
+ struct ffs_epfile *epfiles, unsigned count);
-static struct dentry *
-ffs_sb_create_file(struct super_block *sb, const char *name, void *data,
- const struct file_operations *fops);
+static int ffs_sb_create_file(struct super_block *sb, const char *name,
+ void *data, const struct file_operations *fops);
/* Devices management *******************************************************/
@@ -1881,9 +1879,8 @@ ffs_sb_make_inode(struct super_block *sb, void *data,
}
/* Create "regular" file */
-static struct dentry *ffs_sb_create_file(struct super_block *sb,
- const char *name, void *data,
- const struct file_operations *fops)
+static int ffs_sb_create_file(struct super_block *sb, const char *name,
+ void *data, const struct file_operations *fops)
{
struct ffs_data *ffs = sb->s_fs_info;
struct dentry *dentry;
@@ -1891,16 +1888,16 @@ static struct dentry *ffs_sb_create_file(struct super_block *sb,
dentry = d_alloc_name(sb->s_root, name);
if (!dentry)
- return NULL;
+ return -ENOMEM;
inode = ffs_sb_make_inode(sb, data, fops, NULL, &ffs->file_perms);
if (!inode) {
dput(dentry);
- return NULL;
+ return -ENOMEM;
}
d_add(dentry, inode);
- return dentry;
+ return 0;
}
/* Super block */
@@ -1943,10 +1940,7 @@ static int ffs_sb_fill(struct super_block *sb, struct fs_context *fc)
return -ENOMEM;
/* EP0 file */
- if (!ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations))
- return -ENOMEM;
-
- return 0;
+ return ffs_sb_create_file(sb, "ep0", ffs, &ffs_ep0_operations);
}
enum {
@@ -2176,7 +2170,7 @@ static void ffs_data_closed(struct ffs_data *ffs)
flags);
if (epfiles)
- ffs_epfiles_destroy(epfiles,
+ ffs_epfiles_destroy(ffs->sb, epfiles,
ffs->eps_count);
if (ffs->setup_state == FFS_SETUP_PENDING)
@@ -2241,7 +2235,7 @@ static void ffs_data_clear(struct ffs_data *ffs)
* copy of epfile will save us from use-after-free.
*/
if (epfiles) {
- ffs_epfiles_destroy(epfiles, ffs->eps_count);
+ ffs_epfiles_destroy(ffs->sb, epfiles, ffs->eps_count);
ffs->epfiles = NULL;
}
@@ -2338,6 +2332,7 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
{
struct ffs_epfile *epfile, *epfiles;
unsigned i, count;
+ int err;
count = ffs->eps_count;
epfiles = kcalloc(count, sizeof(*epfiles), GFP_KERNEL);
@@ -2355,12 +2350,11 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
else
sprintf(epfile->name, "ep%u", i);
epfile->in = (ffs->eps_addrmap[i] & USB_ENDPOINT_DIR_MASK) ? 1 : 0;
- epfile->dentry = ffs_sb_create_file(ffs->sb, epfile->name,
- epfile,
- &ffs_epfile_operations);
- if (!epfile->dentry) {
- ffs_epfiles_destroy(epfiles, i - 1);
- return -ENOMEM;
+ err = ffs_sb_create_file(ffs->sb, epfile->name,
+ epfile, &ffs_epfile_operations);
+ if (err) {
+ ffs_epfiles_destroy(ffs->sb, epfiles, i - 1);
+ return err;
}
}
@@ -2368,16 +2362,15 @@ static int ffs_epfiles_create(struct ffs_data *ffs)
return 0;
}
-static void ffs_epfiles_destroy(struct ffs_epfile *epfiles, unsigned count)
+static void ffs_epfiles_destroy(struct super_block *sb,
+ struct ffs_epfile *epfiles, unsigned count)
{
struct ffs_epfile *epfile = epfiles;
+ struct dentry *root = sb->s_root;
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex));
- if (epfile->dentry) {
- simple_recursive_removal(epfile->dentry, NULL);
- epfile->dentry = NULL;
- }
+ simple_remove_by_name(root, epfile->name, NULL);
}
kfree(epfiles);
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH 6.18.y 3/3] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile
2026-07-20 10:54 ` [PATCH 6.18.y 1/3] new helper: simple_remove_by_name() Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 2/3] functionfs: switch to simple_remove_by_name() Sasha Levin
@ 2026-07-20 10:54 ` Sasha Levin
1 sibling, 0 replies; 4+ messages in thread
From: Sasha Levin @ 2026-07-20 10:54 UTC (permalink / raw)
To: stable; +Cc: Neill Kapron, stable, Greg Kroah-Hartman, Sasha Levin
From: Neill Kapron <nkapron@google.com>
[ Upstream commit 8bdcf96eb135aebacac319667f87db034fb38406 ]
Currently, ffs_epfile_release unconditionally frees the endpoint's
read_buffer when a file descriptor is closed. If userspace explicitly
opens the endpoint multiple times and closes one, the read_buffer is
destroyed. This can lead to silent data loss if other file descriptors
are still actively reading from the endpoint.
By tying the lifetime of the read_buffer to the ffs_epfile structure itself
(which is destroyed when the functionfs instance is torn down in
ffs_epfiles_destroy), we eliminate the brittle dependency on open/release
calls while correctly matching the conceptual lifetime of unread data on
the hardware endpoint.
Fixes: 9353afbbfa7b ("usb: gadget: f_fs: buffer data from ‘oversized’ OUT requests")
Cc: stable <stable@kernel.org>
Assisted-by: Antigravity:gemini-3.1-pro
Signed-off-by: Neill Kapron <nkapron@google.com>
Link: https://patch.msgid.link/20260619040609.4010746-3-nkapron@google.com
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/usb/gadget/function/f_fs.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index bd82db001c7250..7705877fdaa8f1 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1352,7 +1352,6 @@ ffs_epfile_release(struct inode *inode, struct file *file)
mutex_unlock(&epfile->dmabufs_mutex);
- __ffs_epfile_read_buffer_free(epfile);
ffs_data_closed(epfile->ffs);
return 0;
@@ -2370,6 +2369,7 @@ static void ffs_epfiles_destroy(struct super_block *sb,
for (; count; --count, ++epfile) {
BUG_ON(mutex_is_locked(&epfile->mutex));
+ __ffs_epfile_read_buffer_free(epfile);
simple_remove_by_name(root, epfile->name, NULL);
}
--
2.53.0
^ permalink raw reply related [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-07-20 10:54 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-14 16:50 FAILED: patch "[PATCH] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile" failed to apply to 6.18-stable tree gregkh
2026-07-20 10:54 ` [PATCH 6.18.y 1/3] new helper: simple_remove_by_name() Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 2/3] functionfs: switch to simple_remove_by_name() Sasha Levin
2026-07-20 10:54 ` [PATCH 6.18.y 3/3] usb: gadget: f_fs: Tie read_buffer lifetime to ffs_epfile Sasha Levin
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox