diff options
| author | Alexei Starovoitov <[email protected]> | 2023-12-15 11:24:51 -0800 |
|---|---|---|
| committer | Alexei Starovoitov <[email protected]> | 2023-12-15 16:25:56 -0800 |
| commit | 3c302e14bd9d7698ea24885a7eee2b44c1a014be (patch) | |
| tree | 4599c7e80eb113dcf3bda5ea435e8c26b7e2a3bf /include/linux | |
| parent | 1467affd16b236fc86e1b8ec5eaa147e104cd2a6 (diff) | |
| parent | 852486b35f344887786d63250946dd921a05d7e8 (diff) | |
Merge branch 'x86-cfi-bpf-fix-cfi-vs-ebpf'
Peter Zijlstra says:
====================
x86/cfi,bpf: Fix CFI vs eBPF
Hi!
What started with the simple observation that bpf_dispatcher_*_func() was
broken for calling CFI functions with a __nocfi calling context for FineIBT
ended up with a complete BPF wide CFI fixup.
With these changes on the BPF selftest suite passes without crashing -- there's
still a few failures, but Alexei has graciously offered to look into those.
(Alexei, I have presumed your SoB on the very last patch, please update
as you see fit)
Changes since v2 are numerous but include:
- cfi_get_offset() -- as a means to communicate the offset (ast)
- 5 new patches fixing various BPF internals to be CFI clean
Note: it *might* be possible to merge the
bpf_bpf_tcp_ca.c:unsupported_ops[] thing into the CFI stubs, as is
get_info will have a NULL stub, unlike the others.
---
arch/riscv/include/asm/cfi.h | 3 +-
arch/riscv/kernel/cfi.c | 2 +-
arch/x86/include/asm/cfi.h | 126 +++++++++++++++++++++++++++++++++++++-
arch/x86/kernel/alternative.c | 87 +++++++++++++++++++++++---
arch/x86/kernel/cfi.c | 4 +-
arch/x86/net/bpf_jit_comp.c | 134 +++++++++++++++++++++++++++++++++++------
include/asm-generic/Kbuild | 1 +
include/linux/bpf.h | 27 ++++++++-
include/linux/cfi.h | 12 ++++
kernel/bpf/bpf_struct_ops.c | 16 ++---
kernel/bpf/core.c | 25 ++++++++
kernel/bpf/cpumask.c | 8 ++-
kernel/bpf/helpers.c | 18 +++++-
net/bpf/bpf_dummy_struct_ops.c | 31 +++++++++-
net/bpf/test_run.c | 15 ++++-
net/ipv4/bpf_tcp_ca.c | 69 +++++++++++++++++++++
16 files changed, 528 insertions(+), 50 deletions(-)
====================
Link: https://lore.kernel.org/r/[email protected]
Signed-off-by: Alexei Starovoitov <[email protected]>
Diffstat (limited to 'include/linux')
| -rw-r--r-- | include/linux/bpf.h | 27 | ||||
| -rw-r--r-- | include/linux/cfi.h | 12 |
2 files changed, 36 insertions, 3 deletions
diff --git a/include/linux/bpf.h b/include/linux/bpf.h index c87c608a3689..5e694934cf37 100644 --- a/include/linux/bpf.h +++ b/include/linux/bpf.h @@ -29,6 +29,7 @@ #include <linux/rcupdate_trace.h> #include <linux/static_call.h> #include <linux/memcontrol.h> +#include <linux/cfi.h> struct bpf_verifier_env; struct bpf_verifier_log; @@ -1059,6 +1060,17 @@ struct btf_func_model { */ #define BPF_TRAMP_F_TAIL_CALL_CTX BIT(7) +/* + * Indicate the trampoline should be suitable to receive indirect calls; + * without this indirectly calling the generated code can result in #UD/#CP, + * depending on the CFI options. + * + * Used by bpf_struct_ops. + * + * Incompatible with FENTRY usage, overloads @func_addr argument. + */ +#define BPF_TRAMP_F_INDIRECT BIT(8) + /* Each call __bpf_prog_enter + call bpf_func + call __bpf_prog_exit is ~50 * bytes on x86. */ @@ -1211,7 +1223,11 @@ struct bpf_dispatcher { #endif }; -static __always_inline __nocfi unsigned int bpf_dispatcher_nop_func( +#ifndef __bpfcall +#define __bpfcall __nocfi +#endif + +static __always_inline __bpfcall unsigned int bpf_dispatcher_nop_func( const void *ctx, const struct bpf_insn *insnsi, bpf_func_t bpf_func) @@ -1303,7 +1319,7 @@ int arch_prepare_bpf_dispatcher(void *image, void *buf, s64 *funcs, int num_func #define DEFINE_BPF_DISPATCHER(name) \ __BPF_DISPATCHER_SC(name); \ - noinline __nocfi unsigned int bpf_dispatcher_##name##_func( \ + noinline __bpfcall unsigned int bpf_dispatcher_##name##_func( \ const void *ctx, \ const struct bpf_insn *insnsi, \ bpf_func_t bpf_func) \ @@ -1453,6 +1469,9 @@ struct bpf_prog_aux { struct bpf_kfunc_desc_tab *kfunc_tab; struct bpf_kfunc_btf_tab *kfunc_btf_tab; u32 size_poke_tab; +#ifdef CONFIG_FINEIBT + struct bpf_ksym ksym_prefix; +#endif struct bpf_ksym ksym; const struct bpf_prog_ops *ops; struct bpf_map **used_maps; @@ -1465,7 +1484,7 @@ struct bpf_prog_aux { int cgroup_atype; /* enum cgroup_bpf_attach_type */ struct bpf_map *cgroup_storage[MAX_BPF_CGROUP_STORAGE_TYPE]; char name[BPF_OBJ_NAME_LEN]; - unsigned int (*bpf_exception_cb)(u64 cookie, u64 sp, u64 bp); + u64 (*bpf_exception_cb)(u64 cookie, u64 sp, u64 bp, u64, u64); #ifdef CONFIG_SECURITY void *security; #endif @@ -1689,6 +1708,7 @@ struct bpf_struct_ops { struct btf_func_model func_models[BPF_STRUCT_OPS_MAX_NR_MEMBERS]; u32 type_id; u32 value_id; + void *cfi_stubs; }; #if defined(CONFIG_BPF_JIT) && defined(CONFIG_BPF_SYSCALL) @@ -1702,6 +1722,7 @@ int bpf_struct_ops_map_sys_lookup_elem(struct bpf_map *map, void *key, int bpf_struct_ops_prepare_trampoline(struct bpf_tramp_links *tlinks, struct bpf_tramp_link *link, const struct btf_func_model *model, + void *stub_func, void *image, void *image_end); static inline bool bpf_try_module_get(const void *data, struct module *owner) { diff --git a/include/linux/cfi.h b/include/linux/cfi.h index 3552ec82b725..f0df518e11dd 100644 --- a/include/linux/cfi.h +++ b/include/linux/cfi.h @@ -9,6 +9,14 @@ #include <linux/bug.h> #include <linux/module.h> +#include <asm/cfi.h> + +#ifndef cfi_get_offset +static inline int cfi_get_offset(void) +{ + return 0; +} +#endif #ifdef CONFIG_CFI_CLANG enum bug_trap_type report_cfi_failure(struct pt_regs *regs, unsigned long addr, @@ -38,4 +46,8 @@ static inline void module_cfi_finalize(const Elf_Ehdr *hdr, #endif /* CONFIG_ARCH_USES_CFI_TRAPS */ #endif /* CONFIG_MODULES */ +#ifndef CFI_NOSEAL +#define CFI_NOSEAL(x) +#endif + #endif /* _LINUX_CFI_H */ |