qemu

Форк
0
/
uaccess.c 
114 строк · 2.7 Кб
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

8
void *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 CONFIG_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 CONFIG_DEBUG_REMAP
28
void 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

46
void *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
 */
59
int 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

73
int 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  */
90
ssize_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
}
115

Использование cookies

Мы используем файлы cookie в соответствии с Политикой конфиденциальности и Политикой использования cookies.

Нажимая кнопку «Принимаю», Вы даете АО «СберТех» согласие на обработку Ваших персональных данных в целях совершенствования нашего веб-сайта и Сервиса GitVerse, а также повышения удобства их использования.

Запретить использование cookies Вы можете самостоятельно в настройках Вашего браузера.