* [PATCH bpf] bpf: roll back stream capacity when allocation fails
@ 2026-07-20 1:23 Jianlin Shi
2026-07-20 1:35 ` sashiko-bot
` (2 more replies)
0 siblings, 3 replies; 6+ messages in thread
From: Jianlin Shi @ 2026-07-20 1:23 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, memxor, 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.
Roll back the capacity 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 | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index be9ce98e9..4b8a74b91 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -79,7 +79,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)
+ atomic_sub(len, &stream->capacity);
+
+ return ret;
}
static struct bpf_stream *bpf_stream_get(enum bpf_stream_id stream_id, struct bpf_prog_aux *aux)
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf] bpf: roll back stream capacity when allocation fails
2026-07-20 1:23 [PATCH bpf] bpf: roll back stream capacity when allocation fails Jianlin Shi
@ 2026-07-20 1:35 ` sashiko-bot
2026-07-20 3:40 ` Pu Lehui
2026-07-20 5:13 ` [PATCH bpf-next v2] " Jianlin Shi
2 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-07-20 1:35 UTC (permalink / raw)
To: Jianlin Shi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
Pre-existing issues:
- [High] The patch addresses a capacity leak in `bpf_stream_push_str()` when stream element allocation fails, but entirely misses the identical capacity leak in the staging logic (`bpf_stream_stage_printk()` and `bpf_stream_stage_commit()`).
- [High] If copy_to_user() fails during bpf_stream_read() after some elements have already been consumed, the function returns -EFAULT instead of the number of bytes successfully read, resulting in silent data loss.
--
--- Patch [1]: [PATCH bpf] bpf: roll back stream capacity when allocation fails ---
commit 06c82cbb65aa09c192205a6718b0fa398300f1ac
Author: Jianlin Shi <shijianlin11@foxmail.com>
bpf: roll back stream capacity when allocation fails
The patch fixes a stream capacity leak in bpf_stream_push_str().
If allocating a stream element fails, the previously charged capacity
is now rolled back to avoid permanent exhaustion.
> diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
> index be9ce98e94692..4b8a74b9162e1 100644
> --- a/kernel/bpf/stream.c
> +++ b/kernel/bpf/stream.c
> @@ -79,7 +79,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)
> + atomic_sub(len, &stream->capacity);
> +
> + return ret;
> }
[Severity: High]
This isn't a bug introduced by this patch, but it seems there's an identical
capacity leak in the staging logic that this patch doesn't address.
In bpf_stream_stage_printk(), ss->len is unconditionally incremented even if
allocation fails:
kernel/bpf/stream.c:bpf_stream_stage_printk() {
...
ss->len += ret;
/* Exclude NULL byte during push. */
ret = __bpf_stream_push_str(&ss->log, buf->buf, ret);
...
}
Then in include/linux/bpf.h, the bpf_stream_stage() macro unconditionally
calls bpf_stream_stage_commit():
#define bpf_stream_stage(ss, prog, stream_id, expr) \
({ \
bpf_stream_stage_init(&ss); \
(expr); \
bpf_stream_stage_commit(&ss, prog, stream_id); \
bpf_stream_stage_free(&ss); \
})
Which then permanently charges the falsely inflated length against the capacity:
kernel/bpf/stream.c:bpf_stream_stage_commit() {
...
ret = bpf_stream_consume_capacity(stream, ss->len);
...
}
Should the staging logic also be updated to prevent permanently leaking
stream capacity when memory allocation fails?
[Severity: High]
This is a pre-existing issue, but I noticed another problem related to how
stream errors are handled in bpf_stream_read() when copy_to_user() fails.
If some elements are successfully consumed and freed:
kernel/bpf/stream.c:bpf_stream_read() {
...
bpf_stream_backlog_pop(stream);
bpf_stream_release_capacity(stream, elem);
bpf_stream_free_elem(elem);
...
}
But a subsequent copy_to_user() fails on an unmapped page, the function returns
-EFAULT unconditionally:
...
mutex_unlock(&stream->lock);
return ret ? ret : len - rem_len;
}
Does this mean the successfully copied elements from earlier loop iterations
are permanently lost without the reader knowing how many bytes were read?
Should it return the bytes successfully read (len - rem_len) when some
elements were already consumed?
--
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_E69EAE29327E25B3548A9AF3F4FA289A6806@qq.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf] bpf: roll back stream capacity when allocation fails
2026-07-20 1:23 [PATCH bpf] bpf: roll back stream capacity when allocation fails Jianlin Shi
2026-07-20 1:35 ` sashiko-bot
@ 2026-07-20 3:40 ` Pu Lehui
2026-07-20 5:13 ` Jianlin Shi
2026-07-20 5:13 ` [PATCH bpf-next v2] " Jianlin Shi
2 siblings, 1 reply; 6+ messages in thread
From: Pu Lehui @ 2026-07-20 3:40 UTC (permalink / raw)
To: Jianlin Shi, bpf; +Cc: ast, daniel, andrii, memxor, linux-kernel
On 2026/7/20 9:23, Jianlin Shi 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.
>
> Roll back the capacity 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 | 9 ++++++++-
> 1 file changed, 8 insertions(+), 1 deletion(-)
>
> diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
> index be9ce98e9..4b8a74b91 100644
> --- a/kernel/bpf/stream.c
> +++ b/kernel/bpf/stream.c
> @@ -79,7 +79,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)
> + atomic_sub(len, &stream->capacity);
> +
> + return ret;
> }
>
> static struct bpf_stream *bpf_stream_get(enum bpf_stream_id stream_id, struct bpf_prog_aux *aux)
looks good to me, but it might be better to target bpf-next, as this
isn't a critical issue.
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [PATCH bpf] bpf: roll back stream capacity when allocation fails
2026-07-20 3:40 ` Pu Lehui
@ 2026-07-20 5:13 ` Jianlin Shi
0 siblings, 0 replies; 6+ messages in thread
From: Jianlin Shi @ 2026-07-20 5:13 UTC (permalink / raw)
To: pulehui; +Cc: bpf, ast, daniel, andrii, memxor, linux-kernel
On 2026/7/20 11:40, Pu Lehui wrote:
> looks good to me, but it might be better to target bpf-next, as this
> isn't a critical issue.
Thanks for the review. Will resend as v2 targeting bpf-next.
Thanks,
Jianlin
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH bpf-next v2] bpf: roll back stream capacity when allocation fails
2026-07-20 1:23 [PATCH bpf] bpf: roll back stream capacity when allocation fails Jianlin Shi
2026-07-20 1:35 ` sashiko-bot
2026-07-20 3:40 ` Pu Lehui
@ 2026-07-20 5:13 ` Jianlin Shi
2026-07-20 5:26 ` sashiko-bot
2 siblings, 1 reply; 6+ messages in thread
From: Jianlin Shi @ 2026-07-20 5:13 UTC (permalink / raw)
To: bpf; +Cc: ast, daniel, andrii, memxor, pulehui, 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.
Roll back the capacity charge when creating the stream element fails.
Fixes: 5ab154f1463a ("bpf: Introduce BPF standard streams")
Signed-off-by: Jianlin Shi <shijianlin11@foxmail.com>
---
v2:
- Retarget to bpf-next as suggested by Pu Lehui.
kernel/bpf/stream.c | 9 ++++++++-
1 file changed, 8 insertions(+), 1 deletion(-)
diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
index be9ce98e9..4b8a74b91 100644
--- a/kernel/bpf/stream.c
+++ b/kernel/bpf/stream.c
@@ -79,7 +79,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)
+ atomic_sub(len, &stream->capacity);
+
+ return ret;
}
static struct bpf_stream *bpf_stream_get(enum bpf_stream_id stream_id, struct bpf_prog_aux *aux)
--
2.43.0
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH bpf-next v2] bpf: roll back stream capacity when allocation fails
2026-07-20 5:13 ` [PATCH bpf-next v2] " Jianlin Shi
@ 2026-07-20 5:26 ` sashiko-bot
0 siblings, 0 replies; 6+ messages in thread
From: sashiko-bot @ 2026-07-20 5:26 UTC (permalink / raw)
To: Jianlin Shi; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 3 potential issue(s) to consider:
Pre-existing issues:
- [High] The patch fixes a capacity leak in `bpf_stream_push_str()` when stream element allocation fails, but misses an identical leak in `bpf_stream_stage_printk()`.
- [High] `bpf_stream_read` drops successfully read data if a subsequent `copy_to_user` fails, violating API contracts.
- [Medium] Log messages are entirely dropped and return an error instead of pushing the truncated message when the formatted output exceeds the internal string buffer size.
--
--- Patch [1]: [PATCH bpf-next v2] bpf: roll back stream capacity when allocation fails ---
commit 3fa8598d2b8afa51091cf463bee21d3c9f140975
Author: Jianlin Shi <shijianlin11@foxmail.com>
bpf: roll back stream capacity when allocation fails
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.
Roll back the capacity charge when creating the stream element fails.
> diff --git a/kernel/bpf/stream.c b/kernel/bpf/stream.c
> index be9ce98e94692..4b8a74b9162e1 100644
> --- a/kernel/bpf/stream.c
> +++ b/kernel/bpf/stream.c
> @@ -79,7 +79,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)
> + atomic_sub(len, &stream->capacity);
> +
> + return ret;
> }
[Severity: High]
This is a pre-existing issue, but does bpf_stream_stage_printk() suffer from
the identical capacity leak that this patch fixes here?
Looking at bpf_stream_stage_printk():
kernel/bpf/stream.c:bpf_stream_stage_printk() {
...
ss->len += ret;
/* Exclude NULL byte during push. */
ret = __bpf_stream_push_str(&ss->log, buf->buf, ret);
...
}
If __bpf_stream_push_str() fails to allocate memory, ss->len remains incremented.
Later, bpf_stream_stage_commit() unconditionally consumes this erroneously
inflated ss->len from the stream capacity:
kernel/bpf/stream.c:bpf_stream_stage_commit() {
...
ret = bpf_stream_consume_capacity(stream, ss->len);
if (ret)
return ret;
...
}
Since the failed element isn't in the log, its length will never be released,
which could permanently leak stream capacity over time.
[Severity: Medium]
This is a pre-existing issue, but what happens if the formatted output exceeds
the internal string buffer size?
Both bstr_printf() and vsnprintf() return the number of characters that would
have been written, not the actual number written.
For example, in bpf_stream_vprintk():
kernel/bpf/stream.c:bpf_stream_vprintk() {
...
ret = bstr_printf(data.buf, MAX_BPRINTF_BUF, fmt__str, data.bin_args);
/* Exclude NULL byte during push. */
ret = bpf_stream_push_str(stream, data.buf, ret);
...
}
If the string is truncated, the un-capped return value is passed as len to
bpf_stream_push_str(). Since bpf_stream_elem_alloc() has a strict bounds check,
it will reject the allocation and return -ENOMEM.
Does this mean the entire log message is dropped instead of safely pushing the
truncated message prefix?
[Severity: High]
This is a pre-existing issue, but does bpf_stream_read() permanently drop data
if a subsequent copy_to_user() fails?
In bpf_stream_read():
kernel/bpf/stream.c:bpf_stream_read() {
...
/* Restore in case of error. */
if (ret) {
ret = -EFAULT;
elem->consumed_len = cons_len;
break;
}
...
return ret ? ret : len - rem_len;
}
If copy_to_user() fails on a subsequent element in the loop, it breaks and
unconditionally returns -EFAULT.
Since elements that were successfully read in previous iterations have already
been popped and freed, returning an error instead of the number of successfully
read bytes hides the fact that partial data was consumed.
Will retrying the read operation cause the previously read data to be
permanently lost?
--
Sashiko AI review · https://sashiko.dev/#/patchset/tencent_C919BB32458A4DAD645A68F441345B971E05@qq.com?part=1
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2026-07-20 5:26 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-07-20 1:23 [PATCH bpf] bpf: roll back stream capacity when allocation fails Jianlin Shi
2026-07-20 1:35 ` sashiko-bot
2026-07-20 3:40 ` Pu Lehui
2026-07-20 5:13 ` Jianlin Shi
2026-07-20 5:13 ` [PATCH bpf-next v2] " Jianlin Shi
2026-07-20 5:26 ` sashiko-bot
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.