Commit 53a5960aadd542dd27b8705ac30df154557d5ffc
1 parent
26f69dc0
Avoid accessing guest memory directly in usermode emulation.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1790 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
15 changed files
with
1194 additions
and
772 deletions
cpu-all.h
... | ... | @@ -584,22 +584,41 @@ static inline void stfq_be_p(void *ptr, float64 v) |
584 | 584 | |
585 | 585 | /* MMU memory access macros */ |
586 | 586 | |
587 | +#if defined(CONFIG_USER_ONLY) | |
588 | +/* On some host systems the guest address space is reserved on the host. | |
589 | + * This allows the guest address space to be offset to a convenient location. | |
590 | + */ | |
591 | +//#define GUEST_BASE 0x20000000 | |
592 | +#define GUEST_BASE 0 | |
593 | + | |
594 | +/* All direct uses of g2h and h2g need to go away for usermode softmmu. */ | |
595 | +#define g2h(x) ((void *)((unsigned long)(x) + GUEST_BASE)) | |
596 | +#define h2g(x) ((target_ulong)(x - GUEST_BASE)) | |
597 | + | |
598 | +#define saddr(x) g2h(x) | |
599 | +#define laddr(x) g2h(x) | |
600 | + | |
601 | +#else /* !CONFIG_USER_ONLY */ | |
587 | 602 | /* NOTE: we use double casts if pointers and target_ulong have |
588 | 603 | different sizes */ |
589 | -#define ldub_raw(p) ldub_p((uint8_t *)(long)(p)) | |
590 | -#define ldsb_raw(p) ldsb_p((uint8_t *)(long)(p)) | |
591 | -#define lduw_raw(p) lduw_p((uint8_t *)(long)(p)) | |
592 | -#define ldsw_raw(p) ldsw_p((uint8_t *)(long)(p)) | |
593 | -#define ldl_raw(p) ldl_p((uint8_t *)(long)(p)) | |
594 | -#define ldq_raw(p) ldq_p((uint8_t *)(long)(p)) | |
595 | -#define ldfl_raw(p) ldfl_p((uint8_t *)(long)(p)) | |
596 | -#define ldfq_raw(p) ldfq_p((uint8_t *)(long)(p)) | |
597 | -#define stb_raw(p, v) stb_p((uint8_t *)(long)(p), v) | |
598 | -#define stw_raw(p, v) stw_p((uint8_t *)(long)(p), v) | |
599 | -#define stl_raw(p, v) stl_p((uint8_t *)(long)(p), v) | |
600 | -#define stq_raw(p, v) stq_p((uint8_t *)(long)(p), v) | |
601 | -#define stfl_raw(p, v) stfl_p((uint8_t *)(long)(p), v) | |
602 | -#define stfq_raw(p, v) stfq_p((uint8_t *)(long)(p), v) | |
604 | +#define saddr(x) (uint8_t *)(long)(x) | |
605 | +#define laddr(x) (uint8_t *)(long)(x) | |
606 | +#endif | |
607 | + | |
608 | +#define ldub_raw(p) ldub_p(laddr((p))) | |
609 | +#define ldsb_raw(p) ldsb_p(laddr((p))) | |
610 | +#define lduw_raw(p) lduw_p(laddr((p))) | |
611 | +#define ldsw_raw(p) ldsw_p(laddr((p))) | |
612 | +#define ldl_raw(p) ldl_p(laddr((p))) | |
613 | +#define ldq_raw(p) ldq_p(laddr((p))) | |
614 | +#define ldfl_raw(p) ldfl_p(laddr((p))) | |
615 | +#define ldfq_raw(p) ldfq_p(laddr((p))) | |
616 | +#define stb_raw(p, v) stb_p(saddr((p)), v) | |
617 | +#define stw_raw(p, v) stw_p(saddr((p)), v) | |
618 | +#define stl_raw(p, v) stl_p(saddr((p)), v) | |
619 | +#define stq_raw(p, v) stq_p(saddr((p)), v) | |
620 | +#define stfl_raw(p, v) stfl_p(saddr((p)), v) | |
621 | +#define stfq_raw(p, v) stfq_p(saddr((p)), v) | |
603 | 622 | |
604 | 623 | |
605 | 624 | #if defined(CONFIG_USER_ONLY) |
... | ... | @@ -648,6 +667,7 @@ static inline void stfq_be_p(void *ptr, float64 v) |
648 | 667 | #define TARGET_PAGE_MASK ~(TARGET_PAGE_SIZE - 1) |
649 | 668 | #define TARGET_PAGE_ALIGN(addr) (((addr) + TARGET_PAGE_SIZE - 1) & TARGET_PAGE_MASK) |
650 | 669 | |
670 | +/* ??? These should be the larger of unsigned long and target_ulong. */ | |
651 | 671 | extern unsigned long qemu_real_host_page_size; |
652 | 672 | extern unsigned long qemu_host_page_bits; |
653 | 673 | extern unsigned long qemu_host_page_size; |
... | ... | @@ -666,9 +686,9 @@ extern unsigned long qemu_host_page_mask; |
666 | 686 | #define PAGE_WRITE_ORG 0x0010 |
667 | 687 | |
668 | 688 | void page_dump(FILE *f); |
669 | -int page_get_flags(unsigned long address); | |
670 | -void page_set_flags(unsigned long start, unsigned long end, int flags); | |
671 | -void page_unprotect_range(uint8_t *data, unsigned long data_size); | |
689 | +int page_get_flags(target_ulong address); | |
690 | +void page_set_flags(target_ulong start, target_ulong end, int flags); | |
691 | +void page_unprotect_range(target_ulong data, target_ulong data_size); | |
672 | 692 | |
673 | 693 | #define SINGLE_CPU_DEFINES |
674 | 694 | #ifdef SINGLE_CPU_DEFINES | ... | ... |
cpu-exec.c
... | ... | @@ -913,7 +913,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
913 | 913 | pc, address, is_write, *(unsigned long *)old_set); |
914 | 914 | #endif |
915 | 915 | /* XXX: locking issue */ |
916 | - if (is_write && page_unprotect(address, pc, puc)) { | |
916 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
917 | 917 | return 1; |
918 | 918 | } |
919 | 919 | |
... | ... | @@ -964,7 +964,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
964 | 964 | pc, address, is_write, *(unsigned long *)old_set); |
965 | 965 | #endif |
966 | 966 | /* XXX: locking issue */ |
967 | - if (is_write && page_unprotect(address, pc, puc)) { | |
967 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
968 | 968 | return 1; |
969 | 969 | } |
970 | 970 | /* see if it is an MMU fault */ |
... | ... | @@ -1000,7 +1000,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
1000 | 1000 | pc, address, is_write, *(unsigned long *)old_set); |
1001 | 1001 | #endif |
1002 | 1002 | /* XXX: locking issue */ |
1003 | - if (is_write && page_unprotect(address, pc, puc)) { | |
1003 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
1004 | 1004 | return 1; |
1005 | 1005 | } |
1006 | 1006 | /* see if it is an MMU fault */ |
... | ... | @@ -1036,7 +1036,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
1036 | 1036 | pc, address, is_write, *(unsigned long *)old_set); |
1037 | 1037 | #endif |
1038 | 1038 | /* XXX: locking issue */ |
1039 | - if (is_write && page_unprotect(address, pc, puc)) { | |
1039 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
1040 | 1040 | return 1; |
1041 | 1041 | } |
1042 | 1042 | |
... | ... | @@ -1086,7 +1086,7 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
1086 | 1086 | pc, address, is_write, *(unsigned long *)old_set); |
1087 | 1087 | #endif |
1088 | 1088 | /* XXX: locking issue */ |
1089 | - if (is_write && page_unprotect(address, pc, puc)) { | |
1089 | + if (is_write && page_unprotect(h2g(address), pc, puc)) { | |
1090 | 1090 | return 1; |
1091 | 1091 | } |
1092 | 1092 | ... | ... |
exec-all.h
... | ... | @@ -93,7 +93,7 @@ int cpu_restore_state_copy(struct TranslationBlock *tb, |
93 | 93 | void *puc); |
94 | 94 | void cpu_resume_from_signal(CPUState *env1, void *puc); |
95 | 95 | void cpu_exec_init(CPUState *env); |
96 | -int page_unprotect(unsigned long address, unsigned long pc, void *puc); | |
96 | +int page_unprotect(target_ulong address, unsigned long pc, void *puc); | |
97 | 97 | void tb_invalidate_phys_page_range(target_ulong start, target_ulong end, |
98 | 98 | int is_cpu_write_access); |
99 | 99 | void tb_invalidate_page_range(target_ulong start, target_ulong end); | ... | ... |
exec.c
... | ... | @@ -34,6 +34,9 @@ |
34 | 34 | |
35 | 35 | #include "cpu.h" |
36 | 36 | #include "exec-all.h" |
37 | +#if defined(CONFIG_USER_ONLY) | |
38 | +#include <qemu.h> | |
39 | +#endif | |
37 | 40 | |
38 | 41 | //#define DEBUG_TB_INVALIDATE |
39 | 42 | //#define DEBUG_FLUSH |
... | ... | @@ -810,7 +813,7 @@ static void tb_invalidate_phys_page(target_ulong addr, |
810 | 813 | |
811 | 814 | /* add the tb in the target page and protect it if necessary */ |
812 | 815 | static inline void tb_alloc_page(TranslationBlock *tb, |
813 | - unsigned int n, unsigned int page_addr) | |
816 | + unsigned int n, target_ulong page_addr) | |
814 | 817 | { |
815 | 818 | PageDesc *p; |
816 | 819 | TranslationBlock *last_first_tb; |
... | ... | @@ -826,23 +829,30 @@ static inline void tb_alloc_page(TranslationBlock *tb, |
826 | 829 | |
827 | 830 | #if defined(CONFIG_USER_ONLY) |
828 | 831 | if (p->flags & PAGE_WRITE) { |
829 | - unsigned long host_start, host_end, addr; | |
832 | + target_ulong addr; | |
833 | + PageDesc *p2; | |
830 | 834 | int prot; |
831 | 835 | |
832 | 836 | /* force the host page as non writable (writes will have a |
833 | 837 | page fault + mprotect overhead) */ |
834 | - host_start = page_addr & qemu_host_page_mask; | |
835 | - host_end = host_start + qemu_host_page_size; | |
838 | + page_addr &= qemu_host_page_mask; | |
836 | 839 | prot = 0; |
837 | - for(addr = host_start; addr < host_end; addr += TARGET_PAGE_SIZE) | |
838 | - prot |= page_get_flags(addr); | |
839 | - mprotect((void *)host_start, qemu_host_page_size, | |
840 | + for(addr = page_addr; addr < page_addr + qemu_host_page_size; | |
841 | + addr += TARGET_PAGE_SIZE) { | |
842 | + | |
843 | + p2 = page_find (addr >> TARGET_PAGE_BITS); | |
844 | + if (!p2) | |
845 | + continue; | |
846 | + prot |= p2->flags; | |
847 | + p2->flags &= ~PAGE_WRITE; | |
848 | + page_get_flags(addr); | |
849 | + } | |
850 | + mprotect(g2h(page_addr), qemu_host_page_size, | |
840 | 851 | (prot & PAGE_BITS) & ~PAGE_WRITE); |
841 | 852 | #ifdef DEBUG_TB_INVALIDATE |
842 | 853 | printf("protecting code page: 0x%08lx\n", |
843 | - host_start); | |
854 | + page_addr); | |
844 | 855 | #endif |
845 | - p->flags &= ~PAGE_WRITE; | |
846 | 856 | } |
847 | 857 | #else |
848 | 858 | /* if some code is already present, then the pages are already |
... | ... | @@ -1546,7 +1556,7 @@ int tlb_set_page_exec(CPUState *env, target_ulong vaddr, |
1546 | 1556 | |
1547 | 1557 | /* called from signal handler: invalidate the code and unprotect the |
1548 | 1558 | page. Return TRUE if the fault was succesfully handled. */ |
1549 | -int page_unprotect(unsigned long addr, unsigned long pc, void *puc) | |
1559 | +int page_unprotect(target_ulong addr, unsigned long pc, void *puc) | |
1550 | 1560 | { |
1551 | 1561 | #if !defined(CONFIG_SOFTMMU) |
1552 | 1562 | VirtPageDesc *vp; |
... | ... | @@ -1645,7 +1655,7 @@ void page_dump(FILE *f) |
1645 | 1655 | } |
1646 | 1656 | } |
1647 | 1657 | |
1648 | -int page_get_flags(unsigned long address) | |
1658 | +int page_get_flags(target_ulong address) | |
1649 | 1659 | { |
1650 | 1660 | PageDesc *p; |
1651 | 1661 | |
... | ... | @@ -1658,10 +1668,10 @@ int page_get_flags(unsigned long address) |
1658 | 1668 | /* modify the flags of a page and invalidate the code if |
1659 | 1669 | necessary. The flag PAGE_WRITE_ORG is positionned automatically |
1660 | 1670 | depending on PAGE_WRITE */ |
1661 | -void page_set_flags(unsigned long start, unsigned long end, int flags) | |
1671 | +void page_set_flags(target_ulong start, target_ulong end, int flags) | |
1662 | 1672 | { |
1663 | 1673 | PageDesc *p; |
1664 | - unsigned long addr; | |
1674 | + target_ulong addr; | |
1665 | 1675 | |
1666 | 1676 | start = start & TARGET_PAGE_MASK; |
1667 | 1677 | end = TARGET_PAGE_ALIGN(end); |
... | ... | @@ -1684,11 +1694,11 @@ void page_set_flags(unsigned long start, unsigned long end, int flags) |
1684 | 1694 | |
1685 | 1695 | /* called from signal handler: invalidate the code and unprotect the |
1686 | 1696 | page. Return TRUE if the fault was succesfully handled. */ |
1687 | -int page_unprotect(unsigned long address, unsigned long pc, void *puc) | |
1697 | +int page_unprotect(target_ulong address, unsigned long pc, void *puc) | |
1688 | 1698 | { |
1689 | 1699 | unsigned int page_index, prot, pindex; |
1690 | 1700 | PageDesc *p, *p1; |
1691 | - unsigned long host_start, host_end, addr; | |
1701 | + target_ulong host_start, host_end, addr; | |
1692 | 1702 | |
1693 | 1703 | host_start = address & qemu_host_page_mask; |
1694 | 1704 | page_index = host_start >> TARGET_PAGE_BITS; |
... | ... | @@ -1707,7 +1717,7 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) |
1707 | 1717 | if (prot & PAGE_WRITE_ORG) { |
1708 | 1718 | pindex = (address - host_start) >> TARGET_PAGE_BITS; |
1709 | 1719 | if (!(p1[pindex].flags & PAGE_WRITE)) { |
1710 | - mprotect((void *)host_start, qemu_host_page_size, | |
1720 | + mprotect((void *)g2h(host_start), qemu_host_page_size, | |
1711 | 1721 | (prot & PAGE_BITS) | PAGE_WRITE); |
1712 | 1722 | p1[pindex].flags |= PAGE_WRITE; |
1713 | 1723 | /* and since the content will be modified, we must invalidate |
... | ... | @@ -1723,11 +1733,12 @@ int page_unprotect(unsigned long address, unsigned long pc, void *puc) |
1723 | 1733 | } |
1724 | 1734 | |
1725 | 1735 | /* call this function when system calls directly modify a memory area */ |
1726 | -void page_unprotect_range(uint8_t *data, unsigned long data_size) | |
1736 | +/* ??? This should be redundant now we have lock_user. */ | |
1737 | +void page_unprotect_range(target_ulong data, target_ulong data_size) | |
1727 | 1738 | { |
1728 | - unsigned long start, end, addr; | |
1739 | + target_ulong start, end, addr; | |
1729 | 1740 | |
1730 | - start = (unsigned long)data; | |
1741 | + start = data; | |
1731 | 1742 | end = start + data_size; |
1732 | 1743 | start &= TARGET_PAGE_MASK; |
1733 | 1744 | end = TARGET_PAGE_ALIGN(end); |
... | ... | @@ -1932,6 +1943,7 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, |
1932 | 1943 | { |
1933 | 1944 | int l, flags; |
1934 | 1945 | target_ulong page; |
1946 | + void * p; | |
1935 | 1947 | |
1936 | 1948 | while (len > 0) { |
1937 | 1949 | page = addr & TARGET_PAGE_MASK; |
... | ... | @@ -1944,11 +1956,15 @@ void cpu_physical_memory_rw(target_phys_addr_t addr, uint8_t *buf, |
1944 | 1956 | if (is_write) { |
1945 | 1957 | if (!(flags & PAGE_WRITE)) |
1946 | 1958 | return; |
1947 | - memcpy((uint8_t *)addr, buf, len); | |
1959 | + p = lock_user(addr, len, 0); | |
1960 | + memcpy(p, buf, len); | |
1961 | + unlock_user(p, addr, len); | |
1948 | 1962 | } else { |
1949 | 1963 | if (!(flags & PAGE_READ)) |
1950 | 1964 | return; |
1951 | - memcpy(buf, (uint8_t *)addr, len); | |
1965 | + p = lock_user(addr, len, 1); | |
1966 | + memcpy(buf, p, len); | |
1967 | + unlock_user(p, addr, 0); | |
1952 | 1968 | } |
1953 | 1969 | len -= l; |
1954 | 1970 | buf += l; | ... | ... |
linux-user/arm-semi.c
... | ... | @@ -77,20 +77,20 @@ static inline uint32_t set_swi_errno(TaskState *ts, uint32_t code) |
77 | 77 | return code; |
78 | 78 | } |
79 | 79 | |
80 | -#define ARG(x) tswap32(args[x]) | |
80 | +#define ARG(n) tget32(args + n * 4) | |
81 | 81 | uint32_t do_arm_semihosting(CPUState *env) |
82 | 82 | { |
83 | - uint32_t *args; | |
83 | + target_ulong args; | |
84 | 84 | char * s; |
85 | 85 | int nr; |
86 | 86 | uint32_t ret; |
87 | 87 | TaskState *ts = env->opaque; |
88 | 88 | |
89 | 89 | nr = env->regs[0]; |
90 | - args = (uint32_t *)env->regs[1]; | |
90 | + args = env->regs[1]; | |
91 | 91 | switch (nr) { |
92 | 92 | case SYS_OPEN: |
93 | - s = (char *)ARG(0); | |
93 | + s = (char *)g2h(ARG(0)); | |
94 | 94 | if (ARG(1) >= 12) |
95 | 95 | return (uint32_t)-1; |
96 | 96 | if (strcmp(s, ":tt") == 0) { |
... | ... | @@ -103,18 +103,23 @@ uint32_t do_arm_semihosting(CPUState *env) |
103 | 103 | case SYS_CLOSE: |
104 | 104 | return set_swi_errno(ts, close(ARG(0))); |
105 | 105 | case SYS_WRITEC: |
106 | - /* Write to debug console. stderr is near enough. */ | |
107 | - return write(STDERR_FILENO, args, 1); | |
106 | + { | |
107 | + char c = tget8(args); | |
108 | + /* Write to debug console. stderr is near enough. */ | |
109 | + return write(STDERR_FILENO, &c, 1); | |
110 | + } | |
108 | 111 | case SYS_WRITE0: |
109 | - s = (char *)args; | |
110 | - return write(STDERR_FILENO, s, strlen(s)); | |
112 | + s = lock_user_string(args); | |
113 | + ret = write(STDERR_FILENO, s, strlen(s)); | |
114 | + unlock_user(s, args, 0); | |
115 | + return ret; | |
111 | 116 | case SYS_WRITE: |
112 | - ret = set_swi_errno(ts, write(ARG(0), (void *)ARG(1), ARG(2))); | |
117 | + ret = set_swi_errno(ts, write(ARG(0), g2h(ARG(1)), ARG(2))); | |
113 | 118 | if (ret == (uint32_t)-1) |
114 | 119 | return -1; |
115 | 120 | return ARG(2) - ret; |
116 | 121 | case SYS_READ: |
117 | - ret = set_swi_errno(ts, read(ARG(0), (void *)ARG(1), ARG(2))); | |
122 | + ret = set_swi_errno(ts, read(ARG(0), g2h(ARG(1)), ARG(2))); | |
118 | 123 | if (ret == (uint32_t)-1) |
119 | 124 | return -1; |
120 | 125 | return ARG(2) - ret; |
... | ... | @@ -140,20 +145,21 @@ uint32_t do_arm_semihosting(CPUState *env) |
140 | 145 | /* XXX: Not implemented. */ |
141 | 146 | return -1; |
142 | 147 | case SYS_REMOVE: |
143 | - return set_swi_errno(ts, remove((char *)ARG(0))); | |
148 | + return set_swi_errno(ts, remove((char *)g2h(ARG(0)))); | |
144 | 149 | case SYS_RENAME: |
145 | - return set_swi_errno(ts, rename((char *)ARG(0), (char *)ARG(2))); | |
150 | + return set_swi_errno(ts, rename((char *)g2h(ARG(0)), | |
151 | + (char *)g2h(ARG(2)))); | |
146 | 152 | case SYS_CLOCK: |
147 | 153 | return clock() / (CLOCKS_PER_SEC / 100); |
148 | 154 | case SYS_TIME: |
149 | 155 | return set_swi_errno(ts, time(NULL)); |
150 | 156 | case SYS_SYSTEM: |
151 | - return set_swi_errno(ts, system((char *)ARG(0))); | |
157 | + return set_swi_errno(ts, system((char *)g2h(ARG(0)))); | |
152 | 158 | case SYS_ERRNO: |
153 | 159 | return ts->swi_errno; |
154 | 160 | case SYS_GET_CMDLINE: |
155 | 161 | /* XXX: Not implemented. */ |
156 | - s = (char *)ARG(0); | |
162 | + s = (char *)g2h(ARG(0)); | |
157 | 163 | *s = 0; |
158 | 164 | return -1; |
159 | 165 | case SYS_HEAPINFO: |
... | ... | @@ -166,11 +172,11 @@ uint32_t do_arm_semihosting(CPUState *env) |
166 | 172 | if (!ts->heap_limit) { |
167 | 173 | long ret; |
168 | 174 | |
169 | - ts->heap_base = do_brk(NULL); | |
175 | + ts->heap_base = do_brk(0); | |
170 | 176 | limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE; |
171 | 177 | /* Try a big heap, and reduce the size if that fails. */ |
172 | 178 | for (;;) { |
173 | - ret = do_brk((char *)limit); | |
179 | + ret = do_brk(limit); | |
174 | 180 | if (ret != -1) |
175 | 181 | break; |
176 | 182 | limit = (ts->heap_base >> 1) + (limit >> 1); |
... | ... | @@ -178,7 +184,8 @@ uint32_t do_arm_semihosting(CPUState *env) |
178 | 184 | ts->heap_limit = limit; |
179 | 185 | } |
180 | 186 | |
181 | - ptr = (uint32_t *)ARG(0); | |
187 | + page_unprotect_range (ARG(0), 32); | |
188 | + ptr = (uint32_t *)g2h(ARG(0)); | |
182 | 189 | ptr[0] = tswap32(ts->heap_base); |
183 | 190 | ptr[1] = tswap32(ts->heap_limit); |
184 | 191 | ptr[2] = tswap32(ts->stack_base); | ... | ... |
linux-user/elfload.c
... | ... | @@ -97,17 +97,17 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i |
97 | 97 | |
98 | 98 | static inline void init_thread(struct target_pt_regs *regs, struct image_info *infop) |
99 | 99 | { |
100 | - target_long *stack = (void *)infop->start_stack; | |
100 | + target_long stack = infop->start_stack; | |
101 | 101 | memset(regs, 0, sizeof(*regs)); |
102 | 102 | regs->ARM_cpsr = 0x10; |
103 | 103 | if (infop->entry & 1) |
104 | 104 | regs->ARM_cpsr |= CPSR_T; |
105 | 105 | regs->ARM_pc = infop->entry & 0xfffffffe; |
106 | 106 | regs->ARM_sp = infop->start_stack; |
107 | - regs->ARM_r2 = tswapl(stack[2]); /* envp */ | |
108 | - regs->ARM_r1 = tswapl(stack[1]); /* argv */ | |
107 | + regs->ARM_r2 = tgetl(stack + 8); /* envp */ | |
108 | + regs->ARM_r1 = tgetl(stack + 4); /* envp */ | |
109 | 109 | /* XXX: it seems that r0 is zeroed after ! */ |
110 | - // regs->ARM_r0 = tswapl(stack[0]); /* argc */ | |
110 | + // regs->ARM_r0 = tgetl(stack); /* argc */ | |
111 | 111 | } |
112 | 112 | |
113 | 113 | #define USE_ELF_CORE_DUMP |
... | ... | @@ -202,7 +202,7 @@ do { \ |
202 | 202 | _r->gpr[3] = bprm->argc; \ |
203 | 203 | _r->gpr[4] = (unsigned long)++pos; \ |
204 | 204 | for (; tmp != 0; pos++) \ |
205 | - tmp = *pos; \ | |
205 | + tmp = ldl(pos); \ | |
206 | 206 | _r->gpr[5] = (unsigned long)pos; \ |
207 | 207 | } while (0) |
208 | 208 | |
... | ... | @@ -297,7 +297,7 @@ static inline void init_thread(struct target_pt_regs *regs, struct image_info *i |
297 | 297 | */ |
298 | 298 | struct linux_binprm { |
299 | 299 | char buf[128]; |
300 | - unsigned long page[MAX_ARG_PAGES]; | |
300 | + void *page[MAX_ARG_PAGES]; | |
301 | 301 | unsigned long p; |
302 | 302 | int sh_bang; |
303 | 303 | int fd; |
... | ... | @@ -427,37 +427,13 @@ static void bswap_sym(Elf32_Sym *sym) |
427 | 427 | } |
428 | 428 | #endif |
429 | 429 | |
430 | -static void * get_free_page(void) | |
431 | -{ | |
432 | - void * retval; | |
433 | - | |
434 | - /* User-space version of kernel get_free_page. Returns a page-aligned | |
435 | - * page-sized chunk of memory. | |
436 | - */ | |
437 | - retval = (void *)target_mmap(0, qemu_host_page_size, PROT_READ|PROT_WRITE, | |
438 | - MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); | |
439 | - | |
440 | - if((long)retval == -1) { | |
441 | - perror("get_free_page"); | |
442 | - exit(-1); | |
443 | - } | |
444 | - else { | |
445 | - return(retval); | |
446 | - } | |
447 | -} | |
448 | - | |
449 | -static void free_page(void * pageaddr) | |
450 | -{ | |
451 | - target_munmap((unsigned long)pageaddr, qemu_host_page_size); | |
452 | -} | |
453 | - | |
454 | 430 | /* |
455 | 431 | * 'copy_string()' copies argument/envelope strings from user |
456 | 432 | * memory to free pages in kernel mem. These are in a format ready |
457 | 433 | * to be put directly into the top of new user memory. |
458 | 434 | * |
459 | 435 | */ |
460 | -static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, | |
436 | +static unsigned long copy_strings(int argc,char ** argv, void **page, | |
461 | 437 | unsigned long p) |
462 | 438 | { |
463 | 439 | char *tmp, *tmp1, *pag = NULL; |
... | ... | @@ -482,10 +458,10 @@ static unsigned long copy_strings(int argc,char ** argv,unsigned long *page, |
482 | 458 | --p; --tmp; --len; |
483 | 459 | if (--offset < 0) { |
484 | 460 | offset = p % TARGET_PAGE_SIZE; |
485 | - pag = (char *) page[p/TARGET_PAGE_SIZE]; | |
461 | + pag = (char *)page[p/TARGET_PAGE_SIZE]; | |
486 | 462 | if (!pag) { |
487 | - pag = (char *)get_free_page(); | |
488 | - page[p/TARGET_PAGE_SIZE] = (unsigned long)pag; | |
463 | + pag = (char *)malloc(TARGET_PAGE_SIZE); | |
464 | + page[p/TARGET_PAGE_SIZE] = pag; | |
489 | 465 | if (!pag) |
490 | 466 | return 0; |
491 | 467 | } |
... | ... | @@ -591,10 +567,20 @@ static int prepare_binprm(struct linux_binprm *bprm) |
591 | 567 | } |
592 | 568 | } |
593 | 569 | |
594 | -unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, | |
595 | - struct image_info * info) | |
570 | +static inline void memcpy_to_target(target_ulong dest, const void *src, | |
571 | + unsigned long len) | |
596 | 572 | { |
597 | - unsigned long stack_base, size, error; | |
573 | + void *host_ptr; | |
574 | + | |
575 | + host_ptr = lock_user(dest, len, 0); | |
576 | + memcpy(host_ptr, src, len); | |
577 | + unlock_user(host_ptr, dest, 1); | |
578 | +} | |
579 | + | |
580 | +unsigned long setup_arg_pages(target_ulong p, struct linux_binprm * bprm, | |
581 | + struct image_info * info) | |
582 | +{ | |
583 | + target_ulong stack_base, size, error; | |
598 | 584 | int i; |
599 | 585 | |
600 | 586 | /* Create enough stack to hold everything. If we don't use |
... | ... | @@ -627,10 +613,10 @@ unsigned long setup_arg_pages(unsigned long p, struct linux_binprm * bprm, |
627 | 613 | if (bprm->page[i]) { |
628 | 614 | info->rss++; |
629 | 615 | |
630 | - memcpy((void *)stack_base, (void *)bprm->page[i], TARGET_PAGE_SIZE); | |
631 | - free_page((void *)bprm->page[i]); | |
616 | + memcpy_to_target(stack_base, bprm->page[i], TARGET_PAGE_SIZE); | |
617 | + free(bprm->page[i]); | |
632 | 618 | } |
633 | - stack_base += TARGET_PAGE_SIZE; | |
619 | + stack_base += TARGET_PAGE_SIZE; | |
634 | 620 | } |
635 | 621 | return p; |
636 | 622 | } |
... | ... | @@ -657,7 +643,6 @@ static void set_brk(unsigned long start, unsigned long end) |
657 | 643 | static void padzero(unsigned long elf_bss) |
658 | 644 | { |
659 | 645 | unsigned long nbyte; |
660 | - char * fpnt; | |
661 | 646 | |
662 | 647 | /* XXX: this is really a hack : if the real host page size is |
663 | 648 | smaller than the target page size, some pages after the end |
... | ... | @@ -679,55 +664,57 @@ static void padzero(unsigned long elf_bss) |
679 | 664 | nbyte = elf_bss & (qemu_host_page_size-1); |
680 | 665 | if (nbyte) { |
681 | 666 | nbyte = qemu_host_page_size - nbyte; |
682 | - fpnt = (char *) elf_bss; | |
683 | 667 | do { |
684 | - *fpnt++ = 0; | |
668 | + tput8(elf_bss, 0); | |
669 | + elf_bss++; | |
685 | 670 | } while (--nbyte); |
686 | 671 | } |
687 | 672 | } |
688 | 673 | |
689 | -static unsigned int * create_elf_tables(char *p, int argc, int envc, | |
690 | - struct elfhdr * exec, | |
691 | - unsigned long load_addr, | |
692 | - unsigned long load_bias, | |
693 | - unsigned long interp_load_addr, int ibcs, | |
694 | - struct image_info *info) | |
674 | + | |
675 | +static unsigned long create_elf_tables(target_ulong p, int argc, int envc, | |
676 | + struct elfhdr * exec, | |
677 | + unsigned long load_addr, | |
678 | + unsigned long load_bias, | |
679 | + unsigned long interp_load_addr, int ibcs, | |
680 | + struct image_info *info) | |
695 | 681 | { |
696 | - target_ulong *argv, *envp; | |
697 | - target_ulong *sp, *csp; | |
698 | - target_ulong *u_platform; | |
682 | + target_ulong argv, envp; | |
683 | + target_ulong sp; | |
684 | + int size; | |
685 | + target_ulong u_platform; | |
699 | 686 | const char *k_platform; |
700 | - int v; | |
687 | + const int n = sizeof(target_ulong); | |
701 | 688 | |
702 | - /* | |
703 | - * Force 16 byte _final_ alignment here for generality. | |
704 | - */ | |
705 | - sp = (unsigned int *) (~15UL & (unsigned long) p); | |
706 | - u_platform = NULL; | |
689 | + sp = p; | |
690 | + u_platform = 0; | |
707 | 691 | k_platform = ELF_PLATFORM; |
708 | 692 | if (k_platform) { |
709 | 693 | size_t len = strlen(k_platform) + 1; |
710 | - sp -= (len + sizeof(target_ulong) - 1) / sizeof(target_ulong); | |
711 | - u_platform = (target_ulong *)sp; | |
712 | - __copy_to_user(u_platform, k_platform, len); | |
694 | + sp -= (len + n - 1) & ~(n - 1); | |
695 | + u_platform = sp; | |
696 | + memcpy_to_target(sp, k_platform, len); | |
713 | 697 | } |
714 | - csp = sp; | |
715 | - csp -= (DLINFO_ITEMS + 1) * 2; | |
698 | + /* | |
699 | + * Force 16 byte _final_ alignment here for generality. | |
700 | + */ | |
701 | + sp = sp &~ (target_ulong)15; | |
702 | + size = (DLINFO_ITEMS + 1) * 2; | |
716 | 703 | if (k_platform) |
717 | - csp -= 2; | |
704 | + size += 2; | |
718 | 705 | #ifdef DLINFO_ARCH_ITEMS |
719 | - csp -= DLINFO_ARCH_ITEMS*2; | |
706 | + size += DLINFO_ARCH_ITEMS * 2; | |
720 | 707 | #endif |
721 | - csp -= envc+1; | |
722 | - csp -= argc+1; | |
723 | - csp -= (!ibcs ? 3 : 1); /* argc itself */ | |
724 | - if ((unsigned long)csp & 15UL) | |
725 | - sp -= ((unsigned long)csp & 15UL) / sizeof(*sp); | |
708 | + size += envc + argc + 2; | |
709 | + size += (!ibcs ? 3 : 1); /* argc itself */ | |
710 | + size *= n; | |
711 | + if (size & 15) | |
712 | + sp -= 16 - (size & 15); | |
726 | 713 | |
727 | -#define NEW_AUX_ENT(id, val) \ | |
728 | - sp -= 2; \ | |
729 | - put_user (id, sp); \ | |
730 | - put_user (val, sp + 1) | |
714 | +#define NEW_AUX_ENT(id, val) do { \ | |
715 | + sp -= n; tputl(sp, val); \ | |
716 | + sp -= n; tputl(sp, id); \ | |
717 | + } while(0) | |
731 | 718 | NEW_AUX_ENT (AT_NULL, 0); |
732 | 719 | |
733 | 720 | /* There must be exactly DLINFO_ITEMS entries here. */ |
... | ... | @@ -744,7 +731,7 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, |
744 | 731 | NEW_AUX_ENT(AT_EGID, (target_ulong) getegid()); |
745 | 732 | NEW_AUX_ENT(AT_HWCAP, (target_ulong) ELF_HWCAP); |
746 | 733 | if (k_platform) |
747 | - NEW_AUX_ENT(AT_PLATFORM, (target_ulong) u_platform); | |
734 | + NEW_AUX_ENT(AT_PLATFORM, u_platform); | |
748 | 735 | #ifdef ARCH_DLINFO |
749 | 736 | /* |
750 | 737 | * ARCH_DLINFO must come last so platform specific code can enforce |
... | ... | @@ -754,39 +741,32 @@ static unsigned int * create_elf_tables(char *p, int argc, int envc, |
754 | 741 | #endif |
755 | 742 | #undef NEW_AUX_ENT |
756 | 743 | |
757 | - sp -= envc+1; | |
744 | + sp -= (envc + 1) * n; | |
758 | 745 | envp = sp; |
759 | - sp -= argc+1; | |
746 | + sp -= (argc + 1) * n; | |
760 | 747 | argv = sp; |
761 | 748 | if (!ibcs) { |
762 | - put_user((target_ulong)envp,--sp); | |
763 | - put_user((target_ulong)argv,--sp); | |
749 | + sp -= n; tputl(sp, envp); | |
750 | + sp -= n; tputl(sp, argv); | |
764 | 751 | } |
765 | - put_user(argc,--sp); | |
766 | - info->arg_start = (unsigned int)((unsigned long)p & 0xffffffff); | |
752 | + sp -= n; tputl(sp, argc); | |
753 | + info->arg_start = p; | |
767 | 754 | while (argc-->0) { |
768 | - put_user((target_ulong)p,argv++); | |
769 | - do { | |
770 | - get_user(v, p); | |
771 | - p++; | |
772 | - } while (v != 0); | |
755 | + tputl(argv, p); argv += n; | |
756 | + p += target_strlen(p) + 1; | |
773 | 757 | } |
774 | - put_user(0,argv); | |
775 | - info->arg_end = info->env_start = (unsigned int)((unsigned long)p & 0xffffffff); | |
758 | + tputl(argv, 0); | |
759 | + info->arg_end = info->env_start = p; | |
776 | 760 | while (envc-->0) { |
777 | - put_user((target_ulong)p,envp++); | |
778 | - do { | |
779 | - get_user(v, p); | |
780 | - p++; | |
781 | - } while (v != 0); | |
761 | + tputl(envp, p); envp += n; | |
762 | + p += target_strlen(p) + 1; | |
782 | 763 | } |
783 | - put_user(0,envp); | |
784 | - info->env_end = (unsigned int)((unsigned long)p & 0xffffffff); | |
764 | + tputl(envp, 0); | |
765 | + info->env_end = p; | |
785 | 766 | return sp; |
786 | 767 | } |
787 | 768 | |
788 | 769 | |
789 | - | |
790 | 770 | static unsigned long load_elf_interp(struct elfhdr * interp_elf_ex, |
791 | 771 | int interpreter_fd, |
792 | 772 | unsigned long *interp_load_addr) |
... | ... | @@ -1335,8 +1315,7 @@ static int load_elf_binary(struct linux_binprm * bprm, struct target_pt_regs * r |
1335 | 1315 | #ifdef LOW_ELF_STACK |
1336 | 1316 | info->start_stack = bprm->p = elf_stack - 4; |
1337 | 1317 | #endif |
1338 | - bprm->p = (unsigned long) | |
1339 | - create_elf_tables((char *)bprm->p, | |
1318 | + bprm->p = create_elf_tables(bprm->p, | |
1340 | 1319 | bprm->argc, |
1341 | 1320 | bprm->envc, |
1342 | 1321 | &elf_ex, |
... | ... | @@ -1432,6 +1411,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, |
1432 | 1411 | if(retval>=0) { |
1433 | 1412 | retval = load_elf_binary(&bprm,regs,infop); |
1434 | 1413 | } |
1414 | + | |
1435 | 1415 | if(retval>=0) { |
1436 | 1416 | /* success. Initialize important registers */ |
1437 | 1417 | init_thread(regs, infop); |
... | ... | @@ -1440,7 +1420,7 @@ int elf_exec(const char * filename, char ** argv, char ** envp, |
1440 | 1420 | |
1441 | 1421 | /* Something went wrong, return the inode and free the argument pages*/ |
1442 | 1422 | for (i=0 ; i<MAX_ARG_PAGES ; i++) { |
1443 | - free_page((void *)bprm.page[i]); | |
1423 | + free(bprm.page[i]); | |
1444 | 1424 | } |
1445 | 1425 | return(retval); |
1446 | 1426 | } | ... | ... |
linux-user/ioctls.h
... | ... | @@ -55,7 +55,7 @@ |
55 | 55 | IOCTL(KDMKTONE, 0, TYPE_INT) |
56 | 56 | IOCTL(KDGKBTYPE, IOC_R, MK_PTR(TYPE_CHAR)) |
57 | 57 | IOCTL(KDGKBENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbentry))) |
58 | - IOCTL(KDGKBSENT, IOC_RW, TYPE_PTRVOID) | |
58 | + IOCTL(KDGKBSENT, IOC_RW, MK_PTR(MK_STRUCT(STRUCT_kbsentry))) | |
59 | 59 | |
60 | 60 | IOCTL(BLKROSET, IOC_W, MK_PTR(TYPE_INT)) |
61 | 61 | IOCTL(BLKROGET, IOC_R, MK_PTR(TYPE_INT)) | ... | ... |
linux-user/main.c
... | ... | @@ -152,21 +152,25 @@ static void write_dt(void *ptr, unsigned long addr, unsigned long limit, |
152 | 152 | int flags) |
153 | 153 | { |
154 | 154 | unsigned int e1, e2; |
155 | + uint32_t *p; | |
155 | 156 | e1 = (addr << 16) | (limit & 0xffff); |
156 | 157 | e2 = ((addr >> 16) & 0xff) | (addr & 0xff000000) | (limit & 0x000f0000); |
157 | 158 | e2 |= flags; |
158 | - stl((uint8_t *)ptr, e1); | |
159 | - stl((uint8_t *)ptr + 4, e2); | |
159 | + p = ptr; | |
160 | + p[0] = tswapl(e1); | |
161 | + p[1] = tswapl(e2); | |
160 | 162 | } |
161 | 163 | |
162 | 164 | static void set_gate(void *ptr, unsigned int type, unsigned int dpl, |
163 | 165 | unsigned long addr, unsigned int sel) |
164 | 166 | { |
165 | 167 | unsigned int e1, e2; |
168 | + uint32_t *p; | |
166 | 169 | e1 = (addr & 0xffff) | (sel << 16); |
167 | 170 | e2 = (addr & 0xffff0000) | 0x8000 | (dpl << 13) | (type << 8); |
168 | - stl((uint8_t *)ptr, e1); | |
169 | - stl((uint8_t *)ptr + 4, e2); | |
171 | + p = ptr; | |
172 | + p[0] = tswapl(e1); | |
173 | + p[1] = tswapl(e2); | |
170 | 174 | } |
171 | 175 | |
172 | 176 | uint64_t gdt_table[6]; |
... | ... | @@ -343,7 +347,7 @@ void cpu_loop(CPUARMState *env) |
343 | 347 | |
344 | 348 | /* we handle the FPU emulation here, as Linux */ |
345 | 349 | /* we get the opcode */ |
346 | - opcode = ldl_raw((uint8_t *)env->regs[15]); | |
350 | + opcode = tget32(env->regs[15]); | |
347 | 351 | |
348 | 352 | if (EmulateAll(opcode, &ts->fpa, env) == 0) { |
349 | 353 | info.si_signo = SIGILL; |
... | ... | @@ -364,20 +368,20 @@ void cpu_loop(CPUARMState *env) |
364 | 368 | /* system call */ |
365 | 369 | if (trapnr == EXCP_BKPT) { |
366 | 370 | if (env->thumb) { |
367 | - insn = lduw((void *)(env->regs[15])); | |
371 | + insn = tget16(env->regs[15]); | |
368 | 372 | n = insn & 0xff; |
369 | 373 | env->regs[15] += 2; |
370 | 374 | } else { |
371 | - insn = ldl((void *)(env->regs[15])); | |
375 | + insn = tget32(env->regs[15]); | |
372 | 376 | n = (insn & 0xf) | ((insn >> 4) & 0xff0); |
373 | 377 | env->regs[15] += 4; |
374 | 378 | } |
375 | 379 | } else { |
376 | 380 | if (env->thumb) { |
377 | - insn = lduw((void *)(env->regs[15] - 2)); | |
381 | + insn = tget16(env->regs[15] - 2); | |
378 | 382 | n = insn & 0xff; |
379 | 383 | } else { |
380 | - insn = ldl((void *)(env->regs[15] - 4)); | |
384 | + insn = tget32(env->regs[15] - 4); | |
381 | 385 | n = insn & 0xffffff; |
382 | 386 | } |
383 | 387 | } |
... | ... | @@ -475,16 +479,16 @@ static inline int get_reg_index(CPUSPARCState *env, int cwp, int index) |
475 | 479 | static inline void save_window_offset(CPUSPARCState *env, int cwp1) |
476 | 480 | { |
477 | 481 | unsigned int i; |
478 | - uint32_t *sp_ptr; | |
482 | + target_ulong sp_ptr; | |
479 | 483 | |
480 | - sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]); | |
484 | + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; | |
481 | 485 | #if defined(DEBUG_WIN) |
482 | 486 | printf("win_overflow: sp_ptr=0x%x save_cwp=%d\n", |
483 | 487 | (int)sp_ptr, cwp1); |
484 | 488 | #endif |
485 | 489 | for(i = 0; i < 16; i++) { |
486 | - put_user(env->regbase[get_reg_index(env, cwp1, 8 + i)], sp_ptr); | |
487 | - sp_ptr++; | |
490 | + tputl(sp_ptr, env->regbase[get_reg_index(env, cwp1, 8 + i)]); | |
491 | + sp_ptr += sizeof(target_ulong); | |
488 | 492 | } |
489 | 493 | } |
490 | 494 | |
... | ... | @@ -500,22 +504,21 @@ static void save_window(CPUSPARCState *env) |
500 | 504 | static void restore_window(CPUSPARCState *env) |
501 | 505 | { |
502 | 506 | unsigned int new_wim, i, cwp1; |
503 | - uint32_t *sp_ptr, reg; | |
507 | + target_ulong sp_ptr; | |
504 | 508 | |
505 | 509 | new_wim = ((env->wim << 1) | (env->wim >> (NWINDOWS - 1))) & |
506 | 510 | ((1LL << NWINDOWS) - 1); |
507 | 511 | |
508 | 512 | /* restore the invalid window */ |
509 | 513 | cwp1 = (env->cwp + 1) & (NWINDOWS - 1); |
510 | - sp_ptr = (uint32_t *)(env->regbase[get_reg_index(env, cwp1, 6)]); | |
514 | + sp_ptr = env->regbase[get_reg_index(env, cwp1, 6)]; | |
511 | 515 | #if defined(DEBUG_WIN) |
512 | 516 | printf("win_underflow: sp_ptr=0x%x load_cwp=%d\n", |
513 | 517 | (int)sp_ptr, cwp1); |
514 | 518 | #endif |
515 | 519 | for(i = 0; i < 16; i++) { |
516 | - get_user(reg, sp_ptr); | |
517 | - env->regbase[get_reg_index(env, cwp1, 8 + i)] = reg; | |
518 | - sp_ptr++; | |
520 | + env->regbase[get_reg_index(env, cwp1, 8 + i)] = tgetl(sp_ptr); | |
521 | + sp_ptr += sizeof(target_ulong); | |
519 | 522 | } |
520 | 523 | env->wim = new_wim; |
521 | 524 | } |
... | ... | @@ -1304,15 +1307,9 @@ void cpu_loop(CPUMIPSState *env) |
1304 | 1307 | if (nb_args >= 5) { |
1305 | 1308 | sp_reg = env->gpr[29]; |
1306 | 1309 | /* these arguments are taken from the stack */ |
1307 | - if (get_user(arg5, (target_ulong *)(sp_reg + 16))) { | |
1308 | - ret = -EFAULT; | |
1309 | - goto fail; | |
1310 | - } | |
1310 | + arg5 = tgetl(sp_reg + 16); | |
1311 | 1311 | if (nb_args >= 6) { |
1312 | - if (get_user(arg6, (target_ulong *)(sp_reg + 20))) { | |
1313 | - ret = -EFAULT; | |
1314 | - goto fail; | |
1315 | - } | |
1312 | + arg6 = tgetl(sp_reg + 20); | |
1316 | 1313 | } else { |
1317 | 1314 | arg6 = 0; |
1318 | 1315 | } |
... | ... | @@ -1347,8 +1344,7 @@ void cpu_loop(CPUMIPSState *env) |
1347 | 1344 | { |
1348 | 1345 | uint32_t insn, op; |
1349 | 1346 | |
1350 | - if (get_user(insn, (uint32_t *)env->PC) < 0) | |
1351 | - goto sigill; | |
1347 | + insn = tget32(env->PC); | |
1352 | 1348 | op = insn >> 26; |
1353 | 1349 | // printf("insn=%08x op=%02x\n", insn, op); |
1354 | 1350 | /* XXX: totally dummy FP ops just to be able to launch |
... | ... | @@ -1531,7 +1527,7 @@ int main(int argc, char **argv) |
1531 | 1527 | fprintf(logfile, "entry 0x%08lx\n" , info->entry); |
1532 | 1528 | } |
1533 | 1529 | |
1534 | - target_set_brk((char *)info->brk); | |
1530 | + target_set_brk(info->brk); | |
1535 | 1531 | syscall_init(); |
1536 | 1532 | signal_init(); |
1537 | 1533 | |
... | ... | @@ -1566,7 +1562,7 @@ int main(int argc, char **argv) |
1566 | 1562 | env->eip = regs->eip; |
1567 | 1563 | |
1568 | 1564 | /* linux interrupt setup */ |
1569 | - env->idt.base = (long)idt_table; | |
1565 | + env->idt.base = h2g(idt_table); | |
1570 | 1566 | env->idt.limit = sizeof(idt_table) - 1; |
1571 | 1567 | set_idt(0, 0); |
1572 | 1568 | set_idt(1, 0); |
... | ... | @@ -1591,7 +1587,7 @@ int main(int argc, char **argv) |
1591 | 1587 | set_idt(0x80, 3); |
1592 | 1588 | |
1593 | 1589 | /* linux segment setup */ |
1594 | - env->gdt.base = (long)gdt_table; | |
1590 | + env->gdt.base = h2g(gdt_table); | |
1595 | 1591 | env->gdt.limit = sizeof(gdt_table) - 1; |
1596 | 1592 | write_dt(&gdt_table[__USER_CS >> 3], 0, 0xfffff, |
1597 | 1593 | DESC_G_MASK | DESC_B_MASK | DESC_P_MASK | DESC_S_MASK | | ... | ... |
linux-user/mmap.c
... | ... | @@ -29,10 +29,10 @@ |
29 | 29 | |
30 | 30 | //#define DEBUG_MMAP |
31 | 31 | |
32 | -/* NOTE: all the constants are the HOST ones */ | |
33 | -int target_mprotect(unsigned long start, unsigned long len, int prot) | |
32 | +/* NOTE: all the constants are the HOST ones, but addresses are target. */ | |
33 | +int target_mprotect(target_ulong start, target_ulong len, int prot) | |
34 | 34 | { |
35 | - unsigned long end, host_start, host_end, addr; | |
35 | + target_ulong end, host_start, host_end, addr; | |
36 | 36 | int prot1, ret; |
37 | 37 | |
38 | 38 | #ifdef DEBUG_MMAP |
... | ... | @@ -67,7 +67,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) |
67 | 67 | } |
68 | 68 | end = host_end; |
69 | 69 | } |
70 | - ret = mprotect((void *)host_start, qemu_host_page_size, prot1 & PAGE_BITS); | |
70 | + ret = mprotect(g2h(host_start), qemu_host_page_size, prot1 & PAGE_BITS); | |
71 | 71 | if (ret != 0) |
72 | 72 | return ret; |
73 | 73 | host_start += qemu_host_page_size; |
... | ... | @@ -77,7 +77,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) |
77 | 77 | for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { |
78 | 78 | prot1 |= page_get_flags(addr); |
79 | 79 | } |
80 | - ret = mprotect((void *)(host_end - qemu_host_page_size), qemu_host_page_size, | |
80 | + ret = mprotect(g2h(host_end - qemu_host_page_size), qemu_host_page_size, | |
81 | 81 | prot1 & PAGE_BITS); |
82 | 82 | if (ret != 0) |
83 | 83 | return ret; |
... | ... | @@ -86,7 +86,7 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) |
86 | 86 | |
87 | 87 | /* handle the pages in the middle */ |
88 | 88 | if (host_start < host_end) { |
89 | - ret = mprotect((void *)host_start, host_end - host_start, prot); | |
89 | + ret = mprotect(g2h(host_start), host_end - host_start, prot); | |
90 | 90 | if (ret != 0) |
91 | 91 | return ret; |
92 | 92 | } |
... | ... | @@ -95,28 +95,31 @@ int target_mprotect(unsigned long start, unsigned long len, int prot) |
95 | 95 | } |
96 | 96 | |
97 | 97 | /* map an incomplete host page */ |
98 | -int mmap_frag(unsigned long host_start, | |
99 | - unsigned long start, unsigned long end, | |
100 | - int prot, int flags, int fd, unsigned long offset) | |
98 | +static int mmap_frag(target_ulong real_start, | |
99 | + target_ulong start, target_ulong end, | |
100 | + int prot, int flags, int fd, target_ulong offset) | |
101 | 101 | { |
102 | - unsigned long host_end, ret, addr; | |
102 | + target_ulong real_end, ret, addr; | |
103 | + void *host_start; | |
103 | 104 | int prot1, prot_new; |
104 | 105 | |
105 | - host_end = host_start + qemu_host_page_size; | |
106 | + real_end = real_start + qemu_host_page_size; | |
107 | + host_start = g2h(real_start); | |
106 | 108 | |
107 | 109 | /* get the protection of the target pages outside the mapping */ |
108 | 110 | prot1 = 0; |
109 | - for(addr = host_start; addr < host_end; addr++) { | |
111 | + for(addr = real_start; addr < real_end; addr++) { | |
110 | 112 | if (addr < start || addr >= end) |
111 | 113 | prot1 |= page_get_flags(addr); |
112 | 114 | } |
113 | 115 | |
114 | 116 | if (prot1 == 0) { |
115 | 117 | /* no page was there, so we allocate one */ |
116 | - ret = (long)mmap((void *)host_start, qemu_host_page_size, prot, | |
118 | + ret = (long)mmap(host_start, qemu_host_page_size, prot, | |
117 | 119 | flags | MAP_ANONYMOUS, -1, 0); |
118 | 120 | if (ret == -1) |
119 | 121 | return ret; |
122 | + prot1 = prot; | |
120 | 123 | } |
121 | 124 | prot1 &= PAGE_BITS; |
122 | 125 | |
... | ... | @@ -130,31 +133,35 @@ int mmap_frag(unsigned long host_start, |
130 | 133 | |
131 | 134 | /* adjust protection to be able to read */ |
132 | 135 | if (!(prot1 & PROT_WRITE)) |
133 | - mprotect((void *)host_start, qemu_host_page_size, prot1 | PROT_WRITE); | |
136 | + mprotect(host_start, qemu_host_page_size, prot1 | PROT_WRITE); | |
134 | 137 | |
135 | 138 | /* read the corresponding file data */ |
136 | - pread(fd, (void *)start, end - start, offset); | |
139 | + pread(fd, g2h(start), end - start, offset); | |
137 | 140 | |
138 | 141 | /* put final protection */ |
139 | 142 | if (prot_new != (prot1 | PROT_WRITE)) |
140 | - mprotect((void *)host_start, qemu_host_page_size, prot_new); | |
143 | + mprotect(host_start, qemu_host_page_size, prot_new); | |
141 | 144 | } else { |
142 | 145 | /* just update the protection */ |
143 | 146 | if (prot_new != prot1) { |
144 | - mprotect((void *)host_start, qemu_host_page_size, prot_new); | |
147 | + mprotect(host_start, qemu_host_page_size, prot_new); | |
145 | 148 | } |
146 | 149 | } |
147 | 150 | return 0; |
148 | 151 | } |
149 | 152 | |
150 | 153 | /* NOTE: all the constants are the HOST ones */ |
151 | -long target_mmap(unsigned long start, unsigned long len, int prot, | |
152 | - int flags, int fd, unsigned long offset) | |
154 | +long target_mmap(target_ulong start, target_ulong len, int prot, | |
155 | + int flags, int fd, target_ulong offset) | |
153 | 156 | { |
154 | - unsigned long ret, end, host_start, host_end, retaddr, host_offset, host_len; | |
157 | + target_ulong ret, end, real_start, real_end, retaddr, host_offset, host_len; | |
158 | + long host_start; | |
155 | 159 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ |
156 | 160 | defined(__ia64) |
157 | - static unsigned long last_start = 0x40000000; | |
161 | + static target_ulong last_start = 0x40000000; | |
162 | +#elif defined(__CYGWIN__) | |
163 | + /* Cygwin doesn't have a whole lot of address space. */ | |
164 | + static target_ulong last_start = 0x18000000; | |
158 | 165 | #endif |
159 | 166 | |
160 | 167 | #ifdef DEBUG_MMAP |
... | ... | @@ -191,45 +198,49 @@ long target_mmap(unsigned long start, unsigned long len, int prot, |
191 | 198 | len = TARGET_PAGE_ALIGN(len); |
192 | 199 | if (len == 0) |
193 | 200 | return start; |
194 | - host_start = start & qemu_host_page_mask; | |
201 | + real_start = start & qemu_host_page_mask; | |
195 | 202 | |
196 | 203 | if (!(flags & MAP_FIXED)) { |
197 | 204 | #if defined(__alpha__) || defined(__sparc__) || defined(__x86_64__) || \ |
198 | - defined(__ia64) | |
205 | + defined(__ia64) || defined(__CYGWIN__) | |
199 | 206 | /* tell the kenel to search at the same place as i386 */ |
200 | - if (host_start == 0) { | |
201 | - host_start = last_start; | |
207 | + if (real_start == 0) { | |
208 | + real_start = last_start; | |
202 | 209 | last_start += HOST_PAGE_ALIGN(len); |
203 | 210 | } |
204 | 211 | #endif |
205 | 212 | if (qemu_host_page_size != qemu_real_host_page_size) { |
206 | 213 | /* NOTE: this code is only for debugging with '-p' option */ |
214 | + /* ??? Can also occur when TARGET_PAGE_SIZE > host page size. */ | |
207 | 215 | /* reserve a memory area */ |
216 | + /* ??? This needs fixing for remapping. */ | |
217 | +abort(); | |
208 | 218 | host_len = HOST_PAGE_ALIGN(len) + qemu_host_page_size - TARGET_PAGE_SIZE; |
209 | - host_start = (long)mmap((void *)host_start, host_len, PROT_NONE, | |
219 | + real_start = (long)mmap(g2h(real_start), host_len, PROT_NONE, | |
210 | 220 | MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); |
211 | - if (host_start == -1) | |
212 | - return host_start; | |
213 | - host_end = host_start + host_len; | |
214 | - start = HOST_PAGE_ALIGN(host_start); | |
221 | + if (real_start == -1) | |
222 | + return real_start; | |
223 | + real_end = real_start + host_len; | |
224 | + start = HOST_PAGE_ALIGN(real_start); | |
215 | 225 | end = start + HOST_PAGE_ALIGN(len); |
216 | - if (start > host_start) | |
217 | - munmap((void *)host_start, start - host_start); | |
218 | - if (end < host_end) | |
219 | - munmap((void *)end, host_end - end); | |
226 | + if (start > real_start) | |
227 | + munmap((void *)real_start, start - real_start); | |
228 | + if (end < real_end) | |
229 | + munmap((void *)end, real_end - end); | |
220 | 230 | /* use it as a fixed mapping */ |
221 | 231 | flags |= MAP_FIXED; |
222 | 232 | } else { |
223 | 233 | /* if not fixed, no need to do anything */ |
224 | 234 | host_offset = offset & qemu_host_page_mask; |
225 | 235 | host_len = len + offset - host_offset; |
226 | - start = (long)mmap((void *)host_start, host_len, | |
227 | - prot, flags, fd, host_offset); | |
228 | - if (start == -1) | |
229 | - return start; | |
236 | + host_start = (long)mmap(real_start ? g2h(real_start) : NULL, | |
237 | + host_len, prot, flags, fd, host_offset); | |
238 | + if (host_start == -1) | |
239 | + return host_start; | |
230 | 240 | /* update start so that it points to the file position at 'offset' */ |
231 | 241 | if (!(flags & MAP_ANONYMOUS)) |
232 | - start += offset - host_offset; | |
242 | + host_start += offset - host_offset; | |
243 | + start = h2g(host_start); | |
233 | 244 | goto the_end1; |
234 | 245 | } |
235 | 246 | } |
... | ... | @@ -239,7 +250,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, |
239 | 250 | return -1; |
240 | 251 | } |
241 | 252 | end = start + len; |
242 | - host_end = HOST_PAGE_ALIGN(end); | |
253 | + real_end = HOST_PAGE_ALIGN(end); | |
243 | 254 | |
244 | 255 | /* worst case: we cannot map the file because the offset is not |
245 | 256 | aligned, so we read it */ |
... | ... | @@ -257,7 +268,7 @@ long target_mmap(unsigned long start, unsigned long len, int prot, |
257 | 268 | -1, 0); |
258 | 269 | if (retaddr == -1) |
259 | 270 | return retaddr; |
260 | - pread(fd, (void *)start, len, offset); | |
271 | + pread(fd, g2h(start), len, offset); | |
261 | 272 | if (!(prot & PROT_WRITE)) { |
262 | 273 | ret = target_mprotect(start, len, prot); |
263 | 274 | if (ret != 0) |
... | ... | @@ -267,40 +278,40 @@ long target_mmap(unsigned long start, unsigned long len, int prot, |
267 | 278 | } |
268 | 279 | |
269 | 280 | /* handle the start of the mapping */ |
270 | - if (start > host_start) { | |
271 | - if (host_end == host_start + qemu_host_page_size) { | |
281 | + if (start > real_start) { | |
282 | + if (real_end == real_start + qemu_host_page_size) { | |
272 | 283 | /* one single host page */ |
273 | - ret = mmap_frag(host_start, start, end, | |
284 | + ret = mmap_frag(real_start, start, end, | |
274 | 285 | prot, flags, fd, offset); |
275 | 286 | if (ret == -1) |
276 | 287 | return ret; |
277 | 288 | goto the_end1; |
278 | 289 | } |
279 | - ret = mmap_frag(host_start, start, host_start + qemu_host_page_size, | |
290 | + ret = mmap_frag(real_start, start, real_start + qemu_host_page_size, | |
280 | 291 | prot, flags, fd, offset); |
281 | 292 | if (ret == -1) |
282 | 293 | return ret; |
283 | - host_start += qemu_host_page_size; | |
294 | + real_start += qemu_host_page_size; | |
284 | 295 | } |
285 | 296 | /* handle the end of the mapping */ |
286 | - if (end < host_end) { | |
287 | - ret = mmap_frag(host_end - qemu_host_page_size, | |
288 | - host_end - qemu_host_page_size, host_end, | |
297 | + if (end < real_end) { | |
298 | + ret = mmap_frag(real_end - qemu_host_page_size, | |
299 | + real_end - qemu_host_page_size, real_end, | |
289 | 300 | prot, flags, fd, |
290 | - offset + host_end - qemu_host_page_size - start); | |
301 | + offset + real_end - qemu_host_page_size - start); | |
291 | 302 | if (ret == -1) |
292 | 303 | return ret; |
293 | - host_end -= qemu_host_page_size; | |
304 | + real_end -= qemu_host_page_size; | |
294 | 305 | } |
295 | 306 | |
296 | 307 | /* map the middle (easier) */ |
297 | - if (host_start < host_end) { | |
308 | + if (real_start < real_end) { | |
298 | 309 | unsigned long offset1; |
299 | 310 | if (flags & MAP_ANONYMOUS) |
300 | 311 | offset1 = 0; |
301 | 312 | else |
302 | - offset1 = offset + host_start - start; | |
303 | - ret = (long)mmap((void *)host_start, host_end - host_start, | |
313 | + offset1 = offset + real_start - start; | |
314 | + ret = (long)mmap(g2h(real_start), real_end - real_start, | |
304 | 315 | prot, flags, fd, offset1); |
305 | 316 | if (ret == -1) |
306 | 317 | return ret; |
... | ... | @@ -316,9 +327,9 @@ long target_mmap(unsigned long start, unsigned long len, int prot, |
316 | 327 | return start; |
317 | 328 | } |
318 | 329 | |
319 | -int target_munmap(unsigned long start, unsigned long len) | |
330 | +int target_munmap(target_ulong start, target_ulong len) | |
320 | 331 | { |
321 | - unsigned long end, host_start, host_end, addr; | |
332 | + target_ulong end, real_start, real_end, addr; | |
322 | 333 | int prot, ret; |
323 | 334 | |
324 | 335 | #ifdef DEBUG_MMAP |
... | ... | @@ -330,36 +341,36 @@ int target_munmap(unsigned long start, unsigned long len) |
330 | 341 | if (len == 0) |
331 | 342 | return -EINVAL; |
332 | 343 | end = start + len; |
333 | - host_start = start & qemu_host_page_mask; | |
334 | - host_end = HOST_PAGE_ALIGN(end); | |
344 | + real_start = start & qemu_host_page_mask; | |
345 | + real_end = HOST_PAGE_ALIGN(end); | |
335 | 346 | |
336 | - if (start > host_start) { | |
347 | + if (start > real_start) { | |
337 | 348 | /* handle host page containing start */ |
338 | 349 | prot = 0; |
339 | - for(addr = host_start; addr < start; addr += TARGET_PAGE_SIZE) { | |
350 | + for(addr = real_start; addr < start; addr += TARGET_PAGE_SIZE) { | |
340 | 351 | prot |= page_get_flags(addr); |
341 | 352 | } |
342 | - if (host_end == host_start + qemu_host_page_size) { | |
343 | - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { | |
353 | + if (real_end == real_start + qemu_host_page_size) { | |
354 | + for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { | |
344 | 355 | prot |= page_get_flags(addr); |
345 | 356 | } |
346 | - end = host_end; | |
357 | + end = real_end; | |
347 | 358 | } |
348 | 359 | if (prot != 0) |
349 | - host_start += qemu_host_page_size; | |
360 | + real_start += qemu_host_page_size; | |
350 | 361 | } |
351 | - if (end < host_end) { | |
362 | + if (end < real_end) { | |
352 | 363 | prot = 0; |
353 | - for(addr = end; addr < host_end; addr += TARGET_PAGE_SIZE) { | |
364 | + for(addr = end; addr < real_end; addr += TARGET_PAGE_SIZE) { | |
354 | 365 | prot |= page_get_flags(addr); |
355 | 366 | } |
356 | 367 | if (prot != 0) |
357 | - host_end -= qemu_host_page_size; | |
368 | + real_end -= qemu_host_page_size; | |
358 | 369 | } |
359 | 370 | |
360 | 371 | /* unmap what we can */ |
361 | - if (host_start < host_end) { | |
362 | - ret = munmap((void *)host_start, host_end - host_start); | |
372 | + if (real_start < real_end) { | |
373 | + ret = munmap((void *)real_start, real_end - real_start); | |
363 | 374 | if (ret != 0) |
364 | 375 | return ret; |
365 | 376 | } |
... | ... | @@ -370,25 +381,26 @@ int target_munmap(unsigned long start, unsigned long len) |
370 | 381 | |
371 | 382 | /* XXX: currently, we only handle MAP_ANONYMOUS and not MAP_FIXED |
372 | 383 | blocks which have been allocated starting on a host page */ |
373 | -long target_mremap(unsigned long old_addr, unsigned long old_size, | |
374 | - unsigned long new_size, unsigned long flags, | |
375 | - unsigned long new_addr) | |
384 | +long target_mremap(target_ulong old_addr, target_ulong old_size, | |
385 | + target_ulong new_size, unsigned long flags, | |
386 | + target_ulong new_addr) | |
376 | 387 | { |
377 | 388 | int prot; |
378 | 389 | |
379 | 390 | /* XXX: use 5 args syscall */ |
380 | - new_addr = (long)mremap((void *)old_addr, old_size, new_size, flags); | |
391 | + new_addr = (long)mremap(g2h(old_addr), old_size, new_size, flags); | |
381 | 392 | if (new_addr == -1) |
382 | 393 | return new_addr; |
394 | + new_addr = h2g(new_addr); | |
383 | 395 | prot = page_get_flags(old_addr); |
384 | 396 | page_set_flags(old_addr, old_addr + old_size, 0); |
385 | 397 | page_set_flags(new_addr, new_addr + new_size, prot | PAGE_VALID); |
386 | 398 | return new_addr; |
387 | 399 | } |
388 | 400 | |
389 | -int target_msync(unsigned long start, unsigned long len, int flags) | |
401 | +int target_msync(target_ulong start, target_ulong len, int flags) | |
390 | 402 | { |
391 | - unsigned long end; | |
403 | + target_ulong end; | |
392 | 404 | |
393 | 405 | if (start & ~TARGET_PAGE_MASK) |
394 | 406 | return -EINVAL; |
... | ... | @@ -400,6 +412,6 @@ int target_msync(unsigned long start, unsigned long len, int flags) |
400 | 412 | return 0; |
401 | 413 | |
402 | 414 | start &= qemu_host_page_mask; |
403 | - return msync((void *)start, end - start, flags); | |
415 | + return msync(g2h(start), end - start, flags); | |
404 | 416 | } |
405 | 417 | ... | ... |
linux-user/qemu.h
... | ... | @@ -69,7 +69,7 @@ typedef struct TaskState { |
69 | 69 | int swi_errno; |
70 | 70 | #endif |
71 | 71 | #ifdef TARGET_I386 |
72 | - struct target_vm86plus_struct *target_v86; | |
72 | + target_ulong target_v86; | |
73 | 73 | struct vm86_saved_state vm86_saved_regs; |
74 | 74 | struct target_vm86plus_struct vm86plus; |
75 | 75 | uint32_t v86flags; |
... | ... | @@ -84,8 +84,8 @@ extern TaskState *first_task_state; |
84 | 84 | int elf_exec(const char * filename, char ** argv, char ** envp, |
85 | 85 | struct target_pt_regs * regs, struct image_info *infop); |
86 | 86 | |
87 | -void target_set_brk(char *new_brk); | |
88 | -long do_brk(char *new_brk); | |
87 | +void target_set_brk(target_ulong new_brk); | |
88 | +long do_brk(target_ulong new_brk); | |
89 | 89 | void syscall_init(void); |
90 | 90 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
91 | 91 | long arg4, long arg5, long arg6); |
... | ... | @@ -112,19 +112,18 @@ long do_rt_sigreturn(CPUState *env); |
112 | 112 | void save_v86_state(CPUX86State *env); |
113 | 113 | void handle_vm86_trap(CPUX86State *env, int trapno); |
114 | 114 | void handle_vm86_fault(CPUX86State *env); |
115 | -int do_vm86(CPUX86State *env, long subfunction, | |
116 | - struct target_vm86plus_struct * target_v86); | |
115 | +int do_vm86(CPUX86State *env, long subfunction, target_ulong v86_addr); | |
117 | 116 | #endif |
118 | 117 | |
119 | 118 | /* mmap.c */ |
120 | -int target_mprotect(unsigned long start, unsigned long len, int prot); | |
121 | -long target_mmap(unsigned long start, unsigned long len, int prot, | |
122 | - int flags, int fd, unsigned long offset); | |
123 | -int target_munmap(unsigned long start, unsigned long len); | |
124 | -long target_mremap(unsigned long old_addr, unsigned long old_size, | |
125 | - unsigned long new_size, unsigned long flags, | |
126 | - unsigned long new_addr); | |
127 | -int target_msync(unsigned long start, unsigned long len, int flags); | |
119 | +int target_mprotect(target_ulong start, target_ulong len, int prot); | |
120 | +long target_mmap(target_ulong start, target_ulong len, int prot, | |
121 | + int flags, int fd, target_ulong offset); | |
122 | +int target_munmap(target_ulong start, target_ulong len); | |
123 | +long target_mremap(target_ulong old_addr, target_ulong old_size, | |
124 | + target_ulong new_size, unsigned long flags, | |
125 | + target_ulong new_addr); | |
126 | +int target_msync(target_ulong start, target_ulong len, int flags); | |
128 | 127 | |
129 | 128 | /* user access */ |
130 | 129 | |
... | ... | @@ -133,21 +132,22 @@ int target_msync(unsigned long start, unsigned long len, int flags); |
133 | 132 | |
134 | 133 | #define access_ok(type,addr,size) (1) |
135 | 134 | |
135 | +/* NOTE get_user and put_user use host addresses. */ | |
136 | 136 | #define __put_user(x,ptr)\ |
137 | 137 | ({\ |
138 | 138 | int size = sizeof(*ptr);\ |
139 | 139 | switch(size) {\ |
140 | 140 | case 1:\ |
141 | - stb(ptr, (typeof(*ptr))(x));\ | |
141 | + *(uint8_t *)(ptr) = (typeof(*ptr))(x);\ | |
142 | 142 | break;\ |
143 | 143 | case 2:\ |
144 | - stw(ptr, (typeof(*ptr))(x));\ | |
144 | + *(uint16_t *)(ptr) = tswap16((typeof(*ptr))(x));\ | |
145 | 145 | break;\ |
146 | 146 | case 4:\ |
147 | - stl(ptr, (typeof(*ptr))(x));\ | |
147 | + *(uint32_t *)(ptr) = tswap32((typeof(*ptr))(x));\ | |
148 | 148 | break;\ |
149 | 149 | case 8:\ |
150 | - stq(ptr, (typeof(*ptr))(x));\ | |
150 | + *(uint64_t *)(ptr) = tswap64((typeof(*ptr))(x));\ | |
151 | 151 | break;\ |
152 | 152 | default:\ |
153 | 153 | abort();\ |
... | ... | @@ -160,16 +160,16 @@ int target_msync(unsigned long start, unsigned long len, int flags); |
160 | 160 | int size = sizeof(*ptr);\ |
161 | 161 | switch(size) {\ |
162 | 162 | case 1:\ |
163 | - x = (typeof(*ptr))ldub((void *)ptr);\ | |
163 | + x = (typeof(*ptr))*(uint8_t *)(ptr);\ | |
164 | 164 | break;\ |
165 | 165 | case 2:\ |
166 | - x = (typeof(*ptr))lduw((void *)ptr);\ | |
166 | + x = (typeof(*ptr))tswap16(*(uint16_t *)(ptr));\ | |
167 | 167 | break;\ |
168 | 168 | case 4:\ |
169 | - x = (typeof(*ptr))ldl((void *)ptr);\ | |
169 | + x = (typeof(*ptr))tswap32(*(uint32_t *)(ptr));\ | |
170 | 170 | break;\ |
171 | 171 | case 8:\ |
172 | - x = (typeof(*ptr))ldq((void *)ptr);\ | |
172 | + x = (typeof(*ptr))tswap64(*(uint64_t *)(ptr));\ | |
173 | 173 | break;\ |
174 | 174 | default:\ |
175 | 175 | abort();\ |
... | ... | @@ -177,26 +177,6 @@ int target_msync(unsigned long start, unsigned long len, int flags); |
177 | 177 | 0;\ |
178 | 178 | }) |
179 | 179 | |
180 | -static inline unsigned long __copy_to_user(void *dst, const void *src, | |
181 | - unsigned long size) | |
182 | -{ | |
183 | - memcpy(dst, src, size); | |
184 | - return 0; | |
185 | -} | |
186 | - | |
187 | -static inline unsigned long __copy_from_user(void *dst, const void *src, | |
188 | - unsigned long size) | |
189 | -{ | |
190 | - memcpy(dst, src, size); | |
191 | - return 0; | |
192 | -} | |
193 | - | |
194 | -static inline unsigned long __clear_user(void *dst, unsigned long size) | |
195 | -{ | |
196 | - memset(dst, 0, size); | |
197 | - return 0; | |
198 | -} | |
199 | - | |
200 | 180 | #define put_user(x,ptr)\ |
201 | 181 | ({\ |
202 | 182 | int __ret;\ |
... | ... | @@ -217,30 +197,77 @@ static inline unsigned long __clear_user(void *dst, unsigned long size) |
217 | 197 | __ret;\ |
218 | 198 | }) |
219 | 199 | |
220 | -static inline unsigned long copy_to_user(void *dst, const void *src, | |
221 | - unsigned long size) | |
200 | +/* Functions for accessing guest memory. The tget and tput functions | |
201 | + read/write single values, byteswapping as neccessary. The lock_user | |
202 | + gets a pointer to a contiguous area of guest memory, but does not perform | |
203 | + and byteswapping. lock_user may return either a pointer to the guest | |
204 | + memory, or a temporary buffer. */ | |
205 | + | |
206 | +/* Lock an area of guest memory into the host. If copy is true then the | |
207 | + host area will have the same contents as the guest. */ | |
208 | +static inline void *lock_user(target_ulong guest_addr, long len, int copy) | |
222 | 209 | { |
223 | - if (access_ok(VERIFY_WRITE, dst, size)) | |
224 | - return __copy_to_user(dst, src, size); | |
210 | +#ifdef DEBUG_REMAP | |
211 | + void *addr; | |
212 | + addr = malloc(len); | |
213 | + if (copy) | |
214 | + memcpy(addr, g2h(guest_addr), len); | |
225 | 215 | else |
226 | - return size; | |
216 | + memset(addr, 0, len); | |
217 | + return addr; | |
218 | +#else | |
219 | + return g2h(guest_addr); | |
220 | +#endif | |
227 | 221 | } |
228 | 222 | |
229 | -static inline unsigned long copy_from_user(void *dst, const void *src, | |
230 | - unsigned long size) | |
223 | +/* Unlock an area of guest memory. The first LEN bytes must be flushed back | |
224 | + to guest memory. */ | |
225 | +static inline void unlock_user(void *host_addr, target_ulong guest_addr, | |
226 | + long len) | |
231 | 227 | { |
232 | - if (access_ok(VERIFY_READ, src, size)) | |
233 | - return __copy_from_user(dst, src, size); | |
234 | - else | |
235 | - return size; | |
228 | +#ifdef DEBUG_REMAP | |
229 | + if (host_addr == g2h(guest_addr)) | |
230 | + return; | |
231 | + if (len > 0) | |
232 | + memcpy(g2h(guest_addr), host_addr, len); | |
233 | + free(host_addr); | |
234 | +#endif | |
236 | 235 | } |
237 | 236 | |
238 | -static inline unsigned long clear_user(void *dst, unsigned long size) | |
237 | +/* Return the length of a string in target memory. */ | |
238 | +static inline int target_strlen(target_ulong ptr) | |
239 | 239 | { |
240 | - if (access_ok(VERIFY_WRITE, dst, size)) | |
241 | - return __clear_user(dst, size); | |
242 | - else | |
243 | - return size; | |
240 | + return strlen(g2h(ptr)); | |
241 | +} | |
242 | + | |
243 | +/* Like lock_user but for null terminated strings. */ | |
244 | +static inline void *lock_user_string(target_ulong guest_addr) | |
245 | +{ | |
246 | + long len; | |
247 | + len = target_strlen(guest_addr) + 1; | |
248 | + return lock_user(guest_addr, len, 1); | |
244 | 249 | } |
245 | 250 | |
251 | +/* Helper macros for locking/ulocking a target struct. */ | |
252 | +#define lock_user_struct(host_ptr, guest_addr, copy) \ | |
253 | + host_ptr = lock_user(guest_addr, sizeof(*host_ptr), copy) | |
254 | +#define unlock_user_struct(host_ptr, guest_addr, copy) \ | |
255 | + unlock_user(host_ptr, guest_addr, (copy) ? sizeof(*host_ptr) : 0) | |
256 | + | |
257 | +#define tget8(addr) ldub(addr) | |
258 | +#define tput8(addr, val) stb(addr, val) | |
259 | +#define tget16(addr) lduw(addr) | |
260 | +#define tput16(addr, val) stw(addr, val) | |
261 | +#define tget32(addr) ldl(addr) | |
262 | +#define tput32(addr, val) stl(addr, val) | |
263 | +#define tget64(addr) ldq(addr) | |
264 | +#define tput64(addr, val) stq(addr, val) | |
265 | +#if TARGET_LONG_BITS == 64 | |
266 | +#define tgetl(addr) ldq(addr) | |
267 | +#define tputl(addr, val) stq(addr, val) | |
268 | +#else | |
269 | +#define tgetl(addr) ldl(addr) | |
270 | +#define tputl(addr, val) stl(addr, val) | |
271 | +#endif | |
272 | + | |
246 | 273 | #endif /* QEMU_H */ | ... | ... |
linux-user/signal.c
... | ... | @@ -135,7 +135,7 @@ void host_to_target_sigset(target_sigset_t *d, const sigset_t *s) |
135 | 135 | |
136 | 136 | host_to_target_sigset_internal(&d1, s); |
137 | 137 | for(i = 0;i < TARGET_NSIG_WORDS; i++) |
138 | - __put_user(d1.sig[i], &d->sig[i]); | |
138 | + d->sig[i] = tswapl(d1.sig[i]); | |
139 | 139 | } |
140 | 140 | |
141 | 141 | void target_to_host_sigset_internal(sigset_t *d, const target_sigset_t *s) |
... | ... | @@ -168,7 +168,7 @@ void target_to_host_sigset(sigset_t *d, const target_sigset_t *s) |
168 | 168 | int i; |
169 | 169 | |
170 | 170 | for(i = 0;i < TARGET_NSIG_WORDS; i++) |
171 | - __get_user(s1.sig[i], &s->sig[i]); | |
171 | + s1.sig[i] = tswapl(s->sig[i]); | |
172 | 172 | target_to_host_sigset_internal(d, &s1); |
173 | 173 | } |
174 | 174 | |
... | ... | @@ -647,7 +647,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUX86State *env, size_t frame_size) |
647 | 647 | ka->sa.sa_restorer) { |
648 | 648 | esp = (unsigned long) ka->sa.sa_restorer; |
649 | 649 | } |
650 | - return (void *)((esp - frame_size) & -8ul); | |
650 | + return g2h((esp - frame_size) & -8ul); | |
651 | 651 | } |
652 | 652 | |
653 | 653 | static void setup_frame(int sig, struct emulated_sigaction *ka, |
... | ... | @@ -694,7 +694,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
694 | 694 | goto give_sigsegv; |
695 | 695 | |
696 | 696 | /* Set up registers for signal handler */ |
697 | - env->regs[R_ESP] = (unsigned long) frame; | |
697 | + env->regs[R_ESP] = h2g(frame); | |
698 | 698 | env->eip = (unsigned long) ka->sa._sa_handler; |
699 | 699 | |
700 | 700 | cpu_x86_load_seg(env, R_DS, __USER_DS); |
... | ... | @@ -835,7 +835,7 @@ badframe: |
835 | 835 | |
836 | 836 | long do_sigreturn(CPUX86State *env) |
837 | 837 | { |
838 | - struct sigframe *frame = (struct sigframe *)(env->regs[R_ESP] - 8); | |
838 | + struct sigframe *frame = (struct sigframe *)g2h(env->regs[R_ESP] - 8); | |
839 | 839 | target_sigset_t target_set; |
840 | 840 | sigset_t set; |
841 | 841 | int eax, i; |
... | ... | @@ -866,7 +866,7 @@ badframe: |
866 | 866 | |
867 | 867 | long do_rt_sigreturn(CPUX86State *env) |
868 | 868 | { |
869 | - struct rt_sigframe *frame = (struct rt_sigframe *)(env->regs[R_ESP] - 4); | |
869 | + struct rt_sigframe *frame = (struct rt_sigframe *)g2h(env->regs[R_ESP] - 4); | |
870 | 870 | sigset_t set; |
871 | 871 | // stack_t st; |
872 | 872 | int eax; |
... | ... | @@ -1029,7 +1029,7 @@ get_sigframe(struct emulated_sigaction *ka, CPUState *regs, int framesize) |
1029 | 1029 | /* |
1030 | 1030 | * ATPCS B01 mandates 8-byte alignment |
1031 | 1031 | */ |
1032 | - return (void *)((sp - framesize) & ~7); | |
1032 | + return g2h((sp - framesize) & ~7); | |
1033 | 1033 | } |
1034 | 1034 | |
1035 | 1035 | static int |
... | ... | @@ -1084,7 +1084,7 @@ setup_return(CPUState *env, struct emulated_sigaction *ka, |
1084 | 1084 | } |
1085 | 1085 | |
1086 | 1086 | env->regs[0] = usig; |
1087 | - env->regs[13] = (target_ulong)frame; | |
1087 | + env->regs[13] = h2g(frame); | |
1088 | 1088 | env->regs[14] = retcode; |
1089 | 1089 | env->regs[15] = handler & (thumb ? ~1 : ~3); |
1090 | 1090 | |
... | ... | @@ -1130,7 +1130,7 @@ static void setup_rt_frame(int usig, struct emulated_sigaction *ka, |
1130 | 1130 | err |= copy_siginfo_to_user(&frame->info, info); |
1131 | 1131 | |
1132 | 1132 | /* Clear all the bits of the ucontext we don't use. */ |
1133 | - err |= __clear_user(&frame->uc, offsetof(struct ucontext, uc_mcontext)); | |
1133 | + memset(&frame->uc, 0, offsetof(struct target_ucontext, tuc_mcontext)); | |
1134 | 1134 | |
1135 | 1135 | err |= setup_sigcontext(&frame->uc.tuc_mcontext, /*&frame->fpstate,*/ |
1136 | 1136 | env, set->sig[0]); |
... | ... | @@ -1202,7 +1202,7 @@ long do_sigreturn(CPUState *env) |
1202 | 1202 | if (env->regs[13] & 7) |
1203 | 1203 | goto badframe; |
1204 | 1204 | |
1205 | - frame = (struct sigframe *)env->regs[13]; | |
1205 | + frame = (struct sigframe *)g2h(env->regs[13]); | |
1206 | 1206 | |
1207 | 1207 | #if 0 |
1208 | 1208 | if (verify_area(VERIFY_READ, frame, sizeof (*frame))) |
... | ... | @@ -1378,7 +1378,7 @@ static inline void *get_sigframe(struct emulated_sigaction *sa, CPUState *env, u |
1378 | 1378 | sp = current->sas_ss_sp + current->sas_ss_size; |
1379 | 1379 | } |
1380 | 1380 | #endif |
1381 | - return (void *)(sp - framesize); | |
1381 | + return g2h(sp - framesize); | |
1382 | 1382 | } |
1383 | 1383 | |
1384 | 1384 | static int |
... | ... | @@ -1461,10 +1461,10 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
1461 | 1461 | goto sigsegv; |
1462 | 1462 | |
1463 | 1463 | /* 3. signal handler back-trampoline and parameters */ |
1464 | - env->regwptr[UREG_FP] = (target_ulong) sf; | |
1464 | + env->regwptr[UREG_FP] = h2g(sf); | |
1465 | 1465 | env->regwptr[UREG_I0] = sig; |
1466 | - env->regwptr[UREG_I1] = (target_ulong) &sf->info; | |
1467 | - env->regwptr[UREG_I2] = (target_ulong) &sf->info; | |
1466 | + env->regwptr[UREG_I1] = h2g(&sf->info); | |
1467 | + env->regwptr[UREG_I2] = h2g(&sf->info); | |
1468 | 1468 | |
1469 | 1469 | /* 4. signal handler */ |
1470 | 1470 | env->pc = (unsigned long) ka->sa._sa_handler; |
... | ... | @@ -1473,7 +1473,7 @@ static void setup_frame(int sig, struct emulated_sigaction *ka, |
1473 | 1473 | if (ka->sa.sa_restorer) |
1474 | 1474 | env->regwptr[UREG_I7] = (unsigned long)ka->sa.sa_restorer; |
1475 | 1475 | else { |
1476 | - env->regwptr[UREG_I7] = (unsigned long)(&(sf->insns[0]) - 2); | |
1476 | + env->regwptr[UREG_I7] = h2g(&(sf->insns[0]) - 2); | |
1477 | 1477 | |
1478 | 1478 | /* mov __NR_sigreturn, %g1 */ |
1479 | 1479 | err |= __put_user(0x821020d8, &sf->insns[0]); |
... | ... | @@ -1548,7 +1548,7 @@ long do_sigreturn(CPUState *env) |
1548 | 1548 | target_ulong fpu_save; |
1549 | 1549 | int err, i; |
1550 | 1550 | |
1551 | - sf = (struct target_signal_frame *) env->regwptr[UREG_FP]; | |
1551 | + sf = (struct target_signal_frame *)g2h(env->regwptr[UREG_FP]); | |
1552 | 1552 | #if 0 |
1553 | 1553 | fprintf(stderr, "sigreturn\n"); |
1554 | 1554 | fprintf(stderr, "sf: %x pc %x fp %x sp %x\n", sf, env->pc, env->regwptr[UREG_FP], env->regwptr[UREG_SP]); | ... | ... |
linux-user/syscall.c
... | ... | @@ -252,44 +252,43 @@ static inline int is_error(long ret) |
252 | 252 | return (unsigned long)ret >= (unsigned long)(-4096); |
253 | 253 | } |
254 | 254 | |
255 | -static char *target_brk; | |
256 | -static char *target_original_brk; | |
255 | +static target_ulong target_brk; | |
256 | +static target_ulong target_original_brk; | |
257 | 257 | |
258 | -void target_set_brk(char *new_brk) | |
258 | +void target_set_brk(target_ulong new_brk) | |
259 | 259 | { |
260 | - target_brk = new_brk; | |
261 | - target_original_brk = new_brk; | |
260 | + target_original_brk = target_brk = new_brk; | |
262 | 261 | } |
263 | 262 | |
264 | -long do_brk(char *new_brk) | |
263 | +long do_brk(target_ulong new_brk) | |
265 | 264 | { |
266 | - char *brk_page; | |
265 | + target_ulong brk_page; | |
267 | 266 | long mapped_addr; |
268 | 267 | int new_alloc_size; |
269 | 268 | |
270 | 269 | if (!new_brk) |
271 | - return (long)target_brk; | |
270 | + return target_brk; | |
272 | 271 | if (new_brk < target_original_brk) |
273 | 272 | return -ENOMEM; |
274 | 273 | |
275 | - brk_page = (char *)HOST_PAGE_ALIGN((unsigned long)target_brk); | |
274 | + brk_page = HOST_PAGE_ALIGN(target_brk); | |
276 | 275 | |
277 | 276 | /* If the new brk is less than this, set it and we're done... */ |
278 | 277 | if (new_brk < brk_page) { |
279 | 278 | target_brk = new_brk; |
280 | - return (long)target_brk; | |
279 | + return target_brk; | |
281 | 280 | } |
282 | 281 | |
283 | 282 | /* We need to allocate more memory after the brk... */ |
284 | 283 | new_alloc_size = HOST_PAGE_ALIGN(new_brk - brk_page + 1); |
285 | - mapped_addr = get_errno(target_mmap((unsigned long)brk_page, new_alloc_size, | |
284 | + mapped_addr = get_errno(target_mmap(brk_page, new_alloc_size, | |
286 | 285 | PROT_READ|PROT_WRITE, |
287 | 286 | MAP_ANON|MAP_FIXED|MAP_PRIVATE, 0, 0)); |
288 | 287 | if (is_error(mapped_addr)) { |
289 | 288 | return mapped_addr; |
290 | 289 | } else { |
291 | 290 | target_brk = new_brk; |
292 | - return (long)target_brk; | |
291 | + return target_brk; | |
293 | 292 | } |
294 | 293 | } |
295 | 294 | |
... | ... | @@ -354,9 +353,12 @@ static inline long host_to_target_clock_t(long ticks) |
354 | 353 | #endif |
355 | 354 | } |
356 | 355 | |
357 | -static inline void host_to_target_rusage(struct target_rusage *target_rusage, | |
356 | +static inline void host_to_target_rusage(target_ulong target_addr, | |
358 | 357 | const struct rusage *rusage) |
359 | 358 | { |
359 | + struct target_rusage *target_rusage; | |
360 | + | |
361 | + lock_user_struct(target_rusage, target_addr, 0); | |
360 | 362 | target_rusage->ru_utime.tv_sec = tswapl(rusage->ru_utime.tv_sec); |
361 | 363 | target_rusage->ru_utime.tv_usec = tswapl(rusage->ru_utime.tv_usec); |
362 | 364 | target_rusage->ru_stime.tv_sec = tswapl(rusage->ru_stime.tv_sec); |
... | ... | @@ -375,35 +377,64 @@ static inline void host_to_target_rusage(struct target_rusage *target_rusage, |
375 | 377 | target_rusage->ru_nsignals = tswapl(rusage->ru_nsignals); |
376 | 378 | target_rusage->ru_nvcsw = tswapl(rusage->ru_nvcsw); |
377 | 379 | target_rusage->ru_nivcsw = tswapl(rusage->ru_nivcsw); |
380 | + unlock_user_struct(target_rusage, target_addr, 1); | |
378 | 381 | } |
379 | 382 | |
380 | -static inline void target_to_host_timeval(struct timeval *tv, | |
381 | - const struct target_timeval *target_tv) | |
383 | +static inline void target_to_host_timeval(struct timeval *tv, | |
384 | + target_ulong target_addr) | |
382 | 385 | { |
386 | + struct target_timeval *target_tv; | |
387 | + | |
388 | + lock_user_struct(target_tv, target_addr, 1); | |
383 | 389 | tv->tv_sec = tswapl(target_tv->tv_sec); |
384 | 390 | tv->tv_usec = tswapl(target_tv->tv_usec); |
391 | + unlock_user_struct(target_tv, target_addr, 0); | |
385 | 392 | } |
386 | 393 | |
387 | -static inline void host_to_target_timeval(struct target_timeval *target_tv, | |
394 | +static inline void host_to_target_timeval(target_ulong target_addr, | |
388 | 395 | const struct timeval *tv) |
389 | 396 | { |
397 | + struct target_timeval *target_tv; | |
398 | + | |
399 | + lock_user_struct(target_tv, target_addr, 0); | |
390 | 400 | target_tv->tv_sec = tswapl(tv->tv_sec); |
391 | 401 | target_tv->tv_usec = tswapl(tv->tv_usec); |
402 | + unlock_user_struct(target_tv, target_addr, 1); | |
392 | 403 | } |
393 | 404 | |
394 | 405 | |
395 | 406 | static long do_select(long n, |
396 | - target_long *target_rfds, target_long *target_wfds, | |
397 | - target_long *target_efds, struct target_timeval *target_tv) | |
407 | + target_ulong rfd_p, target_ulong wfd_p, | |
408 | + target_ulong efd_p, target_ulong target_tv) | |
398 | 409 | { |
399 | 410 | fd_set rfds, wfds, efds; |
400 | 411 | fd_set *rfds_ptr, *wfds_ptr, *efds_ptr; |
412 | + target_long *target_rfds, *target_wfds, *target_efds; | |
401 | 413 | struct timeval tv, *tv_ptr; |
402 | 414 | long ret; |
415 | + int ok; | |
403 | 416 | |
404 | - rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); | |
405 | - wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); | |
406 | - efds_ptr = target_to_host_fds(&efds, target_efds, n); | |
417 | + if (rfd_p) { | |
418 | + target_rfds = lock_user(rfd_p, sizeof(target_long) * n, 1); | |
419 | + rfds_ptr = target_to_host_fds(&rfds, target_rfds, n); | |
420 | + } else { | |
421 | + target_rfds = NULL; | |
422 | + rfds_ptr = NULL; | |
423 | + } | |
424 | + if (wfd_p) { | |
425 | + target_wfds = lock_user(wfd_p, sizeof(target_long) * n, 1); | |
426 | + wfds_ptr = target_to_host_fds(&wfds, target_wfds, n); | |
427 | + } else { | |
428 | + target_wfds = NULL; | |
429 | + wfds_ptr = NULL; | |
430 | + } | |
431 | + if (efd_p) { | |
432 | + target_efds = lock_user(efd_p, sizeof(target_long) * n, 1); | |
433 | + efds_ptr = target_to_host_fds(&efds, target_efds, n); | |
434 | + } else { | |
435 | + target_efds = NULL; | |
436 | + efds_ptr = NULL; | |
437 | + } | |
407 | 438 | |
408 | 439 | if (target_tv) { |
409 | 440 | target_to_host_timeval(&tv, target_tv); |
... | ... | @@ -412,7 +443,9 @@ static long do_select(long n, |
412 | 443 | tv_ptr = NULL; |
413 | 444 | } |
414 | 445 | ret = get_errno(select(n, rfds_ptr, wfds_ptr, efds_ptr, tv_ptr)); |
415 | - if (!is_error(ret)) { | |
446 | + ok = !is_error(ret); | |
447 | + | |
448 | + if (ok) { | |
416 | 449 | host_to_target_fds(target_rfds, rfds_ptr, n); |
417 | 450 | host_to_target_fds(target_wfds, wfds_ptr, n); |
418 | 451 | host_to_target_fds(target_efds, efds_ptr, n); |
... | ... | @@ -421,25 +454,41 @@ static long do_select(long n, |
421 | 454 | host_to_target_timeval(target_tv, &tv); |
422 | 455 | } |
423 | 456 | } |
457 | + if (target_rfds) | |
458 | + unlock_user(target_rfds, rfd_p, ok ? sizeof(target_long) * n : 0); | |
459 | + if (target_wfds) | |
460 | + unlock_user(target_wfds, wfd_p, ok ? sizeof(target_long) * n : 0); | |
461 | + if (target_efds) | |
462 | + unlock_user(target_efds, efd_p, ok ? sizeof(target_long) * n : 0); | |
463 | + | |
424 | 464 | return ret; |
425 | 465 | } |
426 | 466 | |
427 | 467 | static inline void target_to_host_sockaddr(struct sockaddr *addr, |
428 | - struct target_sockaddr *target_addr, | |
468 | + target_ulong target_addr, | |
429 | 469 | socklen_t len) |
430 | 470 | { |
431 | - memcpy(addr, target_addr, len); | |
432 | - addr->sa_family = tswap16(target_addr->sa_family); | |
471 | + struct target_sockaddr *target_saddr; | |
472 | + | |
473 | + target_saddr = lock_user(target_addr, len, 1); | |
474 | + memcpy(addr, target_saddr, len); | |
475 | + addr->sa_family = tswap16(target_saddr->sa_family); | |
476 | + unlock_user(target_saddr, target_addr, 0); | |
433 | 477 | } |
434 | 478 | |
435 | -static inline void host_to_target_sockaddr(struct target_sockaddr *target_addr, | |
479 | +static inline void host_to_target_sockaddr(target_ulong target_addr, | |
436 | 480 | struct sockaddr *addr, |
437 | 481 | socklen_t len) |
438 | 482 | { |
439 | - memcpy(target_addr, addr, len); | |
440 | - target_addr->sa_family = tswap16(addr->sa_family); | |
483 | + struct target_sockaddr *target_saddr; | |
484 | + | |
485 | + target_saddr = lock_user(target_addr, len, 0); | |
486 | + memcpy(target_saddr, addr, len); | |
487 | + target_saddr->sa_family = tswap16(addr->sa_family); | |
488 | + unlock_user(target_saddr, target_addr, len); | |
441 | 489 | } |
442 | 490 | |
491 | +/* ??? Should this also swap msgh->name? */ | |
443 | 492 | static inline void target_to_host_cmsg(struct msghdr *msgh, |
444 | 493 | struct target_msghdr *target_msgh) |
445 | 494 | { |
... | ... | @@ -484,6 +533,7 @@ static inline void target_to_host_cmsg(struct msghdr *msgh, |
484 | 533 | msgh->msg_controllen = space; |
485 | 534 | } |
486 | 535 | |
536 | +/* ??? Should this also swap msgh->name? */ | |
487 | 537 | static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, |
488 | 538 | struct msghdr *msgh) |
489 | 539 | { |
... | ... | @@ -528,7 +578,7 @@ static inline void host_to_target_cmsg(struct target_msghdr *target_msgh, |
528 | 578 | } |
529 | 579 | |
530 | 580 | static long do_setsockopt(int sockfd, int level, int optname, |
531 | - void *optval, socklen_t optlen) | |
581 | + target_ulong optval, socklen_t optlen) | |
532 | 582 | { |
533 | 583 | int val, ret; |
534 | 584 | |
... | ... | @@ -538,8 +588,7 @@ static long do_setsockopt(int sockfd, int level, int optname, |
538 | 588 | if (optlen < sizeof(uint32_t)) |
539 | 589 | return -EINVAL; |
540 | 590 | |
541 | - if (get_user(val, (uint32_t *)optval)) | |
542 | - return -EFAULT; | |
591 | + val = tget32(optval); | |
543 | 592 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
544 | 593 | break; |
545 | 594 | case SOL_IP: |
... | ... | @@ -561,11 +610,9 @@ static long do_setsockopt(int sockfd, int level, int optname, |
561 | 610 | case IP_MULTICAST_LOOP: |
562 | 611 | val = 0; |
563 | 612 | if (optlen >= sizeof(uint32_t)) { |
564 | - if (get_user(val, (uint32_t *)optval)) | |
565 | - return -EFAULT; | |
613 | + val = tget32(optval); | |
566 | 614 | } else if (optlen >= 1) { |
567 | - if (get_user(val, (uint8_t *)optval)) | |
568 | - return -EFAULT; | |
615 | + val = tget8(optval); | |
569 | 616 | } |
570 | 617 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
571 | 618 | break; |
... | ... | @@ -598,8 +645,8 @@ static long do_setsockopt(int sockfd, int level, int optname, |
598 | 645 | case SO_SNDTIMEO: |
599 | 646 | if (optlen < sizeof(uint32_t)) |
600 | 647 | return -EINVAL; |
601 | - if (get_user(val, (uint32_t *)optval)) | |
602 | - return -EFAULT; | |
648 | + | |
649 | + val = tget32(optval); | |
603 | 650 | ret = get_errno(setsockopt(sockfd, level, optname, &val, sizeof(val))); |
604 | 651 | break; |
605 | 652 | default: |
... | ... | @@ -615,7 +662,7 @@ static long do_setsockopt(int sockfd, int level, int optname, |
615 | 662 | } |
616 | 663 | |
617 | 664 | static long do_getsockopt(int sockfd, int level, int optname, |
618 | - void *optval, socklen_t *optlen) | |
665 | + target_ulong optval, target_ulong optlen) | |
619 | 666 | { |
620 | 667 | int len, lv, val, ret; |
621 | 668 | |
... | ... | @@ -636,8 +683,7 @@ static long do_getsockopt(int sockfd, int level, int optname, |
636 | 683 | case SOL_TCP: |
637 | 684 | /* TCP options all take an 'int' value. */ |
638 | 685 | int_case: |
639 | - if (get_user(len, optlen)) | |
640 | - return -EFAULT; | |
686 | + len = tget32(optlen); | |
641 | 687 | if (len < 0) |
642 | 688 | return -EINVAL; |
643 | 689 | lv = sizeof(int); |
... | ... | @@ -647,10 +693,11 @@ static long do_getsockopt(int sockfd, int level, int optname, |
647 | 693 | val = tswap32(val); |
648 | 694 | if (len > lv) |
649 | 695 | len = lv; |
650 | - if (copy_to_user(optval, &val, len)) | |
651 | - return -EFAULT; | |
652 | - if (put_user(len, optlen)) | |
653 | - return -EFAULT; | |
696 | + if (len == 4) | |
697 | + tput32(optval, val); | |
698 | + else | |
699 | + tput8(optval, val); | |
700 | + tput32(optlen, len); | |
654 | 701 | break; |
655 | 702 | case SOL_IP: |
656 | 703 | switch(optname) { |
... | ... | @@ -669,8 +716,7 @@ static long do_getsockopt(int sockfd, int level, int optname, |
669 | 716 | #endif |
670 | 717 | case IP_MULTICAST_TTL: |
671 | 718 | case IP_MULTICAST_LOOP: |
672 | - if (get_user(len, optlen)) | |
673 | - return -EFAULT; | |
719 | + len = tget32(optlen); | |
674 | 720 | if (len < 0) |
675 | 721 | return -EINVAL; |
676 | 722 | lv = sizeof(int); |
... | ... | @@ -678,20 +724,14 @@ static long do_getsockopt(int sockfd, int level, int optname, |
678 | 724 | if (ret < 0) |
679 | 725 | return ret; |
680 | 726 | if (len < sizeof(int) && len > 0 && val >= 0 && val < 255) { |
681 | - unsigned char ucval = val; | |
682 | 727 | len = 1; |
683 | - if (put_user(len, optlen)) | |
684 | - return -EFAULT; | |
685 | - if (copy_to_user(optval,&ucval,1)) | |
686 | - return -EFAULT; | |
728 | + tput32(optlen, len); | |
729 | + tput8(optval, val); | |
687 | 730 | } else { |
688 | - val = tswap32(val); | |
689 | 731 | if (len > sizeof(int)) |
690 | 732 | len = sizeof(int); |
691 | - if (put_user(len, optlen)) | |
692 | - return -EFAULT; | |
693 | - if (copy_to_user(optval, &val, len)) | |
694 | - return -EFAULT; | |
733 | + tput32(optlen, len); | |
734 | + tput32(optval, val); | |
695 | 735 | } |
696 | 736 | break; |
697 | 737 | default: |
... | ... | @@ -708,25 +748,57 @@ static long do_getsockopt(int sockfd, int level, int optname, |
708 | 748 | return ret; |
709 | 749 | } |
710 | 750 | |
711 | -static long do_socketcall(int num, int32_t *vptr) | |
751 | +static void lock_iovec(struct iovec *vec, target_ulong target_addr, | |
752 | + int count, int copy) | |
753 | +{ | |
754 | + struct target_iovec *target_vec; | |
755 | + target_ulong base; | |
756 | + int i; | |
757 | + | |
758 | + target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | |
759 | + for(i = 0;i < count; i++) { | |
760 | + base = tswapl(target_vec[i].iov_base); | |
761 | + vec[i].iov_len = tswapl(target_vec[i].iov_len); | |
762 | + vec[i].iov_base = lock_user(base, vec[i].iov_len, copy); | |
763 | + } | |
764 | + unlock_user (target_vec, target_addr, 0); | |
765 | +} | |
766 | + | |
767 | +static void unlock_iovec(struct iovec *vec, target_ulong target_addr, | |
768 | + int count, int copy) | |
769 | +{ | |
770 | + struct target_iovec *target_vec; | |
771 | + target_ulong base; | |
772 | + int i; | |
773 | + | |
774 | + target_vec = lock_user(target_addr, count * sizeof(struct target_iovec), 1); | |
775 | + for(i = 0;i < count; i++) { | |
776 | + base = tswapl(target_vec[i].iov_base); | |
777 | + unlock_user(vec[i].iov_base, base, copy ? vec[i].iov_len : 0); | |
778 | + } | |
779 | + unlock_user (target_vec, target_addr, 0); | |
780 | +} | |
781 | + | |
782 | +static long do_socketcall(int num, target_ulong vptr) | |
712 | 783 | { |
713 | 784 | long ret; |
785 | + const int n = sizeof(target_ulong); | |
714 | 786 | |
715 | 787 | switch(num) { |
716 | 788 | case SOCKOP_socket: |
717 | 789 | { |
718 | - int domain = tswap32(vptr[0]); | |
719 | - int type = tswap32(vptr[1]); | |
720 | - int protocol = tswap32(vptr[2]); | |
790 | + int domain = tgetl(vptr); | |
791 | + int type = tgetl(vptr + n); | |
792 | + int protocol = tgetl(vptr + 2 * n); | |
721 | 793 | |
722 | 794 | ret = get_errno(socket(domain, type, protocol)); |
723 | 795 | } |
724 | 796 | break; |
725 | 797 | case SOCKOP_bind: |
726 | 798 | { |
727 | - int sockfd = tswap32(vptr[0]); | |
728 | - void *target_addr = (void *)tswap32(vptr[1]); | |
729 | - socklen_t addrlen = tswap32(vptr[2]); | |
799 | + int sockfd = tgetl(vptr); | |
800 | + target_ulong target_addr = tgetl(vptr + n); | |
801 | + socklen_t addrlen = tgetl(vptr + 2 * n); | |
730 | 802 | void *addr = alloca(addrlen); |
731 | 803 | |
732 | 804 | target_to_host_sockaddr(addr, target_addr, addrlen); |
... | ... | @@ -735,9 +807,9 @@ static long do_socketcall(int num, int32_t *vptr) |
735 | 807 | break; |
736 | 808 | case SOCKOP_connect: |
737 | 809 | { |
738 | - int sockfd = tswap32(vptr[0]); | |
739 | - void *target_addr = (void *)tswap32(vptr[1]); | |
740 | - socklen_t addrlen = tswap32(vptr[2]); | |
810 | + int sockfd = tgetl(vptr); | |
811 | + target_ulong target_addr = tgetl(vptr + n); | |
812 | + socklen_t addrlen = tgetl(vptr + 2 * n); | |
741 | 813 | void *addr = alloca(addrlen); |
742 | 814 | |
743 | 815 | target_to_host_sockaddr(addr, target_addr, addrlen); |
... | ... | @@ -746,128 +818,142 @@ static long do_socketcall(int num, int32_t *vptr) |
746 | 818 | break; |
747 | 819 | case SOCKOP_listen: |
748 | 820 | { |
749 | - int sockfd = tswap32(vptr[0]); | |
750 | - int backlog = tswap32(vptr[1]); | |
821 | + int sockfd = tgetl(vptr); | |
822 | + int backlog = tgetl(vptr + n); | |
751 | 823 | |
752 | 824 | ret = get_errno(listen(sockfd, backlog)); |
753 | 825 | } |
754 | 826 | break; |
755 | 827 | case SOCKOP_accept: |
756 | 828 | { |
757 | - int sockfd = tswap32(vptr[0]); | |
758 | - void *target_addr = (void *)tswap32(vptr[1]); | |
759 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | |
760 | - socklen_t addrlen = tswap32(*target_addrlen); | |
829 | + int sockfd = tgetl(vptr); | |
830 | + target_ulong target_addr = tgetl(vptr + n); | |
831 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | |
832 | + socklen_t addrlen = tget32(target_addrlen); | |
761 | 833 | void *addr = alloca(addrlen); |
762 | 834 | |
763 | 835 | ret = get_errno(accept(sockfd, addr, &addrlen)); |
764 | 836 | if (!is_error(ret)) { |
765 | 837 | host_to_target_sockaddr(target_addr, addr, addrlen); |
766 | - *target_addrlen = tswap32(addrlen); | |
838 | + tput32(target_addrlen, addrlen); | |
767 | 839 | } |
768 | 840 | } |
769 | 841 | break; |
770 | 842 | case SOCKOP_getsockname: |
771 | 843 | { |
772 | - int sockfd = tswap32(vptr[0]); | |
773 | - void *target_addr = (void *)tswap32(vptr[1]); | |
774 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | |
775 | - socklen_t addrlen = tswap32(*target_addrlen); | |
844 | + int sockfd = tgetl(vptr); | |
845 | + target_ulong target_addr = tgetl(vptr + n); | |
846 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | |
847 | + socklen_t addrlen = tget32(target_addrlen); | |
776 | 848 | void *addr = alloca(addrlen); |
777 | 849 | |
778 | 850 | ret = get_errno(getsockname(sockfd, addr, &addrlen)); |
779 | 851 | if (!is_error(ret)) { |
780 | 852 | host_to_target_sockaddr(target_addr, addr, addrlen); |
781 | - *target_addrlen = tswap32(addrlen); | |
853 | + tput32(target_addrlen, addrlen); | |
782 | 854 | } |
783 | 855 | } |
784 | 856 | break; |
785 | 857 | case SOCKOP_getpeername: |
786 | 858 | { |
787 | - int sockfd = tswap32(vptr[0]); | |
788 | - void *target_addr = (void *)tswap32(vptr[1]); | |
789 | - uint32_t *target_addrlen = (void *)tswap32(vptr[2]); | |
790 | - socklen_t addrlen = tswap32(*target_addrlen); | |
859 | + int sockfd = tgetl(vptr); | |
860 | + target_ulong target_addr = tgetl(vptr + n); | |
861 | + target_ulong target_addrlen = tgetl(vptr + 2 * n); | |
862 | + socklen_t addrlen = tget32(target_addrlen); | |
791 | 863 | void *addr = alloca(addrlen); |
792 | 864 | |
793 | 865 | ret = get_errno(getpeername(sockfd, addr, &addrlen)); |
794 | 866 | if (!is_error(ret)) { |
795 | 867 | host_to_target_sockaddr(target_addr, addr, addrlen); |
796 | - *target_addrlen = tswap32(addrlen); | |
868 | + tput32(target_addrlen, addrlen); | |
797 | 869 | } |
798 | 870 | } |
799 | 871 | break; |
800 | 872 | case SOCKOP_socketpair: |
801 | 873 | { |
802 | - int domain = tswap32(vptr[0]); | |
803 | - int type = tswap32(vptr[1]); | |
804 | - int protocol = tswap32(vptr[2]); | |
805 | - int32_t *target_tab = (void *)tswap32(vptr[3]); | |
874 | + int domain = tgetl(vptr); | |
875 | + int type = tgetl(vptr + n); | |
876 | + int protocol = tgetl(vptr + 2 * n); | |
877 | + target_ulong target_tab = tgetl(vptr + 3 * n); | |
806 | 878 | int tab[2]; |
807 | 879 | |
808 | 880 | ret = get_errno(socketpair(domain, type, protocol, tab)); |
809 | 881 | if (!is_error(ret)) { |
810 | - target_tab[0] = tswap32(tab[0]); | |
811 | - target_tab[1] = tswap32(tab[1]); | |
882 | + tput32(target_tab, tab[0]); | |
883 | + tput32(target_tab + 4, tab[1]); | |
812 | 884 | } |
813 | 885 | } |
814 | 886 | break; |
815 | 887 | case SOCKOP_send: |
816 | 888 | { |
817 | - int sockfd = tswap32(vptr[0]); | |
818 | - void *msg = (void *)tswap32(vptr[1]); | |
819 | - size_t len = tswap32(vptr[2]); | |
820 | - int flags = tswap32(vptr[3]); | |
889 | + int sockfd = tgetl(vptr); | |
890 | + target_ulong msg = tgetl(vptr + n); | |
891 | + size_t len = tgetl(vptr + 2 * n); | |
892 | + int flags = tgetl(vptr + 3 * n); | |
893 | + void *host_msg; | |
821 | 894 | |
822 | - ret = get_errno(send(sockfd, msg, len, flags)); | |
895 | + host_msg = lock_user(msg, len, 1); | |
896 | + ret = get_errno(send(sockfd, host_msg, len, flags)); | |
897 | + unlock_user(host_msg, msg, 0); | |
823 | 898 | } |
824 | 899 | break; |
825 | 900 | case SOCKOP_recv: |
826 | 901 | { |
827 | - int sockfd = tswap32(vptr[0]); | |
828 | - void *msg = (void *)tswap32(vptr[1]); | |
829 | - size_t len = tswap32(vptr[2]); | |
830 | - int flags = tswap32(vptr[3]); | |
902 | + int sockfd = tgetl(vptr); | |
903 | + target_ulong msg = tgetl(vptr + n); | |
904 | + size_t len = tgetl(vptr + 2 * n); | |
905 | + int flags = tgetl(vptr + 3 * n); | |
906 | + void *host_msg; | |
831 | 907 | |
832 | - ret = get_errno(recv(sockfd, msg, len, flags)); | |
908 | + host_msg = lock_user(msg, len, 0); | |
909 | + ret = get_errno(recv(sockfd, host_msg, len, flags)); | |
910 | + unlock_user(host_msg, msg, ret); | |
833 | 911 | } |
834 | 912 | break; |
835 | 913 | case SOCKOP_sendto: |
836 | 914 | { |
837 | - int sockfd = tswap32(vptr[0]); | |
838 | - void *msg = (void *)tswap32(vptr[1]); | |
839 | - size_t len = tswap32(vptr[2]); | |
840 | - int flags = tswap32(vptr[3]); | |
841 | - void *target_addr = (void *)tswap32(vptr[4]); | |
842 | - socklen_t addrlen = tswap32(vptr[5]); | |
915 | + int sockfd = tgetl(vptr); | |
916 | + target_ulong msg = tgetl(vptr + n); | |
917 | + size_t len = tgetl(vptr + 2 * n); | |
918 | + int flags = tgetl(vptr + 3 * n); | |
919 | + target_ulong target_addr = tgetl(vptr + 4 * n); | |
920 | + socklen_t addrlen = tgetl(vptr + 5 * n); | |
843 | 921 | void *addr = alloca(addrlen); |
922 | + void *host_msg; | |
844 | 923 | |
924 | + host_msg = lock_user(msg, len, 1); | |
845 | 925 | target_to_host_sockaddr(addr, target_addr, addrlen); |
846 | - ret = get_errno(sendto(sockfd, msg, len, flags, addr, addrlen)); | |
926 | + ret = get_errno(sendto(sockfd, host_msg, len, flags, addr, addrlen)); | |
927 | + unlock_user(host_msg, msg, 0); | |
847 | 928 | } |
848 | 929 | break; |
849 | 930 | case SOCKOP_recvfrom: |
850 | 931 | { |
851 | - int sockfd = tswap32(vptr[0]); | |
852 | - void *msg = (void *)tswap32(vptr[1]); | |
853 | - size_t len = tswap32(vptr[2]); | |
854 | - int flags = tswap32(vptr[3]); | |
855 | - void *target_addr = (void *)tswap32(vptr[4]); | |
856 | - uint32_t *target_addrlen = (void *)tswap32(vptr[5]); | |
857 | - socklen_t addrlen = tswap32(*target_addrlen); | |
932 | + int sockfd = tgetl(vptr); | |
933 | + target_ulong msg = tgetl(vptr + n); | |
934 | + size_t len = tgetl(vptr + 2 * n); | |
935 | + int flags = tgetl(vptr + 3 * n); | |
936 | + target_ulong target_addr = tgetl(vptr + 4 * n); | |
937 | + target_ulong target_addrlen = tgetl(vptr + 5 * n); | |
938 | + socklen_t addrlen = tget32(target_addrlen); | |
858 | 939 | void *addr = alloca(addrlen); |
940 | + void *host_msg; | |
859 | 941 | |
860 | - ret = get_errno(recvfrom(sockfd, msg, len, flags, addr, &addrlen)); | |
942 | + host_msg = lock_user(msg, len, 0); | |
943 | + ret = get_errno(recvfrom(sockfd, host_msg, len, flags, addr, &addrlen)); | |
861 | 944 | if (!is_error(ret)) { |
862 | 945 | host_to_target_sockaddr(target_addr, addr, addrlen); |
863 | - *target_addrlen = tswap32(addrlen); | |
946 | + tput32(target_addrlen, addrlen); | |
947 | + unlock_user(host_msg, msg, len); | |
948 | + } else { | |
949 | + unlock_user(host_msg, msg, 0); | |
864 | 950 | } |
865 | 951 | } |
866 | 952 | break; |
867 | 953 | case SOCKOP_shutdown: |
868 | 954 | { |
869 | - int sockfd = tswap32(vptr[0]); | |
870 | - int how = tswap32(vptr[1]); | |
955 | + int sockfd = tgetl(vptr); | |
956 | + int how = tgetl(vptr + n); | |
871 | 957 | |
872 | 958 | ret = get_errno(shutdown(sockfd, how)); |
873 | 959 | } |
... | ... | @@ -876,32 +962,39 @@ static long do_socketcall(int num, int32_t *vptr) |
876 | 962 | case SOCKOP_recvmsg: |
877 | 963 | { |
878 | 964 | int fd; |
965 | + target_ulong target_msg; | |
879 | 966 | struct target_msghdr *msgp; |
880 | 967 | struct msghdr msg; |
881 | - int flags, count, i; | |
968 | + int flags, count; | |
882 | 969 | struct iovec *vec; |
883 | - struct target_iovec *target_vec; | |
884 | - | |
885 | - msgp = (void *)tswap32(vptr[1]); | |
886 | - msg.msg_name = (void *)tswapl(msgp->msg_name); | |
887 | - msg.msg_namelen = tswapl(msgp->msg_namelen); | |
970 | + target_ulong target_vec; | |
971 | + int send = (num == SOCKOP_sendmsg); | |
972 | + | |
973 | + target_msg = tgetl(vptr + n); | |
974 | + lock_user_struct(msgp, target_msg, 1); | |
975 | + if (msgp->msg_name) { | |
976 | + msg.msg_namelen = tswap32(msgp->msg_namelen); | |
977 | + msg.msg_name = alloca(msg.msg_namelen); | |
978 | + target_to_host_sockaddr(msg.msg_name, tswapl(msgp->msg_name), | |
979 | + msg.msg_namelen); | |
980 | + } else { | |
981 | + msg.msg_name = NULL; | |
982 | + msg.msg_namelen = 0; | |
983 | + } | |
888 | 984 | msg.msg_controllen = 2 * tswapl(msgp->msg_controllen); |
889 | 985 | msg.msg_control = alloca(msg.msg_controllen); |
890 | 986 | msg.msg_flags = tswap32(msgp->msg_flags); |
891 | 987 | |
892 | 988 | count = tswapl(msgp->msg_iovlen); |
893 | 989 | vec = alloca(count * sizeof(struct iovec)); |
894 | - target_vec = (void *)tswapl(msgp->msg_iov); | |
895 | - for(i = 0;i < count; i++) { | |
896 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | |
897 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | |
898 | - } | |
990 | + target_vec = tswapl(msgp->msg_iov); | |
991 | + lock_iovec(vec, target_vec, count, send); | |
899 | 992 | msg.msg_iovlen = count; |
900 | 993 | msg.msg_iov = vec; |
901 | 994 | |
902 | - fd = tswap32(vptr[0]); | |
903 | - flags = tswap32(vptr[2]); | |
904 | - if (num == SOCKOP_sendmsg) { | |
995 | + fd = tgetl(vptr); | |
996 | + flags = tgetl(vptr + 2 * n); | |
997 | + if (send) { | |
905 | 998 | target_to_host_cmsg(&msg, msgp); |
906 | 999 | ret = get_errno(sendmsg(fd, &msg, flags)); |
907 | 1000 | } else { |
... | ... | @@ -909,26 +1002,27 @@ static long do_socketcall(int num, int32_t *vptr) |
909 | 1002 | if (!is_error(ret)) |
910 | 1003 | host_to_target_cmsg(msgp, &msg); |
911 | 1004 | } |
1005 | + unlock_iovec(vec, target_vec, count, !send); | |
912 | 1006 | } |
913 | 1007 | break; |
914 | 1008 | case SOCKOP_setsockopt: |
915 | 1009 | { |
916 | - int sockfd = tswap32(vptr[0]); | |
917 | - int level = tswap32(vptr[1]); | |
918 | - int optname = tswap32(vptr[2]); | |
919 | - void *optval = (void *)tswap32(vptr[3]); | |
920 | - socklen_t optlen = tswap32(vptr[4]); | |
1010 | + int sockfd = tgetl(vptr); | |
1011 | + int level = tgetl(vptr + n); | |
1012 | + int optname = tgetl(vptr + 2 * n); | |
1013 | + target_ulong optval = tgetl(vptr + 3 * n); | |
1014 | + socklen_t optlen = tgetl(vptr + 4 * n); | |
921 | 1015 | |
922 | 1016 | ret = do_setsockopt(sockfd, level, optname, optval, optlen); |
923 | 1017 | } |
924 | 1018 | break; |
925 | 1019 | case SOCKOP_getsockopt: |
926 | 1020 | { |
927 | - int sockfd = tswap32(vptr[0]); | |
928 | - int level = tswap32(vptr[1]); | |
929 | - int optname = tswap32(vptr[2]); | |
930 | - void *optval = (void *)tswap32(vptr[3]); | |
931 | - uint32_t *poptlen = (void *)tswap32(vptr[4]); | |
1021 | + int sockfd = tgetl(vptr); | |
1022 | + int level = tgetl(vptr + n); | |
1023 | + int optname = tgetl(vptr + 2 * n); | |
1024 | + target_ulong optval = tgetl(vptr + 3 * n); | |
1025 | + target_ulong poptlen = tgetl(vptr + 4 * n); | |
932 | 1026 | |
933 | 1027 | ret = do_getsockopt(sockfd, level, optname, optval, poptlen); |
934 | 1028 | } |
... | ... | @@ -949,6 +1043,7 @@ static struct shm_region { |
949 | 1043 | uint32_t size; |
950 | 1044 | } shm_regions[N_SHM_REGIONS]; |
951 | 1045 | |
1046 | +/* ??? This only works with linear mappings. */ | |
952 | 1047 | static long do_ipc(long call, long first, long second, long third, |
953 | 1048 | long ptr, long fifth) |
954 | 1049 | { |
... | ... | @@ -1065,12 +1160,15 @@ IOCTLEntry ioctl_entries[] = { |
1065 | 1160 | { 0, 0, }, |
1066 | 1161 | }; |
1067 | 1162 | |
1163 | +/* ??? Implement proper locking for ioctls. */ | |
1068 | 1164 | static long do_ioctl(long fd, long cmd, long arg) |
1069 | 1165 | { |
1070 | 1166 | const IOCTLEntry *ie; |
1071 | 1167 | const argtype *arg_type; |
1072 | 1168 | long ret; |
1073 | 1169 | uint8_t buf_temp[MAX_STRUCT_SIZE]; |
1170 | + int target_size; | |
1171 | + void *argptr; | |
1074 | 1172 | |
1075 | 1173 | ie = ioctl_entries; |
1076 | 1174 | for(;;) { |
... | ... | @@ -1098,23 +1196,32 @@ static long do_ioctl(long fd, long cmd, long arg) |
1098 | 1196 | break; |
1099 | 1197 | case TYPE_PTR: |
1100 | 1198 | arg_type++; |
1199 | + target_size = thunk_type_size(arg_type, 0); | |
1101 | 1200 | switch(ie->access) { |
1102 | 1201 | case IOC_R: |
1103 | 1202 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1104 | 1203 | if (!is_error(ret)) { |
1105 | - thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET); | |
1204 | + argptr = lock_user(arg, target_size, 0); | |
1205 | + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); | |
1206 | + unlock_user(argptr, arg, target_size); | |
1106 | 1207 | } |
1107 | 1208 | break; |
1108 | 1209 | case IOC_W: |
1109 | - thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST); | |
1210 | + argptr = lock_user(arg, target_size, 1); | |
1211 | + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); | |
1212 | + unlock_user(argptr, arg, 0); | |
1110 | 1213 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1111 | 1214 | break; |
1112 | 1215 | default: |
1113 | 1216 | case IOC_RW: |
1114 | - thunk_convert(buf_temp, (void *)arg, arg_type, THUNK_HOST); | |
1217 | + argptr = lock_user(arg, target_size, 1); | |
1218 | + thunk_convert(buf_temp, argptr, arg_type, THUNK_HOST); | |
1219 | + unlock_user(argptr, arg, 0); | |
1115 | 1220 | ret = get_errno(ioctl(fd, ie->host_cmd, buf_temp)); |
1116 | 1221 | if (!is_error(ret)) { |
1117 | - thunk_convert((void *)arg, buf_temp, arg_type, THUNK_TARGET); | |
1222 | + argptr = lock_user(arg, target_size, 0); | |
1223 | + thunk_convert(argptr, buf_temp, arg_type, THUNK_TARGET); | |
1224 | + unlock_user(argptr, arg, target_size); | |
1118 | 1225 | } |
1119 | 1226 | break; |
1120 | 1227 | } |
... | ... | @@ -1338,35 +1445,41 @@ static bitmask_transtbl fcntl_flags_tbl[] = { |
1338 | 1445 | /* NOTE: there is really one LDT for all the threads */ |
1339 | 1446 | uint8_t *ldt_table; |
1340 | 1447 | |
1341 | -static int read_ldt(void *ptr, unsigned long bytecount) | |
1448 | +static int read_ldt(target_ulong ptr, unsigned long bytecount) | |
1342 | 1449 | { |
1343 | 1450 | int size; |
1451 | + void *p; | |
1344 | 1452 | |
1345 | 1453 | if (!ldt_table) |
1346 | 1454 | return 0; |
1347 | 1455 | size = TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE; |
1348 | 1456 | if (size > bytecount) |
1349 | 1457 | size = bytecount; |
1350 | - memcpy(ptr, ldt_table, size); | |
1458 | + p = lock_user(ptr, size, 0); | |
1459 | + /* ??? Shoudl this by byteswapped? */ | |
1460 | + memcpy(p, ldt_table, size); | |
1461 | + unlock_user(p, ptr, size); | |
1351 | 1462 | return size; |
1352 | 1463 | } |
1353 | 1464 | |
1354 | 1465 | /* XXX: add locking support */ |
1355 | 1466 | static int write_ldt(CPUX86State *env, |
1356 | - void *ptr, unsigned long bytecount, int oldmode) | |
1467 | + target_ulong ptr, unsigned long bytecount, int oldmode) | |
1357 | 1468 | { |
1358 | 1469 | struct target_modify_ldt_ldt_s ldt_info; |
1470 | + struct target_modify_ldt_ldt_s *target_ldt_info; | |
1359 | 1471 | int seg_32bit, contents, read_exec_only, limit_in_pages; |
1360 | 1472 | int seg_not_present, useable; |
1361 | 1473 | uint32_t *lp, entry_1, entry_2; |
1362 | 1474 | |
1363 | 1475 | if (bytecount != sizeof(ldt_info)) |
1364 | 1476 | return -EINVAL; |
1365 | - memcpy(&ldt_info, ptr, sizeof(ldt_info)); | |
1366 | - tswap32s(&ldt_info.entry_number); | |
1367 | - tswapls((long *)&ldt_info.base_addr); | |
1368 | - tswap32s(&ldt_info.limit); | |
1369 | - tswap32s(&ldt_info.flags); | |
1477 | + lock_user_struct(target_ldt_info, ptr, 1); | |
1478 | + ldt_info.entry_number = tswap32(target_ldt_info->entry_number); | |
1479 | + ldt_info.base_addr = tswapl(target_ldt_info->base_addr); | |
1480 | + ldt_info.limit = tswap32(target_ldt_info->limit); | |
1481 | + ldt_info.flags = tswap32(target_ldt_info->flags); | |
1482 | + unlock_user_struct(target_ldt_info, ptr, 0); | |
1370 | 1483 | |
1371 | 1484 | if (ldt_info.entry_number >= TARGET_LDT_ENTRIES) |
1372 | 1485 | return -EINVAL; |
... | ... | @@ -1389,7 +1502,7 @@ static int write_ldt(CPUX86State *env, |
1389 | 1502 | if (!ldt_table) |
1390 | 1503 | return -ENOMEM; |
1391 | 1504 | memset(ldt_table, 0, TARGET_LDT_ENTRIES * TARGET_LDT_ENTRY_SIZE); |
1392 | - env->ldt.base = (long)ldt_table; | |
1505 | + env->ldt.base = h2g(ldt_table); | |
1393 | 1506 | env->ldt.limit = 0xffff; |
1394 | 1507 | } |
1395 | 1508 | |
... | ... | @@ -1432,7 +1545,7 @@ install: |
1432 | 1545 | } |
1433 | 1546 | |
1434 | 1547 | /* specific and weird i386 syscalls */ |
1435 | -int do_modify_ldt(CPUX86State *env, int func, void *ptr, unsigned long bytecount) | |
1548 | +int do_modify_ldt(CPUX86State *env, int func, target_ulong ptr, unsigned long bytecount) | |
1436 | 1549 | { |
1437 | 1550 | int ret = -ENOSYS; |
1438 | 1551 | |
... | ... | @@ -1523,31 +1636,35 @@ int do_fork(CPUState *env, unsigned int flags, unsigned long newsp) |
1523 | 1636 | return ret; |
1524 | 1637 | } |
1525 | 1638 | |
1526 | -static long do_fcntl(int fd, int cmd, unsigned long arg) | |
1639 | +static long do_fcntl(int fd, int cmd, target_ulong arg) | |
1527 | 1640 | { |
1528 | 1641 | struct flock fl; |
1529 | - struct target_flock *target_fl = (void *)arg; | |
1642 | + struct target_flock *target_fl; | |
1530 | 1643 | long ret; |
1531 | - | |
1644 | + | |
1532 | 1645 | switch(cmd) { |
1533 | 1646 | case TARGET_F_GETLK: |
1534 | 1647 | ret = fcntl(fd, cmd, &fl); |
1535 | 1648 | if (ret == 0) { |
1649 | + lock_user_struct(target_fl, arg, 0); | |
1536 | 1650 | target_fl->l_type = tswap16(fl.l_type); |
1537 | 1651 | target_fl->l_whence = tswap16(fl.l_whence); |
1538 | 1652 | target_fl->l_start = tswapl(fl.l_start); |
1539 | 1653 | target_fl->l_len = tswapl(fl.l_len); |
1540 | 1654 | target_fl->l_pid = tswapl(fl.l_pid); |
1655 | + unlock_user_struct(target_fl, arg, 1); | |
1541 | 1656 | } |
1542 | 1657 | break; |
1543 | 1658 | |
1544 | 1659 | case TARGET_F_SETLK: |
1545 | 1660 | case TARGET_F_SETLKW: |
1661 | + lock_user_struct(target_fl, arg, 1); | |
1546 | 1662 | fl.l_type = tswap16(target_fl->l_type); |
1547 | 1663 | fl.l_whence = tswap16(target_fl->l_whence); |
1548 | 1664 | fl.l_start = tswapl(target_fl->l_start); |
1549 | 1665 | fl.l_len = tswapl(target_fl->l_len); |
1550 | 1666 | fl.l_pid = tswapl(target_fl->l_pid); |
1667 | + unlock_user_struct(target_fl, arg, 0); | |
1551 | 1668 | ret = fcntl(fd, cmd, &fl); |
1552 | 1669 | break; |
1553 | 1670 | |
... | ... | @@ -1690,12 +1807,35 @@ static inline long target_ftruncate64(void *cpu_env, long arg1, long arg2, |
1690 | 1807 | } |
1691 | 1808 | #endif |
1692 | 1809 | |
1810 | +static inline void target_to_host_timespec(struct timespec *host_ts, | |
1811 | + target_ulong target_addr) | |
1812 | +{ | |
1813 | + struct target_timespec *target_ts; | |
1814 | + | |
1815 | + lock_user_struct(target_ts, target_addr, 1); | |
1816 | + host_ts->tv_sec = tswapl(target_ts->tv_sec); | |
1817 | + host_ts->tv_nsec = tswapl(target_ts->tv_nsec); | |
1818 | + unlock_user_struct(target_ts, target_addr, 0); | |
1819 | +} | |
1820 | + | |
1821 | +static inline void host_to_target_timespec(target_ulong target_addr, | |
1822 | + struct timespec *host_ts) | |
1823 | +{ | |
1824 | + struct target_timespec *target_ts; | |
1825 | + | |
1826 | + lock_user_struct(target_ts, target_addr, 0); | |
1827 | + target_ts->tv_sec = tswapl(host_ts->tv_sec); | |
1828 | + target_ts->tv_nsec = tswapl(host_ts->tv_nsec); | |
1829 | + unlock_user_struct(target_ts, target_addr, 1); | |
1830 | +} | |
1831 | + | |
1693 | 1832 | long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1694 | 1833 | long arg4, long arg5, long arg6) |
1695 | 1834 | { |
1696 | 1835 | long ret; |
1697 | 1836 | struct stat st; |
1698 | 1837 | struct statfs stfs; |
1838 | + void *p; | |
1699 | 1839 | |
1700 | 1840 | #ifdef DEBUG |
1701 | 1841 | gemu_log("syscall %d", num); |
... | ... | @@ -1711,89 +1851,140 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1711 | 1851 | ret = 0; /* avoid warning */ |
1712 | 1852 | break; |
1713 | 1853 | case TARGET_NR_read: |
1714 | - page_unprotect_range((void *)arg2, arg3); | |
1715 | - ret = get_errno(read(arg1, (void *)arg2, arg3)); | |
1854 | + page_unprotect_range(arg2, arg3); | |
1855 | + p = lock_user(arg2, arg3, 0); | |
1856 | + ret = get_errno(read(arg1, p, arg3)); | |
1857 | + unlock_user(p, arg2, ret); | |
1716 | 1858 | break; |
1717 | 1859 | case TARGET_NR_write: |
1718 | - ret = get_errno(write(arg1, (void *)arg2, arg3)); | |
1860 | + p = lock_user(arg2, arg3, 1); | |
1861 | + ret = get_errno(write(arg1, p, arg3)); | |
1862 | + unlock_user(p, arg2, 0); | |
1719 | 1863 | break; |
1720 | 1864 | case TARGET_NR_open: |
1721 | - ret = get_errno(open(path((const char *)arg1), | |
1865 | + p = lock_user_string(arg1); | |
1866 | + ret = get_errno(open(path(p), | |
1722 | 1867 | target_to_host_bitmask(arg2, fcntl_flags_tbl), |
1723 | 1868 | arg3)); |
1869 | + unlock_user(p, arg1, 0); | |
1724 | 1870 | break; |
1725 | 1871 | case TARGET_NR_close: |
1726 | 1872 | ret = get_errno(close(arg1)); |
1727 | 1873 | break; |
1728 | 1874 | case TARGET_NR_brk: |
1729 | - ret = do_brk((char *)arg1); | |
1875 | + ret = do_brk(arg1); | |
1730 | 1876 | break; |
1731 | 1877 | case TARGET_NR_fork: |
1732 | 1878 | ret = get_errno(do_fork(cpu_env, SIGCHLD, 0)); |
1733 | 1879 | break; |
1734 | 1880 | case TARGET_NR_waitpid: |
1735 | 1881 | { |
1736 | - int *status = (int *)arg2; | |
1737 | - ret = get_errno(waitpid(arg1, status, arg3)); | |
1738 | - if (!is_error(ret) && status) | |
1739 | - tswapls((long *)&status); | |
1882 | + int status; | |
1883 | + ret = get_errno(waitpid(arg1, &status, arg3)); | |
1884 | + if (!is_error(ret) && arg2) | |
1885 | + tput32(arg2, status); | |
1740 | 1886 | } |
1741 | 1887 | break; |
1742 | 1888 | case TARGET_NR_creat: |
1743 | - ret = get_errno(creat((const char *)arg1, arg2)); | |
1889 | + p = lock_user_string(arg1); | |
1890 | + ret = get_errno(creat(p, arg2)); | |
1891 | + unlock_user(p, arg1, 0); | |
1744 | 1892 | break; |
1745 | 1893 | case TARGET_NR_link: |
1746 | - ret = get_errno(link((const char *)arg1, (const char *)arg2)); | |
1894 | + { | |
1895 | + void * p2; | |
1896 | + p = lock_user_string(arg1); | |
1897 | + p2 = lock_user_string(arg2); | |
1898 | + ret = get_errno(link(p, p2)); | |
1899 | + unlock_user(p2, arg2, 0); | |
1900 | + unlock_user(p, arg1, 0); | |
1901 | + } | |
1747 | 1902 | break; |
1748 | 1903 | case TARGET_NR_unlink: |
1749 | - ret = get_errno(unlink((const char *)arg1)); | |
1904 | + p = lock_user_string(arg1); | |
1905 | + ret = get_errno(unlink(p)); | |
1906 | + unlock_user(p, arg1, 0); | |
1750 | 1907 | break; |
1751 | 1908 | case TARGET_NR_execve: |
1752 | 1909 | { |
1753 | 1910 | char **argp, **envp; |
1754 | 1911 | int argc, envc; |
1755 | - uint32_t *p; | |
1912 | + target_ulong gp; | |
1913 | + target_ulong guest_argp; | |
1914 | + target_ulong guest_envp; | |
1915 | + target_ulong addr; | |
1756 | 1916 | char **q; |
1757 | 1917 | |
1758 | 1918 | argc = 0; |
1759 | - for (p = (void *)arg2; *p; p++) | |
1919 | + guest_argp = arg2; | |
1920 | + for (gp = guest_argp; tgetl(gp); gp++) | |
1760 | 1921 | argc++; |
1761 | 1922 | envc = 0; |
1762 | - for (p = (void *)arg3; *p; p++) | |
1923 | + guest_envp = arg3; | |
1924 | + for (gp = guest_envp; tgetl(gp); gp++) | |
1763 | 1925 | envc++; |
1764 | 1926 | |
1765 | 1927 | argp = alloca((argc + 1) * sizeof(void *)); |
1766 | 1928 | envp = alloca((envc + 1) * sizeof(void *)); |
1767 | 1929 | |
1768 | - for (p = (void *)arg2, q = argp; *p; p++, q++) | |
1769 | - *q = (void *)tswap32(*p); | |
1930 | + for (gp = guest_argp, q = argp; ; | |
1931 | + gp += sizeof(target_ulong), q++) { | |
1932 | + addr = tgetl(gp); | |
1933 | + if (!addr) | |
1934 | + break; | |
1935 | + *q = lock_user_string(addr); | |
1936 | + } | |
1770 | 1937 | *q = NULL; |
1771 | 1938 | |
1772 | - for (p = (void *)arg3, q = envp; *p; p++, q++) | |
1773 | - *q = (void *)tswap32(*p); | |
1939 | + for (gp = guest_envp, q = envp; ; | |
1940 | + gp += sizeof(target_ulong), q++) { | |
1941 | + addr = tgetl(gp); | |
1942 | + if (!addr) | |
1943 | + break; | |
1944 | + *q = lock_user_string(addr); | |
1945 | + } | |
1774 | 1946 | *q = NULL; |
1775 | 1947 | |
1776 | - ret = get_errno(execve((const char *)arg1, argp, envp)); | |
1948 | + p = lock_user_string(arg1); | |
1949 | + ret = get_errno(execve(p, argp, envp)); | |
1950 | + unlock_user(p, arg1, 0); | |
1951 | + | |
1952 | + for (gp = guest_argp, q = argp; *q; | |
1953 | + gp += sizeof(target_ulong), q++) { | |
1954 | + addr = tgetl(gp); | |
1955 | + unlock_user(*q, addr, 0); | |
1956 | + } | |
1957 | + for (gp = guest_envp, q = envp; *q; | |
1958 | + gp += sizeof(target_ulong), q++) { | |
1959 | + addr = tgetl(gp); | |
1960 | + unlock_user(*q, addr, 0); | |
1961 | + } | |
1777 | 1962 | } |
1778 | 1963 | break; |
1779 | 1964 | case TARGET_NR_chdir: |
1780 | - ret = get_errno(chdir((const char *)arg1)); | |
1965 | + p = lock_user_string(arg1); | |
1966 | + ret = get_errno(chdir(p)); | |
1967 | + unlock_user(p, arg1, 0); | |
1781 | 1968 | break; |
1782 | 1969 | #ifdef TARGET_NR_time |
1783 | 1970 | case TARGET_NR_time: |
1784 | 1971 | { |
1785 | - int *time_ptr = (int *)arg1; | |
1786 | - ret = get_errno(time((time_t *)time_ptr)); | |
1787 | - if (!is_error(ret) && time_ptr) | |
1788 | - tswap32s(time_ptr); | |
1972 | + time_t host_time; | |
1973 | + ret = get_errno(time(&host_time)); | |
1974 | + if (!is_error(ret) && arg1) | |
1975 | + tputl(arg1, host_time); | |
1789 | 1976 | } |
1790 | 1977 | break; |
1791 | 1978 | #endif |
1792 | 1979 | case TARGET_NR_mknod: |
1793 | - ret = get_errno(mknod((const char *)arg1, arg2, arg3)); | |
1980 | + p = lock_user_string(arg1); | |
1981 | + ret = get_errno(mknod(p, arg2, arg3)); | |
1982 | + unlock_user(p, arg1, 0); | |
1794 | 1983 | break; |
1795 | 1984 | case TARGET_NR_chmod: |
1796 | - ret = get_errno(chmod((const char *)arg1, arg2)); | |
1985 | + p = lock_user_string(arg1); | |
1986 | + ret = get_errno(chmod(p, arg2)); | |
1987 | + unlock_user(p, arg1, 0); | |
1797 | 1988 | break; |
1798 | 1989 | #ifdef TARGET_NR_break |
1799 | 1990 | case TARGET_NR_break: |
... | ... | @@ -1813,14 +2004,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1813 | 2004 | /* need to look at the data field */ |
1814 | 2005 | goto unimplemented; |
1815 | 2006 | case TARGET_NR_umount: |
1816 | - ret = get_errno(umount((const char *)arg1)); | |
2007 | + p = lock_user_string(arg1); | |
2008 | + ret = get_errno(umount(p)); | |
2009 | + unlock_user(p, arg1, 0); | |
1817 | 2010 | break; |
1818 | 2011 | case TARGET_NR_stime: |
1819 | 2012 | { |
1820 | - int *time_ptr = (int *)arg1; | |
1821 | - if (time_ptr) | |
1822 | - tswap32s(time_ptr); | |
1823 | - ret = get_errno(stime((time_t *)time_ptr)); | |
2013 | + time_t host_time; | |
2014 | + host_time = tgetl(arg1); | |
2015 | + ret = get_errno(stime(&host_time)); | |
1824 | 2016 | } |
1825 | 2017 | break; |
1826 | 2018 | case TARGET_NR_ptrace: |
... | ... | @@ -1837,30 +2029,36 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1837 | 2029 | break; |
1838 | 2030 | case TARGET_NR_utime: |
1839 | 2031 | { |
1840 | - struct utimbuf tbuf, *tbuf1; | |
1841 | - struct target_utimbuf *target_tbuf = (void *)arg2; | |
1842 | - if (target_tbuf) { | |
1843 | - get_user(tbuf.actime, &target_tbuf->actime); | |
1844 | - get_user(tbuf.modtime, &target_tbuf->modtime); | |
1845 | - tbuf1 = &tbuf; | |
2032 | + struct utimbuf tbuf, *host_tbuf; | |
2033 | + struct target_utimbuf *target_tbuf; | |
2034 | + if (arg2) { | |
2035 | + lock_user_struct(target_tbuf, arg2, 1); | |
2036 | + tbuf.actime = tswapl(target_tbuf->actime); | |
2037 | + tbuf.modtime = tswapl(target_tbuf->modtime); | |
2038 | + unlock_user_struct(target_tbuf, arg2, 0); | |
2039 | + host_tbuf = &tbuf; | |
1846 | 2040 | } else { |
1847 | - tbuf1 = NULL; | |
2041 | + host_tbuf = NULL; | |
1848 | 2042 | } |
1849 | - ret = get_errno(utime((const char *)arg1, tbuf1)); | |
2043 | + p = lock_user_string(arg1); | |
2044 | + ret = get_errno(utime(p, host_tbuf)); | |
2045 | + unlock_user(p, arg1, 0); | |
1850 | 2046 | } |
1851 | 2047 | break; |
1852 | 2048 | case TARGET_NR_utimes: |
1853 | 2049 | { |
1854 | - struct target_timeval *target_tvp = (struct target_timeval *)arg2; | |
1855 | 2050 | struct timeval *tvp, tv[2]; |
1856 | - if (target_tvp) { | |
1857 | - target_to_host_timeval(&tv[0], &target_tvp[0]); | |
1858 | - target_to_host_timeval(&tv[1], &target_tvp[1]); | |
2051 | + if (arg2) { | |
2052 | + target_to_host_timeval(&tv[0], arg2); | |
2053 | + target_to_host_timeval(&tv[1], | |
2054 | + arg2 + sizeof (struct target_timeval)); | |
1859 | 2055 | tvp = tv; |
1860 | 2056 | } else { |
1861 | 2057 | tvp = NULL; |
1862 | 2058 | } |
1863 | - ret = get_errno(utimes((const char *)arg1, tvp)); | |
2059 | + p = lock_user_string(arg1); | |
2060 | + ret = get_errno(utimes(p, tvp)); | |
2061 | + unlock_user(p, arg1, 0); | |
1864 | 2062 | } |
1865 | 2063 | break; |
1866 | 2064 | #ifdef TARGET_NR_stty |
... | ... | @@ -1872,7 +2070,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1872 | 2070 | goto unimplemented; |
1873 | 2071 | #endif |
1874 | 2072 | case TARGET_NR_access: |
1875 | - ret = get_errno(access((const char *)arg1, arg2)); | |
2073 | + p = lock_user_string(arg1); | |
2074 | + ret = get_errno(access(p, arg2)); | |
2075 | + unlock_user(p, arg1, 0); | |
1876 | 2076 | break; |
1877 | 2077 | case TARGET_NR_nice: |
1878 | 2078 | ret = get_errno(nice(arg1)); |
... | ... | @@ -1889,33 +2089,45 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1889 | 2089 | ret = get_errno(kill(arg1, arg2)); |
1890 | 2090 | break; |
1891 | 2091 | case TARGET_NR_rename: |
1892 | - ret = get_errno(rename((const char *)arg1, (const char *)arg2)); | |
2092 | + { | |
2093 | + void *p2; | |
2094 | + p = lock_user_string(arg1); | |
2095 | + p2 = lock_user_string(arg2); | |
2096 | + ret = get_errno(rename(p, p2)); | |
2097 | + unlock_user(p2, arg2, 0); | |
2098 | + unlock_user(p, arg1, 0); | |
2099 | + } | |
1893 | 2100 | break; |
1894 | 2101 | case TARGET_NR_mkdir: |
1895 | - ret = get_errno(mkdir((const char *)arg1, arg2)); | |
2102 | + p = lock_user_string(arg1); | |
2103 | + ret = get_errno(mkdir(p, arg2)); | |
2104 | + unlock_user(p, arg1, 0); | |
1896 | 2105 | break; |
1897 | 2106 | case TARGET_NR_rmdir: |
1898 | - ret = get_errno(rmdir((const char *)arg1)); | |
2107 | + p = lock_user_string(arg1); | |
2108 | + ret = get_errno(rmdir(p)); | |
2109 | + unlock_user(p, arg1, 0); | |
1899 | 2110 | break; |
1900 | 2111 | case TARGET_NR_dup: |
1901 | 2112 | ret = get_errno(dup(arg1)); |
1902 | 2113 | break; |
1903 | 2114 | case TARGET_NR_pipe: |
1904 | 2115 | { |
1905 | - int *pipe_ptr = (int *)arg1; | |
1906 | - ret = get_errno(pipe(pipe_ptr)); | |
2116 | + int host_pipe[2]; | |
2117 | + ret = get_errno(pipe(host_pipe)); | |
1907 | 2118 | if (!is_error(ret)) { |
1908 | - tswap32s(&pipe_ptr[0]); | |
1909 | - tswap32s(&pipe_ptr[1]); | |
2119 | + tput32(arg1, host_pipe[0]); | |
2120 | + tput32(arg1 + 4, host_pipe[1]); | |
1910 | 2121 | } |
1911 | 2122 | } |
1912 | 2123 | break; |
1913 | 2124 | case TARGET_NR_times: |
1914 | 2125 | { |
1915 | - struct target_tms *tmsp = (void *)arg1; | |
2126 | + struct target_tms *tmsp; | |
1916 | 2127 | struct tms tms; |
1917 | 2128 | ret = get_errno(times(&tms)); |
1918 | - if (tmsp) { | |
2129 | + if (arg1) { | |
2130 | + tmsp = lock_user(arg1, sizeof(struct target_tms), 0); | |
1919 | 2131 | tmsp->tms_utime = tswapl(host_to_target_clock_t(tms.tms_utime)); |
1920 | 2132 | tmsp->tms_stime = tswapl(host_to_target_clock_t(tms.tms_stime)); |
1921 | 2133 | tmsp->tms_cutime = tswapl(host_to_target_clock_t(tms.tms_cutime)); |
... | ... | @@ -1935,7 +2147,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1935 | 2147 | case TARGET_NR_acct: |
1936 | 2148 | goto unimplemented; |
1937 | 2149 | case TARGET_NR_umount2: |
1938 | - ret = get_errno(umount2((const char *)arg1, arg2)); | |
2150 | + p = lock_user_string(arg1); | |
2151 | + ret = get_errno(umount2(p, arg2)); | |
2152 | + unlock_user(p, arg1, 0); | |
1939 | 2153 | break; |
1940 | 2154 | #ifdef TARGET_NR_lock |
1941 | 2155 | case TARGET_NR_lock: |
... | ... | @@ -1966,7 +2180,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1966 | 2180 | ret = get_errno(umask(arg1)); |
1967 | 2181 | break; |
1968 | 2182 | case TARGET_NR_chroot: |
1969 | - ret = get_errno(chroot((const char *)arg1)); | |
2183 | + p = lock_user_string(arg1); | |
2184 | + ret = get_errno(chroot(p)); | |
2185 | + unlock_user(p, arg1, 0); | |
1970 | 2186 | break; |
1971 | 2187 | case TARGET_NR_ustat: |
1972 | 2188 | goto unimplemented; |
... | ... | @@ -1984,29 +2200,49 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
1984 | 2200 | break; |
1985 | 2201 | case TARGET_NR_sigaction: |
1986 | 2202 | { |
1987 | - struct target_old_sigaction *old_act = (void *)arg2; | |
1988 | - struct target_old_sigaction *old_oact = (void *)arg3; | |
2203 | + struct target_old_sigaction *old_act; | |
1989 | 2204 | struct target_sigaction act, oact, *pact; |
1990 | - if (old_act) { | |
2205 | + if (arg2) { | |
2206 | + lock_user_struct(old_act, arg2, 1); | |
1991 | 2207 | act._sa_handler = old_act->_sa_handler; |
1992 | 2208 | target_siginitset(&act.sa_mask, old_act->sa_mask); |
1993 | 2209 | act.sa_flags = old_act->sa_flags; |
1994 | 2210 | act.sa_restorer = old_act->sa_restorer; |
2211 | + unlock_user_struct(old_act, arg2, 0); | |
1995 | 2212 | pact = &act; |
1996 | 2213 | } else { |
1997 | 2214 | pact = NULL; |
1998 | 2215 | } |
1999 | 2216 | ret = get_errno(do_sigaction(arg1, pact, &oact)); |
2000 | - if (!is_error(ret) && old_oact) { | |
2001 | - old_oact->_sa_handler = oact._sa_handler; | |
2002 | - old_oact->sa_mask = oact.sa_mask.sig[0]; | |
2003 | - old_oact->sa_flags = oact.sa_flags; | |
2004 | - old_oact->sa_restorer = oact.sa_restorer; | |
2217 | + if (!is_error(ret) && arg3) { | |
2218 | + lock_user_struct(old_act, arg3, 0); | |
2219 | + old_act->_sa_handler = oact._sa_handler; | |
2220 | + old_act->sa_mask = oact.sa_mask.sig[0]; | |
2221 | + old_act->sa_flags = oact.sa_flags; | |
2222 | + old_act->sa_restorer = oact.sa_restorer; | |
2223 | + unlock_user_struct(old_act, arg3, 1); | |
2005 | 2224 | } |
2006 | 2225 | } |
2007 | 2226 | break; |
2008 | 2227 | case TARGET_NR_rt_sigaction: |
2009 | - ret = get_errno(do_sigaction(arg1, (void *)arg2, (void *)arg3)); | |
2228 | + { | |
2229 | + struct target_sigaction *act; | |
2230 | + struct target_sigaction *oact; | |
2231 | + | |
2232 | + if (arg2) | |
2233 | + lock_user_struct(act, arg2, 1); | |
2234 | + else | |
2235 | + act = NULL; | |
2236 | + if (arg3) | |
2237 | + lock_user_struct(oact, arg3, 0); | |
2238 | + else | |
2239 | + oact = NULL; | |
2240 | + ret = get_errno(do_sigaction(arg1, act, oact)); | |
2241 | + if (arg2) | |
2242 | + unlock_user_struct(act, arg2, 0); | |
2243 | + if (arg3) | |
2244 | + unlock_user_struct(oact, arg3, 1); | |
2245 | + } | |
2010 | 2246 | break; |
2011 | 2247 | case TARGET_NR_sgetmask: |
2012 | 2248 | { |
... | ... | @@ -2033,9 +2269,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2033 | 2269 | { |
2034 | 2270 | int how = arg1; |
2035 | 2271 | sigset_t set, oldset, *set_ptr; |
2036 | - target_ulong *pset = (void *)arg2, *poldset = (void *)arg3; | |
2037 | 2272 | |
2038 | - if (pset) { | |
2273 | + if (arg2) { | |
2039 | 2274 | switch(how) { |
2040 | 2275 | case TARGET_SIG_BLOCK: |
2041 | 2276 | how = SIG_BLOCK; |
... | ... | @@ -2050,15 +2285,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2050 | 2285 | ret = -EINVAL; |
2051 | 2286 | goto fail; |
2052 | 2287 | } |
2053 | - target_to_host_old_sigset(&set, pset); | |
2288 | + p = lock_user(arg2, sizeof(target_sigset_t), 1); | |
2289 | + target_to_host_old_sigset(&set, p); | |
2290 | + unlock_user(p, arg2, 0); | |
2054 | 2291 | set_ptr = &set; |
2055 | 2292 | } else { |
2056 | 2293 | how = 0; |
2057 | 2294 | set_ptr = NULL; |
2058 | 2295 | } |
2059 | 2296 | ret = get_errno(sigprocmask(arg1, set_ptr, &oldset)); |
2060 | - if (!is_error(ret) && poldset) { | |
2061 | - host_to_target_old_sigset(poldset, &oldset); | |
2297 | + if (!is_error(ret) && arg3) { | |
2298 | + p = lock_user(arg3, sizeof(target_sigset_t), 0); | |
2299 | + host_to_target_old_sigset(p, &oldset); | |
2300 | + unlock_user(p, arg3, sizeof(target_sigset_t)); | |
2062 | 2301 | } |
2063 | 2302 | } |
2064 | 2303 | break; |
... | ... | @@ -2066,10 +2305,8 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2066 | 2305 | { |
2067 | 2306 | int how = arg1; |
2068 | 2307 | sigset_t set, oldset, *set_ptr; |
2069 | - target_sigset_t *pset = (void *)arg2; | |
2070 | - target_sigset_t *poldset = (void *)arg3; | |
2071 | 2308 | |
2072 | - if (pset) { | |
2309 | + if (arg2) { | |
2073 | 2310 | switch(how) { |
2074 | 2311 | case TARGET_SIG_BLOCK: |
2075 | 2312 | how = SIG_BLOCK; |
... | ... | @@ -2084,15 +2321,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2084 | 2321 | ret = -EINVAL; |
2085 | 2322 | goto fail; |
2086 | 2323 | } |
2087 | - target_to_host_sigset(&set, pset); | |
2324 | + p = lock_user(arg2, sizeof(target_sigset_t), 1); | |
2325 | + target_to_host_sigset(&set, p); | |
2326 | + unlock_user(p, arg2, 0); | |
2088 | 2327 | set_ptr = &set; |
2089 | 2328 | } else { |
2090 | 2329 | how = 0; |
2091 | 2330 | set_ptr = NULL; |
2092 | 2331 | } |
2093 | 2332 | ret = get_errno(sigprocmask(how, set_ptr, &oldset)); |
2094 | - if (!is_error(ret) && poldset) { | |
2095 | - host_to_target_sigset(poldset, &oldset); | |
2333 | + if (!is_error(ret) && arg3) { | |
2334 | + p = lock_user(arg3, sizeof(target_sigset_t), 0); | |
2335 | + host_to_target_sigset(p, &oldset); | |
2336 | + unlock_user(p, arg3, sizeof(target_sigset_t)); | |
2096 | 2337 | } |
2097 | 2338 | } |
2098 | 2339 | break; |
... | ... | @@ -2101,7 +2342,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2101 | 2342 | sigset_t set; |
2102 | 2343 | ret = get_errno(sigpending(&set)); |
2103 | 2344 | if (!is_error(ret)) { |
2104 | - host_to_target_old_sigset((target_ulong *)arg1, &set); | |
2345 | + p = lock_user(arg1, sizeof(target_sigset_t), 0); | |
2346 | + host_to_target_old_sigset(p, &set); | |
2347 | + unlock_user(p, arg1, sizeof(target_sigset_t)); | |
2105 | 2348 | } |
2106 | 2349 | } |
2107 | 2350 | break; |
... | ... | @@ -2110,51 +2353,59 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2110 | 2353 | sigset_t set; |
2111 | 2354 | ret = get_errno(sigpending(&set)); |
2112 | 2355 | if (!is_error(ret)) { |
2113 | - host_to_target_sigset((target_sigset_t *)arg1, &set); | |
2356 | + p = lock_user(arg1, sizeof(target_sigset_t), 0); | |
2357 | + host_to_target_sigset(p, &set); | |
2358 | + unlock_user(p, arg1, sizeof(target_sigset_t)); | |
2114 | 2359 | } |
2115 | 2360 | } |
2116 | 2361 | break; |
2117 | 2362 | case TARGET_NR_sigsuspend: |
2118 | 2363 | { |
2119 | 2364 | sigset_t set; |
2120 | - target_to_host_old_sigset(&set, (target_ulong *)arg1); | |
2365 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
2366 | + target_to_host_old_sigset(&set, p); | |
2367 | + unlock_user(p, arg1, 0); | |
2121 | 2368 | ret = get_errno(sigsuspend(&set)); |
2122 | 2369 | } |
2123 | 2370 | break; |
2124 | 2371 | case TARGET_NR_rt_sigsuspend: |
2125 | 2372 | { |
2126 | 2373 | sigset_t set; |
2127 | - target_to_host_sigset(&set, (target_sigset_t *)arg1); | |
2374 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
2375 | + target_to_host_sigset(&set, p); | |
2376 | + unlock_user(p, arg1, 0); | |
2128 | 2377 | ret = get_errno(sigsuspend(&set)); |
2129 | 2378 | } |
2130 | 2379 | break; |
2131 | 2380 | case TARGET_NR_rt_sigtimedwait: |
2132 | 2381 | { |
2133 | - target_sigset_t *target_set = (void *)arg1; | |
2134 | - target_siginfo_t *target_uinfo = (void *)arg2; | |
2135 | - struct target_timespec *target_uts = (void *)arg3; | |
2136 | 2382 | sigset_t set; |
2137 | 2383 | struct timespec uts, *puts; |
2138 | 2384 | siginfo_t uinfo; |
2139 | 2385 | |
2140 | - target_to_host_sigset(&set, target_set); | |
2141 | - if (target_uts) { | |
2386 | + p = lock_user(arg1, sizeof(target_sigset_t), 1); | |
2387 | + target_to_host_sigset(&set, p); | |
2388 | + unlock_user(p, arg1, 0); | |
2389 | + if (arg3) { | |
2142 | 2390 | puts = &uts; |
2143 | - puts->tv_sec = tswapl(target_uts->tv_sec); | |
2144 | - puts->tv_nsec = tswapl(target_uts->tv_nsec); | |
2391 | + target_to_host_timespec(puts, arg3); | |
2145 | 2392 | } else { |
2146 | 2393 | puts = NULL; |
2147 | 2394 | } |
2148 | 2395 | ret = get_errno(sigtimedwait(&set, &uinfo, puts)); |
2149 | - if (!is_error(ret) && target_uinfo) { | |
2150 | - host_to_target_siginfo(target_uinfo, &uinfo); | |
2396 | + if (!is_error(ret) && arg2) { | |
2397 | + p = lock_user(arg2, sizeof(target_sigset_t), 0); | |
2398 | + host_to_target_siginfo(p, &uinfo); | |
2399 | + unlock_user(p, arg2, sizeof(target_sigset_t)); | |
2151 | 2400 | } |
2152 | 2401 | } |
2153 | 2402 | break; |
2154 | 2403 | case TARGET_NR_rt_sigqueueinfo: |
2155 | 2404 | { |
2156 | 2405 | siginfo_t uinfo; |
2157 | - target_to_host_siginfo(&uinfo, (target_siginfo_t *)arg3); | |
2406 | + p = lock_user(arg3, sizeof(target_sigset_t), 1); | |
2407 | + target_to_host_siginfo(&uinfo, p); | |
2408 | + unlock_user(p, arg1, 0); | |
2158 | 2409 | ret = get_errno(sys_rt_sigqueueinfo(arg1, arg2, &uinfo)); |
2159 | 2410 | } |
2160 | 2411 | break; |
... | ... | @@ -2167,16 +2418,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2167 | 2418 | ret = do_rt_sigreturn(cpu_env); |
2168 | 2419 | break; |
2169 | 2420 | case TARGET_NR_sethostname: |
2170 | - ret = get_errno(sethostname((const char *)arg1, arg2)); | |
2421 | + p = lock_user_string(arg1); | |
2422 | + ret = get_errno(sethostname(p, arg2)); | |
2423 | + unlock_user(p, arg1, 0); | |
2171 | 2424 | break; |
2172 | 2425 | case TARGET_NR_setrlimit: |
2173 | 2426 | { |
2174 | 2427 | /* XXX: convert resource ? */ |
2175 | 2428 | int resource = arg1; |
2176 | - struct target_rlimit *target_rlim = (void *)arg2; | |
2429 | + struct target_rlimit *target_rlim; | |
2177 | 2430 | struct rlimit rlim; |
2431 | + lock_user_struct(target_rlim, arg2, 1); | |
2178 | 2432 | rlim.rlim_cur = tswapl(target_rlim->rlim_cur); |
2179 | 2433 | rlim.rlim_max = tswapl(target_rlim->rlim_max); |
2434 | + unlock_user_struct(target_rlim, arg2, 0); | |
2180 | 2435 | ret = get_errno(setrlimit(resource, &rlim)); |
2181 | 2436 | } |
2182 | 2437 | break; |
... | ... | @@ -2184,72 +2439,91 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2184 | 2439 | { |
2185 | 2440 | /* XXX: convert resource ? */ |
2186 | 2441 | int resource = arg1; |
2187 | - struct target_rlimit *target_rlim = (void *)arg2; | |
2442 | + struct target_rlimit *target_rlim; | |
2188 | 2443 | struct rlimit rlim; |
2189 | 2444 | |
2190 | 2445 | ret = get_errno(getrlimit(resource, &rlim)); |
2191 | 2446 | if (!is_error(ret)) { |
2192 | - target_rlim->rlim_cur = tswapl(rlim.rlim_cur); | |
2193 | - target_rlim->rlim_max = tswapl(rlim.rlim_max); | |
2447 | + lock_user_struct(target_rlim, arg2, 0); | |
2448 | + rlim.rlim_cur = tswapl(target_rlim->rlim_cur); | |
2449 | + rlim.rlim_max = tswapl(target_rlim->rlim_max); | |
2450 | + unlock_user_struct(target_rlim, arg2, 1); | |
2194 | 2451 | } |
2195 | 2452 | } |
2196 | 2453 | break; |
2197 | 2454 | case TARGET_NR_getrusage: |
2198 | 2455 | { |
2199 | 2456 | struct rusage rusage; |
2200 | - struct target_rusage *target_rusage = (void *)arg2; | |
2201 | 2457 | ret = get_errno(getrusage(arg1, &rusage)); |
2202 | 2458 | if (!is_error(ret)) { |
2203 | - host_to_target_rusage(target_rusage, &rusage); | |
2459 | + host_to_target_rusage(arg2, &rusage); | |
2204 | 2460 | } |
2205 | 2461 | } |
2206 | 2462 | break; |
2207 | 2463 | case TARGET_NR_gettimeofday: |
2208 | 2464 | { |
2209 | - struct target_timeval *target_tv = (void *)arg1; | |
2210 | 2465 | struct timeval tv; |
2211 | 2466 | ret = get_errno(gettimeofday(&tv, NULL)); |
2212 | 2467 | if (!is_error(ret)) { |
2213 | - host_to_target_timeval(target_tv, &tv); | |
2468 | + host_to_target_timeval(arg1, &tv); | |
2214 | 2469 | } |
2215 | 2470 | } |
2216 | 2471 | break; |
2217 | 2472 | case TARGET_NR_settimeofday: |
2218 | 2473 | { |
2219 | - struct target_timeval *target_tv = (void *)arg1; | |
2220 | 2474 | struct timeval tv; |
2221 | - target_to_host_timeval(&tv, target_tv); | |
2475 | + target_to_host_timeval(&tv, arg1); | |
2222 | 2476 | ret = get_errno(settimeofday(&tv, NULL)); |
2223 | 2477 | } |
2224 | 2478 | break; |
2225 | 2479 | #ifdef TARGET_NR_select |
2226 | 2480 | case TARGET_NR_select: |
2227 | 2481 | { |
2228 | - struct target_sel_arg_struct *sel = (void *)arg1; | |
2229 | - sel->n = tswapl(sel->n); | |
2230 | - sel->inp = tswapl(sel->inp); | |
2231 | - sel->outp = tswapl(sel->outp); | |
2232 | - sel->exp = tswapl(sel->exp); | |
2233 | - sel->tvp = tswapl(sel->tvp); | |
2234 | - ret = do_select(sel->n, (void *)sel->inp, (void *)sel->outp, | |
2235 | - (void *)sel->exp, (void *)sel->tvp); | |
2482 | + struct target_sel_arg_struct *sel; | |
2483 | + target_ulong inp, outp, exp, tvp; | |
2484 | + long nsel; | |
2485 | + | |
2486 | + lock_user_struct(sel, arg1, 1); | |
2487 | + nsel = tswapl(sel->n); | |
2488 | + inp = tswapl(sel->inp); | |
2489 | + outp = tswapl(sel->outp); | |
2490 | + exp = tswapl(sel->exp); | |
2491 | + tvp = tswapl(sel->tvp); | |
2492 | + unlock_user_struct(sel, arg1, 0); | |
2493 | + ret = do_select(nsel, inp, outp, exp, tvp); | |
2236 | 2494 | } |
2237 | 2495 | break; |
2238 | 2496 | #endif |
2239 | 2497 | case TARGET_NR_symlink: |
2240 | - ret = get_errno(symlink((const char *)arg1, (const char *)arg2)); | |
2498 | + { | |
2499 | + void *p2; | |
2500 | + p = lock_user_string(arg1); | |
2501 | + p2 = lock_user_string(arg2); | |
2502 | + ret = get_errno(symlink(p, p2)); | |
2503 | + unlock_user(p2, arg2, 0); | |
2504 | + unlock_user(p, arg1, 0); | |
2505 | + } | |
2241 | 2506 | break; |
2242 | 2507 | #ifdef TARGET_NR_oldlstat |
2243 | 2508 | case TARGET_NR_oldlstat: |
2244 | 2509 | goto unimplemented; |
2245 | 2510 | #endif |
2246 | 2511 | case TARGET_NR_readlink: |
2247 | - ret = get_errno(readlink(path((const char *)arg1), (char *)arg2, arg3)); | |
2512 | + { | |
2513 | + void *p2; | |
2514 | + p = lock_user_string(arg1); | |
2515 | + p2 = lock_user(arg2, arg3, 0); | |
2516 | + ret = get_errno(readlink(path(p), p2, arg3)); | |
2517 | + unlock_user(p2, arg2, ret); | |
2518 | + unlock_user(p, arg1, 0); | |
2519 | + } | |
2248 | 2520 | break; |
2249 | 2521 | case TARGET_NR_uselib: |
2250 | 2522 | goto unimplemented; |
2251 | 2523 | case TARGET_NR_swapon: |
2252 | - ret = get_errno(swapon((const char *)arg1, arg2)); | |
2524 | + p = lock_user_string(arg1); | |
2525 | + ret = get_errno(swapon(p, arg2)); | |
2526 | + unlock_user(p, arg1, 0); | |
2253 | 2527 | break; |
2254 | 2528 | case TARGET_NR_reboot: |
2255 | 2529 | goto unimplemented; |
... | ... | @@ -2258,14 +2532,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2258 | 2532 | case TARGET_NR_mmap: |
2259 | 2533 | #if defined(TARGET_I386) || defined(TARGET_ARM) |
2260 | 2534 | { |
2261 | - uint32_t v1, v2, v3, v4, v5, v6, *vptr; | |
2262 | - vptr = (uint32_t *)arg1; | |
2263 | - v1 = tswap32(vptr[0]); | |
2264 | - v2 = tswap32(vptr[1]); | |
2265 | - v3 = tswap32(vptr[2]); | |
2266 | - v4 = tswap32(vptr[3]); | |
2267 | - v5 = tswap32(vptr[4]); | |
2268 | - v6 = tswap32(vptr[5]); | |
2535 | + target_ulong *v; | |
2536 | + target_ulong v1, v2, v3, v4, v5, v6; | |
2537 | + v = lock_user(arg1, 6 * sizeof(target_ulong), 1); | |
2538 | + v1 = tswapl(v[0]); | |
2539 | + v2 = tswapl(v[1]); | |
2540 | + v3 = tswapl(v[2]); | |
2541 | + v4 = tswapl(v[3]); | |
2542 | + v5 = tswapl(v[4]); | |
2543 | + v6 = tswapl(v[5]); | |
2544 | + unlock_user(v, arg1, 0); | |
2269 | 2545 | ret = get_errno(target_mmap(v1, v2, v3, |
2270 | 2546 | target_to_host_bitmask(v4, mmap_flags_tbl), |
2271 | 2547 | v5, v6)); |
... | ... | @@ -2299,14 +2575,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2299 | 2575 | case TARGET_NR_mremap: |
2300 | 2576 | ret = get_errno(target_mremap(arg1, arg2, arg3, arg4, arg5)); |
2301 | 2577 | break; |
2578 | + /* ??? msync/mlock/munlock are broken for softmmu. */ | |
2302 | 2579 | case TARGET_NR_msync: |
2303 | - ret = get_errno(msync((void *)arg1, arg2, arg3)); | |
2580 | + ret = get_errno(msync(g2h(arg1), arg2, arg3)); | |
2304 | 2581 | break; |
2305 | 2582 | case TARGET_NR_mlock: |
2306 | - ret = get_errno(mlock((void *)arg1, arg2)); | |
2583 | + ret = get_errno(mlock(g2h(arg1), arg2)); | |
2307 | 2584 | break; |
2308 | 2585 | case TARGET_NR_munlock: |
2309 | - ret = get_errno(munlock((void *)arg1, arg2)); | |
2586 | + ret = get_errno(munlock(g2h(arg1), arg2)); | |
2310 | 2587 | break; |
2311 | 2588 | case TARGET_NR_mlockall: |
2312 | 2589 | ret = get_errno(mlockall(arg1)); |
... | ... | @@ -2315,7 +2592,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2315 | 2592 | ret = get_errno(munlockall()); |
2316 | 2593 | break; |
2317 | 2594 | case TARGET_NR_truncate: |
2318 | - ret = get_errno(truncate((const char *)arg1, arg2)); | |
2595 | + p = lock_user_string(arg1); | |
2596 | + ret = get_errno(truncate(p, arg2)); | |
2597 | + unlock_user(p, arg1, 0); | |
2319 | 2598 | break; |
2320 | 2599 | case TARGET_NR_ftruncate: |
2321 | 2600 | ret = get_errno(ftruncate(arg1, arg2)); |
... | ... | @@ -2334,11 +2613,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2334 | 2613 | goto unimplemented; |
2335 | 2614 | #endif |
2336 | 2615 | case TARGET_NR_statfs: |
2337 | - ret = get_errno(statfs(path((const char *)arg1), &stfs)); | |
2616 | + p = lock_user_string(arg1); | |
2617 | + ret = get_errno(statfs(path(p), &stfs)); | |
2618 | + unlock_user(p, arg1, 0); | |
2338 | 2619 | convert_statfs: |
2339 | 2620 | if (!is_error(ret)) { |
2340 | - struct target_statfs *target_stfs = (void *)arg2; | |
2621 | + struct target_statfs *target_stfs; | |
2341 | 2622 | |
2623 | + lock_user_struct(target_stfs, arg2, 0); | |
2624 | + /* ??? put_user is probably wrong. */ | |
2342 | 2625 | put_user(stfs.f_type, &target_stfs->f_type); |
2343 | 2626 | put_user(stfs.f_bsize, &target_stfs->f_bsize); |
2344 | 2627 | put_user(stfs.f_blocks, &target_stfs->f_blocks); |
... | ... | @@ -2348,6 +2631,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2348 | 2631 | put_user(stfs.f_ffree, &target_stfs->f_ffree); |
2349 | 2632 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); |
2350 | 2633 | put_user(stfs.f_namelen, &target_stfs->f_namelen); |
2634 | + unlock_user_struct(target_stfs, arg2, 1); | |
2351 | 2635 | } |
2352 | 2636 | break; |
2353 | 2637 | case TARGET_NR_fstatfs: |
... | ... | @@ -2355,11 +2639,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2355 | 2639 | goto convert_statfs; |
2356 | 2640 | #ifdef TARGET_NR_statfs64 |
2357 | 2641 | case TARGET_NR_statfs64: |
2358 | - ret = get_errno(statfs(path((const char *)arg1), &stfs)); | |
2642 | + p = lock_user_string(arg1); | |
2643 | + ret = get_errno(statfs(path(p), &stfs)); | |
2644 | + unlock_user(p, arg1, 0); | |
2359 | 2645 | convert_statfs64: |
2360 | 2646 | if (!is_error(ret)) { |
2361 | - struct target_statfs64 *target_stfs = (void *)arg3; | |
2362 | - | |
2647 | + struct target_statfs64 *target_stfs; | |
2648 | + | |
2649 | + lock_user_struct(target_stfs, arg3, 0); | |
2650 | + /* ??? put_user is probably wrong. */ | |
2363 | 2651 | put_user(stfs.f_type, &target_stfs->f_type); |
2364 | 2652 | put_user(stfs.f_bsize, &target_stfs->f_bsize); |
2365 | 2653 | put_user(stfs.f_blocks, &target_stfs->f_blocks); |
... | ... | @@ -2369,6 +2657,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2369 | 2657 | put_user(stfs.f_ffree, &target_stfs->f_ffree); |
2370 | 2658 | put_user(stfs.f_fsid.__val[0], &target_stfs->f_fsid); |
2371 | 2659 | put_user(stfs.f_namelen, &target_stfs->f_namelen); |
2660 | + unlock_user_struct(target_stfs, arg3, 0); | |
2372 | 2661 | } |
2373 | 2662 | break; |
2374 | 2663 | case TARGET_NR_fstatfs64: |
... | ... | @@ -2380,60 +2669,63 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2380 | 2669 | goto unimplemented; |
2381 | 2670 | #endif |
2382 | 2671 | case TARGET_NR_socketcall: |
2383 | - ret = do_socketcall(arg1, (int32_t *)arg2); | |
2672 | + ret = do_socketcall(arg1, arg2); | |
2384 | 2673 | break; |
2385 | 2674 | case TARGET_NR_syslog: |
2386 | 2675 | goto unimplemented; |
2387 | 2676 | case TARGET_NR_setitimer: |
2388 | 2677 | { |
2389 | - struct target_itimerval *target_value = (void *)arg2; | |
2390 | - struct target_itimerval *target_ovalue = (void *)arg3; | |
2391 | 2678 | struct itimerval value, ovalue, *pvalue; |
2392 | 2679 | |
2393 | - if (target_value) { | |
2680 | + if (arg2) { | |
2394 | 2681 | pvalue = &value; |
2395 | 2682 | target_to_host_timeval(&pvalue->it_interval, |
2396 | - &target_value->it_interval); | |
2683 | + arg2); | |
2397 | 2684 | target_to_host_timeval(&pvalue->it_value, |
2398 | - &target_value->it_value); | |
2685 | + arg2 + sizeof(struct target_timeval)); | |
2399 | 2686 | } else { |
2400 | 2687 | pvalue = NULL; |
2401 | 2688 | } |
2402 | 2689 | ret = get_errno(setitimer(arg1, pvalue, &ovalue)); |
2403 | - if (!is_error(ret) && target_ovalue) { | |
2404 | - host_to_target_timeval(&target_ovalue->it_interval, | |
2690 | + if (!is_error(ret) && arg3) { | |
2691 | + host_to_target_timeval(arg3, | |
2405 | 2692 | &ovalue.it_interval); |
2406 | - host_to_target_timeval(&target_ovalue->it_value, | |
2693 | + host_to_target_timeval(arg3 + sizeof(struct target_timeval), | |
2407 | 2694 | &ovalue.it_value); |
2408 | 2695 | } |
2409 | 2696 | } |
2410 | 2697 | break; |
2411 | 2698 | case TARGET_NR_getitimer: |
2412 | 2699 | { |
2413 | - struct target_itimerval *target_value = (void *)arg2; | |
2414 | 2700 | struct itimerval value; |
2415 | 2701 | |
2416 | 2702 | ret = get_errno(getitimer(arg1, &value)); |
2417 | - if (!is_error(ret) && target_value) { | |
2418 | - host_to_target_timeval(&target_value->it_interval, | |
2703 | + if (!is_error(ret) && arg2) { | |
2704 | + host_to_target_timeval(arg2, | |
2419 | 2705 | &value.it_interval); |
2420 | - host_to_target_timeval(&target_value->it_value, | |
2706 | + host_to_target_timeval(arg2 + sizeof(struct target_timeval), | |
2421 | 2707 | &value.it_value); |
2422 | 2708 | } |
2423 | 2709 | } |
2424 | 2710 | break; |
2425 | 2711 | case TARGET_NR_stat: |
2426 | - ret = get_errno(stat(path((const char *)arg1), &st)); | |
2712 | + p = lock_user_string(arg1); | |
2713 | + ret = get_errno(stat(path(p), &st)); | |
2714 | + unlock_user(p, arg1, 0); | |
2427 | 2715 | goto do_stat; |
2428 | 2716 | case TARGET_NR_lstat: |
2429 | - ret = get_errno(lstat(path((const char *)arg1), &st)); | |
2717 | + p = lock_user_string(arg1); | |
2718 | + ret = get_errno(lstat(path(p), &st)); | |
2719 | + unlock_user(p, arg1, 0); | |
2430 | 2720 | goto do_stat; |
2431 | 2721 | case TARGET_NR_fstat: |
2432 | 2722 | { |
2433 | 2723 | ret = get_errno(fstat(arg1, &st)); |
2434 | 2724 | do_stat: |
2435 | 2725 | if (!is_error(ret)) { |
2436 | - struct target_stat *target_st = (void *)arg2; | |
2726 | + struct target_stat *target_st; | |
2727 | + | |
2728 | + lock_user_struct(target_st, arg2, 0); | |
2437 | 2729 | target_st->st_dev = tswap16(st.st_dev); |
2438 | 2730 | target_st->st_ino = tswapl(st.st_ino); |
2439 | 2731 | #if defined(TARGET_PPC) |
... | ... | @@ -2453,6 +2745,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2453 | 2745 | target_st->target_st_atime = tswapl(st.st_atime); |
2454 | 2746 | target_st->target_st_mtime = tswapl(st.st_mtime); |
2455 | 2747 | target_st->target_st_ctime = tswapl(st.st_ctime); |
2748 | + unlock_user_struct(target_st, arg2, 1); | |
2456 | 2749 | } |
2457 | 2750 | } |
2458 | 2751 | break; |
... | ... | @@ -2479,9 +2772,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2479 | 2772 | case TARGET_NR_wait4: |
2480 | 2773 | { |
2481 | 2774 | int status; |
2482 | - target_long *status_ptr = (void *)arg2; | |
2775 | + target_long status_ptr = arg2; | |
2483 | 2776 | struct rusage rusage, *rusage_ptr; |
2484 | - struct target_rusage *target_rusage = (void *)arg4; | |
2777 | + target_ulong target_rusage = arg4; | |
2485 | 2778 | if (target_rusage) |
2486 | 2779 | rusage_ptr = &rusage; |
2487 | 2780 | else |
... | ... | @@ -2489,7 +2782,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2489 | 2782 | ret = get_errno(wait4(arg1, &status, arg3, rusage_ptr)); |
2490 | 2783 | if (!is_error(ret)) { |
2491 | 2784 | if (status_ptr) |
2492 | - *status_ptr = tswap32(status); | |
2785 | + tputl(status_ptr, status); | |
2493 | 2786 | if (target_rusage) { |
2494 | 2787 | host_to_target_rusage(target_rusage, &rusage); |
2495 | 2788 | } |
... | ... | @@ -2497,15 +2790,19 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2497 | 2790 | } |
2498 | 2791 | break; |
2499 | 2792 | case TARGET_NR_swapoff: |
2500 | - ret = get_errno(swapoff((const char *)arg1)); | |
2793 | + p = lock_user_string(arg1); | |
2794 | + ret = get_errno(swapoff(p)); | |
2795 | + unlock_user(p, arg1, 0); | |
2501 | 2796 | break; |
2502 | 2797 | case TARGET_NR_sysinfo: |
2503 | 2798 | { |
2504 | - struct target_sysinfo *target_value = (void *)arg1; | |
2799 | + struct target_sysinfo *target_value; | |
2505 | 2800 | struct sysinfo value; |
2506 | 2801 | ret = get_errno(sysinfo(&value)); |
2507 | - if (!is_error(ret) && target_value) | |
2802 | + if (!is_error(ret) && arg1) | |
2508 | 2803 | { |
2804 | + /* ??? __put_user is probably wrong. */ | |
2805 | + lock_user_struct(target_value, arg1, 0); | |
2509 | 2806 | __put_user(value.uptime, &target_value->uptime); |
2510 | 2807 | __put_user(value.loads[0], &target_value->loads[0]); |
2511 | 2808 | __put_user(value.loads[1], &target_value->loads[1]); |
... | ... | @@ -2520,6 +2817,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2520 | 2817 | __put_user(value.totalhigh, &target_value->totalhigh); |
2521 | 2818 | __put_user(value.freehigh, &target_value->freehigh); |
2522 | 2819 | __put_user(value.mem_unit, &target_value->mem_unit); |
2820 | + unlock_user_struct(target_value, arg1, 1); | |
2523 | 2821 | } |
2524 | 2822 | } |
2525 | 2823 | break; |
... | ... | @@ -2540,30 +2838,33 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2540 | 2838 | break; |
2541 | 2839 | #endif |
2542 | 2840 | case TARGET_NR_setdomainname: |
2543 | - ret = get_errno(setdomainname((const char *)arg1, arg2)); | |
2841 | + p = lock_user_string(arg1); | |
2842 | + ret = get_errno(setdomainname(p, arg2)); | |
2843 | + unlock_user(p, arg1, 0); | |
2544 | 2844 | break; |
2545 | 2845 | case TARGET_NR_uname: |
2546 | 2846 | /* no need to transcode because we use the linux syscall */ |
2547 | 2847 | { |
2548 | 2848 | struct new_utsname * buf; |
2549 | 2849 | |
2550 | - buf = (struct new_utsname *)arg1; | |
2850 | + lock_user_struct(buf, arg1, 0); | |
2551 | 2851 | ret = get_errno(sys_uname(buf)); |
2552 | 2852 | if (!is_error(ret)) { |
2553 | 2853 | /* Overrite the native machine name with whatever is being |
2554 | 2854 | emulated. */ |
2555 | 2855 | strcpy (buf->machine, UNAME_MACHINE); |
2556 | 2856 | } |
2857 | + unlock_user_struct(buf, arg1, 1); | |
2557 | 2858 | } |
2558 | 2859 | break; |
2559 | 2860 | #ifdef TARGET_I386 |
2560 | 2861 | case TARGET_NR_modify_ldt: |
2561 | - ret = get_errno(do_modify_ldt(cpu_env, arg1, (void *)arg2, arg3)); | |
2862 | + ret = get_errno(do_modify_ldt(cpu_env, arg1, arg2, arg3)); | |
2562 | 2863 | break; |
2563 | 2864 | case TARGET_NR_vm86old: |
2564 | 2865 | goto unimplemented; |
2565 | 2866 | case TARGET_NR_vm86: |
2566 | - ret = do_vm86(cpu_env, arg1, (void *)arg2); | |
2867 | + ret = do_vm86(cpu_env, arg1, arg2); | |
2567 | 2868 | break; |
2568 | 2869 | #endif |
2569 | 2870 | case TARGET_NR_adjtimex: |
... | ... | @@ -2594,20 +2895,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2594 | 2895 | { |
2595 | 2896 | #if defined (__x86_64__) |
2596 | 2897 | ret = get_errno(lseek(arg1, ((uint64_t )arg2 << 32) | arg3, arg5)); |
2597 | - *(int64_t *)arg4 = ret; | |
2898 | + tput64(arg4, ret); | |
2598 | 2899 | #else |
2599 | 2900 | int64_t res; |
2600 | 2901 | ret = get_errno(_llseek(arg1, arg2, arg3, &res, arg5)); |
2601 | - *(int64_t *)arg4 = tswap64(res); | |
2902 | + tput64(arg4, res); | |
2602 | 2903 | #endif |
2603 | 2904 | } |
2604 | 2905 | break; |
2605 | 2906 | case TARGET_NR_getdents: |
2606 | 2907 | #if TARGET_LONG_SIZE != 4 |
2908 | + goto unimplemented; | |
2607 | 2909 | #warning not supported |
2608 | 2910 | #elif TARGET_LONG_SIZE == 4 && HOST_LONG_SIZE == 8 |
2609 | 2911 | { |
2610 | - struct target_dirent *target_dirp = (void *)arg2; | |
2912 | + struct target_dirent *target_dirp; | |
2611 | 2913 | struct dirent *dirp; |
2612 | 2914 | long count = arg3; |
2613 | 2915 | |
... | ... | @@ -2625,6 +2927,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2625 | 2927 | |
2626 | 2928 | count1 = 0; |
2627 | 2929 | de = dirp; |
2930 | + target_dirp = lock_user(arg2, count, 0); | |
2628 | 2931 | tde = target_dirp; |
2629 | 2932 | while (len > 0) { |
2630 | 2933 | reclen = de->d_reclen; |
... | ... | @@ -2644,13 +2947,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2644 | 2947 | } |
2645 | 2948 | ret = count1; |
2646 | 2949 | } |
2950 | + unlock_user(target_dirp, arg2, ret); | |
2647 | 2951 | free(dirp); |
2648 | 2952 | } |
2649 | 2953 | #else |
2650 | 2954 | { |
2651 | - struct dirent *dirp = (void *)arg2; | |
2955 | + struct dirent *dirp; | |
2652 | 2956 | long count = arg3; |
2653 | 2957 | |
2958 | + dirp = lock_user(arg2, count, 0); | |
2654 | 2959 | ret = get_errno(sys_getdents(arg1, dirp, count)); |
2655 | 2960 | if (!is_error(ret)) { |
2656 | 2961 | struct dirent *de; |
... | ... | @@ -2668,14 +2973,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2668 | 2973 | len -= reclen; |
2669 | 2974 | } |
2670 | 2975 | } |
2976 | + unlock_user(dirp, arg2, ret); | |
2671 | 2977 | } |
2672 | 2978 | #endif |
2673 | 2979 | break; |
2674 | 2980 | #ifdef TARGET_NR_getdents64 |
2675 | 2981 | case TARGET_NR_getdents64: |
2676 | 2982 | { |
2677 | - struct dirent64 *dirp = (void *)arg2; | |
2983 | + struct dirent64 *dirp; | |
2678 | 2984 | long count = arg3; |
2985 | + dirp = lock_user(arg2, count, 0); | |
2679 | 2986 | ret = get_errno(sys_getdents64(arg1, dirp, count)); |
2680 | 2987 | if (!is_error(ret)) { |
2681 | 2988 | struct dirent64 *de; |
... | ... | @@ -2693,21 +3000,22 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2693 | 3000 | len -= reclen; |
2694 | 3001 | } |
2695 | 3002 | } |
3003 | + unlock_user(dirp, arg2, ret); | |
2696 | 3004 | } |
2697 | 3005 | break; |
2698 | 3006 | #endif /* TARGET_NR_getdents64 */ |
2699 | 3007 | case TARGET_NR__newselect: |
2700 | - ret = do_select(arg1, (void *)arg2, (void *)arg3, (void *)arg4, | |
2701 | - (void *)arg5); | |
3008 | + ret = do_select(arg1, arg2, arg3, arg4, arg5); | |
2702 | 3009 | break; |
2703 | 3010 | case TARGET_NR_poll: |
2704 | 3011 | { |
2705 | - struct target_pollfd *target_pfd = (void *)arg1; | |
3012 | + struct target_pollfd *target_pfd; | |
2706 | 3013 | unsigned int nfds = arg2; |
2707 | 3014 | int timeout = arg3; |
2708 | 3015 | struct pollfd *pfd; |
2709 | 3016 | unsigned int i; |
2710 | 3017 | |
3018 | + target_pfd = lock_user(arg1, sizeof(struct target_pollfd) * nfds, 1); | |
2711 | 3019 | pfd = alloca(sizeof(struct pollfd) * nfds); |
2712 | 3020 | for(i = 0; i < nfds; i++) { |
2713 | 3021 | pfd[i].fd = tswap32(target_pfd[i].fd); |
... | ... | @@ -2718,7 +3026,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2718 | 3026 | for(i = 0; i < nfds; i++) { |
2719 | 3027 | target_pfd[i].revents = tswap16(pfd[i].revents); |
2720 | 3028 | } |
3029 | + ret += nfds * (sizeof(struct target_pollfd) | |
3030 | + - sizeof(struct pollfd)); | |
2721 | 3031 | } |
3032 | + unlock_user(target_pfd, arg1, ret); | |
2722 | 3033 | } |
2723 | 3034 | break; |
2724 | 3035 | case TARGET_NR_flock: |
... | ... | @@ -2729,31 +3040,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2729 | 3040 | case TARGET_NR_readv: |
2730 | 3041 | { |
2731 | 3042 | int count = arg3; |
2732 | - int i; | |
2733 | 3043 | struct iovec *vec; |
2734 | - struct target_iovec *target_vec = (void *)arg2; | |
2735 | 3044 | |
2736 | 3045 | vec = alloca(count * sizeof(struct iovec)); |
2737 | - for(i = 0;i < count; i++) { | |
2738 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | |
2739 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | |
2740 | - } | |
3046 | + lock_iovec(vec, arg2, count, 0); | |
2741 | 3047 | ret = get_errno(readv(arg1, vec, count)); |
3048 | + unlock_iovec(vec, arg2, count, 1); | |
2742 | 3049 | } |
2743 | 3050 | break; |
2744 | 3051 | case TARGET_NR_writev: |
2745 | 3052 | { |
2746 | 3053 | int count = arg3; |
2747 | - int i; | |
2748 | 3054 | struct iovec *vec; |
2749 | - struct target_iovec *target_vec = (void *)arg2; | |
2750 | 3055 | |
2751 | 3056 | vec = alloca(count * sizeof(struct iovec)); |
2752 | - for(i = 0;i < count; i++) { | |
2753 | - vec[i].iov_base = (void *)tswapl(target_vec[i].iov_base); | |
2754 | - vec[i].iov_len = tswapl(target_vec[i].iov_len); | |
2755 | - } | |
3057 | + lock_iovec(vec, arg2, count, 1); | |
2756 | 3058 | ret = get_errno(writev(arg1, vec, count)); |
3059 | + unlock_iovec(vec, arg2, count, 0); | |
2757 | 3060 | } |
2758 | 3061 | break; |
2759 | 3062 | case TARGET_NR_getsid: |
... | ... | @@ -2768,27 +3071,34 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2768 | 3071 | return -ENOTDIR; |
2769 | 3072 | case TARGET_NR_sched_setparam: |
2770 | 3073 | { |
2771 | - struct sched_param *target_schp = (void *)arg2; | |
3074 | + struct sched_param *target_schp; | |
2772 | 3075 | struct sched_param schp; |
3076 | + | |
3077 | + lock_user_struct(target_schp, arg2, 1); | |
2773 | 3078 | schp.sched_priority = tswap32(target_schp->sched_priority); |
3079 | + unlock_user_struct(target_schp, arg2, 0); | |
2774 | 3080 | ret = get_errno(sched_setparam(arg1, &schp)); |
2775 | 3081 | } |
2776 | 3082 | break; |
2777 | 3083 | case TARGET_NR_sched_getparam: |
2778 | 3084 | { |
2779 | - struct sched_param *target_schp = (void *)arg2; | |
3085 | + struct sched_param *target_schp; | |
2780 | 3086 | struct sched_param schp; |
2781 | 3087 | ret = get_errno(sched_getparam(arg1, &schp)); |
2782 | 3088 | if (!is_error(ret)) { |
3089 | + lock_user_struct(target_schp, arg2, 0); | |
2783 | 3090 | target_schp->sched_priority = tswap32(schp.sched_priority); |
3091 | + unlock_user_struct(target_schp, arg2, 1); | |
2784 | 3092 | } |
2785 | 3093 | } |
2786 | 3094 | break; |
2787 | 3095 | case TARGET_NR_sched_setscheduler: |
2788 | 3096 | { |
2789 | - struct sched_param *target_schp = (void *)arg3; | |
3097 | + struct sched_param *target_schp; | |
2790 | 3098 | struct sched_param schp; |
3099 | + lock_user_struct(target_schp, arg3, 1); | |
2791 | 3100 | schp.sched_priority = tswap32(target_schp->sched_priority); |
3101 | + unlock_user_struct(target_schp, arg3, 0); | |
2792 | 3102 | ret = get_errno(sched_setscheduler(arg1, arg2, &schp)); |
2793 | 3103 | } |
2794 | 3104 | break; |
... | ... | @@ -2806,26 +3116,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2806 | 3116 | break; |
2807 | 3117 | case TARGET_NR_sched_rr_get_interval: |
2808 | 3118 | { |
2809 | - struct target_timespec *target_ts = (void *)arg2; | |
2810 | 3119 | struct timespec ts; |
2811 | 3120 | ret = get_errno(sched_rr_get_interval(arg1, &ts)); |
2812 | 3121 | if (!is_error(ret)) { |
2813 | - target_ts->tv_sec = tswapl(ts.tv_sec); | |
2814 | - target_ts->tv_nsec = tswapl(ts.tv_nsec); | |
3122 | + host_to_target_timespec(arg2, &ts); | |
2815 | 3123 | } |
2816 | 3124 | } |
2817 | 3125 | break; |
2818 | 3126 | case TARGET_NR_nanosleep: |
2819 | 3127 | { |
2820 | - struct target_timespec *target_req = (void *)arg1; | |
2821 | - struct target_timespec *target_rem = (void *)arg2; | |
2822 | 3128 | struct timespec req, rem; |
2823 | - req.tv_sec = tswapl(target_req->tv_sec); | |
2824 | - req.tv_nsec = tswapl(target_req->tv_nsec); | |
3129 | + target_to_host_timespec(&req, arg1); | |
2825 | 3130 | ret = get_errno(nanosleep(&req, &rem)); |
2826 | - if (is_error(ret) && target_rem) { | |
2827 | - target_rem->tv_sec = tswapl(rem.tv_sec); | |
2828 | - target_rem->tv_nsec = tswapl(rem.tv_nsec); | |
3131 | + if (is_error(ret) && arg2) { | |
3132 | + host_to_target_timespec(arg2, &rem); | |
2829 | 3133 | } |
2830 | 3134 | } |
2831 | 3135 | break; |
... | ... | @@ -2837,15 +3141,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2837 | 3141 | goto unimplemented; |
2838 | 3142 | #ifdef TARGET_NR_pread |
2839 | 3143 | case TARGET_NR_pread: |
2840 | - page_unprotect_range((void *)arg2, arg3); | |
2841 | - ret = get_errno(pread(arg1, (void *)arg2, arg3, arg4)); | |
3144 | + page_unprotect_range(arg2, arg3); | |
3145 | + p = lock_user(arg2, arg3, 0); | |
3146 | + ret = get_errno(pread(arg1, p, arg3, arg4)); | |
3147 | + unlock_user(p, arg2, ret); | |
2842 | 3148 | break; |
2843 | 3149 | case TARGET_NR_pwrite: |
2844 | - ret = get_errno(pwrite(arg1, (void *)arg2, arg3, arg4)); | |
3150 | + p = lock_user(arg2, arg3, 1); | |
3151 | + ret = get_errno(pwrite(arg1, p, arg3, arg4)); | |
3152 | + unlock_user(p, arg2, 0); | |
2845 | 3153 | break; |
2846 | 3154 | #endif |
2847 | 3155 | case TARGET_NR_getcwd: |
2848 | - ret = get_errno(sys_getcwd1((char *)arg1, arg2)); | |
3156 | + p = lock_user(arg1, arg2, 0); | |
3157 | + ret = get_errno(sys_getcwd1(p, arg2)); | |
3158 | + unlock_user(p, arg1, ret); | |
2849 | 3159 | break; |
2850 | 3160 | case TARGET_NR_capget: |
2851 | 3161 | goto unimplemented; |
... | ... | @@ -2874,16 +3184,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2874 | 3184 | struct rlimit rlim; |
2875 | 3185 | ret = get_errno(getrlimit(arg1, &rlim)); |
2876 | 3186 | if (!is_error(ret)) { |
2877 | - struct target_rlimit *target_rlim = (void *)arg2; | |
3187 | + struct target_rlimit *target_rlim; | |
3188 | + lock_user_struct(target_rlim, arg2, 0); | |
2878 | 3189 | target_rlim->rlim_cur = tswapl(rlim.rlim_cur); |
2879 | 3190 | target_rlim->rlim_max = tswapl(rlim.rlim_max); |
3191 | + unlock_user_struct(target_rlim, arg2, 1); | |
2880 | 3192 | } |
2881 | 3193 | break; |
2882 | 3194 | } |
2883 | 3195 | #endif |
2884 | 3196 | #ifdef TARGET_NR_truncate64 |
2885 | 3197 | case TARGET_NR_truncate64: |
2886 | - ret = target_truncate64(cpu_env, (const char *)arg1, arg2, arg3, arg4); | |
3198 | + p = lock_user_string(arg1); | |
3199 | + ret = target_truncate64(cpu_env, p, arg2, arg3, arg4); | |
3200 | + unlock_user(p, arg1, 0); | |
2887 | 3201 | break; |
2888 | 3202 | #endif |
2889 | 3203 | #ifdef TARGET_NR_ftruncate64 |
... | ... | @@ -2893,12 +3207,16 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2893 | 3207 | #endif |
2894 | 3208 | #ifdef TARGET_NR_stat64 |
2895 | 3209 | case TARGET_NR_stat64: |
2896 | - ret = get_errno(stat(path((const char *)arg1), &st)); | |
3210 | + p = lock_user_string(arg1); | |
3211 | + ret = get_errno(stat(path(p), &st)); | |
3212 | + unlock_user(p, arg1, 0); | |
2897 | 3213 | goto do_stat64; |
2898 | 3214 | #endif |
2899 | 3215 | #ifdef TARGET_NR_lstat64 |
2900 | 3216 | case TARGET_NR_lstat64: |
2901 | - ret = get_errno(lstat(path((const char *)arg1), &st)); | |
3217 | + p = lock_user_string(arg1); | |
3218 | + ret = get_errno(lstat(path(p), &st)); | |
3219 | + unlock_user(p, arg1, 0); | |
2902 | 3220 | goto do_stat64; |
2903 | 3221 | #endif |
2904 | 3222 | #ifdef TARGET_NR_fstat64 |
... | ... | @@ -2909,8 +3227,10 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2909 | 3227 | if (!is_error(ret)) { |
2910 | 3228 | #ifdef TARGET_ARM |
2911 | 3229 | if (((CPUARMState *)cpu_env)->eabi) { |
2912 | - struct target_eabi_stat64 *target_st = (void *)arg2; | |
3230 | + struct target_eabi_stat64 *target_st; | |
3231 | + lock_user_struct(target_st, arg2, 1); | |
2913 | 3232 | memset(target_st, 0, sizeof(struct target_eabi_stat64)); |
3233 | + /* put_user is probably wrong. */ | |
2914 | 3234 | put_user(st.st_dev, &target_st->st_dev); |
2915 | 3235 | put_user(st.st_ino, &target_st->st_ino); |
2916 | 3236 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
... | ... | @@ -2928,11 +3248,14 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2928 | 3248 | put_user(st.st_atime, &target_st->target_st_atime); |
2929 | 3249 | put_user(st.st_mtime, &target_st->target_st_mtime); |
2930 | 3250 | put_user(st.st_ctime, &target_st->target_st_ctime); |
3251 | + unlock_user_struct(target_st, arg2, 0); | |
2931 | 3252 | } else |
2932 | 3253 | #endif |
2933 | 3254 | { |
2934 | - struct target_stat64 *target_st = (void *)arg2; | |
3255 | + struct target_stat64 *target_st; | |
3256 | + lock_user_struct(target_st, arg2, 1); | |
2935 | 3257 | memset(target_st, 0, sizeof(struct target_stat64)); |
3258 | + /* ??? put_user is probably wrong. */ | |
2936 | 3259 | put_user(st.st_dev, &target_st->st_dev); |
2937 | 3260 | put_user(st.st_ino, &target_st->st_ino); |
2938 | 3261 | #ifdef TARGET_STAT64_HAS_BROKEN_ST_INO |
... | ... | @@ -2950,6 +3273,7 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2950 | 3273 | put_user(st.st_atime, &target_st->target_st_atime); |
2951 | 3274 | put_user(st.st_mtime, &target_st->target_st_mtime); |
2952 | 3275 | put_user(st.st_ctime, &target_st->target_st_ctime); |
3276 | + unlock_user_struct(target_st, arg2, 0); | |
2953 | 3277 | } |
2954 | 3278 | } |
2955 | 3279 | } |
... | ... | @@ -2957,7 +3281,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2957 | 3281 | #endif |
2958 | 3282 | #ifdef USE_UID16 |
2959 | 3283 | case TARGET_NR_lchown: |
2960 | - ret = get_errno(lchown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | |
3284 | + p = lock_user_string(arg1); | |
3285 | + ret = get_errno(lchown(p, low2highuid(arg2), low2highgid(arg3))); | |
3286 | + unlock_user(p, arg1, 0); | |
2961 | 3287 | break; |
2962 | 3288 | case TARGET_NR_getuid: |
2963 | 3289 | ret = get_errno(high2lowuid(getuid())); |
... | ... | @@ -2980,28 +3306,32 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
2980 | 3306 | case TARGET_NR_getgroups: |
2981 | 3307 | { |
2982 | 3308 | int gidsetsize = arg1; |
2983 | - uint16_t *target_grouplist = (void *)arg2; | |
3309 | + uint16_t *target_grouplist; | |
2984 | 3310 | gid_t *grouplist; |
2985 | 3311 | int i; |
2986 | 3312 | |
2987 | 3313 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
2988 | 3314 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
2989 | 3315 | if (!is_error(ret)) { |
3316 | + target_grouplist = lock_user(arg2, gidsetsize * 2, 0); | |
2990 | 3317 | for(i = 0;i < gidsetsize; i++) |
2991 | 3318 | target_grouplist[i] = tswap16(grouplist[i]); |
3319 | + unlock_user(target_grouplist, arg2, gidsetsize * 2); | |
2992 | 3320 | } |
2993 | 3321 | } |
2994 | 3322 | break; |
2995 | 3323 | case TARGET_NR_setgroups: |
2996 | 3324 | { |
2997 | 3325 | int gidsetsize = arg1; |
2998 | - uint16_t *target_grouplist = (void *)arg2; | |
3326 | + uint16_t *target_grouplist; | |
2999 | 3327 | gid_t *grouplist; |
3000 | 3328 | int i; |
3001 | 3329 | |
3002 | 3330 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3331 | + target_grouplist = lock_user(arg2, gidsetsize * 2, 1); | |
3003 | 3332 | for(i = 0;i < gidsetsize; i++) |
3004 | 3333 | grouplist[i] = tswap16(target_grouplist[i]); |
3334 | + unlock_user(target_grouplist, arg2, 0); | |
3005 | 3335 | ret = get_errno(setgroups(gidsetsize, grouplist)); |
3006 | 3336 | } |
3007 | 3337 | break; |
... | ... | @@ -3018,12 +3348,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3018 | 3348 | #ifdef TARGET_NR_getresuid |
3019 | 3349 | case TARGET_NR_getresuid: |
3020 | 3350 | { |
3021 | - int ruid, euid, suid; | |
3351 | + uid_t ruid, euid, suid; | |
3022 | 3352 | ret = get_errno(getresuid(&ruid, &euid, &suid)); |
3023 | 3353 | if (!is_error(ret)) { |
3024 | - *(uint16_t *)arg1 = tswap16(high2lowuid(ruid)); | |
3025 | - *(uint16_t *)arg2 = tswap16(high2lowuid(euid)); | |
3026 | - *(uint16_t *)arg3 = tswap16(high2lowuid(suid)); | |
3354 | + tput16(arg1, tswap16(high2lowuid(ruid))); | |
3355 | + tput16(arg2, tswap16(high2lowuid(euid))); | |
3356 | + tput16(arg3, tswap16(high2lowuid(suid))); | |
3027 | 3357 | } |
3028 | 3358 | } |
3029 | 3359 | break; |
... | ... | @@ -3038,18 +3368,20 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3038 | 3368 | #ifdef TARGET_NR_getresgid |
3039 | 3369 | case TARGET_NR_getresgid: |
3040 | 3370 | { |
3041 | - int rgid, egid, sgid; | |
3371 | + gid_t rgid, egid, sgid; | |
3042 | 3372 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); |
3043 | 3373 | if (!is_error(ret)) { |
3044 | - *(uint16_t *)arg1 = tswap16(high2lowgid(rgid)); | |
3045 | - *(uint16_t *)arg2 = tswap16(high2lowgid(egid)); | |
3046 | - *(uint16_t *)arg3 = tswap16(high2lowgid(sgid)); | |
3374 | + tput16(arg1, tswap16(high2lowgid(rgid))); | |
3375 | + tput16(arg2, tswap16(high2lowgid(egid))); | |
3376 | + tput16(arg3, tswap16(high2lowgid(sgid))); | |
3047 | 3377 | } |
3048 | 3378 | } |
3049 | 3379 | break; |
3050 | 3380 | #endif |
3051 | 3381 | case TARGET_NR_chown: |
3052 | - ret = get_errno(chown((const char *)arg1, low2highuid(arg2), low2highgid(arg3))); | |
3382 | + p = lock_user_string(arg1); | |
3383 | + ret = get_errno(chown(p, low2highuid(arg2), low2highgid(arg3))); | |
3384 | + unlock_user(p, arg1, 0); | |
3053 | 3385 | break; |
3054 | 3386 | case TARGET_NR_setuid: |
3055 | 3387 | ret = get_errno(setuid(low2highuid(arg1))); |
... | ... | @@ -3067,7 +3399,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3067 | 3399 | |
3068 | 3400 | #ifdef TARGET_NR_lchown32 |
3069 | 3401 | case TARGET_NR_lchown32: |
3070 | - ret = get_errno(lchown((const char *)arg1, arg2, arg3)); | |
3402 | + p = lock_user_string(arg1); | |
3403 | + ret = get_errno(lchown(p, arg2, arg3)); | |
3404 | + unlock_user(p, arg1, 0); | |
3071 | 3405 | break; |
3072 | 3406 | #endif |
3073 | 3407 | #ifdef TARGET_NR_getuid32 |
... | ... | @@ -3104,15 +3438,17 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3104 | 3438 | case TARGET_NR_getgroups32: |
3105 | 3439 | { |
3106 | 3440 | int gidsetsize = arg1; |
3107 | - uint32_t *target_grouplist = (void *)arg2; | |
3441 | + uint32_t *target_grouplist; | |
3108 | 3442 | gid_t *grouplist; |
3109 | 3443 | int i; |
3110 | 3444 | |
3111 | 3445 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3112 | 3446 | ret = get_errno(getgroups(gidsetsize, grouplist)); |
3113 | 3447 | if (!is_error(ret)) { |
3448 | + target_grouplist = lock_user(arg2, gidsetsize * 4, 0); | |
3114 | 3449 | for(i = 0;i < gidsetsize; i++) |
3115 | - put_user(grouplist[i], &target_grouplist[i]); | |
3450 | + target_grouplist[i] = tswap32(grouplist[i]); | |
3451 | + unlock_user(target_grouplist, arg2, gidsetsize * 4); | |
3116 | 3452 | } |
3117 | 3453 | } |
3118 | 3454 | break; |
... | ... | @@ -3121,13 +3457,15 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3121 | 3457 | case TARGET_NR_setgroups32: |
3122 | 3458 | { |
3123 | 3459 | int gidsetsize = arg1; |
3124 | - uint32_t *target_grouplist = (void *)arg2; | |
3460 | + uint32_t *target_grouplist; | |
3125 | 3461 | gid_t *grouplist; |
3126 | 3462 | int i; |
3127 | 3463 | |
3128 | 3464 | grouplist = alloca(gidsetsize * sizeof(gid_t)); |
3465 | + target_grouplist = lock_user(arg2, gidsetsize * 4, 1); | |
3129 | 3466 | for(i = 0;i < gidsetsize; i++) |
3130 | - get_user(grouplist[i], &target_grouplist[i]); | |
3467 | + grouplist[i] = tswap32(target_grouplist[i]); | |
3468 | + unlock_user(target_grouplist, arg2, 0); | |
3131 | 3469 | ret = get_errno(setgroups(gidsetsize, grouplist)); |
3132 | 3470 | } |
3133 | 3471 | break; |
... | ... | @@ -3145,12 +3483,12 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3145 | 3483 | #ifdef TARGET_NR_getresuid32 |
3146 | 3484 | case TARGET_NR_getresuid32: |
3147 | 3485 | { |
3148 | - int ruid, euid, suid; | |
3486 | + uid_t ruid, euid, suid; | |
3149 | 3487 | ret = get_errno(getresuid(&ruid, &euid, &suid)); |
3150 | 3488 | if (!is_error(ret)) { |
3151 | - *(uint32_t *)arg1 = tswap32(ruid); | |
3152 | - *(uint32_t *)arg2 = tswap32(euid); | |
3153 | - *(uint32_t *)arg3 = tswap32(suid); | |
3489 | + tput32(arg1, tswap32(ruid)); | |
3490 | + tput32(arg2, tswap32(euid)); | |
3491 | + tput32(arg3, tswap32(suid)); | |
3154 | 3492 | } |
3155 | 3493 | } |
3156 | 3494 | break; |
... | ... | @@ -3163,19 +3501,21 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3163 | 3501 | #ifdef TARGET_NR_getresgid32 |
3164 | 3502 | case TARGET_NR_getresgid32: |
3165 | 3503 | { |
3166 | - int rgid, egid, sgid; | |
3504 | + gid_t rgid, egid, sgid; | |
3167 | 3505 | ret = get_errno(getresgid(&rgid, &egid, &sgid)); |
3168 | 3506 | if (!is_error(ret)) { |
3169 | - *(uint32_t *)arg1 = tswap32(rgid); | |
3170 | - *(uint32_t *)arg2 = tswap32(egid); | |
3171 | - *(uint32_t *)arg3 = tswap32(sgid); | |
3507 | + tput32(arg1, tswap32(rgid)); | |
3508 | + tput32(arg2, tswap32(egid)); | |
3509 | + tput32(arg3, tswap32(sgid)); | |
3172 | 3510 | } |
3173 | 3511 | } |
3174 | 3512 | break; |
3175 | 3513 | #endif |
3176 | 3514 | #ifdef TARGET_NR_chown32 |
3177 | 3515 | case TARGET_NR_chown32: |
3178 | - ret = get_errno(chown((const char *)arg1, arg2, arg3)); | |
3516 | + p = lock_user_string(arg1); | |
3517 | + ret = get_errno(chown(p, arg2, arg3)); | |
3518 | + unlock_user(p, arg1, 0); | |
3179 | 3519 | break; |
3180 | 3520 | #endif |
3181 | 3521 | #ifdef TARGET_NR_setuid32 |
... | ... | @@ -3213,9 +3553,9 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3213 | 3553 | case TARGET_NR_fcntl64: |
3214 | 3554 | { |
3215 | 3555 | struct flock64 fl; |
3216 | - struct target_flock64 *target_fl = (void *)arg3; | |
3556 | + struct target_flock64 *target_fl; | |
3217 | 3557 | #ifdef TARGET_ARM |
3218 | - struct target_eabi_flock64 *target_efl = (void *)arg3; | |
3558 | + struct target_eabi_flock64 *target_efl; | |
3219 | 3559 | #endif |
3220 | 3560 | |
3221 | 3561 | switch(arg2) { |
... | ... | @@ -3224,19 +3564,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3224 | 3564 | if (ret == 0) { |
3225 | 3565 | #ifdef TARGET_ARM |
3226 | 3566 | if (((CPUARMState *)cpu_env)->eabi) { |
3567 | + lock_user_struct(target_efl, arg3, 0); | |
3227 | 3568 | target_efl->l_type = tswap16(fl.l_type); |
3228 | 3569 | target_efl->l_whence = tswap16(fl.l_whence); |
3229 | 3570 | target_efl->l_start = tswap64(fl.l_start); |
3230 | 3571 | target_efl->l_len = tswap64(fl.l_len); |
3231 | 3572 | target_efl->l_pid = tswapl(fl.l_pid); |
3573 | + unlock_user_struct(target_efl, arg3, 1); | |
3232 | 3574 | } else |
3233 | 3575 | #endif |
3234 | 3576 | { |
3577 | + lock_user_struct(target_fl, arg3, 0); | |
3235 | 3578 | target_fl->l_type = tswap16(fl.l_type); |
3236 | 3579 | target_fl->l_whence = tswap16(fl.l_whence); |
3237 | 3580 | target_fl->l_start = tswap64(fl.l_start); |
3238 | 3581 | target_fl->l_len = tswap64(fl.l_len); |
3239 | 3582 | target_fl->l_pid = tswapl(fl.l_pid); |
3583 | + unlock_user_struct(target_fl, arg3, 1); | |
3240 | 3584 | } |
3241 | 3585 | } |
3242 | 3586 | break; |
... | ... | @@ -3245,19 +3589,23 @@ long do_syscall(void *cpu_env, int num, long arg1, long arg2, long arg3, |
3245 | 3589 | case F_SETLKW64: |
3246 | 3590 | #ifdef TARGET_ARM |
3247 | 3591 | if (((CPUARMState *)cpu_env)->eabi) { |
3592 | + lock_user_struct(target_efl, arg3, 1); | |
3248 | 3593 | fl.l_type = tswap16(target_efl->l_type); |
3249 | 3594 | fl.l_whence = tswap16(target_efl->l_whence); |
3250 | 3595 | fl.l_start = tswap64(target_efl->l_start); |
3251 | 3596 | fl.l_len = tswap64(target_efl->l_len); |
3252 | 3597 | fl.l_pid = tswapl(target_efl->l_pid); |
3598 | + unlock_user_struct(target_efl, arg3, 0); | |
3253 | 3599 | } else |
3254 | 3600 | #endif |
3255 | 3601 | { |
3602 | + lock_user_struct(target_fl, arg3, 1); | |
3256 | 3603 | fl.l_type = tswap16(target_fl->l_type); |
3257 | 3604 | fl.l_whence = tswap16(target_fl->l_whence); |
3258 | 3605 | fl.l_start = tswap64(target_fl->l_start); |
3259 | 3606 | fl.l_len = tswap64(target_fl->l_len); |
3260 | 3607 | fl.l_pid = tswapl(target_fl->l_pid); |
3608 | + unlock_user_struct(target_fl, arg3, 0); | |
3261 | 3609 | } |
3262 | 3610 | ret = get_errno(fcntl(arg1, arg2, &fl)); |
3263 | 3611 | break; | ... | ... |
linux-user/syscall_types.h
linux-user/vm86.c
... | ... | @@ -62,25 +62,28 @@ static inline unsigned int vm_getl(uint8_t *segptr, unsigned int reg16) |
62 | 62 | void save_v86_state(CPUX86State *env) |
63 | 63 | { |
64 | 64 | TaskState *ts = env->opaque; |
65 | + struct target_vm86plus_struct * target_v86; | |
65 | 66 | |
67 | + lock_user_struct(target_v86, ts->target_v86, 0); | |
66 | 68 | /* put the VM86 registers in the userspace register structure */ |
67 | - ts->target_v86->regs.eax = tswap32(env->regs[R_EAX]); | |
68 | - ts->target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | |
69 | - ts->target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | |
70 | - ts->target_v86->regs.edx = tswap32(env->regs[R_EDX]); | |
71 | - ts->target_v86->regs.esi = tswap32(env->regs[R_ESI]); | |
72 | - ts->target_v86->regs.edi = tswap32(env->regs[R_EDI]); | |
73 | - ts->target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | |
74 | - ts->target_v86->regs.esp = tswap32(env->regs[R_ESP]); | |
75 | - ts->target_v86->regs.eip = tswap32(env->eip); | |
76 | - ts->target_v86->regs.cs = tswap16(env->segs[R_CS].selector); | |
77 | - ts->target_v86->regs.ss = tswap16(env->segs[R_SS].selector); | |
78 | - ts->target_v86->regs.ds = tswap16(env->segs[R_DS].selector); | |
79 | - ts->target_v86->regs.es = tswap16(env->segs[R_ES].selector); | |
80 | - ts->target_v86->regs.fs = tswap16(env->segs[R_FS].selector); | |
81 | - ts->target_v86->regs.gs = tswap16(env->segs[R_GS].selector); | |
69 | + target_v86->regs.eax = tswap32(env->regs[R_EAX]); | |
70 | + target_v86->regs.ebx = tswap32(env->regs[R_EBX]); | |
71 | + target_v86->regs.ecx = tswap32(env->regs[R_ECX]); | |
72 | + target_v86->regs.edx = tswap32(env->regs[R_EDX]); | |
73 | + target_v86->regs.esi = tswap32(env->regs[R_ESI]); | |
74 | + target_v86->regs.edi = tswap32(env->regs[R_EDI]); | |
75 | + target_v86->regs.ebp = tswap32(env->regs[R_EBP]); | |
76 | + target_v86->regs.esp = tswap32(env->regs[R_ESP]); | |
77 | + target_v86->regs.eip = tswap32(env->eip); | |
78 | + target_v86->regs.cs = tswap16(env->segs[R_CS].selector); | |
79 | + target_v86->regs.ss = tswap16(env->segs[R_SS].selector); | |
80 | + target_v86->regs.ds = tswap16(env->segs[R_DS].selector); | |
81 | + target_v86->regs.es = tswap16(env->segs[R_ES].selector); | |
82 | + target_v86->regs.fs = tswap16(env->segs[R_FS].selector); | |
83 | + target_v86->regs.gs = tswap16(env->segs[R_GS].selector); | |
82 | 84 | set_flags(env->eflags, ts->v86flags, VIF_MASK | ts->v86mask); |
83 | - ts->target_v86->regs.eflags = tswap32(env->eflags); | |
85 | + target_v86->regs.eflags = tswap32(env->eflags); | |
86 | + unlock_user_struct(target_v86, ts->target_v86, 1); | |
84 | 87 | #ifdef DEBUG_VM86 |
85 | 88 | fprintf(logfile, "save_v86_state: eflags=%08x cs:ip=%04x:%04x\n", |
86 | 89 | env->eflags, env->segs[R_CS].selector, env->eip); |
... | ... | @@ -378,10 +381,10 @@ void handle_vm86_fault(CPUX86State *env) |
378 | 381 | } |
379 | 382 | } |
380 | 383 | |
381 | -int do_vm86(CPUX86State *env, long subfunction, | |
382 | - struct target_vm86plus_struct * target_v86) | |
384 | +int do_vm86(CPUX86State *env, long subfunction, target_ulong vm86_addr) | |
383 | 385 | { |
384 | 386 | TaskState *ts = env->opaque; |
387 | + struct target_vm86plus_struct * target_v86; | |
385 | 388 | int ret; |
386 | 389 | |
387 | 390 | switch (subfunction) { |
... | ... | @@ -402,7 +405,6 @@ int do_vm86(CPUX86State *env, long subfunction, |
402 | 405 | goto out; |
403 | 406 | } |
404 | 407 | |
405 | - ts->target_v86 = target_v86; | |
406 | 408 | /* save current CPU regs */ |
407 | 409 | ts->vm86_saved_regs.eax = 0; /* default vm86 syscall return code */ |
408 | 410 | ts->vm86_saved_regs.ebx = env->regs[R_EBX]; |
... | ... | @@ -421,6 +423,8 @@ int do_vm86(CPUX86State *env, long subfunction, |
421 | 423 | ts->vm86_saved_regs.fs = env->segs[R_FS].selector; |
422 | 424 | ts->vm86_saved_regs.gs = env->segs[R_GS].selector; |
423 | 425 | |
426 | + ts->target_v86 = vm86_addr; | |
427 | + lock_user_struct(target_v86, vm86_addr, 1); | |
424 | 428 | /* build vm86 CPU state */ |
425 | 429 | ts->v86flags = tswap32(target_v86->regs.eflags); |
426 | 430 | env->eflags = (env->eflags & ~SAFE_MASK) | |
... | ... | @@ -465,6 +469,7 @@ int do_vm86(CPUX86State *env, long subfunction, |
465 | 469 | ts->vm86plus.vm86plus.flags = tswapl(target_v86->vm86plus.flags); |
466 | 470 | memcpy(&ts->vm86plus.vm86plus.vm86dbg_intxxtab, |
467 | 471 | target_v86->vm86plus.vm86dbg_intxxtab, 32); |
472 | + unlock_user_struct(target_v86, vm86_addr, 0); | |
468 | 473 | |
469 | 474 | #ifdef DEBUG_VM86 |
470 | 475 | fprintf(logfile, "do_vm86: cs:ip=%04x:%04x\n", | ... | ... |
target-arm/nwfpe/fpa11_cpdt.c
... | ... | @@ -31,48 +31,52 @@ |
31 | 31 | static inline |
32 | 32 | void loadSingle(const unsigned int Fn,const unsigned int *pMem) |
33 | 33 | { |
34 | + target_ulong addr = (target_ulong)(long)pMem; | |
34 | 35 | FPA11 *fpa11 = GET_FPA11(); |
35 | 36 | fpa11->fType[Fn] = typeSingle; |
36 | - get_user(fpa11->fpreg[Fn].fSingle, pMem); | |
37 | + fpa11->fpreg[Fn].fSingle = tget32(addr); | |
37 | 38 | } |
38 | 39 | |
39 | 40 | static inline |
40 | 41 | void loadDouble(const unsigned int Fn,const unsigned int *pMem) |
41 | 42 | { |
43 | + target_ulong addr = (target_ulong)(long)pMem; | |
42 | 44 | FPA11 *fpa11 = GET_FPA11(); |
43 | 45 | unsigned int *p; |
44 | 46 | p = (unsigned int*)&fpa11->fpreg[Fn].fDouble; |
45 | 47 | fpa11->fType[Fn] = typeDouble; |
46 | 48 | #ifdef WORDS_BIGENDIAN |
47 | - get_user(p[0], &pMem[0]); /* sign & exponent */ | |
48 | - get_user(p[1], &pMem[1]); | |
49 | + p[0] = tget32(addr); /* sign & exponent */ | |
50 | + p[1] = tget32(addr + 4); | |
49 | 51 | #else |
50 | - get_user(p[0], &pMem[1]); | |
51 | - get_user(p[1], &pMem[0]); /* sign & exponent */ | |
52 | + p[0] = tget32(addr + 4); | |
53 | + p[1] = tget32(addr); /* sign & exponent */ | |
52 | 54 | #endif |
53 | 55 | } |
54 | 56 | |
55 | 57 | static inline |
56 | 58 | void loadExtended(const unsigned int Fn,const unsigned int *pMem) |
57 | 59 | { |
60 | + target_ulong addr = (target_ulong)(long)pMem; | |
58 | 61 | FPA11 *fpa11 = GET_FPA11(); |
59 | 62 | unsigned int *p; |
60 | 63 | p = (unsigned int*)&fpa11->fpreg[Fn].fExtended; |
61 | 64 | fpa11->fType[Fn] = typeExtended; |
62 | - get_user(p[0], &pMem[0]); /* sign & exponent */ | |
63 | - get_user(p[1], &pMem[2]); /* ls bits */ | |
64 | - get_user(p[2], &pMem[1]); /* ms bits */ | |
65 | + p[0] = tget32(addr); /* sign & exponent */ | |
66 | + p[1] = tget32(addr + 8); /* ls bits */ | |
67 | + p[2] = tget32(addr + 4); /* ms bits */ | |
65 | 68 | } |
66 | 69 | |
67 | 70 | static inline |
68 | 71 | void loadMultiple(const unsigned int Fn,const unsigned int *pMem) |
69 | 72 | { |
73 | + target_ulong addr = (target_ulong)(long)pMem; | |
70 | 74 | FPA11 *fpa11 = GET_FPA11(); |
71 | 75 | register unsigned int *p; |
72 | 76 | unsigned long x; |
73 | 77 | |
74 | 78 | p = (unsigned int*)&(fpa11->fpreg[Fn]); |
75 | - get_user(x, &pMem[0]); | |
79 | + x = tget32(addr); | |
76 | 80 | fpa11->fType[Fn] = (x >> 14) & 0x00000003; |
77 | 81 | |
78 | 82 | switch (fpa11->fType[Fn]) |
... | ... | @@ -80,16 +84,16 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) |
80 | 84 | case typeSingle: |
81 | 85 | case typeDouble: |
82 | 86 | { |
83 | - get_user(p[0], &pMem[2]); /* Single */ | |
84 | - get_user(p[1], &pMem[1]); /* double msw */ | |
87 | + p[0] = tget32(addr + 8); /* Single */ | |
88 | + p[1] = tget32(addr + 4); /* double msw */ | |
85 | 89 | p[2] = 0; /* empty */ |
86 | 90 | } |
87 | 91 | break; |
88 | 92 | |
89 | 93 | case typeExtended: |
90 | 94 | { |
91 | - get_user(p[1], &pMem[2]); | |
92 | - get_user(p[2], &pMem[1]); /* msw */ | |
95 | + p[1] = tget32(addr + 8); | |
96 | + p[2] = tget32(addr + 4); /* msw */ | |
93 | 97 | p[0] = (x & 0x80003fff); |
94 | 98 | } |
95 | 99 | break; |
... | ... | @@ -99,6 +103,7 @@ void loadMultiple(const unsigned int Fn,const unsigned int *pMem) |
99 | 103 | static inline |
100 | 104 | void storeSingle(const unsigned int Fn,unsigned int *pMem) |
101 | 105 | { |
106 | + target_ulong addr = (target_ulong)(long)pMem; | |
102 | 107 | FPA11 *fpa11 = GET_FPA11(); |
103 | 108 | float32 val; |
104 | 109 | register unsigned int *p = (unsigned int*)&val; |
... | ... | @@ -116,12 +121,13 @@ void storeSingle(const unsigned int Fn,unsigned int *pMem) |
116 | 121 | default: val = fpa11->fpreg[Fn].fSingle; |
117 | 122 | } |
118 | 123 | |
119 | - put_user(p[0], pMem); | |
124 | + tput32(addr, p[0]); | |
120 | 125 | } |
121 | 126 | |
122 | 127 | static inline |
123 | 128 | void storeDouble(const unsigned int Fn,unsigned int *pMem) |
124 | 129 | { |
130 | + target_ulong addr = (target_ulong)(long)pMem; | |
125 | 131 | FPA11 *fpa11 = GET_FPA11(); |
126 | 132 | float64 val; |
127 | 133 | register unsigned int *p = (unsigned int*)&val; |
... | ... | @@ -139,17 +145,18 @@ void storeDouble(const unsigned int Fn,unsigned int *pMem) |
139 | 145 | default: val = fpa11->fpreg[Fn].fDouble; |
140 | 146 | } |
141 | 147 | #ifdef WORDS_BIGENDIAN |
142 | - put_user(p[0], &pMem[0]); /* msw */ | |
143 | - put_user(p[1], &pMem[1]); /* lsw */ | |
148 | + tput32(addr, p[0]); /* msw */ | |
149 | + tput32(addr + 4, p[1]); /* lsw */ | |
144 | 150 | #else |
145 | - put_user(p[1], &pMem[0]); /* msw */ | |
146 | - put_user(p[0], &pMem[1]); /* lsw */ | |
151 | + tput32(addr, p[1]); /* msw */ | |
152 | + tput32(addr + 4, p[0]); /* lsw */ | |
147 | 153 | #endif |
148 | 154 | } |
149 | 155 | |
150 | 156 | static inline |
151 | 157 | void storeExtended(const unsigned int Fn,unsigned int *pMem) |
152 | 158 | { |
159 | + target_ulong addr = (target_ulong)(long)pMem; | |
153 | 160 | FPA11 *fpa11 = GET_FPA11(); |
154 | 161 | floatx80 val; |
155 | 162 | register unsigned int *p = (unsigned int*)&val; |
... | ... | @@ -167,14 +174,15 @@ void storeExtended(const unsigned int Fn,unsigned int *pMem) |
167 | 174 | default: val = fpa11->fpreg[Fn].fExtended; |
168 | 175 | } |
169 | 176 | |
170 | - put_user(p[0], &pMem[0]); /* sign & exp */ | |
171 | - put_user(p[1], &pMem[2]); | |
172 | - put_user(p[2], &pMem[1]); /* msw */ | |
177 | + tput32(addr, p[0]); /* sign & exp */ | |
178 | + tput32(addr + 8, p[1]); | |
179 | + tput32(addr + 4, p[2]); /* msw */ | |
173 | 180 | } |
174 | 181 | |
175 | 182 | static inline |
176 | 183 | void storeMultiple(const unsigned int Fn,unsigned int *pMem) |
177 | 184 | { |
185 | + target_ulong addr = (target_ulong)(long)pMem; | |
178 | 186 | FPA11 *fpa11 = GET_FPA11(); |
179 | 187 | register unsigned int nType, *p; |
180 | 188 | |
... | ... | @@ -186,17 +194,17 @@ void storeMultiple(const unsigned int Fn,unsigned int *pMem) |
186 | 194 | case typeSingle: |
187 | 195 | case typeDouble: |
188 | 196 | { |
189 | - put_user(p[0], &pMem[2]); /* single */ | |
190 | - put_user(p[1], &pMem[1]); /* double msw */ | |
191 | - put_user(nType << 14, &pMem[0]); | |
197 | + tput32(addr + 8, p[0]); /* single */ | |
198 | + tput32(addr + 4, p[1]); /* double msw */ | |
199 | + tput32(addr, nType << 14); | |
192 | 200 | } |
193 | 201 | break; |
194 | 202 | |
195 | 203 | case typeExtended: |
196 | 204 | { |
197 | - put_user(p[2], &pMem[1]); /* msw */ | |
198 | - put_user(p[1], &pMem[2]); | |
199 | - put_user((p[0] & 0x80003fff) | (nType << 14), &pMem[0]); | |
205 | + tput32(addr + 4, p[2]); /* msw */ | |
206 | + tput32(addr + 8, p[1]); | |
207 | + tput32(addr, (p[0] & 0x80003fff) | (nType << 14)); | |
200 | 208 | } |
201 | 209 | break; |
202 | 210 | } | ... | ... |