* [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates
@ 2026-06-24 7:20 Sun Jian
2026-06-24 7:20 ` [PATCH bpf 2/2] selftests/bpf: Add inner map template lookup NULLness test Sun Jian
2026-06-24 7:37 ` [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates sashiko-bot
0 siblings, 2 replies; 4+ messages in thread
From: Sun Jian @ 2026-06-24 7:20 UTC (permalink / raw)
To: bpf
Cc: sun.jian.kdev, linux-kernel, linux-kselftest, ast, daniel,
john.fastabend, andrii, martin.lau, eddyz87, memxor, song,
yonghong.song, jolsa, shuah, dxu
Commit d2102f2f5d75 ("bpf: verifier: Support eliding map lookup
nullness") allowed the verifier to elide NULLness of
bpf_map_lookup_elem() for array maps when the key is statically known to
be within max_entries.
This is not valid for array maps used as inner map templates. For such
maps, the template's max_entries is not necessarily the same as the
max_entries of the concrete inner map used at runtime. As a result, a
key that is within the template's max_entries can still be out of range
for the concrete inner map, and the lookup may return NULL.
Do not elide lookup NULLness for array maps used as inner map templates.
Fixes: d2102f2f5d75 ("bpf: verifier: Support eliding map lookup nullness")
Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
---
kernel/bpf/verifier.c | 1 +
1 file changed, 1 insertion(+)
diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
index 7fb88e1cd7c4..3f38f85c3cb8 100644
--- a/kernel/bpf/verifier.c
+++ b/kernel/bpf/verifier.c
@@ -10590,6 +10590,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
if (func_id == BPF_FUNC_map_lookup_elem &&
can_elide_value_nullness(meta.map.ptr->map_type) &&
+ !(meta.map.ptr->map_flags & BPF_F_INNER_MAP) &&
meta.const_map_key >= 0 &&
meta.const_map_key < meta.map.ptr->max_entries)
ret_flag &= ~PTR_MAYBE_NULL;
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH bpf 2/2] selftests/bpf: Add inner map template lookup NULLness test
2026-06-24 7:20 [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates Sun Jian
@ 2026-06-24 7:20 ` Sun Jian
2026-06-24 7:37 ` [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates sashiko-bot
1 sibling, 0 replies; 4+ messages in thread
From: Sun Jian @ 2026-06-24 7:20 UTC (permalink / raw)
To: bpf
Cc: sun.jian.kdev, linux-kernel, linux-kselftest, ast, daniel,
john.fastabend, andrii, martin.lau, eddyz87, memxor, song,
yonghong.song, jolsa, shuah, dxu
Add a verifier test that performs an inner array lookup with a constant
key that is within the template's max_entries, and then dereferences the
lookup result without a NULL check.
The test covers array maps used as inner map templates, where the
template's max_entries does not prove that a runtime lookup against a
concrete inner map cannot return NULL.
The verifier should reject the program because the lookup result must
remain PTR_TO_MAP_VALUE_OR_NULL.
Signed-off-by: Sun Jian <sun.jian.kdev@gmail.com>
---
.../selftests/bpf/progs/verifier_map_in_map.c | 44 +++++++++++++++++++
1 file changed, 44 insertions(+)
diff --git a/tools/testing/selftests/bpf/progs/verifier_map_in_map.c b/tools/testing/selftests/bpf/progs/verifier_map_in_map.c
index 16b761e510f0..c650731c6151 100644
--- a/tools/testing/selftests/bpf/progs/verifier_map_in_map.c
+++ b/tools/testing/selftests/bpf/progs/verifier_map_in_map.c
@@ -18,6 +18,20 @@ struct {
});
} map_in_map SEC(".maps");
+struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY_OF_MAPS);
+ __uint(max_entries, 1);
+ __type(key, int);
+ __type(value, int);
+ __array(values, struct {
+ __uint(type, BPF_MAP_TYPE_ARRAY);
+ __uint(max_entries, 8);
+ __uint(map_flags, BPF_F_INNER_MAP);
+ __type(key, int);
+ __type(value, int);
+ });
+} map_in_map_inner_array SEC(".maps");
+
SEC("socket")
__description("map in map access")
__success __success_unpriv __retval(0)
@@ -139,6 +153,36 @@ __naked void on_the_inner_map_pointer(void)
: __clobber_all);
}
+SEC("socket")
+__description("inner array lookup requires null check")
+__failure __msg("invalid mem access 'map_value_or_null'")
+__failure_unpriv
+__naked void inner_array_lookup_requires_null_check(void)
+{
+ asm volatile (" \
+ r1 = 0; \
+ *(u32*)(r10 - 4) = r1; \
+ r2 = r10; \
+ r2 += -4; \
+ r1 = %[map_in_map_inner_array] ll; \
+ call %[bpf_map_lookup_elem]; \
+ if r0 == 0 goto l0_%=; \
+ r1 = 6; \
+ *(u32*)(r10 - 4) = r1; \
+ r2 = r10; \
+ r2 += -4; \
+ r1 = r0; \
+ call %[bpf_map_lookup_elem]; \
+ r0 = *(u32*)(r0 + 0); \
+ exit; \
+l0_%=: r0 = 0; \
+ exit; \
+" :
+ : __imm(bpf_map_lookup_elem),
+ __imm_addr(map_in_map_inner_array)
+ : __clobber_all);
+}
+
SEC("socket")
__description("map_ptr is never null")
__success
--
2.43.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* Re: [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates
2026-06-24 7:20 [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates Sun Jian
2026-06-24 7:20 ` [PATCH bpf 2/2] selftests/bpf: Add inner map template lookup NULLness test Sun Jian
@ 2026-06-24 7:37 ` sashiko-bot
2026-06-24 7:41 ` sun jian
1 sibling, 1 reply; 4+ messages in thread
From: sashiko-bot @ 2026-06-24 7:37 UTC (permalink / raw)
To: Sun Jian; +Cc: bpf
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
Pre-existing issues:
- [Critical] The patch relies on the `BPF_F_INNER_MAP` flag to prevent unsafe NULL-check elision for inner map templates. However, this fix is fundamentally incomplete because `BPF_MAP_TYPE_PERCPU_ARRAY` explicitly rejects the `BPF_F_INNER_MAP` flag during creation. This leaves per-CPU arrays vulnerable to out-of-bounds memory accesses and NULL pointer dereferences.
--
commit 3ab30507af620d9da556d3b2d80a1f172474785b
Author: Sun Jian <sun.jian.kdev@gmail.com>
bpf: Avoid eliding lookup NULLness for inner map templates
This commit prevents the verifier from eliding NULLness checks for array maps
used as inner map templates. It achieves this by requiring that the
BPF_F_INNER_MAP flag is not set on the map before clearing the PTR_MAYBE_NULL
flag from the register.
> diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> index 69d75515ed3f7..a32704bb5e058 100644
> --- a/kernel/bpf/verifier.c
> +++ b/kernel/bpf/verifier.c
> @@ -10577,6 +10577,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
>
> if (func_id == BPF_FUNC_map_lookup_elem &&
> can_elide_value_nullness(meta.map.ptr->map_type) &&
> + !(meta.map.ptr->map_flags & BPF_F_INNER_MAP) &&
[Severity: Critical]
This isn't a bug introduced by this patch, but does this check completely
prevent NULL-check elision for all inner map templates?
Looking at can_elide_value_nullness(), it allows both BPF_MAP_TYPE_ARRAY
and BPF_MAP_TYPE_PERCPU_ARRAY.
However, in array_map_alloc_check(), the BPF_F_INNER_MAP flag is
explicitly rejected for per-CPU arrays:
kernel/bpf/arraymap.c:array_map_alloc_check() {
if (attr->map_type != BPF_MAP_TYPE_ARRAY &&
attr->map_flags & (BPF_F_MMAPABLE | BPF_F_INNER_MAP))
return -EINVAL;
...
}
Since BPF_MAP_TYPE_PERCPU_ARRAY can never have the BPF_F_INNER_MAP flag
set, won't this allow the verifier to still incorrectly elide NULLness
checks for per-CPU arrays used as inner map templates?
If a per-CPU array with a large max_entries is used as an inner map
template, and a concrete map with a smaller max_entries is inserted at
runtime (which is possible because percpu_array_map_ops.map_meta_equal uses
bpf_map_meta_equal() which ignores max_entries checks), couldn't this
lead to an out-of-bounds access or NULL pointer dereference?
Additionally, since percpu_array_map_gen_lookup() also relies on
BPF_F_INNER_MAP to skip JIT inlining, will it inline the lookup with the
template's excessively large bounds hardcoded, resulting in out-of-bounds
heap reads on the concrete inner map?
> meta.const_map_key >= 0 &&
> meta.const_map_key < meta.map.ptr->max_entries)
> ret_flag &= ~PTR_MAYBE_NULL;
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260624072031.735846-1-sun.jian.kdev@gmail.com?part=1
^ permalink raw reply [flat|nested] 4+ messages in thread* Re: [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates
2026-06-24 7:37 ` [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates sashiko-bot
@ 2026-06-24 7:41 ` sun jian
0 siblings, 0 replies; 4+ messages in thread
From: sun jian @ 2026-06-24 7:41 UTC (permalink / raw)
To: sashiko-reviews; +Cc: bpf
On Wed, Jun 24, 2026 at 3:37 PM <sashiko-bot@kernel.org> wrote:
>
> Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
>
> Pre-existing issues:
> - [Critical] The patch relies on the `BPF_F_INNER_MAP` flag to prevent unsafe NULL-check elision for inner map templates. However, this fix is fundamentally incomplete because `BPF_MAP_TYPE_PERCPU_ARRAY` explicitly rejects the `BPF_F_INNER_MAP` flag during creation. This leaves per-CPU arrays vulnerable to out-of-bounds memory accesses and NULL pointer dereferences.
> --
>
> commit 3ab30507af620d9da556d3b2d80a1f172474785b
> Author: Sun Jian <sun.jian.kdev@gmail.com>
>
> bpf: Avoid eliding lookup NULLness for inner map templates
>
> This commit prevents the verifier from eliding NULLness checks for array maps
> used as inner map templates. It achieves this by requiring that the
> BPF_F_INNER_MAP flag is not set on the map before clearing the PTR_MAYBE_NULL
> flag from the register.
>
> > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c
> > index 69d75515ed3f7..a32704bb5e058 100644
> > --- a/kernel/bpf/verifier.c
> > +++ b/kernel/bpf/verifier.c
> > @@ -10577,6 +10577,7 @@ static int check_helper_call(struct bpf_verifier_env *env, struct bpf_insn *insn
> >
> > if (func_id == BPF_FUNC_map_lookup_elem &&
> > can_elide_value_nullness(meta.map.ptr->map_type) &&
> > + !(meta.map.ptr->map_flags & BPF_F_INNER_MAP) &&
>
> [Severity: Critical]
> This isn't a bug introduced by this patch, but does this check completely
> prevent NULL-check elision for all inner map templates?
>
> Looking at can_elide_value_nullness(), it allows both BPF_MAP_TYPE_ARRAY
> and BPF_MAP_TYPE_PERCPU_ARRAY.
>
> However, in array_map_alloc_check(), the BPF_F_INNER_MAP flag is
> explicitly rejected for per-CPU arrays:
>
> kernel/bpf/arraymap.c:array_map_alloc_check() {
> if (attr->map_type != BPF_MAP_TYPE_ARRAY &&
> attr->map_flags & (BPF_F_MMAPABLE | BPF_F_INNER_MAP))
> return -EINVAL;
> ...
> }
>
> Since BPF_MAP_TYPE_PERCPU_ARRAY can never have the BPF_F_INNER_MAP flag
> set, won't this allow the verifier to still incorrectly elide NULLness
> checks for per-CPU arrays used as inner map templates?
>
> If a per-CPU array with a large max_entries is used as an inner map
> template, and a concrete map with a smaller max_entries is inserted at
> runtime (which is possible because percpu_array_map_ops.map_meta_equal uses
> bpf_map_meta_equal() which ignores max_entries checks), couldn't this
> lead to an out-of-bounds access or NULL pointer dereference?
>
> Additionally, since percpu_array_map_gen_lookup() also relies on
> BPF_F_INNER_MAP to skip JIT inlining, will it inline the lookup with the
> template's excessively large bounds hardcoded, resulting in out-of-bounds
> heap reads on the concrete inner map?
>
> > meta.const_map_key >= 0 &&
> > meta.const_map_key < meta.map.ptr->max_entries)
> > ret_flag &= ~PTR_MAYBE_NULL;
>
> --
> Sashiko AI review · https://sashiko.dev/#/patchset/20260624072031.735846-1-sun.jian.kdev@gmail.com?part=1
Please ignore this series.
I just noticed that Nuoqi Gui's "[PATCH bpf v2 0/2] Keep dynamic inner
array lookups nullable" already covers the same verifier issue and
selftest.
Sorry for the noise.
^ permalink raw reply [flat|nested] 4+ messages in thread
end of thread, other threads:[~2026-06-24 7:42 UTC | newest]
Thread overview: 4+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-06-24 7:20 [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates Sun Jian
2026-06-24 7:20 ` [PATCH bpf 2/2] selftests/bpf: Add inner map template lookup NULLness test Sun Jian
2026-06-24 7:37 ` [PATCH bpf 1/2] bpf: Avoid eliding lookup NULLness for inner map templates sashiko-bot
2026-06-24 7:41 ` sun jian
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.