// SPDX-License-Identifier: GPL-2.0 #include #include #include #include "../../../include/linux/filter.h" #include "bpf_misc.h" /* The targets are global_unwinds() and global_never_unwinds() in verifier_unwind.c */ #define unwind_exit ".8byte %[insn_unwind_exit];" #define __imm_unwind_exit \ __imm_insn(insn_unwind_exit, \ BPF_RAW_INSN(BPF_JMP | BPF_EXIT, 0, BPF_UNWIND_EXIT, 0, 0)) extern void bpf_throw(__u64 cookie) __ksym; int fentry_cnt; SEC("?fentry/global_unwinds") int BPF_PROG(fentry_unwind) { fentry_cnt++; return 0; } SEC("?fexit/global_unwinds") int BPF_PROG(fexit_unwind) { return 0; } SEC("?freplace/global_unwinds") unsigned long freplace_returns(void) { return 9; } SEC("?freplace/global_unwinds") __naked unsigned long freplace_unwinds(void) { asm volatile ( "r0 = 3;" unwind_exit : : __imm_unwind_exit ); } /* Not naked: the argument has to have a name in BTF */ __noinline int throws_cb(__u64 cookie) { if (cookie) asm volatile ("r0 = 3;" unwind_exit :: __imm_unwind_exit : "r0"); return 0; } /* It has no unwind_exit, so it can replace a subprog that cannot unwind */ SEC("?freplace/global_never_unwinds") __attribute__((btf_decl_tag("exception_callback:throws_cb"))) unsigned long freplace_throws(void) { bpf_throw(1); return 0; } char _license[] SEC("license") = "GPL";