Skip to content

Commit 93e04e4

Browse files
eddyz87Kernel Patches Daemon
authored andcommitted
selftests/bpf: a demo for check_cond_jmp_op() non-null inference bug
A comparison between PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED and PTR_TO_MAP_VALUE_OR_NULL should not infer that map pointer is not null. A bug in check_cond_jmp_op() made such inference possible. Signed-off-by: Eduard Zingerman <eddyz87@gmail.com>
1 parent 5801147 commit 93e04e4

1 file changed

Lines changed: 44 additions & 0 deletions

File tree

tools/testing/selftests/bpf/progs/verifier_jeq_infer_not_null.c

Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,9 @@
33

44
#include <linux/bpf.h>
55
#include <bpf/bpf_helpers.h>
6+
#include <stdbool.h>
67
#include "bpf_misc.h"
8+
#include "bpf_kfuncs.h"
79

810
struct {
911
__uint(type, BPF_MAP_TYPE_XSKMAP);
@@ -264,4 +266,46 @@ __naked void jne_reg_reg_null_check(void)
264266
: __clobber_all);
265267
}
266268

269+
/*
270+
* A comparison between PTR_TO_MEM | MEM_RDONLY | PTR_UNTRUSTED and
271+
* PTR_TO_MAP_VALUE_OR_NULL should not infer that map pointer is not null.
272+
* A bug in check_cond_jmp_op() made such inference possible.
273+
*/
274+
SEC("raw_tp")
275+
__failure
276+
__msg("error: invalid dereference of R0 (xdp_sock_or_null)")
277+
__msg(">>> 10 | (61) r0 = *(u32 *)(r0 +0)")
278+
__naked void untrusted_mem_does_not_infer_map_value_non_null(void)
279+
{
280+
asm volatile (" \
281+
/* r8 = bpf_rdonly_cast(0, 0); */ \
282+
r2 = 0; \
283+
call %[bpf_rdonly_cast]; \
284+
r6 = r0; \
285+
/* r0 = bpf_map_lookup_elem(map_hash, &key); */ \
286+
*(u64 *)(r10 - 8) = 0; \
287+
r1 = %[map_xskmap] ll; \
288+
r2 = r10; \
289+
r2 += -8; \
290+
call %[bpf_map_lookup_elem]; \
291+
/* \
292+
* buggy verifier assumed that r6 can't be null \
293+
* and marked r0 non-null as well. \
294+
*/ \
295+
if r6 != r0 goto 1f; \
296+
r0 = *(u32 *)(r0 + 0); \
297+
1: r0 = 0; \
298+
exit; \
299+
" :
300+
: __imm(bpf_rdonly_cast),
301+
__imm(bpf_map_lookup_elem),
302+
__imm_addr(map_xskmap)
303+
: __clobber_all);
304+
}
305+
306+
void kfunc_root(void)
307+
{
308+
bpf_rdonly_cast(0, 0);
309+
}
310+
267311
char _license[] SEC("license") = "GPL";

0 commit comments

Comments
 (0)