* [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED
@ 2025-07-02 7:36 Eduard Zingerman
2025-07-02 7:36 ` [PATCH bpf-next v1 2/2] selftests/bpf: null checks for rdonly_untrusted_mem should be preserved Eduard Zingerman
2025-07-02 15:00 ` [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED patchwork-bot+netdevbpf
0 siblings, 2 replies; 3+ messages in thread
From: Eduard Zingerman @ 2025-07-02 7:36 UTC (permalink / raw)
To: bpf, ast
Cc: andrii, daniel, martin.lau, kernel-team, yonghong.song,
Eduard Zingerman, Alexei Starovoitov
Commit f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
added a notion of PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED type.
This simultaneously introduced a bug in jump prediction logic for
situations like below:
p = bpf_rdonly_cast(..., 0);
if (p) a(); else b();
Here verifier would wrongly predict that else branch cannot be taken.
This happens because:
- Function reg_not_null() assumes that PTR_TO_MEM w/o PTR_MAYBE_NULL
flag cannot be zero.
- The call to bpf_rdonly_cast() returns a rdonly_untrusted_mem value
w/o PTR_MAYBE_NULL flag.
Tracking of PTR_MAYBE_NULL flag for untrusted PTR_TO_MEM does not make
sense, as the main purpose of the flag is to catch null pointer access
errors. Such errors are not possible on load of PTR_UNTRUSTED values
and verifier makes sure that PTR_UNTRUSTED can't be passed to helpers
or kfuncs.
Hence, modify reg_not_null() to assume that nullness of untrusted
PTR_TO_MEM is not known.
Fixes: f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
Suggested-by: Alexei Starovoitov <alexei.starovoitov@gmail.com>
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
kernel/bpf/verifier.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index a352b35be479..525a21dbcce3 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -410,7 +410,7 @@ static bool reg_not_null(const struct bpf_reg_state *reg)
type == PTR_TO_MAP_KEY ||
type == PTR_TO_SOCK_COMMON ||
(type == PTR_TO_BTF_ID && is_trusted_reg(reg)) ||
- type == PTR_TO_MEM ||
+ (type == PTR_TO_MEM && !(reg->type & PTR_UNTRUSTED)) ||
type == CONST_PTR_TO_MAP;
}
--
2.49.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* [PATCH bpf-next v1 2/2] selftests/bpf: null checks for rdonly_untrusted_mem should be preserved
2025-07-02 7:36 [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED Eduard Zingerman
@ 2025-07-02 7:36 ` Eduard Zingerman
2025-07-02 15:00 ` [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: Eduard Zingerman @ 2025-07-02 7:36 UTC (permalink / raw)
To: bpf, ast
Cc: andrii, daniel, martin.lau, kernel-team, yonghong.song,
Eduard Zingerman
Test case checking that verifier does not assume rdonly_untrusted_mem
values as not null.
Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
---
.../bpf/progs/mem_rdonly_untrusted.c | 21 +++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c b/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
index b0486af36f55..8185130ede95 100644
--- a/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
+++ b/tools/testing/selftests/bpf/progs/mem_rdonly_untrusted.c
@@ -174,4 +174,25 @@ int misaligned_access(void *ctx)
return combine(bpf_rdonly_cast(&global, 0) + 1);
}
+__weak int return_one(void)
+{
+ return 1;
+}
+
+SEC("socket")
+__success
+__retval(1)
+int null_check(void *ctx)
+{
+ int *p;
+
+ p = bpf_rdonly_cast(0, 0);
+ if (p == 0)
+ /* make this a function call to avoid compiler
+ * moving r0 assignment before check.
+ */
+ return return_one();
+ return 0;
+}
+
char _license[] SEC("license") = "GPL";
--
2.49.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* Re: [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED
2025-07-02 7:36 [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED Eduard Zingerman
2025-07-02 7:36 ` [PATCH bpf-next v1 2/2] selftests/bpf: null checks for rdonly_untrusted_mem should be preserved Eduard Zingerman
@ 2025-07-02 15:00 ` patchwork-bot+netdevbpf
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-07-02 15:00 UTC (permalink / raw)
To: Eduard Zingerman
Cc: bpf, ast, andrii, daniel, martin.lau, kernel-team, yonghong.song,
alexei.starovoitov
Hello:
This series was applied to bpf/bpf-next.git (master)
by Alexei Starovoitov <ast@kernel.org>:
On Wed, 2 Jul 2025 00:36:19 -0700 you wrote:
> Commit f2362a57aeff ("bpf: allow void* cast using bpf_rdonly_cast()")
> added a notion of PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED type.
> This simultaneously introduced a bug in jump prediction logic for
> situations like below:
>
> p = bpf_rdonly_cast(..., 0);
> if (p) a(); else b();
>
> [...]
Here is the summary with links:
- [bpf-next,v1,1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED
https://git.kernel.org/bpf/bpf-next/c/c8313bad6d24
- [bpf-next,v1,2/2] selftests/bpf: null checks for rdonly_untrusted_mem should be preserved
https://git.kernel.org/bpf/bpf-next/c/621af1928153
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2025-07-02 14:59 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-07-02 7:36 [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED Eduard Zingerman
2025-07-02 7:36 ` [PATCH bpf-next v1 2/2] selftests/bpf: null checks for rdonly_untrusted_mem should be preserved Eduard Zingerman
2025-07-02 15:00 ` [PATCH bpf-next v1 1/2] bpf: avoid jump misprediction for PTR_TO_MEM | PTR_UNTRUSTED patchwork-bot+netdevbpf
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.