diff options
| author | Jianlin Shi <shijianlin11@foxmail.com> | 2026-08-23 22:17:24 +0800 |
|---|---|---|
| committer | Kumar Kartikeya Dwivedi <memxor@gmail.com> | 2026-08-23 20:45:20 +0200 |
| commit | bd2466ed8fc2ee54408bfe433e75f9f46bfa04f7 (patch) | |
| tree | 05e8a98b34b1767aef42e60e69638116d4711341 /kernel | |
| parent | af22d273aa1f61fb86ec712b3ed785da73c3296e (diff) | |
| download | linux-next-bd2466ed8fc2ee54408bfe433e75f9f46bfa04f7.tar.gz linux-next-bd2466ed8fc2ee54408bfe433e75f9f46bfa04f7.zip | |
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.
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>
Link: https://lore.kernel.org/r/c0ad7b18c59be6695fcc9e4e1200b2f4d5cbbea2.1787492521.git.shijianlin11@foxmail.com
Signed-off-by: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Diffstat (limited to 'kernel')
| -rw-r--r-- | kernel/bpf/stream.c | 15 |
1 files 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); } |
