[PATCH 09/19] usb: gadget: f_fs: let the request keep its fence
From: Greg Kroah-Hartman
Date: Tue Oct 27 2026 - 11:10:44 EST
From: Josef Bacik <josef@xxxxxxxxxxxxxx>
ffs_dmabuf_transfer() stores a plain pointer to the fence in the context
of the USB request, and since the fix for the fence leak it drops the
initial reference right after dma_resv_add_fence(). The only reference
left is the one of the reservation object.
That one does not last until the fence is signalled. dma_resv_add_fence()
replaces and puts a fence as soon as a later fence of the same context
and the same usage is added. All the fences of an attachment share a
context, and a transfer on an IN endpoint only waits for the writers,
not for the read fence of the transfer before it. So the second
FUNCTIONFS_DMABUF_TRANSFER of a buffer which is still queued frees the
fence of the first. When the first request completes,
ffs_dmabuf_signal_done() signals a fence in freed memory and queues the
work item in it.
The leak came from the reference which ffs_dmabuf_signal_done() takes
and ffs_dmabuf_cleanup() drops: with it nobody dropped the initial one.
Do not take it, and leave the initial reference to the request until the
cleanup.
Fixes: baa6b6068a3f ("usb: gadget: f_fs: Fix DMA fence leak")
Cc: stable <stable@xxxxxxxxxx>
Cc: Neill Kapron <nkapron@xxxxxxxxxx>
Signed-off-by: Josef Bacik <josef@xxxxxxxxxxxxxx>
Signed-off-by: Greg Kroah-Hartman <gregkh@xxxxxxxxxxxxxxxxxxx>
---
drivers/usb/gadget/function/f_fs.c | 10 +++++++---
1 file changed, 7 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/gadget/function/f_fs.c b/drivers/usb/gadget/function/f_fs.c
index c64a268e98a4..26f511794d6f 100644
--- a/drivers/usb/gadget/function/f_fs.c
+++ b/drivers/usb/gadget/function/f_fs.c
@@ -1447,13 +1447,12 @@ static void ffs_dmabuf_signal_done(struct ffs_dma_fence *dma_fence, int ret)
struct dma_fence *fence = &dma_fence->base;
bool cookie = dma_fence_begin_signalling();
- dma_fence_get(fence);
fence->error = ret;
dma_fence_signal(fence);
dma_fence_end_signalling(cookie);
/*
- * The fence will be unref'd in ffs_dmabuf_cleanup.
+ * The reference of the request will be dropped in ffs_dmabuf_cleanup.
* It can't be done here, as the unref functions might try to lock
* the resv object, which would deadlock.
*/
@@ -1737,8 +1736,13 @@ static int ffs_dmabuf_transfer(struct file *file,
resv_dir = epfile->in ? DMA_RESV_USAGE_READ : DMA_RESV_USAGE_WRITE;
+ /*
+ * The reservation object takes a reference of its own, and drops it as
+ * soon as a later fence of this attachment takes the place of this
+ * one. The initial reference stays with the request, which points to
+ * the fence until ffs_dmabuf_cleanup() has run.
+ */
dma_resv_add_fence(dmabuf->resv, &fence->base, resv_dir);
- dma_fence_put(&fence->base);
dma_resv_unlock(dmabuf->resv);
/* Now that the dma_fence is in place, queue the transfer. */
--
2.56.0