usercopy_64.c 4.1 KB

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