public inbox for linux-arm-kernel@lists.infradead.org 
 help / color / mirror / Atom feed
From: "Alexis Lothoré (eBPF Foundation)" <alexis.lothore@bootlin•com>
To: Alexei Starovoitov <ast@kernel•org>,
	 Daniel Borkmann <daniel@iogearbox•net>,
	Andrii Nakryiko <andrii@kernel•org>,
	 Martin KaFai Lau <martin.lau@linux•dev>,
	 Eduard Zingerman <eddyz87@gmail•com>,
	 Kumar Kartikeya Dwivedi <memxor@gmail•com>,
	Song Liu <song@kernel•org>,
	 Yonghong Song <yonghong.song@linux•dev>,
	Jiri Olsa <jolsa@kernel•org>,
	 John Fastabend <john.fastabend@gmail•com>,
	 Thomas Gleixner <tglx@kernel•org>,
	Ingo Molnar <mingo@redhat•com>,  Borislav Petkov <bp@alien8•de>,
	Dave Hansen <dave.hansen@linux•intel.com>,
	 x86@kernel•org, "H. Peter Anvin" <hpa@zytor•com>,
	 Shuah Khan <shuah@kernel•org>,
	Maxime Coquelin <mcoquelin.stm32@gmail•com>,
	 Alexandre Torgue <alexandre.torgue@foss•st.com>,
	 Ihor Solodrai <ihor.solodrai@linux•dev>
Cc: ebpf@linuxfoundation•org,
	"Bastien Curutchet" <bastien.curutchet@bootlin•com>,
	"Thomas Petazzoni" <thomas.petazzoni@bootlin•com>,
	bpf@vger•kernel.org, linux-kernel@vger•kernel.org,
	linux-kselftest@vger•kernel.org,
	linux-stm32@st-md-mailman•stormreply.com,
	linux-arm-kernel@lists•infradead.org,
	"Alexis Lothoré (eBPF Foundation)" <alexis.lothore@bootlin•com>
Subject: [PATCH bpf-next v2 3/8] bpf, x86: add helper to emit kasan checks in x86 JITed programs
Date: Thu, 04 Jun 2026 22:22:01 +0200	[thread overview]
Message-ID: <20260604-kasan-v2-3-c066e627fda8@bootlin.com> (raw)
In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com>

Add the emit_kasan_check() function that emits KASAN shadow memory
checks before memory accesses in JIT-compiled BPF programs. The
implementation relies on the existing __asan_{load,store}X functions
from KASAN subsystem. The helper:
- ensures that the kasan instrumention is actually needed: if the
  instruction being processed accesses the program stack, we skip the
  instrumentation, as those accesses are already protected with page
  guards
- saves registers. This includes caller-saved registers, but also
  temporary registers, as those were possibly used by the
  affected program
- computes the accessed address and stores it in %rdi
- calls the relevant function, depending on the instruction being a load
  or a store, and the size of the access.
- restores registers

The special care needed when inserting this instrumentation comes at the
cost of a non negligeable increase in JITed code size. For example, a
bare

  mov 	0x0(%si),rbx # Load in rbx content at address stored in rsi

becomes

  push    %rax
  push    %rcx
  push    %rdx
  push    %rsi
  push    %rdi
  push    %r8
  push    %r9
  mov     %rsi,%rdi
  call    0xffffffff81da0a60 <__asan_load8>
  pop     %r9
  pop     %r8
  pop     %rdi
  pop     %rsi
  pop     %rdx
  pop     %rcx
  pop     %rax
  mov     0x0(%rsi),rbx

Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin•com>
---
Changes in v2:
- move asan functions declaration directly into jit compiler, and guard
  them with IS_ENABLED
- remove faulty stack alignment, no arg is passed to kasan funcs on the
  stack anyway
- make sure to emit call depth accounting code
- do not save unneeded registers
- update helper signature to let caller configure some values (eg:
  is_write)

Signed-off-by: Alexis Lothoré (eBPF Foundation) <alexis.lothore@bootlin•com>
---
 arch/x86/net/bpf_jit_comp.c | 93 +++++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 93 insertions(+)

diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c
index a0c541a441cf..0981791014eb 100644
--- a/arch/x86/net/bpf_jit_comp.c
+++ b/arch/x86/net/bpf_jit_comp.c
@@ -21,6 +21,19 @@
 #include <asm/unwind.h>
 #include <asm/cfi.h>
 
+#if IS_ENABLED(CONFIG_BPF_JIT_KASAN)
+void __asan_load1(void *p);
+void __asan_store1(void *p);
+void __asan_load2(void *p);
+void __asan_store2(void *p);
+void __asan_load4(void *p);
+void __asan_store4(void *p);
+void __asan_load8(void *p);
+void __asan_store8(void *p);
+void __asan_load16(void *p);
+void __asan_store16(void *p);
+#endif
+
 static bool all_callee_regs_used[4] = {true, true, true, true};
 
 static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len)
@@ -1330,6 +1343,86 @@ static void emit_store_stack_imm64(u8 **pprog, int reg, int stack_off, u64 imm64
 	emit_stx(pprog, BPF_DW, BPF_REG_FP, reg, stack_off);
 }
 
+static int emit_kasan_check(u8 **pprog, u32 addr_reg, struct bpf_insn *insn,
+			    u8 *ip, bool is_write, bool accesses_stack_only)
+{
+#ifdef CONFIG_BPF_JIT_KASAN
+	u32 bpf_size = BPF_SIZE(insn->code);
+	s32 off = insn->off;
+	u8 *prog = *pprog;
+	void *kasan_func;
+
+	if (accesses_stack_only)
+		return 0;
+
+	/* Derive KASAN check function from access type and size */
+	switch (bpf_size) {
+	case BPF_B:
+		kasan_func = is_write ? __asan_store1 : __asan_load1;
+		break;
+	case BPF_H:
+		kasan_func = is_write ? __asan_store2 : __asan_load2;
+		break;
+	case BPF_W:
+		kasan_func = is_write ? __asan_store4 : __asan_load4;
+		break;
+	case BPF_DW:
+		kasan_func = is_write ? __asan_store8 : __asan_load8;
+		break;
+	default:
+		return -EINVAL;
+	}
+
+	/* Save rax */
+	EMIT1(0x50);
+	/* Save rcx */
+	EMIT1(0x51);
+	/* Save rdx */
+	EMIT1(0x52);
+	/* Save rsi */
+	EMIT1(0x56);
+	/* Save rdi */
+	EMIT1(0x57);
+	/* Save r8 */
+	EMIT2(0x41, 0x50);
+	/* Save r9 */
+	EMIT2(0x41, 0x51);
+
+	/* mov rdi, addr_reg */
+	EMIT_mov(BPF_REG_1, addr_reg);
+
+	/* add rdi, off (if offset is non-zero) */
+	if (off) {
+		if (is_imm8(off)) {
+			/* add rdi, imm8 */
+			EMIT4(0x48, 0x83, 0xC7, (u8)off);
+		} else {
+			/* add rdi, imm32 */
+			EMIT3_off32(0x48, 0x81, 0xC7, off);
+		}
+	}
+
+	/* Adjust ip to account for the instrumentation generated so far */
+	ip += (prog - *pprog);
+	/* We emit a call, so update call depth counting */
+	ip += x86_call_depth_emit_accounting(&prog, kasan_func, ip);
+	/* call kasan_func */
+	if (emit_call(&prog, kasan_func, ip))
+		return -ERANGE;
+
+	EMIT2(0x41, 0x59);
+	EMIT2(0x41, 0x58);
+	EMIT1(0x5F);
+	EMIT1(0x5E);
+	EMIT1(0x5A);
+	EMIT1(0x59);
+	EMIT1(0x58);
+
+	*pprog = prog;
+#endif /* CONFIG_BPF_JIT_KASAN */
+	return 0;
+}
+
 static int emit_atomic_rmw(u8 **pprog, u32 atomic_op,
 			   u32 dst_reg, u32 src_reg, s16 off, u8 bpf_size)
 {

-- 
2.54.0



  parent reply	other threads:[~2026-06-04 20:22 UTC|newest]

Thread overview: 13+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-04 20:21 [PATCH bpf-next v2 0/8] bpf: add support for KASAN checks in JITed programs Alexis Lothoré (eBPF Foundation)
2026-06-04 20:21 ` [PATCH bpf-next v2 1/8] bpf: mark instructions accessing program stack Alexis Lothoré (eBPF Foundation)
2026-06-04 21:13   ` bot+bpf-ci
2026-06-04 20:22 ` [PATCH bpf-next v2 2/8] bpf: add BPF_JIT_KASAN for KASAN instrumentation of JITed programs Alexis Lothoré (eBPF Foundation)
2026-06-04 21:13   ` bot+bpf-ci
2026-06-04 20:22 ` Alexis Lothoré (eBPF Foundation) [this message]
2026-06-04 20:22 ` [PATCH bpf-next v2 4/8] bpf, x86: refactor BPF_ST management in do_jit Alexis Lothoré (eBPF Foundation)
2026-06-04 21:13   ` bot+bpf-ci
2026-06-04 20:22 ` [PATCH bpf-next v2 5/8] bpf, x86: emit KASAN checks into x86 JITed programs Alexis Lothoré (eBPF Foundation)
2026-06-04 20:22 ` [PATCH bpf-next v2 6/8] bpf, x86: enable KASAN for JITed programs on x86 Alexis Lothoré (eBPF Foundation)
2026-06-04 20:22 ` [PATCH bpf-next v2 7/8] selftests/bpf: add helper to check whether eBPF KASAN is active Alexis Lothoré (eBPF Foundation)
2026-06-04 20:22 ` [PATCH bpf-next v2 8/8] selftests/bpf: add tests to validate KASAN on JIT programs Alexis Lothoré (eBPF Foundation)
2026-06-04 21:45   ` bot+bpf-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=20260604-kasan-v2-3-c066e627fda8@bootlin.com \
    --to=alexis.lothore@bootlin$(echo .)com \
    --cc=alexandre.torgue@foss$(echo .)st.com \
    --cc=andrii@kernel$(echo .)org \
    --cc=ast@kernel$(echo .)org \
    --cc=bastien.curutchet@bootlin$(echo .)com \
    --cc=bp@alien8$(echo .)de \
    --cc=bpf@vger$(echo .)kernel.org \
    --cc=daniel@iogearbox$(echo .)net \
    --cc=dave.hansen@linux$(echo .)intel.com \
    --cc=ebpf@linuxfoundation$(echo .)org \
    --cc=eddyz87@gmail$(echo .)com \
    --cc=hpa@zytor$(echo .)com \
    --cc=ihor.solodrai@linux$(echo .)dev \
    --cc=john.fastabend@gmail$(echo .)com \
    --cc=jolsa@kernel$(echo .)org \
    --cc=linux-arm-kernel@lists$(echo .)infradead.org \
    --cc=linux-kernel@vger$(echo .)kernel.org \
    --cc=linux-kselftest@vger$(echo .)kernel.org \
    --cc=linux-stm32@st-md-mailman$(echo .)stormreply.com \
    --cc=martin.lau@linux$(echo .)dev \
    --cc=mcoquelin.stm32@gmail$(echo .)com \
    --cc=memxor@gmail$(echo .)com \
    --cc=mingo@redhat$(echo .)com \
    --cc=shuah@kernel$(echo .)org \
    --cc=song@kernel$(echo .)org \
    --cc=tglx@kernel$(echo .)org \
    --cc=thomas.petazzoni@bootlin$(echo .)com \
    --cc=x86@kernel$(echo .)org \
    --cc=yonghong.song@linux$(echo .)dev \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html
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