diff options
Diffstat (limited to 'arch/s390/include/asm/uaccess.h')
| -rw-r--r-- | arch/s390/include/asm/uaccess.h | 171 |
1 files changed, 72 insertions, 99 deletions
diff --git a/arch/s390/include/asm/uaccess.h b/arch/s390/include/asm/uaccess.h index 79330af9a5f8..4133b3f72fb0 100644 --- a/arch/s390/include/asm/uaccess.h +++ b/arch/s390/include/asm/uaccess.h | |||
| @@ -92,33 +92,58 @@ static inline unsigned long extable_fixup(const struct exception_table_entry *x) | |||
| 92 | #define ARCH_HAS_SORT_EXTABLE | 92 | #define ARCH_HAS_SORT_EXTABLE |
| 93 | #define ARCH_HAS_SEARCH_EXTABLE | 93 | #define ARCH_HAS_SEARCH_EXTABLE |
| 94 | 94 | ||
| 95 | struct uaccess_ops { | 95 | int __handle_fault(unsigned long, unsigned long, int); |
| 96 | size_t (*copy_from_user)(size_t, const void __user *, void *); | ||
| 97 | size_t (*copy_to_user)(size_t, void __user *, const void *); | ||
| 98 | size_t (*copy_in_user)(size_t, void __user *, const void __user *); | ||
| 99 | size_t (*clear_user)(size_t, void __user *); | ||
| 100 | size_t (*strnlen_user)(size_t, const char __user *); | ||
| 101 | size_t (*strncpy_from_user)(size_t, const char __user *, char *); | ||
| 102 | int (*futex_atomic_op)(int op, u32 __user *, int oparg, int *old); | ||
| 103 | int (*futex_atomic_cmpxchg)(u32 *, u32 __user *, u32 old, u32 new); | ||
| 104 | }; | ||
| 105 | 96 | ||
| 106 | extern struct uaccess_ops uaccess; | 97 | /** |
| 107 | extern struct uaccess_ops uaccess_mvcos; | 98 | * __copy_from_user: - Copy a block of data from user space, with less checking. |
| 108 | extern struct uaccess_ops uaccess_pt; | 99 | * @to: Destination address, in kernel space. |
| 100 | * @from: Source address, in user space. | ||
| 101 | * @n: Number of bytes to copy. | ||
| 102 | * | ||
| 103 | * Context: User context only. This function may sleep. | ||
| 104 | * | ||
| 105 | * Copy data from user space to kernel space. Caller must check | ||
| 106 | * the specified block with access_ok() before calling this function. | ||
| 107 | * | ||
| 108 | * Returns number of bytes that could not be copied. | ||
| 109 | * On success, this will be zero. | ||
| 110 | * | ||
| 111 | * If some data could not be copied, this function will pad the copied | ||
| 112 | * data to the requested size using zero bytes. | ||
| 113 | */ | ||
| 114 | unsigned long __must_check __copy_from_user(void *to, const void __user *from, | ||
| 115 | unsigned long n); | ||
| 116 | |||
| 117 | /** | ||
| 118 | * __copy_to_user: - Copy a block of data into user space, with less checking. | ||
| 119 | * @to: Destination address, in user space. | ||
| 120 | * @from: Source address, in kernel space. | ||
| 121 | * @n: Number of bytes to copy. | ||
| 122 | * | ||
| 123 | * Context: User context only. This function may sleep. | ||
| 124 | * | ||
| 125 | * Copy data from kernel space to user space. Caller must check | ||
| 126 | * the specified block with access_ok() before calling this function. | ||
| 127 | * | ||
| 128 | * Returns number of bytes that could not be copied. | ||
| 129 | * On success, this will be zero. | ||
| 130 | */ | ||
| 131 | unsigned long __must_check __copy_to_user(void __user *to, const void *from, | ||
| 132 | unsigned long n); | ||
| 109 | 133 | ||
| 110 | extern int __handle_fault(unsigned long, unsigned long, int); | 134 | #define __copy_to_user_inatomic __copy_to_user |
| 135 | #define __copy_from_user_inatomic __copy_from_user | ||
| 111 | 136 | ||
| 112 | static inline int __put_user_fn(size_t size, void __user *ptr, void *x) | 137 | static inline int __put_user_fn(void *x, void __user *ptr, unsigned long size) |
| 113 | { | 138 | { |
| 114 | size = uaccess.copy_to_user(size, ptr, x); | 139 | size = __copy_to_user(ptr, x, size); |
| 115 | return size ? -EFAULT : size; | 140 | return size ? -EFAULT : 0; |
| 116 | } | 141 | } |
| 117 | 142 | ||
| 118 | static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) | 143 | static inline int __get_user_fn(void *x, const void __user *ptr, unsigned long size) |
| 119 | { | 144 | { |
| 120 | size = uaccess.copy_from_user(size, ptr, x); | 145 | size = __copy_from_user(x, ptr, size); |
| 121 | return size ? -EFAULT : size; | 146 | return size ? -EFAULT : 0; |
| 122 | } | 147 | } |
| 123 | 148 | ||
| 124 | /* | 149 | /* |
| @@ -135,8 +160,8 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) | |||
| 135 | case 2: \ | 160 | case 2: \ |
| 136 | case 4: \ | 161 | case 4: \ |
| 137 | case 8: \ | 162 | case 8: \ |
| 138 | __pu_err = __put_user_fn(sizeof (*(ptr)), \ | 163 | __pu_err = __put_user_fn(&__x, ptr, \ |
| 139 | ptr, &__x); \ | 164 | sizeof(*(ptr))); \ |
| 140 | break; \ | 165 | break; \ |
| 141 | default: \ | 166 | default: \ |
| 142 | __put_user_bad(); \ | 167 | __put_user_bad(); \ |
| @@ -152,7 +177,7 @@ static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) | |||
| 152 | }) | 177 | }) |
| 153 | 178 | ||
| 154 | 179 | ||
| 155 | extern int __put_user_bad(void) __attribute__((noreturn)); | 180 | int __put_user_bad(void) __attribute__((noreturn)); |
| 156 | 181 | ||
| 157 | #define __get_user(x, ptr) \ | 182 | #define __get_user(x, ptr) \ |
| 158 | ({ \ | 183 | ({ \ |
| @@ -161,29 +186,29 @@ extern int __put_user_bad(void) __attribute__((noreturn)); | |||
| 161 | switch (sizeof(*(ptr))) { \ | 186 | switch (sizeof(*(ptr))) { \ |
| 162 | case 1: { \ | 187 | case 1: { \ |
| 163 | unsigned char __x; \ | 188 | unsigned char __x; \ |
| 164 | __gu_err = __get_user_fn(sizeof (*(ptr)), \ | 189 | __gu_err = __get_user_fn(&__x, ptr, \ |
| 165 | ptr, &__x); \ | 190 | sizeof(*(ptr))); \ |
| 166 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ | 191 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ |
| 167 | break; \ | 192 | break; \ |
| 168 | }; \ | 193 | }; \ |
| 169 | case 2: { \ | 194 | case 2: { \ |
| 170 | unsigned short __x; \ | 195 | unsigned short __x; \ |
| 171 | __gu_err = __get_user_fn(sizeof (*(ptr)), \ | 196 | __gu_err = __get_user_fn(&__x, ptr, \ |
| 172 | ptr, &__x); \ | 197 | sizeof(*(ptr))); \ |
| 173 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ | 198 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ |
| 174 | break; \ | 199 | break; \ |
| 175 | }; \ | 200 | }; \ |
| 176 | case 4: { \ | 201 | case 4: { \ |
| 177 | unsigned int __x; \ | 202 | unsigned int __x; \ |
| 178 | __gu_err = __get_user_fn(sizeof (*(ptr)), \ | 203 | __gu_err = __get_user_fn(&__x, ptr, \ |
| 179 | ptr, &__x); \ | 204 | sizeof(*(ptr))); \ |
| 180 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ | 205 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ |
| 181 | break; \ | 206 | break; \ |
| 182 | }; \ | 207 | }; \ |
| 183 | case 8: { \ | 208 | case 8: { \ |
| 184 | unsigned long long __x; \ | 209 | unsigned long long __x; \ |
| 185 | __gu_err = __get_user_fn(sizeof (*(ptr)), \ | 210 | __gu_err = __get_user_fn(&__x, ptr, \ |
| 186 | ptr, &__x); \ | 211 | sizeof(*(ptr))); \ |
| 187 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ | 212 | (x) = *(__force __typeof__(*(ptr)) *) &__x; \ |
| 188 | break; \ | 213 | break; \ |
| 189 | }; \ | 214 | }; \ |
| @@ -200,35 +225,12 @@ extern int __put_user_bad(void) __attribute__((noreturn)); | |||
| 200 | __get_user(x, ptr); \ | 225 | __get_user(x, ptr); \ |
| 201 | }) | 226 | }) |
| 202 | 227 | ||
| 203 | extern int __get_user_bad(void) __attribute__((noreturn)); | 228 | int __get_user_bad(void) __attribute__((noreturn)); |
| 204 | 229 | ||
| 205 | #define __put_user_unaligned __put_user | 230 | #define __put_user_unaligned __put_user |
| 206 | #define __get_user_unaligned __get_user | 231 | #define __get_user_unaligned __get_user |
| 207 | 232 | ||
| 208 | /** | 233 | /** |
| 209 | * __copy_to_user: - Copy a block of data into user space, with less checking. | ||
| 210 | * @to: Destination address, in user space. | ||
| 211 | * @from: Source address, in kernel space. | ||
| 212 | * @n: Number of bytes to copy. | ||
| 213 | * | ||
| 214 | * Context: User context only. This function may sleep. | ||
| 215 | * | ||
| 216 | * Copy data from kernel space to user space. Caller must check | ||
| 217 | * the specified block with access_ok() before calling this function. | ||
| 218 | * | ||
| 219 | * Returns number of bytes that could not be copied. | ||
| 220 | * On success, this will be zero. | ||
| 221 | */ | ||
| 222 | static inline unsigned long __must_check | ||
| 223 | __copy_to_user(void __user *to, const void *from, unsigned long n) | ||
| 224 | { | ||
| 225 | return uaccess.copy_to_user(n, to, from); | ||
| 226 | } | ||
| 227 | |||
| 228 | #define __copy_to_user_inatomic __copy_to_user | ||
| 229 | #define __copy_from_user_inatomic __copy_from_user | ||
| 230 | |||
| 231 | /** | ||
| 232 | * copy_to_user: - Copy a block of data into user space. | 234 | * copy_to_user: - Copy a block of data into user space. |
| 233 | * @to: Destination address, in user space. | 235 | * @to: Destination address, in user space. |
| 234 | * @from: Source address, in kernel space. | 236 | * @from: Source address, in kernel space. |
| @@ -248,30 +250,7 @@ copy_to_user(void __user *to, const void *from, unsigned long n) | |||
| 248 | return __copy_to_user(to, from, n); | 250 | return __copy_to_user(to, from, n); |
| 249 | } | 251 | } |
| 250 | 252 | ||
| 251 | /** | 253 | void copy_from_user_overflow(void) |
| 252 | * __copy_from_user: - Copy a block of data from user space, with less checking. | ||
| 253 | * @to: Destination address, in kernel space. | ||
| 254 | * @from: Source address, in user space. | ||
| 255 | * @n: Number of bytes to copy. | ||
| 256 | * | ||
| 257 | * Context: User context only. This function may sleep. | ||
| 258 | * | ||
| 259 | * Copy data from user space to kernel space. Caller must check | ||
| 260 | * the specified block with access_ok() before calling this function. | ||
| 261 | * | ||
| 262 | * Returns number of bytes that could not be copied. | ||
| 263 | * On success, this will be zero. | ||
| 264 | * | ||
| 265 | * If some data could not be copied, this function will pad the copied | ||
| 266 | * data to the requested size using zero bytes. | ||
| 267 | */ | ||
| 268 | static inline unsigned long __must_check | ||
| 269 | __copy_from_user(void *to, const void __user *from, unsigned long n) | ||
| 270 | { | ||
| 271 | return uaccess.copy_from_user(n, from, to); | ||
| 272 | } | ||
| 273 | |||
| 274 | extern void copy_from_user_overflow(void) | ||
| 275 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS | 254 | #ifdef CONFIG_DEBUG_STRICT_USER_COPY_CHECKS |
| 276 | __compiletime_warning("copy_from_user() buffer size is not provably correct") | 255 | __compiletime_warning("copy_from_user() buffer size is not provably correct") |
| 277 | #endif | 256 | #endif |
| @@ -306,11 +285,8 @@ copy_from_user(void *to, const void __user *from, unsigned long n) | |||
| 306 | return __copy_from_user(to, from, n); | 285 | return __copy_from_user(to, from, n); |
| 307 | } | 286 | } |
| 308 | 287 | ||
| 309 | static inline unsigned long __must_check | 288 | unsigned long __must_check |
| 310 | __copy_in_user(void __user *to, const void __user *from, unsigned long n) | 289 | __copy_in_user(void __user *to, const void __user *from, unsigned long n); |
| 311 | { | ||
| 312 | return uaccess.copy_in_user(n, to, from); | ||
| 313 | } | ||
| 314 | 290 | ||
| 315 | static inline unsigned long __must_check | 291 | static inline unsigned long __must_check |
| 316 | copy_in_user(void __user *to, const void __user *from, unsigned long n) | 292 | copy_in_user(void __user *to, const void __user *from, unsigned long n) |
| @@ -322,18 +298,22 @@ copy_in_user(void __user *to, const void __user *from, unsigned long n) | |||
| 322 | /* | 298 | /* |
| 323 | * Copy a null terminated string from userspace. | 299 | * Copy a null terminated string from userspace. |
| 324 | */ | 300 | */ |
| 301 | |||
| 302 | long __strncpy_from_user(char *dst, const char __user *src, long count); | ||
| 303 | |||
| 325 | static inline long __must_check | 304 | static inline long __must_check |
| 326 | strncpy_from_user(char *dst, const char __user *src, long count) | 305 | strncpy_from_user(char *dst, const char __user *src, long count) |
| 327 | { | 306 | { |
| 328 | might_fault(); | 307 | might_fault(); |
| 329 | return uaccess.strncpy_from_user(count, src, dst); | 308 | return __strncpy_from_user(dst, src, count); |
| 330 | } | 309 | } |
| 331 | 310 | ||
| 332 | static inline unsigned long | 311 | unsigned long __must_check __strnlen_user(const char __user *src, unsigned long count); |
| 333 | strnlen_user(const char __user * src, unsigned long n) | 312 | |
| 313 | static inline unsigned long strnlen_user(const char __user *src, unsigned long n) | ||
| 334 | { | 314 | { |
| 335 | might_fault(); | 315 | might_fault(); |
| 336 | return uaccess.strnlen_user(n, src); | 316 | return __strnlen_user(src, n); |
| 337 | } | 317 | } |
| 338 | 318 | ||
| 339 | /** | 319 | /** |
| @@ -355,21 +335,14 @@ strnlen_user(const char __user * src, unsigned long n) | |||
| 355 | /* | 335 | /* |
| 356 | * Zero Userspace | 336 | * Zero Userspace |
| 357 | */ | 337 | */ |
| 338 | unsigned long __must_check __clear_user(void __user *to, unsigned long size); | ||
| 358 | 339 | ||
| 359 | static inline unsigned long __must_check | 340 | static inline unsigned long __must_check clear_user(void __user *to, unsigned long n) |
| 360 | __clear_user(void __user *to, unsigned long n) | ||
| 361 | { | ||
| 362 | return uaccess.clear_user(n, to); | ||
| 363 | } | ||
| 364 | |||
| 365 | static inline unsigned long __must_check | ||
| 366 | clear_user(void __user *to, unsigned long n) | ||
| 367 | { | 341 | { |
| 368 | might_fault(); | 342 | might_fault(); |
| 369 | return uaccess.clear_user(n, to); | 343 | return __clear_user(to, n); |
| 370 | } | 344 | } |
| 371 | 345 | ||
| 372 | extern int copy_to_user_real(void __user *dest, void *src, size_t count); | 346 | int copy_to_user_real(void __user *dest, void *src, unsigned long count); |
| 373 | extern int copy_from_user_real(void *dest, void __user *src, size_t count); | ||
| 374 | 347 | ||
| 375 | #endif /* __S390_UACCESS_H */ | 348 | #endif /* __S390_UACCESS_H */ |
