1 /* SPDX-License-Identifier: GPL-2.0 */ 2 #ifndef __ASM_GENERIC_UACCESS_H 3 #define __ASM_GENERIC_UACCESS_H 4 5 /* 6 * User space memory access functions, these should work 7 * on any machine that has kernel and user data in the same 8 * address space, e.g. all NOMMU machines. 9 */ 10 #include <linux/string.h> 11 12 #ifdef CONFIG_UACCESS_MEMCPY 13 static inline __must_check unsigned long 14 raw_copy_from_user(void *to, const void __user * from, unsigned long n) 15 { 16 if (__builtin_constant_p(n)) { 17 switch(n) { 18 case 1: 19 *(u8 *)to = *(u8 __force *)from; 20 return 0; 21 case 2: 22 *(u16 *)to = *(u16 __force *)from; 23 return 0; 24 case 4: 25 *(u32 *)to = *(u32 __force *)from; 26 return 0; 27 #ifdef CONFIG_64BIT 28 case 8: 29 *(u64 *)to = *(u64 __force *)from; 30 return 0; 31 #endif 32 } 33 } 34 35 memcpy(to, (const void __force *)from, n); 36 return 0; 37 } 38 39 static inline __must_check unsigned long 40 raw_copy_to_user(void __user *to, const void *from, unsigned long n) 41 { 42 if (__builtin_constant_p(n)) { 43 switch(n) { 44 case 1: 45 *(u8 __force *)to = *(u8 *)from; 46 return 0; 47 case 2: 48 *(u16 __force *)to = *(u16 *)from; 49 return 0; 50 case 4: 51 *(u32 __force *)to = *(u32 *)from; 52 return 0; 53 #ifdef CONFIG_64BIT 54 case 8: 55 *(u64 __force *)to = *(u64 *)from; 56 return 0; 57 #endif 58 default: 59 break; 60 } 61 } 62 63 memcpy((void __force *)to, from, n); 64 return 0; 65 } 66 #define INLINE_COPY_FROM_USER 67 #define INLINE_COPY_TO_USER 68 #endif /* CONFIG_UACCESS_MEMCPY */ 69 70 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 71 72 #ifndef KERNEL_DS 73 #define KERNEL_DS MAKE_MM_SEG(~0UL) 74 #endif 75 76 #ifndef USER_DS 77 #define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) 78 #endif 79 80 #ifndef get_fs 81 #define get_fs() (current_thread_info()->addr_limit) 82 83 static inline void set_fs(mm_segment_t fs) 84 { 85 current_thread_info()->addr_limit = fs; 86 } 87 #endif 88 89 #ifndef uaccess_kernel 90 #define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) 91 #endif 92 93 #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) 94 95 /* 96 * The architecture should really override this if possible, at least 97 * doing a check on the get_fs() 98 */ 99 #ifndef __access_ok 100 static inline int __access_ok(unsigned long addr, unsigned long size) 101 { 102 return 1; 103 } 104 #endif 105 106 /* 107 * These are the main single-value transfer routines. They automatically 108 * use the right size if we just have the right pointer type. 109 * This version just falls back to copy_{from,to}_user, which should 110 * provide a fast-path for small values. 111 */ 112 #define __put_user(x, ptr) \ 113 ({ \ 114 __typeof__(*(ptr)) __x = (x); \ 115 int __pu_err = -EFAULT; \ 116 __chk_user_ptr(ptr); \ 117 switch (sizeof (*(ptr))) { \ 118 case 1: \ 119 case 2: \ 120 case 4: \ 121 case 8: \ 122 __pu_err = __put_user_fn(sizeof (*(ptr)), \ 123 ptr, &__x); \ 124 break; \ 125 default: \ 126 __put_user_bad(); \ 127 break; \ 128 } \ 129 __pu_err; \ 130 }) 131 132 #define put_user(x, ptr) \ 133 ({ \ 134 void __user *__p = (ptr); \ 135 might_fault(); \ 136 access_ok(__p, sizeof(*ptr)) ? \ 137 __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) : \ 138 -EFAULT; \ 139 }) 140 141 #ifndef __put_user_fn 142 143 static inline int __put_user_fn(size_t size, void __user *ptr, void *x) 144 { 145 return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0; 146 } 147 148 #define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 149 150 #endif 151 152 extern int __put_user_bad(void) __attribute__((noreturn)); 153 154 #define __get_user(x, ptr) \ 155 ({ \ 156 int __gu_err = -EFAULT; \ 157 __chk_user_ptr(ptr); \ 158 switch (sizeof(*(ptr))) { \ 159 case 1: { \ 160 unsigned char __x = 0; \ 161 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 162 ptr, &__x); \ 163 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 164 break; \ 165 }; \ 166 case 2: { \ 167 unsigned short __x = 0; \ 168 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 169 ptr, &__x); \ 170 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 171 break; \ 172 }; \ 173 case 4: { \ 174 unsigned int __x = 0; \ 175 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 176 ptr, &__x); \ 177 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 178 break; \ 179 }; \ 180 case 8: { \ 181 unsigned long long __x = 0; \ 182 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 183 ptr, &__x); \ 184 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 185 break; \ 186 }; \ 187 default: \ 188 __get_user_bad(); \ 189 break; \ 190 } \ 191 __gu_err; \ 192 }) 193 194 #define get_user(x, ptr) \ 195 ({ \ 196 const void __user *__p = (ptr); \ 197 might_fault(); \ 198 access_ok(__p, sizeof(*ptr)) ? \ 199 __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\ 200 ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ 201 }) 202 203 #ifndef __get_user_fn 204 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 205 { 206 return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0; 207 } 208 209 #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 210 211 #endif 212 213 extern int __get_user_bad(void) __attribute__((noreturn)); 214 215 /* 216 * Copy a null terminated string from userspace. 217 */ 218 #ifndef __strncpy_from_user 219 static inline long 220 __strncpy_from_user(char *dst, const char __user *src, long count) 221 { 222 char *tmp; 223 strncpy(dst, (const char __force *)src, count); 224 for (tmp = dst; *tmp && count > 0; tmp++, count--) 225 ; 226 return (tmp - dst); 227 } 228 #endif 229 230 static inline long 231 strncpy_from_user(char *dst, const char __user *src, long count) 232 { 233 if (!access_ok(src, 1)) 234 return -EFAULT; 235 return __strncpy_from_user(dst, src, count); 236 } 237 238 /* 239 * Return the size of a string (including the ending 0) 240 * 241 * Return 0 on exception, a value greater than N if too long 242 */ 243 #ifndef __strnlen_user 244 #define __strnlen_user(s, n) (strnlen((s), (n)) + 1) 245 #endif 246 247 /* 248 * Unlike strnlen, strnlen_user includes the nul terminator in 249 * its returned count. Callers should check for a returned value 250 * greater than N as an indication the string is too long. 251 */ 252 static inline long strnlen_user(const char __user *src, long n) 253 { 254 if (!access_ok(src, 1)) 255 return 0; 256 return __strnlen_user(src, n); 257 } 258 259 /* 260 * Zero Userspace 261 */ 262 #ifndef __clear_user 263 static inline __must_check unsigned long 264 __clear_user(void __user *to, unsigned long n) 265 { 266 memset((void __force *)to, 0, n); 267 return 0; 268 } 269 #endif 270 271 static inline __must_check unsigned long 272 clear_user(void __user *to, unsigned long n) 273 { 274 might_fault(); 275 if (!access_ok(to, n)) 276 return n; 277 278 return __clear_user(to, n); 279 } 280 281 #include <asm/extable.h> 282 283 #endif /* __ASM_GENERIC_UACCESS_H */ 284