libc - Fix bugs in getcontext(), setcontext(), and swapcontext()
authorMatthew Dillon <dillon@apollo.backplane.com>
Mon, 21 Dec 2015 08:33:54 +0000 (00:33 -0800)
committerMatthew Dillon <dillon@apollo.backplane.com>
Tue, 22 Dec 2015 00:39:08 +0000 (16:39 -0800)
commit63261abbc5bc59d5ff6f9015d352ce1782cd1dd7
tree99a0730ccfc881722deb8a28c104046988c4b48d
parent7646771a8df242ed8cb0ebfa8940e9599258783b
libc - Fix bugs in getcontext(), setcontext(), and swapcontext()

* Fix multiple bugs revealed by qemu's use of these functions.  Most of
  these fixes are accomplished by calling sigreturn(uctx) to restore the
  state instead of trying to roll our own in userland.  This won't be much
  slower (if at all) because we had to save and restore the signal state
  in the userland code anyway, so we could not avoid making at least one
  system call.

  Using sigreturn() handles the signal mask atomicy for us so we don't have
  to deal with it and fixes numerous other issues.  Along with this change,
  adjust getcontext() and makecontext() to fill out additional important
  fields in the ucontext that sigreturn() inspects.

* Fixes two stack corruption bugs. First, getcontext() was calling
  get_mcontext() and get_mcontext() was setting up the setcontext return
  state to return 1 ... from get_mcontext(), NOT from getcontext().  If
  normal operations or signals mess with the stack, the double return
  will not work.  Oops.

  Secondly, getcontext scribbled over the red-zone in a way that is not
  permitted.

* setcontext() was restoring the context as saved by makecontext() or
  getcontext(), but setcontext() can also be called with the ucontext
  from the signal handler which requires a full restore.  setcontext()
  was not restoring FPU or scratch registers or rflags.

* Fixes signal restoration bug and corruption that can mess up emulation
  in qemu.

* Fixes issues with qemu related to SMP startup and lack of preemption.

Reported-by: ivadasz
lib/libc/gen/ucontext.c
lib/libc/x86_64/gen/makecontext.c
lib/libc/x86_64/gen/mcontext.S
lib/libc/x86_64/sys/asmcontext.c
lib/libc/x86_64/sys/getcontext.S