#include #include 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(user_addr); if (BAN::Math::will_addition_overflow(user_vaddr, size)) return false; if (user_vaddr + size > USERSPACE_END) return false; return true; } BAN::ErrorOr 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 read_string_from_user(const char* user_addr, char* out, size_t max_size) { max_size = BAN::Math::min(max_size, USERSPACE_END - reinterpret_cast(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 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 {}; } }