On Thu, Feb 20, 2020 at 01:17:27PM +0100, Borislav Petkov wrote: > On Wed, Feb 19, 2020 at 04:57:15PM +0100, Peter Zijlstra wrote: > > - memmove(&gpregs->ip, (void *)regs->sp, 5*8); > > + for (i = 0; i < count; i++) { > > + int idx = (dst <= src) ? i : count - i; > > + dst[idx] = src[idx]; > > + } > > Or, you can actually unroll it. This way it even documents clearly what > it does: > > diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c > index fe38015ed50a..2b790a574ba5 100644 > --- a/arch/x86/kernel/traps.c > +++ b/arch/x86/kernel/traps.c > @@ -298,6 +298,7 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign > regs->ip == (unsigned long)native_irq_return_iret) > { > struct pt_regs *gpregs = (struct pt_regs *)this_cpu_read(cpu_tss_rw.x86_tss.sp0) - 1; > + unsigned long *p = (unsigned long *)regs->sp; > > /* > * regs->sp points to the failing IRET frame on the > @@ -305,7 +306,11 @@ dotraplinkage void do_double_fault(struct pt_regs *regs, long error_code, unsign > * in gpregs->ss through gpregs->ip. > * > */ > - memmove(&gpregs->ip, (void *)regs->sp, 5*8); > + gpregs->ip = *p; > + gpregs->cs = *(p + 1); > + gpregs->flags = *(p + 2); > + gpregs->sp = *(p + 3); > + gpregs->ss = *(p + 4); > gpregs->orig_ax = 0; /* Missing (lost) #GP error code */ > > /* While I love that; is that actually correct? This is an unroll of memcpy() not memmove(). IFF the ranges overlap, the above is buggered. Was the original memmove() really needed?