qemu/bsd-user/uaccess.c
<<
>>
Prefs
   1/* User memory access */
   2#include <stdio.h>
   3#include <string.h>
   4
   5#include "qemu.h"
   6
   7/* copy_from_user() and copy_to_user() are usually used to copy data
   8 * buffers between the target and host.  These internally perform
   9 * locking/unlocking of the memory.
  10 */
  11abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
  12{
  13    abi_long ret = 0;
  14    void *ghptr;
  15
  16    if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
  17        memcpy(hptr, ghptr, len);
  18        unlock_user(ghptr, gaddr, 0);
  19    } else
  20        ret = -TARGET_EFAULT;
  21
  22    return ret;
  23}
  24
  25
  26abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
  27{
  28    abi_long ret = 0;
  29    void *ghptr;
  30
  31    if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
  32        memcpy(ghptr, hptr, len);
  33        unlock_user(ghptr, gaddr, len);
  34    } else
  35        ret = -TARGET_EFAULT;
  36
  37    return ret;
  38}
  39
  40/* XXX: use host strnlen if available ? */
  41static int qemu_strnlen(const char *s, int max_len)
  42{
  43    int i;
  44    for(i = 0; i < max_len; i++) {
  45        if (s[i] == '\0')
  46            break;
  47    }
  48    return i;
  49}
  50
  51/* Return the length of a string in target memory or -TARGET_EFAULT if
  52   access error  */
  53abi_long target_strlen(abi_ulong guest_addr1)
  54{
  55    uint8_t *ptr;
  56    abi_ulong guest_addr;
  57    int max_len, len;
  58
  59    guest_addr = guest_addr1;
  60    for(;;) {
  61        max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
  62        ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
  63        if (!ptr)
  64            return -TARGET_EFAULT;
  65        len = qemu_strnlen(ptr, max_len);
  66        unlock_user(ptr, guest_addr, 0);
  67        guest_addr += len;
  68        /* we don't allow wrapping or integer overflow */
  69        if (guest_addr == 0 ||
  70            (guest_addr - guest_addr1) > 0x7fffffff)
  71            return -TARGET_EFAULT;
  72        if (len != max_len)
  73            break;
  74    }
  75    return guest_addr - guest_addr1;
  76}
  77