| .. | .. |
|---|
| 1 | +/* SPDX-License-Identifier: GPL-2.0 */ |
|---|
| 1 | 2 | /* |
|---|
| 2 | 3 | * Copyright (C) 2008-2009 Michal Simek <monstr@monstr.eu> |
|---|
| 3 | 4 | * Copyright (C) 2008-2009 PetaLogix |
|---|
| 4 | 5 | * Copyright (C) 2006 Atmark Techno, Inc. |
|---|
| 5 | | - * |
|---|
| 6 | | - * This file is subject to the terms and conditions of the GNU General Public |
|---|
| 7 | | - * License. See the file "COPYING" in the main directory of this archive |
|---|
| 8 | | - * for more details. |
|---|
| 9 | 6 | */ |
|---|
| 10 | 7 | |
|---|
| 11 | 8 | #ifndef _ASM_MICROBLAZE_UACCESS_H |
|---|
| 12 | 9 | #define _ASM_MICROBLAZE_UACCESS_H |
|---|
| 13 | 10 | |
|---|
| 14 | 11 | #include <linux/kernel.h> |
|---|
| 15 | | -#include <linux/mm.h> |
|---|
| 16 | 12 | |
|---|
| 17 | 13 | #include <asm/mmu.h> |
|---|
| 18 | 14 | #include <asm/page.h> |
|---|
| 19 | | -#include <asm/pgtable.h> |
|---|
| 15 | +#include <linux/pgtable.h> |
|---|
| 20 | 16 | #include <asm/extable.h> |
|---|
| 21 | 17 | #include <linux/string.h> |
|---|
| 22 | 18 | |
|---|
| .. | .. |
|---|
| 42 | 38 | # define USER_DS MAKE_MM_SEG(TASK_SIZE - 1) |
|---|
| 43 | 39 | # endif |
|---|
| 44 | 40 | |
|---|
| 45 | | -# define get_ds() (KERNEL_DS) |
|---|
| 46 | 41 | # define get_fs() (current_thread_info()->addr_limit) |
|---|
| 47 | 42 | # define set_fs(val) (current_thread_info()->addr_limit = (val)) |
|---|
| 48 | 43 | |
|---|
| 49 | | -# define segment_eq(a, b) ((a).seg == (b).seg) |
|---|
| 44 | +# define uaccess_kernel() (get_fs().seg == KERNEL_DS.seg) |
|---|
| 50 | 45 | |
|---|
| 51 | 46 | #ifndef CONFIG_MMU |
|---|
| 52 | 47 | |
|---|
| .. | .. |
|---|
| 60 | 55 | #define __range_ok(addr, size) \ |
|---|
| 61 | 56 | ___range_ok((unsigned long)(addr), (unsigned long)(size)) |
|---|
| 62 | 57 | |
|---|
| 63 | | -#define access_ok(type, addr, size) (__range_ok((addr), (size)) == 0) |
|---|
| 58 | +#define access_ok(addr, size) (__range_ok((addr), (size)) == 0) |
|---|
| 64 | 59 | |
|---|
| 65 | 60 | #else |
|---|
| 66 | 61 | |
|---|
| 67 | | -static inline int access_ok(int type, const void __user *addr, |
|---|
| 68 | | - unsigned long size) |
|---|
| 62 | +static inline int access_ok(const void __user *addr, unsigned long size) |
|---|
| 69 | 63 | { |
|---|
| 70 | 64 | if (!size) |
|---|
| 71 | 65 | goto ok; |
|---|
| 72 | 66 | |
|---|
| 73 | 67 | if ((get_fs().seg < ((unsigned long)addr)) || |
|---|
| 74 | 68 | (get_fs().seg < ((unsigned long)addr + size - 1))) { |
|---|
| 75 | | - pr_devel("ACCESS fail: %s at 0x%08x (size 0x%x), seg 0x%08x\n", |
|---|
| 76 | | - type ? "WRITE" : "READ ", (__force u32)addr, (u32)size, |
|---|
| 69 | + pr_devel("ACCESS fail at 0x%08x (size 0x%x), seg 0x%08x\n", |
|---|
| 70 | + (__force u32)addr, (u32)size, |
|---|
| 77 | 71 | (u32)get_fs().seg); |
|---|
| 78 | 72 | return 0; |
|---|
| 79 | 73 | } |
|---|
| 80 | 74 | ok: |
|---|
| 81 | | - pr_devel("ACCESS OK: %s at 0x%08x (size 0x%x), seg 0x%08x\n", |
|---|
| 82 | | - type ? "WRITE" : "READ ", (__force u32)addr, (u32)size, |
|---|
| 75 | + pr_devel("ACCESS OK at 0x%08x (size 0x%x), seg 0x%08x\n", |
|---|
| 76 | + (__force u32)addr, (u32)size, |
|---|
| 83 | 77 | (u32)get_fs().seg); |
|---|
| 84 | 78 | return 1; |
|---|
| 85 | 79 | } |
|---|
| .. | .. |
|---|
| 120 | 114 | unsigned long n) |
|---|
| 121 | 115 | { |
|---|
| 122 | 116 | might_fault(); |
|---|
| 123 | | - if (unlikely(!access_ok(VERIFY_WRITE, to, n))) |
|---|
| 117 | + if (unlikely(!access_ok(to, n))) |
|---|
| 124 | 118 | return n; |
|---|
| 125 | 119 | |
|---|
| 126 | 120 | return __clear_user(to, n); |
|---|
| .. | .. |
|---|
| 165 | 159 | * Returns zero on success, or -EFAULT on error. |
|---|
| 166 | 160 | * On error, the variable @x is set to zero. |
|---|
| 167 | 161 | */ |
|---|
| 168 | | -#define get_user(x, ptr) \ |
|---|
| 169 | | - __get_user_check((x), (ptr), sizeof(*(ptr))) |
|---|
| 170 | | - |
|---|
| 171 | | -#define __get_user_check(x, ptr, size) \ |
|---|
| 172 | | -({ \ |
|---|
| 173 | | - unsigned long __gu_val = 0; \ |
|---|
| 174 | | - const typeof(*(ptr)) __user *__gu_addr = (ptr); \ |
|---|
| 175 | | - int __gu_err = 0; \ |
|---|
| 176 | | - \ |
|---|
| 177 | | - if (access_ok(VERIFY_READ, __gu_addr, size)) { \ |
|---|
| 178 | | - switch (size) { \ |
|---|
| 179 | | - case 1: \ |
|---|
| 180 | | - __get_user_asm("lbu", __gu_addr, __gu_val, \ |
|---|
| 181 | | - __gu_err); \ |
|---|
| 182 | | - break; \ |
|---|
| 183 | | - case 2: \ |
|---|
| 184 | | - __get_user_asm("lhu", __gu_addr, __gu_val, \ |
|---|
| 185 | | - __gu_err); \ |
|---|
| 186 | | - break; \ |
|---|
| 187 | | - case 4: \ |
|---|
| 188 | | - __get_user_asm("lw", __gu_addr, __gu_val, \ |
|---|
| 189 | | - __gu_err); \ |
|---|
| 190 | | - break; \ |
|---|
| 191 | | - default: \ |
|---|
| 192 | | - __gu_err = __user_bad(); \ |
|---|
| 193 | | - break; \ |
|---|
| 194 | | - } \ |
|---|
| 195 | | - } else { \ |
|---|
| 196 | | - __gu_err = -EFAULT; \ |
|---|
| 197 | | - } \ |
|---|
| 198 | | - x = (__force typeof(*(ptr)))__gu_val; \ |
|---|
| 199 | | - __gu_err; \ |
|---|
| 162 | +#define get_user(x, ptr) ({ \ |
|---|
| 163 | + const typeof(*(ptr)) __user *__gu_ptr = (ptr); \ |
|---|
| 164 | + access_ok(__gu_ptr, sizeof(*__gu_ptr)) ? \ |
|---|
| 165 | + __get_user(x, __gu_ptr) : -EFAULT; \ |
|---|
| 200 | 166 | }) |
|---|
| 201 | 167 | |
|---|
| 202 | 168 | #define __get_user(x, ptr) \ |
|---|
| 203 | 169 | ({ \ |
|---|
| 204 | | - unsigned long __gu_val = 0; \ |
|---|
| 205 | | - /*unsigned long __gu_ptr = (unsigned long)(ptr);*/ \ |
|---|
| 206 | 170 | long __gu_err; \ |
|---|
| 207 | 171 | switch (sizeof(*(ptr))) { \ |
|---|
| 208 | 172 | case 1: \ |
|---|
| 209 | | - __get_user_asm("lbu", (ptr), __gu_val, __gu_err); \ |
|---|
| 173 | + __get_user_asm("lbu", (ptr), x, __gu_err); \ |
|---|
| 210 | 174 | break; \ |
|---|
| 211 | 175 | case 2: \ |
|---|
| 212 | | - __get_user_asm("lhu", (ptr), __gu_val, __gu_err); \ |
|---|
| 176 | + __get_user_asm("lhu", (ptr), x, __gu_err); \ |
|---|
| 213 | 177 | break; \ |
|---|
| 214 | 178 | case 4: \ |
|---|
| 215 | | - __get_user_asm("lw", (ptr), __gu_val, __gu_err); \ |
|---|
| 179 | + __get_user_asm("lw", (ptr), x, __gu_err); \ |
|---|
| 216 | 180 | break; \ |
|---|
| 181 | + case 8: { \ |
|---|
| 182 | + __u64 __x = 0; \ |
|---|
| 183 | + __gu_err = raw_copy_from_user(&__x, ptr, 8) ? \ |
|---|
| 184 | + -EFAULT : 0; \ |
|---|
| 185 | + (x) = (typeof(x))(typeof((x) - (x)))__x; \ |
|---|
| 186 | + break; \ |
|---|
| 187 | + } \ |
|---|
| 217 | 188 | default: \ |
|---|
| 218 | 189 | /* __gu_val = 0; __gu_err = -EINVAL;*/ __gu_err = __user_bad();\ |
|---|
| 219 | 190 | } \ |
|---|
| 220 | | - x = (__force __typeof__(*(ptr))) __gu_val; \ |
|---|
| 221 | 191 | __gu_err; \ |
|---|
| 222 | 192 | }) |
|---|
| 223 | 193 | |
|---|
| .. | .. |
|---|
| 286 | 256 | typeof(*(ptr)) __user *__pu_addr = (ptr); \ |
|---|
| 287 | 257 | int __pu_err = 0; \ |
|---|
| 288 | 258 | \ |
|---|
| 289 | | - if (access_ok(VERIFY_WRITE, __pu_addr, size)) { \ |
|---|
| 259 | + if (access_ok(__pu_addr, size)) { \ |
|---|
| 290 | 260 | switch (size) { \ |
|---|
| 291 | 261 | case 1: \ |
|---|
| 292 | 262 | __put_user_asm("sb", __pu_addr, __pu_val, \ |
|---|
| .. | .. |
|---|
| 358 | 328 | static inline long |
|---|
| 359 | 329 | strncpy_from_user(char *dst, const char __user *src, long count) |
|---|
| 360 | 330 | { |
|---|
| 361 | | - if (!access_ok(VERIFY_READ, src, 1)) |
|---|
| 331 | + if (!access_ok(src, 1)) |
|---|
| 362 | 332 | return -EFAULT; |
|---|
| 363 | 333 | return __strncpy_user(dst, src, count); |
|---|
| 364 | 334 | } |
|---|
| .. | .. |
|---|
| 372 | 342 | |
|---|
| 373 | 343 | static inline long strnlen_user(const char __user *src, long n) |
|---|
| 374 | 344 | { |
|---|
| 375 | | - if (!access_ok(VERIFY_READ, src, 1)) |
|---|
| 345 | + if (!access_ok(src, 1)) |
|---|
| 376 | 346 | return 0; |
|---|
| 377 | 347 | return __strnlen_user(src, n); |
|---|
| 378 | 348 | } |
|---|