1
Fork 0
mirror of https://github.com/RGBCube/serenity synced 2025-05-31 15:48:12 +00:00

LibELF: Ensure that DynamicLoader only receives absolute paths

While at it, start renaming variables where we know that they store a
path, so that we will get less confused in the future.
This commit is contained in:
Tim Schumacher 2022-10-28 16:30:27 +02:00 committed by Linus Groh
parent a1de15498d
commit 177a5baf60
5 changed files with 23 additions and 16 deletions

View file

@ -83,21 +83,21 @@ void _entry(int argc, char** argv, char** envp)
init_libc(); init_libc();
int main_program_fd = -1; int main_program_fd = -1;
String main_program_name; String main_program_path;
bool is_secure = false; bool is_secure = false;
for (; auxvp->a_type != AT_NULL; ++auxvp) { for (; auxvp->a_type != AT_NULL; ++auxvp) {
if (auxvp->a_type == ELF::AuxiliaryValue::ExecFileDescriptor) { if (auxvp->a_type == ELF::AuxiliaryValue::ExecFileDescriptor) {
main_program_fd = auxvp->a_un.a_val; main_program_fd = auxvp->a_un.a_val;
} }
if (auxvp->a_type == ELF::AuxiliaryValue::ExecFilename) { if (auxvp->a_type == ELF::AuxiliaryValue::ExecFilename) {
main_program_name = (char const*)auxvp->a_un.a_ptr; main_program_path = (char const*)auxvp->a_un.a_ptr;
} }
if (auxvp->a_type == ELF::AuxiliaryValue::Secure) { if (auxvp->a_type == ELF::AuxiliaryValue::Secure) {
is_secure = auxvp->a_un.a_val == 1; is_secure = auxvp->a_un.a_val == 1;
} }
} }
if (main_program_name == "/usr/lib/Loader.so"sv) { if (main_program_path == "/usr/lib/Loader.so"sv) {
// We've been invoked directly as an executable rather than as the // We've been invoked directly as an executable rather than as the
// ELF interpreter for some other binary. In the future we may want // ELF interpreter for some other binary. In the future we may want
// to support launching a program directly from the dynamic loader // to support launching a program directly from the dynamic loader
@ -107,9 +107,9 @@ void _entry(int argc, char** argv, char** envp)
} }
VERIFY(main_program_fd >= 0); VERIFY(main_program_fd >= 0);
VERIFY(!main_program_name.is_empty()); VERIFY(!main_program_path.is_empty());
ELF::DynamicLinker::linker_main(move(main_program_name), main_program_fd, is_secure, argc, argv, envp); ELF::DynamicLinker::linker_main(move(main_program_path), main_program_fd, is_secure, argc, argv, envp);
VERIFY_NOT_REACHED(); VERIFY_NOT_REACHED();
} }
} }

View file

@ -35,7 +35,7 @@
namespace ELF { namespace ELF {
static HashMap<String, NonnullRefPtr<ELF::DynamicLoader>> s_loaders; static HashMap<String, NonnullRefPtr<ELF::DynamicLoader>> s_loaders;
static String s_main_program_name; static String s_main_program_path;
static OrderedHashMap<String, NonnullRefPtr<ELF::DynamicObject>> s_global_objects; static OrderedHashMap<String, NonnullRefPtr<ELF::DynamicObject>> s_global_objects;
using EntryPointFunction = int (*)(int, char**, char**); using EntryPointFunction = int (*)(int, char**, char**);
@ -459,7 +459,7 @@ static Result<void*, DlErrorMessage> __dlopen(char const* filename, int flags)
dbgln_if(DYNAMIC_LOAD_DEBUG, "__dlopen invoked, filename={}, flags={}", filename, flags); dbgln_if(DYNAMIC_LOAD_DEBUG, "__dlopen invoked, filename={}, flags={}", filename, flags);
auto library_name = get_library_name(filename ? filename : s_main_program_name); auto library_name = get_library_name(filename ? filename : s_main_program_path);
if (pthread_mutex_trylock(&s_loader_lock) != 0) if (pthread_mutex_trylock(&s_loader_lock) != 0)
return DlErrorMessage { "Nested calls to dlopen() are not permitted." }; return DlErrorMessage { "Nested calls to dlopen() are not permitted." };
@ -474,7 +474,7 @@ static Result<void*, DlErrorMessage> __dlopen(char const* filename, int flags)
VERIFY(!library_name.is_empty()); VERIFY(!library_name.is_empty());
auto const& parent_object = **s_global_objects.get(get_library_name(s_main_program_name)); auto const& parent_object = **s_global_objects.get(get_library_name(s_main_program_path));
auto result1 = map_library(filename, parent_object); auto result1 = map_library(filename, parent_object);
if (result1.is_error()) { if (result1.is_error()) {
@ -598,21 +598,23 @@ static void read_environment_variables()
} }
} }
void ELF::DynamicLinker::linker_main(String&& main_program_name, int main_program_fd, bool is_secure, int argc, char** argv, char** envp) void ELF::DynamicLinker::linker_main(String&& main_program_path, int main_program_fd, bool is_secure, int argc, char** argv, char** envp)
{ {
VERIFY(main_program_path.starts_with('/'));
s_envp = envp; s_envp = envp;
s_allowed_to_check_environment_variables = !is_secure; s_allowed_to_check_environment_variables = !is_secure;
if (s_allowed_to_check_environment_variables) if (s_allowed_to_check_environment_variables)
read_environment_variables(); read_environment_variables();
s_main_program_name = main_program_name; s_main_program_path = main_program_path;
auto library_name = get_library_name(main_program_name); auto library_name = get_library_name(main_program_path);
// NOTE: We always map the main library first, since it may require // NOTE: We always map the main library first, since it may require
// placement at a specific address. // placement at a specific address.
auto result1 = map_library(main_program_name, main_program_fd, main_program_name); auto result1 = map_library(main_program_path, main_program_fd, main_program_path);
if (result1.is_error()) { if (result1.is_error()) {
warnln("{}", result1.error().text); warnln("{}", result1.error().text);
fflush(stderr); fflush(stderr);
@ -634,8 +636,8 @@ void ELF::DynamicLinker::linker_main(String&& main_program_name, int main_progra
allocate_tls(); allocate_tls();
auto entry_point_function = [&main_program_name] { auto entry_point_function = [&main_program_path] {
auto library_name = get_library_name(main_program_name); auto library_name = get_library_name(main_program_path);
auto result = link_main_library(library_name, RTLD_GLOBAL | RTLD_LAZY); auto result = link_main_library(library_name, RTLD_GLOBAL | RTLD_LAZY);
if (result.is_error()) { if (result.is_error()) {
warnln("{}", result.error().text); warnln("{}", result.error().text);

View file

@ -15,7 +15,7 @@ namespace ELF {
class DynamicLinker { class DynamicLinker {
public: public:
static Optional<DynamicObject::SymbolLookupResult> lookup_global_symbol(StringView symbol); static Optional<DynamicObject::SymbolLookupResult> lookup_global_symbol(StringView symbol);
[[noreturn]] static void linker_main(String&& main_program_name, int fd, bool is_secure, int argc, char** argv, char** envp); [[noreturn]] static void linker_main(String&& main_program_path, int fd, bool is_secure, int argc, char** argv, char** envp);
private: private:
DynamicLinker() = delete; DynamicLinker() = delete;

View file

@ -39,6 +39,8 @@ namespace ELF {
Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> DynamicLoader::try_create(int fd, String filename, String filepath) Result<NonnullRefPtr<DynamicLoader>, DlErrorMessage> DynamicLoader::try_create(int fd, String filename, String filepath)
{ {
VERIFY(filepath.starts_with('/'));
struct stat stat; struct stat stat;
if (fstat(fd, &stat) < 0) { if (fstat(fd, &stat) < 0) {
return DlErrorMessage { "DynamicLoader::try_create fstat" }; return DlErrorMessage { "DynamicLoader::try_create fstat" };

View file

@ -4,6 +4,7 @@
* SPDX-License-Identifier: BSD-2-Clause * SPDX-License-Identifier: BSD-2-Clause
*/ */
#include <AK/LexicalPath.h>
#include <AK/String.h> #include <AK/String.h>
#include <AK/StringBuilder.h> #include <AK/StringBuilder.h>
#include <AK/StringView.h> #include <AK/StringView.h>
@ -232,7 +233,7 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
{ {
TRY(Core::System::pledge("stdio rpath")); TRY(Core::System::pledge("stdio rpath"));
StringView path {}; String path {};
static bool display_all = false; static bool display_all = false;
static bool display_elf_header = false; static bool display_elf_header = false;
static bool display_program_headers = false; static bool display_program_headers = false;
@ -288,6 +289,8 @@ ErrorOr<int> serenity_main(Main::Arguments arguments)
display_hardening = true; display_hardening = true;
} }
path = LexicalPath::absolute_path(TRY(Core::System::getcwd()), path);
auto file_or_error = Core::MappedFile::map(path); auto file_or_error = Core::MappedFile::map(path);
if (file_or_error.is_error()) { if (file_or_error.is_error()) {