Skip to content
  • Alexander van Heukelum's avatar
    i386: fix/simplify espfix stack switching, move it into assembly · dc4c2a0a
    Alexander van Heukelum authored
    
    
    The espfix code triggers if we have a protected mode userspace
    application with a 16-bit stack. On returning to userspace, with iret,
    the CPU doesn't restore the high word of the stack pointer. This is an
    "official" bug, and the work-around used in the kernel is to temporarily
    switch to a 32-bit stack segment/pointer pair where the high word of the
    pointer is equal to the high word of the userspace stackpointer.
    
    The current implementation uses THREAD_SIZE to determine the cut-off,
    but there is no good reason not to use the more natural 64kb... However,
    implementing this by simply substituting THREAD_SIZE with 65536 in
    patch_espfix_desc crashed the test application. patch_espfix_desc tries
    to do what is described above, but gets it subtly wrong if the userspace
    stack pointer is just below a multiple of THREAD_SIZE: an overflow
    occurs to bit 13... With a bit of luck, when the kernelspace
    stackpointer is just below a 64kb-boundary, the overflow then ripples
    trough to bit 16 and userspace will see its stack pointer changed by
    65536.
    
    This patch moves all espfix code into entry_32.S. Selecting a 16-bit
    cut-off simplifies the code. The game with changing the limit dynamically
    is removed too. It complicates matters and I see no value in it. Changing
    only the top 16-bit word of ESP is one instruction and it also implies
    that only two bytes of the ESPFIX GDT entry need to be changed and this
    can be implemented in just a handful simple to understand instructions.
    As a side effect, the operation to compute the original ESP from the
    ESPFIX ESP and the GDT entry simplifies a bit too, and the remaining
    three instructions have been expanded inline in entry_32.S.
    
    impact: can now reliably run userspace with ESP=xxxxfffc on 16-bit
    stack segment
    
    Signed-off-by: default avatarAlexander van Heukelum <heukelum@fastmail.fm>
    Acked-by: default avatarStas Sergeev <stsp@aknet.ru>
    Signed-off-by: default avatarH. Peter Anvin <hpa@zytor.com>
    dc4c2a0a