2019-01-30 14:07:13 +00:00
|
|
|
# HG changeset patch
|
|
|
|
# User aph
|
|
|
|
# Date 1530894306 -3600
|
|
|
|
# Fri Jul 06 17:25:06 2018 +0100
|
|
|
|
# Node ID 1485461a0fd1ff977a6acb8f2ed1069aaaf3b07e
|
|
|
|
# Parent d7bcbcfde5057ad066ad2fb55a87d19a5827ddee
|
|
|
|
8197429: Increased stack guard causes segfaults on x86-32
|
|
|
|
Reviewed-by: dholmes
|
|
|
|
|
|
|
|
diff --git openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp openjdk/hotspot/src/os/linux/vm/os_linux.cpp
|
|
|
|
--- openjdk.orig/hotspot/src/os/linux/vm/os_linux.cpp
|
|
|
|
+++ openjdk/hotspot/src/os/linux/vm/os_linux.cpp
|
|
|
|
@@ -724,6 +724,10 @@
|
2018-03-29 13:33:41 +00:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+void os::Linux::expand_stack_to(address bottom) {
|
|
|
|
+ _expand_stack_to(bottom);
|
|
|
|
+}
|
|
|
|
+
|
|
|
|
bool os::Linux::manually_expand_stack(JavaThread * t, address addr) {
|
|
|
|
assert(t!=NULL, "just checking");
|
|
|
|
assert(t->osthread()->expanding_stack(), "expand should be set");
|
2019-01-30 14:07:13 +00:00
|
|
|
diff --git openjdk.orig/hotspot/src/os/linux/vm/os_linux.hpp openjdk/hotspot/src/os/linux/vm/os_linux.hpp
|
|
|
|
--- openjdk.orig/hotspot/src/os/linux/vm/os_linux.hpp
|
|
|
|
+++ openjdk/hotspot/src/os/linux/vm/os_linux.hpp
|
|
|
|
@@ -249,6 +249,8 @@
|
2018-03-29 13:33:41 +00:00
|
|
|
static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime);
|
|
|
|
|
|
|
|
private:
|
|
|
|
+ static void expand_stack_to(address bottom);
|
|
|
|
+
|
|
|
|
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_max_node_func_t)(void);
|
2019-01-30 14:07:13 +00:00
|
|
|
diff --git openjdk.orig/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp openjdk/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
|
|
|
|
--- openjdk.orig/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
|
|
|
|
+++ openjdk/hotspot/src/os_cpu/linux_x86/vm/os_linux_x86.cpp
|
|
|
|
@@ -892,6 +892,27 @@
|
2018-03-29 13:33:41 +00:00
|
|
|
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.
|
|
|
|
+ *
|
|
|
|
+ */
|
2019-01-30 14:07:13 +00:00
|
|
|
+ if (os::is_primordial_thread()) {
|
2018-03-29 13:33:41 +00:00
|
|
|
+ address limit = Linux::initial_thread_stack_bottom();
|
2019-01-30 14:07:13 +00:00
|
|
|
+ if (! DisablePrimordialThreadGuardPages) {
|
|
|
|
+ limit += (StackYellowPages + StackRedPages) * page_size;
|
|
|
|
+ }
|
2018-03-29 13:33:41 +00:00
|
|
|
+ os::Linux::expand_stack_to(limit);
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
/*
|
|
|
|
* Take the highest VA the OS will give us and exec
|
|
|
|
*
|
2019-01-30 14:07:13 +00:00
|
|
|
@@ -910,6 +931,16 @@
|
2018-03-29 13:33:41 +00:00
|
|
|
char* hint = (char*) (Linux::initial_thread_stack_bottom() -
|
|
|
|
((StackYellowPages + StackRedPages + 1) * 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.
|
|
|
|
}
|
2019-01-30 14:07:13 +00:00
|
|
|
diff --git openjdk.orig/hotspot/test/runtime/StackGap/T.java openjdk/hotspot/test/runtime/StackGap/T.java
|
|
|
|
new file mode 100644
|
|
|
|
--- /dev/null
|
|
|
|
+++ openjdk/hotspot/test/runtime/StackGap/T.java
|
|
|
|
@@ -0,0 +1,33 @@
|
|
|
|
+/*
|
|
|
|
+ * 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);
|
|
|
|
+
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+}
|
|
|
|
diff --git openjdk.orig/hotspot/test/runtime/StackGap/exestack-gap.c openjdk/hotspot/test/runtime/StackGap/exestack-gap.c
|
|
|
|
new file mode 100644
|
|
|
|
--- /dev/null
|
|
|
|
+++ openjdk/hotspot/test/runtime/StackGap/exestack-gap.c
|
|
|
|
@@ -0,0 +1,82 @@
|
|
|
|
+/*
|
|
|
|
+ * 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;
|
|
|
|
+}
|
|
|
|
diff --git openjdk.orig/hotspot/test/runtime/StackGap/testme.sh openjdk/hotspot/test/runtime/StackGap/testme.sh
|
|
|
|
new file mode 100644
|
|
|
|
--- /dev/null
|
|
|
|
+++ openjdk/hotspot/test/runtime/StackGap/testme.sh
|
|
|
|
@@ -0,0 +1,73 @@
|
|
|
|
+# 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 $?
|