blob: 55d0adbf65098a78241d45038d1a57f642a7992e [file] [log] [blame]
Catalin Marinas0aea86a2012-03-05 11:49:32 +00001/*
2 * Based on arch/arm/include/asm/uaccess.h
3 *
4 * Copyright (C) 2012 ARM Ltd.
5 *
6 * This program is free software; you can redistribute it and/or modify
7 * it under the terms of the GNU General Public License version 2 as
8 * published by the Free Software Foundation.
9 *
10 * This program is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
13 * GNU General Public License for more details.
14 *
15 * You should have received a copy of the GNU General Public License
16 * along with this program. If not, see <http://www.gnu.org/licenses/>.
17 */
18#ifndef __ASM_UACCESS_H
19#define __ASM_UACCESS_H
20
21/*
22 * User space memory access functions
23 */
Andre Przywara87261d12016-10-19 14:40:54 +010024#include <linux/bitops.h>
Yang Shibffe1baff2016-06-08 14:40:56 -070025#include <linux/kasan-checks.h>
Catalin Marinas0aea86a2012-03-05 11:49:32 +000026#include <linux/string.h>
27#include <linux/thread_info.h>
28
James Morse338d4f42015-07-22 19:05:54 +010029#include <asm/alternative.h>
30#include <asm/cpufeature.h>
Catalin Marinas0aea86a2012-03-05 11:49:32 +000031#include <asm/ptrace.h>
James Morse338d4f42015-07-22 19:05:54 +010032#include <asm/sysreg.h>
Catalin Marinas0aea86a2012-03-05 11:49:32 +000033#include <asm/errno.h>
34#include <asm/memory.h>
35#include <asm/compiler.h>
36
37#define VERIFY_READ 0
38#define VERIFY_WRITE 1
39
40/*
Ard Biesheuvel6c94f272016-01-01 15:02:12 +010041 * The exception table consists of pairs of relative offsets: the first
42 * is the relative offset to an instruction that is allowed to fault,
43 * and the second is the relative offset at which the program should
44 * continue. No registers are modified, so it is entirely up to the
45 * continuation code to figure out what to do.
Catalin Marinas0aea86a2012-03-05 11:49:32 +000046 *
47 * All the routines below use bits of fixup code that are out of line
48 * with the main instruction path. This means when everything is well,
49 * we don't even have to jump over them. Further, they do not intrude
50 * on our cache or tlb entries.
51 */
52
53struct exception_table_entry
54{
Ard Biesheuvel6c94f272016-01-01 15:02:12 +010055 int insn, fixup;
Catalin Marinas0aea86a2012-03-05 11:49:32 +000056};
57
Ard Biesheuvel6c94f272016-01-01 15:02:12 +010058#define ARCH_HAS_RELATIVE_EXTABLE
59
Catalin Marinas0aea86a2012-03-05 11:49:32 +000060extern int fixup_exception(struct pt_regs *regs);
61
62#define KERNEL_DS (-1UL)
63#define get_ds() (KERNEL_DS)
64
65#define USER_DS TASK_SIZE_64
66#define get_fs() (current_thread_info()->addr_limit)
67
68static inline void set_fs(mm_segment_t fs)
69{
70 current_thread_info()->addr_limit = fs;
James Morse57f49592016-02-05 14:58:48 +000071
72 /*
73 * Enable/disable UAO so that copy_to_user() etc can access
74 * kernel memory with the unprivileged instructions.
75 */
76 if (IS_ENABLED(CONFIG_ARM64_UAO) && fs == KERNEL_DS)
77 asm(ALTERNATIVE("nop", SET_PSTATE_UAO(1), ARM64_HAS_UAO));
78 else
79 asm(ALTERNATIVE("nop", SET_PSTATE_UAO(0), ARM64_HAS_UAO,
80 CONFIG_ARM64_UAO));
Catalin Marinas0aea86a2012-03-05 11:49:32 +000081}
82
Michael S. Tsirkin967f0e52015-01-06 15:11:13 +020083#define segment_eq(a, b) ((a) == (b))
Catalin Marinas0aea86a2012-03-05 11:49:32 +000084
85/*
Catalin Marinas0aea86a2012-03-05 11:49:32 +000086 * Test whether a block of memory is a valid user space address.
87 * Returns 1 if the range is valid, 0 otherwise.
88 *
89 * This is equivalent to the following test:
Christopher Covington31b1e942014-03-19 16:29:37 +000090 * (u65)addr + (u65)size <= current->addr_limit
Catalin Marinas0aea86a2012-03-05 11:49:32 +000091 *
92 * This needs 65-bit arithmetic.
93 */
94#define __range_ok(addr, size) \
95({ \
96 unsigned long flag, roksum; \
97 __chk_user_ptr(addr); \
Christopher Covington31b1e942014-03-19 16:29:37 +000098 asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \
Catalin Marinas0aea86a2012-03-05 11:49:32 +000099 : "=&r" (flag), "=&r" (roksum) \
100 : "1" (addr), "Ir" (size), \
101 "r" (current_thread_info()->addr_limit) \
102 : "cc"); \
103 flag; \
104})
105
Andre Przywara87261d12016-10-19 14:40:54 +0100106/*
107 * When dealing with data aborts or instruction traps we may end up with
108 * a tagged userland pointer. Clear the tag to get a sane pointer to pass
109 * on to access_ok(), for instance.
110 */
111#define untagged_addr(addr) sign_extend64(addr, 55)
112
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000113#define access_ok(type, addr, size) __range_ok(addr, size)
Will Deacon12a0ef72013-11-06 17:20:22 +0000114#define user_addr_max get_fs
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000115
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100116#define _ASM_EXTABLE(from, to) \
117 " .pushsection __ex_table, \"a\"\n" \
118 " .align 3\n" \
119 " .long (" #from " - .), (" #to " - .)\n" \
120 " .popsection\n"
121
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000122/*
123 * The "__xxx" versions of the user access functions do not verify the address
124 * space - it must have been done previously with a separate "access_ok()"
125 * call.
126 *
127 * The "__xxx_error" versions set the third argument to -EFAULT if an error
128 * occurs, and leave it unchanged on success.
129 */
James Morse57f49592016-02-05 14:58:48 +0000130#define __get_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000131 asm volatile( \
James Morse57f49592016-02-05 14:58:48 +0000132 "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
133 alt_instr " " reg "1, [%2]\n", feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000134 "2:\n" \
135 " .section .fixup, \"ax\"\n" \
136 " .align 2\n" \
137 "3: mov %w0, %3\n" \
138 " mov %1, #0\n" \
139 " b 2b\n" \
140 " .previous\n" \
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100141 _ASM_EXTABLE(1b, 3b) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000142 : "+r" (err), "=&r" (x) \
143 : "r" (addr), "i" (-EFAULT))
144
145#define __get_user_err(x, ptr, err) \
146do { \
147 unsigned long __gu_val; \
148 __chk_user_ptr(ptr); \
James Morse70544192016-02-05 14:58:50 +0000149 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100150 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000151 switch (sizeof(*(ptr))) { \
152 case 1: \
James Morse57f49592016-02-05 14:58:48 +0000153 __get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr), \
154 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000155 break; \
156 case 2: \
James Morse57f49592016-02-05 14:58:48 +0000157 __get_user_asm("ldrh", "ldtrh", "%w", __gu_val, (ptr), \
158 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000159 break; \
160 case 4: \
James Morse57f49592016-02-05 14:58:48 +0000161 __get_user_asm("ldr", "ldtr", "%w", __gu_val, (ptr), \
162 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000163 break; \
164 case 8: \
James Morse57f49592016-02-05 14:58:48 +0000165 __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \
166 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000167 break; \
168 default: \
169 BUILD_BUG(); \
170 } \
Michael S. Tsirkin58fff512014-12-12 01:56:04 +0200171 (x) = (__force __typeof__(*(ptr)))__gu_val; \
James Morse70544192016-02-05 14:58:50 +0000172 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100173 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000174} while (0)
175
176#define __get_user(x, ptr) \
177({ \
178 int __gu_err = 0; \
179 __get_user_err((x), (ptr), __gu_err); \
180 __gu_err; \
181})
182
183#define __get_user_error(x, ptr, err) \
184({ \
185 __get_user_err((x), (ptr), (err)); \
186 (void)0; \
187})
188
189#define __get_user_unaligned __get_user
190
191#define get_user(x, ptr) \
192({ \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100193 __typeof__(*(ptr)) __user *__p = (ptr); \
Michael S. Tsirkin56d2ef72013-05-26 17:30:42 +0300194 might_fault(); \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100195 access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \
196 __get_user((x), __p) : \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000197 ((x) = 0, -EFAULT); \
198})
199
James Morse57f49592016-02-05 14:58:48 +0000200#define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000201 asm volatile( \
James Morse57f49592016-02-05 14:58:48 +0000202 "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
203 alt_instr " " reg "1, [%2]\n", feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000204 "2:\n" \
205 " .section .fixup,\"ax\"\n" \
206 " .align 2\n" \
207 "3: mov %w0, %3\n" \
208 " b 2b\n" \
209 " .previous\n" \
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100210 _ASM_EXTABLE(1b, 3b) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000211 : "+r" (err) \
212 : "r" (x), "r" (addr), "i" (-EFAULT))
213
214#define __put_user_err(x, ptr, err) \
215do { \
216 __typeof__(*(ptr)) __pu_val = (x); \
217 __chk_user_ptr(ptr); \
James Morse70544192016-02-05 14:58:50 +0000218 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100219 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000220 switch (sizeof(*(ptr))) { \
221 case 1: \
James Morse57f49592016-02-05 14:58:48 +0000222 __put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr), \
223 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000224 break; \
225 case 2: \
James Morse57f49592016-02-05 14:58:48 +0000226 __put_user_asm("strh", "sttrh", "%w", __pu_val, (ptr), \
227 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000228 break; \
229 case 4: \
James Morse57f49592016-02-05 14:58:48 +0000230 __put_user_asm("str", "sttr", "%w", __pu_val, (ptr), \
231 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000232 break; \
233 case 8: \
James Morse57f49592016-02-05 14:58:48 +0000234 __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \
235 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000236 break; \
237 default: \
238 BUILD_BUG(); \
239 } \
James Morse70544192016-02-05 14:58:50 +0000240 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100241 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000242} while (0)
243
244#define __put_user(x, ptr) \
245({ \
246 int __pu_err = 0; \
247 __put_user_err((x), (ptr), __pu_err); \
248 __pu_err; \
249})
250
251#define __put_user_error(x, ptr, err) \
252({ \
253 __put_user_err((x), (ptr), (err)); \
254 (void)0; \
255})
256
257#define __put_user_unaligned __put_user
258
259#define put_user(x, ptr) \
260({ \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100261 __typeof__(*(ptr)) __user *__p = (ptr); \
Michael S. Tsirkin56d2ef72013-05-26 17:30:42 +0300262 might_fault(); \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100263 access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \
264 __put_user((x), __p) : \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000265 -EFAULT; \
266})
267
Yang Shibffe1baff2016-06-08 14:40:56 -0700268extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
269extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000270extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
271extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
272
Yang Shibffe1baff2016-06-08 14:40:56 -0700273static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
274{
275 kasan_check_write(to, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700276 check_object_size(to, n, false);
277 return __arch_copy_from_user(to, from, n);
Yang Shibffe1baff2016-06-08 14:40:56 -0700278}
279
280static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
281{
282 kasan_check_read(from, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700283 check_object_size(from, n, true);
284 return __arch_copy_to_user(to, from, n);
Yang Shibffe1baff2016-06-08 14:40:56 -0700285}
286
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000287static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
288{
Al Viro4855bd22016-09-10 16:50:00 -0400289 unsigned long res = n;
Yang Shibffe1baff2016-06-08 14:40:56 -0700290 kasan_check_write(to, n);
291
Kees Cookfaf5b632016-06-23 15:59:42 -0700292 if (access_ok(VERIFY_READ, from, n)) {
293 check_object_size(to, n, false);
Al Viro4855bd22016-09-10 16:50:00 -0400294 res = __arch_copy_from_user(to, from, n);
295 }
296 if (unlikely(res))
297 memset(to + (n - res), 0, res);
298 return res;
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000299}
300
301static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
302{
Yang Shibffe1baff2016-06-08 14:40:56 -0700303 kasan_check_read(from, n);
304
Kees Cookfaf5b632016-06-23 15:59:42 -0700305 if (access_ok(VERIFY_WRITE, to, n)) {
306 check_object_size(from, n, true);
Yang Shibffe1baff2016-06-08 14:40:56 -0700307 n = __arch_copy_to_user(to, from, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700308 }
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000309 return n;
310}
311
312static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n)
313{
314 if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))
315 n = __copy_in_user(to, from, n);
316 return n;
317}
318
319#define __copy_to_user_inatomic __copy_to_user
320#define __copy_from_user_inatomic __copy_from_user
321
322static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
323{
324 if (access_ok(VERIFY_WRITE, to, n))
325 n = __clear_user(to, n);
326 return n;
327}
328
Will Deacon12a0ef72013-11-06 17:20:22 +0000329extern long strncpy_from_user(char *dest, const char __user *src, long count);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000330
Will Deacon12a0ef72013-11-06 17:20:22 +0000331extern __must_check long strlen_user(const char __user *str);
332extern __must_check long strnlen_user(const char __user *str, long n);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000333
334#endif /* __ASM_UACCESS_H */