• Josh Poimboeuf's avatar
    x86/entry: Fix register corruption in compat syscall · 036c07c0
    Josh Poimboeuf authored
    A panic was reported in the init process on AMD:
    
      Run /sbin/init as init process
      init[1]: segfault at f7fd5ca0 ip 00000000f7f5bbc7 sp 00000000ffa06aa0 error 7 in libc.so[f7f51000+4e000]
      Code: 8a 44 24 10 88 41 ff 8b 44 24 10 83 c4 2c 5b 5e 5f 5d c3 53 83 ec 08 8b 5c 24 10 81 fb 00 f0 ff ff 76 0c e8 ba dc ff ff f7 db <89> 18 83 cb ff 83 c4 08 89 d8 5b c3 e8 81 60 ff ff 05 28 84 07 00
      Kernel panic - not syncing: Attempted to kill init! exitcode=0x0000000b
      CPU: 1 PID: 1 Comm: init Tainted: G        W         5.18.0-rc7-next-20220519 #1
      Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS rel-1.15.0-0-g2dd4b9b3f840-prebuilt.qemu.org 04/01/2014
      Call Trace:
       <TASK>
       dump_stack_lvl+0x57/0x7d
       panic+0x10f/0x28d
       do_exit.cold+0x18/0x48
       do_group_exit+0x2e/0xb0
       get_signal+0xb6d/0xb80
       arch_do_signal_or_restart+0x31/0x760
       ? show_opcodes.cold+0x1c/0x21
       ? force_sig_fault+0x49/0x70
       exit_to_user_mode_prepare+0x131/0x1a0
       irqentry_exit_to_user_mode+0x5/0x30
       asm_exc_page_fault+0x27/0x30
      RIP: 0023:0xf7f5bbc7
      Code: 8a 44 24 10 88 41 ff 8b 44 24 10 83 c4 2c 5b 5e 5f 5d c3 53 83 ec 08 8b 5c 24 10 81 fb 00 f0 ff ff 76 0c e8 ba dc ff ff f7 db <89> 18 83 cb ff 83 c4 08 89 d8 5b c3 e8 81 60 ff ff 05 28 84 07 00
      RSP: 002b:00000000ffa06aa0 EFLAGS: 00000217
      RAX: 00000000f7fd5ca0 RBX: 000000000000000c RCX: 0000000000001000
      RDX: 0000000000000001 RSI: 00000000f7fd5b60 RDI: 00000000f7fd5b60
      RBP: 00000000f7fd1c1c R08: 0000000000000000 R09: 0000000000000000
      R10: 0000000000000000 R11: 0000000000000206 R12: 0000000000000000
      R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
       </TASK>
    
    The task's CX register got corrupted by commit 8c42819b ("x86/entry:
    Use PUSH_AND_CLEAR_REGS for compat"), which overlooked the fact that
    compat SYSCALL apparently stores the user's CX value in BP.
    
    Before that commit, CX was saved from its stashed value in BP:
    
    	pushq   %rbp                    /* pt_regs->cx (stashed in bp) */
    
    But then it got changed to:
    
    	pushq	%rcx			/* pt_regs->cx */
    
    So the wrong value got saved and later restored back to the user.  Fix
    it by pushing the correct value again (BP) for regs->cx.
    
    Fixes: 8c42819b ("x86/entry: Use PUSH_AND_CLEAR_REGS for compat")
    Reported-by: default avatarGuenter Roeck <linux@roeck-us.net>
    Signed-off-by: default avatarJosh Poimboeuf <jpoimboe@kernel.org>
    Signed-off-by: default avatarPeter Zijlstra (Intel) <peterz@infradead.org>
    Tested-by: default avatarGuenter Roeck <linux@roeck-us.net>
    Link: https://lkml.kernel.org/r/b5a26592c9dd60bbacdf97974a7433fd802a5593.1652985970.git.jpoimboe@kernel.org
    036c07c0
calling.h 10.1 KB