소스 검색

LibELF: Disallow the DynamicLinker from linking a static-pie ELF object

The dynamic loader can't reasonably run static-pie ELF. static-pie ELFs
might run executable code that invokes syscalls outside of the defined
syscall memory executable (code) region security measure we implement.

Known examples of static-pie ELF objects are ELF packers, and the actual
system-provided dynamic loader itself.
Liav A 1 년 전
부모
커밋
69b97fe318
3개의 변경된 파일30개의 추가작업 그리고 1개의 파일을 삭제
  1. 25 1
      Userland/Libraries/LibELF/DynamicLinker.cpp
  2. 1 0
      Userland/Libraries/LibELF/DynamicObject.cpp
  3. 4 0
      Userland/Libraries/LibELF/DynamicObject.h

+ 25 - 1
Userland/Libraries/LibELF/DynamicLinker.cpp

@@ -680,7 +680,31 @@ void ELF::DynamicLinker::linker_main(DeprecatedString&& main_program_path, int m
         fflush(stderr);
         _exit(1);
     }
-    (void)result1.release_value();
+
+    auto loader = result1.release_value();
+    size_t needed_dependencies = 0;
+    loader->for_each_needed_library([&needed_dependencies](auto) {
+        needed_dependencies++;
+    });
+    bool has_interpreter = false;
+    loader->image().for_each_program_header([&has_interpreter](const ELF::Image::ProgramHeader& program_header) {
+        if (program_header.type() == PT_INTERP)
+            has_interpreter = true;
+    });
+    // NOTE: Refuse to run a program if it has a dynamic section,
+    // it is pie, and does not have an interpreter or needed libraries
+    // which is also called "static-pie". These binaries are probably
+    // some sort of ELF packers or dynamic loaders, and there's no added
+    // value in trying to run them, as they will probably crash due to trying
+    // to invoke syscalls from a non-syscall memory executable (code) region.
+    if (loader->is_dynamic() && (!has_interpreter || needed_dependencies == 0) && loader->dynamic_object().is_pie()) {
+        char const message[] = R"(error: the dynamic loader can't reasonably run static-pie ELF. static-pie ELFs might run executable code that invokes syscalls
+outside of the defined syscall memory executable (code) region security measure we implement.
+Examples of static-pie ELF objects are ELF packers, and the system dynamic loader itself.)";
+        fprintf(stderr, "%s", message);
+        fflush(stderr);
+        _exit(1);
+    }
 
     auto result2 = map_dependencies(main_program_path);
     if (result2.is_error()) {

+ 1 - 0
Userland/Libraries/LibELF/DynamicObject.cpp

@@ -183,6 +183,7 @@ void DynamicObject::parse()
         case DT_DEBUG:
             break;
         case DT_FLAGS_1:
+            m_is_pie = true;
             break;
         case DT_NEEDED:
             // We handle these in for_each_needed_library

+ 4 - 0
Userland/Libraries/LibELF/DynamicObject.h

@@ -254,6 +254,8 @@ public:
     InitializationFunction init_section_function() const;
     Section init_array_section() const;
 
+    bool is_pie() const { return m_is_pie; }
+
     bool has_fini_section() const { return m_fini_offset != 0; }
     bool has_fini_array_section() const { return m_fini_array_offset != 0; }
     Section fini_section() const;
@@ -378,6 +380,8 @@ private:
     FlatPtr m_relr_relocation_table_offset { 0 };
     bool m_is_elf_dynamic { false };
 
+    bool m_is_pie { false };
+
     // DT_FLAGS
     ElfW(Word) m_dt_flags { 0 };