1*62ef2041SSong Liu // SPDX-License-Identifier: GPL-2.0 2*62ef2041SSong Liu /* 3*62ef2041SSong Liu * An indirect call, which under kCFI is preceded by a type check and a trap. 4*62ef2041SSong Liu * 5*62ef2041SSong Liu * Clang emits a __cfi_<func> prefix symbol carrying the type hash ahead of 6*62ef2041SSong Liu * every address-taken function, and records the trap site in .kcfi_traps. 7*62ef2041SSong Liu * Both belong to the function and both have to come with it into a patch. 8*62ef2041SSong Liu * 9*62ef2041SSong Liu * Needs -fsanitize=kcfi, which only Clang has. 10*62ef2041SSong Liu */ 11*62ef2041SSong Liu 12*62ef2041SSong Liu static const char __modinfo[] 13*62ef2041SSong Liu __attribute__((section(".modinfo"), used, aligned(1))) = "\0name=vmlinux"; 14*62ef2041SSong Liu impl_a(int x)15*62ef2041SSong Liustatic int impl_a(int x) 16*62ef2041SSong Liu { 17*62ef2041SSong Liu return x + 1; 18*62ef2041SSong Liu } 19*62ef2041SSong Liu impl_b(int x)20*62ef2041SSong Liustatic int impl_b(int x) 21*62ef2041SSong Liu { 22*62ef2041SSong Liu return x * 2; 23*62ef2041SSong Liu } 24*62ef2041SSong Liu pick(int x)25*62ef2041SSong Liu__attribute__((noinline)) int (*pick(int x))(int) 26*62ef2041SSong Liu { 27*62ef2041SSong Liu return (x & 1) ? impl_a : impl_b; 28*62ef2041SSong Liu } 29*62ef2041SSong Liu target(int x)30*62ef2041SSong Liuint target(int x) 31*62ef2041SSong Liu { 32*62ef2041SSong Liu int (*fn)(int arg) = pick(x); 33*62ef2041SSong Liu 34*62ef2041SSong Liu #ifdef PATCHED 35*62ef2041SSong Liu return fn(x) + 2; 36*62ef2041SSong Liu #else 37*62ef2041SSong Liu return fn(x) + 1; 38*62ef2041SSong Liu #endif 39*62ef2041SSong Liu } 40