at v5.2 283 lines 6.3 kB view raw
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 13static inline __must_check unsigned long 14raw_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 39static inline __must_check unsigned long 40raw_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 83static inline void set_fs(mm_segment_t fs) 84{ 85 current_thread_info()->addr_limit = fs; 86} 87#endif 88 89#ifndef segment_eq 90#define segment_eq(a, b) ((a).seg == (b).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 100static 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 143static 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 152extern 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 204static 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 213extern int __get_user_bad(void) __attribute__((noreturn)); 214 215/* 216 * Copy a null terminated string from userspace. 217 */ 218#ifndef __strncpy_from_user 219static 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 230static inline long 231strncpy_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 */ 252static 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 263static 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 271static inline __must_check unsigned long 272clear_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 */