Linux Kernel Selftest development
 help / color / mirror / Atom feed
* [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling
       [not found] <tencent_E69EAE29327E25B3548A9AF3F4FA289A6806@qq.com>
@ 2026-08-23 14:17 ` Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails Jianlin Shi
                     ` (5 more replies)
  0 siblings, 6 replies; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

v3 addressed Kartikeya's review on v2 and the related Sashiko findings.
v4 fixes the stream_oversize selftest to verify capacity rollback on the
same BPF program stream, since streams live on prog->aux and are not
shared across programs.

Tested locally:
  stream_oversize and stream_partial_read (equivalent to
  ./test_progs -t stream_oversize,stream_partial_read).

Changelog:
v3 -> v4:
  - In stream_oversize, perform the oversized bpf_stream_printk() and a
    subsequent successful "foo" push in the same program; read that
    program's stream in userspace instead of switching to stream_syscall.
  - Drop a redundant vscnprintf() comment in bpf_stream_stage_printk().

v2 -> v3:
  - Refactor bpf_stream_release_capacity() to take a length.
  - Fix staging-path capacity leak; use vscnprintf().
  - Return partial bpf_stream_read() progress on copy_to_user() fault.
  - Reject truncated bpf_stream_vprintk() output with -E2BIG.
  - Add selftests for oversize and straddling-buffer partial read.

v1 -> v2:
  - Retarget to bpf-next as suggested by Pu Lehui.

Links:
v3: https://lore.kernel.org/bpf/?q=%22PATCH+bpf-next+v3+0%2F5%22+fix+stream+capacity
v2: https://lore.kernel.org/bpf/tencent_C919BB32458A4DAD645A68F441345B971E05@qq.com/
v1: https://lore.kernel.org/bpf/tencent_E69EAE29327E25B3548A9AF3F4FA289A6806@qq.com/

Jianlin Shi (5):
  bpf: roll back stream capacity when allocation fails
  bpf: fix stream capacity leak in staging path
  bpf: return partial progress from bpf_stream_read on fault
  bpf: reject oversized bpf_stream_vprintk output with -E2BIG
  selftests/bpf: cover stream capacity and partial read edge cases

 kernel/bpf/stream.c                           | 53 +++++++++------
 .../testing/selftests/bpf/prog_tests/stream.c | 65 +++++++++++++++++++
 tools/testing/selftests/bpf/progs/stream.c    | 18 +++++
 3 files changed, 116 insertions(+), 20 deletions(-)

-- 
2.43.0


^ permalink raw reply	[flat|nested] 10+ messages in thread

* [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
@ 2026-08-23 14:17   ` Jianlin Shi
  2026-08-23 19:20     ` patchwork-bot+netdevbpf
  2026-08-23 14:17   ` [PATCH bpf-next v4 2/5] bpf: fix stream capacity leak in staging path Jianlin Shi
                     ` (4 subsequent siblings)
  5 siblings, 1 reply; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

bpf_stream_push_str() accounts the string length before allocating a
stream element. If the allocation fails, the length remains charged even
though no element is queued and therefore cannot be released by a reader.
Repeated failures can exhaust the stream capacity permanently until the
BPF program is freed.

Refactor bpf_stream_release_capacity() to take a length so the consume
and release sides are symmetric, and use it to roll back the charge when
creating the stream element fails.

Fixes: 5ab154f1463a ("bpf: Introduce BPF standard streams")
Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
 kernel/bpf/stream.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index be9ce98e9469..0b157ec4e38e 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -68,10 +68,8 @@ static int bpf_stream_consume_capacity(struct bpf_stream *stream, int len)
 	return 0;
 }
 
-static void bpf_stream_release_capacity(struct bpf_stream *stream, struct bpf_stream_elem *elem)
+static void bpf_stream_release_capacity(struct bpf_stream *stream, int len)
 {
-	int len = elem->total_len;
-
 	atomic_sub(len, &stream->capacity);
 }
 
@@ -79,7 +77,14 @@ static int bpf_stream_push_str(struct bpf_stream *stream, const char *str, int l
 {
 	int ret = bpf_stream_consume_capacity(stream, len);
 
-	return ret ?: __bpf_stream_push_str(&stream->log, str, len);
+	if (ret)
+		return ret;
+
+	ret = __bpf_stream_push_str(&stream->log, str, len);
+	if (ret)
+		bpf_stream_release_capacity(stream, len);
+
+	return ret;
 }
 
 static struct bpf_stream *bpf_stream_get(enum bpf_stream_id stream_id, struct bpf_prog_aux *aux)
@@ -188,7 +193,7 @@ static int bpf_stream_read(struct bpf_stream *stream, void __user *buf, int len)
 		if (cont)
 			continue;
 		bpf_stream_backlog_pop(stream);
-		bpf_stream_release_capacity(stream, elem);
+		bpf_stream_release_capacity(stream, elem->total_len);
 		bpf_stream_free_elem(elem);
 	}
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH bpf-next v4 2/5] bpf: fix stream capacity leak in staging path
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails Jianlin Shi
@ 2026-08-23 14:17   ` Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 3/5] bpf: return partial progress from bpf_stream_read on fault Jianlin Shi
                     ` (3 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

bpf_stream_stage_printk() increments ss->len before pushing the
formatted string to the staging log. If element allocation fails,
ss->len remains inflated and bpf_stream_stage_commit() permanently
charges the stream capacity for data that was never queued.

Only account the string length after a successful push, and use
vscnprintf() so the staged length is the truncated payload without
the trailing NUL.

Fixes: 5ab154f1463a ("bpf: Introduce BPF standard streams")
Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
 kernel/bpf/stream.c | 9 +++++----
 1 file changed, 5 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index 0b157ec4e38e..a36fc9338967 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -316,17 +316,18 @@ int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...)
 {
 	struct bpf_bprintf_buffers *buf;
 	va_list args;
-	int ret;
+	int len, ret;
 
 	if (bpf_try_get_buffers(&buf))
 		return -EBUSY;
 
 	va_start(args, fmt);
-	ret = vsnprintf(buf->buf, ARRAY_SIZE(buf->buf), fmt, args);
+	len = vscnprintf(buf->buf, ARRAY_SIZE(buf->buf), fmt, args);
 	va_end(args);
-	ss->len += ret;
 	/* Exclude NULL byte during push. */
-	ret = __bpf_stream_push_str(&ss->log, buf->buf, ret);
+	ret = __bpf_stream_push_str(&ss->log, buf->buf, len);
+	if (!ret)
+		ss->len += len;
 	bpf_put_buffers();
 	return ret;
 }
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH bpf-next v4 3/5] bpf: return partial progress from bpf_stream_read on fault
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 2/5] bpf: fix stream capacity leak in staging path Jianlin Shi
@ 2026-08-23 14:17   ` Jianlin Shi
  2026-08-23 14:17   ` [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG Jianlin Shi
                     ` (2 subsequent siblings)
  5 siblings, 0 replies; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

bpf_stream_read() pops and frees stream elements after a successful
copy_to_user(). If a later copy_to_user() fails, it currently restores
only the current element's consumed_len and returns -EFAULT, hiding
bytes already delivered to userspace and making the consumed data
unrecoverable on retry.

On a short copy, keep the successfully copied prefix of the current
element and return the number of bytes copied. Return -EFAULT only when
no bytes were copied for the call.

Fixes: 5ab154f1463a ("bpf: Introduce BPF standard streams")
Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
 kernel/bpf/stream.c | 16 +++++++++-------
 1 file changed, 9 insertions(+), 7 deletions(-)

diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index a36fc9338967..09471a605268 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -167,6 +167,7 @@ static int bpf_stream_read(struct bpf_stream *stream, void __user *buf, int len)
 
 	while (rem_len) {
 		int pos = len - rem_len;
+		int chunk, n;
 		bool cont;
 
 		node = bpf_stream_backlog_peek(stream);
@@ -180,13 +181,14 @@ static int bpf_stream_read(struct bpf_stream *stream, void __user *buf, int len)
 
 		cons_len = elem->consumed_len;
 		cont = bpf_stream_consume_elem(elem, &rem_len) == false;
-
-		ret = copy_to_user(buf + pos, elem->str + cons_len,
-				   elem->consumed_len - cons_len);
-		/* Restore in case of error. */
-		if (ret) {
-			ret = -EFAULT;
-			elem->consumed_len = cons_len;
+		chunk = elem->consumed_len - cons_len;
+
+		n = copy_to_user(buf + pos, elem->str + cons_len, chunk);
+		if (n) {
+			/* Keep any successfully copied bytes; -EFAULT only if none. */
+			elem->consumed_len -= n;
+			rem_len += n;
+			ret = (len == rem_len) ? -EFAULT : 0;
 			break;
 		}
 
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
                     ` (2 preceding siblings ...)
  2026-08-23 14:17   ` [PATCH bpf-next v4 3/5] bpf: return partial progress from bpf_stream_read on fault Jianlin Shi
@ 2026-08-23 14:17   ` Jianlin Shi
  2026-08-23 15:10     ` bot+bpf-ci
  2026-08-23 14:17   ` [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases Jianlin Shi
  2026-08-23 19:22   ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Kumar Kartikeya Dwivedi
  5 siblings, 1 reply; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

bstr_printf() returns the would-be length excluding the trailing NUL.
When that value is >= MAX_BPRINTF_BUF the message was truncated, but
bpf_stream_push_str() still tried to allocate with the inflated length
and failed with -ENOMEM. The boundary case of exactly MAX_BPRINTF_BUF
could also copy the trailing NUL into the stream element.

Reject such lengths with -E2BIG before charging stream capacity, and
tighten bpf_stream_elem_alloc() to accept only payloads strictly shorter
than the bprintf buffer.

Fixes: 5ab154f1463a ("bpf: Introduce BPF standard streams")
Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
 kernel/bpf/stream.c | 13 +++++++++----
 1 file changed, 9 insertions(+), 4 deletions(-)

diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index 09471a605268..7a5c3ac8676b 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -22,11 +22,11 @@ static struct bpf_stream_elem *bpf_stream_elem_alloc(int len)
 	size_t alloc_size;
 
 	/*
-	 * Length denotes the amount of data to be written as part of stream element,
-	 * thus includes '\0' byte. We're capped by how much bpf_bprintf_buffers can
-	 * accomodate, therefore deny allocations that won't fit into them.
+	 * Length is the payload pushed into the stream, excluding the
+	 * trailing NUL of the bprintf buffer. Reject anything that cannot
+	 * fit without copying that NUL into the stream element.
 	 */
-	if (len < 0 || len > max_len)
+	if (len < 0 || len >= max_len)
 		return NULL;
 
 	alloc_size = offsetof(struct bpf_stream_elem, str[len]);
@@ -245,6 +245,11 @@ __bpf_kfunc int bpf_stream_vprintk(int stream_id, const char *fmt__str, const vo
 		return ret;
 
 	ret = bstr_printf(data.buf, MAX_BPRINTF_BUF, fmt__str, data.bin_args);
+	/* Truncation: reject before capacity charge (not -ENOMEM). */
+	if (ret >= MAX_BPRINTF_BUF) {
+		bpf_bprintf_cleanup(&data);
+		return -E2BIG;
+	}
 	/* Exclude NULL byte during push. */
 	ret = bpf_stream_push_str(stream, data.buf, ret);
 	bpf_bprintf_cleanup(&data);
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
                     ` (3 preceding siblings ...)
  2026-08-23 14:17   ` [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG Jianlin Shi
@ 2026-08-23 14:17   ` Jianlin Shi
  2026-08-23 15:10     ` bot+bpf-ci
  2026-08-23 19:22   ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Kumar Kartikeya Dwivedi
  5 siblings, 1 reply; 10+ messages in thread
From: Jianlin Shi @ 2026-08-23 14:17 UTC (permalink / raw)
  To: bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

Add coverage for the stream fixes requested on the capacity rollback
series:

- oversized bpf_stream_printk() returns -E2BIG and does not leak
  capacity for a subsequent successful write on the same program;
- bpf_prog_stream_read() returns the successfully copied prefix when
  the userspace buffer straddles an unmapped page.

Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
 .../testing/selftests/bpf/prog_tests/stream.c | 65 +++++++++++++++++++
 tools/testing/selftests/bpf/progs/stream.c    | 18 +++++
 2 files changed, 83 insertions(+)

diff --git a/tools/testing/selftests/bpf/prog_tests/stream.c b/tools/testing/selftests/bpf/prog_tests/stream.c
index c3cce5c292bd..87170dcad3ad 100644
--- a/tools/testing/selftests/bpf/prog_tests/stream.c
+++ b/tools/testing/selftests/bpf/prog_tests/stream.c
@@ -58,6 +58,71 @@ void test_stream_syscall(void)
 	stream__destroy(skel);
 }
 
+void test_stream_oversize(void)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, opts);
+	struct stream *skel;
+	int ret, prog_fd;
+	char buf[8] = {};
+
+	skel = stream__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "stream__open_and_load"))
+		return;
+
+	prog_fd = bpf_program__fd(skel->progs.stream_oversize);
+	ret = bpf_prog_test_run_opts(prog_fd, &opts);
+	ASSERT_OK(ret, "oversize run");
+	ASSERT_OK(opts.retval, "oversize retval");
+
+	/* Oversized push must not permanently consume capacity on this prog. */
+	ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, buf, sizeof(buf), NULL);
+	ASSERT_EQ(ret, 3, "bytes after oversize");
+	ASSERT_OK(memcmp(buf, "foo", 3), "payload after oversize");
+
+	stream__destroy(skel);
+}
+
+void test_stream_partial_read(void)
+{
+	LIBBPF_OPTS(bpf_test_run_opts, opts);
+	struct stream *skel;
+	int ret, prog_fd;
+	long page_size;
+	char *page, *buf;
+	char rest[8] = {};
+
+	skel = stream__open_and_load();
+	if (!ASSERT_OK_PTR(skel, "stream__open_and_load"))
+		return;
+
+	prog_fd = bpf_program__fd(skel->progs.stream_syscall);
+	ret = bpf_prog_test_run_opts(prog_fd, &opts);
+	ASSERT_OK(ret, "ret");
+	ASSERT_OK(opts.retval, "retval");
+
+	page_size = sysconf(_SC_PAGESIZE);
+	page = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
+		    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
+	if (!ASSERT_NEQ(page, MAP_FAILED, "mmap")) {
+		stream__destroy(skel);
+		return;
+	}
+	/* Leave only the first page mapped so a straddling copy faults. */
+	ASSERT_OK(munmap(page + page_size, page_size), "munmap second page");
+
+	buf = page + page_size - 1;
+	ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, buf, 3, NULL);
+	ASSERT_EQ(ret, 1, "partial bytes");
+	ASSERT_EQ(buf[0], 'f', "first byte");
+
+	ret = bpf_prog_stream_read(prog_fd, BPF_STREAM_STDOUT, rest, sizeof(rest), NULL);
+	ASSERT_EQ(ret, 2, "remaining bytes");
+	ASSERT_OK(memcmp(rest, "oo", 2), "remaining data");
+
+	munmap(page, page_size);
+	stream__destroy(skel);
+}
+
 static void test_address(struct bpf_program *prog, unsigned long *fault_addr_p)
 {
 	LIBBPF_OPTS(bpf_test_run_opts, opts);
diff --git a/tools/testing/selftests/bpf/progs/stream.c b/tools/testing/selftests/bpf/progs/stream.c
index 6f999ba951a3..9b97f5e01b83 100644
--- a/tools/testing/selftests/bpf/progs/stream.c
+++ b/tools/testing/selftests/bpf/progs/stream.c
@@ -36,7 +36,12 @@ struct {
 } array SEC(".maps");
 
 #define ENOSPC 28
+#define E2BIG 7
 #define _STR "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+#define _X64 "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
+/* 1024 bytes: truncated by bstr_printf, must return -E2BIG. */
+#define _BIG_STR (_X64 _X64 _X64 _X64 _X64 _X64 _X64 _X64 \
+		  _X64 _X64 _X64 _X64 _X64 _X64 _X64 _X64)
 
 int size;
 u64 fault_addr;
@@ -117,6 +122,19 @@ int stream_syscall(void *ctx)
 	return 0;
 }
 
+SEC("syscall")
+__success __retval(0)
+int stream_oversize(void *ctx)
+{
+	int ret;
+
+	ret = bpf_stream_printk(BPF_STDOUT, _BIG_STR);
+	if (ret != -E2BIG)
+		return ret;
+
+	return bpf_stream_printk(BPF_STDOUT, "foo");
+}
+
 SEC("syscall")
 __arch_x86_64
 __arch_arm64
-- 
2.43.0


^ permalink raw reply related	[flat|nested] 10+ messages in thread

* Re: [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases
  2026-08-23 14:17   ` [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases Jianlin Shi
@ 2026-08-23 15:10     ` bot+bpf-ci
  0 siblings, 0 replies; 10+ messages in thread
From: bot+bpf-ci @ 2026-08-23 15:10 UTC (permalink / raw)
  To: shijianlin11, bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 2203 bytes --]

> diff --git a/tools/testing/selftests/bpf/prog_tests/stream.c b/tools/testing/selftests/bpf/prog_tests/stream.c
> index e4e9374309e2..9a21f055d80a 100644
> --- a/tools/testing/selftests/bpf/prog_tests/stream.c
> +++ b/tools/testing/selftests/bpf/prog_tests/stream.c

[ ... ]

> +void test_stream_partial_read(void)
> +{
> +	LIBBPF_OPTS(bpf_test_run_opts, opts);
> +	struct stream *skel;
> +	int ret, prog_fd;
> +	long page_size;
> +	char *page, *buf;
> +	char rest[8] = {};
> +
> +	skel = stream__open_and_load();
> +	if (!ASSERT_OK_PTR(skel, "stream__open_and_load"))
> +		return;
> +
> +	prog_fd = bpf_program__fd(skel->progs.stream_syscall);
> +	ret = bpf_prog_test_run_opts(prog_fd, &opts);
> +	ASSERT_OK(ret, "ret");
> +	ASSERT_OK(opts.retval, "retval");
> +
> +	page_size = sysconf(_SC_PAGESIZE);
> +	page = mmap(NULL, page_size * 2, PROT_READ | PROT_WRITE,
> +		    MAP_PRIVATE | MAP_ANONYMOUS, -1, 0);
> +	if (!ASSERT_NEQ(page, MAP_FAILED, "mmap")) {
> +		stream__destroy(skel);
> +		return;
> +	}
> +	/* Leave only the first page mapped so a straddling copy faults. */
> +	ASSERT_OK(munmap(page + page_size, page_size), "munmap second page");
                     ^^^^

Should this munmap() be gated like the other setup steps?  The mmap() above
returns early on failure, but this munmap() just records the result and
continues.

If the unmap fails, page + page_size stays mapped, copy_to_user() in
bpf_stream_read() no longer faults, and the first bpf_prog_stream_read()
returns 3 instead of 1.  The test then reports confusing failures
('partial bytes: actual 3 != expected 1' and 'remaining bytes: actual 0
!= expected 2') that point away from the real cause.

Also, the trailing cleanup only unmaps the first page:

> +	munmap(page, page_size);
> +	stream__destroy(skel);
> +}

so the still-mapped second page would be leaked for the remainder of the
test-runner process.  Would gating it the same way as the surrounding
checks work here?

[ ... ]


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32645868670

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG
  2026-08-23 14:17   ` [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG Jianlin Shi
@ 2026-08-23 15:10     ` bot+bpf-ci
  0 siblings, 0 replies; 10+ messages in thread
From: bot+bpf-ci @ 2026-08-23 15:10 UTC (permalink / raw)
  To: shijianlin11, bpf, memxor
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel, ast, andrii, daniel, martin.lau,
	eddyz87, yonghong.song, clm, ihor.solodrai

[-- Attachment #1: Type: text/plain, Size: 1448 bytes --]

> diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
> index 09471a605268..7a5c3ac8676b 100644
> --- a/kernel/bpf/stream.c
> +++ b/kernel/bpf/stream.c

[ ... ]

> @@ -245,6 +245,11 @@ __bpf_kfunc int bpf_stream_vprintk(int stream_id, const char *fmt__str, const vo
>  		return ret;
>
>  	ret = bstr_printf(data.buf, MAX_BPRINTF_BUF, fmt__str, data.bin_args);
> +	/* Truncation: reject before capacity charge (not -ENOMEM). */
> +	if (ret >= MAX_BPRINTF_BUF) {
> +		bpf_bprintf_cleanup(&data);
> +		return -E2BIG;
> +	}
>  	/* Exclude NULL byte during push. */
>  	ret = bpf_stream_push_str(stream, data.buf, ret);
>  	bpf_bprintf_cleanup(&data);

This isn't a bug, but could the truncation case set ret = -E2BIG and
fall through to the existing bpf_bprintf_cleanup(), so the buffer release
stays in one place?

The single-cleanup pattern appears elsewhere in this area:
bpf_stream_stage_printk() has one bpf_put_buffers() at the end, and
bpf_bprintf_prepare() funnels every failure through 'goto out'.

Something like:

	if (ret >= MAX_BPRINTF_BUF)
		ret = -E2BIG;
	else
		ret = bpf_stream_push_str(stream, data.buf, ret);
	bpf_bprintf_cleanup(&data);
	return ret;

would keep the release in one place.


---
AI reviewed your patch. Please fix the bug or email reply why it's not a bug.
See: https://github.com/kernel-patches/vmtest/blob/master/ci/claude/README.md

CI run summary: https://github.com/kernel-patches/bpf/actions/runs/32645868670

^ permalink raw reply	[flat|nested] 10+ messages in thread

* Re: [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails
  2026-08-23 14:17   ` [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails Jianlin Shi
@ 2026-08-23 19:20     ` patchwork-bot+netdevbpf
  0 siblings, 0 replies; 10+ messages in thread
From: patchwork-bot+netdevbpf @ 2026-08-23 19:20 UTC (permalink / raw)
  To: Jianlin Shi
  Cc: bpf, memxor, ast, daniel, andrii, martin.lau, eddyz87, song,
	yonghong.song, john.fastabend, kpsingh, sdf, haoluo, jolsa, emil,
	pulehui, shuah, linux-kselftest, linux-kernel

Hello:

This series was applied to bpf/bpf-next.git (master)
by Kumar Kartikeya Dwivedi <memxor@gmail.com>:

On Sun, 23 Aug 2026 22:17:24 +0800 you wrote:
> bpf_stream_push_str() accounts the string length before allocating a
> stream element. If the allocation fails, the length remains charged even
> though no element is queued and therefore cannot be released by a reader.
> Repeated failures can exhaust the stream capacity permanently until the
> BPF program is freed.
> 
> Refactor bpf_stream_release_capacity() to take a length so the consume
> and release sides are symmetric, and use it to roll back the charge when
> creating the stream element fails.
> 
> [...]

Here is the summary with links:
  - [bpf-next,v4,1/5] bpf: roll back stream capacity when allocation fails
    https://git.kernel.org/bpf/bpf-next/c/bd2466ed8fc2
  - [bpf-next,v4,2/5] bpf: fix stream capacity leak in staging path
    https://git.kernel.org/bpf/bpf-next/c/effa6370ba89
  - [bpf-next,v4,3/5] bpf: return partial progress from bpf_stream_read on fault
    https://git.kernel.org/bpf/bpf-next/c/16790357a50b
  - [bpf-next,v4,4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG
    https://git.kernel.org/bpf/bpf-next/c/41c0348f6e65
  - [bpf-next,v4,5/5] selftests/bpf: cover stream capacity and partial read edge cases
    (no matching commit)

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] 10+ messages in thread

* Re: [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling
  2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
                     ` (4 preceding siblings ...)
  2026-08-23 14:17   ` [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases Jianlin Shi
@ 2026-08-23 19:22   ` Kumar Kartikeya Dwivedi
  5 siblings, 0 replies; 10+ messages in thread
From: Kumar Kartikeya Dwivedi @ 2026-08-23 19:22 UTC (permalink / raw)
  To: Jianlin Shi, bpf
  Cc: ast, daniel, andrii, martin.lau, eddyz87, song, yonghong.song,
	john.fastabend, kpsingh, sdf, haoluo, jolsa, emil, pulehui, shuah,
	linux-kselftest, linux-kernel

On Sun Aug 23, 2026 at 4:17 PM CEST, Jianlin Shi wrote:
> v3 addressed Kartikeya's review on v2 and the related Sashiko findings.
> v4 fixes the stream_oversize selftest to verify capacity rollback on the
> same BPF program stream, since streams live on prog->aux and are not
> shared across programs.
>
> Tested locally:
>   stream_oversize and stream_partial_read (equivalent to
>   ./test_progs -t stream_oversize,stream_partial_read).
>
> Changelog:
> v3 -> v4:
>   - In stream_oversize, perform the oversized bpf_stream_printk() and a
>     subsequent successful "foo" push in the same program; read that
>     program's stream in userspace instead of switching to stream_syscall.
>   - Drop a redundant vscnprintf() comment in bpf_stream_stage_printk().
>
> v2 -> v3:
>   - Refactor bpf_stream_release_capacity() to take a length.
>   - Fix staging-path capacity leak; use vscnprintf().
>   - Return partial bpf_stream_read() progress on copy_to_user() fault.
>   - Reject truncated bpf_stream_vprintk() output with -E2BIG.
>   - Add selftests for oversize and straddling-buffer partial read.
>
> v1 -> v2:
>   - Retarget to bpf-next as suggested by Pu Lehui.
>

Adjusted patch 5 for AI concerns for the selftests and applied. Will post a
separate fix for u32 concern. Thanks!

> Links:
> v3: https://lore.kernel.org/bpf/?q=%22PATCH+bpf-next+v3+0%2F5%22+fix+stream+capacity
> v2: https://lore.kernel.org/bpf/tencent_C919BB32458A4DAD645A68F441345B971E05@qq.com/
> v1: https://lore.kernel.org/bpf/tencent_E69EAE29327E25B3548A9AF3F4FA289A6806@qq.com/
>
> Jianlin Shi (5):
>   bpf: roll back stream capacity when allocation fails
>   bpf: fix stream capacity leak in staging path
>   bpf: return partial progress from bpf_stream_read on fault
>   bpf: reject oversized bpf_stream_vprintk output with -E2BIG
>   selftests/bpf: cover stream capacity and partial read edge cases
>
>  kernel/bpf/stream.c                           | 53 +++++++++------
>  .../testing/selftests/bpf/prog_tests/stream.c | 65 +++++++++++++++++++
>  tools/testing/selftests/bpf/progs/stream.c    | 18 +++++
>  3 files changed, 116 insertions(+), 20 deletions(-)


^ permalink raw reply	[flat|nested] 10+ messages in thread

end of thread, other threads:[~2026-08-23 19:22 UTC | newest]

Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
     [not found] <tencent_E69EAE29327E25B3548A9AF3F4FA289A6806@qq.com>
2026-08-23 14:17 ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Jianlin Shi
2026-08-23 14:17   ` [PATCH bpf-next v4 1/5] bpf: roll back stream capacity when allocation fails Jianlin Shi
2026-08-23 19:20     ` patchwork-bot+netdevbpf
2026-08-23 14:17   ` [PATCH bpf-next v4 2/5] bpf: fix stream capacity leak in staging path Jianlin Shi
2026-08-23 14:17   ` [PATCH bpf-next v4 3/5] bpf: return partial progress from bpf_stream_read on fault Jianlin Shi
2026-08-23 14:17   ` [PATCH bpf-next v4 4/5] bpf: reject oversized bpf_stream_vprintk output with -E2BIG Jianlin Shi
2026-08-23 15:10     ` bot+bpf-ci
2026-08-23 14:17   ` [PATCH bpf-next v4 5/5] selftests/bpf: cover stream capacity and partial read edge cases Jianlin Shi
2026-08-23 15:10     ` bot+bpf-ci
2026-08-23 19:22   ` [PATCH bpf-next v4 0/5] bpf: fix stream capacity, read, and oversize handling Kumar Kartikeya Dwivedi

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox