Fri, 06 Jul 2018 17:25:06 +0100
8197429: Increased stack guard causes segfaults on x86-32
Reviewed-by: dholmes
1.1 --- a/src/os/linux/vm/os_linux.cpp Mon Dec 03 14:07:45 2018 +0000 1.2 +++ b/src/os/linux/vm/os_linux.cpp Fri Jul 06 17:25:06 2018 +0100 1.3 @@ -724,6 +724,10 @@ 1.4 } 1.5 } 1.6 1.7 +void os::Linux::expand_stack_to(address bottom) { 1.8 + _expand_stack_to(bottom); 1.9 +} 1.10 + 1.11 bool os::Linux::manually_expand_stack(JavaThread * t, address addr) { 1.12 assert(t!=NULL, "just checking"); 1.13 assert(t->osthread()->expanding_stack(), "expand should be set");
2.1 --- a/src/os/linux/vm/os_linux.hpp Mon Dec 03 14:07:45 2018 +0000 2.2 +++ b/src/os/linux/vm/os_linux.hpp Fri Jul 06 17:25:06 2018 +0100 2.3 @@ -249,6 +249,8 @@ 2.4 static int safe_cond_timedwait(pthread_cond_t *_cond, pthread_mutex_t *_mutex, const struct timespec *_abstime); 2.5 2.6 private: 2.7 + static void expand_stack_to(address bottom); 2.8 + 2.9 typedef int (*sched_getcpu_func_t)(void); 2.10 typedef int (*numa_node_to_cpus_func_t)(int node, unsigned long *buffer, int bufferlen); 2.11 typedef int (*numa_max_node_func_t)(void);
3.1 --- a/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Mon Dec 03 14:07:45 2018 +0000 3.2 +++ b/src/os_cpu/linux_x86/vm/os_linux_x86.cpp Fri Jul 06 17:25:06 2018 +0100 3.3 @@ -892,6 +892,27 @@ 3.4 void os::workaround_expand_exec_shield_cs_limit() { 3.5 #if defined(IA32) 3.6 size_t page_size = os::vm_page_size(); 3.7 + 3.8 + /* 3.9 + * JDK-8197429 3.10 + * 3.11 + * Expand the stack mapping to the end of the initial stack before 3.12 + * attempting to install the codebuf. This is needed because newer 3.13 + * Linux kernels impose a distance of a megabyte between stack 3.14 + * memory and other memory regions. If we try to install the 3.15 + * codebuf before expanding the stack the installation will appear 3.16 + * to succeed but we'll get a segfault later if we expand the stack 3.17 + * in Java code. 3.18 + * 3.19 + */ 3.20 + if (os::is_primordial_thread()) { 3.21 + address limit = Linux::initial_thread_stack_bottom(); 3.22 + if (! DisablePrimordialThreadGuardPages) { 3.23 + limit += (StackYellowPages + StackRedPages) * page_size; 3.24 + } 3.25 + os::Linux::expand_stack_to(limit); 3.26 + } 3.27 + 3.28 /* 3.29 * Take the highest VA the OS will give us and exec 3.30 * 3.31 @@ -910,6 +931,16 @@ 3.32 char* hint = (char*) (Linux::initial_thread_stack_bottom() - 3.33 ((StackYellowPages + StackRedPages + 1) * page_size)); 3.34 char* codebuf = os::attempt_reserve_memory_at(page_size, hint); 3.35 + 3.36 + if (codebuf == NULL) { 3.37 + // JDK-8197429: There may be a stack gap of one megabyte between 3.38 + // the limit of the stack and the nearest memory region: this is a 3.39 + // Linux kernel workaround for CVE-2017-1000364. If we failed to 3.40 + // map our codebuf, try again at an address one megabyte lower. 3.41 + hint -= 1 * M; 3.42 + codebuf = os::attempt_reserve_memory_at(page_size, hint); 3.43 + } 3.44 + 3.45 if ( (codebuf == NULL) || (!os::commit_memory(codebuf, page_size, true)) ) { 3.46 return; // No matter, we tried, best effort. 3.47 }
4.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 4.2 +++ b/test/runtime/StackGap/T.java Fri Jul 06 17:25:06 2018 +0100 4.3 @@ -0,0 +1,33 @@ 4.4 +/* 4.5 + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. 4.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4.7 + * 4.8 + * This code is free software; you can redistribute it and/or modify it 4.9 + * under the terms of the GNU General Public License version 2 only, as 4.10 + * published by the Free Software Foundation. 4.11 + * 4.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 4.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 4.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 4.15 + * version 2 for more details (a copy is included in the LICENSE file that 4.16 + * accompanied this code). 4.17 + * 4.18 + * You should have received a copy of the GNU General Public License version 4.19 + * 2 along with this work; if not, write to the Free Software Foundation, 4.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 4.21 + * 4.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 4.23 + * or visit www.oracle.com if you need additional information or have any 4.24 + * questions. 4.25 + */ 4.26 + 4.27 +public class T { 4.28 + 4.29 + public static void test(int n) { 4.30 + if (n == 0) return; 4.31 + System.out.println (n); 4.32 + test (n - 1); 4.33 + 4.34 + } 4.35 + 4.36 +}
5.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 5.2 +++ b/test/runtime/StackGap/exestack-gap.c Fri Jul 06 17:25:06 2018 +0100 5.3 @@ -0,0 +1,82 @@ 5.4 +/* 5.5 + * Copyright (c) 2018, Red Hat, Inc. All rights reserved. 5.6 + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 5.7 + * 5.8 + * This code is free software; you can redistribute it and/or modify it 5.9 + * under the terms of the GNU General Public License version 2 only, as 5.10 + * published by the Free Software Foundation. 5.11 + * 5.12 + * This code is distributed in the hope that it will be useful, but WITHOUT 5.13 + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 5.14 + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 5.15 + * version 2 for more details (a copy is included in the LICENSE file that 5.16 + * accompanied this code). 5.17 + * 5.18 + * You should have received a copy of the GNU General Public License version 5.19 + * 2 along with this work; if not, write to the Free Software Foundation, 5.20 + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 5.21 + * 5.22 + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 5.23 + * or visit www.oracle.com if you need additional information or have any 5.24 + * questions. 5.25 + */ 5.26 + 5.27 +#include <jni.h> 5.28 +#include <stdio.h> 5.29 +#include <stdlib.h> 5.30 + 5.31 +JNIEnv* create_vm(JavaVM **jvm, char *extra_option) 5.32 +{ 5.33 + JNIEnv* env; 5.34 + JavaVMInitArgs args; 5.35 + JavaVMOption options[4]; 5.36 + args.version = JNI_VERSION_1_8; 5.37 + args.nOptions = 3 + (extra_option != NULL); 5.38 + options[0].optionString = "-Xss2048k"; 5.39 + char classpath[4096]; 5.40 + snprintf(classpath, sizeof classpath, 5.41 + "-Djava.class.path=%s", getenv("CLASSPATH")); 5.42 + options[1].optionString = classpath; 5.43 + options[2].optionString = "-XX:+UnlockExperimentalVMOptions"; 5.44 + if (extra_option) { 5.45 + options[3].optionString = extra_option; 5.46 + } 5.47 + args.options = &options[0]; 5.48 + args.ignoreUnrecognized = 0; 5.49 + int rv; 5.50 + rv = JNI_CreateJavaVM(jvm, (void**)&env, &args); 5.51 + if (rv < 0) return NULL; 5.52 + return env; 5.53 +} 5.54 + 5.55 +void run(char *extra_arg) { 5.56 + JavaVM *jvm; 5.57 + jclass T_class; 5.58 + jmethodID test_method; 5.59 + JNIEnv *env = create_vm(&jvm, extra_arg); 5.60 + if (env == NULL) 5.61 + exit(1); 5.62 + T_class = (*env)->FindClass(env, "T"); 5.63 + if ((*env)->ExceptionCheck(env) == JNI_TRUE) { 5.64 + (*env)->ExceptionDescribe(env); 5.65 + exit(1); 5.66 + } 5.67 + test_method = (*env)->GetStaticMethodID(env, T_class, "test", "(I)V"); 5.68 + if ((*env)->ExceptionCheck(env) == JNI_TRUE) { 5.69 + (*env)->ExceptionDescribe(env); 5.70 + exit(1); 5.71 + } 5.72 + (*env)->CallStaticVoidMethod(env, T_class, test_method, 1000); 5.73 +} 5.74 + 5.75 + 5.76 +int main(int argc, char **argv) 5.77 +{ 5.78 + if (argc > 1) { 5.79 + run(argv[1]); 5.80 + } else { 5.81 + run(NULL); 5.82 + } 5.83 + 5.84 + return 0; 5.85 +}
6.1 --- /dev/null Thu Jan 01 00:00:00 1970 +0000 6.2 +++ b/test/runtime/StackGap/testme.sh Fri Jul 06 17:25:06 2018 +0100 6.3 @@ -0,0 +1,73 @@ 6.4 +# Copyright (c) 2014, 2018, Oracle and/or its affiliates. All rights reserved. 6.5 +# DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 6.6 +# 6.7 +# This code is free software; you can redistribute it and/or modify it 6.8 +# under the terms of the GNU General Public License version 2 only, as 6.9 +# published by the Free Software Foundation. 6.10 +# 6.11 +# This code is distributed in the hope that it will be useful, but WITHOUT 6.12 +# ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 6.13 +# FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 6.14 +# version 2 for more details (a copy is included in the LICENSE file that 6.15 +# accompanied this code). 6.16 +# 6.17 +# You should have received a copy of the GNU General Public License version 6.18 +# 2 along with this work; if not, write to the Free Software Foundation, 6.19 +# Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 6.20 +# 6.21 +# Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 6.22 +# or visit www.oracle.com if you need additional information or have any 6.23 +# questions. 6.24 +#!/bin/sh 6.25 + 6.26 +# 6.27 +# @test testme.sh 6.28 +# @bug 8197429 6.29 +# @summary Linux kernel stack guard should not cause segfaults on x86-32 6.30 +# @compile T.java 6.31 +# @run shell testme.sh 6.32 +# 6.33 + 6.34 +if [ "${TESTSRC}" = "" ] 6.35 +then 6.36 + TESTSRC=${PWD} 6.37 + echo "TESTSRC not set. Using "${TESTSRC}" as default" 6.38 +fi 6.39 +echo "TESTSRC=${TESTSRC}" 6.40 +## Adding common setup Variables for running shell tests. 6.41 +. ${TESTSRC}/../../test_env.sh 6.42 + 6.43 +if [ "${VM_OS}" != "linux" ] 6.44 +then 6.45 + echo "Test only valid for Linux" 6.46 + exit 0 6.47 +fi 6.48 + 6.49 +gcc_cmd=`which gcc` 6.50 +if [ "x$gcc_cmd" = "x" ]; then 6.51 + echo "WARNING: gcc not found. Cannot execute test." 2>&1 6.52 + exit 0; 6.53 +fi 6.54 + 6.55 +CFLAGS="-m${VM_BITS}" 6.56 + 6.57 +LD_LIBRARY_PATH=.:${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE}:/usr/lib:$LD_LIBRARY_PATH 6.58 +export LD_LIBRARY_PATH 6.59 + 6.60 +cp ${TESTSRC}${FS}exestack-gap.c . 6.61 + 6.62 +# Copy the result of our @compile action: 6.63 +cp ${TESTCLASSES}${FS}T.class . 6.64 + 6.65 +echo "Compilation flag: ${COMP_FLAG}" 6.66 +# Note pthread may not be found thus invoke creation will fail to be created. 6.67 +# Check to ensure you have a /usr/lib/libpthread.so if you don't please look 6.68 +# for /usr/lib/`uname -m`-linux-gnu version ensure to add that path to below compilation. 6.69 + 6.70 +$gcc_cmd -DLINUX ${CFLAGS} -o stack-gap \ 6.71 + -I${COMPILEJAVA}/include -I${COMPILEJAVA}/include/linux \ 6.72 + -L${COMPILEJAVA}/jre/lib/${VM_CPU}/${VM_TYPE} \ 6.73 + -ljvm -lpthread exestack-gap.c 6.74 + 6.75 +./stack-gap || exit $? 6.76 +./stack-gap -XX:+DisablePrimordialThreadGuardPages || exit $?