* XDP BPF JIT memory leak on armv7
@ 2026-04-16 14:05 Jonas Rebmann
2026-04-16 14:36 ` Daniel Borkmann
0 siblings, 1 reply; 7+ messages in thread
From: Jonas Rebmann @ 2026-04-16 14:05 UTC (permalink / raw)
To: Alexei Starovoitov, Daniel Borkmann, Russell King, Puranjay Mohan
Cc: bpf, linux-kernel, kernel
Hello,
We have observed a memory leak when using the JIT on armv7 with XDP
programs in all kernels tested (6.1 to v7.0/master).
kmemleak reports:
unreferenced object 0xbf0a1000 (size 4096):
comm "ping", pid 818, jiffies 4294949376
hex dump (first 32 bytes):
00 10 00 00 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................
f1 de fd e7 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................
backtrace (crc 38a5ba95):
kmemleak_vmalloc+0x38/0x94
__vmalloc_node_range_noprof+0x624/0x7e0
execmem_alloc+0x7c/0x100
bpf_jit_binary_alloc+0x64/0xfc
bpf_int_jit_compile+0x14c/0x348
bpf_jit_subprogs+0x4fc/0xa60
bpf_check+0x1840/0x30e0
bpf_prog_load+0x720/0xec4
__sys_bpf+0x4cc/0x25d4
ret_fast_syscall+0x0/0x54
This was reproduced on various debian systems:
- stock debian sid with 6.19.12+deb14-armmp-lpae
- stock debian 12 with 6.1.0-44-armmp-lpae
As well as debian sid with custom built kernels with a
multi_v7_defconfig based config, amongst versions tested: latest master,
(7.0.0-08391-g1d51b370a0f8), v7.0, v6.18, v6.8, v6.12.
Precise reproduction steps:
Enable the BPF JIT (if not done via CONFIG_BPF_JIT_ALWAYS_ON=y):
# sysctl -w net.core.bpf_jit_enable=1
Prepare any simple XDP program:
$ git clone https://github.com/xdp-project/xdp-tutorial.git
$ cd xdp-tutorial
# apt install git cmake build-essential xdp-tools clang pkg-config libelf-dev m4 libpcap-dev llvm libbpf-dev libxdp-dev
$ ln -s /usr/include/arm-linux-gnueabihf/gnu/stubs-hard.h /usr/include/arm-linux-gnueabihf/gnu/stubs-soft.h
$ ./configure
$ cd basic01-xdp-pass
$ make
Store /proc/vmallocinfo:
# cat /proc/vmallocinfo > /tmp/vmallocinfo-before
Load the program and confirm it is loaded, unload and confirm:
# ./xdp_pass_user -d lo
# xdp-loader status
lo xdp_prog_simple skb 83 d4f8542f2b42fac5
# ./xdp_pass_user -d lo --unload-all
# xdp-loader status
lo <No XDP program loaded!>
Compare /proc/vmallocinfo:
# cat /proc/vmallocinfo > /tmp/vmallocinfo-after
# diff -u <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-before) <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-after)
+0x4e292a08-0xae3e49c0 8192 bpf_jit_binary_alloc+0x64/0xfc pages=1 vmalloc
# echo scan > /sys/kernel/debug/kmemleak
# cat /sys/kernel/debug/kmemleak
[see above]
The backtrace corresponds in commit 1d51b370a0f8 to
mm/kmemleak.c:596
mm/vmalloc.c:4093
mm/execmem.c:44
kernel/bpf/core.c:1093
arch/arm/net/bpf_jit_32.c:2241
kernel/bpf/fixups.c:1122
kernel/bpf/verifier.c:20099
kernel/bpf/syscall.c:3083
kernel/bpf/syscall.c:6252
arch/arm/kernel/entry-common.S:44
Each subsequent run introduces an additional leak.
Thanks,
Jonas
^ permalink raw reply [flat|nested] 7+ messages in thread* Re: XDP BPF JIT memory leak on armv7 2026-04-16 14:05 XDP BPF JIT memory leak on armv7 Jonas Rebmann @ 2026-04-16 14:36 ` Daniel Borkmann 2026-04-16 15:58 ` Puranjay Mohan 0 siblings, 1 reply; 7+ messages in thread From: Daniel Borkmann @ 2026-04-16 14:36 UTC (permalink / raw) To: Jonas Rebmann, Alexei Starovoitov, Russell King, Puranjay Mohan Cc: bpf, linux-kernel, kernel Hi Jonas, On 4/16/26 4:05 PM, Jonas Rebmann wrote: > Hello, > > We have observed a memory leak when using the JIT on armv7 with XDP > programs in all kernels tested (6.1 to v7.0/master). > > kmemleak reports: > > unreferenced object 0xbf0a1000 (size 4096): > comm "ping", pid 818, jiffies 4294949376 > hex dump (first 32 bytes): > 00 10 00 00 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................ > f1 de fd e7 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................ > backtrace (crc 38a5ba95): > kmemleak_vmalloc+0x38/0x94 > __vmalloc_node_range_noprof+0x624/0x7e0 > execmem_alloc+0x7c/0x100 > bpf_jit_binary_alloc+0x64/0xfc > bpf_int_jit_compile+0x14c/0x348 > bpf_jit_subprogs+0x4fc/0xa60 > bpf_check+0x1840/0x30e0 > bpf_prog_load+0x720/0xec4 > __sys_bpf+0x4cc/0x25d4 > ret_fast_syscall+0x0/0x54 > > This was reproduced on various debian systems: > - stock debian sid with 6.19.12+deb14-armmp-lpae > - stock debian 12 with 6.1.0-44-armmp-lpae > > As well as debian sid with custom built kernels with a > multi_v7_defconfig based config, amongst versions tested: latest master, > (7.0.0-08391-g1d51b370a0f8), v7.0, v6.18, v6.8, v6.12. > > Precise reproduction steps: > Enable the BPF JIT (if not done via CONFIG_BPF_JIT_ALWAYS_ON=y): > # sysctl -w net.core.bpf_jit_enable=1 > > Prepare any simple XDP program: > $ git clone https://github.com/xdp-project/xdp-tutorial.git > $ cd xdp-tutorial > # apt install git cmake build-essential xdp-tools clang pkg-config libelf-dev m4 libpcap-dev llvm libbpf-dev libxdp-dev > $ ln -s /usr/include/arm-linux-gnueabihf/gnu/stubs-hard.h /usr/include/arm-linux-gnueabihf/gnu/stubs-soft.h > $ ./configure > $ cd basic01-xdp-pass > $ make > > Store /proc/vmallocinfo: > # cat /proc/vmallocinfo > /tmp/vmallocinfo-before > > Load the program and confirm it is loaded, unload and confirm: > # ./xdp_pass_user -d lo > # xdp-loader status > lo xdp_prog_simple skb 83 d4f8542f2b42fac5 > # ./xdp_pass_user -d lo --unload-all > # xdp-loader status > lo <No XDP program loaded!> > > Compare /proc/vmallocinfo: > # cat /proc/vmallocinfo > /tmp/vmallocinfo-after > # diff -u <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-before) <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-after) > +0x4e292a08-0xae3e49c0 8192 bpf_jit_binary_alloc+0x64/0xfc pages=1 vmalloc > > # echo scan > /sys/kernel/debug/kmemleak > # cat /sys/kernel/debug/kmemleak > [see above] > > The backtrace corresponds in commit 1d51b370a0f8 to > > mm/kmemleak.c:596 > mm/vmalloc.c:4093 > mm/execmem.c:44 > kernel/bpf/core.c:1093 > arch/arm/net/bpf_jit_32.c:2241 > kernel/bpf/fixups.c:1122 > kernel/bpf/verifier.c:20099 > kernel/bpf/syscall.c:3083 > kernel/bpf/syscall.c:6252 > arch/arm/kernel/entry-common.S:44 > > Each subsequent run introduces an additional leak. I don't have access to arm32, but it looks like its completely missing the ability to do BPF to BPF calls.. you would need something like the below (uncompiled / untested). It would actually be nice to you have any chance to run through the BPF selftests to see what else is broken on arm32. Outside of x86-64, arm64, riscv64 and s390x BPF JITs the results might vary quite a lot on what works and what doesn't. :/ diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index deeb8f292454..89b24fe357aa 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -216,6 +216,12 @@ struct jit_ctx { #endif }; +struct arm_jit_data { + struct jit_ctx ctx; + struct bpf_binary_header *header; + u8 *image_ptr; +}; + /* * Wrappers which handle both OABI and EABI and assures Thumb2 interworking * (where the assembly routines like __aeabi_uidiv could cause problems). @@ -2146,7 +2152,9 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) { struct bpf_prog *tmp, *orig_prog = prog; struct bpf_binary_header *header; + struct arm_jit_data *jit_data; bool tmp_blinded = false; + bool extra_pass = false; struct jit_ctx ctx; unsigned int tmp_idx; unsigned int image_size; @@ -2171,6 +2179,24 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog = tmp; } + jit_data = prog->aux->jit_data; + if (!jit_data) { + jit_data = kzalloc(sizeof(*jit_data), GFP_KERNEL); + if (!jit_data) { + prog = orig_prog; + goto out; + } + prog->aux->jit_data = jit_data; + } + if (jit_data->ctx.offsets) { + ctx = jit_data->ctx; + image_ptr = jit_data->image_ptr; + header = jit_data->header; + extra_pass = true; + image_size = sizeof(u32) * ctx.idx; + goto skip_init_ctx; + } + memset(&ctx, 0, sizeof(ctx)); ctx.prog = prog; ctx.cpu_architecture = cpu_architecture(); @@ -2181,7 +2207,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) ctx.offsets = kcalloc(prog->len, sizeof(int), GFP_KERNEL); if (ctx.offsets == NULL) { prog = orig_prog; - goto out; + goto out_off; } /* 1) fake pass to find in the length of the JITed code, @@ -2243,6 +2269,7 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) goto out_imms; } +skip_init_ctx: /* 2.) Actual pass to generate final JIT code */ ctx.target = (u32 *) image_ptr; ctx.idx = 0; @@ -2271,13 +2298,21 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_prog *prog) prog->jited = 1; prog->jited_len = image_size; + if (!prog->is_func || extra_pass) { out_imms: #if __LINUX_ARM_ARCH__ < 7 - if (ctx.imm_count) - kfree(ctx.imms); + if (ctx.imm_count) + kfree(ctx.imms); #endif out_off: - kfree(ctx.offsets); + kfree(ctx.offsets); + kfree(jit_data); + prog->aux->jit_data = NULL; + } else { + jit_data->ctx = ctx; + jit_data->image_ptr = image_ptr; + jit_data->header = header; + } out: if (tmp_blinded) bpf_jit_prog_release_other(prog, prog == orig_prog ? -- 2.43.0 ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: XDP BPF JIT memory leak on armv7 2026-04-16 14:36 ` Daniel Borkmann @ 2026-04-16 15:58 ` Puranjay Mohan 2026-04-17 9:47 ` Jonas Rebmann 0 siblings, 1 reply; 7+ messages in thread From: Puranjay Mohan @ 2026-04-16 15:58 UTC (permalink / raw) To: Daniel Borkmann Cc: Jonas Rebmann, Alexei Starovoitov, Russell King, bpf, linux-kernel, kernel On Thu, Apr 16, 2026 at 3:36 PM Daniel Borkmann <daniel@iogearbox.net> wrote: > > Hi Jonas, > > On 4/16/26 4:05 PM, Jonas Rebmann wrote: > > Hello, > > > > We have observed a memory leak when using the JIT on armv7 with XDP > > programs in all kernels tested (6.1 to v7.0/master). > > > > kmemleak reports: > > > > unreferenced object 0xbf0a1000 (size 4096): > > comm "ping", pid 818, jiffies 4294949376 > > hex dump (first 32 bytes): > > 00 10 00 00 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................ > > f1 de fd e7 f1 de fd e7 f1 de fd e7 f1 de fd e7 ................ > > backtrace (crc 38a5ba95): > > kmemleak_vmalloc+0x38/0x94 > > __vmalloc_node_range_noprof+0x624/0x7e0 > > execmem_alloc+0x7c/0x100 > > bpf_jit_binary_alloc+0x64/0xfc > > bpf_int_jit_compile+0x14c/0x348 > > bpf_jit_subprogs+0x4fc/0xa60 > > bpf_check+0x1840/0x30e0 > > bpf_prog_load+0x720/0xec4 > > __sys_bpf+0x4cc/0x25d4 > > ret_fast_syscall+0x0/0x54 > > > > This was reproduced on various debian systems: > > - stock debian sid with 6.19.12+deb14-armmp-lpae > > - stock debian 12 with 6.1.0-44-armmp-lpae > > > > As well as debian sid with custom built kernels with a > > multi_v7_defconfig based config, amongst versions tested: latest master, > > (7.0.0-08391-g1d51b370a0f8), v7.0, v6.18, v6.8, v6.12. > > > > Precise reproduction steps: > > Enable the BPF JIT (if not done via CONFIG_BPF_JIT_ALWAYS_ON=y): > > # sysctl -w net.core.bpf_jit_enable=1 > > > > Prepare any simple XDP program: > > $ git clone https://github.com/xdp-project/xdp-tutorial.git > > $ cd xdp-tutorial > > # apt install git cmake build-essential xdp-tools clang pkg-config libelf-dev m4 libpcap-dev llvm libbpf-dev libxdp-dev > > $ ln -s /usr/include/arm-linux-gnueabihf/gnu/stubs-hard.h /usr/include/arm-linux-gnueabihf/gnu/stubs-soft.h > > $ ./configure > > $ cd basic01-xdp-pass > > $ make > > > > Store /proc/vmallocinfo: > > # cat /proc/vmallocinfo > /tmp/vmallocinfo-before > > > > Load the program and confirm it is loaded, unload and confirm: > > # ./xdp_pass_user -d lo > > # xdp-loader status > > lo xdp_prog_simple skb 83 d4f8542f2b42fac5 > > # ./xdp_pass_user -d lo --unload-all > > # xdp-loader status > > lo <No XDP program loaded!> > > > > Compare /proc/vmallocinfo: > > # cat /proc/vmallocinfo > /tmp/vmallocinfo-after > > # diff -u <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-before) <(grep bpf_jit_binary_alloc /tmp/vmallocinfo-after) > > +0x4e292a08-0xae3e49c0 8192 bpf_jit_binary_alloc+0x64/0xfc pages=1 vmalloc > > > > # echo scan > /sys/kernel/debug/kmemleak > > # cat /sys/kernel/debug/kmemleak > > [see above] > > > > The backtrace corresponds in commit 1d51b370a0f8 to > > > > mm/kmemleak.c:596 > > mm/vmalloc.c:4093 > > mm/execmem.c:44 > > kernel/bpf/core.c:1093 > > arch/arm/net/bpf_jit_32.c:2241 > > kernel/bpf/fixups.c:1122 > > kernel/bpf/verifier.c:20099 > > kernel/bpf/syscall.c:3083 > > kernel/bpf/syscall.c:6252 > > arch/arm/kernel/entry-common.S:44 > > > > Each subsequent run introduces an additional leak. > I don't have access to arm32, but it looks like its completely missing the > ability to do BPF to BPF calls.. you would need something like the below > (uncompiled / untested). I think the problem is that BPF to BPF calls are not supported but the JIT doesn't reject them as well, so the best way to fix this would be to do: diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c index deeb8f292454..91fef10e88bc 100644 --- a/arch/arm/net/bpf_jit_32.c +++ b/arch/arm/net/bpf_jit_32.c @@ -2047,6 +2047,8 @@ static int build_insn(const struct bpf_insn *insn, struct jit_ctx *ctx) /* function call */ case BPF_JMP | BPF_CALL: { + if (insn->src_reg == BPF_PSEUDO_CALL) + goto notyet; const s8 *r0 = bpf2a32[BPF_REG_0]; const s8 *r1 = bpf2a32[BPF_REG_1]; const s8 *r2 = bpf2a32[BPF_REG_2]; This will cause the memory to be freed properly. > It would actually be nice to you have any chance to run through the BPF > selftests to see what else is broken on arm32. Outside of x86-64, arm64, > riscv64 and s390x BPF JITs the results might vary quite a lot on what works > and what doesn't. :/ I will do that soon when I get some time, the selftests won't easily compile for 32-bit archs as pointers are 32-bit and bpf pointers are 64 bit, etc. etc. [..] Thanks, Puranjay ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: XDP BPF JIT memory leak on armv7 2026-04-16 15:58 ` Puranjay Mohan @ 2026-04-17 9:47 ` Jonas Rebmann 2026-04-17 9:56 ` Puranjay Mohan 0 siblings, 1 reply; 7+ messages in thread From: Jonas Rebmann @ 2026-04-17 9:47 UTC (permalink / raw) To: Puranjay Mohan, Daniel Borkmann Cc: Alexei Starovoitov, Russell King, bpf, linux-kernel, kernel Hello Daniel, Hello Puranjay, On 2026-04-16 16:36, Daniel Borkmann wrote: > I don't have access to arm32, but it looks like its completely missing the > ability to do BPF to BPF calls.. you would need something like the below > (uncompiled / untested). Applying your Patch to latest master leads to a paging error [1] and segmentation fault in xdp_program__attach when I run ./xdp_pass_user -d lo > I think the problem is that BPF to BPF calls are not supported but the > JIT doesn't reject them as well, so the best way to fix this would be > to do: > > diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c > index deeb8f292454..91fef10e88bc 100644 > --- a/arch/arm/net/bpf_jit_32.c > +++ b/arch/arm/net/bpf_jit_32.c > @@ -2047,6 +2047,8 @@ static int build_insn(const struct bpf_insn > *insn, struct jit_ctx *ctx) > /* function call */ > case BPF_JMP | BPF_CALL: > { > + if (insn->src_reg == BPF_PSEUDO_CALL) > + goto notyet; > const s8 *r0 = bpf2a32[BPF_REG_0]; > const s8 *r1 = bpf2a32[BPF_REG_1]; > const s8 *r2 = bpf2a32[BPF_REG_2]; > > This will cause the memory to be freed properly. This works for me and resolves the issue. Tested-by: Jonas Rebmann <jre@pengutronix.de> >> It would actually be nice to you have any chance to run through the BPF >> selftests to see what else is broken on arm32. Outside of x86-64, arm64, >> riscv64 and s390x BPF JITs the results might vary quite a lot on what works >> and what doesn't. :/ > > I will do that soon when I get some time, the selftests won't easily > compile for 32-bit archs as pointers are 32-bit and bpf pointers are > 64 bit, etc. etc. Thank you! Regards, Jonas [1]: 8<--- cut here --- Unable to handle kernel paging request at virtual address bf0abbb0 when write [bf0abbb0] *pgd=42290811, *pte=703364df, *ppte=7033665e Internal error: Oops: 80f [#4] SMP ARM Modules linked in: CPU: 0 UID: 0 PID: 2049 Comm: xdp_pass_user Tainted: G D 7.0.0-08392-gcd33e05e22fa #19 VOLUNTARY Tainted: [D]=DIE Hardware name: QEMU QEMU Virtual Machine, BIOS unknown 02/02/2022 PC is at build_prologue+0x20/0x180 LR is at bpf_int_jit_compile+0xe0/0x440 pc : [<c0131f8c>] lr : [<c0135fcc>] psr: a00f0013 sp : f0c19b98 ip : f0c19be0 fp : 00000000 r10: bf0ab000 r9 : 00000001 r8 : 00000060 r7 : c23b1bc0 r6 : c3e96a40 r5 : f0adf000 r4 : f0adf000 r3 : e92d4bf0 r2 : f0c19bc0 r1 : bf0abbb0 r0 : 00000000 Flags: NzCv IRQs on FIQs on Mode SVC_32 ISA ARM Segment none Control: 10c5387d Table: 4553c06a DAC: 00000051 Register r0 information: NULL pointer Register r1 information: 1-page vmalloc region starting at 0xbf0ab000 allocated at bpf_jit_binary_alloc+0x64/0xfc Register r2 information: 2-page vmalloc region starting at 0xf0c18000 allocated at kernel_clone+0xb4/0x3f8 Register r3 information: non-slab/vmalloc memory Register r4 information: 1-page vmalloc region starting at 0xf0adf000 allocated at bpf_prog_alloc_no_stats+0x28/0x17c Register r5 information: 1-page vmalloc region starting at 0xf0adf000 allocated at bpf_prog_alloc_no_stats+0x28/0x17c Register r6 information: slab kmalloc-64 start c3e96a40 pointer offset 0 size 64 Register r7 information: slab task_struct start c23b1bc0 pointer offset 0 size 2368 Register r8 information: non-paged memory Register r9 information: non-paged memory Register r10 information: 1-page vmalloc region starting at 0xbf0ab000 allocated at bpf_jit_binary_alloc+0x64/0xfc Register r11 information: NULL pointer Register r12 information: 2-page vmalloc region starting at 0xf0c18000 allocated at kernel_clone+0xb4/0x3f8 Process xdp_pass_user (pid: 2049, stack limit = 0x95192730) Stack: (0xf0c19b98 to 0xf0c1a000) 9b80: f0adf000 f0adf000 9ba0: c3e96a40 c0135fcc c2001180 00000000 00000002 00000004 00000002 bf0abbb0 9bc0: f0adf000 00000000 00000024 00000016 00000009 00000000 c40bd4c0 bf0abbb0 9be0: 00000050 99439246 c4f44600 f0a8d000 c5070000 00000000 bf0abbb0 c5076000 9c00: f0a8d048 c02c04e0 f0a91000 f0a8d048 00000004 c4f445fc f0a8d000 00000000 9c20: c5076000 00100cc0 c4f44600 f0a8d048 c4f445fc 00000000 00000000 00000000 9c40: ffffffff f0c19ed0 c5070830 00000002 c5070000 00000000 00000001 c029a6ac 9c60: 00000000 00000000 00000000 00000000 c5076000 c5070000 f0c19d68 00000000 9c80: 00000000 c23b1bc0 00000000 00000000 00000000 3aa2f52f 00000075 00000001 9ca0: c5070458 f0a8d048 00000000 c4f44600 00000048 38e38e39 00000000 c4f4460c 9cc0: c5070878 00000000 f0c19ed0 00000001 beffea78 00000000 00000400 00000000 9ce0: 00000000 00000000 00000001 00000000 00000000 00000000 00000000 00000000 9d00: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 99439246 9d20: c1009d80 f0c19ed0 00000000 c4e9b730 f0c19d60 000000a8 00000002 c23b1bc0 9d40: 00000000 c027315c 000000a8 00000003 f0a8d048 00000020 c12cd684 00000000 9d60: beffea78 00000000 f0a8d000 00000000 c504e680 c4f4a180 0000000c 00000000 9d80: 0000001c f0c19dec c504e680 c0412a6c 00000000 004c5047 00000000 00000000 9da0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9dc0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9de0: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9e00: 00000000 00000000 00000000 00000000 00000000 99439246 f0c19e90 c23b1bc0 9e20: f0c19e90 beffea78 f0c19e70 00000000 00000005 000000a8 00000051 c02786dc 9e40: 00000001 c2272540 c2272540 99439246 000000c0 c2272540 00000000 c018dfc4 9e60: ffffff9c f0c19ebc c07247cc c2141418 beffea78 00000000 c160423c c01cc100 9e80: 00000001 00000001 c23b0000 eefe8a00 beffea78 00000000 c293ba70 00000088 9ea0: c23b1bc0 c23b0000 c15afa00 2da39000 c23b070c 800f0093 f0c19efc c018894c 9ec0: f0c19ec4 00000000 00000000 00000000 00000002 00000004 beffec20 00000000 9ee0: b6f97d4c 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9f00: 5f746564 5f677261 00787463 00000000 00000000 00000000 00000003 00000008 9f20: beffec10 00000000 00000002 00000000 00000000 00000000 00000000 00000000 9f40: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 9f60: 00000000 00000000 00000000 00000000 00000000 00000000 c4132c00 99439246 9f80: 00000006 beffeb58 00000000 00000002 00000182 c01002c4 c23b1bc0 00000182 9fa0: 000001a4 c0100060 beffeb58 00000000 00000005 beffea78 000000a8 0000005c 9fc0: beffeb58 00000000 00000002 00000182 beffea78 beffea78 00000005 000001a4 9fe0: beffea38 beffea28 b6f681f1 b6eaab02 200f0030 00000005 00000000 00000000 Call trace: build_prologue from bpf_int_jit_compile+0xe0/0x440 bpf_int_jit_compile from bpf_jit_subprogs+0x8e4/0xa60 bpf_jit_subprogs from bpf_check+0x1840/0x30e0 bpf_check from bpf_prog_load+0x720/0xec4 bpf_prog_load from __sys_bpf+0x4cc/0x25d4 __sys_bpf from ret_fast_syscall+0x0/0x54 Exception stack(0xf0c19fa8 to 0xf0c19ff0) 9fa0: beffeb58 00000000 00000005 beffea78 000000a8 0000005c 9fc0: beffeb58 00000000 00000002 00000182 beffea78 beffea78 00000005 000001a4 9fe0: beffea38 beffea28 b6f681f1 b6eaab02 Code: e3510000 0a00004e e3043bf0 e34e392d (e7813100) ---[ end trace 0000000000000000 ]--- -- Pengutronix e.K. | Jonas Rebmann | Steuerwalder Str. 21 | http://www.pengutronix.de/ | 31137 Hildesheim, Germany | Phone: +49-5121-206917-0 | Amtsgericht Hildesheim, HRA 2686 | Fax: +49-5121-206917-9 | ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: XDP BPF JIT memory leak on armv7 2026-04-17 9:47 ` Jonas Rebmann @ 2026-04-17 9:56 ` Puranjay Mohan 2026-04-17 11:24 ` Daniel Borkmann 0 siblings, 1 reply; 7+ messages in thread From: Puranjay Mohan @ 2026-04-17 9:56 UTC (permalink / raw) To: Jonas Rebmann Cc: Daniel Borkmann, Alexei Starovoitov, Russell King, bpf, linux-kernel, kernel On Fri, Apr 17, 2026 at 10:47 AM Jonas Rebmann <jre@pengutronix.de> wrote: > > Hello Daniel, > Hello Puranjay, > > On 2026-04-16 16:36, Daniel Borkmann wrote: > > I don't have access to arm32, but it looks like its completely missing the > > ability to do BPF to BPF calls.. you would need something like the below > > (uncompiled / untested). > > Applying your Patch to latest master leads to a paging error [1] and > segmentation fault in xdp_program__attach when I run > ./xdp_pass_user -d lo > > > I think the problem is that BPF to BPF calls are not supported but the > > JIT doesn't reject them as well, so the best way to fix this would be > > to do: > > > > diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c > > index deeb8f292454..91fef10e88bc 100644 > > --- a/arch/arm/net/bpf_jit_32.c > > +++ b/arch/arm/net/bpf_jit_32.c > > @@ -2047,6 +2047,8 @@ static int build_insn(const struct bpf_insn > > *insn, struct jit_ctx *ctx) > > /* function call */ > > case BPF_JMP | BPF_CALL: > > { > > + if (insn->src_reg == BPF_PSEUDO_CALL) > > + goto notyet; > > const s8 *r0 = bpf2a32[BPF_REG_0]; > > const s8 *r1 = bpf2a32[BPF_REG_1]; > > const s8 *r2 = bpf2a32[BPF_REG_2]; > > > > This will cause the memory to be freed properly. > > This works for me and resolves the issue. > > Tested-by: Jonas Rebmann <jre@pengutronix.de> Thanks for testing, let me send the patch to the list. ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: XDP BPF JIT memory leak on armv7 2026-04-17 9:56 ` Puranjay Mohan @ 2026-04-17 11:24 ` Daniel Borkmann 2026-04-17 11:35 ` Daniel Borkmann 0 siblings, 1 reply; 7+ messages in thread From: Daniel Borkmann @ 2026-04-17 11:24 UTC (permalink / raw) To: Puranjay Mohan, Jonas Rebmann Cc: Alexei Starovoitov, Russell King, bpf, linux-kernel, kernel On 4/17/26 11:56 AM, Puranjay Mohan wrote: >> On 2026-04-16 16:36, Daniel Borkmann wrote: >>> I don't have access to arm32, but it looks like its completely missing the >>> ability to do BPF to BPF calls.. you would need something like the below >>> (uncompiled / untested). >> >> Applying your Patch to latest master leads to a paging error [1] and >> segmentation fault in xdp_program__attach when I run >> ./xdp_pass_user -d lo >> >>> I think the problem is that BPF to BPF calls are not supported but the >>> JIT doesn't reject them as well, so the best way to fix this would be >>> to do: >>> >>> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c >>> index deeb8f292454..91fef10e88bc 100644 >>> --- a/arch/arm/net/bpf_jit_32.c >>> +++ b/arch/arm/net/bpf_jit_32.c >>> @@ -2047,6 +2047,8 @@ static int build_insn(const struct bpf_insn >>> *insn, struct jit_ctx *ctx) >>> /* function call */ >>> case BPF_JMP | BPF_CALL: >>> { >>> + if (insn->src_reg == BPF_PSEUDO_CALL) >>> + goto notyet; >>> const s8 *r0 = bpf2a32[BPF_REG_0]; >>> const s8 *r1 = bpf2a32[BPF_REG_1]; >>> const s8 *r2 = bpf2a32[BPF_REG_2]; >>> >>> This will cause the memory to be freed properly. >> >> This works for me and resolves the issue. >> >> Tested-by: Jonas Rebmann <jre@pengutronix.de> > > Thanks for testing, let me send the patch to the list. Sounds good, I think it might also be worth to check the other JITs which are not mainstream to see if they have the extra pass and if not then adding similar not-yet bailout to them. Cheers, Daniel ^ permalink raw reply [flat|nested] 7+ messages in thread
* Re: XDP BPF JIT memory leak on armv7 2026-04-17 11:24 ` Daniel Borkmann @ 2026-04-17 11:35 ` Daniel Borkmann 0 siblings, 0 replies; 7+ messages in thread From: Daniel Borkmann @ 2026-04-17 11:35 UTC (permalink / raw) To: Puranjay Mohan, Jonas Rebmann Cc: Alexei Starovoitov, Russell King, bpf, linux-kernel, kernel On 4/17/26 1:24 PM, Daniel Borkmann wrote: > On 4/17/26 11:56 AM, Puranjay Mohan wrote: >>> On 2026-04-16 16:36, Daniel Borkmann wrote: >>>> I don't have access to arm32, but it looks like its completely missing the >>>> ability to do BPF to BPF calls.. you would need something like the below >>>> (uncompiled / untested). >>> >>> Applying your Patch to latest master leads to a paging error [1] and >>> segmentation fault in xdp_program__attach when I run >>> ./xdp_pass_user -d lo >>> >>>> I think the problem is that BPF to BPF calls are not supported but the >>>> JIT doesn't reject them as well, so the best way to fix this would be >>>> to do: >>>> >>>> diff --git a/arch/arm/net/bpf_jit_32.c b/arch/arm/net/bpf_jit_32.c >>>> index deeb8f292454..91fef10e88bc 100644 >>>> --- a/arch/arm/net/bpf_jit_32.c >>>> +++ b/arch/arm/net/bpf_jit_32.c >>>> @@ -2047,6 +2047,8 @@ static int build_insn(const struct bpf_insn >>>> *insn, struct jit_ctx *ctx) >>>> /* function call */ >>>> case BPF_JMP | BPF_CALL: >>>> { >>>> + if (insn->src_reg == BPF_PSEUDO_CALL) >>>> + goto notyet; >>>> const s8 *r0 = bpf2a32[BPF_REG_0]; >>>> const s8 *r1 = bpf2a32[BPF_REG_1]; >>>> const s8 *r2 = bpf2a32[BPF_REG_2]; >>>> >>>> This will cause the memory to be freed properly. >>> >>> This works for me and resolves the issue. >>> >>> Tested-by: Jonas Rebmann <jre@pengutronix.de> >> >> Thanks for testing, let me send the patch to the list. > > Sounds good, I think it might also be worth to check the other > JITs which are not mainstream to see if they have the extra > pass and if not then adding similar not-yet bailout to them. Could probably be done in one sweep via a similar mechanism we have for kfuncs (bpf_jit_supports_kfunc_call), then verifier can also print a more meaningful message to the user. ^ permalink raw reply [flat|nested] 7+ messages in thread
end of thread, other threads:[~2026-04-17 11:35 UTC | newest] Thread overview: 7+ messages (download: mbox.gz / follow: Atom feed) -- links below jump to the message on this page -- 2026-04-16 14:05 XDP BPF JIT memory leak on armv7 Jonas Rebmann 2026-04-16 14:36 ` Daniel Borkmann 2026-04-16 15:58 ` Puranjay Mohan 2026-04-17 9:47 ` Jonas Rebmann 2026-04-17 9:56 ` Puranjay Mohan 2026-04-17 11:24 ` Daniel Borkmann 2026-04-17 11:35 ` Daniel Borkmann
This is a public inbox, see mirroring instructions for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®