On Wed, 2023-07-12 at 23:08 -0700, Yonghong Song wrote: > Add unit tests for new ldsx insns. The test includes sign-extension > with a single value or with a value range. > > Signed-off-by: Yonghong Song <yhs@xxxxxx> > --- > .../selftests/bpf/prog_tests/verifier.c | 2 + > .../selftests/bpf/progs/verifier_ldsx.c | 115 ++++++++++++++++++ > 2 files changed, 117 insertions(+) > create mode 100644 tools/testing/selftests/bpf/progs/verifier_ldsx.c > > diff --git a/tools/testing/selftests/bpf/prog_tests/verifier.c b/tools/testing/selftests/bpf/prog_tests/verifier.c > index c375e59ff28d..6eec6a9463c8 100644 > --- a/tools/testing/selftests/bpf/prog_tests/verifier.c > +++ b/tools/testing/selftests/bpf/prog_tests/verifier.c > @@ -31,6 +31,7 @@ > #include "verifier_int_ptr.skel.h" > #include "verifier_jeq_infer_not_null.skel.h" > #include "verifier_ld_ind.skel.h" > +#include "verifier_ldsx.skel.h" > #include "verifier_leak_ptr.skel.h" > #include "verifier_loops1.skel.h" > #include "verifier_lwt.skel.h" > @@ -133,6 +134,7 @@ void test_verifier_helper_value_access(void) { RUN(verifier_helper_value_access > void test_verifier_int_ptr(void) { RUN(verifier_int_ptr); } > void test_verifier_jeq_infer_not_null(void) { RUN(verifier_jeq_infer_not_null); } > void test_verifier_ld_ind(void) { RUN(verifier_ld_ind); } > +void test_verifier_ldsx(void) { RUN(verifier_ldsx); } > void test_verifier_leak_ptr(void) { RUN(verifier_leak_ptr); } > void test_verifier_loops1(void) { RUN(verifier_loops1); } > void test_verifier_lwt(void) { RUN(verifier_lwt); } > diff --git a/tools/testing/selftests/bpf/progs/verifier_ldsx.c b/tools/testing/selftests/bpf/progs/verifier_ldsx.c > new file mode 100644 > index 000000000000..cd90913583b9 > --- /dev/null > +++ b/tools/testing/selftests/bpf/progs/verifier_ldsx.c > @@ -0,0 +1,115 @@ > +// SPDX-License-Identifier: GPL-2.0 > + > +#include <linux/bpf.h> > +#include <bpf/bpf_helpers.h> > +#include "bpf_misc.h" > + > +SEC("socket") > +__description("LDSX, S8") > +__success __success_unpriv __retval(-2) > +__naked void ldsx_s8(void) > +{ > + asm volatile (" \ > + r1 = 0x3fe; \ > + *(u64 *)(r10 - 8) = r1; \ > + r0 = *(s8 *)(r10 - 8); \ > + exit; \ > +" ::: __clobber_all); > +} > + > +SEC("socket") > +__description("LDSX, S16") > +__success __success_unpriv __retval(-2) > +__naked void ldsx_s16(void) > +{ > + asm volatile (" \ > + r1 = 0x3fffe; \ > + *(u64 *)(r10 - 8) = r1; \ > + r0 = *(s16 *)(r10 - 8); \ > + exit; \ > +" ::: __clobber_all); > +} > + > +SEC("socket") > +__description("LDSX, S32") > +__success __success_unpriv __retval(-2) > +__naked void ldsx_s32(void) > +{ > + asm volatile (" \ > + r1 = 0xfffffffe; \ > + *(u64 *)(r10 - 8) = r1; \ > + r0 = *(s32 *)(r10 - 8); \ > + exit; \ > +" ::: __clobber_all); > +} Note that __retval is a 32-bit value, so if I change r0 = *(s32 *)(r10 - 8); to r0 = *(u32 *)(r10 - 8); ^ __retval would be the same, probably better to add some shift right as a last instruction or something like that. (Also applies to a similar test in the movsx tests). > + > +SEC("socket") > +__description("LDSX, S8 range checking") > +__success __success_unpriv __retval(1) > +__naked void ldsx_s8_range(void) Maybe add __log_level(2) and a few __msg("... R1_w=scalar(smin=-128,smax=127)") ? So that verifier range logic is checked as well. > +{ > + asm volatile (" \ > + call %[bpf_get_prandom_u32]; \ > + *(u64 *)(r10 - 8) = r0; \ > + r1 = *(s8 *)(r10 - 8); \ > + /* r1 with s8 range */ \ > + if r1 s> 0x7f goto l0_%=; \ > + if r1 s< -0x80 goto l0_%=; \ > + r0 = 1; \ > +l1_%=: \ > + exit; \ > +l0_%=: \ > + r0 = 2; \ > + goto l1_%=; \ > +" : > + : __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} > + > +SEC("socket") > +__description("LDSX, S16 range checking") > +__success __success_unpriv __retval(1) > +__naked void ldsx_s16_range(void) > +{ > + asm volatile (" \ > + call %[bpf_get_prandom_u32]; \ > + *(u64 *)(r10 - 8) = r0; \ > + r1 = *(s16 *)(r10 - 8); \ > + /* r1 with s16 range */ \ > + if r1 s> 0x7fff goto l0_%=; \ > + if r1 s< -0x8000 goto l0_%=; \ > + r0 = 1; \ > +l1_%=: \ > + exit; \ > +l0_%=: \ > + r0 = 2; \ > + goto l1_%=; \ > +" : > + : __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} > + > +SEC("socket") > +__description("LDSX, S32 range checking") > +__success __success_unpriv __retval(1) > +__naked void ldsx_s32_range(void) > +{ > + asm volatile (" \ > + call %[bpf_get_prandom_u32]; \ > + *(u64 *)(r10 - 8) = r0; \ > + r1 = *(s32 *)(r10 - 8); \ > + /* r1 with s16 range */ \ > + if r1 s> 0x7fffFFFF goto l0_%=; \ > + if r1 s< -0x80000000 goto l0_%=; \ > + r0 = 1; \ > +l1_%=: \ > + exit; \ > +l0_%=: \ > + r0 = 2; \ > + goto l1_%=; \ > +" : > + : __imm(bpf_get_prandom_u32) > + : __clobber_all); > +} > + > +char _license[] SEC("license") = "GPL";