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