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 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.