8183262: noexecstack check in os::dll_load on Linux is too expensive
authorkvn
Wed, 05 Jul 2017 11:03:19 -0700
changeset 46629 8eeacdc76bf2
parent 46628 d19bf13a5655
child 46630 75aa3e39d02c
child 46632 cef226af6c02
8183262: noexecstack check in os::dll_load on Linux is too expensive Summary: convert ElfFile::specifies_noexecstack() to static method which read file header and check executable stack flag. Reviewed-by: iklam, stuefe
hotspot/src/os/linux/vm/os_linux.cpp
hotspot/src/share/vm/aot/aotLoader.cpp
hotspot/src/share/vm/utilities/elfFile.cpp
hotspot/src/share/vm/utilities/elfFile.hpp
--- a/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/os/linux/vm/os_linux.cpp	Wed Jul 05 11:03:19 2017 -0700
@@ -1639,8 +1639,7 @@
   //
   // See Linux man page execstack(8) for more info.
   if (os::uses_stack_guard_pages() && !os::Linux::_stack_is_executable) {
-    ElfFile ef(filename);
-    if (!ef.specifies_noexecstack()) {
+    if (!ElfFile::specifies_noexecstack(filename)) {
       if (!is_init_completed()) {
         os::Linux::_stack_is_executable = true;
         // This is OK - No Java threads have been created yet, and hence no
--- a/hotspot/src/share/vm/aot/aotLoader.cpp	Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/aot/aotLoader.cpp	Wed Jul 05 11:03:19 2017 -0700
@@ -29,6 +29,7 @@
 #include "oops/method.hpp"
 #include "prims/jvm.h"
 #include "runtime/os.hpp"
+#include "runtime/timerTrace.hpp"
 
 GrowableArray<AOTCodeHeap*>* AOTLoader::_heaps = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTCodeHeap*> (2, true);
 GrowableArray<AOTLib*>* AOTLoader::_libraries = new(ResourceObj::C_HEAP, mtCode) GrowableArray<AOTLib*> (2, true);
@@ -112,6 +113,8 @@
 };
 
 void AOTLoader::initialize() {
+  TraceTime timer("AOT initialization", TRACETIME_LOG(Info, aot, startuptime));
+
   if (FLAG_IS_DEFAULT(UseAOT) && AOTLibrary != NULL) {
     // Don't need to set UseAOT on command line when AOTLibrary is specified
     FLAG_SET_DEFAULT(UseAOT, true);
--- a/hotspot/src/share/vm/utilities/elfFile.cpp	Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/utilities/elfFile.cpp	Wed Jul 05 11:03:19 2017 -0700
@@ -242,32 +242,45 @@
 }
 
 #ifdef LINUX
-bool ElfFile::specifies_noexecstack() {
-  Elf_Phdr phdr;
-  if (!m_file)  return true;
+bool ElfFile::specifies_noexecstack(const char* filepath) {
+  // Returns true if the elf file is marked NOT to require an executable stack,
+  // or if the file could not be opened.
+  // Returns false if the elf file requires an executable stack, the stack flag
+  // is not set at all, or if the file can not be read.
+  if (filepath == NULL) return true;
+
+  FILE* file = fopen(filepath, "r");
+  if (file == NULL)  return true;
 
-  if (!fseek(m_file, m_elfHdr.e_phoff, SEEK_SET)) {
-    for (int index = 0; index < m_elfHdr.e_phnum; index ++) {
-      if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, m_file) != 1) {
-        m_status = NullDecoder::file_invalid;
-        return false;
+  // AARCH64 defaults to noexecstack. All others default to execstack.
+#ifdef AARCH64
+  bool result = true;
+#else
+  bool result = false;
+#endif
+
+  // Read file header
+  Elf_Ehdr head;
+  if (fread(&head, sizeof(Elf_Ehdr), 1, file) == 1 &&
+      is_elf_file(head) &&
+      fseek(file, head.e_phoff, SEEK_SET) == 0) {
+
+    // Read program header table
+    Elf_Phdr phdr;
+    for (int index = 0; index < head.e_phnum; index ++) {
+      if (fread((void*)&phdr, sizeof(Elf_Phdr), 1, file) != 1) {
+        result = false;
+        break;
       }
       if (phdr.p_type == PT_GNU_STACK) {
-        if (phdr.p_flags == (PF_R | PF_W))  {
-          return true;
-        } else {
-          return false;
-        }
+        result = (phdr.p_flags == (PF_R | PF_W));
+        break;
       }
     }
   }
-// AARCH64 defaults to noexecstack. All others default to execstack.
-#ifdef AARCH64
-  return true;
-#else
-  return false;
-#endif
+  fclose(file);
+  return result;
 }
-#endif
+#endif // LINUX
 
 #endif // !_WINDOWS && !__APPLE__
--- a/hotspot/src/share/vm/utilities/elfFile.hpp	Wed Jul 05 17:19:37 2017 +0200
+++ b/hotspot/src/share/vm/utilities/elfFile.hpp	Wed Jul 05 11:03:19 2017 -0700
@@ -108,7 +108,7 @@
 
  private:
   // sanity check, if the file is a real elf file
-  bool is_elf_file(Elf_Ehdr&);
+  static bool is_elf_file(Elf_Ehdr&);
 
   // load string tables from the elf file
   bool load_tables();
@@ -132,7 +132,7 @@
   // Returns false if the elf file requires an executable stack, the stack flag
   // is not set at all, or if the file can not be read.
   // On systems other than linux it always returns false.
-  bool specifies_noexecstack() NOT_LINUX({ return false; });
+  static bool specifies_noexecstack(const char* filepath) NOT_LINUX({ return false; });
 
  protected:
     ElfFile*         m_next;