comparison src/os/linux/vm/os_linux.cpp @ 8710:9058789475af

7107135: Stack guard pages are no more protected after loading a shared library with executable stack Summary: Detect the execstack attribute of the loaded library and attempt to fix the stack guard using Safepoint op. Reviewed-by: dholmes, zgu Contributed-by: ioi.lam@oracle.com
author iklam
date Tue, 05 Mar 2013 13:55:56 -0800
parents 63e54c37ac64
children 6b803ba47588
comparison
equal deleted inserted replaced
8709:255c0a4cb4eb 8710:9058789475af
42 #include "prims/jvm_misc.hpp" 42 #include "prims/jvm_misc.hpp"
43 #include "runtime/arguments.hpp" 43 #include "runtime/arguments.hpp"
44 #include "runtime/extendedPC.hpp" 44 #include "runtime/extendedPC.hpp"
45 #include "runtime/globals.hpp" 45 #include "runtime/globals.hpp"
46 #include "runtime/interfaceSupport.hpp" 46 #include "runtime/interfaceSupport.hpp"
47 #include "runtime/init.hpp"
47 #include "runtime/java.hpp" 48 #include "runtime/java.hpp"
48 #include "runtime/javaCalls.hpp" 49 #include "runtime/javaCalls.hpp"
49 #include "runtime/mutexLocker.hpp" 50 #include "runtime/mutexLocker.hpp"
50 #include "runtime/objectMonitor.hpp" 51 #include "runtime/objectMonitor.hpp"
51 #include "runtime/osThread.hpp" 52 #include "runtime/osThread.hpp"
59 #include "services/attachListener.hpp" 60 #include "services/attachListener.hpp"
60 #include "services/runtimeService.hpp" 61 #include "services/runtimeService.hpp"
61 #include "utilities/decoder.hpp" 62 #include "utilities/decoder.hpp"
62 #include "utilities/defaultStream.hpp" 63 #include "utilities/defaultStream.hpp"
63 #include "utilities/events.hpp" 64 #include "utilities/events.hpp"
65 #include "utilities/elfFile.hpp"
64 #include "utilities/growableArray.hpp" 66 #include "utilities/growableArray.hpp"
65 #include "utilities/vmError.hpp" 67 #include "utilities/vmError.hpp"
66 68
67 // put OS-includes here 69 // put OS-includes here
68 # include <sys/types.h> 70 # include <sys/types.h>
1794 1796
1795 // Loads .dll/.so and 1797 // Loads .dll/.so and
1796 // in case of error it checks if .dll/.so was built for the 1798 // in case of error it checks if .dll/.so was built for the
1797 // same architecture as Hotspot is running on 1799 // same architecture as Hotspot is running on
1798 1800
1801
1802 // Remember the stack's state. The Linux dynamic linker will change
1803 // the stack to 'executable' at most once, so we must safepoint only once.
1804 bool os::Linux::_stack_is_executable = false;
1805
1806 // VM operation that loads a library. This is necessary if stack protection
1807 // of the Java stacks can be lost during loading the library. If we
1808 // do not stop the Java threads, they can stack overflow before the stacks
1809 // are protected again.
1810 class VM_LinuxDllLoad: public VM_Operation {
1811 private:
1812 const char *_filename;
1813 void *_lib;
1814 public:
1815 VM_LinuxDllLoad(const char *fn) :
1816 _filename(fn), _lib(NULL) {}
1817 VMOp_Type type() const { return VMOp_LinuxDllLoad; }
1818 void doit() {
1819 _lib = os::Linux::dll_load_inner(_filename);
1820 os::Linux::_stack_is_executable = true;
1821 }
1822 void* loaded_library() { return _lib; }
1823 };
1824
1799 void * os::dll_load(const char *filename, char *ebuf, int ebuflen) 1825 void * os::dll_load(const char *filename, char *ebuf, int ebuflen)
1800 { 1826 {
1801 void * result= ::dlopen(filename, RTLD_LAZY); 1827 void * result = NULL;
1828 bool load_attempted = false;
1829
1830 // Check whether the library to load might change execution rights
1831 // of the stack. If they are changed, the protection of the stack
1832 // guard pages will be lost. We need a safepoint to fix this.
1833 //
1834 // See Linux man page execstack(8) for more info.
1835 if (os::uses_stack_guard_pages() && !os::Linux::_stack_is_executable) {
1836 ElfFile ef(filename);
1837 if (!ef.specifies_noexecstack()) {
1838 if (!is_init_completed()) {
1839 os::Linux::_stack_is_executable = true;
1840 // This is OK - No Java threads have been created yet, and hence no
1841 // stack guard pages to fix.
1842 //
1843 // This should happen only when you are building JDK7 using a very
1844 // old version of JDK6 (e.g., with JPRT) and running test_gamma.
1845 //
1846 // Dynamic loader will make all stacks executable after
1847 // this function returns, and will not do that again.
1848 assert(Threads::first() == NULL, "no Java threads should exist yet.");
1849 } else {
1850 warning("You have loaded library %s which might have disabled stack guard. "
1851 "The VM will try to fix the stack guard now.\n"
1852 "It's highly recommended that you fix the library with "
1853 "'execstack -c <libfile>', or link it with '-z noexecstack'.",
1854 filename);
1855
1856 assert(Thread::current()->is_Java_thread(), "must be Java thread");
1857 JavaThread *jt = JavaThread::current();
1858 if (jt->thread_state() != _thread_in_native) {
1859 // This happens when a compiler thread tries to load a hsdis-<arch>.so file
1860 // that requires ExecStack. Cannot enter safe point. Let's give up.
1861 warning("Unable to fix stack guard. Giving up.");
1862 } else {
1863 if (!LoadExecStackDllInVMThread) {
1864 // This is for the case where the DLL has an static
1865 // constructor function that executes JNI code. We cannot
1866 // load such DLLs in the VMThread.
1867 result = ::dlopen(filename, RTLD_LAZY);
1868 }
1869
1870 ThreadInVMfromNative tiv(jt);
1871 debug_only(VMNativeEntryWrapper vew;)
1872
1873 VM_LinuxDllLoad op(filename);
1874 VMThread::execute(&op);
1875 if (LoadExecStackDllInVMThread) {
1876 result = op.loaded_library();
1877 }
1878 load_attempted = true;
1879 }
1880 }
1881 }
1882 }
1883
1884 if (!load_attempted) {
1885 result = ::dlopen(filename, RTLD_LAZY);
1886 }
1887
1802 if (result != NULL) { 1888 if (result != NULL) {
1803 // Successful loading 1889 // Successful loading
1804 return result; 1890 return result;
1805 } 1891 }
1806 1892
1948 arch_array[running_arch_index].name); 2034 arch_array[running_arch_index].name);
1949 } 2035 }
1950 } 2036 }
1951 2037
1952 return NULL; 2038 return NULL;
2039 }
2040
2041 void * os::Linux::dll_load_inner(const char *filename) {
2042 void * result = NULL;
2043 if (LoadExecStackDllInVMThread) {
2044 result = ::dlopen(filename, RTLD_LAZY);
2045 }
2046
2047 // Since 7019808, libjvm.so is linked with -noexecstack. If the VM loads a
2048 // library that requires an executable stack, or which does not have this
2049 // stack attribute set, dlopen changes the stack attribute to executable. The
2050 // read protection of the guard pages gets lost.
2051 //
2052 // Need to check _stack_is_executable again as multiple VM_LinuxDllLoad
2053 // may have been queued at the same time.
2054
2055 if (!_stack_is_executable) {
2056 JavaThread *jt = Threads::first();
2057
2058 while (jt) {
2059 if (!jt->stack_guard_zone_unused() && // Stack not yet fully initialized
2060 jt->stack_yellow_zone_enabled()) { // No pending stack overflow exceptions
2061 if (!os::guard_memory((char *) jt->stack_red_zone_base() - jt->stack_red_zone_size(),
2062 jt->stack_yellow_zone_size() + jt->stack_red_zone_size())) {
2063 warning("Attempt to reguard stack yellow zone failed.");
2064 }
2065 }
2066 jt = jt->next();
2067 }
2068 }
2069
2070 return result;
1953 } 2071 }
1954 2072
1955 /* 2073 /*
1956 * glibc-2.0 libdl is not MT safe. If you are building with any glibc, 2074 * glibc-2.0 libdl is not MT safe. If you are building with any glibc,
1957 * chances are you might want to run the generated bits against glibc-2.0 2075 * chances are you might want to run the generated bits against glibc-2.0