Mercurial > hg > graal-jvmci-8
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 |