diff --git a/Userland/Libraries/LibELF/DynamicLinker.cpp b/Userland/Libraries/LibELF/DynamicLinker.cpp index a1a61e2e55..44140ef3b5 100644 --- a/Userland/Libraries/LibELF/DynamicLinker.cpp +++ b/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()) { diff --git a/Userland/Libraries/LibELF/DynamicObject.cpp b/Userland/Libraries/LibELF/DynamicObject.cpp index 52b38c24da..94d61d3c99 100644 --- a/Userland/Libraries/LibELF/DynamicObject.cpp +++ b/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 diff --git a/Userland/Libraries/LibELF/DynamicObject.h b/Userland/Libraries/LibELF/DynamicObject.h index d6785f779d..0b64a57486 100644 --- a/Userland/Libraries/LibELF/DynamicObject.h +++ b/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 };