]> www.infradead.org Git - users/dwmw2/linux.git/commitdiff
x86/kexec: Add CFI type information to relocate_kernel()
authorDavid Woodhouse <dwmw@amazon.co.uk>
Mon, 16 Dec 2024 10:26:24 +0000 (10:26 +0000)
committerDavid Woodhouse <dwmw@amazon.co.uk>
Tue, 18 Mar 2025 15:53:34 +0000 (15:53 +0000)
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 <dwmw@amazon.co.uk>
arch/x86/kernel/machine_kexec_64.c
arch/x86/kernel/relocate_kernel_64.S

index 016862d2b544b08343a31aca956e6e89be82df8d..e1f5fc858aee25254d548b5421cc27b8ec9bf8ad 100644 (file)
@@ -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;
index 814af7fa6318890b76871c76b661a5a4c4f4d8b7..428401e55d293172c79ba68b024cae72fc35f2bc 100644 (file)
@@ -5,6 +5,7 @@
  */
 
 #include <linux/linkage.h>
+#include <linux/cfi_types.h>
 #include <linux/stringify.h>
 #include <asm/alternative.h>
 #include <asm/page_types.h>
@@ -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