diff options
author | Yonghong Song <yhs@fb.com> | 2023-05-16 21:04:04 -0700 |
---|---|---|
committer | Daniel Borkmann <daniel@iogearbox.net> | 2023-05-17 16:52:26 +0200 |
commit | 12852f8e0f70d9a5263e2834c5483268b08b5e9c (patch) | |
tree | 8ff0bbfee9d6a25048afc7760984fcbbacb47988 /tools/testing/selftests/bpf/bpf_kfuncs.h | |
parent | 8819495a754e71d3c3fde991c26ad832af995136 (diff) | |
download | linux-12852f8e0f70d9a5263e2834c5483268b08b5e9c.tar.gz linux-12852f8e0f70d9a5263e2834c5483268b08b5e9c.tar.bz2 linux-12852f8e0f70d9a5263e2834c5483268b08b5e9c.zip |
selftests/bpf: Fix dynptr/test_dynptr_is_null
With latest llvm17, dynptr/test_dynptr_is_null subtest failed in my testing
VM. The failure log looks like below:
All error logs:
tester_init:PASS:tester_log_buf 0 nsec
process_subtest:PASS:obj_open_mem 0 nsec
process_subtest:PASS:Can't alloc specs array 0 nsec
verify_success:PASS:dynptr_success__open 0 nsec
verify_success:PASS:bpf_object__find_program_by_name 0 nsec
verify_success:PASS:dynptr_success__load 0 nsec
verify_success:PASS:bpf_program__attach 0 nsec
verify_success:FAIL:err unexpected err: actual 4 != expected 0
#65/9 dynptr/test_dynptr_is_null:FAIL
The error happens for bpf prog test_dynptr_is_null in dynptr_success.c:
if (bpf_dynptr_is_null(&ptr2)) {
err = 4;
goto exit;
}
The bpf_dynptr_is_null(&ptr) unexpectedly returned a non-zero value and
the control went to the error path. Digging further, I found the root cause
is due to function signature difference between kernel and user space.
In kernel, we have ...
__bpf_kfunc bool bpf_dynptr_is_null(struct bpf_dynptr_kern *ptr)
... while in bpf_kfuncs.h we have:
extern int bpf_dynptr_is_null(const struct bpf_dynptr *ptr) __ksym;
The kernel bpf_dynptr_is_null disasm code:
ffffffff812f1a90 <bpf_dynptr_is_null>:
ffffffff812f1a90: f3 0f 1e fa endbr64
ffffffff812f1a94: 0f 1f 44 00 00 nopl (%rax,%rax)
ffffffff812f1a99: 53 pushq %rbx
ffffffff812f1a9a: 48 89 fb movq %rdi, %rbx
ffffffff812f1a9d: e8 ae 29 17 00 callq 0xffffffff81464450 <__asan_load8_noabort>
ffffffff812f1aa2: 48 83 3b 00 cmpq $0x0, (%rbx)
ffffffff812f1aa6: 0f 94 c0 sete %al
ffffffff812f1aa9: 5b popq %rbx
ffffffff812f1aaa: c3 retq
Note that only 1-byte register %al is set and the other 7-bytes are not
touched. In bpf program, the asm code for the above bpf_dynptr_is_null(&ptr2):
266: 85 10 00 00 ff ff ff ff call -0x1
267: b4 01 00 00 04 00 00 00 w1 = 0x4
268: 16 00 03 00 00 00 00 00 if w0 == 0x0 goto +0x3 <LBB9_8>
Basically, 4-byte subregister is tested. This might cause error as the value
other than the lowest byte might not be 0.
This patch fixed the issue by using the identical func prototype across kernel
and selftest user space. The fixed bpf asm code:
267: 85 10 00 00 ff ff ff ff call -0x1
268: 54 00 00 00 01 00 00 00 w0 &= 0x1
269: b4 01 00 00 04 00 00 00 w1 = 0x4
270: 16 00 03 00 00 00 00 00 if w0 == 0x0 goto +0x3 <LBB9_8>
Signed-off-by: Yonghong Song <yhs@fb.com>
Signed-off-by: Daniel Borkmann <daniel@iogearbox.net>
Link: https://lore.kernel.org/bpf/20230517040404.4023912-1-yhs@fb.com
Diffstat (limited to 'tools/testing/selftests/bpf/bpf_kfuncs.h')
-rw-r--r-- | tools/testing/selftests/bpf/bpf_kfuncs.h | 2 |
1 files changed, 1 insertions, 1 deletions
diff --git a/tools/testing/selftests/bpf/bpf_kfuncs.h b/tools/testing/selftests/bpf/bpf_kfuncs.h index f3c41f8902a0..821c25b7d0df 100644 --- a/tools/testing/selftests/bpf/bpf_kfuncs.h +++ b/tools/testing/selftests/bpf/bpf_kfuncs.h @@ -36,7 +36,7 @@ extern void *bpf_dynptr_slice_rdwr(const struct bpf_dynptr *ptr, __u32 offset, void *buffer, __u32 buffer__szk) __ksym; extern int bpf_dynptr_adjust(const struct bpf_dynptr *ptr, __u32 start, __u32 end) __ksym; -extern int bpf_dynptr_is_null(const struct bpf_dynptr *ptr) __ksym; +extern bool bpf_dynptr_is_null(const struct bpf_dynptr *ptr) __ksym; extern int bpf_dynptr_is_rdonly(const struct bpf_dynptr *ptr) __ksym; extern __u32 bpf_dynptr_size(const struct bpf_dynptr *ptr) __ksym; extern int bpf_dynptr_clone(const struct bpf_dynptr *ptr, struct bpf_dynptr *clone__init) __ksym; |