dma-buf: fix UAF in dma_buf_fd() tracepoint
Subsystems (3)
PATCH 1/1 dma-buf: fix UAF in dma_buf_fd() tracepoint
Once FD_ADD() returns, the fd is live in the file descriptor table and a thread sharing that table can close() it before DMA_BUF_TRACE() runs. The close drops the last reference, __fput() frees the dma_buf, and the tracepoint then dereferences dmabuf to take dmabuf->name_lock -- slab-use-after-free.
Split FD_ADD() back into get_unused_fd_flags() + fd_install() and emit the tracepoint between them. While the fdtable slot is reserved with a NULL file pointer, a racing close() returns -EBADF without entering __fput(), so the dma_buf stays alive across the trace. Same approach as commit 2d76319c4cbb ("dma-buf: fix UAF in dma_buf_put() tracepoint").
This undoes the FD_ADD() conversion done in commit 34dfce523c90 ("dma: convert dma_buf_fd() to FD_ADD()"); FD_ADD() has no place to hook the tracepoint safely.
--- drivers/dma-buf/dma-buf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/dma-buf/dma-buf.c +5 -1
@@ -792,9 +792,13 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)if (!dmabuf || !dmabuf->file)return -EINVAL ; - fd =FD_ADD (flags, dmabuf->file); + fd =get_unused_fd_flags (flags); +if (fd <0 ) +return fd; +DMA_BUF_TRACE (trace_dma_buf_fd, dmabuf, fd); +fd_install (fd, dmabuf->file);return fd; }EXPORT_SYMBOL_NS_GPL (dma_buf_fd,"DMA_BUF" );
Signature · 1 line
2.53.0
Quoted 17 lines · David Carlier
Once
FD_ADD()returns, the fd is live in the file descriptor table and a thread sharing that table canclose()it beforeDMA_BUF_TRACE()runs. The close drops the last reference,__fput()frees thedma_buf, and the tracepoint then dereferences dmabuf to takedmabuf->name_lock-- slab-use-after-free.Split
FD_ADD()back intoget_unused_fd_flags()+fd_install()and emit the tracepoint between them. While the fdtable slot is reserved with a NULL file pointer, a racingclose()returns-EBADFwithout entering__fput(), so thedma_bufstays alive across the trace. Same approach as commit2d76319c4cbb("dma-buf: fix UAF indma_buf_put()tracepoint").This undoes the
FD_ADD()conversion done in commit34dfce523c90("dma: convertdma_buf_fd()toFD_ADD()");FD_ADD()has no place to hook the tracepoint safely.
Quoted 5 lines
Reported-by [email protected]Fixes 281a22631423 ("dma-buf: add some tracepoints to debug.")Cc [email protected] # 7.0.xSigned-off-by David Carlier <[email protected]>
Quoted 26 lines
--- drivers/dma-buf/dma-buf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)drivers/dma-buf/dma-buf.c +5
-2@@ -792,9 +792,13 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)if (!dmabuf || !dmabuf->file)return -EINVAL ; - fd =FD_ADD (flags, dmabuf->file); + fd =get_unused_fd_flags (flags); +if (fd <0 ) +return fd; +DMA_BUF_TRACE (trace_dma_buf_fd, dmabuf, fd); +fd_install (fd, dmabuf->file);return fd; }EXPORT_SYMBOL_NS_GPL (dma_buf_fd,"DMA_BUF" ); --2.53.0
Sumit Semwal
maintainerHi David,
Quoted 19 lines · Christian König
Quoted 17 lines · David Carlier
Once
FD_ADD()returns, the fd is live in the file descriptor table and a thread sharing that table canclose()it beforeDMA_BUF_TRACE()runs. The close drops the last reference,__fput()frees thedma_buf, and the tracepoint then dereferences dmabuf to takedmabuf->name_lock-- slab-use-after-free.Split
FD_ADD()back intoget_unused_fd_flags()+fd_install()and emit the tracepoint between them. While the fdtable slot is reserved with a NULL file pointer, a racingclose()returns-EBADFwithout entering__fput(), so thedma_bufstays alive across the trace. Same approach as commit2d76319c4cbb("dma-buf: fix UAF indma_buf_put()tracepoint").This undoes the
FD_ADD()conversion done in commit34dfce523c90("dma: convertdma_buf_fd()toFD_ADD()");FD_ADD()has no place to hook the tracepoint safely.
Quoted 7 lines
Quoted 5 lines
Reported-by [email protected]Fixes 281a22631423 ("dma-buf: add some tracepoints to debug.")Cc [email protected] # 7.0.xSigned-off-by David Carlier <[email protected]>Reviewed-by Christian König <[email protected]>
Thanks very much for the patch; applied to drm-misc-fixes.
Quoted 20 lines
Quoted 20 lines
--- drivers/dma-buf/dma-buf.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)drivers/dma-buf/dma-buf.c +4
-1@@ -792,9 +792,13 @@ int dma_buf_fd(struct dma_buf *dmabuf, int flags)if (!dmabuf || !dmabuf->file)return -EINVAL ; - fd =FD_ADD (flags, dmabuf->file); + fd =get_unused_fd_flags (flags); +if (fd <0 ) +return fd; +DMA_BUF_TRACE (trace_dma_buf_fd, dmabuf, fd);
Quoted 8 lines
Quoted 7 lines
drivers/dma-buf/dma-buf.c +1
-1+fd_install (fd, dmabuf->file);return fd; }EXPORT_SYMBOL_NS_GPL (dma_buf_fd,"DMA_BUF" ); --2.53.0
Best,
Sumit.