The issue #1045 exposed a bug in the dynamic linker when processing
some headers like PT_NOTE require accessing data in the PT_LOAD segments.
If PT_NOTE headers come earlier than PT_NOTE we end up with the page fault
as the portions of ELF file have not been mapped yet. 

This patch separates loading of segments - load_segments() - from
processing headers by adding new method - process_headers().

Fixes #1045

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>
---
 core/elf.cc        | 17 ++++++++++++++---
 include/osv/elf.hh |  1 +
 2 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/core/elf.cc b/core/elf.cc
index 39de219f..73834b19 100644
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -452,14 +452,22 @@ extern "C" char _pie_static_tls_start, 
_pie_static_tls_end;
 void object::load_segments()
 {
     elf_debug("Loading segments\n");
+    for (unsigned i = 0; i < _ehdr.e_phnum; ++i) {
+        auto &phdr = _phdrs[i];
+        if (phdr.p_type == PT_LOAD) {
+            load_segment(phdr);
+        }
+    }
+}
+
+void object::process_headers()
+{
+    elf_debug("Processing headers\n");
     for (unsigned i = 0; i < _ehdr.e_phnum; ++i) {
         auto &phdr = _phdrs[i];
         switch (phdr.p_type) {
         case PT_NULL:
             break;
-        case PT_LOAD:
-            load_segment(phdr);
-            break;
         case PT_DYNAMIC:
             _dynamic_table = reinterpret_cast<Elf64_Dyn*>(_base + 
phdr.p_vaddr);
             break;
@@ -495,6 +503,7 @@ void object::load_segments()
             }
             break;
         }
+        case PT_LOAD:
         case PT_PHDR:
         case PT_GNU_STACK:
         case PT_GNU_RELRO:
@@ -1233,6 +1242,7 @@ program::program(void* addr)
     _core->set_base(program_base);
     assert(_core->module_index() == core_module_index);
     _core->load_segments();
+    _core->process_headers();
     set_search_path({"/", "/usr/lib"});
     // Our kernel already supplies the features of a bunch of traditional
     // shared libraries:
@@ -1361,6 +1371,7 @@ program::load_object(std::string name, 
std::vector<std::string> extra_path,
         _modules_rcu.assign(new_modules.release());
         osv::rcu_dispose(old_modules);
         ef->load_segments();
+        ef->process_headers();
         if (!ef->is_non_pie_executable())
            _next_alloc = ef->end();
         add_debugger_obj(ef.get());
diff --git a/include/osv/elf.hh b/include/osv/elf.hh
index 3722da9e..1dac6c08 100644
--- a/include/osv/elf.hh
+++ b/include/osv/elf.hh
@@ -348,6 +348,7 @@ public:
     void* end() const;
     Elf64_Sym* lookup_symbol(const char* name, bool self_lookup);
     void load_segments();
+    void process_headers();
     void unload_segments();
     void fix_permissions();
     void* resolve_pltgot(unsigned index);
-- 
2.20.1

-- 
You received this message because you are subscribed to the Google Groups "OSv 
Development" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to osv-dev+unsubscr...@googlegroups.com.
To view this discussion on the web visit 
https://groups.google.com/d/msgid/osv-dev/20200114125901.16800-1-jwkozaczuk%40gmail.com.

Reply via email to