kernel: Separate a thread's page directory into two
All checks were successful
continuous-integration/drone/pr Build is passing

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: apio
GPG Key ID: B8A7D06E42258954
5 changed files with 13 additions and 11 deletions

View File

@ -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();

View File

@ -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));

View File

@ -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());

View File

@ -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);

View File

@ -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);
}