Kernel: moved read/write_from_user out of Process
This commit is contained in:
@@ -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
|
||||
)
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
12
kernel/include/kernel/UserCopy.h
Normal file
12
kernel/include/kernel/UserCopy.h
Normal 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);
|
||||
|
||||
};
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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?
|
||||
|
||||
@@ -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);
|
||||
};
|
||||
|
||||
|
||||
48
kernel/kernel/UserCopy.cpp
Normal file
48
kernel/kernel/UserCopy.cpp
Normal 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 {};
|
||||
}
|
||||
|
||||
}
|
||||
Reference in New Issue
Block a user