8197429: Increased stack guard causes segfaults on x86-32

Reviewed-by: dholmes
This commit is contained in:
Andrew Haley 2018-02-16 09:43:26 +00:00
parent 9523d40461
commit f48f7c36d5
7 changed files with 198 additions and 2 deletions

View file

@ -1,5 +1,5 @@
/*
* Copyright (c) 1999, 2017, Oracle and/or its affiliates. All rights reserved.
* Copyright (c) 1999, 2018, Oracle and/or its affiliates. All rights reserved.
* DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
*
* This code is free software; you can redistribute it and/or modify it
@ -834,6 +834,28 @@ void os::verify_stack_alignment() {
void os::workaround_expand_exec_shield_cs_limit() {
#if defined(IA32)
size_t page_size = os::vm_page_size();
/*
* JDK-8197429
*
* Expand the stack mapping to the end of the initial stack before
* attempting to install the codebuf. This is needed because newer
* Linux kernels impose a distance of a megabyte between stack
* memory and other memory regions. If we try to install the
* codebuf before expanding the stack the installation will appear
* to succeed but we'll get a segfault later if we expand the stack
* in Java code.
*
*/
if (os::is_primordial_thread()) {
address limit = Linux::initial_thread_stack_bottom();
if (! DisablePrimordialThreadGuardPages) {
limit += JavaThread::stack_red_zone_size() +
JavaThread::stack_yellow_zone_size();
}
os::Linux::expand_stack_to(limit);
}
/*
* Take the highest VA the OS will give us and exec
*
@ -852,6 +874,16 @@ void os::workaround_expand_exec_shield_cs_limit() {
char* hint = (char*)(Linux::initial_thread_stack_bottom() -
(JavaThread::stack_guard_zone_size() + page_size));
char* codebuf = os::attempt_reserve_memory_at(page_size, hint);
if (codebuf == NULL) {
// JDK-8197429: There may be a stack gap of one megabyte between
// the limit of the stack and the nearest memory region: this is a
// Linux kernel workaround for CVE-2017-1000364. If we failed to
// map our codebuf, try again at an address one megabyte lower.
hint -= 1 * M;
codebuf = os::attempt_reserve_memory_at(page_size, hint);
}
if ((codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true))) {
return; // No matter, we tried, best effort.
}