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! :^)
This commit is contained in:
Andreas Kling 2020-07-27 18:32:30 +02:00
parent b9a0ba9624
commit 0b287c18b9
Notes: sideshowbarker 2024-07-19 04:33:39 +09:00
2 changed files with 45 additions and 0 deletions

View file

@ -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(&params, params_addr, sizeof(params));
auto path = String::copy(mmu().copy_buffer_from_vm((FlatPtr)params.path.characters, params.path.length));
Vector<String> arguments;
Vector<String> 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<char*> argv;
Vector<char*> envp;
argv.append(const_cast<char*>("/bin/UserspaceEmulator"));
auto create_string_vector = [](auto& output_vector, auto& input_vector) {
for (auto& string : input_vector)
output_vector.append(const_cast<char*>(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());
}
}

View file

@ -71,6 +71,7 @@ private:
void setup_stack(const Vector<String>& arguments, const Vector<String>& 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);