usercopy.c 7.8 KB

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