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