Index: vm/port/src/signals/linux/signals_common.cpp =================================================================== --- vm/port/src/signals/linux/signals_common.cpp (revision 640091) +++ vm/port/src/signals/linux/signals_common.cpp (working copy) @@ -15,6 +15,8 @@ * limitations under the License. */ +#include +#include #include #undef __USE_XOPEN #include @@ -39,6 +41,41 @@ } +// Because application can set up some protected area in stack region, +// we need to re-enable access to this area because we need to operate +// with the original stack of the thread +// Application should take care of restoring this protected area after +// signal processing +// FIXME This is workaround only; it also can break crash processing for SIGSEGV +// Ideally all the functionality on guard pages should be in Port. +// Unfortunately, it can involve thread creation in Port, additional +// thread wrapper, and moving general TLS operations to Port, so +// it's postponed +static void clear_stack_protection(Registers* regs, void* fault_addr) +{ + if (!fault_addr) // is not SO + return; + + size_t fault = (size_t)fault_addr; + size_t sp = (size_t)regs->get_sp(); + size_t diff = (fault > sp) ? (fault - sp) : (sp - fault); + size_t page_size = (size_t)sysconf(_SC_PAGE_SIZE); + + if (diff > page_size) + return; // Most probably is not SO + + size_t start = sp & ~(page_size - 1); + size_t size = page_size; + + if (sp - start < 0x400) + { + start -= page_size; + size += page_size; + } + + int res = mprotect((void*)start, size, PROT_READ | PROT_WRITE); +} + static void c_handler(Registers* pregs, size_t signum, void* fault_addr) { // this exception handler is executed *after* VEH handler returned int result; @@ -101,6 +138,10 @@ Registers regs; // Convert OS context to Registers port_thread_context_to_regs(®s, (ucontext_t*)context); + + if (signum == SIGSEGV) + clear_stack_protection(®s, info->si_addr); + // Prepare registers for transfering control out of signal handler void* callback = (void*)&c_handler; port_set_longjump_regs(callback, ®s, 3, Index: vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp =================================================================== --- vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp (revision 640091) +++ vm/vmcore/src/util/linux/ia32_em64t/signals_common.cpp (working copy) @@ -353,10 +353,10 @@ regs->set_ip(new_ip); } - if (!vmthread || env == NULL || - !is_in_java(regs) || interpreter_enabled()) + if (!vmthread || env == NULL) return FALSE; // Crash + // Stack overflow can occur in native code as well as in interpreter if (check_stack_overflow(regs, fault_addr)) { Boolean result = stack_overflow_handler(signum, regs, fault_addr); @@ -367,6 +367,9 @@ return result; } + if (!is_in_java(regs) || interpreter_enabled()) + return FALSE; // Crash + // Pass exception to NCAI exception handler bool is_handled = 0; ncai_process_signal_event((NativeCodePtr)regs->get_ip(),