[pypy-commit] pypy shadowstack-issue2722: in-progress

arigo pypy.commits at gmail.com
Sat May 4 10:41:04 EDT 2019


Author: Armin Rigo <arigo at tunes.org>
Branch: shadowstack-issue2722
Changeset: r96571:b47f28c00520
Date: 2019-05-04 16:40 +0200
http://bitbucket.org/pypy/pypy/changeset/b47f28c00520/

Log:	in-progress

diff --git a/rpython/memory/gctransform/shadowstack.py b/rpython/memory/gctransform/shadowstack.py
--- a/rpython/memory/gctransform/shadowstack.py
+++ b/rpython/memory/gctransform/shadowstack.py
@@ -95,7 +95,7 @@
         self.shadow_stack_pool = ShadowStackPool(gcdata)
         rsd = gctransformer.root_stack_depth
         if rsd is not None:
-            self.shadow_stack_pool.root_stack_depth = rsd
+            self.shadow_stack_pool.root_stack_size = sizeofaddr * rsd
 
     def push_stack(self, addr):
         top = self.incr_stack(1)
@@ -140,6 +140,7 @@
         # this is a dict {tid: SHADOWSTACKREF}, where the tid for the
         # current thread may be missing so far
         gcdata.thread_stacks = None
+        shadow_stack_pool.has_threads = True
 
         # Return the thread identifier, as an integer.
         get_tid = rthread.get_ident
@@ -268,7 +269,8 @@
     """Manages a pool of shadowstacks.
     """
     _alloc_flavor_ = "raw"
-    root_stack_depth = 163840
+    root_stack_size = sizeofaddr * 163840
+    has_threads = False
 
     def __init__(self, gcdata):
         self.unused_full_stack = llmemory.NULL
@@ -332,11 +334,47 @@
 
     def _prepare_unused_stack(self):
         if self.unused_full_stack == llmemory.NULL:
-            root_stack_size = sizeofaddr * self.root_stack_depth
-            self.unused_full_stack = llmemory.raw_malloc(root_stack_size)
+            self.unused_full_stack = llmemory.raw_malloc(self.root_stack_size)
             if self.unused_full_stack == llmemory.NULL:
                 raise MemoryError
 
+    def increase_root_stack_size(self, new_size):
+        if new_size <= self.root_stack_size:
+            return     # can't easily decrease the size
+        if self.unused_full_stack:
+            llmemory.raw_free(self.unused_full_stack)
+            self.unused_full_stack = llmemory.NULL
+        used = self.gcdata.root_stack_top - self.gcdata.root_stack_base
+        addr = self._resize(self.gcdata.root_stack_base, used, new_size)
+        self.gcdata.root_stack_base = addr
+        self.gcdata.root_stack_top  = addr + used
+        # no gc operations above: we just switched shadowstacks
+        if self.has_threads:
+            self._resize_thread_shadowstacks(new_size)
+        self.root_stack_size = new_size
+
+    def _resize_thread_shadowstacks(self, new_size):
+        if self.gcdata.thread_stacks is not None:
+            for ssref in self.gcdata.thread_stacks.values():
+                if ssref.base:
+                    used = ssref.top - ssref.base
+                    addr = self._resize(base, used, new_size)
+                    ssref.base = addr
+                    ssref.top = addr + used
+    _resize_thread_shadowstacks._dont_inline_ = True
+
+    def _resize(self, base, used, new_size):
+        ll_assert(used <= new_size, "shadowstack resize: overflow detected")
+        addr = llmemory.raw_malloc(new_size)
+        if addr == llmemory.NULL:
+            raise MemoryError
+        # note that we don't know the total memory size of 'base', but we
+        # know the size of the part that is used right now, and we only need
+        # to copy that
+        llmemory.raw_memmove(base, addr, used)
+        llmemory.raw_free(base)
+        return addr
+
 
 def get_shadowstackref(root_walker, gctransformer):
     if hasattr(gctransformer, '_SHADOWSTACKREF'):


More information about the pypy-commit mailing list