On Thu, Jan 11, 2018 at 08:39:25PM -0700, Theo de Raadt wrote:
> Stefan (stefan@) and I have been working for a few months on this
> diff, with help from a few others.
> 
> At every trap and system call, it checks if the stack-pointer is on a
> page that is marked MAP_STACK.  execve() is changed to create such
> mappings for the process stack.  Also, libpthread is taught the new
> MAP_STACK flag to use with mmap().
> 
> There is no corresponding system call which can set MAP_FLAG on an
> existing page, you can only set the flag by mapping new memory into
> place.  That is a piece of the security model.
> 
> The purpose of this change is to twart stack pivots, which apparently
> have gained some popularity in JIT ROP attacks.  It makes it difficult
> to place the ROP stack in regular data memory, and then perform a
> system call from it.  Workarounds are cumbersome, increasing the need
> for far more gadgetry.  But also the trap case -- if any memory
> experiences a demand page fault, the same check will occur and
> potentially also kill the process.
> 
> We have experimented a little with performing this check during device
> interrupts, but there are some locking concerns and performance may
> then become a concern.  It'll be best to gain experience from handle
> of syncronous trap cases first.
> 
> chrome and other applications I use run fine!
> 
> I'm asking for some feedback to discover what ports this breaks, we'd
> like to know.  Those would be ports which try to (unconvenionally)
> create their stacks in malloc()'d memory or inside another
> datastructure.  Most of them are probably easily fixed ...

lang/sbcl will need a small patch:

$OpenBSD$

Index: src/runtime/thread.c
--- src/runtime/thread.c.orig
+++ src/runtime/thread.c
@@ -636,9 +636,16 @@ create_thread_struct(lispobj initial_function) {
      * on the alignment passed from os_validate, since that might
      * assume the current (e.g. 4k) pagesize, while we calculate with
      * the biggest (e.g. 64k) pagesize allowed by the ABI. */
+#ifdef MAP_STACK
+    spaces = mmap(0, THREAD_STRUCT_SIZE, OS_VM_PROT_ALL,
+       MAP_PRIVATE | MAP_ANON | MAP_STACK, -1, 0);
+    if(spaces == MAP_FAILED)
+        return NULL;
+#else
     spaces=os_validate(0, THREAD_STRUCT_SIZE);
     if(!spaces)
         return NULL;
+#endif
     /* Aligning up is safe as THREAD_STRUCT_SIZE has
      * THREAD_ALIGNMENT_BYTES padding. */
     aligned_spaces = (void *)((((uword_t)(char *)spaces)

Reply via email to