From: Ilya Leoshkevich Date: Tue, 17 Feb 2026 16:10:06 +0000 (+0100) Subject: s390/bpf: Do not increment tailcall count when prog is NULL X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e4094d56c5592dd90aa619f9480265b0689ed3d9;p=thirdparty%2Flinux.git s390/bpf: Do not increment tailcall count when prog is NULL 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 Signed-off-by: Ilya Leoshkevich Link: https://lore.kernel.org/r/20260217161058.101346-1-iii@linux.ibm.com Signed-off-by: Alexei Starovoitov --- diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index bf92964246eb1..2112267486623 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -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 */