]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/bpf: Do not increment tailcall count when prog is NULL
authorIlya Leoshkevich <iii@linux.ibm.com>
Tue, 17 Feb 2026 16:10:06 +0000 (17:10 +0100)
committerAlexei Starovoitov <ast@kernel.org>
Tue, 24 Feb 2026 18:47:33 +0000 (10:47 -0800)
Currently tail calling a non-existent prog results in tailcall count
increment. This is what the interpreter is doing, but this is clearly
wrong, so replace load-and-increment and compare-and-jump with load
and compare-and-jump, conditionally followed by increment and store.

Reported-by: Hari Bathini <hbathini@linux.ibm.com>
Signed-off-by: Ilya Leoshkevich <iii@linux.ibm.com>
Link: https://lore.kernel.org/r/20260217161058.101346-1-iii@linux.ibm.com
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
arch/s390/net/bpf_jit_comp.c

index bf92964246eb19e96ad99a14d9e6d251b0081e40..211226748662337e3f43a4d2b056d50246e962b2 100644 (file)
@@ -1862,20 +1862,21 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
                                 jit->prg);
 
                /*
-                * if (tail_call_cnt++ >= MAX_TAIL_CALL_CNT)
+                * if (tail_call_cnt >= MAX_TAIL_CALL_CNT)
                 *         goto out;
+                *
+                * tail_call_cnt is read into %w0, which needs to be preserved
+                * until it's incremented and flushed.
                 */
 
                off = jit->frame_off +
                      offsetof(struct prog_frame, tail_call_cnt);
-               /* lhi %w0,1 */
-               EMIT4_IMM(0xa7080000, REG_W0, 1);
-               /* laal %w1,%w0,off(%r15) */
-               EMIT6_DISP_LH(0xeb000000, 0x00fa, REG_W1, REG_W0, REG_15, off);
-               /* clij %w1,MAX_TAIL_CALL_CNT-1,0x2,out */
+               /* ly %w0,off(%r15) */
+               EMIT6_DISP_LH(0xe3000000, 0x0058, REG_W0, REG_0, REG_15, off);
+               /* clij %w0,MAX_TAIL_CALL_CNT,0xa,out */
                patch_2_clij = jit->prg;
-               EMIT6_PCREL_RIEC(0xec000000, 0x007f, REG_W1, MAX_TAIL_CALL_CNT - 1,
-                                2, jit->prg);
+               EMIT6_PCREL_RIEC(0xec000000, 0x007f, REG_W0, MAX_TAIL_CALL_CNT,
+                                0xa, jit->prg);
 
                /*
                 * prog = array->ptrs[index];
@@ -1894,6 +1895,12 @@ static noinline int bpf_jit_insn(struct bpf_jit *jit, struct bpf_prog *fp,
                patch_3_brc = jit->prg;
                EMIT4_PCREL_RIC(0xa7040000, 8, jit->prg);
 
+               /* tail_call_cnt++; */
+               /* ahi %w0,1 */
+               EMIT4_IMM(0xa70a0000, REG_W0, 1);
+               /* sty %w0,off(%r15) */
+               EMIT6_DISP_LH(0xe3000000, 0x0050, REG_W0, REG_0, REG_15, off);
+
                /*
                 * Restore registers before calling function
                 */