bpf: reject direct access to nullable PTR_TO_BUF pointers
Subsystems (4)
v4 cover bpf: reject direct access to nullable PTR_TO_BUF pointers
check_mem_access() allows direct dereference of PTR_TO_BUF | PTR_MAYBE_NULL without a null check, causing kernel NULL dereference on map iterator stop callbacks.
Patch 1 adds the missing type_may_be_null() guard. Patch 2 adds a selftest with a test runner.
Changes in v4:
- Add test runner in prog_tests/ so the test is actually invoked by test_progs (Kumar)
Changes in v3:
- Drop stack trace from commit log
- Split kernel fix and selftest into separate patches
- Use [PATCH bpf] prefix
Changes in v2:
- Add selftest
Qi Tang (2):
bpf: reject direct access to nullable PTR_TO_BUF pointers selftests/bpf: add test for nullable PTR_TO_BUF access
kernel/bpf/verifier.c | 3 ++- tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c | 9 +++++++++ tools/testing/selftests/bpf/progs/iter_buf_null_fail.c | 51 ++++++++++++ 3 files changed, 62 insertions(+), 1 deletion(-) create mode 100644 tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c create mode 100644 tools/testing/selftests/bpf/progs/iter_buf_null_fail.c
PATCH v4 1/2 bpf: reject direct access to nullable PTR_TO_BUF pointers
check_mem_access() matches PTR_TO_BUF via base_type() which strips PTR_MAYBE_NULL, allowing direct dereference without a null check.
Map iterator ctx->key and ctx->value are PTR_TO_BUF | PTR_MAYBE_NULL. On stop callbacks these are NULL, causing a kernel NULL dereference.
Add a type_may_be_null() guard to the PTR_TO_BUF branch, matching the existing PTR_TO_BTF_ID pattern.
--- kernel/bpf/verifier.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
kernel/bpf/verifier.c +2 -1
@@ -7905,7 +7905,8 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn }else if (reg->type ==CONST_PTR_TO_MAP ) { err =check_ptr_to_map_access (env, regs, regno, off, size, t, value_regno); - }else if (base_type (reg->type) ==PTR_TO_BUF ) { + }else if (base_type (reg->type) ==PTR_TO_BUF && + !type_may_be_null (reg->type)) {bool rdonly_mem =type_is_rdonly_mem (reg->type);u32 *max_access;
Signature · 1 line
2.43.0
Quoted 7 lines · Qi Tang
check_mem_access()matchesPTR_TO_BUFviabase_type()which stripsPTR_MAYBE_NULL, allowing direct dereference without a null check.Map iterator
ctx->keyandctx->valuearePTR_TO_BUF|PTR_MAYBE_NULL. On stop callbacks these are NULL, causing a kernel NULL dereference.
Quoted 6 lines
Add a
type_may_be_null()guard to thePTR_TO_BUFbranch, matching the existingPTR_TO_BTF_IDpattern.Fixes 20b2aff4bc15 ("bpf: Introduce MEM_RDONLY flag")Signed-off-by Qi Tang <[email protected]>
PATCH v4 2/2 selftests/bpf: add test for nullable PTR_TO_BUF access
In reply to Qi TangAdd iter_buf_null_fail with two tests and a test runner:
- iter_buf_null_deref: verifier must reject direct dereference of
ctx->key (PTR_TO_BUF | PTR_MAYBE_NULL) without a null check
- iter_buf_null_check_ok: verifier must accept dereference after an explicit null check
--- .../bpf/prog_tests/iter_buf_null_fail.c | 9 ++++ .../selftests/bpf/progs/iter_buf_null_fail.c | 51 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c create mode 100644 tools/testing/selftests/bpf/progs/iter_buf_null_fail.c
tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c new file +9 -0
@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <test_progs.h> +#include "iter_buf_null_fail.skel.h" + +void test_iter_buf_null_fail (void ) +{ +RUN_TESTS (iter_buf_null_fail); +}
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +51 -0
51 lines not on this page · raw message
Signature · 1 line
2.43.0
Re: [PATCH bpf v4 2/2] selftests/bpf: add test for nullable PTR_TO_BUF access
Quoted 42 lines · Qi Tang
Add
iter_buf_null_failwith two tests and a test runner:
-iter_buf_null_deref: verifier must reject direct dereference ofctx->key (PTR_TO_BUF | PTR_MAYBE_NULL) without a null check-
iter_buf_null_check_ok: verifier must accept dereference after an explicit null checkSigned-off-by Qi Tang <[email protected]>--- .../bpf/prog_tests/iter_buf_null_fail.c | 9 ++++ .../selftests/bpf/progs/iter_buf_null_fail.c | 51 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c create mode 100644 tools/testing/selftests/bpf/progs/iter_buf_null_fail.ctools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c new file +9
-0@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <test_progs.h> +#include "iter_buf_null_fail.skel.h" + +void test_iter_buf_null_fail (void ) +{ +RUN_TESTS (iter_buf_null_fail); +}tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +6
-0@@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Qi Tang */ + +#include <vmlinux.h> +#include <bpf/bpf_helpers.h> +#include "bpf_misc.h"
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 16
Quoted 10 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +10
-0+ +char _license[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, __u64); +} hashmap SEC(".maps"); +
hashmap is not used and can be removed.
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 28
Quoted 12 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +12
-0+/* +* Verify that the verifier rejects direct access to nullable PTR_TO_BUF +* (ctx->key) without a null check. On the iterator stop callback, +* ctx->key is NULL, so unconditional access would be a NULL deref. +*/ +SEC("iter/bpf_map_elem") +__failure __msg("invalid mem access") +int iter_buf_null_deref (struct bpf_iter__bpf_map_elem *ctx) +{ +/* ctx->key is PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY. +* Direct access without null check must be rejected. +*/
nit: consider kernel-style comment instead of netdev
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 37
Quoted 9 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +9
-0+volatile __u32 v = *(__u32 *)ctx->key; + + (void )v; +return 0 ; +} + +/* +* Verify that access after a null check is still accepted. +*/
nit: maybe just one line /* ... */ ?
Quoted 18 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +14
-1+SEC("iter/bpf_map_elem") +__success +int iter_buf_null_check_ok (struct bpf_iter__bpf_map_elem *ctx) +{ +__u32 *key = ctx->key; + +if (!key) +return 0 ; + +volatile __u32 v = *key; + + (void )v; +return 0 ; +} --2.43.0
Kumar Kartikeya Dwivedi
maintainerRe: [PATCH bpf v4 2/2] selftests/bpf: add test for nullable PTR_TO_BUF access
Quoted 84 lines · Amery Hung
Quoted 42 lines · Qi Tang
Add
iter_buf_null_failwith two tests and a test runner:
-iter_buf_null_deref: verifier must reject direct dereference ofctx->key (PTR_TO_BUF | PTR_MAYBE_NULL) without a null check-
iter_buf_null_check_ok: verifier must accept dereference after an explicit null checkSigned-off-by Qi Tang <[email protected]>--- .../bpf/prog_tests/iter_buf_null_fail.c | 9 ++++ .../selftests/bpf/progs/iter_buf_null_fail.c | 51 +++++++++++++++++++ 2 files changed, 60 insertions(+) create mode 100644 tools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c create mode 100644 tools/testing/selftests/bpf/progs/iter_buf_null_fail.ctools/testing/selftests/bpf/prog_tests/iter_buf_null_fail.c new file +9
-0@@ -0,0 +1,9 @@ +// SPDX-License-Identifier: GPL-2.0 + +#include <test_progs.h> +#include "iter_buf_null_fail.skel.h" + +void test_iter_buf_null_fail (void ) +{ +RUN_TESTS (iter_buf_null_fail); +}tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +6
-0@@ -0,0 +1,51 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (c) 2026 Qi Tang */ + +#include <vmlinux.h> +#include <bpf/bpf_helpers.h> +#include "bpf_misc.h" tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 16
Quoted 10 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +10
-0+ +char _license[] SEC("license") = "GPL"; + +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __uint(max_entries, 1); + __type(key, __u32); + __type(value, __u64); +} hashmap SEC(".maps"); +hashmap is not used and can be removed.
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 28
Quoted 12 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +12
-0+/* +* Verify that the verifier rejects direct access to nullable PTR_TO_BUF +* (ctx->key) without a null check. On the iterator stop callback, +* ctx->key is NULL, so unconditional access would be a NULL deref. +*/ +SEC("iter/bpf_map_elem") +__failure __msg("invalid mem access") +int iter_buf_null_deref (struct bpf_iter__bpf_map_elem *ctx) +{ +/* ctx->key is PTR_TO_BUF | PTR_MAYBE_NULL | MEM_RDONLY. +* Direct access without null check must be rejected. +*/ nit: consider kernel-style comment instead of netdev
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c line 37
Quoted 9 lines
tools/testing/selftests/bpf/progs/iter_buf_null_fail.c new file +9
-0+volatile __u32 v = *(__u32 *)ctx->key; + + (void )v; +return 0 ; +} + +/* +* Verify that access after a null check is still accepted. +*/ nit: maybe just one line /* ... */ ?
Quoted 1 line
Reviewed-by Amery Hung <[email protected]>
Qi, only the fix was applied, the test still needs to be resent. Please respin the selftest alone and send it against bpf-next. Thanks.
Re: [PATCH bpf v4 2/2] selftests/bpf: add test for nullable PTR_TO_BUF access
Quoted 2 lines · Kumar Kartikeya Dwivedi
Qi, only the fix was applied, the test still needs to be resent. Please respin the selftest alone and send it against bpf-next.
Got it. Thanks for the ack and for guiding me through the review rounds on this one. Will respin the selftest with Amery's nits fixed and send against bpf-next.
Qi Tang
This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov <[email protected]>:
Hello:
This series was applied to bpf/bpf-next.git (master) by Alexei Starovoitov <[email protected]>:
Quoted 8 lines · On Fri, 3 Apr 2026 11:38:26 +0800 you wrote:
check_mem_access()allows direct dereference ofPTR_TO_BUF|PTR_MAYBE_NULLwithout a null check, causing kernel NULL dereference on map iterator stop callbacks.Patch 1 adds the missing
type_may_be_null()guard. Patch 2 adds a selftest with a test runner.[...]
Here is the summary with links:
- [bpf,v4,1/2] bpf: reject direct access to nullable PTR_TO_BUF pointers
https://git.kernel.org/bpf/bpf-next/c/b0db1accbc73
- [bpf,v4,2/2] selftests/bpf: add test for nullable PTR_TO_BUF access (no matching commit)
You are awesome, thank you!
Signature · 2 lines
Deet-doot-dot, I am a bot. https://korg.docs.kernel.org/patchwork/pwbot.html