kernel: Separate a thread's page directory into two

The self directory, and the active directory. The active directory is the one the thread is currently using,
and the self directory is the one the thread owns.

This lets us keep track of both, which fixes ext2 executables crashing the system.
This commit is contained in:
apio 2023-06-25 20:09:40 +02:00
parent 5f4103251a
commit e9e7b22323
Signed by: asleepymoon
GPG Key ID: B8A7D06E42258954
5 changed files with 13 additions and 11 deletions
kernel/src

@ -146,7 +146,7 @@ namespace ATA
{
if (drive == m_current_drive) return;
u8 value = (drive << 4) | 0xa0;
u8 value = (u8)(drive << 4) | 0xa0;
write_register(Register::DriveSelect, value);
delay_400ns();

@ -70,7 +70,7 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
kdbgln("exec: attempting to replace current image with %s", path.chars());
#endif
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->directory); });
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); });
auto image = TRY(ThreadImage::try_load_from_elf(inode));
@ -99,7 +99,7 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
}
}
MMU::delete_userspace_page_directory(current->directory);
MMU::delete_userspace_page_directory(current->self_directory);
if (VFS::is_setuid(inode)) current->auth.euid = current->auth.suid = inode->uid();
if (VFS::is_setgid(inode)) current->auth.egid = current->auth.sgid = inode->gid();
@ -108,7 +108,7 @@ Result<u64> sys_execve(Registers* regs, SyscallArgs args)
image->apply(current);
MMU::switch_page_directory(current->directory);
MMU::switch_page_directory(current->self_directory);
current->set_arguments(user_argc, user_argv, user_envc, user_envp);
@ -123,7 +123,7 @@ Result<u64> sys_fork(Registers* regs, SyscallArgs)
{
auto current = Scheduler::current();
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->directory); });
auto guard = make_scope_guard([current] { MMU::switch_page_directory(current->self_directory); });
memcpy(&current->regs, regs, sizeof(*regs));

@ -191,7 +191,7 @@ namespace Scheduler
}
}
if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->directory);
if (!thread->is_kernel) MMU::delete_userspace_page_directory(thread->self_directory);
delete thread;
@ -236,8 +236,8 @@ namespace Scheduler
switch_context(old_thread, new_thread, regs);
if (!old_thread->is_kernel) old_thread->fp_data.save();
if (MMU::get_page_directory() != MMU::kernel_page_directory())
old_thread->directory = MMU::get_page_directory();
if (new_thread->directory) MMU::switch_page_directory(new_thread->directory);
old_thread->active_directory = MMU::get_page_directory();
if (new_thread->active_directory) MMU::switch_page_directory(new_thread->active_directory);
if (!new_thread->is_kernel)
{
CPU::switch_kernel_stack(new_thread->kernel_stack.top());

@ -97,7 +97,8 @@ struct Thread : public LinkedListNode<Thread>
Thread* parent { nullptr };
Option<pid_t> child_being_waited_for = {};
PageDirectory* directory;
PageDirectory* self_directory;
PageDirectory* active_directory { nullptr };
[[noreturn]] void exit_and_signal_parent(u8 status);

@ -69,7 +69,7 @@ Result<OwnedPtr<ThreadImage>> ThreadImage::clone_from_thread(Thread* parent)
auto vm_allocator = TRY(parent->vm_allocator->clone());
auto new_directory = TRY(MMU::clone_userspace_page_directory(parent->directory));
auto new_directory = TRY(MMU::clone_userspace_page_directory(parent->self_directory));
const ELFData data = { .entry = parent->ip() };
@ -124,7 +124,8 @@ void ThreadImage::apply(Thread* thread)
thread->stack = m_user_stack;
thread->set_sp(align_down<16>(m_sp));
thread->directory = m_directory;
thread->self_directory = m_directory;
thread->active_directory = m_directory;
thread->vm_allocator = move(m_vm_allocator);
}