It is safe to do memcpy() in fixup_bad_iret() now.

Signed-off-by: Lai Jiangshan <[email protected]>
---
 arch/x86/kernel/traps.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c
index 9d16672865f8..1a0253a80a4c 100644
--- a/arch/x86/kernel/traps.c
+++ b/arch/x86/kernel/traps.c
@@ -660,17 +660,23 @@ struct bad_iret_stack *fixup_bad_iret(struct 
bad_iret_stack *s)
         * (rather than just below the IRET frame) and we want to
         * pretend that the exception came from the IRET target.
         */
-       struct bad_iret_stack tmp, *new_stack =
+       struct bad_iret_stack *new_stack =
                (struct bad_iret_stack 
*)__this_cpu_read(cpu_current_top_of_stack) - 1;
 
-       /* Copy the IRET target to the temporary storage. */
-       memcpy(&tmp.regs.ip, (void *)s->regs.sp, 5*8);
+       /*
+        * Both the IRET frame and the saved pt_regs must be on the
+        * entry stacks since iret to user is only issued on the
+        * entry stacks. So they don't overlap with kernel stack and
+        * memcpy() is safe to copy them.
+        */
+       BUG_ON(((unsigned long)s - (unsigned long)new_stack) < PAGE_SIZE ||
+              ((unsigned long)new_stack - (unsigned long)s) < PAGE_SIZE);
 
-       /* Copy the remainder of the stack from the current stack. */
-       memcpy(&tmp, s, offsetof(struct bad_iret_stack, regs.ip));
+       /* Copy the IRET target to the new stack. */
+       memcpy(&new_stack->regs.ip, (void *)s->regs.sp, 5*8);
 
-       /* Update the entry stack */
-       memcpy(new_stack, &tmp, sizeof(tmp));
+       /* Copy the remainder of the stack from the current stack. */
+       memcpy(new_stack, s, offsetof(struct bad_iret_stack, regs.ip));
 
        BUG_ON(!user_mode(&new_stack->regs));
        return new_stack;
-- 
2.20.1

Reply via email to