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 #include <asm/segment.h> 13 14 #define MAKE_MM_SEG(s) ((mm_segment_t) { (s) }) 15 16 #ifndef KERNEL_DS 17 #define KERNEL_DS MAKE_MM_SEG(~0UL) 18 #endif 19 20 #ifndef USER_DS 21 #define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) 22 #endif 23 24 #ifndef get_fs 25 #define get_ds() (KERNEL_DS) 26 #define get_fs() (current_thread_info()->addr_limit) 27 28 static inline void set_fs(mm_segment_t fs) 29 { 30 current_thread_info()->addr_limit = fs; 31 } 32 #endif 33 34 #ifndef segment_eq 35 #define segment_eq(a, b) ((a).seg == (b).seg) 36 #endif 37 38 #define access_ok(addr, size) __access_ok((unsigned long)(addr),(size)) 39 40 /* 41 * The architecture should really override this if possible, at least 42 * doing a check on the get_fs() 43 */ 44 #ifndef __access_ok 45 static inline int __access_ok(unsigned long addr, unsigned long size) 46 { 47 return 1; 48 } 49 #endif 50 51 /* 52 * These are the main single-value transfer routines. They automatically 53 * use the right size if we just have the right pointer type. 54 * This version just falls back to copy_{from,to}_user, which should 55 * provide a fast-path for small values. 56 */ 57 #define __put_user(x, ptr) \ 58 ({ \ 59 __typeof__(*(ptr)) __x = (x); \ 60 int __pu_err = -EFAULT; \ 61 __chk_user_ptr(ptr); \ 62 switch (sizeof (*(ptr))) { \ 63 case 1: \ 64 case 2: \ 65 case 4: \ 66 case 8: \ 67 __pu_err = __put_user_fn(sizeof (*(ptr)), \ 68 ptr, &__x); \ 69 break; \ 70 default: \ 71 __put_user_bad(); \ 72 break; \ 73 } \ 74 __pu_err; \ 75 }) 76 77 #define put_user(x, ptr) \ 78 ({ \ 79 void __user *__p = (ptr); \ 80 might_fault(); \ 81 access_ok(__p, sizeof(*ptr)) ? \ 82 __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) : \ 83 -EFAULT; \ 84 }) 85 86 #ifndef __put_user_fn 87 88 static inline int __put_user_fn(size_t size, void __user *ptr, void *x) 89 { 90 return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0; 91 } 92 93 #define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 94 95 #endif 96 97 extern int __put_user_bad(void) __attribute__((noreturn)); 98 99 #define __get_user(x, ptr) \ 100 ({ \ 101 int __gu_err = -EFAULT; \ 102 __chk_user_ptr(ptr); \ 103 switch (sizeof(*(ptr))) { \ 104 case 1: { \ 105 unsigned char __x = 0; \ 106 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 107 ptr, &__x); \ 108 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 109 break; \ 110 }; \ 111 case 2: { \ 112 unsigned short __x = 0; \ 113 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 114 ptr, &__x); \ 115 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 116 break; \ 117 }; \ 118 case 4: { \ 119 unsigned int __x = 0; \ 120 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 121 ptr, &__x); \ 122 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 123 break; \ 124 }; \ 125 case 8: { \ 126 unsigned long long __x = 0; \ 127 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 128 ptr, &__x); \ 129 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 130 break; \ 131 }; \ 132 default: \ 133 __get_user_bad(); \ 134 break; \ 135 } \ 136 __gu_err; \ 137 }) 138 139 #define get_user(x, ptr) \ 140 ({ \ 141 const void __user *__p = (ptr); \ 142 might_fault(); \ 143 access_ok(__p, sizeof(*ptr)) ? \ 144 __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\ 145 ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ 146 }) 147 148 #ifndef __get_user_fn 149 static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 150 { 151 return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0; 152 } 153 154 #define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 155 156 #endif 157 158 extern int __get_user_bad(void) __attribute__((noreturn)); 159 160 /* 161 * Copy a null terminated string from userspace. 162 */ 163 #ifndef __strncpy_from_user 164 static inline long 165 __strncpy_from_user(char *dst, const char __user *src, long count) 166 { 167 char *tmp; 168 strncpy(dst, (const char __force *)src, count); 169 for (tmp = dst; *tmp && count > 0; tmp++, count--) 170 ; 171 return (tmp - dst); 172 } 173 #endif 174 175 static inline long 176 strncpy_from_user(char *dst, const char __user *src, long count) 177 { 178 if (!access_ok(src, 1)) 179 return -EFAULT; 180 return __strncpy_from_user(dst, src, count); 181 } 182 183 /* 184 * Return the size of a string (including the ending 0) 185 * 186 * Return 0 on exception, a value greater than N if too long 187 */ 188 #ifndef __strnlen_user 189 #define __strnlen_user(s, n) (strnlen((s), (n)) + 1) 190 #endif 191 192 /* 193 * Unlike strnlen, strnlen_user includes the nul terminator in 194 * its returned count. Callers should check for a returned value 195 * greater than N as an indication the string is too long. 196 */ 197 static inline long strnlen_user(const char __user *src, long n) 198 { 199 if (!access_ok(src, 1)) 200 return 0; 201 return __strnlen_user(src, n); 202 } 203 204 /* 205 * Zero Userspace 206 */ 207 #ifndef __clear_user 208 static inline __must_check unsigned long 209 __clear_user(void __user *to, unsigned long n) 210 { 211 memset((void __force *)to, 0, n); 212 return 0; 213 } 214 #endif 215 216 static inline __must_check unsigned long 217 clear_user(void __user *to, unsigned long n) 218 { 219 might_fault(); 220 if (!access_ok(to, n)) 221 return n; 222 223 return __clear_user(to, n); 224 } 225 226 #include <asm/extable.h> 227 228 #endif /* __ASM_GENERIC_UACCESS_H */ 229