bpf: Skip zero-length stream writes

A stream write whose formatted output is empty still allocates a stream
element and links it into the stream log. Capacity accounting only counts
payload bytes, so such elements never count against the stream limit, and a
program that keeps producing empty output allocates elements without bound
until a reader drains them.

Return success without allocating anything when there is nothing to write,
for both bpf_stream_vprintk() and staged writes. Every element in a stream
log then carries at least one byte, which later changes rely on when they
derive read readiness from published byte counts.

Fixes: 5ab154f146 ("bpf: Introduce BPF standard streams")
Suggested-by: Emil Tsalapatis <emil@etsalapatis.com>
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20260925045536.1480933-2-memxor@gmail.com
This commit is contained in:
Kumar Kartikeya Dwivedi 2026-09-25 06:55:28 +02:00 committed by Alexei Starovoitov
parent fff8738e87
commit f17bedcd29
No known key found for this signature in database

View File

@ -75,8 +75,13 @@ static void bpf_stream_release_capacity(struct bpf_stream *stream, int len)
static int bpf_stream_push_str(struct bpf_stream *stream, const char *str, int len)
{
int ret = bpf_stream_consume_capacity(stream, len);
int ret;
/* Nothing to publish; do not allocate an element for it. */
if (!len)
return 0;
ret = bpf_stream_consume_capacity(stream, len);
if (ret)
return ret;
@ -333,8 +338,8 @@ int bpf_stream_stage_printk(struct bpf_stream_stage *ss, const char *fmt, ...)
va_start(args, fmt);
len = vscnprintf(buf->buf, ARRAY_SIZE(buf->buf), fmt, args);
va_end(args);
/* Exclude NULL byte during push. */
ret = __bpf_stream_push_str(&ss->log, buf->buf, len);
/* Exclude NULL byte during push; skip empty output entirely. */
ret = len ? __bpf_stream_push_str(&ss->log, buf->buf, len) : 0;
if (!ret)
ss->len += len;
bpf_put_buffers();