1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright (C) 2018 Hangzhou C-SKY Microsystems co.,ltd. 3 4 #include <linux/uaccess.h> 5 #include <linux/types.h> 6 7 unsigned long raw_copy_from_user(void *to, const void *from, 8 unsigned long n) 9 { 10 if (access_ok(from, n)) 11 __copy_user_zeroing(to, from, n); 12 else 13 memset(to, 0, n); 14 return n; 15 } 16 EXPORT_SYMBOL(raw_copy_from_user); 17 18 unsigned long raw_copy_to_user(void *to, const void *from, 19 unsigned long n) 20 { 21 if (access_ok(to, n)) 22 __copy_user(to, from, n); 23 return n; 24 } 25 EXPORT_SYMBOL(raw_copy_to_user); 26 27 28 /* 29 * copy a null terminated string from userspace. 30 */ 31 #define __do_strncpy_from_user(dst, src, count, res) \ 32 do { \ 33 int tmp; \ 34 long faultres; \ 35 asm volatile( \ 36 " cmpnei %3, 0 \n" \ 37 " bf 4f \n" \ 38 "1: cmpnei %1, 0 \n" \ 39 " bf 5f \n" \ 40 "2: ldb %4, (%3, 0) \n" \ 41 " stb %4, (%2, 0) \n" \ 42 " cmpnei %4, 0 \n" \ 43 " bf 3f \n" \ 44 " addi %3, 1 \n" \ 45 " addi %2, 1 \n" \ 46 " subi %1, 1 \n" \ 47 " br 1b \n" \ 48 "3: subu %0, %1 \n" \ 49 " br 5f \n" \ 50 "4: mov %0, %5 \n" \ 51 " br 5f \n" \ 52 ".section __ex_table, \"a\" \n" \ 53 ".align 2 \n" \ 54 ".long 2b, 4b \n" \ 55 ".previous \n" \ 56 "5: \n" \ 57 : "=r"(res), "=r"(count), "=r"(dst), \ 58 "=r"(src), "=r"(tmp), "=r"(faultres) \ 59 : "5"(-EFAULT), "0"(count), "1"(count), \ 60 "2"(dst), "3"(src) \ 61 : "memory", "cc"); \ 62 } while (0) 63 64 /* 65 * __strncpy_from_user: - Copy a NUL terminated string from userspace, 66 * with less checking. 67 * @dst: Destination address, in kernel space. This buffer must be at 68 * least @count bytes long. 69 * @src: Source address, in user space. 70 * @count: Maximum number of bytes to copy, including the trailing NUL. 71 * 72 * Copies a NUL-terminated string from userspace to kernel space. 73 * Caller must check the specified block with access_ok() before calling 74 * this function. 75 * 76 * On success, returns the length of the string (not including the trailing 77 * NUL). 78 * 79 * If access to userspace fails, returns -EFAULT (some data may have been 80 * copied). 81 * 82 * If @count is smaller than the length of the string, copies @count bytes 83 * and returns @count. 84 */ 85 long __strncpy_from_user(char *dst, const char *src, long count) 86 { 87 long res; 88 89 __do_strncpy_from_user(dst, src, count, res); 90 return res; 91 } 92 EXPORT_SYMBOL(__strncpy_from_user); 93 94 /* 95 * strncpy_from_user: - Copy a NUL terminated string from userspace. 96 * @dst: Destination address, in kernel space. This buffer must be at 97 * least @count bytes long. 98 * @src: Source address, in user space. 99 * @count: Maximum number of bytes to copy, including the trailing NUL. 100 * 101 * Copies a NUL-terminated string from userspace to kernel space. 102 * 103 * On success, returns the length of the string (not including the trailing 104 * NUL). 105 * 106 * If access to userspace fails, returns -EFAULT (some data may have been 107 * copied). 108 * 109 * If @count is smaller than the length of the string, copies @count bytes 110 * and returns @count. 111 */ 112 long strncpy_from_user(char *dst, const char *src, long count) 113 { 114 long res = -EFAULT; 115 116 if (access_ok(src, 1)) 117 __do_strncpy_from_user(dst, src, count, res); 118 return res; 119 } 120 EXPORT_SYMBOL(strncpy_from_user); 121 122 /* 123 * strlen_user: - Get the size of a string in user space. 124 * @str: The string to measure. 125 * @n: The maximum valid length 126 * 127 * Get the size of a NUL-terminated string in user space. 128 * 129 * Returns the size of the string INCLUDING the terminating NUL. 130 * On exception, returns 0. 131 * If the string is too long, returns a value greater than @n. 132 */ 133 long strnlen_user(const char *s, long n) 134 { 135 unsigned long res, tmp; 136 137 if (s == NULL) 138 return 0; 139 140 asm volatile( 141 " cmpnei %1, 0 \n" 142 " bf 3f \n" 143 "1: cmpnei %0, 0 \n" 144 " bf 3f \n" 145 "2: ldb %3, (%1, 0) \n" 146 " cmpnei %3, 0 \n" 147 " bf 3f \n" 148 " subi %0, 1 \n" 149 " addi %1, 1 \n" 150 " br 1b \n" 151 "3: subu %2, %0 \n" 152 " addi %2, 1 \n" 153 " br 5f \n" 154 "4: movi %0, 0 \n" 155 " br 5f \n" 156 ".section __ex_table, \"a\" \n" 157 ".align 2 \n" 158 ".long 2b, 4b \n" 159 ".previous \n" 160 "5: \n" 161 : "=r"(n), "=r"(s), "=r"(res), "=r"(tmp) 162 : "0"(n), "1"(s), "2"(n) 163 : "memory", "cc"); 164 165 return res; 166 } 167 EXPORT_SYMBOL(strnlen_user); 168 169 #define __do_clear_user(addr, size) \ 170 do { \ 171 int __d0, zvalue, tmp; \ 172 \ 173 asm volatile( \ 174 "0: cmpnei %1, 0 \n" \ 175 " bf 7f \n" \ 176 " mov %3, %1 \n" \ 177 " andi %3, 3 \n" \ 178 " cmpnei %3, 0 \n" \ 179 " bf 1f \n" \ 180 " br 5f \n" \ 181 "1: cmplti %0, 32 \n" /* 4W */ \ 182 " bt 3f \n" \ 183 "8: stw %2, (%1, 0) \n" \ 184 "10: stw %2, (%1, 4) \n" \ 185 "11: stw %2, (%1, 8) \n" \ 186 "12: stw %2, (%1, 12) \n" \ 187 "13: stw %2, (%1, 16) \n" \ 188 "14: stw %2, (%1, 20) \n" \ 189 "15: stw %2, (%1, 24) \n" \ 190 "16: stw %2, (%1, 28) \n" \ 191 " addi %1, 32 \n" \ 192 " subi %0, 32 \n" \ 193 " br 1b \n" \ 194 "3: cmplti %0, 4 \n" /* 1W */ \ 195 " bt 5f \n" \ 196 "4: stw %2, (%1, 0) \n" \ 197 " addi %1, 4 \n" \ 198 " subi %0, 4 \n" \ 199 " br 3b \n" \ 200 "5: cmpnei %0, 0 \n" /* 1B */ \ 201 "9: bf 7f \n" \ 202 "6: stb %2, (%1, 0) \n" \ 203 " addi %1, 1 \n" \ 204 " subi %0, 1 \n" \ 205 " br 5b \n" \ 206 ".section __ex_table,\"a\" \n" \ 207 ".align 2 \n" \ 208 ".long 8b, 9b \n" \ 209 ".long 10b, 9b \n" \ 210 ".long 11b, 9b \n" \ 211 ".long 12b, 9b \n" \ 212 ".long 13b, 9b \n" \ 213 ".long 14b, 9b \n" \ 214 ".long 15b, 9b \n" \ 215 ".long 16b, 9b \n" \ 216 ".long 4b, 9b \n" \ 217 ".long 6b, 9b \n" \ 218 ".previous \n" \ 219 "7: \n" \ 220 : "=r"(size), "=r" (__d0), \ 221 "=r"(zvalue), "=r"(tmp) \ 222 : "0"(size), "1"(addr), "2"(0) \ 223 : "memory", "cc"); \ 224 } while (0) 225 226 /* 227 * clear_user: - Zero a block of memory in user space. 228 * @to: Destination address, in user space. 229 * @n: Number of bytes to zero. 230 * 231 * Zero a block of memory in user space. 232 * 233 * Returns number of bytes that could not be cleared. 234 * On success, this will be zero. 235 */ 236 unsigned long 237 clear_user(void __user *to, unsigned long n) 238 { 239 if (access_ok(to, n)) 240 __do_clear_user(to, n); 241 return n; 242 } 243 EXPORT_SYMBOL(clear_user); 244 245 /* 246 * __clear_user: - Zero a block of memory in user space, with less checking. 247 * @to: Destination address, in user space. 248 * @n: Number of bytes to zero. 249 * 250 * Zero a block of memory in user space. Caller must check 251 * the specified block with access_ok() before calling this function. 252 * 253 * Returns number of bytes that could not be cleared. 254 * On success, this will be zero. 255 */ 256 unsigned long 257 __clear_user(void __user *to, unsigned long n) 258 { 259 __do_clear_user(to, n); 260 return n; 261 } 262 EXPORT_SYMBOL(__clear_user); 263