Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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

Pull x86 core updates from Thomas Gleixner:

- Prevent kprobes on compiler generated CFI checking code.

The compiler generates an 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

* tag 'x86-core-2023-08-30-v2' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
x86/kprobes: Prohibit probing on compiler generated CFI checking code
x86/smpboot: Change smp_store_boot_cpu_info() to static
x86/smp: Remove a non-existent function declaration
x86/smpboot: Remove a stray comment about CPU hotplug

+39 -8
-3
arch/x86/include/asm/smp.h
··· 132 132 void native_smp_send_reschedule(int cpu); 133 133 void native_send_call_func_ipi(const struct cpumask *mask); 134 134 void native_send_call_func_single_ipi(int cpu); 135 - void x86_idle_thread_init(unsigned int cpu, struct task_struct *idle); 136 135 137 136 bool smp_park_other_cpus_in_init(void); 138 - 139 - void smp_store_boot_cpu_info(void); 140 137 void smp_store_cpu_info(int id); 141 138 142 139 asmlinkage __visible void smp_reboot_interrupt(void);
+34
arch/x86/kernel/kprobes/core.c
··· 45 45 #include <linux/vmalloc.h> 46 46 #include <linux/pgtable.h> 47 47 #include <linux/set_memory.h> 48 + #include <linux/cfi.h> 48 49 49 50 #include <asm/text-patching.h> 50 51 #include <asm/cacheflush.h> ··· 294 293 #endif 295 294 addr += insn.length; 296 295 } 296 + if (IS_ENABLED(CONFIG_CFI_CLANG)) { 297 + /* 298 + * The compiler generates the following instruction sequence 299 + * for indirect call checks and cfi.c decodes this; 300 + * 301 + *  movl -<id>, %r10d ; 6 bytes 302 + * addl -4(%reg), %r10d ; 4 bytes 303 + * je .Ltmp1 ; 2 bytes 304 + * ud2 ; <- regs->ip 305 + * .Ltmp1: 306 + * 307 + * Also, these movl and addl are used for showing expected 308 + * type. So those must not be touched. 309 + */ 310 + __addr = recover_probed_instruction(buf, addr); 311 + if (!__addr) 312 + return 0; 297 313 314 + if (insn_decode_kernel(&insn, (void *)__addr) < 0) 315 + return 0; 316 + 317 + if (insn.opcode.value == 0xBA) 318 + offset = 12; 319 + else if (insn.opcode.value == 0x3) 320 + offset = 6; 321 + else 322 + goto out; 323 + 324 + /* This movl/addl is used for decoding CFI. */ 325 + if (is_cfi_trap(addr + offset)) 326 + return 0; 327 + } 328 + 329 + out: 298 330 return (addr == paddr); 299 331 } 300 332
+2 -4
arch/x86/kernel/smpboot.c
··· 414 414 return 0; 415 415 } 416 416 417 - void __init smp_store_boot_cpu_info(void) 417 + static void __init smp_store_boot_cpu_info(void) 418 418 { 419 419 int id = 0; /* CPU 0 */ 420 420 struct cpuinfo_x86 *c = &cpu_data(id); ··· 1601 1601 idle_task_exit(); 1602 1602 1603 1603 cpuhp_ap_report_dead(); 1604 - /* 1605 - * With physical CPU hotplug, we should halt the cpu 1606 - */ 1604 + 1607 1605 local_irq_disable(); 1608 1606 } 1609 1607
+3 -1
include/linux/cfi.h
··· 19 19 { 20 20 return report_cfi_failure(regs, addr, NULL, 0); 21 21 } 22 + #endif /* CONFIG_CFI_CLANG */ 22 23 23 24 #ifdef CONFIG_ARCH_USES_CFI_TRAPS 24 25 bool is_cfi_trap(unsigned long addr); 26 + #else 27 + static inline bool is_cfi_trap(unsigned long addr) { return false; } 25 28 #endif 26 - #endif /* CONFIG_CFI_CLANG */ 27 29 28 30 #ifdef CONFIG_MODULES 29 31 #ifdef CONFIG_ARCH_USES_CFI_TRAPS