uaccess.h (5639B)
1/* SPDX-License-Identifier: GPL-2.0 */ 2#ifndef __ASM_GENERIC_UACCESS_H 3#define __ASM_GENERIC_UACCESS_H 4 5/* 6 * User space memory access functions, these should work 7 * on any machine that has kernel and user data in the same 8 * address space, e.g. all NOMMU machines. 9 */ 10#include <linux/string.h> 11#include <asm-generic/access_ok.h> 12 13#ifdef CONFIG_UACCESS_MEMCPY 14#include <asm/unaligned.h> 15 16static __always_inline int 17__get_user_fn(size_t size, const void __user *from, void *to) 18{ 19 BUILD_BUG_ON(!__builtin_constant_p(size)); 20 21 switch (size) { 22 case 1: 23 *(u8 *)to = *((u8 __force *)from); 24 return 0; 25 case 2: 26 *(u16 *)to = get_unaligned((u16 __force *)from); 27 return 0; 28 case 4: 29 *(u32 *)to = get_unaligned((u32 __force *)from); 30 return 0; 31 case 8: 32 *(u64 *)to = get_unaligned((u64 __force *)from); 33 return 0; 34 default: 35 BUILD_BUG(); 36 return 0; 37 } 38 39} 40#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 41 42static __always_inline int 43__put_user_fn(size_t size, void __user *to, void *from) 44{ 45 BUILD_BUG_ON(!__builtin_constant_p(size)); 46 47 switch (size) { 48 case 1: 49 *(u8 __force *)to = *(u8 *)from; 50 return 0; 51 case 2: 52 put_unaligned(*(u16 *)from, (u16 __force *)to); 53 return 0; 54 case 4: 55 put_unaligned(*(u32 *)from, (u32 __force *)to); 56 return 0; 57 case 8: 58 put_unaligned(*(u64 *)from, (u64 __force *)to); 59 return 0; 60 default: 61 BUILD_BUG(); 62 return 0; 63 } 64} 65#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 66 67#define __get_kernel_nofault(dst, src, type, err_label) \ 68do { \ 69 *((type *)dst) = get_unaligned((type *)(src)); \ 70 if (0) /* make sure the label looks used to the compiler */ \ 71 goto err_label; \ 72} while (0) 73 74#define __put_kernel_nofault(dst, src, type, err_label) \ 75do { \ 76 put_unaligned(*((type *)src), (type *)(dst)); \ 77 if (0) /* make sure the label looks used to the compiler */ \ 78 goto err_label; \ 79} while (0) 80 81static inline __must_check unsigned long 82raw_copy_from_user(void *to, const void __user * from, unsigned long n) 83{ 84 memcpy(to, (const void __force *)from, n); 85 return 0; 86} 87 88static inline __must_check unsigned long 89raw_copy_to_user(void __user *to, const void *from, unsigned long n) 90{ 91 memcpy((void __force *)to, from, n); 92 return 0; 93} 94#define INLINE_COPY_FROM_USER 95#define INLINE_COPY_TO_USER 96#endif /* CONFIG_UACCESS_MEMCPY */ 97 98/* 99 * These are the main single-value transfer routines. They automatically 100 * use the right size if we just have the right pointer type. 101 * This version just falls back to copy_{from,to}_user, which should 102 * provide a fast-path for small values. 103 */ 104#define __put_user(x, ptr) \ 105({ \ 106 __typeof__(*(ptr)) __x = (x); \ 107 int __pu_err = -EFAULT; \ 108 __chk_user_ptr(ptr); \ 109 switch (sizeof (*(ptr))) { \ 110 case 1: \ 111 case 2: \ 112 case 4: \ 113 case 8: \ 114 __pu_err = __put_user_fn(sizeof (*(ptr)), \ 115 ptr, &__x); \ 116 break; \ 117 default: \ 118 __put_user_bad(); \ 119 break; \ 120 } \ 121 __pu_err; \ 122}) 123 124#define put_user(x, ptr) \ 125({ \ 126 void __user *__p = (ptr); \ 127 might_fault(); \ 128 access_ok(__p, sizeof(*ptr)) ? \ 129 __put_user((x), ((__typeof__(*(ptr)) __user *)__p)) : \ 130 -EFAULT; \ 131}) 132 133#ifndef __put_user_fn 134 135static inline int __put_user_fn(size_t size, void __user *ptr, void *x) 136{ 137 return unlikely(raw_copy_to_user(ptr, x, size)) ? -EFAULT : 0; 138} 139 140#define __put_user_fn(sz, u, k) __put_user_fn(sz, u, k) 141 142#endif 143 144extern int __put_user_bad(void) __attribute__((noreturn)); 145 146#define __get_user(x, ptr) \ 147({ \ 148 int __gu_err = -EFAULT; \ 149 __chk_user_ptr(ptr); \ 150 switch (sizeof(*(ptr))) { \ 151 case 1: { \ 152 unsigned char __x = 0; \ 153 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 154 ptr, &__x); \ 155 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 156 break; \ 157 }; \ 158 case 2: { \ 159 unsigned short __x = 0; \ 160 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 161 ptr, &__x); \ 162 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 163 break; \ 164 }; \ 165 case 4: { \ 166 unsigned int __x = 0; \ 167 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 168 ptr, &__x); \ 169 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 170 break; \ 171 }; \ 172 case 8: { \ 173 unsigned long long __x = 0; \ 174 __gu_err = __get_user_fn(sizeof (*(ptr)), \ 175 ptr, &__x); \ 176 (x) = *(__force __typeof__(*(ptr)) *) &__x; \ 177 break; \ 178 }; \ 179 default: \ 180 __get_user_bad(); \ 181 break; \ 182 } \ 183 __gu_err; \ 184}) 185 186#define get_user(x, ptr) \ 187({ \ 188 const void __user *__p = (ptr); \ 189 might_fault(); \ 190 access_ok(__p, sizeof(*ptr)) ? \ 191 __get_user((x), (__typeof__(*(ptr)) __user *)__p) :\ 192 ((x) = (__typeof__(*(ptr)))0,-EFAULT); \ 193}) 194 195#ifndef __get_user_fn 196static inline int __get_user_fn(size_t size, const void __user *ptr, void *x) 197{ 198 return unlikely(raw_copy_from_user(x, ptr, size)) ? -EFAULT : 0; 199} 200 201#define __get_user_fn(sz, u, k) __get_user_fn(sz, u, k) 202 203#endif 204 205extern int __get_user_bad(void) __attribute__((noreturn)); 206 207/* 208 * Zero Userspace 209 */ 210#ifndef __clear_user 211static inline __must_check unsigned long 212__clear_user(void __user *to, unsigned long n) 213{ 214 memset((void __force *)to, 0, n); 215 return 0; 216} 217#endif 218 219static inline __must_check unsigned long 220clear_user(void __user *to, unsigned long n) 221{ 222 might_fault(); 223 if (!access_ok(to, n)) 224 return n; 225 226 return __clear_user(to, n); 227} 228 229#include <asm/extable.h> 230 231__must_check long strncpy_from_user(char *dst, const char __user *src, 232 long count); 233__must_check long strnlen_user(const char __user *src, long n); 234 235#endif /* __ASM_GENERIC_UACCESS_H */