Luna/kernel/src/sys/exec.cpp

73 lines
1.9 KiB
C++
Raw Normal View History

#include "ELF.h"
#include "Log.h"
#include "fs/VFS.h"
#include "memory/MemoryManager.h"
#include "sys/Syscall.h"
#include "thread/Scheduler.h"
#include "thread/ThreadImage.h"
#include <bits/modes.h>
#include <luna/CString.h>
#include <luna/ScopeGuard.h>
2023-03-18 20:55:16 +00:00
#include <luna/Vector.h>
static Result<Vector<OwnedStringView>> copy_string_vector_from_userspace(u64 address)
{
Vector<OwnedStringView> result;
const u64* user_vector = (const u64*)address;
u64 item;
while (true)
{
if (!MemoryManager::copy_from_user_typed(user_vector, &item)) return err(EFAULT);
if (!item) break;
auto string = TRY(MemoryManager::strdup_from_user(item));
TRY(result.try_append(move(string)));
user_vector++;
}
return result;
}
Result<u64> sys_exec(Registers* regs, SyscallArgs args)
{
auto path = TRY(MemoryManager::strdup_from_user(args[0]));
2023-03-18 20:55:16 +00:00
auto argv = TRY(copy_string_vector_from_userspace(args[1]));
kdbgln("exec: printing out argv (argc = %zu)", argv.size());
for (const auto& arg : argv) { kdbgln("* %s", arg.chars()); }
// FIXME: Make sure argv is not too big.
auto inode = TRY(VFS::resolve_path(path.chars()));
// Not executable
if ((inode->mode() & S_IXUSR) != S_IXUSR) return err(EACCES);
kinfoln("exec: attempting to replace current image with %s", path.chars());
auto current = Scheduler::current();
auto image = TRY(ThreadImage::try_load_from_elf(inode));
// From now on, nothing should fail.
kinfoln("exec: image load ok, will now replace existing process image");
2023-03-18 20:55:16 +00:00
// FIXME: Close O_CLOEXEC file descriptors.
// for (int i = 0; i < FD_MAX; i++) { current->fd_table[i] = {}; }
MMU::delete_userspace_page_directory(current->directory);
image->apply(current);
MMU::switch_page_directory(current->directory);
memcpy(regs, &current->regs, sizeof(*regs));
kinfoln("exec: done");
return 0;
}