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/USBManager.cpp
|
||||||
kernel/USB/XHCI/Controller.cpp
|
kernel/USB/XHCI/Controller.cpp
|
||||||
kernel/USB/XHCI/Device.cpp
|
kernel/USB/XHCI/Device.cpp
|
||||||
|
kernel/UserCopy.cpp
|
||||||
icxxabi.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<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<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);
|
BAN::ErrorOr<MemoryRegion*> validate_and_pin_pointer_access(const void*, size_t, bool needs_write);
|
||||||
|
|
||||||
uint64_t signal_pending_mask() const
|
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/Networking/NetworkManager.h>
|
||||||
#include <kernel/OpenFileDescriptorSet.h>
|
#include <kernel/OpenFileDescriptorSet.h>
|
||||||
#include <kernel/Process.h>
|
#include <kernel/Process.h>
|
||||||
|
#include <kernel/UserCopy.h>
|
||||||
|
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <sys/file.h>
|
#include <sys/file.h>
|
||||||
@@ -254,7 +255,7 @@ namespace Kernel
|
|||||||
if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK)
|
if (cmd == F_SETLK || cmd == F_SETLKW || cmd == F_GETLK)
|
||||||
{
|
{
|
||||||
struct flock flock;
|
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();
|
flock.l_pid = Process::current().pid();
|
||||||
|
|
||||||
BAN::RefPtr<Inode> inode;
|
BAN::RefPtr<Inode> inode;
|
||||||
@@ -307,7 +308,7 @@ namespace Kernel
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (cmd == F_GETLK)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -20,6 +20,7 @@
|
|||||||
#include <kernel/Storage/StorageDevice.h>
|
#include <kernel/Storage/StorageDevice.h>
|
||||||
#include <kernel/Terminal/PseudoTerminal.h>
|
#include <kernel/Terminal/PseudoTerminal.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
#include <kernel/UserCopy.h>
|
||||||
|
|
||||||
#include <LibELF/AuxiliaryVector.h>
|
#include <LibELF/AuxiliaryVector.h>
|
||||||
|
|
||||||
@@ -3885,47 +3886,6 @@ namespace Kernel
|
|||||||
return region->allocate_page_containing(address, wants_write);
|
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)
|
BAN::ErrorOr<MemoryRegion*> Process::validate_and_pin_pointer_access(const void* ptr, size_t size, bool needs_write)
|
||||||
{
|
{
|
||||||
// TODO: allow pinning multiple regions?
|
// TODO: allow pinning multiple regions?
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
#include <kernel/Scheduler.h>
|
#include <kernel/Scheduler.h>
|
||||||
#include <kernel/Thread.h>
|
#include <kernel/Thread.h>
|
||||||
#include <kernel/Timer/Timer.h>
|
#include <kernel/Timer/Timer.h>
|
||||||
|
#include <kernel/UserCopy.h>
|
||||||
|
|
||||||
namespace Kernel
|
namespace Kernel
|
||||||
{
|
{
|
||||||
@@ -727,7 +728,7 @@ namespace Kernel
|
|||||||
{
|
{
|
||||||
static_assert(sizeof(T) >= sizeof(uintptr_t));
|
static_assert(sizeof(T) >= sizeof(uintptr_t));
|
||||||
sp -= sizeof(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);
|
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