1 // SPDX-License-Identifier: GPL-2.0-only 2 #include <linux/extable.h> 3 #include <linux/uaccess.h> 4 #include <linux/sched/debug.h> 5 #include <xen/xen.h> 6 7 #include <asm/fpu/internal.h> 8 #include <asm/traps.h> 9 #include <asm/kdebug.h> 10 11 typedef bool (*ex_handler_t)(const struct exception_table_entry *, 12 struct pt_regs *, int, unsigned long, 13 unsigned long); 14 15 static inline unsigned long 16 ex_fixup_addr(const struct exception_table_entry *x) 17 { 18 return (unsigned long)&x->fixup + x->fixup; 19 } 20 static inline ex_handler_t 21 ex_fixup_handler(const struct exception_table_entry *x) 22 { 23 return (ex_handler_t)((unsigned long)&x->handler + x->handler); 24 } 25 26 __visible bool ex_handler_default(const struct exception_table_entry *fixup, 27 struct pt_regs *regs, int trapnr, 28 unsigned long error_code, 29 unsigned long fault_addr) 30 { 31 regs->ip = ex_fixup_addr(fixup); 32 return true; 33 } 34 EXPORT_SYMBOL(ex_handler_default); 35 36 __visible bool ex_handler_fault(const struct exception_table_entry *fixup, 37 struct pt_regs *regs, int trapnr, 38 unsigned long error_code, 39 unsigned long fault_addr) 40 { 41 regs->ip = ex_fixup_addr(fixup); 42 regs->ax = trapnr; 43 return true; 44 } 45 EXPORT_SYMBOL_GPL(ex_handler_fault); 46 47 /* 48 * Handler for when we fail to restore a task's FPU state. We should never get 49 * here because the FPU state of a task using the FPU (task->thread.fpu.state) 50 * should always be valid. However, past bugs have allowed userspace to set 51 * reserved bits in the XSAVE area using PTRACE_SETREGSET or sys_rt_sigreturn(). 52 * These caused XRSTOR to fail when switching to the task, leaking the FPU 53 * registers of the task previously executing on the CPU. Mitigate this class 54 * of vulnerability by restoring from the initial state (essentially, zeroing 55 * out all the FPU registers) if we can't restore from the task's FPU state. 56 */ 57 __visible bool ex_handler_fprestore(const struct exception_table_entry *fixup, 58 struct pt_regs *regs, int trapnr, 59 unsigned long error_code, 60 unsigned long fault_addr) 61 { 62 regs->ip = ex_fixup_addr(fixup); 63 64 WARN_ONCE(1, "Bad FPU state detected at %pB, reinitializing FPU registers.", 65 (void *)instruction_pointer(regs)); 66 67 __copy_kernel_to_fpregs(&init_fpstate, -1); 68 return true; 69 } 70 EXPORT_SYMBOL_GPL(ex_handler_fprestore); 71 72 __visible bool ex_handler_uaccess(const struct exception_table_entry *fixup, 73 struct pt_regs *regs, int trapnr, 74 unsigned long error_code, 75 unsigned long fault_addr) 76 { 77 WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); 78 regs->ip = ex_fixup_addr(fixup); 79 return true; 80 } 81 EXPORT_SYMBOL(ex_handler_uaccess); 82 83 __visible bool ex_handler_copy(const struct exception_table_entry *fixup, 84 struct pt_regs *regs, int trapnr, 85 unsigned long error_code, 86 unsigned long fault_addr) 87 { 88 WARN_ONCE(trapnr == X86_TRAP_GP, "General protection fault in user access. Non-canonical address?"); 89 regs->ip = ex_fixup_addr(fixup); 90 regs->ax = trapnr; 91 return true; 92 } 93 EXPORT_SYMBOL(ex_handler_copy); 94 95 __visible bool ex_handler_rdmsr_unsafe(const struct exception_table_entry *fixup, 96 struct pt_regs *regs, int trapnr, 97 unsigned long error_code, 98 unsigned long fault_addr) 99 { 100 if (pr_warn_once("unchecked MSR access error: RDMSR from 0x%x at rIP: 0x%lx (%pS)\n", 101 (unsigned int)regs->cx, regs->ip, (void *)regs->ip)) 102 show_stack_regs(regs); 103 104 /* Pretend that the read succeeded and returned 0. */ 105 regs->ip = ex_fixup_addr(fixup); 106 regs->ax = 0; 107 regs->dx = 0; 108 return true; 109 } 110 EXPORT_SYMBOL(ex_handler_rdmsr_unsafe); 111 112 __visible bool ex_handler_wrmsr_unsafe(const struct exception_table_entry *fixup, 113 struct pt_regs *regs, int trapnr, 114 unsigned long error_code, 115 unsigned long fault_addr) 116 { 117 if (pr_warn_once("unchecked MSR access error: WRMSR to 0x%x (tried to write 0x%08x%08x) at rIP: 0x%lx (%pS)\n", 118 (unsigned int)regs->cx, (unsigned int)regs->dx, 119 (unsigned int)regs->ax, regs->ip, (void *)regs->ip)) 120 show_stack_regs(regs); 121 122 /* Pretend that the write succeeded. */ 123 regs->ip = ex_fixup_addr(fixup); 124 return true; 125 } 126 EXPORT_SYMBOL(ex_handler_wrmsr_unsafe); 127 128 __visible bool ex_handler_clear_fs(const struct exception_table_entry *fixup, 129 struct pt_regs *regs, int trapnr, 130 unsigned long error_code, 131 unsigned long fault_addr) 132 { 133 if (static_cpu_has(X86_BUG_NULL_SEG)) 134 asm volatile ("mov %0, %%fs" : : "rm" (__USER_DS)); 135 asm volatile ("mov %0, %%fs" : : "rm" (0)); 136 return ex_handler_default(fixup, regs, trapnr, error_code, fault_addr); 137 } 138 EXPORT_SYMBOL(ex_handler_clear_fs); 139 140 enum handler_type ex_get_fault_handler_type(unsigned long ip) 141 { 142 const struct exception_table_entry *e; 143 ex_handler_t handler; 144 145 e = search_exception_tables(ip); 146 if (!e) 147 return EX_HANDLER_NONE; 148 handler = ex_fixup_handler(e); 149 if (handler == ex_handler_fault) 150 return EX_HANDLER_FAULT; 151 else if (handler == ex_handler_uaccess || handler == ex_handler_copy) 152 return EX_HANDLER_UACCESS; 153 else 154 return EX_HANDLER_OTHER; 155 } 156 157 int fixup_exception(struct pt_regs *regs, int trapnr, unsigned long error_code, 158 unsigned long fault_addr) 159 { 160 const struct exception_table_entry *e; 161 ex_handler_t handler; 162 163 #ifdef CONFIG_PNPBIOS 164 if (unlikely(SEGMENT_IS_PNP_CODE(regs->cs))) { 165 extern u32 pnp_bios_fault_eip, pnp_bios_fault_esp; 166 extern u32 pnp_bios_is_utter_crap; 167 pnp_bios_is_utter_crap = 1; 168 printk(KERN_CRIT "PNPBIOS fault.. attempting recovery.\n"); 169 __asm__ volatile( 170 "movl %0, %%esp\n\t" 171 "jmp *%1\n\t" 172 : : "g" (pnp_bios_fault_esp), "g" (pnp_bios_fault_eip)); 173 panic("do_trap: can't hit this"); 174 } 175 #endif 176 177 e = search_exception_tables(regs->ip); 178 if (!e) 179 return 0; 180 181 handler = ex_fixup_handler(e); 182 return handler(e, regs, trapnr, error_code, fault_addr); 183 } 184 185 extern unsigned int early_recursion_flag; 186 187 /* Restricted version used during very early boot */ 188 void __init early_fixup_exception(struct pt_regs *regs, int trapnr) 189 { 190 /* Ignore early NMIs. */ 191 if (trapnr == X86_TRAP_NMI) 192 return; 193 194 if (early_recursion_flag > 2) 195 goto halt_loop; 196 197 /* 198 * Old CPUs leave the high bits of CS on the stack 199 * undefined. I'm not sure which CPUs do this, but at least 200 * the 486 DX works this way. 201 * Xen pv domains are not using the default __KERNEL_CS. 202 */ 203 if (!xen_pv_domain() && regs->cs != __KERNEL_CS) 204 goto fail; 205 206 /* 207 * The full exception fixup machinery is available as soon as 208 * the early IDT is loaded. This means that it is the 209 * responsibility of extable users to either function correctly 210 * when handlers are invoked early or to simply avoid causing 211 * exceptions before they're ready to handle them. 212 * 213 * This is better than filtering which handlers can be used, 214 * because refusing to call a handler here is guaranteed to 215 * result in a hard-to-debug panic. 216 * 217 * Keep in mind that not all vectors actually get here. Early 218 * page faults, for example, are special. 219 */ 220 if (fixup_exception(regs, trapnr, regs->orig_ax, 0)) 221 return; 222 223 if (trapnr == X86_TRAP_UD) { 224 if (report_bug(regs->ip, regs) == BUG_TRAP_TYPE_WARN) { 225 /* Skip the ud2. */ 226 regs->ip += LEN_UD2; 227 return; 228 } 229 230 /* 231 * If this was a BUG and report_bug returns or if this 232 * was just a normal #UD, we want to continue onward and 233 * crash. 234 */ 235 } 236 237 fail: 238 early_printk("PANIC: early exception 0x%02x IP %lx:%lx error %lx cr2 0x%lx\n", 239 (unsigned)trapnr, (unsigned long)regs->cs, regs->ip, 240 regs->orig_ax, read_cr2()); 241 242 show_regs(regs); 243 244 halt_loop: 245 while (true) 246 halt(); 247 } 248