usercopy.c 7.7 KB

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