From: Waldemar Kozaczuk <jwkozac...@gmail.com>
Committer: Waldemar Kozaczuk <jwkozac...@gmail.com>
Branch: master

dynamic linker: fix the old bug in the logic to calculate the ELF base

In order to properly calculate and then map an elf object
in virtual memory, the set_base() method needs to identify the lowest
and the highest PT_LOAD header in terms of the p_vaddr value.

Unfortunately, there seems to be a bug in how it is implemented now
and in some cases, when for example there are multiple PT_LOAD and non-PT_LOAD
headers sharing the same p_vaddr value, it ends up using wrong
header and then overwriting other segments data.

This patch fixes it by separating filtering of PT_LOAD headers
and indentifying the lowest and highest ones.

Signed-off-by: Waldemar Kozaczuk <jwkozac...@gmail.com>

---
diff --git a/core/elf.cc b/core/elf.cc
--- a/core/elf.cc
+++ b/core/elf.cc
@@ -347,14 +347,19 @@ static bool intersects_with_kernel(Elf64_Addr elf_addr)
 
 void object::set_base(void* base)
 {
-    auto p = std::min_element(_phdrs.begin(), _phdrs.end(),
-                              [](Elf64_Phdr a, Elf64_Phdr b)
-                                  { return a.p_type == PT_LOAD
-                                        && a.p_vaddr < b.p_vaddr; });
-    auto q = std::min_element(_phdrs.begin(), _phdrs.end(),
-                              [](Elf64_Phdr a, Elf64_Phdr b)
-                                  { return a.p_type == PT_LOAD
-                                        && a.p_vaddr > b.p_vaddr; });
+    std::vector<const Elf64_Phdr*> pt_load_headers;
+    for (auto& p : _phdrs) {
+        if (p.p_type == PT_LOAD) {
+            pt_load_headers.push_back(&p);
+        }
+    }
+
+    auto p = *std::min_element(pt_load_headers.begin(), pt_load_headers.end(),
+                              [](const Elf64_Phdr* a, const Elf64_Phdr* b)
+                                  { return a->p_vaddr < b->p_vaddr; });
+    auto q = *std::max_element(pt_load_headers.begin(), pt_load_headers.end(),
+                              [](const Elf64_Phdr* a, const Elf64_Phdr* b)
+                                  { return a->p_vaddr < b->p_vaddr; });
 
     if (!is_core() && is_non_pie_executable()) {
         // Verify non-PIE executable does not collide with the kernel

-- 
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/00000000000090464405aa5a0c40%40google.com.

Reply via email to