]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/bpf: Zero-extend bpf prog return values and kfunc arguments
authorIlya Leoshkevich <iii@linux.ibm.com>
Fri, 13 Mar 2026 17:46:25 +0000 (18:46 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Mon, 16 Mar 2026 16:21:35 +0000 (09:21 -0700)
s390x ABI requires callers to zero-extend unsigned arguments and
sign-extend signed arguments, and callees to zero-extend unsigned
return values and sign-extend signed return values.

s390 BPF JIT currently implements only sign extension. Fix this
omission and implement zero extension too.

Fixes: 528eb2cb87bc ("s390/bpf: Implement arch_prepare_bpf_trampoline()")
Reported-by: Hari Bathini <hbathini@linux.ibm.com>
Closes: https://lore.kernel.org/bpf/20260312080113.843408-1-hbathini@linux.ibm.com/
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Tested-by: Ihor Solodrai <ihor.solodrai@linux.dev>
Link: https://lore.kernel.org/r/20260313174807.581826-1-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
arch/s390/net/bpf_jit_comp.c

index 1f9a6b728beb34e26fdefccc6f7d9743f422ddab..d08d159b63193efce34cb3db8a3349b41a36ff25 100644 (file)
@@ -830,25 +830,34 @@ static int bpf_jit_probe_post(struct bpf_jit *jit, struct bpf_prog *fp,
 }
 
 /*
- * Sign-extend the register if necessary
+ * Sign- or zero-extend the register if necessary
  */
-static int sign_extend(struct bpf_jit *jit, int r, u8 size, u8 flags)
+static int sign_zero_extend(struct bpf_jit *jit, int r, u8 size, u8 flags)
 {
-       if (!(flags & BTF_FMODEL_SIGNED_ARG))
-               return 0;
-
        switch (size) {
        case 1:
-               /* lgbr %r,%r */
-               EMIT4(0xb9060000, r, r);
+               if (flags & BTF_FMODEL_SIGNED_ARG)
+                       /* lgbr %r,%r */
+                       EMIT4(0xb9060000, r, r);
+               else
+                       /* llgcr %r,%r */
+                       EMIT4(0xb9840000, r, r);
                return 0;
        case 2:
-               /* lghr %r,%r */
-               EMIT4(0xb9070000, r, r);
+               if (flags & BTF_FMODEL_SIGNED_ARG)
+                       /* lghr %r,%r */
+                       EMIT4(0xb9070000, r, r);
+               else
+                       /* llghr %r,%r */
+                       EMIT4(0xb9850000, r, r);
                return 0;
        case 4:
-               /* lgfr %r,%r */
-               EMIT4(0xb9140000, r, r);
+               if (flags & BTF_FMODEL_SIGNED_ARG)
+                       /* lgfr %r,%r */
+                       EMIT4(0xb9140000, r, r);
+               else
+                       /* llgfr %r,%r */
+                       EMIT4(0xb9160000, r, r);
                return 0;
        case 8:
                return 0;
@@ -1798,9 +1807,9 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
                                return -1;
 
                        for (j = 0; j < m->nr_args; j++) {
-                               if (sign_extend(jit, BPF_REG_1 + j,
-                                               m->arg_size[j],
-                                               m->arg_flags[j]))
+                               if (sign_zero_extend(jit, BPF_REG_1 + j,
+                                                    m->arg_size[j],
+                                                    m->arg_flags[j]))
                                        return -1;
                        }
                }
@@ -2566,7 +2575,7 @@ static int invoke_bpf_prog(struct bpf_tramp_jit *tjit,
        EMIT6_PCREL_RILB_PTR(0xc0050000, REG_14, p->bpf_func);
        /* stg %r2,retval_off(%r15) */
        if (save_ret) {
-               if (sign_extend(jit, REG_2, m->ret_size, m->ret_flags))
+               if (sign_zero_extend(jit, REG_2, m->ret_size, m->ret_flags))
                        return -1;
                EMIT6_DISP_LH(0xe3000000, 0x0024, REG_2, REG_0, REG_15,
                              tjit->retval_off);