.. | .. |
---|
| 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 | } |
---|