mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* 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®