mirror of
				https://github.com/torvalds/linux.git
				synced 2025-11-04 10:40:15 +02:00 
			
		
		
		
	x86/CPU/AMD: Do not leak quotient data after a division by 0
Under certain circumstances, an integer division by 0 which faults, can leave stale quotient data from a previous division operation on Zen1 microarchitectures. Do a dummy division 0/1 before returning from the #DE exception handler in order to avoid any leaks of potentially sensitive data. Signed-off-by: Borislav Petkov (AMD) <bp@alien8.de> Cc: <stable@kernel.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
		
							parent
							
								
									13b9372068
								
							
						
					
					
						commit
						77245f1c3c
					
				
					 4 changed files with 24 additions and 0 deletions
				
			
		| 
						 | 
				
			
			@ -495,4 +495,5 @@
 | 
			
		|||
 | 
			
		||||
/* BUG word 2 */
 | 
			
		||||
#define X86_BUG_SRSO			X86_BUG(1*32 + 0) /* AMD SRSO bug */
 | 
			
		||||
#define X86_BUG_DIV0			X86_BUG(1*32 + 1) /* AMD DIV0 speculation bug */
 | 
			
		||||
#endif /* _ASM_X86_CPUFEATURES_H */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -683,10 +683,12 @@ extern u16 get_llc_id(unsigned int cpu);
 | 
			
		|||
extern u32 amd_get_nodes_per_socket(void);
 | 
			
		||||
extern u32 amd_get_highest_perf(void);
 | 
			
		||||
extern bool cpu_has_ibpb_brtype_microcode(void);
 | 
			
		||||
extern void amd_clear_divider(void);
 | 
			
		||||
#else
 | 
			
		||||
static inline u32 amd_get_nodes_per_socket(void)	{ return 0; }
 | 
			
		||||
static inline u32 amd_get_highest_perf(void)		{ return 0; }
 | 
			
		||||
static inline bool cpu_has_ibpb_brtype_microcode(void)	{ return false; }
 | 
			
		||||
static inline void amd_clear_divider(void)		{ }
 | 
			
		||||
#endif
 | 
			
		||||
 | 
			
		||||
extern unsigned long arch_align_stack(unsigned long sp);
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -75,6 +75,10 @@ static const int amd_zenbleed[] =
 | 
			
		|||
			   AMD_MODEL_RANGE(0x17, 0x60, 0x0, 0x7f, 0xf),
 | 
			
		||||
			   AMD_MODEL_RANGE(0x17, 0xa0, 0x0, 0xaf, 0xf));
 | 
			
		||||
 | 
			
		||||
static const int amd_div0[] =
 | 
			
		||||
	AMD_LEGACY_ERRATUM(AMD_MODEL_RANGE(0x17, 0x00, 0x0, 0x2f, 0xf),
 | 
			
		||||
			   AMD_MODEL_RANGE(0x17, 0x50, 0x0, 0x5f, 0xf));
 | 
			
		||||
 | 
			
		||||
static bool cpu_has_amd_erratum(struct cpuinfo_x86 *cpu, const int *erratum)
 | 
			
		||||
{
 | 
			
		||||
	int osvw_id = *erratum++;
 | 
			
		||||
| 
						 | 
				
			
			@ -1130,6 +1134,11 @@ static void init_amd(struct cpuinfo_x86 *c)
 | 
			
		|||
		WARN_ON_ONCE(msr_set_bit(MSR_EFER, _EFER_AUTOIBRS));
 | 
			
		||||
 | 
			
		||||
	zenbleed_check(c);
 | 
			
		||||
 | 
			
		||||
	if (cpu_has_amd_erratum(c, amd_div0)) {
 | 
			
		||||
		pr_notice_once("AMD Zen1 DIV0 bug detected. Disable SMT for full protection.\n");
 | 
			
		||||
		setup_force_cpu_bug(X86_BUG_DIV0);
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
#ifdef CONFIG_X86_32
 | 
			
		||||
| 
						 | 
				
			
			@ -1309,3 +1318,13 @@ bool cpu_has_ibpb_brtype_microcode(void)
 | 
			
		|||
		return false;
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/*
 | 
			
		||||
 * Issue a DIV 0/1 insn to clear any division data from previous DIV
 | 
			
		||||
 * operations.
 | 
			
		||||
 */
 | 
			
		||||
void noinstr amd_clear_divider(void)
 | 
			
		||||
{
 | 
			
		||||
	asm volatile(ALTERNATIVE("", "div %2\n\t", X86_BUG_DIV0)
 | 
			
		||||
		     :: "a" (0), "d" (0), "r" (1));
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -206,6 +206,8 @@ DEFINE_IDTENTRY(exc_divide_error)
 | 
			
		|||
{
 | 
			
		||||
	do_error_trap(regs, 0, "divide error", X86_TRAP_DE, SIGFPE,
 | 
			
		||||
		      FPE_INTDIV, error_get_trap_addr(regs));
 | 
			
		||||
 | 
			
		||||
	amd_clear_divider();
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
DEFINE_IDTENTRY(exc_overflow)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
		Reference in a new issue