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)