8197429: Increased stack guard causes segfaults on x86-32

Fri, 06 Jul 2018 17:25:06 +0100

author
aph
date
Fri, 06 Jul 2018 17:25:06 +0100
changeset 9599
1485461a0fd1
parent 9598
d7bcbcfde505
child 9600
a253fe293726

8197429: Increased stack guard causes segfaults on x86-32
Reviewed-by: dholmes

src/os/linux/vm/os_linux.cpp file | annotate | diff | comparison | revisions
src/os/linux/vm/os_linux.hpp file | annotate | diff | comparison | revisions
src/os_cpu/linux_x86/vm/os_linux_x86.cpp file | annotate | diff | comparison | revisions
test/runtime/StackGap/T.java file | annotate | diff | comparison | revisions
test/runtime/StackGap/exestack-gap.c file | annotate | diff | comparison | revisions
test/runtime/StackGap/testme.sh file | annotate | diff | comparison | revisions
     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 $?

mercurial