Serenity Operating System
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}