Merge branch 'bpf-support-for-non_null-ptr-detection-with-jeq-jne-with-register-operand'

Cupertino Miranda says:

====================
bpf: support for non_null ptr detection with JEQ/JNE with register operand

Changes from v1:
 - Corrected typos in commit messages.
 - Fixed indentation.
 - Replaced text by simpler version suggested by Eduard.
Changes from v2:
 - Small fixes after AI patch checker complaints.
Changes from v3:
 - Removed log file. No idea how that got added.
====================

Link: https://patch.msgid.link/20260304195018.181396-1-cupertino.miranda@oracle.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
This commit is contained in:
Alexei Starovoitov 2026-03-10 11:51:18 -07:00
commit 437350df86
2 changed files with 60 additions and 3 deletions

View File

@ -17678,12 +17678,15 @@ static int check_cond_jmp_op(struct bpf_verifier_env *env,
}
/* detect if R == 0 where R is returned from bpf_map_lookup_elem().
* Also does the same detection for a register whose the value is
* known to be 0.
* NOTE: these optimizations below are related with pointer comparison
* which will never be JMP32.
*/
if (!is_jmp32 && BPF_SRC(insn->code) == BPF_K &&
insn->imm == 0 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
type_may_be_null(dst_reg->type)) {
if (!is_jmp32 && (opcode == BPF_JEQ || opcode == BPF_JNE) &&
type_may_be_null(dst_reg->type) &&
((BPF_SRC(insn->code) == BPF_K && insn->imm == 0) ||
(BPF_SRC(insn->code) == BPF_X && register_is_null(src_reg)))) {
/* Mark all identical registers in each branch as either
* safe or unknown depending R == 0 or R != 0 conditional.
*/

View File

@ -210,4 +210,58 @@ l0_%=: /* return 0; */ \
: __clobber_all);
}
/* Verified that we can detect the pointer as non_null when comparing with
* register with value 0. JEQ test case.
*/
SEC("xdp")
__success __log_level(2)
/* to make sure the branch is not falsely predicted*/
__msg("r0 = *(u32 *)(r0 +0)")
__msg("from 7 to 9")
__naked void jeq_reg_reg_null_check(void)
{
asm volatile (" \
*(u32*)(r10 - 8) = 0; \
r1 = %[map_xskmap] ll; \
r2 = r10; \
r2 += -8; \
call %[bpf_map_lookup_elem]; \
r1 = 0; \
if r0 == r1 goto 1f; \
r0 = *(u32*)(r0 +0); \
1: r0 = 0; \
exit; \
" :
: __imm(bpf_map_lookup_elem),
__imm_addr(map_xskmap)
: __clobber_all);
}
/* Same as above but for JNE.
*/
SEC("xdp")
__success __log_level(2)
/* to make sure the branch is not falsely predicted*/
__msg("r0 = *(u32 *)(r0 +0)")
__msg("from 7 to 9")
__naked void jne_reg_reg_null_check(void)
{
asm volatile (" \
*(u32*)(r10 - 8) = 0; \
r1 = %[map_xskmap] ll; \
r2 = r10; \
r2 += -8; \
call %[bpf_map_lookup_elem]; \
r1 = 0; \
if r0 != r1 goto 1f; \
goto 2f; \
1: r0 = *(u32*)(r0 +0); \
2: r0 = 0; \
exit; \
" :
: __imm(bpf_map_lookup_elem),
__imm_addr(map_xskmap)
: __clobber_all);
}
char _license[] SEC("license") = "GPL";