From: David Woodhouse Date: Mon, 16 Dec 2024 10:26:24 +0000 (+0000) Subject: x86/kexec: Add CFI type information to relocate_kernel() X-Git-Url: https://www.infradead.org/git/?a=commitdiff_plain;h=1bbed9c611fd286b68e2c459320910c4fefd4a22;p=users%2Fdwmw2%2Flinux.git x86/kexec: Add CFI type information to relocate_kernel() A previous commit added __nocfi to machine_kexec() because it makes an indirect call to relocate_kernel() which lacked CFI type information, and caused the system to crash. Use SYM_TYPED_FUNC_START() to ensure that the type information is present, and remove the __nocfi tag. And emit the *actual* type signature (0x19835999) because by default, asm code uses the type signature emitted by the *caller*, which is never going to differ! Signed-off-by: David Woodhouse --- diff --git a/arch/x86/kernel/machine_kexec_64.c b/arch/x86/kernel/machine_kexec_64.c index 016862d2b544b..e1f5fc858aee2 100644 --- a/arch/x86/kernel/machine_kexec_64.c +++ b/arch/x86/kernel/machine_kexec_64.c @@ -396,7 +396,7 @@ void machine_kexec_cleanup(struct kimage *image) * Do not allocate memory (or fail in any way) in machine_kexec(). * We are past the point of no return, committed to rebooting now. */ -void __nocfi machine_kexec(struct kimage *image) +void machine_kexec(struct kimage *image) { unsigned long reloc_start = (unsigned long)__relocate_kernel_start; relocate_kernel_fn *relocate_kernel_ptr; diff --git a/arch/x86/kernel/relocate_kernel_64.S b/arch/x86/kernel/relocate_kernel_64.S index 814af7fa63188..428401e55d293 100644 --- a/arch/x86/kernel/relocate_kernel_64.S +++ b/arch/x86/kernel/relocate_kernel_64.S @@ -5,6 +5,7 @@ */ #include +#include #include #include #include @@ -67,8 +68,24 @@ SYM_DATA_END(kexec_debug_idt) * a data section even of the object file, to prevent objtool from having * opinions about it. */ + +#ifdef CONFIG_CFI_CLANG +/* + * The SYM_TYPED_FUNC_START macro emits a CFI prologue for the function, + * referencing the __kcfi_typeid_##name symbol which is the signature of + * the function prototype. The value of that symbol ends up coming from + * a weak symbol emitted by the *caller* (in this case machine_kexec()), + * which means it's *entirely* useless for checking that the caller and + * callee agree about the prototype of the (asm) function being called. + * So, we define the signature *here* for ourselves, and if the C code + * ever calls relocate_kernel() in the belief that it has a different + * prototype, then the CFI check will trigger as $DEITY intended. + */ + .weak __kcfi_typeid_relocate_kernel + .set __kcfi_typeid_relocate_kernel, 0x19835999 +#endif .code64 -SYM_CODE_START_NOALIGN(relocate_kernel) +SYM_TYPED_FUNC_START(relocate_kernel) /* * %rdi indirection_page * %rsi pa_control_page