RFR: 8197429: Increased stack guard causes segfaults on x86-32

David Holmes david.holmes at oracle.com
Mon Feb 12 07:19:41 UTC 2018


Hi Andrew,

On 10/02/2018 2:51 AM, Andrew Haley wrote:
> 32-bit Linux x86 HotSpot allocates an executable memory region just
> below the end of the stack.  This is a workaround for JDK-8023956,
> which in turn relates to a bug in the RHEL 5 & 6 kernels on old
> (pre-NX) CPUs:
> 
>    To summarize: to emulate NX feature on X86_32 code segment is used
>    to limit execution to the highest executable VA. There is a tiny
>    race on SMP MM invalidation code which can cause the lazy CS update
>    code in trap handling to think a general protection fault wasn't
>    cause by itself. This results in sending the JVM a useless SIGSEGV
>    with si_code:SI_KERNEL, results in JVM signal handling forcing a
>    dump.
> 
>    The suggested work around (limited to 32 bit Linux): is to enable
>    execution (PROT_EXEC) on a high address and execute some code.
> 
> To be more precise: on 32-bit Linux kernels the top of the main stack
> is at about 3G (0xC0000000), and HotSpot creates an executable mapping
> of a single page just a little way below the main stack and executes
> an instruction in it.  (It then leaves the region mapped; I do not
> know why.  It could be that the region could be removed at this
> point.)
> 
> Some new Linux kernels by default have a stack guard of a megabyte
> between the main stack and any allocated memory region.  See
> CVE-2017-1000364.  (Note that this megabyte is a default: it can be
> changed at boot time.)
> 
> So, when the stack grows to within a megabyte of the executable region
> HotSpot installed, the process segfaults and is killed.  This only
> happens when we're running on the main stack, and that only happens
> when using the JNI invocation interface.
> 
> 
> I have looked at several ways to fix this.  One was to probe to find
> out what the stack guard size is, and to place the executable mapping
> an appropriate distance from the stack; this can be done, but it is
> complex.  I believe it's also unnecessary, because the workaround for
> JDK-8023956 isn't needed with the newer kernels that have the larger
> stack guard gap.
> 
> The fix I'm proposing here first bangs down the stack to the Java
> stack limit, then tries to map the executable memory region.  On
> systems with a large stack guard gap this mapping attempt will fail,
> and we return and continue.  On older systems which do not have a
> large stack gap it will continue and install the executable memory
> region.

How does this interact with the use of DisablePrimordialThreadGuardPages?

Thanks,
David

> There are other possible fixes.  Rather than failing, we could loop
> trying to install the executable mapping until we succeed.
> 
> http://cr.openjdk.java.net/~aph/8197429-1/
> 


More information about the hotspot-runtime-dev mailing list