From 227b4e108adcc4ea40ba218f5de6b2f3a9890665 Mon Sep 17 00:00:00 2001 From: Heiko Carstens Date: Mon, 27 Jul 2026 16:05:12 +0200 Subject: [PATCH] s390/bpf: Add kCFI support This is the s390 variant of commit 710618c760c0 ("arm64/cfi,bpf: Support kCFI + BPF on arm64"). Signed-off-by: Heiko Carstens Reviewed-by: Ilya Leoshkevich Tested-by: Nathan Chancellor Signed-off-by: Vasily Gorbik --- arch/s390/include/asm/cfi.h | 7 +++++++ arch/s390/net/bpf_jit_comp.c | 28 ++++++++++++++++++++++++---- 2 files changed, 31 insertions(+), 4 deletions(-) create mode 100644 arch/s390/include/asm/cfi.h diff --git a/arch/s390/include/asm/cfi.h b/arch/s390/include/asm/cfi.h new file mode 100644 index 000000000000..9af2c7cb70ca --- /dev/null +++ b/arch/s390/include/asm/cfi.h @@ -0,0 +1,7 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef _ASM_S390_CFI_H +#define _ASM_S390_CFI_H + +#define __bpfcall + +#endif /* _ASM_S390_CFI_H */ diff --git a/arch/s390/net/bpf_jit_comp.c b/arch/s390/net/bpf_jit_comp.c index 31749c0362ca..7f45c106444d 100644 --- a/arch/s390/net/bpf_jit_comp.c +++ b/arch/s390/net/bpf_jit_comp.c @@ -21,6 +21,7 @@ #include #include #include +#include #include #include #include @@ -356,6 +357,19 @@ static void emit6_pcrel_rilc(struct bpf_jit *jit, u32 op, u8 mask, s64 pcrel) } \ }) +static inline void emit_u32_data(const u32 data, struct bpf_jit *jit) +{ + if (jit->prg_buf) + *(u32 *)(jit->prg_buf + jit->prg) = data; + jit->prg += 4; +} + +static inline void emit_kcfi(u32 hash, struct bpf_jit *jit) +{ + if (IS_ENABLED(CONFIG_CFI)) + emit_u32_data(hash, jit); +} + /* * Return whether this is the first pass. The first pass is special, since we * don't know any sizes yet, and thus must be conservative. @@ -597,6 +611,8 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp) { BUILD_BUG_ON(sizeof(struct prog_frame) != STACK_FRAME_OVERHEAD); + emit_kcfi(bpf_is_subprog(fp) ? cfi_bpf_subprog_hash : cfi_bpf_hash, jit); + /* No-op for hotpatching */ /* brcl 0,prologue_plt */ EMIT6_PCREL_RILC(0xc0040000, 0, jit->prologue_plt); @@ -616,7 +632,7 @@ static void bpf_jit_prologue(struct bpf_jit *jit, struct bpf_prog *fp) bpf_skip(jit, 6); } /* Tail calls have to skip above initialization */ - jit->tail_call_start = jit->prg; + jit->tail_call_start = jit->prg - cfi_get_offset(); if (fp->aux->exception_cb) { /* * Switch stack, the new address is in the 2nd parameter. @@ -2401,11 +2417,13 @@ struct bpf_prog *bpf_int_jit_compile(struct bpf_verifier_env *env, struct bpf_pr jit_data->ctx = jit; jit_data->pass = pass; } - fp->bpf_func = (void *) jit.prg_buf; + fp->bpf_func = (void *)jit.prg_buf + cfi_get_offset(); fp->jited = 1; - fp->jited_len = jit.size; + fp->jited_len = jit.size - cfi_get_offset(); if (!fp->is_func || extra_pass) { + for (int i = 0; i < fp->len; i++) + jit.addrs[i] -= cfi_get_offset(); bpf_prog_fill_jited_linfo(fp, jit.addrs + 1); free_addrs: kvfree(jit.addrs); @@ -2671,8 +2689,10 @@ static int __arch_prepare_bpf_trampoline(struct bpf_tramp_image *im, return -ENOTSUPP; /* Return to %r14 in the struct_ops case. */ - if (flags & BPF_TRAMP_F_INDIRECT) + if (flags & BPF_TRAMP_F_INDIRECT) { flags |= BPF_TRAMP_F_SKIP_FRAME; + emit_kcfi(cfi_get_func_hash(func_addr), jit); + } /* * Compute how many arguments we need to pass to BPF programs.