[PATCH v5 0/4] dma-buf: fix fd leak when copy_to_user() fails after fd_install()
From: Baineng Shou
Date: Thu Jul 30 2026 - 02:33:32 EST
Several drivers call dma_buf_fd() — which internally calls fd_install()
— before copy_to_user() returns the fd number to userspace. If
copy_to_user() fails, the fd is already published in the caller's fd
table but the ioctl returns an error, so userspace never learns the fd
number. Worse, the window between fd_install() and copy_to_user()
allows other threads to observe and manipulate the fd (dup, close,
SCM_RIGHTS), making any "close it on the failure path" fix unsafe.
The fix is to split the allocation into three steps: reserve an fd with
get_unused_fd_flags() (not yet visible to other threads), do
copy_to_user(), and only then publish the fd with fd_install() via the
new dma_buf_fd_install() helper. On copy_to_user() failure,
put_unused_fd() + dma_buf_put() cleanly unwind with no user-visible
side effects.
Patch 1 introduces dma_buf_fd_install() in dma-buf.c (wrapping
fd_install() together with the DMA_BUF_TRACE call to preserve export
tracing) and applies the fix to dma-heap.
Patch 2 applies the same fix to fastrpc, which even had a comment
acknowledging the problem could not be fixed before.
Patch 3 replaces the bare fd_install() in drm_gem_prime_handle_to_fd()
with dma_buf_fd_install() to restore tracepoint coverage for DRM PRIME
exports (suggested by Christian König).
Patch 4 adds a selftest to tools/testing/selftests/dmabuf-heaps/ that
reproduces the fd-leak scenario (mprotect flip between copy_from_user
and copy_to_user) and verifies the fd count is unchanged after a failed
ioctl (suggested by Sumit Semwal).
v1: https://lore.kernel.org/dri-devel/20260703080922.1838362-1-shoubaineng@xxxxxxxxx/
v2: https://lore.kernel.org/dri-devel/20260710105430.3059661-1-shoubaineng@xxxxxxxxx/
v3: https://lore.kernel.org/dri-devel/20260714114654.3885457-1-shoubaineng@xxxxxxxxx/
v4: https://lore.kernel.org/dri-devel/20260714114654.3885457-1-shoubaineng@xxxxxxxxx/
Changes in v5:
- Add selftest (patch 4) reproducing the fd-leak scenario (Sumit Semwal)
Changes in v4:
- Add patch 3: drm/prime: use dma_buf_fd_install() (Christian König)
- Add Acked-by: Christian König to patches 1 and 2
Changes in v3:
- Split into two patches (dma-heap + fastrpc separately)
- Add dma_buf_fd_install() to preserve trace_dma_buf_fd tracepoint
- Add fastrpc fix using the new helper (T.J. Mercier)
Baineng Shou (4):
dma-buf: dma-heap: don't publish fd before copy_to_user() succeeds
misc: fastrpc: don't publish fd before copy_to_user() succeeds
drm/prime: use dma_buf_fd_install() to preserve export tracing
selftests: dmabuf-heaps: add fd-leak-on-EFAULT regression test
drivers/dma-buf/dma-buf.c | 20 +++
drivers/dma-buf/dma-heap.c | 80 ++++++------
drivers/gpu/drm/drm_prime.c | 2 +-
drivers/misc/fastrpc.c | 16 +--
include/linux/dma-buf.h | 1 +
.../selftests/dmabuf-heaps/dmabuf-heap.c | 115 +++++++++++++++++-
6 files changed, 182 insertions(+), 52 deletions(-)
--
2.34.1