[GIT pull V2] x86/core for v6.6-rc1

From: Thomas Gleixner
Date: Wed Aug 30 2023 - 14:56:30 EST


Linus,

please pull the latest x86/core branch from:

git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86-core-2023-08-30-v2

up to: b65413768abd: x86/kprobes: Prohibit probing on compiler generated CFI checking code


X86 core updates:

- Prevent kprobes on compiler generated CFI checking code.

The compiler generates a instruction sequence for indirect call
checks. If this sequence is modified with a kprobe, then the check
fails. So the instructions must be protected against probing.

- A few minor cleanups for the SMP code

Thanks,

tglx

Thanks,

tglx

------------------>
Masami Hiramatsu (1):
x86/kprobes: Prohibit probing on compiler generated CFI checking code

Sohil Mehta (3):
x86/smpboot: Remove a stray comment about CPU hotplug
x86/smp: Remove a non-existent function declaration
x86/smpboot: Change smp_store_boot_cpu_info() to static


arch/x86/include/asm/smp.h | 3 ---
arch/x86/kernel/kprobes/core.c | 34 ++++++++++++++++++++++++++++++++++
arch/x86/kernel/smpboot.c | 6 ++----
include/linux/cfi.h | 4 +++-
4 files changed, 39 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/smp.h b/arch/x86/include/asm/smp.h
index 600cf25dbfc6..cf7217ad5701 100644
--- a/arch/x86/include/asm/smp.h
+++ b/arch/x86/include/asm/smp.h
@@ -132,11 +132,8 @@ void smp_kick_mwait_play_dead(void);
void native_smp_send_reschedule(int cpu);
void native_send_call_func_ipi(const struct cpumask *mask);
void native_send_call_func_single_ipi(int cpu);
-void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle);

bool smp_park_other_cpus_in_init(void);
-
-void smp_store_boot_cpu_info(void);
void smp_store_cpu_info(int id);

asmlinkage __visible void smp_reboot_interrupt(void);
diff --git a/arch/x86/kernel/kprobes/core.c b/arch/x86/kernel/kprobes/core.c
index f7f6042eb7e6..e8babebad7b8 100644
--- a/arch/x86/kernel/kprobes/core.c
+++ b/arch/x86/kernel/kprobes/core.c
@@ -45,6 +45,7 @@
#include <linux/vmalloc.h>
#include <linux/pgtable.h>
#include <linux/set_memory.h>
+#include <linux/cfi.h>

#include <asm/text-patching.h>
#include <asm/cacheflush.h>
@@ -293,7 +294,40 @@ static int can_probe(unsigned long paddr)
#endif
addr += insn.length;
}
+ if (IS_ENABLED(CONFIG_CFI_CLANG)) {
+ /*
+ * The compiler generates the following instruction sequence
+ * for indirect call checks and cfi.c decodes this;
+ *
+ *  movl -<id>, %r10d ; 6 bytes
+ * addl -4(%reg), %r10d ; 4 bytes
+ * je .Ltmp1 ; 2 bytes
+ * ud2 ; <- regs->ip
+ * .Ltmp1:
+ *
+ * Also, these movl and addl are used for showing expected
+ * type. So those must not be touched.
+ */
+ __addr = recover_probed_instruction(buf, addr);
+ if (!__addr)
+ return 0;
+
+ if (insn_decode_kernel(&insn, (void *)__addr) < 0)
+ return 0;
+
+ if (insn.opcode.value == 0xBA)
+ offset = 12;
+ else if (insn.opcode.value == 0x3)
+ offset = 6;
+ else
+ goto out;
+
+ /* This movl/addl is used for decoding CFI. */
+ if (is_cfi_trap(addr + offset))
+ return 0;
+ }

+out:
return (addr == paddr);
}

diff --git a/arch/x86/kernel/smpboot.c b/arch/x86/kernel/smpboot.c
index e1aa2cd7734b..28c590b4b1b1 100644
--- a/arch/x86/kernel/smpboot.c
+++ b/arch/x86/kernel/smpboot.c
@@ -422,7 +422,7 @@ int topology_update_die_map(unsigned int die, unsigned int cpu)
return 0;
}

-void __init smp_store_boot_cpu_info(void)
+static void __init smp_store_boot_cpu_info(void)
{
int id = 0; /* CPU 0 */
struct cpuinfo_x86 *c = &cpu_data(id);
@@ -1614,9 +1614,7 @@ void play_dead_common(void)
idle_task_exit();

cpuhp_ap_report_dead();
- /*
- * With physical CPU hotplug, we should halt the cpu
- */
+
local_irq_disable();
}

diff --git a/include/linux/cfi.h b/include/linux/cfi.h
index 5e134f4ce8b7..3552ec82b725 100644
--- a/include/linux/cfi.h
+++ b/include/linux/cfi.h
@@ -19,11 +19,13 @@ static inline enum bug_trap_type report_cfi_failure_noaddr(struct pt_regs *regs,
{
return report_cfi_failure(regs, addr, NULL, 0);
}
+#endif /* CONFIG_CFI_CLANG */

#ifdef CONFIG_ARCH_USES_CFI_TRAPS
bool is_cfi_trap(unsigned long addr);
+#else
+static inline bool is_cfi_trap(unsigned long addr) { return false; }
#endif
-#endif /* CONFIG_CFI_CLANG */

#ifdef CONFIG_MODULES
#ifdef CONFIG_ARCH_USES_CFI_TRAPS