提交 f6a2b1ca 编写于 作者: A aph

8197429: Increased stack guard causes segfaults on x86-32

Reviewed-by: dholmes
上级 ff6477c2
...@@ -724,6 +724,10 @@ static void _expand_stack_to(address bottom) { ...@@ -724,6 +724,10 @@ static void _expand_stack_to(address bottom) {
} }
} }
void os::Linux::expand_stack_to(address bottom) {
_expand_stack_to(bottom);
}
bool os::Linux::manually_expand_stack(JavaThread * t, address addr) { bool os::Linux::manually_expand_stack(JavaThread * t, address addr) {
assert(t!=NULL, "just checking"); assert(t!=NULL, "just checking");
assert(t->osthread()->expanding_stack(), "expand should be set"); assert(t->osthread()->expanding_stack(), "expand should be set");
......
...@@ -249,6 +249,8 @@ class Linux { ...@@ -249,6 +249,8 @@ class Linux {
static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
private: private:
static void expand_stack_to(address bottom);
typedef int (*sched_getcpu_func_t)(void); typedef int (*sched_getcpu_func_t)(void);
typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen);
typedef int (*numa_max_node_func_t)(void); typedef int (*numa_max_node_func_t)(void);
......
...@@ -892,6 +892,27 @@ void os::verify_stack_alignment() { ...@@ -892,6 +892,27 @@ void os::verify_stack_alignment() {
void os::workaround_expand_exec_shield_cs_limit() { void os::workaround_expand_exec_shield_cs_limit() {
#if defined(IA32) #if defined(IA32)
size_t page_size = os::vm_page_size(); 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 += (StackYellowPages + StackRedPages) * page_size;
}
os::Linux::expand_stack_to(limit);
}
/* /*
* Take the highest VA the OS will give us and exec * Take the highest VA the OS will give us and exec
* *
...@@ -910,6 +931,16 @@ void os::workaround_expand_exec_shield_cs_limit() { ...@@ -910,6 +931,16 @@ void os::workaround_expand_exec_shield_cs_limit() {
char* hint = (char*) (Linux::initial_thread_stack_bottom() - char* hint = (char*) (Linux::initial_thread_stack_bottom() -
((StackYellowPages + StackRedPages + 1) * page_size)); ((StackYellowPages + StackRedPages + 1) * page_size));
char* codebuf = os::attempt_reserve_memory_at(page_size, hint); 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)) ) { if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) {
return; // No matter, we tried, best effort. return; // No matter, we tried, best effort.
} }
......
/*
* Copyright (c) 2018, Red Hat, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
public class T {
public static void test(int n) {
if (n == 0) return;
System.out.println (n);
test (n - 1);
}
}
/*
* Copyright (c) 2018, Red Hat, Inc. 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
* under the terms of the GNU General Public License version 2 only, as
* published by the Free Software Foundation.
*
* This code is distributed in the hope that it will be useful, but WITHOUT
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
* version 2 for more details (a copy is included in the LICENSE file that
* accompanied this code).
*
* You should have received a copy of the GNU General Public License version
* 2 along with this work; if not, write to the Free Software Foundation,
* Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
*
* Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
* or visit www.oracle.com if you need additional information or have any
* questions.
*/
#include <jni.h>
#include <stdio.h>
#include <stdlib.h>
JNIEnv* create_vm(JavaVM **jvm, char *extra_option)
{
JNIEnv* env;
JavaVMInitArgs args;
JavaVMOption options[4];
args.version = JNI_VERSION_1_8;
args.nOptions = 3 + (extra_option != NULL);
options[0].optionString = "-Xss2048k";
char classpath[4096];
snprintf(classpath, sizeof classpath,
"-Djava.class.path=%s", getenv("CLASSPATH"));
options[1].optionString = classpath;
options[2].optionString = "-XX:+UnlockExperimentalVMOptions";
if (extra_option) {
options[3].optionString = extra_option;
}
args.options = &options[0];
args.ignoreUnrecognized = 0;
int rv;
rv = JNI_CreateJavaVM(jvm, (void**)&env, &args);
if (rv < 0) return NULL;
return env;
}
void run(char *extra_arg) {
JavaVM *jvm;
jclass T_class;
jmethodID test_method;
JNIEnv *env = create_vm(&jvm, extra_arg);
if (env == NULL)
exit(1);
T_class = (*env)->FindClass(env, "T");
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
(*env)->ExceptionDescribe(env);
exit(1);
}
test_method = (*env)->GetStaticMethodID(env, T_class, "test", "(I)V");
if ((*env)->ExceptionCheck(env) == JNI_TRUE) {
(*env)->ExceptionDescribe(env);
exit(1);
}
(*env)->CallStaticVoidMethod(env, T_class, test_method, 1000);
}
int main(int argc, char **argv)
{
if (argc > 1) {
run(argv[1]);
} else {
run(NULL);
}
return 0;
}
# Copyright (c) 2014, 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
# under the terms of the GNU General Public License version 2 only, as
# published by the Free Software Foundation.
#
# This code is distributed in the hope that it will be useful, but WITHOUT
# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
# version 2 for more details (a copy is included in the LICENSE file that
# accompanied this code).
#
# You should have received a copy of the GNU General Public License version
# 2 along with this work; if not, write to the Free Software Foundation,
# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
#
# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
# or visit www.oracle.com if you need additional information or have any
# questions.
#!/bin/sh
#
# @test testme.sh
# @bug 8197429
# @summary Linux kernel stack guard should not cause segfaults on x86-32
# @compile T.java
# @run shell testme.sh
#
if [ "${TESTSRC}" = "" ]
then
TESTSRC=${PWD}
echo "TESTSRC not set. Using "${TESTSRC}" as default"
fi
echo "TESTSRC=${TESTSRC}"
## Adding common setup Variables for running shell tests.
. ${TESTSRC}/../../test_env.sh
if [ "${VM_OS}" != "linux" ]
then
echo "Test only valid for Linux"
exit 0
fi
gcc_cmd=`which gcc`
if [ "x$gcc_cmd" = "x" ]; then
echo "WARNING: gcc not found. Cannot execute test." 2>&1
exit 0;
fi
CFLAGS="-m${VM_BITS}"
LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH
export LD_LIBRARY_PATH
cp ${TESTSRC}${FS}exestack-gap.c .
# Copy the result of our @compile action:
cp ${TESTCLASSES}${FS}T.class .
echo "Compilation flag: ${COMP_FLAG}"
# Note pthread may not be found thus invoke creation will fail to be created.
# Check to ensure you have a /usr/lib/libpthread.so if you don't please look
# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation.
$gcc_cmd -DLINUX ${CFLAGS} -o stack-gap \
-I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \
-L${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \
-ljvm -lpthread exestack-gap.c
./stack-gap || exit $?
./stack-gap -XX:+DisablePrimordialThreadGuardPages || exit $?
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册