usercopy_64.c 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183
  1. /*
  2. * User address space access functions.
  3. *
  4. * Copyright 1997 Andi Kleen <ak@muc.de>
  5. * Copyright 1997 Linus Torvalds
  6. * Copyright 2002 Andi Kleen <ak@suse.de>
  7. */
  8. #include <linux/module.h>
  9. #include <asm/uaccess.h>
  10. /*
  11. * Copy a null terminated string from userspace.
  12. */
  13. #define __do_strncpy_from_user(dst,src,count,res) \
  14. do { \
  15. long __d0, __d1, __d2; \
  16. might_fault(); \
  17. __asm__ __volatile__( \
  18. " testq %1,%1\n" \
  19. " jz 2f\n" \
  20. "0: lodsb\n" \
  21. " stosb\n" \
  22. " testb %%al,%%al\n" \
  23. " jz 1f\n" \
  24. " decq %1\n" \
  25. " jnz 0b\n" \
  26. "1: subq %1,%0\n" \
  27. "2:\n" \
  28. ".section .fixup,\"ax\"\n" \
  29. "3: movq %5,%0\n" \
  30. " jmp 2b\n" \
  31. ".previous\n" \
  32. _ASM_EXTABLE(0b,3b) \
  33. : "=&r"(res), "=&c"(count), "=&a" (__d0), "=&S" (__d1), \
  34. "=&D" (__d2) \
  35. : "i"(-EFAULT), "0"(count), "1"(count), "3"(src), "4"(dst) \
  36. : "memory"); \
  37. } while (0)
  38. long
  39. __strncpy_from_user(char *dst, const char __user *src, long count)
  40. {
  41. long res;
  42. __do_strncpy_from_user(dst, src, count, res);
  43. return res;
  44. }
  45. EXPORT_SYMBOL(__strncpy_from_user);
  46. long
  47. strncpy_from_user(char *dst, const char __user *src, long count)
  48. {
  49. long res = -EFAULT;
  50. if (access_ok(VERIFY_READ, src, 1))
  51. return __strncpy_from_user(dst, src, count);
  52. return res;
  53. }
  54. EXPORT_SYMBOL(strncpy_from_user);
  55. /*
  56. * Zero Userspace
  57. */
  58. unsigned long __clear_user(void __user *addr, unsigned long size)
  59. {
  60. long __d0;
  61. might_fault();
  62. /* no memory constraint because it doesn't change any memory gcc knows
  63. about */
  64. asm volatile(
  65. " testq %[size8],%[size8]\n"
  66. " jz 4f\n"
  67. "0: movq %[zero],(%[dst])\n"
  68. " addq %[eight],%[dst]\n"
  69. " decl %%ecx ; jnz 0b\n"
  70. "4: movq %[size1],%%rcx\n"
  71. " testl %%ecx,%%ecx\n"
  72. " jz 2f\n"
  73. "1: movb %b[zero],(%[dst])\n"
  74. " incq %[dst]\n"
  75. " decl %%ecx ; jnz 1b\n"
  76. "2:\n"
  77. ".section .fixup,\"ax\"\n"
  78. "3: lea 0(%[size1],%[size8],8),%[size8]\n"
  79. " jmp 2b\n"
  80. ".previous\n"
  81. _ASM_EXTABLE(0b,3b)
  82. _ASM_EXTABLE(1b,2b)
  83. : [size8] "=&c"(size), [dst] "=&D" (__d0)
  84. : [size1] "r"(size & 7), "[size8]" (size / 8), "[dst]"(addr),
  85. [zero] "r" (0UL), [eight] "r" (8UL));
  86. return size;
  87. }
  88. EXPORT_SYMBOL(__clear_user);
  89. unsigned long clear_user(void __user *to, unsigned long n)
  90. {
  91. if (access_ok(VERIFY_WRITE, to, n))
  92. return __clear_user(to, n);
  93. return n;
  94. }
  95. EXPORT_SYMBOL(clear_user);
  96. /*
  97. * Return the size of a string (including the ending 0)
  98. *
  99. * Return 0 on exception, a value greater than N if too long
  100. */
  101. long __strnlen_user(const char __user *s, long n)
  102. {
  103. long res = 0;
  104. char c;
  105. while (1) {
  106. if (res>n)
  107. return n+1;
  108. if (__get_user(c, s))
  109. return 0;
  110. if (!c)
  111. return res+1;
  112. res++;
  113. s++;
  114. }
  115. }
  116. EXPORT_SYMBOL(__strnlen_user);
  117. long strnlen_user(const char __user *s, long n)
  118. {
  119. if (!access_ok(VERIFY_READ, s, 1))
  120. return 0;
  121. return __strnlen_user(s, n);
  122. }
  123. EXPORT_SYMBOL(strnlen_user);
  124. long strlen_user(const char __user *s)
  125. {
  126. long res = 0;
  127. char c;
  128. for (;;) {
  129. if (get_user(c, s))
  130. return 0;
  131. if (!c)
  132. return res+1;
  133. res++;
  134. s++;
  135. }
  136. }
  137. EXPORT_SYMBOL(strlen_user);
  138. unsigned long copy_in_user(void __user *to, const void __user *from, unsigned len)
  139. {
  140. if (access_ok(VERIFY_WRITE, to, len) && access_ok(VERIFY_READ, from, len)) {
  141. return copy_user_generic((__force void *)to, (__force void *)from, len);
  142. }
  143. return len;
  144. }
  145. EXPORT_SYMBOL(copy_in_user);
  146. /*
  147. * Try to copy last bytes and clear the rest if needed.
  148. * Since protection fault in copy_from/to_user is not a normal situation,
  149. * it is not necessary to optimize tail handling.
  150. */
  151. unsigned long
  152. copy_user_handle_tail(char *to, char *from, unsigned len, unsigned zerorest)
  153. {
  154. char c;
  155. unsigned zero_len;
  156. for (; len; --len) {
  157. if (__get_user_nocheck(c, from++, sizeof(char)))
  158. break;
  159. if (__put_user_nocheck(c, to++, sizeof(char)))
  160. break;
  161. }
  162. for (c = 0, zero_len = len; zerorest && zero_len; --zero_len)
  163. if (__put_user_nocheck(c, to++, sizeof(char)))
  164. break;
  165. return len;
  166. }