Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

selftests/bpf: check null propagation only neither reg is PTR_TO_BTF_ID

Verify that nullness information is not porpagated in the branches
of register to register JEQ and JNE operations if one of them is
PTR_TO_BTF_ID. Implement this in C level so we can use CO-RE.

Signed-off-by: Hao Sun <sunhao.th@gmail.com>
Suggested-by: Martin KaFai Lau <martin.lau@kernel.org>
Link: https://lore.kernel.org/r/20221222024414.29539-2-sunhao.th@gmail.com
Signed-off-by: Martin KaFai Lau <martin.lau@kernel.org>

authored by

Hao Sun and committed by
Martin KaFai Lau
cedebd74 8374bfd5

+51
+9
tools/testing/selftests/bpf/prog_tests/jeq_infer_not_null.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include <test_progs.h> 4 + #include "jeq_infer_not_null_fail.skel.h" 5 + 6 + void test_jeq_infer_not_null(void) 7 + { 8 + RUN_TESTS(jeq_infer_not_null_fail); 9 + }
+42
tools/testing/selftests/bpf/progs/jeq_infer_not_null_fail.c
··· 1 + // SPDX-License-Identifier: GPL-2.0 2 + 3 + #include "vmlinux.h" 4 + #include <bpf/bpf_helpers.h> 5 + #include "bpf_misc.h" 6 + 7 + char _license[] SEC("license") = "GPL"; 8 + 9 + struct { 10 + __uint(type, BPF_MAP_TYPE_HASH); 11 + __uint(max_entries, 1); 12 + __type(key, u64); 13 + __type(value, u64); 14 + } m_hash SEC(".maps"); 15 + 16 + SEC("?raw_tp") 17 + __failure __msg("R8 invalid mem access 'map_value_or_null") 18 + int jeq_infer_not_null_ptr_to_btfid(void *ctx) 19 + { 20 + struct bpf_map *map = (struct bpf_map *)&m_hash; 21 + struct bpf_map *inner_map = map->inner_map_meta; 22 + u64 key = 0, ret = 0, *val; 23 + 24 + val = bpf_map_lookup_elem(map, &key); 25 + /* Do not mark ptr as non-null if one of them is 26 + * PTR_TO_BTF_ID (R9), reject because of invalid 27 + * access to map value (R8). 28 + * 29 + * Here, we need to inline those insns to access 30 + * R8 directly, since compiler may use other reg 31 + * once it figures out val==inner_map. 32 + */ 33 + asm volatile("r8 = %[val];\n" 34 + "r9 = %[inner_map];\n" 35 + "if r8 != r9 goto +1;\n" 36 + "%[ret] = *(u64 *)(r8 +0);\n" 37 + : [ret] "+r"(ret) 38 + : [inner_map] "r"(inner_map), [val] "r"(val) 39 + : "r8", "r9"); 40 + 41 + return ret; 42 + }