From 0b287c18b939a89bd5c6884a71a832b091cbe74b Mon Sep 17 00:00:00 2001 From: Andreas Kling Date: Mon, 27 Jul 2020 18:32:30 +0200 Subject: [PATCH] UserspaceEmulator: Implement the execve() syscall :^) This virtual syscall works by exec'ing the UserspaceEmulator itself, with the emulated program's provided arguments as the arguments to the new UserspaceEmulator instance. This means that we "follow" exec'ed programs and emulate them as well. In the future we might want to make this an opt-in (or opt-out, idk) behavior, but for now it's what we do. This is really quite cool, I think! :^) --- DevTools/UserspaceEmulator/Emulator.cpp | 44 +++++++++++++++++++++++++ DevTools/UserspaceEmulator/Emulator.h | 1 + 2 files changed, 45 insertions(+) diff --git a/DevTools/UserspaceEmulator/Emulator.cpp b/DevTools/UserspaceEmulator/Emulator.cpp index 10d6734e29..dcbb5eeef7 100644 --- a/DevTools/UserspaceEmulator/Emulator.cpp +++ b/DevTools/UserspaceEmulator/Emulator.cpp @@ -242,6 +242,8 @@ u32 Emulator::virt_syscall(u32 function, u32 arg1, u32 arg2, u32 arg3) dbgprintf("Syscall: %s (%x)\n", Syscall::to_string((Syscall::Function)function), function); #endif switch (function) { + case SC_execve: + return virt$execve(arg1); case SC_ioctl: return virt$ioctl(arg1, arg2, arg3); case SC_get_dir_entries: @@ -872,4 +874,46 @@ int Emulator::virt$fork() return fork(); } +int Emulator::virt$execve(FlatPtr params_addr) +{ + Syscall::SC_execve_params params; + mmu().copy_from_vm(¶ms, params_addr, sizeof(params)); + + auto path = String::copy(mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length)); + Vector arguments; + Vector environment; + + auto copy_string_list = [this](auto& output_vector, auto& string_list) { + for (size_t i = 0; i < string_list.length; ++i) { + Syscall::StringArgument string; + mmu().copy_from_vm(&string, (FlatPtr)&string_list.strings[i], sizeof(string)); + output_vector.append(String::copy(mmu().copy_buffer_from_vm((FlatPtr)string.characters, string.length))); + } + }; + + copy_string_list(arguments, params.arguments); + copy_string_list(environment, params.environment); + + dbgprintf("\n"); + dbgprintf("==%d== \033[33;1mSyscall:\033[0m execve\n", getpid()); + for (auto& argument : arguments) + dbgprintf("==%d== - %s\n", getpid(), argument.characters()); + + Vector argv; + Vector envp; + + argv.append(const_cast("/bin/UserspaceEmulator")); + + auto create_string_vector = [](auto& output_vector, auto& input_vector) { + for (auto& string : input_vector) + output_vector.append(const_cast(string.characters())); + output_vector.append(nullptr); + }; + + create_string_vector(argv, arguments); + create_string_vector(envp, environment); + + return execve(argv[0], (char* const*)argv.data(), (char* const*)envp.data()); +} + } diff --git a/DevTools/UserspaceEmulator/Emulator.h b/DevTools/UserspaceEmulator/Emulator.h index 6da4bb98f8..7b0fc117cd 100644 --- a/DevTools/UserspaceEmulator/Emulator.h +++ b/DevTools/UserspaceEmulator/Emulator.h @@ -71,6 +71,7 @@ private: void setup_stack(const Vector& arguments, const Vector& environment); int virt$fork(); + int virt$execve(FlatPtr); int virt$get_dir_entries(int fd, FlatPtr buffer, ssize_t); int virt$ioctl(int fd, unsigned, FlatPtr); int virt$usleep(useconds_t);