* [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads
@ 2025-12-04 0:03 T.J. Mercier
2025-12-04 0:03 ` [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads T.J. Mercier
2025-12-10 7:50 ` [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads patchwork-bot+netdevbpf
0 siblings, 2 replies; 4+ messages in thread
From: T.J. Mercier @ 2025-12-04 0:03 UTC (permalink / raw)
To: yonghong.song, ast, daniel, andrii, martin.lau, eddyz87, song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, shuah, bpf,
linux-kernel, linux-kselftest, android-mm
Cc: christian.koenig, sumit.semwal, linux-media, dri-devel,
linaro-mm-sig, T.J. Mercier
If there is a large number (hundreds) of dmabufs allocated, the text
output generated from dmabuf_iter_seq_show can exceed common user buffer
sizes (e.g. PAGE_SIZE) necessitating multiple start/stop cycles to
iterate through all dmabufs. However the dmabuf iterator currently
returns NULL in dmabuf_iter_seq_start for all non-zero pos values, which
results in the truncation of the output before all dmabufs are handled.
After dma_buf_iter_begin / dma_buf_iter_next, the refcount of the buffer
is elevated so that the BPF iterator program can run without holding any
locks. When a stop occurs, instead of immediately dropping the reference
on the buffer, stash a pointer to the buffer in seq->priv until
either start is called or the iterator is released. This also enables
the resumption of iteration without first walking through the list of
dmabufs based on the pos value.
Fixes: 76ea95534995 ("bpf: Add dmabuf iterator")
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
kernel/bpf/dmabuf_iter.c | 56 +++++++++++++++++++++++++++++++++++-----
1 file changed, 49 insertions(+), 7 deletions(-)
diff --git a/kernel/bpf/dmabuf_iter.c b/kernel/bpf/dmabuf_iter.c
index 4dd7ef7c145c..cd500248abd9 100644
--- a/kernel/bpf/dmabuf_iter.c
+++ b/kernel/bpf/dmabuf_iter.c
@@ -6,10 +6,33 @@
#include <linux/kernel.h>
#include <linux/seq_file.h>
+struct dmabuf_iter_priv {
+ /*
+ * If this pointer is non-NULL, the buffer's refcount is elevated to
+ * prevent destruction between stop/start. If reading is not resumed and
+ * start is never called again, then dmabuf_iter_seq_fini drops the
+ * reference when the iterator is released.
+ */
+ struct dma_buf *dmabuf;
+};
+
static void *dmabuf_iter_seq_start(struct seq_file *seq, loff_t *pos)
{
- if (*pos)
- return NULL;
+ struct dmabuf_iter_priv *p = seq->private;
+
+ if (*pos) {
+ struct dma_buf *dmabuf = p->dmabuf;
+
+ if (!dmabuf)
+ return NULL;
+
+ /*
+ * Always resume from where we stopped, regardless of the value
+ * of pos.
+ */
+ p->dmabuf = NULL;
+ return dmabuf;
+ }
return dma_buf_iter_begin();
}
@@ -54,8 +77,11 @@ static void dmabuf_iter_seq_stop(struct seq_file *seq, void *v)
{
struct dma_buf *dmabuf = v;
- if (dmabuf)
- dma_buf_put(dmabuf);
+ if (dmabuf) {
+ struct dmabuf_iter_priv *p = seq->private;
+
+ p->dmabuf = dmabuf;
+ }
}
static const struct seq_operations dmabuf_iter_seq_ops = {
@@ -71,11 +97,27 @@ static void bpf_iter_dmabuf_show_fdinfo(const struct bpf_iter_aux_info *aux,
seq_puts(seq, "dmabuf iter\n");
}
+static int dmabuf_iter_seq_init(void *priv, struct bpf_iter_aux_info *aux)
+{
+ struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
+
+ p->dmabuf = NULL;
+ return 0;
+}
+
+static void dmabuf_iter_seq_fini(void *priv)
+{
+ struct dmabuf_iter_priv *p = (struct dmabuf_iter_priv *)priv;
+
+ if (p->dmabuf)
+ dma_buf_put(p->dmabuf);
+}
+
static const struct bpf_iter_seq_info dmabuf_iter_seq_info = {
.seq_ops = &dmabuf_iter_seq_ops,
- .init_seq_private = NULL,
- .fini_seq_private = NULL,
- .seq_priv_size = 0,
+ .init_seq_private = dmabuf_iter_seq_init,
+ .fini_seq_private = dmabuf_iter_seq_fini,
+ .seq_priv_size = sizeof(struct dmabuf_iter_priv),
};
static struct bpf_iter_reg bpf_dmabuf_reg_info = {
base-commit: 30f09200cc4aefbd8385b01e41bde2e4565a6f0e
--
2.52.0.177.g9f829587af-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads
2025-12-04 0:03 [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads T.J. Mercier
@ 2025-12-04 0:03 ` T.J. Mercier
2025-12-04 16:44 ` T.J. Mercier
2025-12-10 7:50 ` [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads patchwork-bot+netdevbpf
1 sibling, 1 reply; 4+ messages in thread
From: T.J. Mercier @ 2025-12-04 0:03 UTC (permalink / raw)
To: yonghong.song, ast, daniel, andrii, martin.lau, eddyz87, song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, shuah, bpf,
linux-kernel, linux-kselftest, android-mm
Cc: christian.koenig, sumit.semwal, linux-media, dri-devel,
linaro-mm-sig, T.J. Mercier
If many dmabufs are present, reads of the dmabuf iterator can be
truncated at PAGE_SIZE or user buffer size boundaries before the fix in
"selftests/bpf: Add test for open coded dmabuf_iter". Add a test to
confirm truncation does not occur.
Signed-off-by: T.J. Mercier <tjmercier@google.com>
---
.../selftests/bpf/prog_tests/dmabuf_iter.c | 47 +++++++++++++++++--
1 file changed, 42 insertions(+), 5 deletions(-)
diff --git a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
index 6c2b0c3dbcd8..e442be9dde7e 100644
--- a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
+++ b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
@@ -73,12 +73,10 @@ static int create_udmabuf(void)
return -1;
}
-static int create_sys_heap_dmabuf(void)
+static int create_sys_heap_dmabuf(size_t bytes)
{
- sysheap_test_buffer_size = 20 * getpagesize();
-
struct dma_heap_allocation_data data = {
- .len = sysheap_test_buffer_size,
+ .len = bytes,
.fd = 0,
.fd_flags = O_RDWR | O_CLOEXEC,
.heap_flags = 0,
@@ -110,7 +108,9 @@ static int create_sys_heap_dmabuf(void)
static int create_test_buffers(void)
{
udmabuf = create_udmabuf();
- sysheap_dmabuf = create_sys_heap_dmabuf();
+
+ sysheap_test_buffer_size = 20 * getpagesize();
+ sysheap_dmabuf = create_sys_heap_dmabuf(sysheap_test_buffer_size);
if (udmabuf < 0 || sysheap_dmabuf < 0)
return -1;
@@ -219,6 +219,26 @@ static void subtest_dmabuf_iter_check_default_iter(struct dmabuf_iter *skel)
close(iter_fd);
}
+static void subtest_dmabuf_iter_check_lots_of_buffers(struct dmabuf_iter *skel)
+{
+ int iter_fd;
+ char buf[1024];
+ size_t total_bytes_read = 0;
+ ssize_t bytes_read;
+
+ iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector));
+ if (!ASSERT_OK_FD(iter_fd, "iter_create"))
+ return;
+
+ while ((bytes_read = read(iter_fd, buf, sizeof(buf))) > 0)
+ total_bytes_read += bytes_read;
+
+ ASSERT_GT(total_bytes_read, getpagesize(), "total_bytes_read");
+
+ close(iter_fd);
+}
+
+
static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd)
{
LIBBPF_OPTS(bpf_test_run_opts, topts);
@@ -275,6 +295,23 @@ void test_dmabuf_iter(void)
subtest_dmabuf_iter_check_no_infinite_reads(skel);
if (test__start_subtest("default_iter"))
subtest_dmabuf_iter_check_default_iter(skel);
+ if (test__start_subtest("lots_of_buffers")) {
+ size_t NUM_BUFS = 100;
+ int buffers[NUM_BUFS];
+ int i;
+
+ for (i = 0; i < NUM_BUFS; ++i) {
+ buffers[i] = create_sys_heap_dmabuf(getpagesize());
+ if (!ASSERT_OK_FD(buffers[i], "dmabuf_fd"))
+ goto cleanup_bufs;
+ }
+
+ subtest_dmabuf_iter_check_lots_of_buffers(skel);
+
+cleanup_bufs:
+ for (--i; i >= 0; --i)
+ close(buffers[i]);
+ }
if (test__start_subtest("open_coded"))
subtest_dmabuf_iter_check_open_coded(skel, map_fd);
--
2.52.0.177.g9f829587af-goog
^ permalink raw reply related [flat|nested] 4+ messages in thread
* Re: [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads
2025-12-04 0:03 ` [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads T.J. Mercier
@ 2025-12-04 16:44 ` T.J. Mercier
0 siblings, 0 replies; 4+ messages in thread
From: T.J. Mercier @ 2025-12-04 16:44 UTC (permalink / raw)
To: yonghong.song, ast, daniel, andrii, martin.lau, eddyz87, song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, shuah, bpf,
linux-kernel, linux-kselftest, android-mm
Cc: christian.koenig, sumit.semwal, linux-media, dri-devel,
linaro-mm-sig
On Wed, Dec 3, 2025 at 4:05 PM T.J. Mercier <tjmercier@google.com> wrote:
>
> If many dmabufs are present, reads of the dmabuf iterator can be
> truncated at PAGE_SIZE or user buffer size boundaries before the fix in
> "selftests/bpf: Add test for open coded dmabuf_iter".
Copy/paste error here. This should be "bpf: Fix truncated dmabuf
iterator reads" from the previous commit in patch 1. I didn't include
the sha because I don't think they're guaranteed to be stable at this
point.
I also saw the warning from CI about the extra newline before
subtest_dmabuf_iter_check_open_coded, but the current CI failures look
unrelated to this change.
Add a test to
> confirm truncation does not occur.
>
> Signed-off-by: T.J. Mercier <tjmercier@google.com>
> ---
> .../selftests/bpf/prog_tests/dmabuf_iter.c | 47 +++++++++++++++++--
> 1 file changed, 42 insertions(+), 5 deletions(-)
>
> diff --git a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
> index 6c2b0c3dbcd8..e442be9dde7e 100644
> --- a/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
> +++ b/tools/testing/selftests/bpf/prog_tests/dmabuf_iter.c
> @@ -73,12 +73,10 @@ static int create_udmabuf(void)
> return -1;
> }
>
> -static int create_sys_heap_dmabuf(void)
> +static int create_sys_heap_dmabuf(size_t bytes)
> {
> - sysheap_test_buffer_size = 20 * getpagesize();
> -
> struct dma_heap_allocation_data data = {
> - .len = sysheap_test_buffer_size,
> + .len = bytes,
> .fd = 0,
> .fd_flags = O_RDWR | O_CLOEXEC,
> .heap_flags = 0,
> @@ -110,7 +108,9 @@ static int create_sys_heap_dmabuf(void)
> static int create_test_buffers(void)
> {
> udmabuf = create_udmabuf();
> - sysheap_dmabuf = create_sys_heap_dmabuf();
> +
> + sysheap_test_buffer_size = 20 * getpagesize();
> + sysheap_dmabuf = create_sys_heap_dmabuf(sysheap_test_buffer_size);
>
> if (udmabuf < 0 || sysheap_dmabuf < 0)
> return -1;
> @@ -219,6 +219,26 @@ static void subtest_dmabuf_iter_check_default_iter(struct dmabuf_iter *skel)
> close(iter_fd);
> }
>
> +static void subtest_dmabuf_iter_check_lots_of_buffers(struct dmabuf_iter *skel)
> +{
> + int iter_fd;
> + char buf[1024];
> + size_t total_bytes_read = 0;
> + ssize_t bytes_read;
> +
> + iter_fd = bpf_iter_create(bpf_link__fd(skel->links.dmabuf_collector));
> + if (!ASSERT_OK_FD(iter_fd, "iter_create"))
> + return;
> +
> + while ((bytes_read = read(iter_fd, buf, sizeof(buf))) > 0)
> + total_bytes_read += bytes_read;
> +
> + ASSERT_GT(total_bytes_read, getpagesize(), "total_bytes_read");
> +
> + close(iter_fd);
> +}
> +
> +
> static void subtest_dmabuf_iter_check_open_coded(struct dmabuf_iter *skel, int map_fd)
> {
> LIBBPF_OPTS(bpf_test_run_opts, topts);
> @@ -275,6 +295,23 @@ void test_dmabuf_iter(void)
> subtest_dmabuf_iter_check_no_infinite_reads(skel);
> if (test__start_subtest("default_iter"))
> subtest_dmabuf_iter_check_default_iter(skel);
> + if (test__start_subtest("lots_of_buffers")) {
> + size_t NUM_BUFS = 100;
> + int buffers[NUM_BUFS];
> + int i;
> +
> + for (i = 0; i < NUM_BUFS; ++i) {
> + buffers[i] = create_sys_heap_dmabuf(getpagesize());
> + if (!ASSERT_OK_FD(buffers[i], "dmabuf_fd"))
> + goto cleanup_bufs;
> + }
> +
> + subtest_dmabuf_iter_check_lots_of_buffers(skel);
> +
> +cleanup_bufs:
> + for (--i; i >= 0; --i)
> + close(buffers[i]);
> + }
> if (test__start_subtest("open_coded"))
> subtest_dmabuf_iter_check_open_coded(skel, map_fd);
>
> --
> 2.52.0.177.g9f829587af-goog
>
^ permalink raw reply [flat|nested] 4+ messages in thread
* Re: [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads
2025-12-04 0:03 [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads T.J. Mercier
2025-12-04 0:03 ` [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads T.J. Mercier
@ 2025-12-10 7:50 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 4+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-12-10 7:50 UTC (permalink / raw)
To: T.J. Mercier
Cc: yonghong.song, ast, daniel, andrii, martin.lau, eddyz87, song,
john.fastabend, kpsingh, sdf, haoluo, jolsa, shuah, bpf,
linux-kernel, linux-kselftest, android-mm, christian.koenig,
sumit.semwal, linux-media, dri-devel, linaro-mm-sig
Hello:
This series was applied to bpf/bpf.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Wed, 3 Dec 2025 16:03:47 -0800 you wrote:
> If there is a large number (hundreds) of dmabufs allocated, the text
> output generated from dmabuf_iter_seq_show can exceed common user buffer
> sizes (e.g. PAGE_SIZE) necessitating multiple start/stop cycles to
> iterate through all dmabufs. However the dmabuf iterator currently
> returns NULL in dmabuf_iter_seq_start for all non-zero pos values, which
> results in the truncation of the output before all dmabufs are handled.
>
> [...]
Here is the summary with links:
- [bpf,1/2] bpf: Fix truncated dmabuf iterator reads
https://git.kernel.org/bpf/bpf/c/234483565dbb
- [bpf,2/2] selftests/bpf: Add test for truncated dmabuf_iter reads
https://git.kernel.org/bpf/bpf/c/9489d457d48b
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2025-12-10 7:53 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-12-04 0:03 [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads T.J. Mercier
2025-12-04 0:03 ` [PATCH bpf 2/2] selftests/bpf: Add test for truncated dmabuf_iter reads T.J. Mercier
2025-12-04 16:44 ` T.J. Mercier
2025-12-10 7:50 ` [PATCH bpf 1/2] bpf: Fix truncated dmabuf iterator reads patchwork-bot+netdevbpf
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).