svn commit: r279949 - in head: lib/libstand sys/boot/amd64 sys/boot/efi/libefi sys/boot/ficl

John Baldwin jhb at freebsd.org
Fri Mar 13 10:26:36 UTC 2015


On Friday, March 13, 2015 09:38:16 AM John Baldwin wrote:
> Author: jhb
> Date: Fri Mar 13 09:38:16 2015
> New Revision: 279949
> URL: https://svnweb.freebsd.org/changeset/base/279949
> 
> Log:
>   The System V ABI for amd64 allows functions to use space in a 128 byte
>   redzone below the stack pointer for scratch space and requires
>   interrupt and signal frames to avoid overwriting it. However, EFI uses
>   the Windows ABI which does not support this. As a result, interrupt
>   handlers in EFI push their interrupt frames directly on top of the
>   stack pointer. If the compiler used the red zone in a function in the
>   EFI loader, then a device interrupt that occurred while that function
>   was running could trash its local variables.  In practice this happens
>   fairly reliable when using gzipfs as an interrupt during decompression
>   can trash the local variables in the inflate_table() function
>   resulting in corrupted output or hangs.
>   
>   Fix this by disabling the redzone for amd64 EFI binaries. This
>   requires building not only the loader but any libraries used by the
>   loader without redzone support.
>   
>   Thanks to Jilles for pointing me at the redzone once I found the stack
>   corruption.

Note that without this, gzipfs was effectively useless in the EFI loader
for any non-trivial cases (it was even useless in my trivial cases during
testing, but there might be some trivial case (zero-byte file or some
such) that can be decompressed quickly enough to not trigger a device
interrupt).

Also, while the redzone is cute and all, it seems to me that it is very
impractical for any ring 0 context.  Specifically, the CPU doesn't know
anything about it, and any interrupt or exception in ring 0 is going to
push the hardware-defined bits of the frame (%rip, etc.) on top of the
stack pointer overwriting part of the redzone.  (Our kernel is built with
-mno-red-zone as well.)  You could perhaps always use a dedicated stack
for all interrupts and faults via IST, but any nesting there would 
result in reusing a stack if you aren't careful (e.g. a fault in
interrupt context).  I suppose it might work to have one IST entry for
device interrupts, a second for most faults / exceptions, and a third for
double faults (double faults generally need a dedicated stack regardless).
Of course, all these dedicated stacks would have to be per-CPU (as the
double fault stack is) and any fault or interrupt would have to implicitly
pin the thread for the duration (probably not a big deal).

-- 
John Baldwin


More information about the svn-src-all mailing list