xref: /qemu/bsd-user/uaccess.c (revision f4a1016f)
184778508Sblueswir1 /* User memory access */
22231197cSPeter Maydell #include "qemu/osdep.h"
3abd4556aSEd Maste #include "qemu/cutils.h"
484778508Sblueswir1 
584778508Sblueswir1 #include "qemu.h"
684778508Sblueswir1 
784778508Sblueswir1 /* copy_from_user() and copy_to_user() are usually used to copy data
884778508Sblueswir1  * buffers between the target and host.  These internally perform
984778508Sblueswir1  * locking/unlocking of the memory.
1084778508Sblueswir1  */
copy_from_user(void * hptr,abi_ulong gaddr,size_t len)1184778508Sblueswir1 abi_long copy_from_user(void *hptr, abi_ulong gaddr, size_t len)
1284778508Sblueswir1 {
1384778508Sblueswir1     abi_long ret = 0;
1484778508Sblueswir1     void *ghptr;
1584778508Sblueswir1 
1684778508Sblueswir1     if ((ghptr = lock_user(VERIFY_READ, gaddr, len, 1))) {
1784778508Sblueswir1         memcpy(hptr, ghptr, len);
1884778508Sblueswir1         unlock_user(ghptr, gaddr, 0);
1984778508Sblueswir1     } else
2084778508Sblueswir1         ret = -TARGET_EFAULT;
2184778508Sblueswir1 
2284778508Sblueswir1     return ret;
2384778508Sblueswir1 }
2484778508Sblueswir1 
2584778508Sblueswir1 
copy_to_user(abi_ulong gaddr,void * hptr,size_t len)2684778508Sblueswir1 abi_long copy_to_user(abi_ulong gaddr, void *hptr, size_t len)
2784778508Sblueswir1 {
2884778508Sblueswir1     abi_long ret = 0;
2984778508Sblueswir1     void *ghptr;
3084778508Sblueswir1 
3184778508Sblueswir1     if ((ghptr = lock_user(VERIFY_WRITE, gaddr, len, 0))) {
3284778508Sblueswir1         memcpy(ghptr, hptr, len);
3384778508Sblueswir1         unlock_user(ghptr, gaddr, len);
3484778508Sblueswir1     } else
3584778508Sblueswir1         ret = -TARGET_EFAULT;
3684778508Sblueswir1 
3784778508Sblueswir1     return ret;
3884778508Sblueswir1 }
3984778508Sblueswir1 
4084778508Sblueswir1 /* Return the length of a string in target memory or -TARGET_EFAULT if
4184778508Sblueswir1    access error  */
target_strlen(abi_ulong guest_addr1)4284778508Sblueswir1 abi_long target_strlen(abi_ulong guest_addr1)
4384778508Sblueswir1 {
4484778508Sblueswir1     uint8_t *ptr;
4584778508Sblueswir1     abi_ulong guest_addr;
4684778508Sblueswir1     int max_len, len;
4784778508Sblueswir1 
4884778508Sblueswir1     guest_addr = guest_addr1;
4984778508Sblueswir1     for (;;) {
5084778508Sblueswir1         max_len = TARGET_PAGE_SIZE - (guest_addr & ~TARGET_PAGE_MASK);
5184778508Sblueswir1         ptr = lock_user(VERIFY_READ, guest_addr, max_len, 1);
5284778508Sblueswir1         if (!ptr)
5384778508Sblueswir1             return -TARGET_EFAULT;
54*43b0ea1aSEd Maste         len = qemu_strnlen((const char *)ptr, max_len);
5584778508Sblueswir1         unlock_user(ptr, guest_addr, 0);
5684778508Sblueswir1         guest_addr += len;
5784778508Sblueswir1         /* we don't allow wrapping or integer overflow */
5884778508Sblueswir1         if (guest_addr == 0 ||
5984778508Sblueswir1             (guest_addr - guest_addr1) > 0x7fffffff)
6084778508Sblueswir1             return -TARGET_EFAULT;
6184778508Sblueswir1         if (len != max_len)
6284778508Sblueswir1             break;
6384778508Sblueswir1     }
6484778508Sblueswir1     return guest_addr - guest_addr1;
6584778508Sblueswir1 }
66