cachepc-qemu

Fork of AMDESE/qemu with changes for cachepc side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-qemu
Log | Files | Refs | Submodules | LICENSE | sfeed.txt

uaccess.c (2748B)


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