uaccess.c 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. /* User memory access */
  2. #include "qemu/osdep.h"
  3. #include "qemu/cutils.h"
  4. #include "qemu.h"
  5. #include "user-internals.h"
  6. void *lock_user(int type, abi_ulong guest_addr, ssize_t len, bool copy)
  7. {
  8. void *host_addr;
  9. guest_addr = cpu_untagged_addr(thread_cpu, guest_addr);
  10. if (!access_ok_untagged(type, guest_addr, len)) {
  11. return NULL;
  12. }
  13. host_addr = g2h_untagged(guest_addr);
  14. #ifdef CONFIG_DEBUG_REMAP
  15. if (copy) {
  16. host_addr = g_memdup(host_addr, len);
  17. } else {
  18. host_addr = g_malloc0(len);
  19. }
  20. #endif
  21. return host_addr;
  22. }
  23. #ifdef CONFIG_DEBUG_REMAP
  24. void unlock_user(void *host_ptr, abi_ulong guest_addr, ssize_t len)
  25. {
  26. void *host_ptr_conv;
  27. if (!host_ptr) {
  28. return;
  29. }
  30. host_ptr_conv = g2h(thread_cpu, guest_addr);
  31. if (host_ptr == host_ptr_conv) {
  32. return;
  33. }
  34. if (len > 0) {
  35. memcpy(host_ptr_conv, host_ptr, len);
  36. }
  37. g_free(host_ptr);
  38. }
  39. #endif
  40. void *lock_user_string(abi_ulong guest_addr)
  41. {
  42. ssize_t len = target_strlen(guest_addr);
  43. if (len < 0) {
  44. return NULL;
  45. }
  46. return lock_user(VERIFY_READ, guest_addr, len + 1, 1);
  47. }
  48. /* copy_from_user() and copy_to_user() are usually used to copy data
  49. * buffers between the target and host. These internally perform
  50. * locking/unlocking of the memory.
  51. */
  52. int copy_from_user(void *hptr, abi_ulong gaddr, ssize_t len)
  53. {
  54. int ret = 0;
  55. void *ghptr = lock_user(VERIFY_READ, gaddr, len, 1);
  56. if (ghptr) {
  57. memcpy(hptr, ghptr, len);
  58. unlock_user(ghptr, gaddr, 0);
  59. } else {
  60. ret = -TARGET_EFAULT;
  61. }
  62. return ret;
  63. }
  64. int copy_to_user(abi_ulong gaddr, void *hptr, ssize_t len)
  65. {
  66. int ret = 0;
  67. void *ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0);
  68. if (ghptr) {
  69. memcpy(ghptr, hptr, len);
  70. unlock_user(ghptr, gaddr, len);
  71. } else {
  72. ret = -TARGET_EFAULT;
  73. }
  74. return ret;
  75. }
  76. /* Return the length of a string in target memory or -TARGET_EFAULT if
  77. access error */
  78. ssize_t target_strlen(abi_ulong guest_addr1)
  79. {
  80. uint8_t *ptr;
  81. abi_ulong guest_addr;
  82. size_t max_len, len;
  83. guest_addr = guest_addr1;
  84. for(;;) {
  85. max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
  86. ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
  87. if (!ptr)
  88. return -TARGET_EFAULT;
  89. len = qemu_strnlen((const char *)ptr, max_len);
  90. unlock_user(ptr, guest_addr, 0);
  91. guest_addr += len;
  92. /* we don't allow wrapping or integer overflow */
  93. if (guest_addr == 0 || (guest_addr - guest_addr1) > 0x7fffffff) {
  94. return -TARGET_EFAULT;
  95. }
  96. if (len != max_len) {
  97. break;
  98. }
  99. }
  100. return guest_addr - guest_addr1;
  101. }