OSDN Git Service

linker: Improve elf-file validation
authorDimitry Ivanov <dimitry@google.com>
Thu, 14 Jul 2016 00:06:36 +0000 (17:06 -0700)
committerDimitry Ivanov <dimitry@google.com>
Thu, 14 Jul 2016 00:06:36 +0000 (17:06 -0700)
1. Make sure that the .dynamic section offset and size matches
   PT_DYNAMIC segment offset and filesz
2. No section offset can be 0

Bug: http://b/16548758
Bug: http://b/29637134
Change-Id: I11bc2567b0cff89f48699ec74015991fee5b137b
Test: Install and start the app from http://b/29637134

linker/linker_phdr.cpp

index 136e432..4eff46d 100644 (file)
@@ -252,7 +252,12 @@ bool ElfReader::CheckFileRange(ElfW(Addr) offset, size_t size) {
   off64_t range_start;
   off64_t range_end;
 
-  return safe_add(&range_start, file_offset_, offset) &&
+  // Only header can be located at the 0 offset... This function called to
+  // check DYNSYM and DYNAMIC sections and phdr/shdr - none of them can be
+  // and 0 offset.
+
+  return offset > 0 &&
+         safe_add(&range_start, file_offset_, offset) &&
          safe_add(&range_end, range_start, size) &&
          range_start < file_size_ &&
          range_end <= file_size_;
@@ -324,6 +329,35 @@ bool ElfReader::ReadDynamicSection() {
     return false;
   }
 
+  // Make sure dynamic_shdr offset and size matches PT_DYNAMIC phdr
+  size_t pt_dynamic_offset = 0;
+  size_t pt_dynamic_filesz = 0;
+  for (size_t i = 0; i < phdr_num_; ++i) {
+    const ElfW(Phdr)* phdr = &phdr_table_[i];
+    if (phdr->p_type == PT_DYNAMIC) {
+      pt_dynamic_offset = phdr->p_offset;
+      pt_dynamic_filesz = phdr->p_filesz;
+    }
+  }
+
+  if (pt_dynamic_offset != dynamic_shdr->sh_offset) {
+    DL_ERR("\"%s\" .dynamic section has invalid offset: 0x%zx, "
+           "expected to match PT_DYNAMIC offset: 0x%zx",
+           name_.c_str(),
+           static_cast<size_t>(dynamic_shdr->sh_offset),
+           pt_dynamic_offset);
+    return false;
+  }
+
+  if (pt_dynamic_filesz != dynamic_shdr->sh_size) {
+    DL_ERR("\"%s\" .dynamic section has invalid size: 0x%zx, "
+           "expected to match PT_DYNAMIC filesz: 0x%zx",
+           name_.c_str(),
+           static_cast<size_t>(dynamic_shdr->sh_size),
+           pt_dynamic_filesz);
+    return false;
+  }
+
   if (dynamic_shdr->sh_link >= shdr_num_) {
     DL_ERR("\"%s\" .dynamic section has invalid sh_link: %d", name_.c_str(), dynamic_shdr->sh_link);
     return false;