From: sashiko-bot@kernel.org
To: "Alexei Starovoitov" <alexei.starovoitov@gmail.com>, bpf@vger.kernel.org
Subject: Re: [PATCH bpf-next v2 18/43] bpf: Bound the nesting that the BTF show code follows
Date: Sat, 17 Oct 2026 16:54:51 +0000 [thread overview]
Message-ID: <sashiko-outbox-175659@kernel.org> (raw)
In-Reply-To: <20261017163745.3341787-19-alexei.starovoitov@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [Medium] bpf: btf_show_obj_safe() clobbers -E2BIG from btf_show_start_aggr_type()
- [Medium] bpf: btf_show_start_array_type() leaks array_encoding on max depth return
--
commit 759371ec51181daa62496793db6556044a061470
Author: Josef Bacik <josef@toxicpanda.com>
bpf: Bound the nesting that the BTF show code follows
This patch limits BTF struct and array pretty-printing recursion to 32
levels (BTF_SHOW_MAX_DEPTH) to prevent kernel stack overflow when showing
deeply nested BTF types, recording -E2BIG in show->state.status when the
limit is reached.
> diff --git a/kernel/bpf/btf.c b/kernel/bpf/btf.c
> index 64c78434fa050..a9bf4c3c0a273 100644
> --- a/kernel/bpf/btf.c
> +++ b/kernel/bpf/btf.c
> @@ -1081,6 +1081,8 @@ static const struct btf_type *btf_type_skip_qualifiers(const struct btf *btf,
> }
>
> #define BTF_SHOW_MAX_ITER 10
> +/* nested structs and arrays shown; __btf_show_indent() has as many columns */
> +#define BTF_SHOW_MAX_DEPTH 32
>
> #define BTF_KIND_BIT(kind) (1ULL << kind)
>
> @@ -1474,8 +1476,18 @@ static void *btf_show_start_aggr_type(struct btf_show *show,
> const struct btf_type *t,
> u32 type_id, void *data)
> {
> - void *safe_data = btf_show_start_type(show, t, type_id, data);
> + void *safe_data;
>
> + /*
> + * Structs and arrays are shown by recursion. BTF loading bounds the
> + * depth of one resolve walk, not how deep resolved types may nest.
> + */
> + if (show->state.depth >= BTF_SHOW_MAX_DEPTH) {
> + show->state.status = -E2BIG;
> + return NULL;
> + }
[Severity: Medium]
Can show->state.status = -E2BIG be overwritten by subsequent members before
btf_type_snprintf_show() or btf_type_seq_show_flags() returns it?
Returning NULL from btf_show_start_aggr_type() only causes the current
__btf_struct_show() or __btf_array_show() call at BTF_SHOW_MAX_DEPTH to return
early. The enclosing __btf_struct_show() and __btf_array_show() loops at
shallower depths continue iterating over remaining members (and execute a
second pass when BTF_SHOW_ZERO is not set and a shallower member is non-zero).
When BTF_SHOW_UNSAFE is not set (such as in bpf_snprintf_btf() and
bpf_seq_printf_btf()), visiting a subsequent member outside the current
32-byte show->obj.safe window calls btf_show_start_type() ->
btf_show_obj_safe():
kernel/bpf/btf.c:btf_show_obj_safe() {
...
if (!safe) {
size_left = btf_show_obj_size_left(show, data);
if (size_left > BTF_SHOW_OBJ_SAFE_SIZE)
size_left = BTF_SHOW_OBJ_SAFE_SIZE;
show->state.status = copy_from_kernel_nofault(show->obj.safe,
data, size_left);
if (!show->state.status) {
show->obj.data = data;
safe = show->obj.safe;
}
}
...
}
When copy_from_kernel_nofault() succeeds on that later member, doesn't it
unconditionally reset show->state.status to 0, causing bpf_snprintf_btf() and
bpf_seq_printf_btf() to return success with truncated output instead of
-E2BIG?
[Severity: Medium]
Also, what happens to show->state.array_encoding when an array of 1-byte
integers hits BTF_SHOW_MAX_DEPTH?
In __btf_array_show(), btf_show_start_array_type() sets
show->state.array_encoding before calling btf_show_start_aggr_type():
kernel/bpf/btf.c:btf_show_start_array_type() {
show->state.array_encoding = array_encoding;
show->state.array_terminated = 0;
return btf_show_start_aggr_type(show, t, type_id, data);
}
When btf_show_start_aggr_type() returns NULL at BTF_SHOW_MAX_DEPTH,
__btf_array_show() returns early without calling btf_show_end_array_type() to
reset show->state.array_encoding to 0:
kernel/bpf/btf.c:__btf_array_show() {
...
if (!btf_show_start_array_type(show, t, type_id, encoding, data))
return;
...
btf_show_end_array_type(show);
}
If the skipped array had 1-byte integer elements (encoding == BTF_INT_CHAR),
won't show->state.array_encoding remain BTF_INT_CHAR while enclosing structs
continue printing shallower members, causing btf_int_show() to format
subsequent non-array 8-bit integer fields as character literals and treat any
zero byte as a NUL terminator that sets show->state.array_terminated = 1 and
suppresses remaining 8-bit integer fields?
> +
> + safe_data = btf_show_start_type(show, t, type_id, data);
> if (!safe_data)
> return safe_data;
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261017163745.3341787-1-alexei.starovoitov@gmail.com?part=18
next prev parent reply other threads:[~2026-10-17 16:54 UTC|newest]
Thread overview: 60+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-17 16:37 [PATCH bpf-next v2 00/43] bpf: Memory safety, lifetime and locking fixes Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 01/43] bpf: use the frame mem type in devmap egress XDP Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 02/43] bpf: forbid sleeping in hash map for_each callbacks Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 03/43] bpf: don't leak the inode when token creation fails Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 04/43] bpf: don't hand out a linked element as extra element Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 05/43] bpf: reject sleepable programs for task_vma iterator Alexei Starovoitov
2026-10-17 17:16 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 06/43] bpf: forbid sleeping in bpf_find_vma() callbacks Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 07/43] bpf: look at all 64 bits of a BPF_JSET mask on 32-bit Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 08/43] bpf: don't let bpf_skb_adjust_room() use up the MSS Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 09/43] bpf: Read the probe of a perf event under event_mutex Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 10/43] bpf: Don't saturate owner_refcnt on the last unpin Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 11/43] bpf: Validate the SRH which End.DT6 uncovers in End.BPF Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 12/43] bpf: Pull the inner header for End.DT6 " Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 13/43] bpf: Update the SRH state if End.B6 fails late Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 14/43] bpf: Clear sk_refcnt of a clone before its storage is linked Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 15/43] bpf: Fix NULL deref in the sk_storage map iterator Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 16/43] bpf: Link the first element after its storage is published Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 17/43] bpf: Hold the socket in the sk_storage map iterator Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 18/43] bpf: Bound the nesting that the BTF show code follows Alexei Starovoitov
2026-10-17 16:54 ` sashiko-bot [this message]
2026-10-17 16:37 ` [PATCH bpf-next v2 19/43] bpf: Check the new program of an iterator link update Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 20/43] bpf: Fix stale offload->prog pointer after realloc Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 21/43] bpf: Don't bind a program to a netdev that goes away Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 22/43] bpf: Keep a program until its bpf_wq callback has ended Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 23/43] bpf: Count sleepable callbacks as sleepable map users Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 24/43] bpf: Check the maps that sleepable callbacks use Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 25/43] bpf: Assume no bounds for buffers behind a tail call Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 26/43] bpf: Don't take an extension for an iterator program Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 27/43] bpf: Assume no bounds for a writable tp with tail calls Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 28/43] bpf: Don't take an extension for a writable raw tracepoint program Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 29/43] bpf: Keep iterator programs off special map fields Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 30/43] bpf: Free what map_free() unlinks for sleepable readers Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 31/43] bpf: Keep values of a dead owner for sleepable programs Alexei Starovoitov
2026-10-17 17:06 ` sashiko-bot
2026-10-17 16:37 ` [PATCH bpf-next v2 32/43] bpf: Don't take an extension for a function that runs sleepable Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 33/43] bpf: Keep the symbols of a program until it has ended Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 34/43] bpf: Use the socket of a sk_lookup test run under RCU Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 35/43] bpf, cpumap: Hold the device of frames in the queue Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 36/43] bpf: Drop packet pointers behind kfuncs writing an skb Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 37/43] bpf: Let bpf_dynptr_write() mark a global function Alexei Starovoitov
2026-10-17 17:04 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 38/43] bpf: Don't take a dynptr argument for a local dynptr Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 39/43] bpf: Refuse the prologue for an extension that cannot take it Alexei Starovoitov
2026-10-17 17:08 ` sashiko-bot
2026-10-17 17:16 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 40/43] bpf: Unclone the skb for kfuncs that write through a dynptr Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 41/43] bpf: Follow the head if an skb is written from a slice Alexei Starovoitov
2026-10-17 16:37 ` [PATCH bpf-next v2 42/43] bpf: Use memmove() to store bytes in an skb Alexei Starovoitov
2026-10-17 17:16 ` bot+bpf-ci
2026-10-17 16:37 ` [PATCH bpf-next v2 43/43] bpf: Refuse packet slices for packet-changing helpers Alexei Starovoitov
2026-10-17 17:17 ` bot+bpf-ci
2026-10-17 22:10 ` [PATCH bpf-next v2 00/43] bpf: Memory safety, lifetime and locking fixes patchwork-bot+netdevbpf
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-175659@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=alexei.starovoitov@gmail.com \
--cc=bpf@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox