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