qemu-devel.nongnu.org archive mirror
 help / color / mirror / Atom feed
From: Daniele Buono <dbuono@linux.vnet.ibm.com>
To: qemu-devel@nongnu.org
Cc: Kevin Wolf <kwolf@redhat.com>,
	Paolo Bonzini <pbonzini@redhat.com>,
	Tobin Feldman-Fitzthum <tobin@ibm.com>,
	Daniele Buono <dbuono@linux.vnet.ibm.com>,
	Stefan Hajnoczi <stefanha@redhat.com>
Subject: [PATCH 1/4] coroutine: support SafeStack in ucontext backend
Date: Wed, 29 Apr 2020 15:44:17 -0400	[thread overview]
Message-ID: <20200429194420.21147-2-dbuono@linux.vnet.ibm.com> (raw)
In-Reply-To: <20200429194420.21147-1-dbuono@linux.vnet.ibm.com>

LLVM's SafeStack instrumentation does not yet support programs that make
use of the APIs in ucontext.h
With the current implementation of coroutine-ucontext, the resulting
binary is incorrect, with different coroutines sharing the same unsafe
stack and producing undefined behavior at runtime.
This fix allocates an additional unsafe stack area for each coroutine,
and sets the new unsafe stack pointer before calling swapcontext() in
qemu_coroutine_new.
This is the only place where the pointer needs to be manually updated,
since sigsetjmp/siglongjmp are already instrumented by LLVM to properly
support SafeStack.
The additional stack is then freed in qemu_coroutine_delete.

Signed-off-by: Daniele Buono <dbuono@linux.vnet.ibm.com>
---
 include/qemu/coroutine_int.h |  6 ++++++
 util/coroutine-ucontext.c    | 25 +++++++++++++++++++++++++
 2 files changed, 31 insertions(+)

diff --git a/include/qemu/coroutine_int.h b/include/qemu/coroutine_int.h
index bd6b0468e1..2ffd75ddbe 100644
--- a/include/qemu/coroutine_int.h
+++ b/include/qemu/coroutine_int.h
@@ -28,6 +28,12 @@
 #include "qemu/queue.h"
 #include "qemu/coroutine.h"
 
+#if defined(__has_feature) && __has_feature(safe_stack)
+#define CONFIG_SAFESTACK 1
+/* Pointer to the unsafe stack, defined by the compiler */
+extern __thread void *__safestack_unsafe_stack_ptr;
+#endif
+
 #define COROUTINE_STACK_SIZE (1 << 20)
 
 typedef enum {
diff --git a/util/coroutine-ucontext.c b/util/coroutine-ucontext.c
index bd593e61bc..b79e9df9eb 100644
--- a/util/coroutine-ucontext.c
+++ b/util/coroutine-ucontext.c
@@ -41,6 +41,11 @@ typedef struct {
     Coroutine base;
     void *stack;
     size_t stack_size;
+#ifdef CONFIG_SAFESTACK
+    /* Need an unsafe stack for each coroutine */
+    void *unsafe_stack;
+    size_t unsafe_stack_size;
+#endif
     sigjmp_buf env;
 
 #ifdef CONFIG_VALGRIND_H
@@ -140,6 +145,10 @@ Coroutine *qemu_coroutine_new(void)
     co = g_malloc0(sizeof(*co));
     co->stack_size = COROUTINE_STACK_SIZE;
     co->stack = qemu_alloc_stack(&co->stack_size);
+#ifdef CONFIG_SAFESTACK
+    co->unsafe_stack_size = COROUTINE_STACK_SIZE;
+    co->unsafe_stack = qemu_alloc_stack(&co->unsafe_stack_size);
+#endif
     co->base.entry_arg = &old_env; /* stash away our jmp_buf */
 
     uc.uc_link = &old_uc;
@@ -160,6 +169,19 @@ Coroutine *qemu_coroutine_new(void)
     /* swapcontext() in, siglongjmp() back out */
     if (!sigsetjmp(old_env, 0)) {
         start_switch_fiber(&fake_stack_save, co->stack, co->stack_size);
+#ifdef CONFIG_SAFESTACK
+        /*
+         * Before we swap the context, set the new unsafe stack
+         * The unsafe stack grows just like the normal stack, so start from
+         * the last usable location of the memory area.
+         * NOTE: we don't have to re-set it afterwards because sigsetjmp was
+         * called with the original usp. Since we are not coming back with a
+         * swapcontext, but with a siglongjmp, when we are back here we
+         * already have usp restored to the valid one for this function
+         */
+        void *usp = co->unsafe_stack + co->unsafe_stack_size;
+        __safestack_unsafe_stack_ptr = usp;
+#endif
         swapcontext(&old_uc, &uc);
     }
 
@@ -192,6 +214,9 @@ void qemu_coroutine_delete(Coroutine *co_)
 #endif
 
     qemu_free_stack(co->stack, co->stack_size);
+#ifdef CONFIG_SAFESTACK
+    qemu_free_stack(co->unsafe_stack, co->unsafe_stack_size);
+#endif
     g_free(co);
 }
 
-- 
2.26.2



  reply	other threads:[~2020-04-29 19:48 UTC|newest]

Thread overview: 24+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2020-04-29 19:44 [PATCH 0/4] Add support for SafeStack Daniele Buono
2020-04-29 19:44 ` Daniele Buono [this message]
2020-05-21  9:44   ` [PATCH 1/4] coroutine: support SafeStack in ucontext backend Stefan Hajnoczi
2020-05-22 15:18     ` Daniele Buono
2020-05-27 10:34       ` Stefan Hajnoczi
2020-04-29 19:44 ` [PATCH 2/4] coroutine: Add check for SafeStack in sigalstack Daniele Buono
2020-05-04 14:56   ` Philippe Mathieu-Daudé
2020-05-21  9:49   ` Stefan Hajnoczi
2020-05-27 17:56     ` Daniele Buono
2020-04-29 19:44 ` [PATCH 3/4] configure: add flag to enable SafeStack Daniele Buono
2020-05-21  9:52   ` Stefan Hajnoczi
2020-05-22 15:24     ` Daniele Buono
2020-05-27 11:12       ` Stefan Hajnoczi
2020-05-27 13:48         ` Daniele Buono
2020-04-29 19:44 ` [PATCH 4/4] check-block: Enable iotests with SafeStack Daniele Buono
2020-05-21  9:59   ` Stefan Hajnoczi
2020-05-22 15:35     ` Daniele Buono
2020-05-27 11:13       ` Stefan Hajnoczi
2020-05-04 14:55 ` [PATCH 0/4] Add support for SafeStack Philippe Mathieu-Daudé
2020-05-05 13:15 ` Philippe Mathieu-Daudé
2020-05-05 13:31   ` Daniel P. Berrangé
2020-05-05 13:56     ` Philippe Mathieu-Daudé
2020-05-13 14:48       ` Daniele Buono
2020-05-21 10:00         ` Stefan Hajnoczi

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20200429194420.21147-2-dbuono@linux.vnet.ibm.com \
    --to=dbuono@linux.vnet.ibm.com \
    --cc=kwolf@redhat.com \
    --cc=pbonzini@redhat.com \
    --cc=qemu-devel@nongnu.org \
    --cc=stefanha@redhat.com \
    --cc=tobin@ibm.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).