Kernel: moved read/write_from_user out of Process

This commit is contained in:
2026-05-20 17:21:50 +03:00
committed by Bananymous
parent 14aa28b043
commit 718379ce3b
7 changed files with 67 additions and 47 deletions

View File

@@ -121,6 +121,7 @@ set(KERNEL_SOURCES
kernel/USB/USBManager.cpp
kernel/USB/XHCI/Controller.cpp
kernel/USB/XHCI/Device.cpp
kernel/UserCopy.cpp
icxxabi.cpp
)

View File

@@ -284,9 +284,6 @@ namespace Kernel
BAN::ErrorOr<FileParent> find_parent_file(int fd, const char* path, int flags) const;
BAN::ErrorOr<VirtualFileSystem::File> find_relative_parent(int fd, const char* path) const;
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size);
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size);
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size);
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
uint64_t signal_pending_mask() const

View File

@@ -0,0 +1,12 @@
#pragma once
#include <BAN/Errors.h>
namespace Kernel
{
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size);
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size);
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size);
};

View File

@@ -4,6 +4,7 @@
#include <kernel/Networking/NetworkManager.h>
#include <kernel/OpenFileDescriptorSet.h>
#include <kernel/Process.h>
#include <kernel/UserCopy.h>
#include <fcntl.h>
#include <sys/file.h>
@@ -254,7 +255,7 @@ namespace Kernel
if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK)
{
struct flock flock;
TRY(Process::current().read_from_user(reinterpret_cast<void*>(extra), &flock, sizeof(struct flock)));
TRY(read_from_user(reinterpret_cast<void*>(extra), &flock, sizeof(struct flock)));
flock.l_pid = Process::current().pid();
BAN::RefPtr<Inode> inode;
@@ -307,7 +308,7 @@ namespace Kernel
}
if (cmd == F_GETLK)
TRY(Process::current().write_to_user(reinterpret_cast<void*>(extra), &flock, sizeof(struct flock)));
TRY(write_to_user(reinterpret_cast<void*>(extra), &flock, sizeof(struct flock)));
return 0;
}

View File

@@ -20,6 +20,7 @@
#include <kernel/Storage/StorageDevice.h>
#include <kernel/Terminal/PseudoTerminal.h>
#include <kernel/Timer/Timer.h>
#include <kernel/UserCopy.h>
#include <LibELF/AuxiliaryVector.h>
@@ -3885,47 +3886,6 @@ namespace Kernel
return region->allocate_page_containing(address, wants_write);
}
extern "C" bool safe_user_memcpy(void*, const void*, size_t);
extern "C" bool safe_user_strncpy(void*, const void*, size_t);
static inline bool is_valid_user_address(const void* user_addr, size_t size)
{
const vaddr_t user_vaddr = reinterpret_cast<vaddr_t>(user_addr);
if (BAN::Math::will_addition_overflow<vaddr_t>(user_vaddr, size))
return false;
if (user_vaddr + size > USERSPACE_END)
return false;
return true;
}
BAN::ErrorOr<void> Process::read_from_user(const void* user_addr, void* out, size_t size)
{
if (!is_valid_user_address(user_addr, size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_memcpy(out, user_addr, size))
return BAN::Error::from_errno(EFAULT);
return {};
}
BAN::ErrorOr<void> Process::read_string_from_user(const char* user_addr, char* out, size_t max_size)
{
max_size = BAN::Math::min<size_t>(max_size, USERSPACE_END - reinterpret_cast<vaddr_t>(user_addr));
if (!is_valid_user_address(user_addr, max_size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_strncpy(out, user_addr, max_size))
return BAN::Error::from_errno(EFAULT);
return {};
}
BAN::ErrorOr<void> Process::write_to_user(void* user_addr, const void* in, size_t size)
{
if (!is_valid_user_address(user_addr, size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_memcpy(user_addr, in, size))
return BAN::Error::from_errno(EFAULT);
return {};
}
BAN::ErrorOr<MemoryRegion*> Process::validate_and_pin_pointer_access(const void* ptr, size_t size, bool needs_write)
{
// TODO: allow pinning multiple regions?

View File

@@ -9,6 +9,7 @@
#include <kernel/Scheduler.h>
#include <kernel/Thread.h>
#include <kernel/Timer/Timer.h>
#include <kernel/UserCopy.h>
namespace Kernel
{
@@ -727,7 +728,7 @@ namespace Kernel
{
static_assert(sizeof(T) >= sizeof(uintptr_t));
sp -= sizeof(T);
if (m_process->write_to_user(reinterpret_cast<void*>(sp), &value, sizeof(T)).is_error())
if (write_to_user(reinterpret_cast<void*>(sp), &value, sizeof(T)).is_error())
m_process->exit(128 + SIGSEGV, SIGSEGV | 0x80);
};

View File

@@ -0,0 +1,48 @@
#include <kernel/Memory/Types.h>
#include <kernel/UserCopy.h>
extern "C" bool safe_user_memcpy(void*, const void*, size_t);
extern "C" bool safe_user_strncpy(void*, const void*, size_t);
namespace Kernel
{
static inline bool is_valid_user_address(const void* user_addr, size_t size)
{
const vaddr_t user_vaddr = reinterpret_cast<vaddr_t>(user_addr);
if (BAN::Math::will_addition_overflow<vaddr_t>(user_vaddr, size))
return false;
if (user_vaddr + size > USERSPACE_END)
return false;
return true;
}
BAN::ErrorOr<void> read_from_user(const void* user_addr, void* out, size_t size)
{
if (!is_valid_user_address(user_addr, size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_memcpy(out, user_addr, size))
return BAN::Error::from_errno(EFAULT);
return {};
}
BAN::ErrorOr<void> read_string_from_user(const char* user_addr, char* out, size_t max_size)
{
max_size = BAN::Math::min<size_t>(max_size, USERSPACE_END - reinterpret_cast<vaddr_t>(user_addr));
if (!is_valid_user_address(user_addr, max_size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_strncpy(out, user_addr, max_size))
return BAN::Error::from_errno(EFAULT);
return {};
}
BAN::ErrorOr<void> write_to_user(void* user_addr, const void* in, size_t size)
{
if (!is_valid_user_address(user_addr, size))
return BAN::Error::from_errno(EFAULT);
if (!safe_user_memcpy(user_addr, in, size))
return BAN::Error::from_errno(EFAULT);
return {};
}
}