Hi Ilya On Wed, Aug 30, 2023 at 3:12 AM Ilya Leoshkevich <iii@xxxxxxxxxxxxx> wrote: > > On the architectures that use bpf_jit_needs_zext(), e.g., s390x, the > verifier incorrectly inserts a zero-extension after BPF_MEMSX, leading > to miscompilations like the one below: > > 24: 89 1a ff fe 00 00 00 00 "r1 = *(s16 *)(r10 - 2);" # zext_dst set > 0x3ff7fdb910e: lgh %r2,-2(%r13,%r0) # load halfword > 0x3ff7fdb9114: llgfr %r2,%r2 # wrong! > 25: 65 10 00 03 00 00 7f ff if r1 s> 32767 goto +3 <l0_1> # check_cond_jmp_op() > > Disable such zero-extensions. The JITs need to insert sign-extension > themselves, if necessary. > > Signed-off-by: Ilya Leoshkevich <iii@xxxxxxxxxxxxx> > --- > kernel/bpf/verifier.c | 4 +++- > 1 file changed, 3 insertions(+), 1 deletion(-) > > diff --git a/kernel/bpf/verifier.c b/kernel/bpf/verifier.c > index bb78212fa5b2..097985a46edc 100644 > --- a/kernel/bpf/verifier.c > +++ b/kernel/bpf/verifier.c > @@ -3110,7 +3110,9 @@ static void mark_insn_zext(struct bpf_verifier_env *env, > { > s32 def_idx = reg->subreg_def; > > - if (def_idx == DEF_NOT_SUBREG) The problem here is that reg->subreg_def should be set as DEF_NOT_SUBREG for registers that are used as destination registers of BPF_LDX | BPF_MEMSX. I am seeing the same problem on ARM32 and was going to send a patch today. The problem is that is_reg64() returns false for destination registers of BPF_LDX | BPF_MEMSX. But BPF_LDX | BPF_MEMSX always loads a 64 bit value because of the sign extension so is_reg64() should return true. I have written a patch that I will be sending as a reply to this. Please let me know if that makes sense. > + if (def_idx == DEF_NOT_SUBREG || > + (BPF_CLASS(env->prog->insnsi[def_idx - 1].code) == BPF_LDX && > + BPF_MODE(env->prog->insnsi[def_idx - 1].code) == BPF_MEMSX)) > return; > > env->insn_aux_data[def_idx - 1].zext_dst = true; > -- > 2.41.0 > > Thanks, Puranjay