From: Yonghong Song <yonghong.song@linux.dev>
To: Arnaud Lecomte <contact@arnaud-lcm.com>,
song@kernel.org, jolsa@kernel.org, ast@kernel.org,
daniel@iogearbox.net, andrii@kernel.org, martin.lau@linux.dev,
eddyz87@gmail.com, john.fastabend@gmail.com, kpsingh@kernel.org,
sdf@fomichev.me, haoluo@google.com
Cc: bpf@vger.kernel.org, linux-kernel@vger.kernel.org,
syzkaller-bugs@googlegroups.com,
syzbot+c9b724fbb41cf2538b7b@syzkaller.appspotmail.com
Subject: Re: [PATCH v2] bpf: fix stackmap overflow check in __bpf_get_stackid()
Date: Tue, 5 Aug 2025 18:52:02 -0700 [thread overview]
Message-ID: <6cc26e1f-6ad6-44cd-a049-c4e7af9a229a@linux.dev> (raw)
In-Reply-To: <a0e172e9-e4d3-427f-b237-ba8f6b3772f4@arnaud-lcm.com>
On 8/5/25 1:49 PM, Arnaud Lecomte wrote:
> Hi,
> I gave it several tries and I can't find a nice to do see properly.
> The main challenge is to find a way to detect memory corruption. I
> wanted to place a canary value
> by tweaking the map size but we don't have a way from a BPF program
> perspective to access to the size
> of a stack_map_bucket. If we decide to do this computation manually,
> we would end-up with maintainability
> issues:
> #include "vmlinux.h"
> #include "bpf/bpf_helpers.h"
>
> #define MAX_STACK_DEPTH 32
> #define CANARY_VALUE 0xBADCAFE
>
> /* Calculate size based on known layout:
> * - fnode: sizeof(void*)
> * - hash: 4 bytes
> * - nr: 4 bytes
> * - data: MAX_STACK_DEPTH * 8 bytes
> * - canary: 8 bytes
> */
> #define VALUE_SIZE (sizeof(void*) + 4 + 4 + (MAX_STACK_DEPTH * 8) + 8)
>
> struct {
> __uint(type, BPF_MAP_TYPE_STACK_TRACE);
> __uint(max_entries, 1);
> __uint(value_size, VALUE_SIZE);
> __uint(key_size, sizeof(u32));
> } stackmap SEC(".maps");
>
> static __attribute__((noinline)) void recursive_helper(int depth) {
> if (depth <= 0) return;
> asm volatile("" ::: "memory");
> recursive_helper(depth - 1);
> }
>
> SEC("kprobe/do_sys_open")
> int test_stack_overflow(void *ctx) {
> u32 key = 0;
> u64 *stack = bpf_map_lookup_elem(&stackmap, &key);
> if (!stack) return 0;
>
> stack[MAX_STACK_DEPTH] = CANARY_VALUE;
>
> /* Force minimum stack depth */
> recursive_helper(MAX_STACK_DEPTH + 10);
>
> (void)bpf_get_stackid(ctx, &stackmap, 0);
> return 0;
> }
>
> char _license[] SEC("license") = "GPL";
It looks like it hard to trigger memory corruption inside the kernel.
Maybe kasan can detect it for your specific example.
If without selftests, you can do the following:
__bpf_get_stack() already solved the problem you tried to fix.
I suggest you refactor some portions of the code in __bpf_get_stack()
to set trace_nr properly, and then you can use that refactored function
in __bpf_get_stackid(). So two patches:
1. refactor portion of codes (related elem_size/trace_nr) in __bpf_get_stack().
2. fix the issue in __bpf_get_stackid() with newly created function.
>
> On 01/08/2025 19:16, Lecomte, Arnaud wrote:
>> Well, it turns out it is less straightforward than it looked like to
>> detect the memory corruption
>> without KASAN. I am currently in holidays for the next 3 days so
>> I've limited access to a
>> computer. I should be able to sort this out on monday.
>>
>> Thanks,
>> Arnaud
>>
>> On 30/07/2025 08:10, Arnaud Lecomte wrote:
>>> On 29/07/2025 23:45, Yonghong Song wrote:
>>>>
>>>>
>>>> On 7/29/25 9:56 AM, Arnaud Lecomte wrote:
>>>>> Syzkaller reported a KASAN slab-out-of-bounds write in
>>>>> __bpf_get_stackid()
>>>>> when copying stack trace data. The issue occurs when the perf trace
>>>>> contains more stack entries than the stack map bucket can hold,
>>>>> leading to an out-of-bounds write in the bucket's data array.
>>>>> For build_id mode, we use sizeof(struct bpf_stack_build_id)
>>>>> to determine capacity, and for normal mode we use sizeof(u64).
>>>>>
>>>>> Reported-by: syzbot+c9b724fbb41cf2538b7b@syzkaller.appspotmail.com
>>>>> Closes: https://syzkaller.appspot.com/bug?extid=c9b724fbb41cf2538b7b
>>>>> Tested-by: syzbot+c9b724fbb41cf2538b7b@syzkaller.appspotmail.com
>>>>> Signed-off-by: Arnaud Lecomte <contact@arnaud-lcm.com>
>>>>
>>>> Could you add a selftest? This way folks can easily find out what is
>>>> the problem and why this fix solves the issue correctly.
>>>>
>>> Sure, will be done after work
>>> Thanks,
>>> Arnaud
>>>>> ---
>>>>> Changes in v2:
>>>>> - Use utilty stack_map_data_size to compute map stack map size
>>>>> ---
>>>>> kernel/bpf/stackmap.c | 8 +++++++-
>>>>> 1 file changed, 7 insertions(+), 1 deletion(-)
>>>>>
>>>>> diff --git a/kernel/bpf/stackmap.c b/kernel/bpf/stackmap.c
>>>>> index 3615c06b7dfa..6f225d477f07 100644
>>>>> --- a/kernel/bpf/stackmap.c
>>>>> +++ b/kernel/bpf/stackmap.c
>>>>> @@ -230,7 +230,7 @@ static long __bpf_get_stackid(struct bpf_map
>>>>> *map,
>>>>> struct bpf_stack_map *smap = container_of(map, struct
>>>>> bpf_stack_map, map);
>>>>> struct stack_map_bucket *bucket, *new_bucket, *old_bucket;
>>>>> u32 skip = flags & BPF_F_SKIP_FIELD_MASK;
>>>>> - u32 hash, id, trace_nr, trace_len, i;
>>>>> + u32 hash, id, trace_nr, trace_len, i, max_depth;
>>>>> bool user = flags & BPF_F_USER_STACK;
>>>>> u64 *ips;
>>>>> bool hash_matches;
>>>>> @@ -241,6 +241,12 @@ static long __bpf_get_stackid(struct bpf_map
>>>>> *map,
>>>>> trace_nr = trace->nr - skip;
>>>>> trace_len = trace_nr * sizeof(u64);
>>>>> +
>>>>> + /* Clamp the trace to max allowed depth */
>>>>> + max_depth = smap->map.value_size / stack_map_data_size(map);
>>>>> + if (trace_nr > max_depth)
>>>>> + trace_nr = max_depth;
>>>>> +
>>>>> ips = trace->ip + skip;
>>>>> hash = jhash2((u32 *)ips, trace_len / sizeof(u32), 0);
>>>>> id = hash & (smap->n_buckets - 1);
>>>>
>>>>
next prev parent reply other threads:[~2025-08-06 1:52 UTC|newest]
Thread overview: 28+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-07-29 16:56 [PATCH v2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-07-29 22:45 ` Yonghong Song
2025-07-30 7:10 ` Arnaud Lecomte
2025-08-01 18:16 ` Lecomte, Arnaud
2025-08-05 20:49 ` Arnaud Lecomte
2025-08-06 1:52 ` Yonghong Song [this message]
2025-08-07 17:50 ` [PATCH 1/2] bpf: refactor max_depth computation in bpf_get_stack() Arnaud Lecomte
2025-08-07 17:52 ` [PATCH 2/2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-08-07 19:05 ` Yonghong Song
2025-08-07 19:01 ` [PATCH 1/2] bpf: refactor max_depth computation in bpf_get_stack() Yonghong Song
2025-08-07 19:07 ` Yonghong Song
2025-08-09 11:56 ` [PATCH v2 " Arnaud Lecomte
2025-08-09 11:58 ` [PATCH v2 2/2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-08-09 12:09 ` [PATCH RESEND v2 1/2] bpf: refactor max_depth computation in bpf_get_stack() Arnaud Lecomte
2025-08-09 12:14 ` [PATCH RESEND v2 2/2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-08-12 4:39 ` [PATCH RESEND v2 1/2] bpf: refactor max_depth computation in bpf_get_stack() Yonghong Song
2025-08-12 19:30 ` [PATCH bpf-next v3 " Arnaud Lecomte
2025-08-12 19:32 ` [PATCH bpf-next v3 2/2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-08-13 5:59 ` Yonghong Song
2025-08-13 20:46 ` [PATCH bpf-next v4 1/2] bpf: refactor max_depth computation in bpf_get_stack() Arnaud Lecomte
2025-08-13 20:55 ` [PATCH bpf-next v4 2/2] bpf: fix stackmap overflow check in __bpf_get_stackid() Arnaud Lecomte
2025-08-18 13:49 ` Lecomte, Arnaud
2025-08-18 16:57 ` Yonghong Song
2025-08-18 17:02 ` Yonghong Song
2025-08-19 16:20 ` Arnaud Lecomte
2025-08-13 5:54 ` [PATCH bpf-next v3 1/2] bpf: refactor max_depth computation in bpf_get_stack() Yonghong Song
2025-08-12 19:32 ` [PATCH RESEND v2 " Arnaud Lecomte
2025-08-08 7:30 ` [syzbot ci] " syzbot ci
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=6cc26e1f-6ad6-44cd-a049-c4e7af9a229a@linux.dev \
--to=yonghong.song@linux.dev \
--cc=andrii@kernel.org \
--cc=ast@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=contact@arnaud-lcm.com \
--cc=daniel@iogearbox.net \
--cc=eddyz87@gmail.com \
--cc=haoluo@google.com \
--cc=john.fastabend@gmail.com \
--cc=jolsa@kernel.org \
--cc=kpsingh@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=martin.lau@linux.dev \
--cc=sdf@fomichev.me \
--cc=song@kernel.org \
--cc=syzbot+c9b724fbb41cf2538b7b@syzkaller.appspotmail.com \
--cc=syzkaller-bugs@googlegroups.com \
/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.