Author: Armin Rigo <[email protected]>
Branch: shadowstack-issue2722
Changeset: r96574:0f76d02c2314
Date: 2019-05-08 12:27 +0200
http://bitbucket.org/pypy/pypy/changeset/0f76d02c2314/
Log: Link 'increase_root_stack_depth' through RPython and test it
diff --git a/rpython/memory/gctransform/framework.py
b/rpython/memory/gctransform/framework.py
--- a/rpython/memory/gctransform/framework.py
+++ b/rpython/memory/gctransform/framework.py
@@ -236,6 +236,9 @@
if root_walker.stacklet_support:
root_walker.need_stacklet_support(self, getfn)
+ if hasattr(root_walker, 'build_increase_root_stack_depth_ptr'):
+ root_walker.build_increase_root_stack_depth_ptr(getfn)
+
self.layoutbuilder.encode_type_shapes_now()
self.create_custom_trace_funcs(gcdata.gc, translator.rtyper)
@@ -1652,6 +1655,10 @@
else:
hop.rename("same_as")
+ def gct_gc_increase_root_stack_depth(self, hop):
+ hop.genop("direct_call",
+ [self.root_walker.gc_increase_root_stack_depth_ptr,
+ hop.spaceop.args[0]])
class TransformerLayoutBuilder(gctypelayout.TypeLayoutBuilder):
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_size = sizeofaddr * rsd
+ self.shadow_stack_pool.root_stack_depth = rsd
def push_stack(self, addr):
top = self.incr_stack(1)
@@ -253,6 +253,15 @@
self.gc_modified_shadowstack_ptr = getfn(gc_modified_shadowstack,
[], annmodel.s_None)
+ def build_increase_root_stack_depth_ptr(self, getfn):
+ shadow_stack_pool = self.shadow_stack_pool
+ def gc_increase_root_stack_depth(new_size):
+ shadow_stack_pool.increase_root_stack_depth(new_size)
+
+ self.gc_increase_root_stack_depth_ptr = getfn(
+ gc_increase_root_stack_depth, [annmodel.SomeInteger()],
+ annmodel.s_None)
+
def postprocess_graph(self, gct, graph, any_inlining):
from rpython.memory.gctransform import shadowcolor
if any_inlining:
@@ -269,7 +278,7 @@
"""Manages a pool of shadowstacks.
"""
_alloc_flavor_ = "raw"
- root_stack_size = sizeofaddr * 163840
+ root_stack_depth = 163840
has_threads = False
def __init__(self, gcdata):
@@ -334,36 +343,38 @@
def _prepare_unused_stack(self):
if self.unused_full_stack == llmemory.NULL:
- self.unused_full_stack = llmemory.raw_malloc(self.root_stack_size)
+ root_stack_size = sizeofaddr * self.root_stack_depth
+ self.unused_full_stack = llmemory.raw_malloc(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:
+ def increase_root_stack_depth(self, new_depth):
+ if new_depth <= self.root_stack_depth:
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)
+ addr = self._resize(self.gcdata.root_stack_base, used, new_depth)
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
+ self._resize_thread_shadowstacks(new_depth)
+ self.root_stack_depth = new_depth
- def _resize_thread_shadowstacks(self, new_size):
+ def _resize_thread_shadowstacks(self, new_depth):
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)
+ addr = self._resize(base, used, new_depth)
ssref.base = addr
ssref.top = addr + used
_resize_thread_shadowstacks._dont_inline_ = True
- def _resize(self, base, used, new_size):
+ def _resize(self, base, used, new_depth):
+ new_size = sizeofaddr * new_depth
ll_assert(used <= new_size, "shadowstack resize: overflow detected")
addr = llmemory.raw_malloc(new_size)
if addr == llmemory.NULL:
diff --git a/rpython/rlib/rgc.py b/rpython/rlib/rgc.py
--- a/rpython/rlib/rgc.py
+++ b/rpython/rlib/rgc.py
@@ -690,6 +690,13 @@
hop.exception_cannot_occur()
return hop.genop('gc_move_out_of_nursery', hop.args_v,
resulttype=hop.r_result)
[email protected]_look_inside
+def increase_root_stack_depth(new_depth):
+ """Shadowstack: make sure the size of the shadowstack is at least
+ 'new_depth' pointers."""
+ from rpython.rtyper.lltypesystem.lloperation import llop
+ llop.gc_increase_root_stack_depth(lltype.Void, new_depth)
+
# ____________________________________________________________
diff --git a/rpython/rtyper/llinterp.py b/rpython/rtyper/llinterp.py
--- a/rpython/rtyper/llinterp.py
+++ b/rpython/rtyper/llinterp.py
@@ -1226,6 +1226,9 @@
def op_gc_move_out_of_nursery(self, obj):
raise NotImplementedError("gc_move_out_of_nursery")
+ def op_gc_increase_root_stack_depth(self, new_depth):
+ raise NotImplementedError("gc_increase_root_stack_depth")
+
def op_revdb_stop_point(self, *args):
pass
def op_revdb_send_answer(self, *args):
diff --git a/rpython/rtyper/lltypesystem/lloperation.py
b/rpython/rtyper/lltypesystem/lloperation.py
--- a/rpython/rtyper/lltypesystem/lloperation.py
+++ b/rpython/rtyper/lltypesystem/lloperation.py
@@ -530,6 +530,7 @@
'gc_rawrefcount_next_dead': LLOp(),
'gc_move_out_of_nursery': LLOp(),
+ 'gc_increase_root_stack_depth': LLOp(),
'gc_push_roots' : LLOp(), # temporary: list of roots to save
'gc_pop_roots' : LLOp(), # temporary: list of roots to restore
diff --git a/rpython/rtyper/lltypesystem/opimpl.py
b/rpython/rtyper/lltypesystem/opimpl.py
--- a/rpython/rtyper/lltypesystem/opimpl.py
+++ b/rpython/rtyper/lltypesystem/opimpl.py
@@ -776,6 +776,9 @@
def op_gc_move_out_of_nursery(obj):
return obj
+def op_gc_increase_root_stack_depth(new_depth):
+ pass
+
def op_revdb_do_next_call():
pass
diff --git a/rpython/translator/c/test/test_newgc.py
b/rpython/translator/c/test/test_newgc.py
--- a/rpython/translator/c/test/test_newgc.py
+++ b/rpython/translator/c/test/test_newgc.py
@@ -1912,6 +1912,45 @@
def test_total_gc_time(self):
res = self.run("total_gc_time")
assert res > 0 # should take a few microseconds
+
+ def define_increase_root_stack_depth(cls):
+ class X:
+ pass
+ def g(n):
+ if n <= 0:
+ return None
+ x = X()
+ x.n = n
+ x.next = g(n - 1)
+ return x
+ def f(depth):
+ from rpython.rlib.rstack import _stack_set_length_fraction
+ _stack_set_length_fraction(50.0)
+ # ^^^ the default is enough for at least 10'000 (but less than
+ # 100'000) recursions of the simple function g(). We multiply
+ # it by 50.0 to make sure that 200'000 works. The default
+ # shadowstack depth is 163'840 entries, so 200'000 overflows
+ # that default shadowstack depth, and gives a segfault unless
+ # the following line works too.
+ from rpython.rlib.rgc import increase_root_stack_depth
+ increase_root_stack_depth(depth + 100)
+ #
+ g(depth)
+ return 42
+ return f
+
+ def test_increase_root_stack_depth(self):
+ if not sys.platform.startswith('linux'):
+ py.test.skip("linux only")
+ #
+ def myrunner(args):
+ args1 = ['/bin/bash', '-c', 'ulimit -s unlimited && %s' %
+ (' '.join(args),)]
+ return subprocess.check_output(args1)
+ res = self.run("increase_root_stack_depth", 200000, runner=myrunner)
+ assert res == 42
+
+
# ____________________________________________________________________
class TaggedPointersTest(object):
_______________________________________________
pypy-commit mailing list
[email protected]
https://mail.python.org/mailman/listinfo/pypy-commit