Wed, 25 Sep 2013 13:58:13 +0200
8023956: Provide a work-around to broken Linux 32 bit "Exec Shield" using CS for NX emulation (crashing with SI_KERNEL)
Summary: Execute some code at a high virtual address value, and keep mapped
Reviewed-by: coleenp, zgu
1.1 --- a/src/os/linux/vm/os_linux.cpp Mon Sep 23 08:56:19 2013 -0700 1.2 +++ b/src/os/linux/vm/os_linux.cpp Wed Sep 25 13:58:13 2013 +0200 1.3 @@ -4839,6 +4839,10 @@ 1.4 1.5 Linux::capture_initial_stack(JavaThread::stack_size_at_create()); 1.6 1.7 +#if defined(IA32) 1.8 + workaround_expand_exec_shield_cs_limit(); 1.9 +#endif 1.10 + 1.11 Linux::libpthread_init(); 1.12 if (PrintMiscellaneous && (Verbose || WizardMode)) { 1.13 tty->print_cr("[HotSpot is running with %s, %s(%s)]\n",
2.1 --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Sep 23 08:56:19 2013 -0700 2.2 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Wed Sep 25 13:58:13 2013 +0200 2.3 @@ -876,3 +876,46 @@ 2.4 #endif 2.5 } 2.6 #endif 2.7 + 2.8 + 2.9 +/* 2.10 + * IA32 only: execute code at a high address in case buggy NX emulation is present. I.e. avoid CS limit 2.11 + * updates (JDK-8023956). 2.12 + */ 2.13 +void os::workaround_expand_exec_shield_cs_limit() { 2.14 +#if defined(IA32) 2.15 + size_t page_size = os::vm_page_size(); 2.16 + /* 2.17 + * Take the highest VA the OS will give us and exec 2.18 + * 2.19 + * Although using -(pagesz) as mmap hint works on newer kernel as you would 2.20 + * think, older variants affected by this work-around don't (search forward only). 2.21 + * 2.22 + * On the affected distributions, we understand the memory layout to be: 2.23 + * 2.24 + * TASK_LIMIT= 3G, main stack base close to TASK_LIMT. 2.25 + * 2.26 + * A few pages south main stack will do it. 2.27 + * 2.28 + * If we are embedded in an app other than launcher (initial != main stack), 2.29 + * we don't have much control or understanding of the address space, just let it slide. 2.30 + */ 2.31 + char* hint = (char*) (Linux::initial_thread_stack_bottom() - 2.32 + ((StackYellowPages + StackRedPages + 1) * page_size)); 2.33 + char* codebuf = os::reserve_memory(page_size, hint); 2.34 + if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) { 2.35 + return; // No matter, we tried, best effort. 2.36 + } 2.37 + if (PrintMiscellaneous && (Verbose || WizardMode)) { 2.38 + tty->print_cr("[CS limit NX emulation work-around, exec code at: %p]", codebuf); 2.39 + } 2.40 + 2.41 + // Some code to exec: the 'ret' instruction 2.42 + codebuf[0] = 0xC3; 2.43 + 2.44 + // Call the code in the codebuf 2.45 + __asm__ volatile("call *%0" : : "r"(codebuf)); 2.46 + 2.47 + // keep the page mapped so CS limit isn't reduced. 2.48 +#endif 2.49 +}
3.1 --- a/src/os_cpu/linux_x86/vm/os_linux_x86.hpp Mon Sep 23 08:56:19 2013 -0700 3.2 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.hpp Wed Sep 25 13:58:13 2013 +0200 3.3 @@ -36,4 +36,17 @@ 3.4 // Note: Currently only used in 64 bit Windows implementations 3.5 static bool register_code_area(char *low, char *high) { return true; } 3.6 3.7 + /* 3.8 + * Work-around for broken NX emulation using CS limit, Red Hat patch "Exec-Shield" 3.9 + * (IA32 only). 3.10 + * 3.11 + * Map and execute at a high VA to prevent CS lazy updates race with SMP MM 3.12 + * invalidation.Further code generation by the JVM will no longer cause CS limit 3.13 + * updates. 3.14 + * 3.15 + * Affects IA32: RHEL 5 & 6, Ubuntu 10.04 (LTS), 10.10, 11.04, 11.10, 12.04. 3.16 + * @see JDK-8023956 3.17 + */ 3.18 + static void workaround_expand_exec_shield_cs_limit(); 3.19 + 3.20 #endif // OS_CPU_LINUX_X86_VM_OS_LINUX_X86_HPP