blob: 811cf16a65f999b0939e9aad42e6e0adff59f65f [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({ \
Mark Rutlande817a7f2017-05-03 16:09:35 +010096 unsigned long __addr = (unsigned long __force)(addr); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +000097 unsigned long flag, roksum; \
98 __chk_user_ptr(addr); \
Christopher Covington31b1e942014-03-19 16:29:37 +000099 asm("adds %1, %1, %3; ccmp %1, %4, #2, cc; cset %0, ls" \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000100 : "=&r" (flag), "=&r" (roksum) \
Mark Rutlande817a7f2017-05-03 16:09:35 +0100101 : "1" (__addr), "Ir" (size), \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000102 "r" (current_thread_info()->addr_limit) \
103 : "cc"); \
104 flag; \
105})
106
Andre Przywara87261d12016-10-19 14:40:54 +0100107/*
Kristina Martsenko1d61ccb2017-06-06 20:14:09 +0100108 * When dealing with data aborts, watchpoints, or instruction traps we may end
109 * up with a tagged userland pointer. Clear the tag to get a sane pointer to
110 * pass on to access_ok(), for instance.
Andre Przywara87261d12016-10-19 14:40:54 +0100111 */
112#define untagged_addr(addr) sign_extend64(addr, 55)
113
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000114#define access_ok(type, addr, size) __range_ok(addr, size)
Will Deacon12a0ef72013-11-06 17:20:22 +0000115#define user_addr_max get_fs
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000116
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100117#define _ASM_EXTABLE(from, to) \
118 " .pushsection __ex_table, \"a\"\n" \
119 " .align 3\n" \
120 " .long (" #from " - .), (" #to " - .)\n" \
121 " .popsection\n"
122
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000123/*
124 * The "__xxx" versions of the user access functions do not verify the address
125 * space - it must have been done previously with a separate "access_ok()"
126 * call.
127 *
128 * The "__xxx_error" versions set the third argument to -EFAULT if an error
129 * occurs, and leave it unchanged on success.
130 */
James Morse57f49592016-02-05 14:58:48 +0000131#define __get_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000132 asm volatile( \
James Morse57f49592016-02-05 14:58:48 +0000133 "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
134 alt_instr " " reg "1, [%2]\n", feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000135 "2:\n" \
136 " .section .fixup, \"ax\"\n" \
137 " .align 2\n" \
138 "3: mov %w0, %3\n" \
139 " mov %1, #0\n" \
140 " b 2b\n" \
141 " .previous\n" \
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100142 _ASM_EXTABLE(1b, 3b) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000143 : "+r" (err), "=&r" (x) \
144 : "r" (addr), "i" (-EFAULT))
145
146#define __get_user_err(x, ptr, err) \
147do { \
148 unsigned long __gu_val; \
149 __chk_user_ptr(ptr); \
James Morse70544192016-02-05 14:58:50 +0000150 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100151 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000152 switch (sizeof(*(ptr))) { \
153 case 1: \
James Morse57f49592016-02-05 14:58:48 +0000154 __get_user_asm("ldrb", "ldtrb", "%w", __gu_val, (ptr), \
155 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000156 break; \
157 case 2: \
James Morse57f49592016-02-05 14:58:48 +0000158 __get_user_asm("ldrh", "ldtrh", "%w", __gu_val, (ptr), \
159 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000160 break; \
161 case 4: \
James Morse57f49592016-02-05 14:58:48 +0000162 __get_user_asm("ldr", "ldtr", "%w", __gu_val, (ptr), \
163 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000164 break; \
165 case 8: \
James Morse57f49592016-02-05 14:58:48 +0000166 __get_user_asm("ldr", "ldtr", "%", __gu_val, (ptr), \
167 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000168 break; \
169 default: \
170 BUILD_BUG(); \
171 } \
Michael S. Tsirkin58fff512014-12-12 01:56:04 +0200172 (x) = (__force __typeof__(*(ptr)))__gu_val; \
James Morse70544192016-02-05 14:58:50 +0000173 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100174 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000175} while (0)
176
177#define __get_user(x, ptr) \
178({ \
179 int __gu_err = 0; \
180 __get_user_err((x), (ptr), __gu_err); \
181 __gu_err; \
182})
183
184#define __get_user_error(x, ptr, err) \
185({ \
186 __get_user_err((x), (ptr), (err)); \
187 (void)0; \
188})
189
190#define __get_user_unaligned __get_user
191
192#define get_user(x, ptr) \
193({ \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100194 __typeof__(*(ptr)) __user *__p = (ptr); \
Michael S. Tsirkin56d2ef72013-05-26 17:30:42 +0300195 might_fault(); \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100196 access_ok(VERIFY_READ, __p, sizeof(*__p)) ? \
197 __get_user((x), __p) : \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000198 ((x) = 0, -EFAULT); \
199})
200
James Morse57f49592016-02-05 14:58:48 +0000201#define __put_user_asm(instr, alt_instr, reg, x, addr, err, feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000202 asm volatile( \
James Morse57f49592016-02-05 14:58:48 +0000203 "1:"ALTERNATIVE(instr " " reg "1, [%2]\n", \
204 alt_instr " " reg "1, [%2]\n", feature) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000205 "2:\n" \
206 " .section .fixup,\"ax\"\n" \
207 " .align 2\n" \
208 "3: mov %w0, %3\n" \
209 " b 2b\n" \
210 " .previous\n" \
Ard Biesheuvel6c94f272016-01-01 15:02:12 +0100211 _ASM_EXTABLE(1b, 3b) \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000212 : "+r" (err) \
213 : "r" (x), "r" (addr), "i" (-EFAULT))
214
215#define __put_user_err(x, ptr, err) \
216do { \
217 __typeof__(*(ptr)) __pu_val = (x); \
218 __chk_user_ptr(ptr); \
James Morse70544192016-02-05 14:58:50 +0000219 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(0), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100220 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000221 switch (sizeof(*(ptr))) { \
222 case 1: \
James Morse57f49592016-02-05 14:58:48 +0000223 __put_user_asm("strb", "sttrb", "%w", __pu_val, (ptr), \
224 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000225 break; \
226 case 2: \
James Morse57f49592016-02-05 14:58:48 +0000227 __put_user_asm("strh", "sttrh", "%w", __pu_val, (ptr), \
228 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000229 break; \
230 case 4: \
James Morse57f49592016-02-05 14:58:48 +0000231 __put_user_asm("str", "sttr", "%w", __pu_val, (ptr), \
232 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000233 break; \
234 case 8: \
James Morse57f49592016-02-05 14:58:48 +0000235 __put_user_asm("str", "sttr", "%", __pu_val, (ptr), \
236 (err), ARM64_HAS_UAO); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000237 break; \
238 default: \
239 BUILD_BUG(); \
240 } \
James Morse70544192016-02-05 14:58:50 +0000241 asm(ALTERNATIVE("nop", SET_PSTATE_PAN(1), ARM64_ALT_PAN_NOT_UAO,\
James Morse338d4f42015-07-22 19:05:54 +0100242 CONFIG_ARM64_PAN)); \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000243} while (0)
244
245#define __put_user(x, ptr) \
246({ \
247 int __pu_err = 0; \
248 __put_user_err((x), (ptr), __pu_err); \
249 __pu_err; \
250})
251
252#define __put_user_error(x, ptr, err) \
253({ \
254 __put_user_err((x), (ptr), (err)); \
255 (void)0; \
256})
257
258#define __put_user_unaligned __put_user
259
260#define put_user(x, ptr) \
261({ \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100262 __typeof__(*(ptr)) __user *__p = (ptr); \
Michael S. Tsirkin56d2ef72013-05-26 17:30:42 +0300263 might_fault(); \
AKASHI Takahiro1f65c132013-09-24 10:00:50 +0100264 access_ok(VERIFY_WRITE, __p, sizeof(*__p)) ? \
265 __put_user((x), __p) : \
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000266 -EFAULT; \
267})
268
Yang Shibffe1baff2016-06-08 14:40:56 -0700269extern unsigned long __must_check __arch_copy_from_user(void *to, const void __user *from, unsigned long n);
270extern unsigned long __must_check __arch_copy_to_user(void __user *to, const void *from, unsigned long n);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000271extern unsigned long __must_check __copy_in_user(void __user *to, const void __user *from, unsigned long n);
272extern unsigned long __must_check __clear_user(void __user *addr, unsigned long n);
273
Yang Shibffe1baff2016-06-08 14:40:56 -0700274static inline unsigned long __must_check __copy_from_user(void *to, const void __user *from, unsigned long n)
275{
276 kasan_check_write(to, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700277 check_object_size(to, n, false);
278 return __arch_copy_from_user(to, from, n);
Yang Shibffe1baff2016-06-08 14:40:56 -0700279}
280
281static inline unsigned long __must_check __copy_to_user(void __user *to, const void *from, unsigned long n)
282{
283 kasan_check_read(from, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700284 check_object_size(from, n, true);
285 return __arch_copy_to_user(to, from, n);
Yang Shibffe1baff2016-06-08 14:40:56 -0700286}
287
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000288static inline unsigned long __must_check copy_from_user(void *to, const void __user *from, unsigned long n)
289{
Al Viro4855bd22016-09-10 16:50:00 -0400290 unsigned long res = n;
Yang Shibffe1baff2016-06-08 14:40:56 -0700291 kasan_check_write(to, n);
292
Kees Cookfaf5b632016-06-23 15:59:42 -0700293 if (access_ok(VERIFY_READ, from, n)) {
294 check_object_size(to, n, false);
Al Viro4855bd22016-09-10 16:50:00 -0400295 res = __arch_copy_from_user(to, from, n);
296 }
297 if (unlikely(res))
298 memset(to + (n - res), 0, res);
299 return res;
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000300}
301
302static inline unsigned long __must_check copy_to_user(void __user *to, const void *from, unsigned long n)
303{
Yang Shibffe1baff2016-06-08 14:40:56 -0700304 kasan_check_read(from, n);
305
Kees Cookfaf5b632016-06-23 15:59:42 -0700306 if (access_ok(VERIFY_WRITE, to, n)) {
307 check_object_size(from, n, true);
Yang Shibffe1baff2016-06-08 14:40:56 -0700308 n = __arch_copy_to_user(to, from, n);
Kees Cookfaf5b632016-06-23 15:59:42 -0700309 }
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000310 return n;
311}
312
313static inline unsigned long __must_check copy_in_user(void __user *to, const void __user *from, unsigned long n)
314{
315 if (access_ok(VERIFY_READ, from, n) && access_ok(VERIFY_WRITE, to, n))
316 n = __copy_in_user(to, from, n);
317 return n;
318}
319
320#define __copy_to_user_inatomic __copy_to_user
321#define __copy_from_user_inatomic __copy_from_user
322
323static inline unsigned long __must_check clear_user(void __user *to, unsigned long n)
324{
325 if (access_ok(VERIFY_WRITE, to, n))
326 n = __clear_user(to, n);
327 return n;
328}
329
Will Deacon12a0ef72013-11-06 17:20:22 +0000330extern long strncpy_from_user(char *dest, const char __user *src, long count);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000331
Will Deacon12a0ef72013-11-06 17:20:22 +0000332extern __must_check long strlen_user(const char __user *str);
333extern __must_check long strnlen_user(const char __user *str, long n);
Catalin Marinas0aea86a2012-03-05 11:49:32 +0000334
335#endif /* __ASM_UACCESS_H */