From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 17FA93D522B; Thu, 4 Jun 2026 20:22:30 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604552; cv=none; b=nS+NVyZ6WoL2ya6HORpVaqhbfuKF32zG/wd77eQltNpVfEYMzwSD8IcgZJSRRWvEKG4b2iikImRFSA0FXD1iuEkKWqUryQXD7BIglZmAQJstbwPgGGfs0AjS0jiBHNibZVpvkMEpZ7r6h8Bv/L7QJbaSLPhR+piNueBDE1jxSXU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604552; c=relaxed/simple; bh=JfSh90vAuZgkaaHACVBUPe2vqK+R+VcbdXjwcArV0rg=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Gfj0E8I9whk8BDDyCCv9kSceFeOgmQa6N2Blk/13h1mEzki4ZkgBdxLq+AZMamJajvSFRZY+6gvu36gMVBb0oVk3sF1GNFKWXBMux2QHyz8OGII0HWI5uF90WQNBK20GgegNwQDLCg2NAXD1TZoFFG7tDoBr8nSWntqDMJ+tJCA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=g9hZECUL; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="g9hZECUL" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 0777CC63453; Thu, 4 Jun 2026 20:22:29 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 9E7C55FED1; Thu, 4 Jun 2026 20:22:29 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 191B6106A1D38; Thu, 4 Jun 2026 22:22:24 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604547; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=zgpTqib293PeJ1HPHKW/oMt7J0hcVujaLGWwpfesc9M=; b=g9hZECULy4U0Df6PU535oPXEz1CTdnLpDUaLPDCdFKUW1EzbMzT3vnSCPj1Yz1RL5AmWSw aSWz5Znay4r7aREbuSDeR+Uh/v61xzxZO35IwbqtZxAaEsp2a5e0UmDDpi2XsYzVaUtCm5 lfZ2Q3W0l5yc3R2qafhW3f0mniN/TSe0qVuzAf0KGzyhpB8kS237iGmDLI3JToKcQzlg0W NeLWsZ4ocsKBcL6ySdJOVP8GN9uSnQcE8o6fouYfdU1O/+9osSHF89kp4yrpNH67+3o8fD EfolbKvwNMOUdcWT46wWKHkcSO3D+RyfIGff/Aei3m0bt2+XnvBg68mkvOTGgg== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:21:59 +0200 Subject: [PATCH bpf-next v2 1/8] bpf: mark instructions accessing program stack Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-1-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 In order to prepare to emit KASAN checks in JITed programs, JIT compilers need to be aware about whether some load/store instructions are targeting the bpf program stack, as those should not be monitored (we already have guard pages for that, and it is difficult anyway to correctly monitor any kind of data passed on stack). To support this need, make the BPF verifier mark the instructions depending on whether they could access or not memory other than stack: - add a setter that allows the verifier to mark instructions accessing non-stack memory - add a getter that allows JIT compilers to check whether instructions being JITed are accessing the stack _and only_ the stack. If no env is provided (eg this is a cBPF program), do a best-effort check based on source and destination registers. As different states in the verifier could lead to different memory types for the same access, just marking an instruction as accessing stack only is not enough (it could be some other memory type in another verifier state), so the algorithm rather sets by default any load/store instruction as stack only, and if _any_ state leads to any memory access type other than PTR_TO_STACK, it overrides this setting. It also takes care about shifting back the instruction marking in adjust_insn_aux_data if the verifier patches instructions. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- Changes in v2: - invert marking logic to cover possible different reg types when the verifier covers different states - add a best-effort processing for classical bpf programs, inspecting directly src and dst registers since we don't have verifier env - make sure to keep marking in sync with prog when it is patched by verifier --- include/linux/bpf.h | 2 ++ include/linux/bpf_verifier.h | 2 ++ kernel/bpf/core.c | 17 +++++++++++++++++ kernel/bpf/fixups.c | 16 +++++++++++----- kernel/bpf/verifier.c | 9 +++++++++ 5 files changed, 41 insertions(+), 5 deletions(-) diff --git a/include/linux/bpf.h b/include/linux/bpf.h index 8599b451dd7a..ff80d1d62bff 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -1560,6 +1560,8 @@ void bpf_jit_uncharge_modmem(u32 size); bool bpf_prog_has_trampoline(const struct bpf_prog *prog); bool bpf_insn_is_indirect_target(const struct bpf_verifier_env *env, const= struct bpf_prog *prog, int insn_idx); +bool bpf_insn_accesses_stack_only(const struct bpf_verifier_env *env, + const struct bpf_prog *prog, int insn_idx); u16 bpf_out_stack_arg_cnt(const struct bpf_verifier_env *env, const struct= bpf_prog *prog); #else static inline int bpf_trampoline_link_prog(struct bpf_tramp_link *link, diff --git a/include/linux/bpf_verifier.h b/include/linux/bpf_verifier.h index c248ff41f42a..0f3f055d6c14 100644 --- a/include/linux/bpf_verifier.h +++ b/include/linux/bpf_verifier.h @@ -722,6 +722,8 @@ struct bpf_insn_aux_data { u16 const_reg_map_mask; u16 const_reg_subprog_mask; u32 const_reg_vals[10]; + /* instruction can access non-stack memory */ + bool non_stack_access; }; =20 #define MAX_USED_MAPS 64 /* max number of maps accessed by one eBPF progra= m */ diff --git a/kernel/bpf/core.c b/kernel/bpf/core.c index a656a8572bdb..393d9eacd215 100644 --- a/kernel/bpf/core.c +++ b/kernel/bpf/core.c @@ -1583,6 +1583,22 @@ bool bpf_insn_is_indirect_target(const struct bpf_ve= rifier_env *env, const struc return env->insn_aux_data[insn_idx].indirect_target; } =20 +bool bpf_insn_accesses_stack_only(const struct bpf_verifier_env *env, + const struct bpf_prog *prog, int insn_idx) +{ + struct bpf_insn *insn; + + /* cBPF: we have no verifier state, do a best-effort check based on + * dst/src reg + */ + insn_idx +=3D prog->aux->subprog_start; + insn =3D (struct bpf_insn *)prog->insnsi + insn_idx; + if (!env) + return insn->dst_reg =3D=3D BPF_REG_FP || + insn->src_reg =3D=3D BPF_REG_FP; + return !env->insn_aux_data[insn_idx].non_stack_access; +} + u16 bpf_out_stack_arg_cnt(const struct bpf_verifier_env *env, const struct= bpf_prog *prog) { const struct bpf_subprog_info *sub; @@ -1592,6 +1608,7 @@ u16 bpf_out_stack_arg_cnt(const struct bpf_verifier_e= nv *env, const struct bpf_p sub =3D &env->subprog_info[prog->aux->func_idx]; return sub->stack_arg_cnt - bpf_in_stack_arg_cnt(sub); } + #endif /* CONFIG_BPF_JIT */ =20 /* Base function for offset calculation. Needs to go into .text section, diff --git a/kernel/bpf/fixups.c b/kernel/bpf/fixups.c index 5aa3f7d99ac9..5228c910fbf5 100644 --- a/kernel/bpf/fixups.c +++ b/kernel/bpf/fixups.c @@ -185,16 +185,22 @@ static void adjust_insn_aux_data(struct bpf_verifier_= env *env, } =20 /* - * The indirect_target flag of the original instruction was moved to the = last of the - * new instructions by the above memmove and memset, but the indirect jum= p target is - * actually the first instruction, so move it back. This also matches wit= h the behavior - * of bpf_insn_array_adjust(), which preserves xlated_off to point to the= first new - * instruction. + * The indirect_target and non_stack_access flags of the original + * instruction were moved to the last of the new instructions by the + * above memmove and memset, but those actually match the first + * instruction, so move them back. This also matches with the behavior + * of bpf_insn_array_adjust(), which preserves xlated_off to point to + * the first new instruction. */ if (data[off + cnt - 1].indirect_target) { data[off].indirect_target =3D 1; data[off + cnt - 1].indirect_target =3D 0; } + + if (data[off + cnt - 1].non_stack_access) { + data[off].non_stack_access =3D 1; + data[off + cnt - 1].non_stack_access =3D 0; + } } =20 static void adjust_subprog_starts(struct bpf_verifier_env *env, u32 off, u= 32 len) diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c index 8ed484cb1a8a..b3f0f430ad6a 100644 --- a/kernel/bpf/verifier.c +++ b/kernel/bpf/verifier.c @@ -3143,6 +3143,11 @@ static void mark_indirect_target(struct bpf_verifier= _env *env, int idx) env->insn_aux_data[idx].indirect_target =3D true; } =20 +static void mark_non_stack_access(struct bpf_verifier_env *env, int idx) +{ + env->insn_aux_data[idx].non_stack_access =3D true; +} + #define LR_FRAMENO_BITS 3 #define LR_SPI_BITS 6 #define LR_ENTRY_BITS (LR_SPI_BITS + LR_FRAMENO_BITS + 1) @@ -6300,6 +6305,10 @@ static int check_mem_access(struct bpf_verifier_env = *env, int insn_idx, struct b else coerce_reg_to_size_sx(®s[value_regno], size); } + + if (!err && reg->type !=3D PTR_TO_STACK) + mark_non_stack_access(env, insn_idx); + return err; } =20 --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id DC4AE3DCDAB for ; Thu, 4 Jun 2026 20:22:34 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604556; cv=none; b=c6T4bkDJh+T6HhCnzVz5HOvnhStDKjv3dMq5z3AwNDOmdlslyFsgraup6EefHbYeUtG07b7cxMDVlKBSPL+iH2pB1eMtnpLMI1siiRiQ3BjaR3orV8cKH8RVyT6yUZqbZ5xqla1GHcLbVZo/TB8ksSJhWzWZScxUbs+aqjfdgdc= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604556; c=relaxed/simple; bh=1hiG5xNLfuEU1FhaF20lZOtGhnKc2Kxuk+bBeW/hea4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=m3wHQnXggMRZwpLYr9/dwCp9X53mqWsJqReh7p+G8IBHUrllxormvPeEk3Zlv6iRFnOwwxpAifjWBvtmNF1icJBVNEFqTPdcwtJd3H+4fIrvDSwizV4HelHvg7ps6DxlxkrcqgmWHJP6pB+z5c6S/F4vtrvCImD77JWSYxJVW54= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=W43bDU6s; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="W43bDU6s" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 7E9ED4E40719; Thu, 4 Jun 2026 20:22:33 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 515805FED1; Thu, 4 Jun 2026 20:22:33 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A8066106A1D0E; Thu, 4 Jun 2026 22:22:28 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604551; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=JWdw38EiI9Mq6OhPMl4z+SwTGgKYfom6pjkQ6/P5SXE=; b=W43bDU6svXn0gZBV6DoqwOqs70uuSW0/XAyd2Q078jgcmbCzxIVTV2GdZ088o38TOj3oJ5 4WAEW3fsczlFsEm5sGkFHT1clJKkfTDLxlfeQSVs/WLMsdKg2uWpFbiv0chnu4U+NBXTBZ 0GAbixyfx8SqaMATSvIiSEL2CugVww/xt2ulqMPJ2kv74PE3oGqpm6lykWwUklGQPeAjVk /bMTlpyI/FubabCtktk0KuDFD++Q7gcMqaD3VIQg5VtuBKLk85tR/Mb6F1uOr0QnTsSb3Q s9kuqKANfXlFUoXBE7gH/IflXPCLYJu0Lw65kC/e4YUrHE0hndD9YUlHuj7F/Q== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:00 +0200 Subject: [PATCH bpf-next v2 2/8] bpf: add BPF_JIT_KASAN for KASAN instrumentation of JITed programs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-2-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 Add a new Kconfig option CONFIG_BPF_JIT_KASAN that automatically enables generic KASAN (Kernel Address SANitizer) memory access checks for JIT-compiled BPF programs as well, when both KASAN_GENERIC and JIT compiler are enabled. This new Kconfig is not a user selectable one: it is either automatically enabled if KASAN is enabled on a compatible platform, or disabled. When enabled, the JIT compiler will emit shadow memory checks before memory loads and stores to detect use-after-free or out-of-bounds accesses at runtime. The option is gated behind HAVE_EBPF_JIT_KASAN, as it needs proper arch-specific implementation. As KASAN instrumentation for eBPF program will depend on the info that can be accessed during each instruction verification, there may be instructions that will be instrumented even if they don't really need to (eg: global subprograms that access caller stack memory passed as argument). To make sure that those additional checks do not trigger any crash, make sure that VMAP_STACK is enabled so that programs stack has shadow memory allocated. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- Changes in v2: - add dependency on kasan for vmalloc and vmalloc'ed stack --- kernel/bpf/Kconfig | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/kernel/bpf/Kconfig b/kernel/bpf/Kconfig index eb3de35734f0..a8e004f88b92 100644 --- a/kernel/bpf/Kconfig +++ b/kernel/bpf/Kconfig @@ -17,6 +17,10 @@ config HAVE_CBPF_JIT config HAVE_EBPF_JIT bool =20 +# KASAN support for JIT compiler +config HAVE_EBPF_JIT_KASAN + bool + # Used by archs to tell that they want the BPF JIT compiler enabled by # default for kernels that were compiled with BPF JIT support. config ARCH_WANT_DEFAULT_BPF_JIT @@ -101,4 +105,9 @@ config BPF_LSM =20 If you are unsure how to answer this question, answer N. =20 +config BPF_JIT_KASAN + bool + depends on HAVE_EBPF_JIT_KASAN + default y if BPF_JIT && KASAN_GENERIC && KASAN_VMALLOC && VMAP_STACK + endmenu # "BPF subsystem" --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 347E94C9575 for ; Thu, 4 Jun 2026 20:22:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604559; cv=none; b=faHdGebhEeVpUtPtEJIqwK31JA/MurARfDO4wNCyi/QLr1Z7h9ialgyPgxLEO93szD7yxGK7DyFdXlbDe3J1c9X52/omdg0xnT/uKVa8pKHm32p++qJhH5s9QiZ0C/YpjuLyFJIX93clFQGTtlTSVclh127Xm1ogYd52V/CdWFA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604559; c=relaxed/simple; bh=d70yGDy2a/ZDsF0eE0o36k1UjTfp/5kRIgMkTjoR0/c=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=qJwiEf/vEbXYmy4986wFYxzGYCoodW5tOamA9co0VBsq92uBpNHJfjcQWi70a5jw0XHd6mQ0BpvndtoeJiqZyRXn8EptbYunWoAnq6WHlyuv5l1gqVbQXHfTkLaZHuKodieU/BTCTCIGj1JCJ7OowHoMu90bfO+2mh40j3SNx38= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=ew6G7Kqh; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="ew6G7Kqh" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 63750C6344F; Thu, 4 Jun 2026 20:22:36 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 0635A5FED1; Thu, 4 Jun 2026 20:22:37 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 3108D106A1D3D; Thu, 4 Jun 2026 22:22:32 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604555; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=onobyqUpNxQD6/u3MqsXH18ymnmpWqQmDfG8EEUxqLc=; b=ew6G7KqhTvHYNtp8yVygJarlPlaU1vsp2QeUIk98VAjxLseyvgvyOuz6Wgj8h4OlRaPjbn VdBpElk0eUFDLzcuyO9b43etwltKoEEUjekbphiNWscK4R4l+fzLAtKNIKKz31MZbo7J7K 2WdJ2ofGmoW00YAtGX/LA5n30J+9TpURm+MAhmrg7s61IoO/mvbb7PDWE2d7gZACq+89bq espnfaox5Tr1a/WaS82xLgMM+uuQYRqjePSrWpYC+EgOcNrm7mWbpRtSGEtjHbuBUcuuFZ j8yj9B9xjuMFKvWgaFcAH/iRmGe7GHaF7dUbOicoppl6+IXaYaZvG+l5NruraQ== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:01 +0200 Subject: [PATCH bpf-next v2 3/8] bpf, x86: add helper to emit kasan checks in x86 JITed programs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-3-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 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=C3=A9 (eBPF Foundation) --- 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=C3=A9 (eBPF Foundation) --- 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 #include =20 +#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] =3D {true, true, true, true}; =20 static u8 *emit_code(u8 *ptr, u32 bytes, unsigned int len) @@ -1330,6 +1343,86 @@ static void emit_store_stack_imm64(u8 **pprog, int r= eg, int stack_off, u64 imm64 emit_stx(pprog, BPF_DW, BPF_REG_FP, reg, stack_off); } =20 +static int emit_kasan_check(u8 **pprog, u32 addr_reg, struct bpf_insn *ins= n, + u8 *ip, bool is_write, bool accesses_stack_only) +{ +#ifdef CONFIG_BPF_JIT_KASAN + u32 bpf_size =3D BPF_SIZE(insn->code); + s32 off =3D insn->off; + u8 *prog =3D *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 =3D is_write ? __asan_store1 : __asan_load1; + break; + case BPF_H: + kasan_func =3D is_write ? __asan_store2 : __asan_load2; + break; + case BPF_W: + kasan_func =3D is_write ? __asan_store4 : __asan_load4; + break; + case BPF_DW: + kasan_func =3D 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 +=3D (prog - *pprog); + /* We emit a call, so update call depth counting */ + ip +=3D 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 =3D 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) { --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 776CF42DFF1 for ; Thu, 4 Jun 2026 20:22:41 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604562; cv=none; b=p6AlxhIzg6GRrINXFz+4rW4NwhmKQ3TfMN+Wx0Dw/bmP+jtWXebC2MCSaepeJxl4+DfkZ7cKcJWdjx9gPDv3Bw8h9DUmsJa4tykFZnR+b054wRfJPrrqqimYDCgWDoKSN1qOsc7cc+49Jtks/uP47KZJOSVkmHYqsl/pXEiMeQQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604562; c=relaxed/simple; bh=tA/J+y0IViZ+5uj14534YohZ6eRZGM36o/SwEt6cL1o=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=Q0ygMeucvzfw2r+/gMsdOcGjBEeCHFhmpLvciVMHUFRjSTqMqRJkxykjd6/JEvvEB0KVGDogQO+4PPLp4VyJhddb3fBJg1l1zbyFBn42oAvwGooj3MUNCljx0orVPqYInsHRKKB/GoaSLZPO/bDiP2Mtf+9xA1kQFMDLqufiVfc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=DmC5uD7U; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="DmC5uD7U" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 4726C4E4071B; Thu, 4 Jun 2026 20:22:40 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 13DA95FED1; Thu, 4 Jun 2026 20:22:40 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id A3C85106A1D2C; Thu, 4 Jun 2026 22:22:35 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604558; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=RfWDnkDwkkfbnuCPMrlh9TY6xMPQgUKPCYmPMT1bj3Y=; b=DmC5uD7Ufj+9BtNRuy5VfbgxYZpX1m4cXOJ8liQembdGsvxTu8kssq/pi6HlrhNOWCiWaB Tb6vGElU2Vlafl9+fpmnZhj1IaXDxPnt+cjEkjVeABuufocl2HUs3JJhAX2QX+Fj3PpUh3 g4sZpGl6prt/hZCI+kKP5oS5xY9j0fSYd/Df7hfxqJwlzL0ITG/Z+Ixck7kHpjniNJIMEW wt6XfQs3M8gOKP26Y0CMmp/njdD+dyBiKSyFGOMe9GdVDbeYaON6mF9aeyzZjvKbYbgGRJ VOkK+/Va/TqY9jKJhpOc2+P4SHS6KNoJZSMU+c85ZaJQKneIcU9Zyt9Gp8xb+A== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:02 +0200 Subject: [PATCH bpf-next v2 4/8] bpf, x86: refactor BPF_ST management in do_jit Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-4-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 In order to prepare for KASAN checks insertion before every memory-related load or store, group all BPF_ST instructions that indeed access memory in a single block of fall-through cases to allow instrumenting those in one call, rather than having to instrument all cases individually. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- arch/x86/net/bpf_jit_comp.c | 53 ++++++++++++++++++++++++++---------------= ---- 1 file changed, 31 insertions(+), 22 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 0981791014eb..943a0f315cf2 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -2300,41 +2300,50 @@ static int do_jit(struct bpf_verifier_env *env, str= uct bpf_prog *bpf_prog, int * EMIT_LFENCE(); break; =20 - /* ST: *(u8*)(dst_reg + off) =3D imm */ case BPF_ST | BPF_MEM | BPF_B: - if (is_ereg(dst_reg)) - EMIT2(0x41, 0xC6); - else - EMIT1(0xC6); - goto st; case BPF_ST | BPF_MEM | BPF_H: - if (is_ereg(dst_reg)) - EMIT3(0x66, 0x41, 0xC7); - else - EMIT2(0x66, 0xC7); - goto st; case BPF_ST | BPF_MEM | BPF_W: - if (is_ereg(dst_reg)) - EMIT2(0x41, 0xC7); - else - EMIT1(0xC7); - goto st; case BPF_ST | BPF_MEM | BPF_DW: - if (dst_reg =3D=3D BPF_REG_PARAMS && insn->off =3D=3D -8) { - /* Arg 6: store immediate in r9 register */ - emit_mov_imm64(&prog, X86_REG_R9, imm32 >> 31, (u32)imm32); + switch (BPF_SIZE(insn->code)) { + case BPF_B: + if (is_ereg(dst_reg)) + EMIT2(0x41, 0xC6); + else + EMIT1(0xC6); + break; + case BPF_H: + if (is_ereg(dst_reg)) + EMIT3(0x66, 0x41, 0xC7); + else + EMIT2(0x66, 0xC7); + break; + case BPF_W: + if (is_ereg(dst_reg)) + EMIT2(0x41, 0xC7); + else + EMIT1(0xC7); + break; + case BPF_DW: + if (dst_reg =3D=3D BPF_REG_PARAMS && + insn->off =3D=3D -8) { + /* Arg 6: store immediate in r9 register */ + emit_mov_imm64(&prog, X86_REG_R9, + imm32 >> 31, (u32)imm32); + break; + } + EMIT2(add_1mod(0x48, dst_reg), 0xC7); break; } - EMIT2(add_1mod(0x48, dst_reg), 0xC7); =20 -st: insn_off =3D insn->off; + insn_off =3D insn->off; if (dst_reg =3D=3D BPF_REG_PARAMS) { /* * Args 7+: reverse BPF negative offsets to * x86 positive rsp offsets. * BPF off=3D-16 =E2=86=92 [rsp+0], off=3D-24 =E2=86=92 [rsp+8], ... */ - insn_off =3D outgoing_arg_base - outgoing_rsp - insn_off - 16; + insn_off =3D outgoing_arg_base - outgoing_rsp - + insn_off - 16; dst_reg =3D BPF_REG_FP; } if (is_imm8(insn_off)) --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-03.galae.net (smtpout-03.galae.net [185.246.85.4]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9C919495504; Thu, 4 Jun 2026 20:22:44 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.246.85.4 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604566; cv=none; b=WU46zWz9qcSBwyf3L/9TNrPV8W0Cxn10sJPyzQZIxaDtLdMeClGDAQx2W2slLqaR0IVIIvZtlyJ1jGCd97jFj9Y+xIgTRWAfW5iE8YFfBpu3zBlEAu5NFWjhWHIdcjGMvob//quaD05TiqJElk2iV+i1CdGZTomsajO6WOFQzHA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604566; c=relaxed/simple; bh=AFjMJQszEcBLvLk6sSWHhdL5n+e2kJz79mY42ZHlTX4=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=gnokStC1s0E2/tu2DRYnKHIZlRbc8N2vct/MatewD4VikNuU26Yl38qqN3NE2HRhD+8s7nd4/RzgT7eKTODAJV9e+qUGlxHiHplTwmcAF2O/I3wwx6yjJknfycVl2pIf7dzqmKimCDWZ3WIYEuUGhrsnvZ4+BHO60Na3/3ja8+Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=SDLnofRd; arc=none smtp.client-ip=185.246.85.4 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="SDLnofRd" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-03.galae.net (Postfix) with ESMTPS id 479F44E40747; Thu, 4 Jun 2026 20:22:43 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 14D1F5FED1; Thu, 4 Jun 2026 20:22:43 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id B7E44106A1D2E; Thu, 4 Jun 2026 22:22:38 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604561; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=UoqSqntIzj8Teup4Ktkq7Hy+tOt6BUYqG7fRFULwZGI=; b=SDLnofRdJQjkWpFQ6LGyaG2sZP86FbyHIls5X2QUP/GRqr01kMjATXSEiWElfffb9fHpHO SqLnK5hi9Q0E4KWiVd7iND83r6UBBXhxoxFKxp4a8IWFec5dnraufsGFdUHfBVMl/Qk3sh eAh/CxqaHu6M2u7ZtRd55oDSOzTUCIJx9Uiha+AE8Ru11L67+DVHUyDHqS0ePUtAt/pblU Hy3P8O2m1WTPdbi2ePIcGbLurB1oyRXStQWk+VwZg9mJT/FYFzjeSUCzJkefdiOQh/x73i dFJoDeSktVCsoQ3SeQ19KNc21/3/EpBVTbkKciVVtEG9XzRrrNN6WctnVsqY8A== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:03 +0200 Subject: [PATCH bpf-next v2 5/8] bpf, x86: emit KASAN checks into x86 JITed programs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-5-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 Insert KASAN shadow memory checks before memory load and store operations in JIT-compiled BPF programs. This helps detect memory safety bugs such as use-after-free and out-of-bounds accesses at runtime. The main instructions being targeted are BPF_ST, BPF_STX and BPF_LDX, but not all of them are being instrumented: - if the load/store instruction is in fact accessing the program stack, emit_kasan_check silently skips the instrumentation, as we already have page guards to monitor stack accesses. - if the load/store instruction is a BPF_PROBE_MEM or a BPF_PROBE_ATOMIC instruction, we do not instrument it, as the passed address can fault (hence the custom fault management with BPF_PROBE_XXX instructions), and so the corresponding kasan check could fault as well. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- Changes in v2: - support BPF_ATOMICS - support BPF_ST - make sure to systematically pass correct instruction to kasan check --- arch/x86/net/bpf_jit_comp.c | 63 ++++++++++++++++++++++++++++++++++++++---= ---- 1 file changed, 53 insertions(+), 10 deletions(-) diff --git a/arch/x86/net/bpf_jit_comp.c b/arch/x86/net/bpf_jit_comp.c index 943a0f315cf2..cb3c03edc4bd 100644 --- a/arch/x86/net/bpf_jit_comp.c +++ b/arch/x86/net/bpf_jit_comp.c @@ -1516,17 +1516,30 @@ static int emit_atomic_rmw_index(u8 **pprog, u32 at= omic_op, u32 size, return 0; } =20 -static int emit_atomic_ld_st(u8 **pprog, u32 atomic_op, u32 dst_reg, - u32 src_reg, s16 off, u8 bpf_size) +static int emit_atomic_ld_st(u8 **pprog, struct bpf_insn *insn, u8 *ip, + u32 dst_reg, u32 src_reg, bool accesses_stack_only) { + u32 atomic_op =3D insn->imm; + int err; + switch (atomic_op) { case BPF_LOAD_ACQ: + err =3D emit_kasan_check(pprog, src_reg, insn, ip, false, + accesses_stack_only); + if (err) + return err; /* dst_reg =3D smp_load_acquire(src_reg + off16) */ - emit_ldx(pprog, bpf_size, dst_reg, src_reg, off); + emit_ldx(pprog, BPF_SIZE(insn->code), dst_reg, src_reg, + insn->off); break; case BPF_STORE_REL: + err =3D emit_kasan_check(pprog, dst_reg, insn, ip, true, + accesses_stack_only); + if (err) + return err; /* smp_store_release(dst_reg + off16, src_reg) */ - emit_stx(pprog, bpf_size, dst_reg, src_reg, off); + emit_stx(pprog, BPF_SIZE(insn->code), dst_reg, src_reg, + insn->off); break; default: pr_err("bpf_jit: unknown atomic load/store opcode %02x\n", @@ -1904,6 +1917,7 @@ static int do_jit(struct bpf_verifier_env *env, struc= t bpf_prog *bpf_prog, int * const s32 imm32 =3D insn->imm; u32 dst_reg =3D insn->dst_reg; u32 src_reg =3D insn->src_reg; + bool accesses_stack_only; u8 b2 =3D 0, b3 =3D 0; u8 *start_of_ldx; s64 jmp_offset; @@ -1924,6 +1938,8 @@ static int do_jit(struct bpf_verifier_env *env, struc= t bpf_prog *bpf_prog, int * EMIT_ENDBR(); =20 ip =3D image + addrs[i - 1] + (prog - temp); + accesses_stack_only =3D + bpf_insn_accesses_stack_only(env, bpf_prog, i - 1); =20 switch (insn->code) { /* ALU */ @@ -2304,6 +2320,10 @@ static int do_jit(struct bpf_verifier_env *env, stru= ct bpf_prog *bpf_prog, int * case BPF_ST | BPF_MEM | BPF_H: case BPF_ST | BPF_MEM | BPF_W: case BPF_ST | BPF_MEM | BPF_DW: + err =3D emit_kasan_check(&prog, dst_reg, insn, ip, true, + accesses_stack_only); + if (err) + return err; switch (BPF_SIZE(insn->code)) { case BPF_B: if (is_ereg(dst_reg)) @@ -2369,6 +2389,10 @@ static int do_jit(struct bpf_verifier_env *env, stru= ct bpf_prog *bpf_prog, int * insn_off =3D outgoing_arg_base - outgoing_rsp - insn_off - 16; dst_reg =3D BPF_REG_FP; } + err =3D emit_kasan_check(&prog, dst_reg, insn, ip, true, + accesses_stack_only); + if (err) + return err; emit_stx(&prog, BPF_SIZE(insn->code), dst_reg, src_reg, insn_off); break; =20 @@ -2530,6 +2554,12 @@ static int do_jit(struct bpf_verifier_env *env, stru= ct bpf_prog *bpf_prog, int * /* populate jmp_offset for JAE above to jump to start_of_ldx */ start_of_ldx =3D prog; end_of_jmp[-1] =3D start_of_ldx - end_of_jmp; + } else { + err =3D emit_kasan_check(&prog, src_reg, insn, ip, + false, + accesses_stack_only); + if (err) + return err; } if (BPF_MODE(insn->code) =3D=3D BPF_PROBE_MEMSX || BPF_MODE(insn->code) =3D=3D BPF_MEMSX) @@ -2592,13 +2622,13 @@ static int do_jit(struct bpf_verifier_env *env, str= uct bpf_prog *bpf_prog, int * fallthrough; case BPF_STX | BPF_ATOMIC | BPF_W: case BPF_STX | BPF_ATOMIC | BPF_DW: + bool is64 =3D BPF_SIZE(insn->code) =3D=3D BPF_DW; + u32 real_src_reg =3D src_reg; + u32 real_dst_reg =3D dst_reg; + u8 *branch_target; if (insn->imm =3D=3D (BPF_AND | BPF_FETCH) || insn->imm =3D=3D (BPF_OR | BPF_FETCH) || insn->imm =3D=3D (BPF_XOR | BPF_FETCH)) { - bool is64 =3D BPF_SIZE(insn->code) =3D=3D BPF_DW; - u32 real_src_reg =3D src_reg; - u32 real_dst_reg =3D dst_reg; - u8 *branch_target; =20 /* * Can't be implemented with a single x86 insn. @@ -2612,7 +2642,19 @@ static int do_jit(struct bpf_verifier_env *env, stru= ct bpf_prog *bpf_prog, int * if (dst_reg =3D=3D BPF_REG_0) real_dst_reg =3D BPF_REG_AX; =20 + ip +=3D 3; + } + if (!bpf_atomic_is_load_store(insn)) { + err =3D emit_kasan_check(&prog, real_dst_reg, + insn, ip, false, + accesses_stack_only); + if (err) + return err; branch_target =3D prog; + } + if (insn->imm =3D=3D (BPF_AND | BPF_FETCH) || + insn->imm =3D=3D (BPF_OR | BPF_FETCH) || + insn->imm =3D=3D (BPF_XOR | BPF_FETCH)) { /* Load old value */ emit_ldx(&prog, BPF_SIZE(insn->code), BPF_REG_0, real_dst_reg, insn->off); @@ -2644,8 +2686,9 @@ static int do_jit(struct bpf_verifier_env *env, struc= t bpf_prog *bpf_prog, int * } =20 if (bpf_atomic_is_load_store(insn)) - err =3D emit_atomic_ld_st(&prog, insn->imm, dst_reg, src_reg, - insn->off, BPF_SIZE(insn->code)); + err =3D emit_atomic_ld_st(&prog, insn, ip, + dst_reg, src_reg, + accesses_stack_only); else err =3D emit_atomic_rmw(&prog, insn->imm, dst_reg, src_reg, insn->off, BPF_SIZE(insn->code)); --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 626744D2EDD; Thu, 4 Jun 2026 20:22:48 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604569; cv=none; b=W7N0YB/MFZJDc6Udz28pz5zylC9QyIM/cHiKID8RWVoZbD99I10It+BDcn0umdDSF4pB1PXKBAknieFhxd1m7SQpveXGJy4nr+Oqu7FGAhjalCOC74XhM95L3cUt3ahieLQt2R6guzWzNChXssFC46qMZEaTpDTKlIOz2X9uG2Q= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604569; c=relaxed/simple; bh=3489jLTQLhZoLbOLza0oSKGGYmXe080yYtmNNV1r6TU=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=bLSHOd6bx3axrSMHJ49JMmz7cZvMu4AoxD+POJNSUiwLY2Bc1vxdWVgUtJ1ngs6dwV8r+XKumj3+WeeRREdllZn+snJ10+8UBY59tyPIgW1JFRqxSN4De/uxS0fUlLGD3nqay27udWOvd2LFuJ9IvzSPaKHxhnDpsF8Ri7ZOxgI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=lmS+wAdJ; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="lmS+wAdJ" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id 1D79FC6344F; Thu, 4 Jun 2026 20:22:46 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id B4A095FED1; Thu, 4 Jun 2026 20:22:46 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 32563106A1D38; Thu, 4 Jun 2026 22:22:42 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604565; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=DTr9hq1BbZUfbwxQS4V0l0z3LqJ94HV11h9J+XL5gnk=; b=lmS+wAdJ/wDhwTxbEY48mzvs+wfgGH2aqa3uTHEsoYk4+egErzEzcHPpjH1AVPDeMz4PEz Db/xZC5zJYGBVAV0aWWRrcOLTCtc/aEVY57usTmqwcILSZ/aqEU53ASKhDyym4CIWnp3fq 1jyG9sD8p66txJBpYiTxH8hQrKMerm3GDYqyhSjDEAgPA2E7zbfS1fc4KAzkgSltxokMg/ sRJ4+DvgRTdpPca7SQHE4Y6Fdq1wp9YxrWJqzwNCEQx7fG5SJBeTfKl+1wpdQX+pHYuTSS W2LQNIWE80zVDuTAjqn1ibyFMKtbXwmxrxnFwSBpDBIalksKWwHjoLv/cJ3L0A== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:04 +0200 Subject: [PATCH bpf-next v2 6/8] bpf, x86: enable KASAN for JITed programs on x86 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-6-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 Mark x86 as supporting KASAN checks in JITed programs so that the corresponding JIT compiler inserts checks on the translated instructions. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- arch/x86/Kconfig | 1 + 1 file changed, 1 insertion(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index f3f7cb01d69d..cc140108b74c 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -235,6 +235,7 @@ config X86 select HAVE_SAMPLE_FTRACE_DIRECT if X86_64 select HAVE_SAMPLE_FTRACE_DIRECT_MULTI if X86_64 select HAVE_EBPF_JIT + select HAVE_EBPF_JIT_KASAN if X86_64 select HAVE_EFFICIENT_UNALIGNED_ACCESS select HAVE_EISA if X86_32 select HAVE_EXIT_THREAD --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id A74DA4D2EFE for ; Thu, 4 Jun 2026 20:22:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604573; cv=none; b=qZ9tUzWJCZiBBpgmwDejlTh0RKppa6HB4yXqqbXX9nEv0AC1TDFJGK9t0VVnfJMOWYtw1ihnXU+CHTVICcGmY2qgOqXzlaxhnL7pVkA8vkg6BbwxWUBMHqhrWTYhPBJO84wlxPVTKL5GjcNY7pZ2aVwfD69xiciJjKLd3EY0jQI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604573; c=relaxed/simple; bh=etE+N/MlYVxSd4KeNUi+uyfU/waPnCA4ygyLzHNTOPc=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=ROqai/Z5hViXXAu/y/1bPgge0hN0ub9jBXs1nkGxKGSuoiHkGcA8LDjuZ2oOftclMlTND63vo2cuSKw1kAVx87fjdvE/gVzAdkuYSQBwn967AamLMzDYcFyyKMJFgCkEtNLmTuAIl2gV9ygNG1KKhRa7UsvSmRGhLqwQBiFlyrI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=KTpHMHUm; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="KTpHMHUm" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id C0FBFC63454; Thu, 4 Jun 2026 20:22:49 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 6404E5FED1; Thu, 4 Jun 2026 20:22:50 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id AC515106A1D46; Thu, 4 Jun 2026 22:22:45 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604568; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=wdlnHacym1R+fO8OXKjuu51Mo8jbgvgR2Hwxia5FoqM=; b=KTpHMHUmYVt111uGM7eQqwYj9AulLvr+vlSfy6ula6hCrNgH25/QWQyT21VsOXOllIQdS2 SGroiXJx4rPG6CiYkX0WaeOwB39DOR+gvnCS741uKM2g9loglRN0WX8YM+2QaahVHuejho M7LLi65ONCib5M026f6KM8wOe9EefpfZiChi3gNrGnYwmGRmcpNVqKEywt4EJ60gx/VLEc 1xF+hsIoIOz7m7NPlV4DGxfdGgaNg4rOlVnn8ayjQKJut3wuCa+ipTm3zNH4UYEAZx+hNO e9kAh9D1LSVtRkG1ysOV5BFni4K27yHcrfnKVj517lJPXhDIAXDKIctWVjA02A== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:05 +0200 Subject: [PATCH bpf-next v2 7/8] selftests/bpf: add helper to check whether eBPF KASAN is active Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-7-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 Add a simple helper checking whether JIT compiler is able to insert KASAN checks in programs. This will allow to conditionally run selftests for KASAN checks in JITed programs. Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- Changes in v2: - fix condition --- tools/testing/selftests/bpf/unpriv_helpers.c | 5 +++++ tools/testing/selftests/bpf/unpriv_helpers.h | 1 + 2 files changed, 6 insertions(+) diff --git a/tools/testing/selftests/bpf/unpriv_helpers.c b/tools/testing/s= elftests/bpf/unpriv_helpers.c index f997d7ec8fd0..11201b65a3d4 100644 --- a/tools/testing/selftests/bpf/unpriv_helpers.c +++ b/tools/testing/selftests/bpf/unpriv_helpers.c @@ -142,3 +142,8 @@ bool get_unpriv_disabled(void) } return mitigations_off; } + +bool get_kasan_jit_enabled(void) +{ + return config_contains("CONFIG_BPF_JIT_KASAN=3Dy") =3D=3D 1; +} diff --git a/tools/testing/selftests/bpf/unpriv_helpers.h b/tools/testing/s= elftests/bpf/unpriv_helpers.h index 151f67329665..bc5f4c953c9d 100644 --- a/tools/testing/selftests/bpf/unpriv_helpers.h +++ b/tools/testing/selftests/bpf/unpriv_helpers.h @@ -5,3 +5,4 @@ #define UNPRIV_SYSCTL "kernel/unprivileged_bpf_disabled" =20 bool get_unpriv_disabled(void); +bool get_kasan_jit_enabled(void); --=20 2.54.0 From nobody Mon Jun 8 07:22:56 2026 Received: from smtpout-04.galae.net (smtpout-04.galae.net [185.171.202.116]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 666DA4D8DA1 for ; Thu, 4 Jun 2026 20:22:55 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=185.171.202.116 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604581; cv=none; b=Uc0gZmskCIWiZJ7E8XDYmI8ewBOs2RgyiQ8MOlR3vdHP+dP9UI8C7WrfKEalkVtrtvYTkTTA7oPmurkysZUTh3/rapws39UNw3XyBS5sWBp+bJeLZID5UFXLg8NiSAnb/SkOj89Cq8ZvbwVR9DP11GNFg/X/T/Mt/NRUvSBwisM= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1780604581; c=relaxed/simple; bh=Qjn4mik60Scxo8rRNRsuC8KlIr2HBzSjiYJ0R/jj42M=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:References: In-Reply-To:To:Cc; b=KaYreS0CQZRJ+4gPkVaxZO/puj/7K1Q/AdgKJnaUztvJVRm4Z7HNXiIbf4KtShIcApWchRUX5Aj0xIoXiyFVhF20BKH3beSc70K84OtfRlIdtyIUO+8j/PerDx55kA2v/7vWyzSwWJD8UfNi5v4IX6+x3GLviOXup93PXL6EOB4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com; spf=pass smtp.mailfrom=bootlin.com; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b=J4UzzkKR; arc=none smtp.client-ip=185.171.202.116 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=bootlin.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=bootlin.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=bootlin.com header.i=@bootlin.com header.b="J4UzzkKR" Received: from smtpout-01.galae.net (smtpout-01.galae.net [212.83.139.233]) by smtpout-04.galae.net (Postfix) with ESMTPS id B1C86C6344F; Thu, 4 Jun 2026 20:22:53 +0000 (UTC) Received: from mail.galae.net (mail.galae.net [212.83.136.155]) by smtpout-01.galae.net (Postfix) with ESMTPS id 5551B5FED1; Thu, 4 Jun 2026 20:22:54 +0000 (UTC) Received: from [127.0.0.1] (localhost [127.0.0.1]) by localhost (Mailerdaemon) with ESMTPSA id 62FE5106A1D45; Thu, 4 Jun 2026 22:22:49 +0200 (CEST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=bootlin.com; s=dkim; t=1780604572; h=from:subject:date:message-id:to:cc:mime-version:content-type: content-transfer-encoding:in-reply-to:references; bh=n2IVgNtqwqyOrL8sV0OndjLx3yPkOiO2dKXdQe2n4xU=; b=J4UzzkKRUkUGMie49EH2BlP5rmV6WvWqof5s7jF1pAdPFwL87N9Wj+otR7ZEcc547bq6Me G3MQbzD+uOOQVcLKJfwZjiu79IdsFrUG75ju+/tZ6Wahe0ZXso04syHEJFdNMg54mK03vs HJz9vhBQHqD6IXv1yz9UkZhXP5kOR2C923q7W41AJe3ga/KLbMV/qNlTN7h8r/uXVoOsPH UiuVFbaMmQMC/QyNwREw7K8R+YMPRnX/qnKzxBV02odOLfTF9dCI1AYVnJk0ODsMBpnjxp o10QsAXexn3Zg9CnbupiecQlSirIuYJc2hYbk7XnIWXkOaZ3zfbLyKFjROPY5A== From: =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= Date: Thu, 04 Jun 2026 22:22:06 +0200 Subject: [PATCH bpf-next v2 8/8] selftests/bpf: add tests to validate KASAN on JIT programs Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260604-kasan-v2-8-c066e627fda8@bootlin.com> References: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> In-Reply-To: <20260604-kasan-v2-0-c066e627fda8@bootlin.com> To: Alexei Starovoitov , Daniel Borkmann , Andrii Nakryiko , Martin KaFai Lau , Eduard Zingerman , Kumar Kartikeya Dwivedi , Song Liu , Yonghong Song , Jiri Olsa , John Fastabend , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Shuah Khan , Maxime Coquelin , Alexandre Torgue , Ihor Solodrai Cc: ebpf@linuxfoundation.org, Bastien Curutchet , Thomas Petazzoni , 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, =?utf-8?q?Alexis_Lothor=C3=A9_=28eBPF_Foundation=29?= X-Mailer: b4 0.15.2 X-Last-TLS-Session-Version: TLSv1.3 Add a basic KASAN test runner that loads and test-run programs that can trigger memory management bugs. The test captures kernel logs and ensure that the expected KASAN splat is emitted by searching for the corresponding first lines in the report, hence validated that the needed instrumentation has been inserted by the JIT compiler before the relevant memory accesses. The runner covers different cases and settings: in the nominal case, it validates kasan reports on basic instructions (on all supported accesses sizes) but also when report _should not_ be emitted (eg: for accesses on program stack). The runner also comes with a few specialized tests that are then not executed for all sizes/locations. A few of those tests depends on cpuv4 (load_acquire and store_release). # ./test_progs -a kasan #164/1 kasan/st_1_not_on_stack:OK #164/2 kasan/st_1_on_stack:OK #164/3 kasan/st_2_not_on_stack:OK #164/4 kasan/st_2_on_stack:OK #164/5 kasan/st_4_not_on_stack:OK #164/6 kasan/st_4_on_stack:OK #164/7 kasan/st_8_not_on_stack:OK #164/8 kasan/st_8_on_stack:OK #164/9 kasan/stx_1_not_on_stack:OK #164/10 kasan/stx_1_on_stack:OK #164/11 kasan/stx_2_not_on_stack:OK #164/12 kasan/stx_2_on_stack:OK #164/13 kasan/stx_4_not_on_stack:OK #164/14 kasan/stx_4_on_stack:OK #164/15 kasan/stx_8_not_on_stack:OK #164/16 kasan/stx_8_on_stack:OK #164/17 kasan/ldx_1_not_on_stack:OK #164/18 kasan/ldx_1_on_stack:OK #164/19 kasan/ldx_2_not_on_stack:OK #164/20 kasan/ldx_2_on_stack:OK #164/21 kasan/ldx_4_not_on_stack:OK #164/22 kasan/ldx_4_on_stack:OK #164/23 kasan/ldx_8_not_on_stack:OK #164/24 kasan/ldx_8_on_stack:OK #164/25 kasan/simple_atomic_4_not_on_stack:OK #164/26 kasan/simple_atomic_4_on_stack:OK #164/27 kasan/simple_atomic_8_not_on_stack:OK #164/28 kasan/simple_atomic_8_on_stack:OK #164/29 kasan/load_acquire_1_not_on_stack:SKIP #164/30 kasan/load_acquire_1_on_stack:SKIP #164/31 kasan/load_acquire_2_not_on_stack:SKIP #164/32 kasan/load_acquire_2_on_stack:SKIP #164/33 kasan/load_acquire_4_not_on_stack:SKIP #164/34 kasan/load_acquire_4_on_stack:SKIP #164/35 kasan/load_acquire_8_not_on_stack:SKIP #164/36 kasan/load_acquire_8_on_stack:SKIP #164/37 kasan/store_release_1_not_on_stack:SKIP #164/38 kasan/store_release_1_on_stack:SKIP #164/39 kasan/store_release_2_not_on_stack:SKIP #164/40 kasan/store_release_2_on_stack:SKIP #164/41 kasan/store_release_4_not_on_stack:SKIP #164/42 kasan/store_release_4_on_stack:SKIP #164/43 kasan/store_release_8_not_on_stack:SKIP #164/44 kasan/store_release_8_on_stack:SKIP #164/45 kasan/ldx_patched:OK #164/46 kasan/stack_and_non_stack:OK #164 kasan:OK (SKIP: 16/46) Summary: 1/30 PASSED, 16 SKIPPED, 0 FAILED Signed-off-by: Alexis Lothor=C3=A9 (eBPF Foundation) --- Changes in v2: - simplify tests by just manually poisoning test areas with a dedicated kfunc - introduce one prog per covered instruction family - make sure that tests do not consume kernel logs (use /dev/kmgs rather than klogctl) - add tests for stack accesses: - marking correctly set when there are diverging verifier states leading to different memory types - marking kept in sync with prog when it is patched --- tools/testing/selftests/bpf/prog_tests/kasan.c | 356 +++++++++++++++++= ++ tools/testing/selftests/bpf/progs/kasan.c | 382 +++++++++++++++++= ++++ .../testing/selftests/bpf/test_kmods/bpf_testmod.c | 22 ++ 3 files changed, 760 insertions(+) diff --git a/tools/testing/selftests/bpf/prog_tests/kasan.c b/tools/testing= /selftests/bpf/prog_tests/kasan.c new file mode 100644 index 000000000000..adf61e230ec9 --- /dev/null +++ b/tools/testing/selftests/bpf/prog_tests/kasan.c @@ -0,0 +1,356 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause +#include +#include +#include +#include +#include +#include +#include +#include "kasan.skel.h" + +#define SUBTEST_NAME_MAX_LEN 128 +#define PROG_NAME_MAX_LEN 128 + +#define MAX_LOG_SIZE (8 * 1024) +#define READ_CHUNK_SIZE 256 + +#define KASAN_PATTERN_SLAB_UAF "BUG: KASAN: slab-use-after-free " \ + "in bpf_prog_%02x%02x%02x%02x%02x%02x%02x%02x_%s" +#define KASAN_PATTERN_REPORT "%s of size %d at addr" + +static char klog_buffer[MAX_LOG_SIZE]; + +struct test_spec { + char *prog_type; + bool is_write; + bool only_32_or_64; + bool needs_load_acq_store_rel; + bool skip_multi_size_testing; + bool skip_on_stack_testing; + int run_size; + bool expect_no_report; + bool rnd_hi32; +}; + +struct kasan_write_val { + __u8 data_1; + __u16 data_2; + __u32 data_4; + __u64 data_8; +}; + +struct test_ctx { + __u8 prog_tag[BPF_TAG_SIZE]; + struct kasan *skel; + struct bpf_program *prog; + char prog_name[SUBTEST_NAME_MAX_LEN]; + int klog_fd; +}; + +static int open_kernel_logs(void) +{ + int fd; + + fd =3D open("/dev/kmsg", O_RDONLY | O_NONBLOCK); + + return fd; +} + +static void skip_kernel_logs(int fd) +{ + lseek(fd, 0, SEEK_END); +} + +static int read_kernel_logs(int fd, char *buf, size_t max_len) +{ + char record[512]; + size_t total =3D 0; + ssize_t n; + + buf[0] =3D '\0'; + while (1) { + char *msg, *eol; + size_t len; + + n =3D read(fd, record, sizeof(record) - 1); + if (n < 0) { + if (errno =3D=3D EAGAIN) + break; + return n; + } + record[n] =3D '\0'; + + /* Each kmsg record starts with some metadata, separated + * from the actual content by a semi-colon + */ + msg =3D strchr(record, ';'); + if (!msg) + continue; + msg++; + eol =3D strchr(msg, '\n'); + if (eol) + *eol =3D '\0'; + + len =3D strlen(msg); + if (total + len + 2 > max_len) + break; + memcpy(buf + total, msg, len); + total +=3D len; + buf[total++] =3D '\n'; + buf[total] =3D '\0'; + } + + return total; +} + +static int check_kasan_report_in_kernel_logs(char *buf, struct test_ctx *c= tx, + bool is_write, int size) +{ + char *access_desc_start, *access_desc_end, *tmp; + char access_log[READ_CHUNK_SIZE]; + char *kasan_report_start; + int nsize; + + snprintf(access_log, READ_CHUNK_SIZE, KASAN_PATTERN_SLAB_UAF, + ctx->prog_tag[0], ctx->prog_tag[1], ctx->prog_tag[2], + ctx->prog_tag[3], ctx->prog_tag[4], ctx->prog_tag[5], + ctx->prog_tag[6], ctx->prog_tag[7], ctx->prog_name); + /* Searched kasan report is valid if + * - it contains the expected kasan pattern + * - the next line is the description of the faulty access + * - faulty access properties match the tested type and size + */ + kasan_report_start =3D strstr(buf, access_log); + + if (!kasan_report_start) + return 1; + + /* Find next line */ + access_desc_start =3D strchr(kasan_report_start, '\n'); + if (!access_desc_start) + return 1; + access_desc_start++; + + access_desc_end =3D strchr(access_desc_start, '\n'); + if (!access_desc_end) + return 1; + + nsize =3D snprintf(access_log, READ_CHUNK_SIZE, KASAN_PATTERN_REPORT, + is_write ? "Write" : "Read", size); + + tmp =3D memmem(access_desc_start, access_desc_end - access_desc_start, + access_log, nsize); + + if (!tmp) + return 1; + + return 0; +} + +static void run_subtest_with_size_and_location(struct test_ctx *ctx, + struct test_spec *test, + int access_size, + bool on_stack) +{ + char subtest_name[SUBTEST_NAME_MAX_LEN]; + char prog_name[PROG_NAME_MAX_LEN]; + struct bpf_prog_info info; + uint8_t buf[ETH_HLEN]; + __u32 info_len; + int ret; + + if (test->skip_multi_size_testing) { + snprintf(subtest_name, SUBTEST_NAME_MAX_LEN, "%s", + test->prog_type); + strncpy(prog_name, test->prog_type, PROG_NAME_MAX_LEN); + } else { + snprintf(subtest_name, SUBTEST_NAME_MAX_LEN, "%s_%d_%s", + test->prog_type, access_size, + on_stack ? "on_stack" : "not_on_stack"); + snprintf(prog_name, PROG_NAME_MAX_LEN, "%s_%s", test->prog_type, + on_stack ? "on_stack" : "not_on_stack"); + } + + if (!test__start_subtest(subtest_name)) + return; + + if (test->needs_load_acq_store_rel && + ctx->skel->data->skip_load_acq_store_rel_tests) { + test__skip(); + return; + } + + ctx->prog =3D bpf_object__find_program_by_name(ctx->skel->obj, prog_name); + if (!ASSERT_OK_PTR(ctx->prog, "find test prog")) + return; + + info_len =3D sizeof(info); + memset(&info, 0, info_len); + ret =3D bpf_prog_get_info_by_fd(bpf_program__fd(ctx->prog), &info, + &info_len); + if (!ASSERT_OK(ret, "fetch loaded program info")) + return; + memcpy(ctx->prog_tag, info.tag, BPF_TAG_SIZE); + + skip_kernel_logs(ctx->klog_fd); + + LIBBPF_OPTS(bpf_test_run_opts, topts); + topts.sz =3D sizeof(struct bpf_test_run_opts); + topts.data_size_in =3D ETH_HLEN; + topts.data_in =3D buf; + ctx->skel->bss->access_size =3D access_size; + ret =3D bpf_prog_test_run_opts(bpf_program__fd(ctx->prog), + &topts); + if (!ASSERT_OK(ret, "run prog")) + return; + + ret =3D read_kernel_logs(ctx->klog_fd, klog_buffer, MAX_LOG_SIZE); + if (!ASSERT_GE(ret, 0, "read kernel logs")) + return; + + ret =3D check_kasan_report_in_kernel_logs(klog_buffer, ctx, + test->is_write, access_size); + if (on_stack || test->expect_no_report) + ASSERT_NEQ(ret, 0, "no report should be generated"); + else + ASSERT_OK(ret, "report should be generated"); +} + +static void run_subtest_with_size(struct test_ctx *ctx, struct test_spec *= test, + int size) +{ + run_subtest_with_size_and_location(ctx, test, size, false); + if (!test->skip_on_stack_testing) + run_subtest_with_size_and_location(ctx, test, size, true); +} + +static void run_subtest(struct test_ctx *ctx, struct test_spec *test) +{ + if (test->skip_multi_size_testing) { + run_subtest_with_size(ctx, test, test->run_size); + return; + } + + if (!test->only_32_or_64) { + run_subtest_with_size(ctx, test, 1); + run_subtest_with_size(ctx, test, 2); + } + run_subtest_with_size(ctx, test, 4); + run_subtest_with_size(ctx, test, 8); +} + +static struct test_spec tests[] =3D { + { + .prog_type =3D "st", + .is_write =3D true + }, + { + .prog_type =3D "stx", + .is_write =3D true + }, + { + .prog_type =3D "ldx", + .is_write =3D false + }, + { + .prog_type =3D "simple_atomic", + .is_write =3D false, + .only_32_or_64 =3D true + }, + { + .prog_type =3D "load_acquire", + .is_write =3D false, + .needs_load_acq_store_rel =3D true + }, + { + .prog_type =3D "store_release", + .is_write =3D true, + .needs_load_acq_store_rel =3D true + }, + { + .prog_type =3D "ldx_patched", + .is_write =3D false, + .skip_multi_size_testing =3D true, + .skip_on_stack_testing =3D true, + .run_size =3D 4, + /* Make the verifier patch instruction to test + * adjust_insn_aux_data logic + */ + .rnd_hi32 =3D true + }, + { + .prog_type =3D "stack_and_non_stack", + .is_write =3D true, + .skip_multi_size_testing =3D true, + .skip_on_stack_testing =3D true, + .run_size =3D 1 + } +}; + +void test_kasan(void) +{ + struct kasan_write_val val; + struct test_spec *test; + struct test_ctx *ctx; + __u32 key =3D 0; + int i, ret; + + ctx =3D calloc(1, sizeof(struct test_ctx)); + if (!ASSERT_OK_PTR(ctx, "alloc test ctx")) + return; + + if (!is_jit_enabled() || !get_kasan_jit_enabled()) { + test__skip(); + goto end; + } + + ctx->skel =3D kasan__open(); + if (!ASSERT_OK_PTR(ctx->skel, "open prog")) + goto end; + + for (i =3D 0; i < ARRAY_SIZE(tests); i++) { + struct bpf_program *prog; + + if (!tests[i].rnd_hi32) + continue; + + prog =3D bpf_object__find_program_by_name(ctx->skel->obj, + tests[i].prog_type); + if (!ASSERT_OK_PTR(prog, "find rnd_hi32 prog")) + goto destroy; + bpf_program__set_flags(prog, BPF_F_TEST_RND_HI32); + } + + if (!ASSERT_OK(kasan__load(ctx->skel), "load prog")) + goto destroy; + + ctx->klog_fd =3D open_kernel_logs(); + if (!ASSERT_OK_FD(ctx->klog_fd, "open kernel logs")) + goto destroy; + + /* Fill map with recognizable values */ + ret =3D bpf_map__lookup_elem(ctx->skel->maps.test_map, &key, sizeof(key), + &val, sizeof(val), 0); + if (!ASSERT_OK(ret, "get map")) + goto close; + val.data_1 =3D 0xAA; + val.data_2 =3D 0xBBBB; + val.data_4 =3D 0xCCCCCCCC; + val.data_8 =3D 0xDDDDDDDDDDDDDDDD; + ret =3D bpf_map__update_elem(ctx->skel->maps.test_map, &key, sizeof(key), + &val, sizeof(val), 0); + if (!ASSERT_OK(ret, "set map")) + goto close; + + for (i =3D 0; i < ARRAY_SIZE(tests); i++) { + test =3D &tests[i]; + run_subtest(ctx, test); + } + +close: + close(ctx->klog_fd); +destroy: + kasan__destroy(ctx->skel); +end: + free(ctx); +} diff --git a/tools/testing/selftests/bpf/progs/kasan.c b/tools/testing/self= tests/bpf/progs/kasan.c new file mode 100644 index 000000000000..670318a956a4 --- /dev/null +++ b/tools/testing/selftests/bpf/progs/kasan.c @@ -0,0 +1,382 @@ +// SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause + +#include +#include +#include +#include "bpf_misc.h" +#include + +extern void bpf_kfunc_kasan_poison(void *mem, __u32 mem__sz) __ksym; +extern void bpf_kfunc_kasan_unpoison(void *mem, __u32 mem__sz) __ksym; + +int access_size; + +struct kasan_write_val { + __u8 data_1; + __u16 data_2; + __u32 data_4; + __u64 data_8; +}; + +struct { + __uint(type, BPF_MAP_TYPE_ARRAY); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, struct kasan_write_val); +} test_map SEC(".maps"); + +SEC("tcx/ingress") +int st_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + val.data_1 =3D 0xAA; + break; + case 2: + val.data_2 =3D 0xAA; + break; + case 4: + val.data_4 =3D 0xAA; + break; + case 8: + val.data_8 =3D 0xAA; + break; + } + bpf_kfunc_kasan_unpoison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int st_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + val->data_1 =3D 0xAA; + break; + case 2: + val->data_2 =3D 0xAA; + break; + case 4: + val->data_4 =3D 0xAA; + break; + case 8: + val->data_8 =3D 0xAA; + break; + } + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int stx_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + val.data_1 =3D access_size; + break; + case 2: + val.data_2 =3D access_size; + break; + case 4: + val.data_4 =3D access_size; + break; + case 8: + val.data_8 =3D access_size; + break; + } + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int stx_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + val->data_1 =3D access_size; + break; + case 2: + val->data_2 =3D access_size; + break; + case 4: + val->data_4 =3D access_size; + break; + case 8: + val->data_8 =3D access_size; + break; + } + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int ldx_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __sink(val.data_1); + break; + case 2: + __sink(val.data_2); + break; + case 4: + __sink(val.data_4); + break; + case 8: + __sink(val.data_8); + break; + } + bpf_kfunc_kasan_unpoison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int ldx_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __sink(val->data_1); + break; + case 2: + __sink(val->data_2); + break; + case 4: + __sink(val->data_4); + break; + case 8: + __sink(val->data_8); + break; + } + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int ldx_patched(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + __sink(val->data_4); + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + + return 0; +} + +SEC("tcx/ingress") +int simple_atomic_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 4: + __sync_fetch_and_add(&val.data_4, 4); + break; + case 8: + __sync_fetch_and_add(&val.data_8, 8); + break; + } + bpf_kfunc_kasan_unpoison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int simple_atomic_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 4: + __sync_fetch_and_add(&val->data_4, 4); + break; + case 8: + __sync_fetch_and_add(&val->data_8, 8); + break; + } + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + return 0; +} + +#ifdef __BPF_FEATURE_LOAD_ACQ_STORE_REL +bool skip_load_acq_store_rel_tests __attribute__((section(".data"))) =3D 0; + +SEC("tcx/ingress") +int load_acquire_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __atomic_load_n(&val.data_1, __ATOMIC_ACQUIRE); + break; + case 2: + __atomic_load_n(&val.data_2, __ATOMIC_ACQUIRE); + break; + case 4: + __atomic_load_n(&val.data_4, __ATOMIC_ACQUIRE); + break; + case 8: + __atomic_load_n(&val.data_8, __ATOMIC_ACQUIRE); + break; + } + bpf_kfunc_kasan_unpoison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int load_acquire_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __atomic_load_n(&val->data_1, __ATOMIC_ACQUIRE); + break; + case 2: + __atomic_load_n(&val->data_2, __ATOMIC_ACQUIRE); + break; + case 4: + __atomic_load_n(&val->data_4, __ATOMIC_ACQUIRE); + break; + case 8: + __atomic_load_n(&val->data_8, __ATOMIC_ACQUIRE); + break; + } + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int store_release_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val val; + + bpf_kfunc_kasan_poison(&val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __atomic_store_n(&val.data_1, 0xAA, __ATOMIC_RELEASE); + break; + case 2: + __atomic_store_n(&val.data_2, 0xBBBB, __ATOMIC_RELEASE); + break; + case 4: + __atomic_store_n(&val.data_4, 0xCCCCCCCC, __ATOMIC_RELEASE); + break; + case 8: + __atomic_store_n(&val.data_8, 0xDDDDDDDDDDDDDDDD, + __ATOMIC_RELEASE); + break; + } + bpf_kfunc_kasan_unpoison(&val, sizeof(struct kasan_write_val)); + return 0; +} + +SEC("tcx/ingress") +int store_release_not_on_stack(struct __sk_buff *skb) +{ + struct kasan_write_val *val; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + bpf_kfunc_kasan_poison(val, sizeof(struct kasan_write_val)); + switch (access_size) { + case 1: + __atomic_store_n(&val->data_1, 0xAA, __ATOMIC_RELEASE); + break; + case 2: + __atomic_store_n(&val->data_2, 0xBBBB, __ATOMIC_RELEASE); + break; + case 4: + __atomic_store_n(&val->data_4, 0xCCCCCCCC, __ATOMIC_RELEASE); + break; + case 8: + __atomic_store_n(&val->data_8, 0xDDDDDDDDDDDDDDDD, + __ATOMIC_RELEASE); + break; + } + bpf_kfunc_kasan_unpoison(val, sizeof(struct kasan_write_val)); + return 0; +} +#else +bool skip_load_acq_store_rel_tests __attribute__((section(".data"))) =3D 1; +#endif + +SEC("tcx/ingress") +int stack_and_non_stack(struct __sk_buff *skb) +{ + struct kasan_write_val stack_val =3D {}; + struct kasan_write_val *val; + void *ptr; + __u32 key =3D 0; + + val =3D bpf_map_lookup_elem(&test_map, &key); + if (!val) + return 0; + + if (access_size) + ptr =3D val; + else + ptr =3D &stack_val; + + bpf_kfunc_kasan_poison(val, sizeof(*val)); + *(__u8 *)ptr =3D 0xAA; + bpf_kfunc_kasan_unpoison(val, sizeof(*val)); + return 0; +} + +char LICENSE[] SEC("license") =3D "GPL"; diff --git a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c b/tools/t= esting/selftests/bpf/test_kmods/bpf_testmod.c index 30f1cd23093c..09a502a1742f 100644 --- a/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c +++ b/tools/testing/selftests/bpf/test_kmods/bpf_testmod.c @@ -271,6 +271,26 @@ __bpf_kfunc void bpf_kfunc_put_default_trusted_ptr_tes= t(struct prog_test_member */ } =20 +#ifdef CONFIG_KASAN_GENERIC + +extern void kasan_poison(const void *addr, size_t size, u8 value, bool ini= t); + +#define KASAN_SLAB_FREE 0xFB + +__bpf_kfunc void bpf_kfunc_kasan_poison(void *mem, u32 mem__sz) +{ + kasan_poison(mem, mem__sz, KASAN_SLAB_FREE, false); +} + +__bpf_kfunc void bpf_kfunc_kasan_unpoison(void *mem, u32 mem__sz) +{ + kasan_poison(mem, mem__sz, 0x00, false); +} +#else +__bpf_kfunc void bpf_kfunc_kasan_poison(void *mem, u32 mem__sz) { } +__bpf_kfunc void bpf_kfunc_kasan_unpoison(void *mem, u32 mem__sz) { } +#endif + __bpf_kfunc struct bpf_testmod_ctx * bpf_testmod_ctx_create(int *err) { @@ -740,6 +760,8 @@ BTF_ID_FLAGS(func, bpf_testmod_ops3_call_test_1) BTF_ID_FLAGS(func, bpf_testmod_ops3_call_test_2) BTF_ID_FLAGS(func, bpf_kfunc_get_default_trusted_ptr_test); BTF_ID_FLAGS(func, bpf_kfunc_put_default_trusted_ptr_test); +BTF_ID_FLAGS(func, bpf_kfunc_kasan_poison) +BTF_ID_FLAGS(func, bpf_kfunc_kasan_unpoison) BTF_KFUNCS_END(bpf_testmod_common_kfunc_ids) =20 BTF_ID_LIST(bpf_testmod_dtor_ids) --=20 2.54.0