Serenity Operating System
at master 183 lines 7.8 kB view raw
1/* 2 * Copyright (c) 2018-2020, Andreas Kling <kling@serenityos.org> 3 * 4 * SPDX-License-Identifier: BSD-2-Clause 5 */ 6 7#pragma once 8 9#include <AK/Checked.h> 10#include <AK/Error.h> 11#include <AK/Forward.h> 12#include <AK/Time.h> 13#include <AK/Userspace.h> 14#include <Kernel/KString.h> 15#include <Kernel/UnixTypes.h> 16 17ErrorOr<NonnullOwnPtr<Kernel::KString>> try_copy_kstring_from_user(Userspace<char const*>, size_t); 18ErrorOr<Time> copy_time_from_user(timespec const*); 19ErrorOr<Time> copy_time_from_user(timeval const*); 20template<typename T> 21ErrorOr<Time> copy_time_from_user(Userspace<T*>); 22 23[[nodiscard]] Optional<u32> user_atomic_fetch_add_relaxed(u32 volatile* var, u32 val); 24[[nodiscard]] Optional<u32> user_atomic_exchange_relaxed(u32 volatile* var, u32 val); 25[[nodiscard]] Optional<u32> user_atomic_load_relaxed(u32 volatile* var); 26[[nodiscard]] bool user_atomic_store_relaxed(u32 volatile* var, u32 val); 27[[nodiscard]] Optional<bool> user_atomic_compare_exchange_relaxed(u32 volatile* var, u32& expected, u32 val); 28[[nodiscard]] Optional<u32> user_atomic_fetch_and_relaxed(u32 volatile* var, u32 val); 29[[nodiscard]] Optional<u32> user_atomic_fetch_and_not_relaxed(u32 volatile* var, u32 val); 30[[nodiscard]] Optional<u32> user_atomic_fetch_or_relaxed(u32 volatile* var, u32 val); 31[[nodiscard]] Optional<u32> user_atomic_fetch_xor_relaxed(u32 volatile* var, u32 val); 32 33ErrorOr<void> copy_to_user(void*, void const*, size_t); 34ErrorOr<void> copy_from_user(void*, void const*, size_t); 35ErrorOr<void> memset_user(void*, int, size_t); 36 37extern "C" { 38 39void* memcpy(void*, void const*, size_t); 40[[nodiscard]] int strncmp(char const* s1, char const* s2, size_t n); 41[[nodiscard]] char* strstr(char const* haystack, char const* needle); 42[[nodiscard]] int strcmp(char const*, char const*); 43[[nodiscard]] size_t strlen(char const*); 44[[nodiscard]] size_t strnlen(char const*, size_t); 45void* memset(void*, int, size_t); 46[[nodiscard]] int memcmp(void const*, void const*, size_t); 47void* memmove(void* dest, void const* src, size_t n); 48void const* memmem(void const* haystack, size_t, void const* needle, size_t); 49 50[[nodiscard]] inline u16 ntohs(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); } 51[[nodiscard]] inline u16 htons(u16 w) { return (w & 0xff) << 8 | ((w >> 8) & 0xff); } 52} 53 54#define offsetof(type, member) __builtin_offsetof(type, member) 55 56template<typename T> 57[[nodiscard]] inline ErrorOr<void> copy_from_user(T* dest, T const* src) 58{ 59 static_assert(IsTriviallyCopyable<T>); 60 return copy_from_user(dest, src, sizeof(T)); 61} 62 63template<typename T> 64[[nodiscard]] inline ErrorOr<void> copy_to_user(T* dest, T const* src) 65{ 66 static_assert(IsTriviallyCopyable<T>); 67 return copy_to_user(dest, src, sizeof(T)); 68} 69 70template<typename T> 71[[nodiscard]] inline ErrorOr<void> copy_from_user(T* dest, Userspace<T const*> src) 72{ 73 static_assert(IsTriviallyCopyable<T>); 74 return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T)); 75} 76 77template<typename T> 78[[nodiscard]] inline ErrorOr<void> copy_from_user(T* dest, Userspace<T*> src) 79{ 80 static_assert(IsTriviallyCopyable<T>); 81 return copy_from_user(dest, src.unsafe_userspace_ptr(), sizeof(T)); 82} 83 84#define DEPRECATE_COPY_FROM_USER_TYPE(T, REPLACEMENT) \ 85 template<> \ 86 [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) ErrorOr<void> copy_from_user<T>(T*, const T*) \ 87 { \ 88 VERIFY_NOT_REACHED(); \ 89 } \ 90 template<> \ 91 [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) ErrorOr<void> copy_from_user<T>(T*, Userspace<const T*>) \ 92 { \ 93 VERIFY_NOT_REACHED(); \ 94 } \ 95 template<> \ 96 [[nodiscard]] inline __attribute__((deprecated("use " #REPLACEMENT " instead"))) ErrorOr<void> copy_from_user<T>(T*, Userspace<T*>) \ 97 { \ 98 VERIFY_NOT_REACHED(); \ 99 } 100 101DEPRECATE_COPY_FROM_USER_TYPE(timespec, copy_time_from_user) 102DEPRECATE_COPY_FROM_USER_TYPE(timeval, copy_time_from_user) 103 104template<typename T> 105[[nodiscard]] inline ErrorOr<void> copy_to_user(Userspace<T*> dest, T const* src) 106{ 107 static_assert(IsTriviallyCopyable<T>); 108 return copy_to_user(dest.unsafe_userspace_ptr(), src, sizeof(T)); 109} 110 111template<typename T> 112[[nodiscard]] inline ErrorOr<void> copy_to_user(Userspace<T*> dest, void const* src, size_t size) 113{ 114 static_assert(IsTriviallyCopyable<T>); 115 return copy_to_user(dest.unsafe_userspace_ptr(), src, size); 116} 117 118template<typename T> 119[[nodiscard]] inline ErrorOr<void> copy_from_user(void* dest, Userspace<T const*> src, size_t size) 120{ 121 static_assert(IsTriviallyCopyable<T>); 122 return copy_from_user(dest, src.unsafe_userspace_ptr(), size); 123} 124 125template<typename T> 126[[nodiscard]] inline ErrorOr<void> copy_n_from_user(T* dest, T const* src, size_t count) 127{ 128 static_assert(IsTriviallyCopyable<T>); 129 Checked<size_t> size = sizeof(T); 130 size *= count; 131 if (size.has_overflow()) 132 return EOVERFLOW; 133 return copy_from_user(dest, src, size.value()); 134} 135 136template<typename T> 137[[nodiscard]] inline ErrorOr<void> copy_n_to_user(T* dest, T const* src, size_t count) 138{ 139 static_assert(IsTriviallyCopyable<T>); 140 Checked<size_t> size = sizeof(T); 141 size *= count; 142 if (size.has_overflow()) 143 return EOVERFLOW; 144 return copy_to_user(dest, src, size.value()); 145} 146 147template<typename T> 148[[nodiscard]] inline ErrorOr<void> copy_n_from_user(T* dest, Userspace<T const*> src, size_t count) 149{ 150 static_assert(IsTriviallyCopyable<T>); 151 Checked<size_t> size = sizeof(T); 152 size *= count; 153 if (size.has_overflow()) 154 return EOVERFLOW; 155 return copy_from_user(dest, src.unsafe_userspace_ptr(), size.value()); 156} 157 158template<typename T> 159[[nodiscard]] inline ErrorOr<void> try_copy_n_to_user(Userspace<T*> dest, T const* src, size_t count) 160{ 161 static_assert(IsTriviallyCopyable<T>); 162 Checked<size_t> size = sizeof(T); 163 size *= count; 164 if (size.has_overflow()) 165 return EOVERFLOW; 166 return copy_to_user(dest.unsafe_userspace_ptr(), src, size.value()); 167} 168 169template<typename T> 170inline ErrorOr<T> copy_typed_from_user(Userspace<T const*> user_data) 171{ 172 T data {}; 173 TRY(copy_from_user(&data, user_data)); 174 return data; 175} 176 177template<typename T> 178inline ErrorOr<T> copy_typed_from_user(Userspace<T*> user_data) 179{ 180 T data {}; 181 TRY(copy_from_user(&data, user_data)); 182 return data; 183}